decisionshared last reviewed 2026-06-04

Coolify is the default deployment platform for customer-facing apps

Context

Aspire needs a way to deploy ~40+ web apps + APIs without each project re-inventing the deploy story. Options reviewed in early 2026: Vercel/Netlify (managed PaaS), Coolify (self-hosted PaaS), bare Docker on a VPS, Kubernetes.

The first Coolify standard let Coolify pull source and build Dockerfiles directly. That worked, but it made Coolify responsible for expensive build work, increased deploy queue contention, and made staging/prod less artifact-identical. DOCX (docx.aspiredigitalgroup.com.au, api-docx.aspiredigitalgroup.com.au) proved the better pattern: GitLab builds and stores images; Coolify only pulls and runs them.

Detail

Decision

Coolify remains the default runtime/orchestration platform for customer-facing webapps. GitLab CI is the default build and promotion platform.

The standard deployment flow is:

  1. GitLab validates, builds, scans, and pushes an immutable image/artifact.
  2. Staging deploys that exact artifact through Coolify.
  3. Staging smoke tests pass.
  4. Prod promotes the same immutable artifact through Coolify.
  5. Coolify handles env vars, routing, volumes, health checks, logs, deploy hooks, restarts, and rollback redeploys.

Coolify-side Dockerfile builds are now a legacy/fallback path, not the preferred default.

OpenClaw VPS (112.121.151.239) remains reserved for internal AI infrastructure (28 agents, Knowledge OS, MCP servers).

Rationale

What's NOT Coolify

Known Coolify quirks (operational hazards captured 2026-04 โ†’ 2026-05)

#QuirkWorkaround
1ports_exposes API param silently rejected; defaults to 80Encode port in FQDN: https://<host>:4000. Coolify reads this to generate Traefik loadbalancer.server.port=4000
2update_application doesn't regenerate Traefik labelsOnce an app exists, port routing is frozen. Delete + recreate to change.
3Build-time env injection โ€” bulk_update_app_envs defaults is_buildtime=true โ†’ secrets baked into imageForce-rebuild after env changes (not just restart)
4UI env edits sometimes don't propagate via APIFirst attempt may need a manual UI save; API update_app_env worked reliably
5Deploy queue holds 4+ concurrent jobsExpect 5-15min wait during busy times
6Dockerfile-only builds can't COPY external filesInline everything via heredoc: RUN cat > /file <<EOF...EOF
7Helper-prep race / container-recycle race / helper-killed-mid-buildRecover via "wait until in_progress queue EMPTY then retry on idle VPS"
8Volume-prefix doubling on app updates โ†’ fresh-empty volume mounted (Postiz outage 2026-05-13โ†’16, 8 hours)DO NOT run Coolify ops on Postiz until permanent volume fix applied
9GitLab PAT in ~/.claude.json rotates mid-sessionRe-read on 401

Full quirks list lives in MEMORY.md (reference_coolify_gotchas) โ€” read before any Coolify deploy.

Standard deploy flow

git push / merge request
    โ†“
GitLab validate + build + scan
    โ†“
GitLab pushes immutable image tag
    โ†“
Coolify deploy hook pulls that tag
    โ†“
Coolify swaps container (with health-check)
    โ†“
Traefik routes traffic to new container
    โ†“
HTTP 200 on /health

Required project records:

Constraints we accepted

Revisit trigger

Actions

Related

๐Ÿ”— Relationships

graph LR coolify_deployment_default["coolify-deployment-default"]:::self coolify_deployment_default --> aspire_llm_gateway["aspire-llm-gateway"] coolify_deployment_default --> aspire_hub["aspire-hub"] coolify_deployment_default --> knowledge_os_stage_1["knowledge-os-stage-1"] classDef self fill:#715EE3,color:#fff,stroke:#291F50;