Deploy to Coolify
Open-source self-hosted PaaS. Similar shape to Dokploy, larger ecosystem.
Self-hosting with a big library of one-click services alongside your app, and multi-server support once one box is not enough.
Minimal setups: it carries more moving parts than a plain Docker Compose file.
Quick setup
- 1
Install
Same shape as Dokploy: one script on a clean VPS, then everything else through the panel.
curl -fsSL https://cdn.coollabs.io/coolify/install.sh | bash - 2
Add the application
Choose the Dockerfile build pack and set the base directory to the API. Coolify reads the Dockerfile as-is, so the image Grit generates needs no changes.
Build pack: DockerfileBase directory: /apps/apiPorts exposed: 8080 - 3
Attach databases and set the health check
Add Postgres and Redis as resources in the same project, then copy their internal connection strings into the app. Set the health check path to
/api/healthso a failed boot is caught rather than served.
What catches people out
Internal connection strings use the container name, not localhost. Using localhost is the single most common Coolify support question.
Coolify keeps every build image by default and will fill the disk. Set a cleanup schedule on day one.
Coolify runs the real Compose engine, which is why it needs the fewest edits: depends_on with condition: service_healthy behaves exactly as it does locally, and services still resolve each other by compose service name.
Deploying Sentex: VPS + Coolify
The example application below is called sentex and its domains are on gritcms.com. Substitute your own project name and hostnames as you go — every other detail, including the service layout and the Compose translation, applies unchanged to any Grit project.
Coolify also runs your Compose file close to as-is (it literally runs docker compose under the hood), but it manages its own reverse-proxy network and strongly warns against custom Compose networks. You’ll make a small, mechanical edit to docker-compose.prod.yml for this platform — everything else (services, builds, volumes, the migrate job) stays exactly as written.
2.1 Provision the VPS and install Coolify
- Spin up a VPS (same sizing guidance as Dokploy). Ubuntu 24.04 or Debian 13 are the best-supported targets.
- Point the same three DNS A records at this VPS’s IP (a different VPS than Dokploy’s, obviously, if you’re comparing platforms — don’t point both at the same IP at the same time).
- SSH in and run the official installer:curl -fsSL https://cdn.coollabs.io/coolify/install.sh | bash
- Open
http://<VPS public IP>:8000, create your admin account, and (recommended) attach a domain + HTTPS to the Coolify dashboard itself under server settings.
2.2 Make a Coolify-specific branch/copy of the Compose file
Create docker-compose.coolify.yml (or a coolify branch — whatever fits your workflow) with two changes from docker-compose.prod.yml:
- Remove the
networks:block at every service, and delete the top-levelnetworks:section entirely (both thesentexbridge and thedokploy-network: external: truereference). Coolify creates its own isolated bridge network per Compose stack and attaches its own Traefik to it automatically — defining custom networks alongside that causes exactly the kind of intermittent 504/unreachable behavior Coolify’s docs specifically warn about, because your containers would sit on two networks at once and Traefik might pick the wrong one. - Remove the
labels:blocks (thetraefik.*labels) fromapi,admin, andweb. You’ll set domains through Coolify’s UI instead in Part 2.4 — its proxy is still Traefik, but its label names/entrypoint names don’t necessarily match Dokploy’s, so hand-rolled labels are more likely to conflict with what Coolify generates than to help.
Everything else — build:, image:, environment:, env_file:, volumes:, depends_on:, healthcheck:, command:, restart: — stays identical. In particular, leave the migrate service and its depends_on: condition: service_completed_successfully exactly as-is — Coolify runs real Docker Compose, so this ordering guarantee works without any translation, the same as on Dokploy.
Optionally, mark migrate as excluded from Coolify’s aggregate healthchecks, since it’s meant to exit rather than stay running:
services:migrate:exclude_from_hc: true# ...rest unchanged
2.3 Create the resource in Coolify
- In the Coolify dashboard, create a Project, then a new Resource inside it.
- Choose your Git source (Public Repository, or GitHub App / Deploy Key for a private repo — set up whichever you haven’t already under Sources).
- Select the
sentexrepository and branch. - When prompted for a Build Pack, change it from the Nixpacks default to Docker Compose.
- Set:
- Base Directory:
/(repo root) - Docker Compose Location:
docker-compose.coolify.yml(the file from Part 2.2 — match the exact filename/extension you used)
- Base Directory:
- Click Continue.
2.4 Domains
Coolify reads your Compose file’s services and lets you assign a domain to each one directly — no labels needed since you removed them in Part 2.2.
- On the resource’s configuration screen, find the domain field for each service and set:
api→https://api.sentex.gritcms.com:8080(append:8080because that’s the container portapilistens on — Coolify’s proxy still serves the public side on the normal HTTPS port; the:8080just tells it where to send traffic internally)admin→https://admin.sentex.gritcms.com:3000web→https://sentex.gritcms.com:3000
- Leave
postgresandrediswith no domain assigned — without a domain or aports:mapping, Coolify keeps a service private and reachable only over the internal network athttp://postgres:5432/http://redis:6379-style hostnames (i.e., exactly the plain service-name DNS your Compose file’sPOSTGRES_HOST=postgres/REDIS_URLvalues already assume).
2.5 Environment variables
- Coolify auto-detects every
${VARIABLE}referenced in your Compose file (inenvironment:,env_file:-driven values you reference, andbuild.args) and lists them in the resource’s Environment Variables tab. - Fill in the same values you’d put in
.env.production:POSTGRES_USER,POSTGRES_PASSWORD,POSTGRES_DB,WEB_DOMAIN,ADMIN_DOMAIN,API_DOMAIN,THEME,SOCIAL_AUTH_ENABLED,NEXT_PUBLIC_DEMO_LOGINS, theR2_*credentials, and any app secrets. - Coolify injects these both as build args (for
admin/web’sNEXT_PUBLIC_*values) and as runtime environment — matching how the Compose file already declares them.
2.6 Deploy and verify
- Click Deploy. Watch the build/deploy log stream in the UI.
- Confirm
migrateruns and exits cleanly beforeapi,admin, andwebstart (same ordering as Dokploy — real Compose semantics). - Give Coolify’s Traefik a short moment to issue Let’s Encrypt certs for the three domains, then visit each in a browser and confirm no CORS errors and that the seeded demo login works.
- Under the resource’s Webhooks/Source settings, confirm auto-deploy on push is enabled if you want GitHub pushes to redeploy automatically.
Platform dashboards and CLI flags change faster than these docs. For anything that looks different from what is written here, Coolify's own documentation is the authority: coolify.io/docs/
