diff --git a/content/posts/hugo-on-k8s-nginx.md b/content/posts/hugo-on-k8s-nginx.md new file mode 100644 index 0000000..8f3761f --- /dev/null +++ b/content/posts/hugo-on-k8s-nginx.md @@ -0,0 +1,179 @@ ++++ +title = 'Hugo on Kubernetes & NGINX' +date = 2024-02-28T15:35:46-08:00 +draft = true ++++ + +i decided to make a website. a static one. this one. with [Hugo][hugo]. this +is basically as a vanity project so i have some stuff to host in a +[Kubernetes][k8s] cluster i'm running. the k8s cluster is also as a vanity +project. + +because i don't like software, i wanted a way to deploy my site that +doesn't involve much. this post is about that. + +## Getting Started + +i built my site by following the straight-forward _[Getting Started][hugo-started]_ +guide in the Hugo documentation. + +i did `hugo new site estradiol.cloud`. and then `cd estradiol.cloud; git init`. and +then i picked a ridiculous theme ["inspired by terminal ricing aesthetics"][risotto], +installing it like `git submodule add https://github.com/joeroe/risotto.git themes/risotto; echo "theme = 'risotto'" >> hugo.toml`. i appreciate the culinary naming choice. + +at this point, my website is basically finished (i also changed the title in `hugo.toml`). +i probably won't be putting much on it, so there's no point fussing with other details. + +about deployment, the guide's _[Basic Usage][hugo-deploy]_ page has this to offer: + +> Most of our users deploy their sites using a CI/CD workflow, where a push{{< sup "1" >}} +> to their GitHub or GitLab repository triggers a build and deployment. Popular +> providers include AWS Amplify, CloudCannon, Cloudflare Pages, GitHub Pages, +> GitLab Pages, and Netlify. +> +> 1. The Git repository contains the entire project directory, typically excluding the +> public directory because the site is built _after_ the push. + +importantly, you can't make a post about depoying this way. _everyone_ deploys +this way. + +it also involves some system somewhere that can run Hugo to build the site, and push +it to some remote system where my cluster can reach it. i definitely already need +Hugo installed on my workstation if i'm going to post anything here (unlikely), so +now i'm running Hugo in two places. there's definitely going to be other complex +nonsense like webhooks involved. + +and hang on. let's look at this again: + +> 1. The Git repository contains the entire project directory, typically excluding the +> public directory because the site is built _after_ the push. + +you're telling me i'm going to build a nice static site and not check the +_actual content_ into version control? couldn't be me. + +## Getting Static + +what if instead i pushed my site to a git repository exactly as i intend to serve it? +then i could shell into my webserver, pull the site, and _nifty-galifty!_ isn't this +the way it has [always been done][worm]? + +one problem is that i don't have a webserver, i have a _container orchestration +system_. there are several upsides to this (few of which are relevant for my project) +but it demands i get a bit more clever. i _could_ run a little pipeline that builds a +container wrapping my static site, pushes it to a registry somewhere so my deployments +can pull it, all ready to go. but now i've got _software_ again; build stages and webhooks +and i'm hosting and versioning container images. i don't want any of this. + + +```yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app.kubernetes.io/instance: estradiol-cloud + app.kubernetes.io/name: nginx + name: web-nginx + namespace: estradiol-cloud +spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/instance: estradiol-cloud + app.kubernetes.io/name: nginx + template: + metadata: + labels: + app.kubernetes.io/instance: estradiol-cloud + app.kubernetes.io/name: nginx + spec: + containers: + - name: git-repo-syncer + image: docker.io/bitnami/git:2.43.2-debian-12-r2 + imagePullPolicy: IfNotPresent + command: + - /bin/bash + - -ec + - | + while true; do + cd /app && git -c safe.directory=/app pull origin trunk + sleep 60 + done + volumeMounts: + - mountPath: /app + name: staticsite + - name: nginx + image: docker.io/bitnami/nginx:1.25.4-debian-12-r2 + imagePullPolicy: IfNotPresent + env: + - name: NGINX_HTTP_PORT_NUMBER + value: "8080" + livenessProbe: + tcpSocket: + port: http + readinessProbe: + tcpSocket: + port: http + ports: + - containerPort: 8080 + name: http + protocol: TCP + volumeMounts: + - mountPath: /opt/bitnami/nginx/conf/server_blocks + name: nginx-server-block + - mountPath: /app + name: staticsite + initContainers: + - name: git-clone-repository + image: docker.io/bitnami/git:2.43.2-debian-12-r2 + imagePullPolicy: IfNotPresent + command: + - /bin/bash + - -ec + - | + [[ -f "/opt/bitnami/scripts/git/entrypoint.sh" ]] && source "/opt/bitnami/scripts/git/entrypoint.sh" + git clone https://code.estradiol.cloud/tamsin/estradiol.cloud.git --no-checkout --branch trunk /tmp/app + [[ "$?" -eq 0 ]] && cd /tmp/app && git sparse-checkout init --cone && git sparse-checkout set public && git checkout && shopt -s dotglob && rm -rf /app/* && mv /tmp/app/* /app/ + volumeMounts: + - mountPath: /app + name: staticsite + restartPolicy: Always + terminationGracePeriodSeconds: 30 + volumes: + - configMap: + defaultMode: 420 + name: web-nginx-server-block + name: nginx-server-block + - emptyDir: {} + name: staticsite +``` + +## Getting Flux'd + +```yaml +apiVersion: source.toolkit.fluxcd.io/v1beta2 +kind: HelmRepository +metadata: + name: bitnami + namespace: default +spec: + url: https://charts.bitnami.com/bitnami +``` + +```yaml +apiVersion: source.toolkit.fluxcd.io/v1beta2 +kind: HelmRepository +metadata: + name: bitnami + namespace: default +spec: + url: https://charts.bitnami.com/bitnami +``` + + + +[hugo]: https://gohugo.io +[hugo-deploy]: https://gohugo.io/getting-started/usage/#deploy-your-site +[hugo-started]: https://gohugo.io/getting-started +[k8s]: https://kubernetes.io +[risotto]: https://github.com/joeroe/risotto +[worm]: https://www.mikecurato.com/worm-loves-worm diff --git a/hugo.toml b/hugo.toml index fea7ae5..cd64ab4 100644 --- a/hugo.toml +++ b/hugo.toml @@ -2,3 +2,8 @@ baseURL = 'https://estradiol.cloud/' languageCode = 'en-us' title = 'estradiol.cloud' theme = 'risotto' +[menus] +[[menus.main]] + name = 'Posts' + pageRef = '/posts' + weight = 20 diff --git a/layouts/shortcodes/sub.html b/layouts/shortcodes/sub.html new file mode 100644 index 0000000..e1d97d9 --- /dev/null +++ b/layouts/shortcodes/sub.html @@ -0,0 +1 @@ +{{ .Get 0 | markdownify }} diff --git a/layouts/shortcodes/sup.html b/layouts/shortcodes/sup.html new file mode 100644 index 0000000..665c317 --- /dev/null +++ b/layouts/shortcodes/sup.html @@ -0,0 +1 @@ +{{ .Get 0 | markdownify }} diff --git a/public/categories/index.html b/public/categories/index.html index be11a91..c801c1e 100644 --- a/public/categories/index.html +++ b/public/categories/index.html @@ -1,2 +1,2 @@ Categories – estradiol.cloud -

