storage/SECRETS.md
Sergei Poljanski e9388c0b0d
All checks were successful
Deploy storage stack / deploy (push) Successful in 20s
Remove MinIO
Garage serves all three buckets and both apps, and a last comparison
found nothing in MinIO that Garage lacks. Drop the MinIO service, its
bootstrap and its root credentials from the deploy, and let compose
remove the leftover containers.

The storage_minio_data volume is left on the host. All images can be
pulled again, so the deploy goes back to failing on a pull error.

Document Garage in the README and SECRETS, including the key format and
how the existing secrets map to it, and swap the MinIO client in the
flake for awscli and rclone.

Assisted-by: Claude:fable-5-2
2026-11-11 03:55:18 +04:00

5 KiB

Forgejo secrets — storage repo

Add these to git.czsk.it/asxpi/storage → Settings → Actions → Secrets before the first deploy. All values are opaque to the storage stack; nothing is domain-specific.

How to generate a value

openssl rand -hex 32       # 64-char hex, good for any password/key

For a Garage key pair (an id of GK + 24 hex digits, a secret of 64):

printf 'GK%s\n' "$(openssl rand -hex 12)"
openssl rand -hex 32

The pairs in use predate Garage and are not in that format. The bootstrap and the apps' deploys hash such a value into it (garage_key_id, garage_secret in init/garage-bootstrap.sh), so the key Garage knows differs from the secret's text. A value already in Garage's format is used as it is: use the snippet above whenever a pair is rotated.

Required secrets

Deploy access (same pattern as the asxpio repo)

Secret Value
DEPLOY_IP Production host IP/hostname.
DEPLOY_USER SSH user on the prod host.
DEPLOY_SSH_KEY Private SSH key authorised on the prod host.

Reuse the same key the asxpio repo uses.

Postgres

Secret Value
POSTGRES_PASSWORD Postgres superuser password. openssl rand -hex 32. Used only by init/admin.

Per-app credentials provisioned for asxpio

These are also added (with the same values) on the asxpio repo so the app can connect.

Secret Value
ASXPIO_DB_PASSWORD Postgres password for the asxpio role. openssl rand -hex 32.
ASXPIO_S3_ACCESS_KEY S3 key id, see above.
ASXPIO_S3_SECRET_KEY S3 secret, see above.

Per-app credentials provisioned for datacenterbingo

These are read-only:

  • Role bingo gets SELECT on bingo_datacenters and bingo_incidents in the asxpio DB, and default_transaction_read_only.
  • The S3 key may only read the datacenterbingo-photos bucket. asxpio's key has read-write on that bucket for the admin's uploads.

The same values go on the datacenterbingo repo.

Secret Value
BINGO_DB_PASSWORD Postgres password for the bingo role. openssl rand -hex 32.
BINGO_S3_ACCESS_KEY S3 key id.
BINGO_S3_SECRET_KEY S3 secret.

Uploader for the public bucket

Objects in public are readable by anyone at https://s3.asxp.io/public/<key> (no anonymous listing). This key may only put and delete there. Optional: without the secrets the bucket exists and nothing can upload.

Secret Value
PUBLIC_S3_ACCESS_KEY S3 key id.
PUBLIC_S3_SECRET_KEY S3 secret.

The local AWS profile needs the pair as Garage knows it. For a pair not in Garage's format, that is the hashed form:

printf 'GK%s\n' "$(printf '%s' "$PUBLIC_S3_ACCESS_KEY" | sha256sum | cut -c1-24)"
printf '%s' "$PUBLIC_S3_SECRET_KEY" | sha256sum | cut -c1-64
aws --endpoint-url https://s3.asxp.io --profile asxp-public \
  s3 cp shot.png s3://public/shot.png

The table grants need asxpio's migrations to have run. On a fresh install, deploy storage again after asxpio's first boot.

After adding secrets

  1. Push to main. The Forgejo workflow brings Postgres and Garage up, then runs postgres-init (creates asxpio role + DB) and init/garage-bootstrap.sh (creates the buckets and the per-app keys).
  2. Confirm both init containers exited 0:
    ssh deploy@prod 'docker compose -f /opt/storage/docker-compose.yml ps'
    ssh deploy@prod 'docker logs storage-postgres-init'
    ssh deploy@prod 'docker exec storage-garage /garage key list'
    
  3. Add the matching ASXPIO_DB_PASSWORD, ASXPIO_S3_ACCESS_KEY, ASXPIO_S3_SECRET_KEY (plus ADMIN_USER, ADMIN_PASSWORD) on the asxpio repo — see asxpio/SECRETS.md.
  4. Deploy asxpio.

Rotation

  • POSTGRES_PASSWORD: update secret, push. Init scripts only touch per-app roles, so the superuser password is applied on container restart.
  • Per-app password / keys: update both repos' secrets, push storage first (re-provisions the role/user with the new password), then push the consumer.