# Directus + Coolify: Should You Decouple Postgres & Redis?

%[https://www.youtube.com/watch?v=6cMrbfGZqb8] 

> 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:

```bash
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:

```yaml
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:

```yaml
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.
