doran/deploy/hetzner/README.md

105 lines
3.5 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Hetzner single-node bootstrap
This repos canonical infrastructure path is:
1. provision one Hetzner VM with Terraform
2. let cloud-init install k3s (and optionally Tailscale)
3. run `scripts/hetzner/bootstrap.sh` from the operator workstation
4. apply repo-managed platform + project manifests
5. bootstrap Forgejo, the runner, repo secrets/variables, and the first CI-driven deploy
## Source of truth
Use these docs first:
- `docs/hetzner-k3s-bootstrap.md` — bootstrap + destroy + required env
- `docs/hetzner-self-hosted-ci-runbook.md` — Forgejo/runner/CI flow
- `docs/k8s-observability.md` — Grafana, Loki, Promtail, Headlamp
- `deploy/k8s/README.md` — Kubernetes layout
- `deploy/k8s/overlays/hetzner-single-node/README.md` — overlay details
## Current architecture
Infrastructure under `infra/terraform/hetzner/` provisions:
- one Hetzner VM
- one firewall
- one private network attachment
- cloud-init for unattended k3s install
Kubernetes platform services deployed from this repo:
- Forgejo
- Forgejo runner
- private registry
- cert-manager
- Traefik via k3s bundled ingress controller
- Grafana
- Loki
- Promtail
- Headlamp
Project services deployed from this repo:
- Redpanda
- `near-intents-ingest`
- `dummy-reactor`
- `dummy-executor`
- `dummy-consumer`
## Bootstrap model
The current bootstrap is workstation-driven after Terraform.
cloud-init does **not** clone this repo onto the node.
`scripts/hetzner/bootstrap.sh` now:
- loads config and secrets from `scripts/hetzner/bootstrap-secrets.env`
- resolves `*_PASS` values through `pass`
- runs Terraform
- configures DNS through Cloudflare or Porkbun when credentials are present
- fetches kubeconfig from the node
- renders `.state/hetzner/generated-overlay/`
- applies platform + project manifests
- bootstraps Forgejo admin/user/repo/runner state
- seeds the repo into Forgejo
- lets Forgejo Actions perform the routine image build + deploy path by default
Legacy local-image bootstrap still exists, but the default/steady-state path is Forgejo Actions.
## Required operator inputs
Create and source:
```bash
cp scripts/hetzner/bootstrap-secrets.env.example scripts/hetzner/bootstrap-secrets.env
source scripts/hetzner/bootstrap-secrets.env
```
At minimum you need:
- Hetzner credentials
- SSH public key path
- public domain settings
- registry credentials
- app secret(s)
- Forgejo admin credentials
- Grafana admin credentials
Recommended:
- Tailscale auth key for private admin/control-plane access
- DNS provider credentials
- `pass`-backed secret refs instead of raw env values
## Current live/public surfaces
- Forgejo: `https://git.doran.133011.xyz/`
- Registry: `https://registry.doran.133011.xyz/`
- Grafana: `https://grafana.doran.133011.xyz/`
- Headlamp: `https://headlamp.doran.133011.xyz/`
## Notes
- The Forgejo runner no longer reads a pre-seeded `runner_registration_token` from a secret. Bootstrap generates a one-time token in-cluster and persists the runner config on the Forgejo PVC.
- Registry auth is created imperatively during bootstrap from `REGISTRY_USERNAME` and `REGISTRY_PASSWORD`; manual overlay applies must provide `registry.htpasswd` themselves.
- Headlamp login uses a generated Kubernetes service-account token; bootstrap stores it in `pass` when `HEADLAMP_ADMIN_TOKEN_PASS` is configured.
- Ingress is Traefik-based. The old `ingress-nginx` path is obsolete.
## Status
This path has been rebuilt successfully and the cluster is operational, but if you want the strongest reproducibility guarantee after any new platform addition, do one more full destroy/rebuild rehearsal.