From 6450c981dbebf1cd70fb9194aedd82e801ce3af6 Mon Sep 17 00:00:00 2001 From: Erich Blume Date: Tue, 3 Feb 2026 10:28:33 -0800 Subject: [PATCH 1/3] Add quartz deployment for docs hosting (Phase 1b) - Create ArgoCD Application and manifests for quartz service - Add docs.ops.eblu.me to Caddy reverse proxy - ConfigMap points to blumeops v1.0.0 release tarball - Tailscale ingress with homepage annotations for auto-discovery Co-Authored-By: Claude Opus 4.5 --- ansible/roles/caddy/defaults/main.yml | 3 ++ argocd/apps/quartz.yaml | 18 ++++++++ argocd/manifests/quartz/configmap.yaml | 10 +++++ argocd/manifests/quartz/deployment.yaml | 43 +++++++++++++++++++ .../manifests/quartz/ingress-tailscale.yaml | 25 +++++++++++ argocd/manifests/quartz/kustomization.yaml | 9 ++++ argocd/manifests/quartz/service.yaml | 13 ++++++ docs/README.md | 1 + 8 files changed, 122 insertions(+) create mode 100644 argocd/apps/quartz.yaml create mode 100644 argocd/manifests/quartz/configmap.yaml create mode 100644 argocd/manifests/quartz/deployment.yaml create mode 100644 argocd/manifests/quartz/ingress-tailscale.yaml create mode 100644 argocd/manifests/quartz/kustomization.yaml create mode 100644 argocd/manifests/quartz/service.yaml diff --git a/ansible/roles/caddy/defaults/main.yml b/ansible/roles/caddy/defaults/main.yml index 2aefc3d..c35ef76 100644 --- a/ansible/roles/caddy/defaults/main.yml +++ b/ansible/roles/caddy/defaults/main.yml @@ -70,6 +70,9 @@ caddy_services: - name: hajimari host: "go.{{ caddy_domain }}" backend: "https://go.tail8d86e.ts.net" + - name: docs + host: "docs.{{ caddy_domain }}" + backend: "https://docs.tail8d86e.ts.net" - name: sifaka host: "nas.{{ caddy_domain }}" backend: "http://sifaka:5000" diff --git a/argocd/apps/quartz.yaml b/argocd/apps/quartz.yaml new file mode 100644 index 0000000..75924cc --- /dev/null +++ b/argocd/apps/quartz.yaml @@ -0,0 +1,18 @@ +--- +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: quartz + namespace: argocd +spec: + project: default + source: + repoURL: ssh://forgejo@forge.ops.eblu.me:2222/eblume/blumeops.git + targetRevision: main + path: argocd/manifests/quartz + destination: + server: https://kubernetes.default.svc + namespace: quartz + syncPolicy: + syncOptions: + - CreateNamespace=true diff --git a/argocd/manifests/quartz/configmap.yaml b/argocd/manifests/quartz/configmap.yaml new file mode 100644 index 0000000..db70026 --- /dev/null +++ b/argocd/manifests/quartz/configmap.yaml @@ -0,0 +1,10 @@ +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: quartz-config + namespace: quartz +data: + # BlumeOps docs release URL + # Update this to deploy a new docs version + DOCS_RELEASE_URL: "https://forge.ops.eblu.me/eblume/blumeops/releases/download/v1.0.0/docs-v1.0.0.tar.gz" diff --git a/argocd/manifests/quartz/deployment.yaml b/argocd/manifests/quartz/deployment.yaml new file mode 100644 index 0000000..a6f5619 --- /dev/null +++ b/argocd/manifests/quartz/deployment.yaml @@ -0,0 +1,43 @@ +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: quartz + namespace: quartz +spec: + replicas: 1 + selector: + matchLabels: + app: quartz + template: + metadata: + labels: + app: quartz + spec: + containers: + - name: quartz + image: registry.ops.eblu.me/blumeops/quartz:v1.0.0 + ports: + - containerPort: 80 + name: http + envFrom: + - configMapRef: + name: quartz-config + resources: + requests: + memory: "64Mi" + cpu: "10m" + limits: + memory: "128Mi" + livenessProbe: + httpGet: + path: /healthz + port: 80 + initialDelaySeconds: 10 + periodSeconds: 30 + readinessProbe: + httpGet: + path: /healthz + port: 80 + initialDelaySeconds: 5 + periodSeconds: 10 diff --git a/argocd/manifests/quartz/ingress-tailscale.yaml b/argocd/manifests/quartz/ingress-tailscale.yaml new file mode 100644 index 0000000..69cf049 --- /dev/null +++ b/argocd/manifests/quartz/ingress-tailscale.yaml @@ -0,0 +1,25 @@ +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: quartz-tailscale + namespace: quartz + annotations: + tailscale.com/proxy-class: "default" + gethomepage.dev/enabled: "true" + gethomepage.dev/name: "Docs" + gethomepage.dev/group: "Apps" + gethomepage.dev/icon: "mdi-book-open-page-variant" + gethomepage.dev/description: "BlumeOps Documentation" + gethomepage.dev/href: "https://docs.ops.eblu.me" + gethomepage.dev/pod-selector: "app=quartz" +spec: + ingressClassName: tailscale + defaultBackend: + service: + name: quartz + port: + number: 80 + tls: + - hosts: + - docs diff --git a/argocd/manifests/quartz/kustomization.yaml b/argocd/manifests/quartz/kustomization.yaml new file mode 100644 index 0000000..dc0348c --- /dev/null +++ b/argocd/manifests/quartz/kustomization.yaml @@ -0,0 +1,9 @@ +--- +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +namespace: quartz +resources: + - configmap.yaml + - deployment.yaml + - service.yaml + - ingress-tailscale.yaml diff --git a/argocd/manifests/quartz/service.yaml b/argocd/manifests/quartz/service.yaml new file mode 100644 index 0000000..ecdc31e --- /dev/null +++ b/argocd/manifests/quartz/service.yaml @@ -0,0 +1,13 @@ +--- +apiVersion: v1 +kind: Service +metadata: + name: quartz + namespace: quartz +spec: + selector: + app: quartz + ports: + - name: http + port: 80 + targetPort: 80 diff --git a/docs/README.md b/docs/README.md index 1ba602f..b694cb9 100644 --- a/docs/README.md +++ b/docs/README.md @@ -63,6 +63,7 @@ The documentation is being restructured to follow the [Diataxis](https://diataxi ``` - [ ] Test end-to-end: commit -> build -> release -> deploy - [ ] Set up `CHANGELOG.md` with [towncrier](https://towncrier.readthedocs.io/) using news fragments from zk cards +- [ ] Add `docs.ops.eblu.me` link to homepage dashboard ### Phase 2: Tutorials Learning-oriented content for getting started. -- 2.50.1 (Apple Git-155) From 56f5d1d682f32f72922845418f18e51e2d0695a4 Mon Sep 17 00:00:00 2001 From: Erich Blume Date: Tue, 3 Feb 2026 10:36:51 -0800 Subject: [PATCH 2/3] Rename quartz -> docs for service naming The service is 'docs', quartz is just the container image used. This allows future quartz-based sites with different names. Co-Authored-By: Claude Opus 4.5 --- argocd/apps/{quartz.yaml => docs.yaml} | 6 +++--- argocd/manifests/{quartz => docs}/configmap.yaml | 4 ++-- argocd/manifests/{quartz => docs}/deployment.yaml | 12 ++++++------ .../{quartz => docs}/ingress-tailscale.yaml | 8 ++++---- argocd/manifests/{quartz => docs}/kustomization.yaml | 2 +- argocd/manifests/{quartz => docs}/service.yaml | 6 +++--- 6 files changed, 19 insertions(+), 19 deletions(-) rename argocd/apps/{quartz.yaml => docs.yaml} (82%) rename argocd/manifests/{quartz => docs}/configmap.yaml (84%) rename argocd/manifests/{quartz => docs}/deployment.yaml (86%) rename argocd/manifests/{quartz => docs}/ingress-tailscale.yaml (82%) rename argocd/manifests/{quartz => docs}/kustomization.yaml (90%) rename argocd/manifests/{quartz => docs}/service.yaml (70%) diff --git a/argocd/apps/quartz.yaml b/argocd/apps/docs.yaml similarity index 82% rename from argocd/apps/quartz.yaml rename to argocd/apps/docs.yaml index 75924cc..cd8db35 100644 --- a/argocd/apps/quartz.yaml +++ b/argocd/apps/docs.yaml @@ -2,17 +2,17 @@ apiVersion: argoproj.io/v1alpha1 kind: Application metadata: - name: quartz + name: docs namespace: argocd spec: project: default source: repoURL: ssh://forgejo@forge.ops.eblu.me:2222/eblume/blumeops.git targetRevision: main - path: argocd/manifests/quartz + path: argocd/manifests/docs destination: server: https://kubernetes.default.svc - namespace: quartz + namespace: docs syncPolicy: syncOptions: - CreateNamespace=true diff --git a/argocd/manifests/quartz/configmap.yaml b/argocd/manifests/docs/configmap.yaml similarity index 84% rename from argocd/manifests/quartz/configmap.yaml rename to argocd/manifests/docs/configmap.yaml index db70026..7970f3c 100644 --- a/argocd/manifests/quartz/configmap.yaml +++ b/argocd/manifests/docs/configmap.yaml @@ -2,8 +2,8 @@ apiVersion: v1 kind: ConfigMap metadata: - name: quartz-config - namespace: quartz + name: docs-config + namespace: docs data: # BlumeOps docs release URL # Update this to deploy a new docs version diff --git a/argocd/manifests/quartz/deployment.yaml b/argocd/manifests/docs/deployment.yaml similarity index 86% rename from argocd/manifests/quartz/deployment.yaml rename to argocd/manifests/docs/deployment.yaml index a6f5619..01e4e9b 100644 --- a/argocd/manifests/quartz/deployment.yaml +++ b/argocd/manifests/docs/deployment.yaml @@ -2,27 +2,27 @@ apiVersion: apps/v1 kind: Deployment metadata: - name: quartz - namespace: quartz + name: docs + namespace: docs spec: replicas: 1 selector: matchLabels: - app: quartz + app: docs template: metadata: labels: - app: quartz + app: docs spec: containers: - - name: quartz + - name: docs image: registry.ops.eblu.me/blumeops/quartz:v1.0.0 ports: - containerPort: 80 name: http envFrom: - configMapRef: - name: quartz-config + name: docs-config resources: requests: memory: "64Mi" diff --git a/argocd/manifests/quartz/ingress-tailscale.yaml b/argocd/manifests/docs/ingress-tailscale.yaml similarity index 82% rename from argocd/manifests/quartz/ingress-tailscale.yaml rename to argocd/manifests/docs/ingress-tailscale.yaml index 69cf049..4c6710f 100644 --- a/argocd/manifests/quartz/ingress-tailscale.yaml +++ b/argocd/manifests/docs/ingress-tailscale.yaml @@ -2,8 +2,8 @@ apiVersion: networking.k8s.io/v1 kind: Ingress metadata: - name: quartz-tailscale - namespace: quartz + name: docs-tailscale + namespace: docs annotations: tailscale.com/proxy-class: "default" gethomepage.dev/enabled: "true" @@ -12,12 +12,12 @@ metadata: gethomepage.dev/icon: "mdi-book-open-page-variant" gethomepage.dev/description: "BlumeOps Documentation" gethomepage.dev/href: "https://docs.ops.eblu.me" - gethomepage.dev/pod-selector: "app=quartz" + gethomepage.dev/pod-selector: "app=docs" spec: ingressClassName: tailscale defaultBackend: service: - name: quartz + name: docs port: number: 80 tls: diff --git a/argocd/manifests/quartz/kustomization.yaml b/argocd/manifests/docs/kustomization.yaml similarity index 90% rename from argocd/manifests/quartz/kustomization.yaml rename to argocd/manifests/docs/kustomization.yaml index dc0348c..9d55928 100644 --- a/argocd/manifests/quartz/kustomization.yaml +++ b/argocd/manifests/docs/kustomization.yaml @@ -1,7 +1,7 @@ --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization -namespace: quartz +namespace: docs resources: - configmap.yaml - deployment.yaml diff --git a/argocd/manifests/quartz/service.yaml b/argocd/manifests/docs/service.yaml similarity index 70% rename from argocd/manifests/quartz/service.yaml rename to argocd/manifests/docs/service.yaml index ecdc31e..62b0f83 100644 --- a/argocd/manifests/quartz/service.yaml +++ b/argocd/manifests/docs/service.yaml @@ -2,11 +2,11 @@ apiVersion: v1 kind: Service metadata: - name: quartz - namespace: quartz + name: docs + namespace: docs spec: selector: - app: quartz + app: docs ports: - name: http port: 80 -- 2.50.1 (Apple Git-155) From 47fcfcf49e7c8a1157c540a32a3607f7da80f794 Mon Sep 17 00:00:00 2001 From: Erich Blume Date: Tue, 3 Feb 2026 10:41:59 -0800 Subject: [PATCH 3/3] Fix quartz Dockerfile for legacy Docker builder Heredocs in RUN aren't supported without BuildKit. Move nginx config to separate file and COPY it instead. Co-Authored-By: Claude Opus 4.5 --- containers/quartz/Dockerfile | 35 ++-------------------------------- containers/quartz/default.conf | 28 +++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 33 deletions(-) create mode 100644 containers/quartz/default.conf diff --git a/containers/quartz/Dockerfile b/containers/quartz/Dockerfile index 5701990..63e5757 100644 --- a/containers/quartz/Dockerfile +++ b/containers/quartz/Dockerfile @@ -11,42 +11,11 @@ FROM nginx:alpine # Install curl for downloading release assets RUN apk add --no-cache curl -# Copy startup script +# Copy startup script and nginx config COPY start.sh /start.sh +COPY default.conf /etc/nginx/conf.d/default.conf RUN chmod +x /start.sh -# Custom nginx config for SPA routing -RUN cat > /etc/nginx/conf.d/default.conf << 'EOF' -server { - listen 80; - server_name _; - root /usr/share/nginx/html; - index index.html; - - # Enable gzip compression - gzip on; - gzip_types text/plain text/css application/json application/javascript text/xml application/xml text/javascript; - - # Cache static assets - location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2)$ { - expires 1y; - add_header Cache-Control "public, immutable"; - } - - # SPA fallback - serve index.html for client-side routing - location / { - try_files $uri $uri/ $uri.html /index.html; - } - - # Health check endpoint - location /healthz { - access_log off; - return 200 "ok\n"; - add_header Content-Type text/plain; - } -} -EOF - EXPOSE 80 CMD ["/start.sh"] diff --git a/containers/quartz/default.conf b/containers/quartz/default.conf new file mode 100644 index 0000000..4009101 --- /dev/null +++ b/containers/quartz/default.conf @@ -0,0 +1,28 @@ +server { + listen 80; + server_name _; + root /usr/share/nginx/html; + index index.html; + + # Enable gzip compression + gzip on; + gzip_types text/plain text/css application/json application/javascript text/xml application/xml text/javascript; + + # Cache static assets + location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2)$ { + expires 1y; + add_header Cache-Control "public, immutable"; + } + + # SPA fallback - serve index.html for client-side routing + location / { + try_files $uri $uri/ $uri.html /index.html; + } + + # Health check endpoint + location /healthz { + access_log off; + return 200 "ok\n"; + add_header Content-Type text/plain; + } +} -- 2.50.1 (Apple Git-155)