Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Secrets

This page helps you find the secrets SourceOrigin’s deployments use, store the ones piqueld can’t generate, and rotate any of them.

Every secret reaches a service as a file under /run/secrets/, and auth reads it through a file:// reference (see configuration). piqueld keeps two kinds:

  • Generated secrets are declared in infra/piqueld.toml ([[spec.secrets]]). piqueld generates each one per environment and per preview, on the first deployment that mounts it, and never changes it unless you regenerate it.
  • Stored secrets are set by hand with piquelctl app secret, for the environments that may mount them. Their values can’t be read back.

List the secrets

piquelctl env secret sourceorigin --env production list   # generated, with their versions
piquelctl app secret sourceorigin list                    # stored, with who may mount them

Neither prints a value.

Store a secret

Set a stored secret before the first deployment that mounts it, which fails without it. Each is mountable by the environments that use it only:

piquelctl app secret sourceorigin set resend-production --stdin --environments production --no-previews

--stdin asks for the value without echo on a terminal, and drops one trailing newline. --file <path> reads it from a file instead. Stored secrets lists each one’s access and where its value comes from.

Rotate a stored secret

  1. Get the new value from where the secret comes from, such as a new Resend key.

  2. Set it again under the same name, with the same access:

    piquelctl app secret sourceorigin set resend-production --stdin --environments production --no-previews
    
  3. Deploy the environments that mount it. Running services keep the old value until then. Deploy staging with piquelctl --timeout 30m env deploy sourceorigin staging, and production by deploying its own release again.

  4. Revoke the old value where it came from, once the deployments succeeded.

Email and sign-in providers give the steps for their keys, and audit history for the audit keys, which change in a commit.

Rotate a generated secret

Check the secret’s row in generated secrets first: some must never be regenerated, and others need care.

  1. Generate a new value:

    piquelctl env secret sourceorigin --env production regenerate <name>
    
  2. Deploy the environment. Running services keep the old value until then.

Warning: a restore or a rollback deploys the secret versions the earlier deployment used, so it brings an old value back.

The database runtime password

database-runtime-password is sourceorigin_auth’s password. The next deployment’s migrate job sets the new one before the rollout. From then until the new auth replicas are healthy, the old replicas keep their open connections but can’t open new ones.

If that deployment fails after migrate, auth goes down as its pool’s connections expire, within 30 minutes. So rotate it during a deployment you watch, and fix forward if it fails: a retry reuses the new secret.

Generated secrets

SecretMounted byWhat it isRegenerating it
database-passwordpostgres, the migrate jobthe superuser sourceorigin’s passwordnever: the database keeps the password it stored when its volume was created, so the migrate job, which logs in with the new value, fails and every deployment after it stops. Regenerating makes a value nobody sees, so it can’t be set in PostgreSQL first either: there is no supported way to change this password yet
database-runtime-passwordauthsourceorigin_auth’s passwordtakes effect on the next deployment: see the database runtime password
key-encryption-keyauthAUTH_KEY_ENCRYPTION_KEY, which seals the signing keys in the databasenever: the stored signing keys would no longer open, and auth can’t change it
token-digest-keyauthAUTH_TOKEN_DIGEST_KEYends every refresh token and login in progress under it: change it in two deployments instead, as changing the token digest key describes
signing-keyauththe RSA key from before signing keys moved to the database, now AUTH_TOKEN_DIGEST_KEY_ACCEPTED, which the signing-key-import job imports into an empty key setends the refresh tokens still under it: leave it until keys digest-usage lists none, then remove it as its comment in the manifest says
audit-keyauth, in previewsthe seed that signs a preview’s audit checkpointsmakes the preview’s earlier checkpoints fail verification
no-provider-secretauththe placeholder mounted for a sign-in provider that’s offnothing: auth never reads it

Each is 32 random bytes, as hex or unpadded base64url text, except signing-key, a 3072-bit RSA key.

Stored secrets

SecretMountable byWhat it is
resend-productionproductionthe Resend key production sends with: see email
resend-devstaging and previewsthe Resend key for dev.sourceorigin.dev
github-production, github-stagingthat environmentits GitHub OAuth app’s client secret: see sign-in providers
google-production, google-stagingthat environmentits Google OAuth client’s secret
audit-key-production-2, audit-key-staging-2that environmentthe seed that signs its audit checkpoints, whose verifier key is committed: see audit history

The manifest’s variables pick which stored secret each environment mounts: smtp_secret, github_secret, google_secret and audit_key.

The telemetry stack has one generated secret of its own, grafana-admin-password.

Signing keys are not secrets of the manifest: auth keeps them in its database and rotates them on its own (see signing keys).