Files
Gitea/infra/pkg/secrets/secrets.go
T
JMR-devandClaude Opus 5.5 f0e7a3b66f Keep the ACME contact email in Secret Manager
gitea:acmeEmail sat in Pulumi.prod.yaml, which this public repository
publishes, and was then copied into instance metadata. It now lives in a
gitea-acme-email secret instead, read by the VM when it renders the
Caddyfile.

- scripts/bootstrap.sh creates the secret empty and prints how to set
  it, the same as github-pat: the address is chosen, not generated.
- Pulumi grants the VM secretAccessor on it and nothing more. It is kept
  out of secrets.Names, whose members also get secretVersionAdder and are
  mapped to `gitea generate secret` by vm/bootstrap.sh.
- The gitea:acmeEmail config key and the acme-email metadata entry are
  gone.
- vm/bootstrap.sh renders the whole `email` directive. If the secret is
  unreadable it renders a comment instead and warns: Caddy still issues
  certificates under an account with no contact address, whereas an
  empty `email` would fail to parse and leave nothing serving TLS. Same
  directive-or-comment pattern as CADDY_PUBLISH_PORTS and CADDY_SYSCTL.

README setup gains the secret step, plus two that were missing: ADC
login (Pulumi's GCS backend and provider do not use the gcloud login),
and exporting PULUMI_CONFIG_PASSPHRASE from Secret Manager before
`stack init`. Without the latter, init prompts for a new passphrase and
the stack is encrypted with a key Cloud Build's infra trigger never sees.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 14:39:44 +07:00

35 lines
1.5 KiB
Go

// Package secrets names Gitea's signing secrets. It deliberately creates
// nothing.
//
// The secrets are created and populated by scripts/bootstrap.sh, outside
// Pulumi, for two reasons:
//
// 1. Ordering. INTERNAL_TOKEN must be a valid Gitea-issued JWT, not a random
// string, so `gitea generate secret` has to produce it. If Pulumi owned the
// containers, the values could only be added after `pulumi up` -- but the VM
// boots during that same `pulumi up` and wants to render app.ini.
//
// 2. Blast radius. `pulumi destroy` should not be able to delete the keys that
// every existing session, OAuth token, and LFS URL is signed with. Same
// reasoning as the pre-existing DNS zone and the backup bucket.
//
// Pulumi still grants the VM access to them by id -- an IAM binding does not
// require owning the resource.
package secrets
// Names are the Secret Manager secret ids. vm/bootstrap.sh maps each one to its
// `gitea generate secret` argument by suffix, so renaming these means updating
// fetch_or_create_secret too.
var Names = []string{
"gitea-secret-key",
"gitea-internal-token",
"gitea-oauth2-jwt-secret",
"gitea-lfs-jwt-secret",
}
// ACMEEmail holds the contact address Caddy registers with Let's Encrypt. It
// is a secret not because it signs anything but to keep it out of this public
// repository and out of instance metadata. Unlike Names it is supplied by the
// operator, never generated, so the VM gets read access only.
const ACMEEmail = "gitea-acme-email"