Deploying to Coolify
Coolify is a self-hosted PaaS that uses Docker Compose as its source of truth. It adds a Traefik reverse proxy, automatic HTTPS via Let’s Encrypt, and a web UI for managing deployments. All routing, env vars, and storage are configured in the compose file itself.
Official docs: coolify.io/docs/knowledge-base/docker/compose
Docker Compose for Coolify
Section titled “Docker Compose for Coolify”A ready-to-use docker-compose.coolify.yml is included in the repo root:
# docker-compose.coolify.yml — Procella on Coolify
services: procella: build: context: . dockerfile: Dockerfile # Or use a pre-built image: # image: ghcr.io/your-org/procella:latest
environment: # Non-sensitive config (set here or override in Coolify UI) PROCELLA_LISTEN_ADDR: ":9090" PROCELLA_AUTH_MODE: "descope" # or dev PROCELLA_BLOB_BACKEND: "s3" PROCELLA_BLOB_S3_REGION: "us-east-1"
# Sensitive values — set in Coolify UI under "Environment Variables" # (leave as placeholders; Coolify will substitute) PROCELLA_DATABASE_URL: "${PROCELLA_DATABASE_URL}" PROCELLA_DEV_AUTH_TOKEN: "${PROCELLA_DEV_AUTH_TOKEN}" PROCELLA_ENCRYPTION_KEY: "${PROCELLA_ENCRYPTION_KEY}" PROCELLA_DESCOPE_PROJECT_ID: "${PROCELLA_DESCOPE_PROJECT_ID}" PROCELLA_DESCOPE_MANAGEMENT_KEY: "${PROCELLA_DESCOPE_MANAGEMENT_KEY}" PROCELLA_BLOB_S3_BUCKET: "${PROCELLA_BLOB_S3_BUCKET}" PROCELLA_BLOB_S3_ENDPOINT: "${PROCELLA_BLOB_S3_ENDPOINT}" AWS_ACCESS_KEY_ID: "${AWS_ACCESS_KEY_ID}" AWS_SECRET_ACCESS_KEY: "${AWS_SECRET_ACCESS_KEY}"
# Tell Coolify to route procella.your-domain.com:443 → container:9090 labels: - traefik.enable=true - "traefik.http.routers.procella.rule=Host(`procella.your-domain.com`)" - traefik.http.routers.procella.entryPoints=https - traefik.http.routers.procella.tls.certresolver=letsencrypt - traefik.http.services.procella.loadbalancer.server.port=9090
depends_on: db: condition: service_healthy
restart: unless-stopped
healthcheck: test: ["CMD", "/procella", "--healthz"] interval: 15s timeout: 5s retries: 3 start_period: 20s
db: image: postgres:17-alpine environment: POSTGRES_DB: procella POSTGRES_USER: procella POSTGRES_PASSWORD: "${POSTGRES_PASSWORD}" volumes: - procella_pgdata:/var/lib/postgresql/data restart: unless-stopped healthcheck: test: ["CMD-SHELL", "pg_isready -U procella -d procella"] interval: 10s timeout: 5s retries: 5
volumes: procella_pgdata: driver: localCoolify Setup
Section titled “Coolify Setup”1. Add your source
Section titled “1. Add your source”In the Coolify dashboard:
- Projects → New Resource → Docker Compose
- Connect your Git repo (GitHub/GitLab/Gitea)
- Set the compose file path to
docker-compose.coolify.yml
2. Configure the domain
Section titled “2. Configure the domain”Coolify will ask for a domain. Enter procella.your-domain.com. It appends :9090 automatically because the app container port is 9090.
Alternatively, use a Coolify magic variable in your compose:
environment: # Coolify generates the FQDN automatically COOLIFY_FQDN: "${SERVICE_FQDN_PROCELLA_9090}"3. Set secrets
Section titled “3. Set secrets”In the Coolify UI → your service → Environment Variables:
| Variable | Value |
|---|---|
PROCELLA_DATABASE_URL | postgresql://procella:${POSTGRES_PASSWORD}@db:5432/procella |
POSTGRES_PASSWORD | openssl rand -hex 24 output |
PROCELLA_ENCRYPTION_KEY | openssl rand -hex 32 output |
PROCELLA_DEV_AUTH_TOKEN | your auth token |
PROCELLA_DESCOPE_PROJECT_ID | from Descope console |
PROCELLA_DESCOPE_MANAGEMENT_KEY | from Descope console |
4. Deploy
Section titled “4. Deploy”Click Deploy in the Coolify UI, or push to your linked branch for auto-deploy.
External Postgres (Recommended for Production)
Section titled “External Postgres (Recommended for Production)”Rather than bundling Postgres in the same compose stack, provision it as a separate Coolify resource (Database → PostgreSQL 17). This gives it its own volume, restart policy, and backup schedule.
Then in your procella service, reference it via the internal Docker network:
# Coolify renames services to <service>-<uuid> to avoid collisions.# Use the "Connect to Predefined Network" option in Coolify UI,# then reference the database by its Coolify-generated hostname.environment: PROCELLA_DATABASE_URL: "postgresql://procella:pass@postgres-abc123:5432/procella"Blob Storage
Section titled “Blob Storage”For a self-hosted setup, you can run MinIO alongside Procella:
services: minio: image: minio/minio:latest command: server /data --console-address ":9001" environment: MINIO_ROOT_USER: "${MINIO_ROOT_USER}" MINIO_ROOT_PASSWORD: "${MINIO_ROOT_PASSWORD}" volumes: - procella_minio:/data labels: - traefik.enable=true - "traefik.http.routers.minio.rule=Host(`minio.your-domain.com`)" - traefik.http.routers.minio.entryPoints=https - traefik.http.routers.minio.tls.certresolver=letsencrypt - traefik.http.services.minio.loadbalancer.server.port=9000 restart: unless-stoppedThen configure Procella to use it:
PROCELLA_BLOB_BACKEND: "s3"PROCELLA_BLOB_S3_ENDPOINT: "http://minio:9000"PROCELLA_BLOB_S3_BUCKET: "procella"PROCELLA_BLOB_S3_REGION: "us-east-1"AWS_ACCESS_KEY_ID: "${MINIO_ROOT_USER}"AWS_SECRET_ACCESS_KEY: "${MINIO_ROOT_PASSWORD}"Bun / Docker Notes
Section titled “Bun / Docker Notes”- Coolify uses your
Dockerfiledirectly viabuild: { context: ., dockerfile: Dockerfile }. Thebun build --compilebinary runs without a Bun/Node runtime in the final distroless stage. - The distroless base image is compatible with Coolify’s Traefik sidecar network. Note: there is no shell inside the container, so
docker execdebugging requires a debug image or sidecar. - Coolify adds
coolify.managed=trueand Traefik labels automatically if not present. Your explicit Traefik labels in the compose file take precedence.