Operations
Deployment
Building the production images, configuration through environment variables, and running the production stack.
On this page
Production stack
A second Compose file, docker-compose.prod.yml, builds the API image and runs the production
topology. The API ships with a Dockerfile; the frontend builds to static assets served by your CDN
or a static host.
docker compose --env-file .env.prod -f docker-compose.prod.yml up -d --build
Configuration is environment variables
Configuration follows a simple rule: the values in appsettings.json are development placeholders,
and every secret or environment-specific value is overridden by an environment variable in production.
There is no Key Vault or Secrets Manager scaffolding to adopt; wire your platform’s secret mechanism
to environment variables and you are done.
Typical overrides:
Database__ConnectionStringCaching__RedisMessaging__RabbitMq__*,Storage__*(SeaweedFS/S3)Cors__AllowedOrigins__0Otel__Endpointfor your collectorAuditing__IpHashSaltwith a random secret
Compose sets the first CORS origin from FRONTEND_BASE_URL and requires AUDIT_IP_HASH_SALT. Fill in
.env.prod before starting the stack. The internal readiness probe checks the API and Postgres after a startup grace period.
Database migrations
EF Core migrations are applied automatically on start in development. For production, run them as an
explicit step in your deploy pipeline so a rollout never races the schema. The included Compose stack deliberately
sets Database__MigrateOnStartup=true because it has no separate migration job. For multi-replica deployments, use
the image migration bundles and disable startup migrations. Run /app/efbundle-dataprotectionkeycontext
first, then /app/efbundle-appdbcontext, with the same configuration as the API container. Gate the
rollout on both succeeding. To apply the application context manually:
/app/efbundle-dataprotectionkeycontext --connection "$Database__ConnectionString"
/app/efbundle-appdbcontext --connection "$Database__ConnectionString"
On Kubernetes with Argo CD, run them in a Job that is a Sync hook in a sync wave after the secret,
database and ConfigMap and before the Deployment. A PreSync hook runs before those resources are
applied, so it misses a first install and any change to a hashed ConfigMap name. With
docker-compose.prod.yml, which has no separate step, set Database__MigrateOnStartup=true instead.
Behind a reverse proxy
The API trusts forwarded headers, so terminate TLS at your proxy or load balancer and forward the scheme and client address. This keeps secure-cookie flags, redirects and audited IP addresses correct.
Production host ports for the API, Grafana and Alertmanager bind to loopback by default. Put the proxy on
the host or Compose network; change the *_BIND_ADDRESS values only when your network supplies the access boundary.
CI
Pull request checks build and test the API, and format, test, lint and build the SPA. Landing changes have a separate production-build check. Use the same workflows as the gate for your deploys: a green build is a deployable build.
Adapting it
Slicekit does not prescribe a host. The images are standard, the configuration is environment variables, and the observability exporters are OTLP, so point them at your infrastructure and ship.