Skip to content

Docs delivery

The wiki is a static site built with Starlight. One CI build produces one dist/ directory, which is published to two places:

URL Where How
https://docs.cervant.net Cloudflare Workers, static assets only wrangler deploy
https://docs.home.cervant.net Hyperion, nginx Image on GHCR, synced by ArgoCD

The public copy is reachable from anywhere and doesn’t depend on the homelab being up. That matters most when something is broken and the docs are needed to fix it.

The internal copy is reachable when the internet link is down, and it is the one internal tools and agents (such as Hermes on hermes-agent) can use without leaving the LAN.

The two are independent. There is no failover logic between them: each URL is served from one place.

Both copies come from the same artifact, so they can’t drift. The image doesn’t build the site; it only copies dist/ into nginx-unprivileged. The site setting in astro.config.mjs is the public URL, so canonical links, the sitemap and llms.txt point to docs.cervant.net in both copies.

CI pushes ghcr.io/brsalcedom/homelab-docs:latest (plus a sha-<commit> tag for traceability) and stops there. It has no access to the cluster and never pushes to main.

ArgoCD Image Updater does the rest. The ImageUpdater resource in kubernetes/applications/argocd/homelab-docs/manifests/imageupdater.yaml follows the :latest tag with the digest strategy. Every two minutes it checks GHCR, and when the digest changes it sets a Kustomize image override pinned to that digest on the homelab-docs Application. ArgoCD renders the new image and rolls out the Deployment.

This is the argocd write-back method: the override lives on the Application object in the cluster, not in Git. Two consequences:

  • Git doesn’t record which digest is running. The Application in ArgoCD does, and the sha- tag in GHCR maps it back to a commit.
  • The root app-of-apps, which manages the homelab-docs Application from Git, must not undo the override. argocd.tf sets ignoreDifferences on /spec/source/kustomize/images for Applications, with RespectIgnoreDifferences=true.

The app reuses the platform: an HTTPRoute on the shared cilium-gateway, covered by the existing *.home.cervant.net wildcard certificate from cert-manager.

The starlight-llms-txt plugin generates:

File Contents
/llms.txt Index of the docs, following llmstxt.org
/llms-full.txt All pages as one Markdown file
/llms-small.txt A condensed version for smaller context windows

An agent can load llms-full.txt to get the whole wiki in one request.

The reference pages for each Terraform configuration contain a section generated by terraform-docs. CI injects it before astro build, so the published tables always match main without generated content being committed.

Pages follow Diátaxis: tutorials teach, how-to guides solve one task, reference lists facts, and explanation (like this page) gives the reasons.