Prerequisites
Goal: a laptop that can decrypt secrets/bootstrap.sops.yaml, and a file that holds every Phase 0 key.
Requirements
Section titled “Requirements”| Need | Detail |
|---|---|
| Proxmox host | Room for 32 vCPU, 82 GiB RAM and 1000 GiB disk across seven VMs; API access as root@pam; an NVIDIA GPU to pass through to k8s-worker4 |
| Accounts | Hetzner Cloud, Cloudflare (zone for madhan.app), a GitHub OAuth app for Authentik |
| Tools | pulumi, talosctl, kubectl, just, sops, age, go, yq, jq, cdk8s — all in the devcontainer |
VM sizes come from cluster.nodes in config.yml; the Go toolchain is pinned in .mise.toml.
Procedure
Section titled “Procedure”-
Install the tools, or open the devcontainer:
Terminal window brew install pulumi talosctl kubectl just sops age go yq jqnpm install -g cdk8s-cli -
Create the age key and export its path. sops does not find the key file on its own.
Terminal window mkdir -p ~/.config/sops/ageage-keygen -o ~/.config/sops/age/keys.txtecho 'export SOPS_AGE_KEY_FILE="$HOME/.config/sops/age/keys.txt"' >> ~/.zshrc -
Put the public key in
.sops.yamlundercreation_rules[*].age. -
Open the secrets file. sops decrypts it in your editor and re-encrypts on save.
Terminal window just sops-view secrets/bootstrap.sops.yaml -
Add every key below. Generate random values with the command shown.
secrets/bootstrap.sops.yaml (keys only) PROXMOX_PASSWORD: # Proxmox root passwordHCLOUD_TOKEN: # Hetzner Cloud API tokenCLOUDFLARE_API_TOKEN: # Zone:DNS edit — cert-manager and Traefik ACMEAUTHENTIK_TOKEN: # openssl rand -hex 30; becomes the akadmin API tokenAUTHENTIK_SECRET_KEY: # openssl rand -base64 48AUTHENTIK_POSTGRESQL_PASSWORD: # openssl rand -hex 16AUTHENTIK_GITHUB_SECRET: # GitHub OAuth app secretGRAFANA_OAUTH_CLIENT_SECRET: # openssl rand -hex 32NETBIRD_CLIENT_SECRET: # openssl rand -hex 32NB_DATA_STORE_KEY: # openssl rand -base64 32NB_RELAY_SECRET: # openssl rand -base64 32NB_OWNER_PASSWORD: # first NetBird login onlyOPENBAO_UNSEAL_KEY: placeholder # real value in Phase 2NB_BIFROST_SETUP_KEY: placeholder # real value in Phase 6
sops -d secrets/bootstrap.sops.yaml >/dev/null && echo decryptsdecrypts means the key and .sops.yaml match. Never print the decrypted output.