Dev.to · 7 min read

Directus + Coolify: Should You Decouple Postgres & Redis?

Directus + Coolify: Should You Decouple Postgres & Redis?

This is Part 2 of the Directus + Coolify series. If you're new here, start with "Secure Your VPS Before Hackers Do" and the first Directus + Coolify post — the bundled, single-Compose-file setup — before following along with this one. Introduction In the first method, we coupled all of the services into one stack using a single Docker Compose file. The network between all services was created automatically, and we didn't have to start them up individually — which removes the risk of a race condition if service startup isn't handled properly. If you're running a single app, that's genuinely the recommended way to set up Directus on a Coolify-managed VPS. Going in, I assumed there were several good reasons to split the services apart instead — more control over backups, monitoring, restarts, that kind of thing. So before recommending decoupling, I actually tested each of those assumptions on a live Coolify instance. Most of them turned out to be wrong. Myth 1: Restarting Directus Restarts the Whole Stack I expected that restarting Directus inside the bundled Compose file would restart Redis and Postgres along with it. It doesn't. Coolify lets you restart each service in the stack independently — Directus, Database, and Cache each get their own Restart button, right there in the same view. No decoupling needed for this one. Myth 2: You Need a Separate Database Resource for S3 Backups Same story. Even with Postgres bundled inside the Directus Compose file, Coolify still gives it its own dedicated Backups option, S3 included. This isn't a separate-resource-only feature. Myth 3: Scheduled Tasks Require Separate Services Also not true. Coolify exposes a Scheduled Tasks tab per service, even inside a single bundled stack — complete with a Container name dropdown letting you target the cron job at just the database, or just Directus, without splitting anything apart. What Actually Holds Up Two things survived testing. First: metrics. This one's confirmed directly in Coolify's own documentation — CPU and memory metrics collection is explicitly not available for Docker Compose–based deployments. If you want to see per-container resource usage through Coolify's built-in monitoring, the service needs to be created as its own standalone resource, not bundled inside a Compose file. This is a real, documented limitation of the bundled approach. Second: sharing a database across multiple apps. This one isn't a Coolify feature at all — it's just how Docker networking works. A database defined inside one app's Compose file lives on that stack's own private network by default. A second, completely separate application can't reach it without deliberately bridging the two networks. If you've got a desktop app and a mobile app that both need to talk to the same Postgres instance, that database needs to exist as its own standalone resource from the start — it can't stay tucked inside one app's Compose file. So this really comes down to two reasons to decouple, not five — one a genuine Coolify limitation, the other a structural fact about Docker networking. Let's set both of those up properly. Adding the Resources Adding the PostgreSQL Database Dashboard → Add Project + Add Resource Databases → PostgreSQL → Supabase PostgreSQL (with extensions) Change the name to something human-friendly Copy your username and password and save them somewhere — you'll need them shortly Click Save Click Start, and wait for the database to spin up (this can take a little while) Once it's up, the status should read "Running (Healthy)." 💡 Enable metrics while you're here. In the sidebar, go to Servers → localhost → Metrics, and enable metrics. Back in your project, under Databases, click your Postgres database, then Metrics — you should now see live CPU/memory usage for it. This is the exact capability that isn't available on a bundled Compose deployment. Adding Redis Cache Dashboard → + Add Resource (from the project itself) Databases → Redis Rename it to something more convenient Copy the Redis connection URL — you'll need it shortly Save, then Start Once both are running, SSH into your VPS and run: docker ps to confirm both containers are up. The Docker Compose Config for Directus This is what goes into the empty Compose file for the Directus resource: services: directus: image: 'directus/directus:12.2.0' ports: - '8055:8055' volumes: - './uploads:/directus/uploads' - './extensions:/directus/extensions' healthcheck: test: - CMD-SHELL - 'wget --spider -q http://127.0.0.1:8055/server/ping || exit 1' interval: 10s timeout: 5s retries: 5 start_interval: 5s start_period: 30s environment: SECRET: secretstring MARKETPLACE_TRUST: all DB_CLIENT: pg DB_HOST: DB_PORT: '5432' DB_DATABASE: postgres DB_USER: postgres DB_PASSWORD: CACHE_ENABLED: 'true' CACHE_STORE: redis CACHE_AUTO_PURGE: 'true' REDIS: ADMIN_EMAIL: joepublic@example.com ADMIN_PASSWORD: '1234567890' CORS_ENABLED: 'true' CORS_ORIGIN: 'true' CORS_CREDENTIALS: 'true' PUBLIC_URL: Notice the healthcheck already uses 127.0.0.1 instead of localhost — that's the fix from Part 1. Carrying it forward here saves you from hitting the exact same "unhealthy" bug all over again. Adding Directus Dashboard → + Add Resource (from the project itself) Applications → Docker Compose Empty Paste in the Compose configuration above Click Save Network → Connect To Predefined Network → check the box Services → Directus service → Settings Add your Directus subdomain — remember to use https:// (e.g. https://directus.yourdomain.com) Save Connecting the Services Together Variable What it is SECRET A long, unguessable random string DB_HOST The name of your Postgres container — run docker ps on your VPS to find it DB_DATABASE The name of the database on your Postgres server (Coolify's default is usually postgres, but confirm it against your Postgres service) DB_USER The database username, from the Postgres service you created earlier DB_PASSWORD The password from that same Postgres service REDIS The Redis connection URL from the Redis service you created earlier PUBLIC_URL Your Directus subdomain ⚠️ Redis URL gotcha: the connection URL follows the format redis://username:password@host:port. Coolify's generated URL includes the username you set when creating the Redis resource — in my case, that username was also redis, so the URL looked like redis://redis:somelongvariable.... Directus doesn't need the username here, just the password, so strip that segment out: redis://:somelongvariable.... If you used a different username when creating your Redis resource, remove that value instead — not literally the word "redis." Setting Up Environment Variables Rather than hardcoding any of this directly into the Compose file, move it into Directus's environment variables: Dashboard → Projects → Services / Directus Environment Variables Click + Add, enter the variable name in all caps, and its value Save Repeat for: SECRET, DB_HOST, DB_DATABASE, DB_USER, DB_PASSWORD, ADMIN_EMAIL, ADMIN_PASSWORD, and REDIS Updating the Compose File Now reference those variables instead of the raw values: SECRET: '${SECRET}' DB_HOST: '${DB_HOST}' ...and so on for each variable. Then: Save Restart Launching Directus Paste your Directus subdomain into the browser, and you should land on your running Directus instance. You can also click Links on the Directus service, then click the subdomain — it'll take you straight to your Directus Studio login. Same as the last video: sign up for your free license, which arrives by email, and paste it into your Directus instance to unlock everything. Any questions or hit a different result testing any of these yourself? Drop it in the comments — I'm genuinely curious whether this holds up across different Coolify versions and setups.

This is a summary aggregated from Dev.to. Read the complete article on the original site:

Read full article at Dev.to

More Startup & VC News