This guide is organized by outcomes. Use it as a checklist when operating maintainer-d in production or development.
Goal: Load or refresh projects/maintainers from the Google worksheet into Postgres.
Production (SOPS secrets):
- Ensure required secrets are applied:
make sops-apply-bootstrap-secrets
make apply-creds
- Run the bootstrap job:
make bootstrap-run
Development (local .envrc):
- Generate and apply the dev bootstrap secret:
make env
make apply-env
- Run the bootstrap job:
make bootstrap-run-dev
Notes:
maintainerd-bootstrap-envmust includeMD_WORKSHEET,FOSSA_API_TOKEN, andWORKSPACE_CREDENTIALS_FILE(internal worksheet credentials).maintainerd-db-envmust includeMD_DB_DRIVER=postgresandMD_DB_DSN=...for production.- Database extensions required by the schema (e.g.,
unaccent,pg_trgm) must be available in the Postgres image and created before restore/migrations. Update local DB scripts inscripts/if requirements change.
Goal: Deploy the API server and supporting resources.
- Apply namespace, registry secret, and SOPS secrets:
make ensure-ns
make apply-ghcr-secret
make sops-apply-web-secrets
make sops-apply-bootstrap-secrets
make apply-creds
- Apply Kubernetes manifests:
make manifests-apply
- Verify:
kubectl -n maintainerd get pvc,deploy,svc,ing
Goal: Apply database schema changes safely without re-importing data.
- Build and push the migrate image:
make migrate-image-build
make migrate-image-push
- Apply the migrate job manifest:
kubectl -n maintainerd apply -f deploy/manifests/maintainerd-migrate-schema-job.yaml
- Wait for completion:
kubectl -n maintainerd wait --for=condition=complete job/maintainerd-migrate-schema --timeout=5m
- Check logs:
kubectl -n maintainerd logs job/maintainerd-migrate-schema
- Cleanup (optional):
kubectl -n maintainerd delete job/maintainerd-migrate-schema
Goal: Export a snapshot of the production Postgres database.
Run a one-off pg_dump from a pod:
PGPASSWORD="<password>" \
kubectl -n maintainerd run pgdump --rm -i --restart=Never \
--image=postgres:16-alpine \
--env="PGPASSWORD=$PGPASSWORD" -- \
pg_dump "host=<db-host> port=5432 user=<db-user> dbname=maintainerd sslmode=require" \
--format=custom --no-owner --no-privileges > maintainerd-prod.dump
Goal: Run/enable the sanitize job that archives maintainers missing from project admin files.
- Build and push the image:
make sanitize-image-build
make sanitize-image-push
- Apply or update the CronJob manifest:
kubectl -n maintainerd apply -f deploy/manifests/cronjob-sanitize.yaml
Goal: Run/enable the sync job that reconciles DB data into CRDs.
- Build and push the image:
make sync-image-build
make sync-image-push
- Apply or update the CronJob + RBAC:
make sync-apply
- (Optional) Trigger a manual run:
make sync-run
Goal: Deploy web + BFF to production.
- Build/push images:
make web-image-build
make web-image-push
make web-bff-image-build
make web-bff-image-push
- Apply manifests:
make deploy-web
- (Optional) pin the web image to a tag:
make web-image-set TAG=<tag>
.envrcis dev-only.- Generate and apply dev bootstrap secrets:
make env
make apply-env
make apply-creds
We store encrypted secrets in deploy/secrets/.
- Create plaintext secrets (once) and encrypt:
mkdir -p deploy/secrets
cp deploy/templates/maintainerd-web-env.yaml.tmpl deploy/secrets/maintainerd-web-env.yaml
cp deploy/templates/maintainerd-web-bff-env.yaml.tmpl deploy/secrets/maintainerd-web-bff-env.yaml
cp deploy/templates/maintainerd-db-env.yaml.tmpl deploy/secrets/maintainerd-db-env.yaml
cp deploy/templates/maintainerd-bootstrap-env.yaml.tmpl deploy/secrets/maintainerd-bootstrap-env.yaml
# fill in values, then:
make sops-encrypt-web-secrets SOPS_AGE_KEY=age1...
make sops-encrypt-bootstrap-secrets SOPS_AGE_KEY=age1...
- Apply encrypted secrets:
make sops-apply-web-secrets SOPS_AGE_KEY_FILE=~/.config/sops/age/keys.txt
make sops-apply-bootstrap-secrets SOPS_AGE_KEY_FILE=~/.config/sops/age/keys.txt
make apply-creds