Flux bootstrap: a deploy key still depends on a token

flux bootstrap github offers token auth or SSH deploy keys. Both need a personal access token at bootstrap; they differ in what the cluster keeps afterwards, and that is what to choose on.

flux bootstrap github has two authentication modes, and the documentation presents them as alternatives. When I looked closer they turned out to be less different than that suggests, and the one real difference is what I ended up choosing on.

Both modes need a PAT at bootstrap

  • --token-auth: Flux clones over HTTPS with your personal access token, and stores that token in the cluster as the flux-system Secret in the flux-system namespace.
  • --token-auth=false (the default): Flux generates an SSH keypair, registers the public half as a deploy key on the repository, and stores the private half in the cluster.

Either way, flux bootstrap authenticates to GitHub with a PAT so it can create the repository and push the manifests, and in the second mode also register the deploy key. Picking SSH doesn’t get you out of needing a token. What changes is what gets left behind in the cluster.

What the cluster keeps afterwards

With --token-auth, anyone who can read Secrets in flux-system has your GitHub token and can do whatever that token can do. A fine-grained PAT narrows that down. A classic one with repo scope gives access to every repository you own.

With a deploy key, the credential sitting in the cluster only works for one repository. That’s the smaller blast radius, and it’s what I picked. In a homelab the cluster is the least-audited thing holding my credentials, so I want what’s stored there to be as narrow as possible.

The deploy key still depends on the PAT

Flux’s documentation covers this in a single sentence: when the PAT that created the deploy key is removed or expires, the deploy key stops working. So the SSH mode doesn’t free you from managing the token’s lifecycle, it only postpones it. On the day the bootstrap token expires, the cluster stops reconciling.

Recovery is manual, on a cluster that otherwise heals itself: delete the flux-system Secret and re-run flux bootstrap with a valid token. Put the token’s expiry date in a calendar. It’s much better to know about this before the day Flux goes quiet.

Decide these before the first bootstrap

  • The required permissions differ by mode. For a fine-grained token, Administration needs read-only for --token-auth, but read and write for deploy keys, because registering a key counts as an administrative action. If you get it wrong, bootstrap fails straight away, so at least you find out immediately.
  • Image automation needs --read-write-key=true. The default deploy key is read-only, so Flux can’t push image-tag updates back to the repository, and changing it later means re-bootstrapping.
  • New repositories are created private unless you pass --private=false.
  • The bootstrap token can’t live in git. If the rest of your cluster secrets are managed declaratively (SOPS, sealed secrets, a vault), this one sits outside all of that by design. Write down where it’s kept, or the next rebuild starts with a search.