Staging and prod on one host
Run a staging Olympus alongside production on the same VPS
For solo / small teams: one VPS, two Olympus deployments (prod + staging). This recipe covers the gotchas.
Approach
Two complete Compose stacks on the same Podman host, on different ports + domains.
VPS
├── Caddy (prod) :80 :443 → ciam.example.com, iam.example.com
├── ... prod stack
└── Caddy (staging) :8080 :8443 → ciam.staging.example.com, iam.staging.example.com
└── ... staging stackOr use port 80/443 only for prod, with staging behind a wildcard subdomain on a different VPS / Tailscale.
The simpler choice: separate VPSes. Adds ~$5/month for staging. Worth it.
If you really want them on one VPS
Compose project names
Use distinct Compose project names so containers don't collide:
podman compose -p olympus-prod -f compose.prod.yml up -d
podman compose -p olympus-staging -f compose.staging.yml up -dPort conflicts
Both stacks include Postgres (port 5432). To run both:
- Prod uses 5432 (or self-hosted on a non-default port).
- Staging uses 5433 (host-bind on a different port) or its own Postgres container with different volume.
For Caddy, only one can own ports 80/443. Either:
- Prod gets 80/443; staging gets 8080/8443.
- A single shared Caddy reverse-proxies to both stacks' internal services.
The shared-Caddy approach is cleaner for many deployments, one TLS, one rate-limit zone, route via hostname.
Shared Caddy config
ciam.example.com {
reverse_proxy ciam-hera-prod:3000
}
ciam.staging.example.com {
reverse_proxy ciam-hera-staging:3000
}Both stacks reside in the same intranet Compose network so Caddy can reach all upstream service names.
Database isolation
Crucial: prod and staging must have separate Postgres databases. Either:
- Two Postgres containers, separate volumes.
- One Postgres container, separate databases (prefix table names or DBs).
The latter saves resources but mixes prod and staging data physically, riskier.
Domain DNS
Two sets of subdomains:
- Prod:
ciam.example.com,iam.example.com. - Staging:
ciam.staging.example.com,iam.staging.example.com.
Both A-records point to the same VPS IP.
Operational impact
- Resource usage: doubles. A VPS that was fine for prod alone may slow.
- Deploy isolation: a deploy of staging shouldn't break prod. But shared resources (Caddy, Postgres if collocated) can.
- Backups: separate prod and staging backups. Restoring prod backup to staging is a useful regular drill.
Promoting staging to prod
A typical flow:
- Develop a change on staging branch.
- Deploy to staging via
gh workflow run deploy.yml -f env=staging. - Verify.
- Merge staging branch to main.
- Deploy workflow runs against prod.
The platform repo can have multiple compose.<env>.yml files; the deploy workflow accepts an env input.
When two VPSes is cleaner
The added cost is small; isolation is real:
- Staging deploy doesn't risk prod.
- A staging VPS reboot doesn't affect prod.
- Resource contention is impossible.
Recommend two VPSes unless cost is genuinely a constraint.