Categories


\ No newline at end of file +

Categories


\ No newline at end of file diff --git a/public/index.html b/public/index.html index 7fbf8b3..e1feb9b 100644 --- a/public/index.html +++ b/public/index.html @@ -1,2 +1,2 @@ estradiol.cloud – estradiol.cloud -

\ No newline at end of file +

\ No newline at end of file diff --git a/public/index.xml b/public/index.xml index fa7dc51..df95670 100644 --- a/public/index.xml +++ b/public/index.xml @@ -1 +1 @@ -estradiol.cloudhttps://estradiol.cloud/Recent content on estradiol.cloudHugo -- gohugo.ioen-us \ No newline at end of file +estradiol.cloudhttps://estradiol.cloud/Recent content on estradiol.cloudHugo -- gohugo.ioen-us \ No newline at end of file diff --git a/public/posts/hugo-on-k8s-nginx/index.html b/public/posts/hugo-on-k8s-nginx/index.html new file mode 100644 index 0000000..d4c57c8 --- /dev/null +++ b/public/posts/hugo-on-k8s-nginx/index.html @@ -0,0 +1,255 @@ + + + + Hugo on Kubernetes & NGINX – estradiol.cloud + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+

Hugo on Kubernetes & NGINX

+
+
+

i decided to make a website. a static one. this one. with Hugo. this +is basically as a vanity project so i have some stuff to host in a +Kubernetes cluster i’m running. the k8s cluster is also as a vanity +project.

