Start and operate

Start

docker compose up -d --build
docker compose ps

In order: Caddy obtains the certificates; PostgreSQL, RabbitMQ and Redis become healthy; migrations creates the schemas and exits 0; then the identity host, the API, the gateway and the SPA become healthy. Open https://app.example.com, create the first account and confirm it from the e-mail.

Seeding is off in Production: the database starts empty, except for the plan catalog.

The first administrator

BlouppyAdmin is the support role: an account that carries it passes every organization role check of the API, to help an organization's people. Nobody has it in Production, and there is no screen to grant it, on purpose. Give it to your own account once confirmed, from the database — deploy/README.md has the two SQL statements. Sign out and in again: the role is read at sign-in.

Migrations

The migrations service runs before the hosts on every docker compose up. In Production the runner applies nothing unless Migrations__AllowInProduction=true; .env.example sets it, so an upgrade migrates on its own.

To make schema changes a deliberate release step, set it to false and migrate by hand before starting the new version:

docker compose run --rm -e Migrations__AllowInProduction=true migrations

A failed migration exits 1, and the hosts are not started against a schema in an unknown state.

Upgrading

git pull                       # or copy the new version
./backup.sh                    # always before a schema change
docker compose up -d --build   # rebuilds, migrates, then restarts the hosts
docker image prune -f

Sessions survive the restart: the keys that encrypt them are in the database. To build images once elsewhere and only pull on the server, set BLOUPPY_IMAGE_PREFIX to your registry and BLOUPPY_VERSION to the version.

Backups

WhatWhereWithout it
The databasethe postgres-data volumeeverything
The Data Protection certificatedeploy/secrets/data-protection.pfx and its passwordsessions, reset links, saved AI keys and webhook secrets unreadable
Files: data exports and avatarsthe bucket, or the files volumethe files
.envdeploy/.envthe configuration

deploy/backup.sh writes a compressed pg_dump to deploy/backups/ and keeps 14 days. Run it before every upgrade and nightly, and copy backups/ off the server every day. Try a restore once, into a scratch database, before you need one — deploy/README.md gives the commands.

Operating

  • Health. Every host answers GET /health (ready: its database, its broker) and GET /alive (the process). Point an uptime monitor at https://app.example.com/health.
  • Logs.docker compose logs -f gateway identity api, or set OTEL_EXPORTER_OTLP_ENDPOINT to send traces, metrics and logs to an OpenTelemetry collector.
  • Start-up warnings worth acting on: unencrypted Data Protection keys, no CAPTCHA keys, an empty ApiIntrospection:Secret, an API without its response cache, a Stripe test key in production. A healthy start logs no fail line.
  • Scaling out. The hosts are stateless: sessions, keys, scheduled jobs (clustered Quartz.NET) and real-time fan-out (RabbitMQ) are shared. docker compose up -d --scale api=2 works for the API. More than one server needs a load balancer doing what Caddy does here, and FileStorage__Provider=S3.
  • Behind a CDN, list its address ranges in trusted_proxies in deploy/Caddyfile, or the audit log and the rate limits will see the CDN's address instead of the visitor's.

The static sites

The landing page and the documentation site have no dependency on the stack. Each has its own nginx image (front/landing/Dockerfile, front/docs/Dockerfile), or you deploy its build output to any static host:

cd front && npm ci
npm run build --workspace landing
npm run build --workspace docs

Their addresses are built in: set them before building (see Rename and rebrand).

Without Docker Compose

The images run anywhere containers run. What the compose file supplies, you then supply yourself: the connection strings, the hosts' public addresses, the trusted proxy range, a job running the migration image before the hosts roll out, and a TLS-terminating load balancer. deploy/README.md lists each setting.