Infra template: overview
infra/compose composes apps/api and apps/ui into one running stack. It targets your laptop and a first VPS before you need cluster machinery, while keeping observability, email, and queue tooling close to the app.
Service inventory
Section titled “Service inventory”The base stack (always on):
- postgres - Always-on app database
- valkey - Redis-protocol cache plus BullMQ queue backend
- traefik - Prod reverse proxy, ACME, and one-domain path routing
- api-migrate - One-shot schema push plus optional superuser seed
- api-dev / api - Bun + Elysia in dev, GHCR image in production
- ui-dev / ui - Vite dev server locally, nginx static image in production
Optional overlays:
- observability - Prometheus, Grafana, Loki, Promtail, and exporters
- error tracking - GlitchTip
- mail and queue tools - Mailpit, Bull Board, WUD image-update detector
Profile model
Section titled “Profile model”The profile system uses environment flags to compose overlays over the base stack:
./dev.sh up -d # default: api + ui + postgres + valkey + observability + glitchtipSTACK=prod ./dev.sh up -d # prod: GHCR images, Traefik, HTTPS via ACME (same defaults)WITH_OBSERVABILITY=0 ./dev.sh up -d # skip observabilityWITH_GLITCHTIP=0 ./dev.sh up -d # skip glitchtipWITH_BULLMQ=1 ./dev.sh up -d # add bull board (opt-in)WITH_WUD=1 ./dev.sh up -d # add WUD image-update detector (opt-in)WITH_MAILPIT=1 ./dev.sh up -d # add Mailpit local SMTP (opt-in)The default stack includes Prometheus, Grafana, Loki, and GlitchTip. Niche tooling (Bull Board, WUD, Mailpit) is opt-in. See Profiles & overlays.
File layout
Section titled “File layout”Under infra/compose/:
compose/ - Compose files and per-profile service overlays
docker-compose.yml- Base: postgres, valkey, api-migrate, api/ui, Traefik in proddocker-compose.development-labels.yml- Dev overlay: host-published data portsdocker-compose.production-labels.yml- Prod overlay: HTTPS, ACME, path routing, security headersdocker-compose.observability.yml- Prometheus, Grafana, Loki, Promtail, exportersdocker-compose.glitchtip.yml- GlitchTip dev + proddocker-compose.glitchtip-prod-labels.yml- Prod-only HTTPS + BasicAuth labelsdocker-compose.bullmq.yml- Bull Board in developmentdocker-compose.wud.yml- WUD image-update detectordocker-compose.mailpit.yml- Local SMTP catcher in developmentdev.sh- Orchestrator.env.example- All knobs in one fileprometheus/- Scrape configgrafana/- Datasource provisioningalertmanager/- Alert routespromtail/- Log scrape configglitchtip/- init-db.sql
scripts/ - Operational wrappers
compose-up.sh- bring the stack upcompose-down.sh- stop without deleting datacompose-down-clean.sh- clean local services intentionallybackup-wrapper.example.sh- Postgres to rclone, with retentionufw.example.sh- UFW + Cloudflare IP allowlistglitchtip-bootstrap.sh- Prod GlitchTip migrate + superuser
docs/ - Runbooks and cheatsheets
Networks
Section titled “Networks”Two bridge networks. Services are split on purpose:
backend (data plane). postgres, valkey, api[-dev], api-migrate, exporters, glitchtip, and mailpit.
frontend (ingress). traefik in prod, ui[-dev], and glitchtip-web. Traefik joins both when it needs to route.
In prod, Traefik joins both networks so it can route HTTPS from frontend to services on backend. The data plane (Postgres, Valkey) is never exposed to frontend.
Resource budgets
Section titled “Resource budgets”Every service has deploy.resources.limits and reservations driven by env vars with sane defaults sized for a 4-vCPU / 8 GB host. Adjust in compose/.env; see Resource limits for sizing guidance.
What’s not in this template
Section titled “What’s not in this template”- Kubernetes manifests in this (Compose) target. BoringStack is Compose-first, and
infra/composedeliberately stays cluster-free so the single-host path is clear. If you run a Kubernetes cluster and want GitOps, the opt-in Kubernetes (k3s) target lives separately underinfra/k3s. It never mixes into the Compose flow. - Application code. The apps/api and apps/ui own that.
- Cloud-provider provisioning. The OpenTofu bootstrap in
infra/bootstraphandles that.
Related
Section titled “Related”- Profiles & overlays; how the
WITH_*=1flags compose over the base. - Resource limits; the per-service budgets sized for a 4 vCPU / 8 GB host.
- Secrets; how env values reach containers without leaking into images.
- Deployment; the production runtime path end-to-end.
- Provisioning with OpenTofu; going from zero to a live VPS.
- Kubernetes (k3s); the opt-in GitOps target for a cluster you already run.