+

because i don’t like software, i wanted a way to deploy my site that +doesn’t involve much. this post is about that.

+

Getting Started

+

i built my site by following the straight-forward Getting Started +guide in the Hugo documentation.

+

i did hugo new site estradiol.cloud. and then cd estradiol.cloud; git init. and +then i picked a ridiculous theme “inspired by terminal ricing aesthetics”, +installing it like git submodule add https://github.com/joeroe/risotto.git themes/risotto; echo "theme = 'risotto'" >> hugo.toml. i appreciate the culinary naming choice.

+

at this point, my website is basically finished (i also changed the title in hugo.toml). +i probably won’t be putting much on it, so there’s no point fussing with other details.

+

about deployment, the guide’s Basic Usage page has this to offer:

+
+

Most of our users deploy their sites using a CI/CD workflow, where a push1 + +to their GitHub or GitLab repository triggers a build and deployment. Popular +providers include AWS Amplify, CloudCannon, Cloudflare Pages, GitHub Pages, +GitLab Pages, and Netlify.

+
    +
  1. The Git repository contains the entire project directory, typically excluding the +public directory because the site is built after the push.
  2. +
+
+

importantly, you can’t make a post about depoying this way. everyone deploys +this way.

+

it also involves some system somewhere that can run Hugo to build the site, and push +it to some remote system where my cluster can reach it. i definitely already need +Hugo installed on my workstation if i’m going to post anything here (unlikely), so +now i’m running Hugo in two places. there’s definitely going to be other complex +nonsense like webhooks involved.

+

and hang on. let’s look at this again:

+
+
    +
  1. The Git repository contains the entire project directory, typically excluding the +public directory because the site is built after the push.
  2. +
+
+

you’re telling me i’m going to build a nice static site and not check the +actual content into version control? couldn’t be me.

+

Getting Static

+

what if instead i pushed my site to a git repository exactly as i intend to serve it? +then i could shell into my webserver, pull the site, and nifty-galifty! isn’t this +the way it has always been done?

+

one problem is that i don’t have a webserver, i have a container orchestration +system. there are several upsides to this (few of which are relevant for my project) +but it demands i get a bit more clever. i could run a little pipeline that builds a +container wrapping my static site, pushes it to a registry somewhere so my deployments +can pull it, all ready to go. but now i’ve got software again; build stages and webhooks +and i’m hosting and versioning container images. i don’t want any of this.

