# website Simple greeter — the landing page at [0x29a.ch](https://0x29a.ch). Previously a stock `nginx` container on the old Docker host, serving a bind-mounted `/mnt/docker/website/html`. It now ships as a self-contained image (content baked in) and runs on the k3s cluster behind the Hetzner Caddy. ## Layout ``` index.html the greeter _css/styles.css styling _img/ft.jpg background image favicon.ico favicon robots.txt disallow all Dockerfile nginx:1.29-alpine + the static files devenv.nix dev shell: podman ``` ## Build & push the image Images live in the Gitea container registry under `git.0x29a.ch/aaron/website`. `podman` reads the `Dockerfile` natively — a drop-in for `docker`. ```sh podman build -t git.0x29a.ch/aaron/website:1.0.0 . podman login git.0x29a.ch # Gitea user + a token with write:package podman push git.0x29a.ch/aaron/website:1.0.0 ``` Run it locally to smoke-test: ```sh podman run --rm -p 8080:80 git.0x29a.ch/aaron/website:1.0.0 ``` ## Deploy to k3s Deployed via the Helm chart in `helm-k3s-lab-gitops/apps/website`, synced by ArgoCD. The package is private, so the namespace needs a pull secret referenced by the chart's `image.pullSecret` (default `gitea-registry`): ```sh kubectl create secret docker-registry gitea-registry \ --docker-server=git.0x29a.ch \ --docker-username= \ --docker-password= \ -n website ``` Then bump `image.tag` in the chart's `values.yaml` and commit; ArgoCD rolls it out from `main`. (Make the Gitea package public instead and set `image.pullSecret: ""` to drop the secret entirely.) Traefik holds Ingress rules for both `0x29a.ch` and `www.0x29a.ch`. TLS is terminated at the edge by Caddy on the Hetzner box, which reverse-proxies to the three k3s nodes over Tailscale — see `ansible-play-infra/inventory/host_vars/0x29a.ch.yml`.