Deployment

Build, migrate, deploy, verify, and roll back without exposing test surfaces.

This page is the production rollout checklist for the service image, database schema, runtime configuration, and public documentation site.

Environment Layout

Environment Static config Runtime values Expected use
Local process configs/static_config.yaml configs/config_vars.yaml Manual development and API poking.
Dev Docker profile configs/static_config.yaml configs/config_vars.docker.yaml, copied from example Containerized development with source mounted.
Production Docker profile configs/static_config.prod.yaml External SMIRKLY_CONFIG_VARS_PATH and SMIRKLY_SECRETS_PATH Release image without source mount or tests-control endpoints; dynamic config updater/cache enabled.

Build and Release Gate

A release candidate should build the service, compile SQL query headers, run unit tests, run the functional testsuite as a non-root user, and validate the OpenAPI YAML before deployment.

cmake --preset debug
cmake --build build-debug --parallel 2 --target smirkly-auth smirkly-auth_unittest
# Run from a non-root user; testsuite PostgreSQL initdb refuses root.
ctest --test-dir build-debug --output-on-failure
python3 -c "import yaml; yaml.safe_load(open('openapi/auth-v0.yaml'))"

The GitHub Pages workflow publishes docs/ plus the current openapi/auth-v0.yaml, so API docs and the deployed contract move together.

Database Migrations

  • Run the migration job before starting a service version that depends on new schema.
  • Keep MIGRATE_DATABASE_URL and service postgres-dbconnection pointed at the same database; both should come from the deployment secret/config source.
  • Do not run application schema from Postgres init scripts in production; use versioned migrations.
  • For local databases created before migration tracking, recreate the volume or baseline it manually after checking schema state.
docker compose --profile dev run --rm smirkly-migrate-dev

SMIRKLY_CONFIG_VARS_PATH=/etc/smirkly-auth/config_vars.yaml \
SMIRKLY_SECRETS_PATH=/run/secrets/smirkly-auth \
docker compose --profile prod up --build -d smirkly-auth

Production Container Rules

  • Use the release image and configs/static_config.prod.yaml.
  • Run the application as the image's unprivileged smirkly-auth user.
  • Mount writable persistent storage at /var/cache/smirkly-auth for the dynamic-config fallback cache.
  • Mount JWT keys and generated runtime config at deploy time through SMIRKLY_SECRETS_PATH and SMIRKLY_CONFIG_VARS_PATH.
  • Build release images with SMIRKLY_AUTH_ENABLE_TEST_CONTROL=OFF; keep tests-control and fake-mode endpoints out of production.
  • Expose the service only through TLS-terminating ingress or a private service mesh.
  • Set resource limits so userver congestion control reflects real CPU constraints.
  • Keep the monitor listener private; route /health/live, /health/ready, and /service/monitor only through internal health/metrics infrastructure.
  • Roll out auth/outbox policy through config-service dynamic config, backed by dynamic-config.fs-cache-path; roll out secrets and thread-count changes through deploy config plus restart.
  • Use configs/dynamic_config/values.example.json as the initial config-service seed shape; live config-service responses must follow configs/dynamic_config/config_service_response.example.json.

Rollout Sequence

  1. Build and test the release candidate.
  2. Generate environment-specific config_vars.yaml from the secret store and expose it through SMIRKLY_CONFIG_VARS_PATH. Use configs/config_vars.prod.example.yaml only as a tracked shape example.
  3. Seed or update config-service with validated auth/outbox dynamic config values.
  4. Run migrations once per database.
  5. Start the new service version with static_config.prod.yaml.
  6. Check JWKS, sign-up, sign-in, refresh, logout, and email verification smoke tests.
  7. Watch logs, SMTP outbox backlog, DB errors, latency, and 4xx/5xx rate for the rollout window.

Rollback

Prefer forward-compatible migrations. If rollback is required, stop the new service version first, deploy the previous image with its matching runtime config, and only then decide whether a down migration is safe. Never run a destructive down migration while a newer binary can still write to the database.