+
apiVersion: apps/v1
+kind: Deployment
+metadata:
+  labels:
+    app.kubernetes.io/instance: estradiol-cloud
+    app.kubernetes.io/name: nginx
+  name: web-nginx
+  namespace: estradiol-cloud
+spec:
+  replicas: 1
+  selector:
+    matchLabels:
+      app.kubernetes.io/instance: estradiol-cloud
+      app.kubernetes.io/name: nginx
+  template:
+    metadata:
+      labels:
+        app.kubernetes.io/instance: estradiol-cloud
+        app.kubernetes.io/name: nginx
+    spec:
+      containers:
+      - name: git-repo-syncer
+        image: docker.io/bitnami/git:2.43.2-debian-12-r2
+        imagePullPolicy: IfNotPresent
+        command:
+        - /bin/bash
+        - -ec
+        - |
+          while true; do
+              cd /app && git -c safe.directory=/app pull origin trunk
+              sleep 60
+          done          
+        volumeMounts:
+        - mountPath: /app
+          name: staticsite
+      - name: nginx
+        image: docker.io/bitnami/nginx:1.25.4-debian-12-r2
+        imagePullPolicy: IfNotPresent
+        env:
+        - name: NGINX_HTTP_PORT_NUMBER
+          value: "8080"
+        livenessProbe:
+          tcpSocket:
+            port: http
+        readinessProbe:
+          tcpSocket:
+            port: http
+        ports:
+        - containerPort: 8080
+          name: http
+          protocol: TCP
+        volumeMounts:
+        - mountPath: /opt/bitnami/nginx/conf/server_blocks
+          name: nginx-server-block
+        - mountPath: /app
+          name: staticsite
+      initContainers:
+      - name: git-clone-repository
+        image: docker.io/bitnami/git:2.43.2-debian-12-r2
+        imagePullPolicy: IfNotPresent
+        command:
+        - /bin/bash
+        - -ec
+        - |
+          [[ -f "/opt/bitnami/scripts/git/entrypoint.sh" ]] && source "/opt/bitnami/scripts/git/entrypoint.sh"
+          git clone https://code.estradiol.cloud/tamsin/estradiol.cloud.git --no-checkout --branch trunk /tmp/app
+          [[ "$?" -eq 0 ]] && cd /tmp/app && git sparse-checkout init --cone && git sparse-checkout set public && git checkout && shopt -s dotglob && rm -rf /app/* && mv /tmp/app/* /app/          
+        volumeMounts:
+        - mountPath: /app
+          name: staticsite
+      restartPolicy: Always
+      terminationGracePeriodSeconds: 30
+      volumes:
+      - configMap:
+          defaultMode: 420
+          name: web-nginx-server-block
+        name: nginx-server-block
+      - emptyDir: {}
+        name: staticsite
+

Getting Flux’d

+
apiVersion: source.toolkit.fluxcd.io/v1beta2
+kind: HelmRepository
+metadata:
+  name: bitnami
+  namespace: default
+spec:
+  url: https://charts.bitnami.com/bitnami
+
apiVersion: source.toolkit.fluxcd.io/v1beta2
+kind: HelmRepository
+metadata:
+  name: bitnami
+  namespace: default
+spec:
+  url: https://charts.bitnami.com/bitnami
+
+
+
+ +
+ +
+
+ + +
+
+
+ + +

+ + 2024-02-28 +

+ + + + +
+
+ + + +
+ + + diff --git a/public/posts/index.html b/public/posts/index.html new file mode 100644 index 0000000..4c15421 --- /dev/null +++ b/public/posts/index.html @@ -0,0 +1,2 @@ +Posts – estradiol.cloud +

Posts


\ No newline at end of file diff --git a/public/posts/index.xml b/public/posts/index.xml new file mode 100644 index 0000000..841b3e0 --- /dev/null +++ b/public/posts/index.xml @@ -0,0 +1 @@ +Posts on estradiol.cloudhttps://estradiol.cloud/posts/Recent content in Posts on estradiol.cloudHugo -- gohugo.ioen-us \ No newline at end of file diff --git a/public/sitemap.xml b/public/sitemap.xml index 5ad42d2..fe046af 100644 --- a/public/sitemap.xml +++ b/public/sitemap.xml @@ -1 +1 @@ -https://estradiol.cloud/categories/https://estradiol.cloud/https://estradiol.cloud/tags/ \ No newline at end of file +https://estradiol.cloud/2024-02-28T15:35:46-08:00https://estradiol.cloud/posts/2024-02-28T15:35:46-08:00https://estradiol.cloud/categories/https://estradiol.cloud/tags/ \ No newline at end of file diff --git a/public/tags/index.html b/public/tags/index.html index 373d104..3af56b3 100644 --- a/public/tags/index.html +++ b/public/tags/index.html @@ -1,2 +1,2 @@ Tags – estradiol.cloud -

Tags


\ No newline at end of file +

Tags


\ No newline at end of file