Skip to content

Prerequisites

Goal: a laptop that can decrypt secrets/bootstrap.sops.yaml, and a file that holds every Phase 0 key.

NeedDetail
Proxmox hostRoom 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
AccountsHetzner Cloud, Cloudflare (zone for madhan.app), a GitHub OAuth app for Authentik
Toolspulumi, 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.

  1. Install the tools, or open the devcontainer:

    Terminal window
    brew install pulumi talosctl kubectl just sops age go yq jq
    npm install -g cdk8s-cli
  2. Create the age key and export its path. sops does not find the key file on its own.

    Terminal window
    mkdir -p ~/.config/sops/age
    age-keygen -o ~/.config/sops/age/keys.txt
    echo 'export SOPS_AGE_KEY_FILE="$HOME/.config/sops/age/keys.txt"' >> ~/.zshrc
  3. Put the public key in .sops.yaml under creation_rules[*].age.

  4. Open the secrets file. sops decrypts it in your editor and re-encrypts on save.

    Terminal window
    just sops-view secrets/bootstrap.sops.yaml
  5. Add every key below. Generate random values with the command shown.

    secrets/bootstrap.sops.yaml (keys only)
    PROXMOX_PASSWORD: # Proxmox root password
    HCLOUD_TOKEN: # Hetzner Cloud API token
    CLOUDFLARE_API_TOKEN: # Zone:DNS edit — cert-manager and Traefik ACME
    AUTHENTIK_TOKEN: # openssl rand -hex 30; becomes the akadmin API token
    AUTHENTIK_SECRET_KEY: # openssl rand -base64 48
    AUTHENTIK_POSTGRESQL_PASSWORD: # openssl rand -hex 16
    AUTHENTIK_GITHUB_SECRET: # GitHub OAuth app secret
    GRAFANA_OAUTH_CLIENT_SECRET: # openssl rand -hex 32
    NETBIRD_CLIENT_SECRET: # openssl rand -hex 32
    NB_DATA_STORE_KEY: # openssl rand -base64 32
    NB_RELAY_SECRET: # openssl rand -base64 32
    NB_OWNER_PASSWORD: # first NetBird login only
    OPENBAO_UNSEAL_KEY: placeholder # real value in Phase 2
    NB_BIFROST_SETUP_KEY: placeholder # real value in Phase 6
Terminal window
sops -d secrets/bootstrap.sops.yaml >/dev/null && echo decrypts

decrypts means the key and .sops.yaml match. Never print the decrypted output.