Directus on Ubuntu 24.04 (PostgreSQL + PM2 + Nginx + SSL)
Directus is an open-source data platform that provides a real-time REST and GraphQL API plus an admin app on top of your SQL database. Unlike a traditional CMS that owns your schema, Directus treats your database as the source of truth: it introspects existing tables, adds a lightweight system schema, and exposes content and data with granular permissions.
Ubuntu 24.04 (Noble) offers a secure, long-supported base, modern OpenSSL 3, systemd 255, and up-to-date Node.js and PostgreSQL packages—ideal for self-hosted Directus.
Architecture Overview
Layer | Component | Role |
---|---|---|
OS | Ubuntu 24.04 LTS | Stable, secure base; systemd service management |
Runtime | Node.js LTS (18 or 20) | Runs Directus API/admin application |
Database | PostgreSQL 15/16 | Primary datastore for content, system tables, and files metadata |
Process Manager | PM2 | Keeps Directus alive, logging, clustering, startup on boot |
Reverse Proxy | Nginx | TLS termination, HTTP/2, compression, caching, routing |
TLS | Let’s Encrypt or corporate PKI | HTTPS for admin panel and APIs |
Why PostgreSQL for Directus
Directus supports MySQL, SQLite, and PostgreSQL; Postgres is commonly preferred for:
- JSONB and rich indexing for semi-structured fields.
- Strong transactional guarantees and concurrency under API load.
- Mature extensions (pg_trgm, full-text search) and role management.
- Straightforward replication/WAL archiving for backup and HA.
Use a dedicated Postgres instance for medium/large footprints; tune shared_buffers
, work_mem
, effective_cache_size
, and WAL settings per workload and storage.
PM2 for Process Control
- Daemonizes Directus; auto-restarts on crashes and reboots (
pm2 startup
). - Cluster mode to leverage multiple CPU cores with zero-downtime reloads.
- Centralized logs with rotation; basic metrics via
pm2 monit
or exporters. - Use an ecosystem file to pin environment variables, working dir, instances, and per-env configs.
Nginx and SSL as the Public Edge
- Reverse proxy to Directus on localhost (e.g., 8055), keep the app port blocked externally.
- TLS termination with HTTP/2, OCSP stapling, modern ciphers (OpenSSL 3).
- Security headers: HSTS, X-Content-Type-Options, X-Frame-Options, Referrer-Policy, and a tight CSP for the admin UI.
- Static and upload routing, gzip/brotli, basic rate limiting on auth and admin endpoints.
- Automate certificates with Certbot/ACME; test renewals and reloads.
Security and Access Control
- Environment variables only for secrets; never commit
.env
files. Consider a secret manager if already in your stack. - Ubuntu firewall (UFW or nftables): expose only 80/443; bind Directus to 127.0.0.1.
- Directus RBAC: roles, permissions, and granular field-level access. Separate “admin” from “editor” and “public” roles.
- Authentication: local accounts, OAuth/OIDC, SSO providers; rotate tokens.
- File security: choose a storage driver (local, S3/MinIO, GCS). For public assets, serve via Nginx or a CDN with signed URLs when needed.
- Keep Node, Directus core, and extensions patched; run dependency audits in CI.
- Fail2Ban on Nginx for brute-force mitigation; centralized logging for forensics.
Sizing and Performance
Small (pilot or internal)
- 2 vCPU, 4–8 GB RAM, single PM2 instance.
- PostgreSQL co-located or small dedicated VM.
- Local file storage acceptable; backups to object storage.
Medium (multi-team, public APIs)
- 4–8 vCPU, 8–16 GB RAM; PM2 cluster (2–4 workers).
- Dedicated PostgreSQL on NVMe; automated backups and point-in-time recovery.
- Object storage (S3/MinIO) for files; Nginx caching for GETs where safe.
Large (high traffic, complex schema)
- Multiple Directus nodes; L4/L7 load balancer plus per-node Nginx.
- HA PostgreSQL (managed service or Patroni) with read replicas for reporting.
- Redis (if used by extensions/ratelimiting); CDN in front of assets.
Operational tips:
- Set
NODE_ENV=production
. - Cache safe, public GET endpoints at Nginx/CDN.
- Keep Directus system schema under version control via migrations; test upgrades in staging.
Observability
- Logs: PM2/application logs to journald or files; ship with Vector/Fluent Bit to ELK/OpenSearch.
- Metrics: Node/PM2 exporters to Prometheus; postgres_exporter for DB health; Nginx exporter or
stub_status
. - Health checks: Nginx upstream checks; synthetic probes for key endpoints; database liveness checks in CI/CD.
Typical Use Cases
- Data-first headless CMS where you own the schema and data model.
- Rapid API layer over existing databases without rewriting schemas.
- Multi-tenant content hubs with granular permissions.
- Back-office dashboards and admin portals for operational data.
- Product catalogs, documentation hubs, and multilingual content services.
Directus vs. Other Headless/Databases-First Platforms
Capability | Directus | Strapi | KeystoneJS | Payload | Hasura |
---|---|---|---|---|---|
DB ownership | Your existing SQL | ORM-managed | Schema-defined | Schema-defined | Your existing SQL |
Admin app | Built-in | Built-in | Built-in | Built-in | Console (focus on GraphQL) |
APIs | REST + GraphQL | REST + GraphQL | REST + GraphQL | REST + GraphQL | GraphQL (auto) |
RBAC/permissions | Granular, field-level | Role/permission model | Schema-driven | Role/field rules | Row-level policies (RLS) |
Files | Local/S3 drivers | Local/S3 drivers | Local/S3 | Local/S3 | External |
Directus is strongest when you want a no-lock-in admin UI and APIs directly on top of a database you fully control.
Production Checklist (no commands)
- Lock Node.js LTS and package manager versions in CI; build once, promote across environments.
- PostgreSQL 15/16 with backups, PITR, and monitoring; define roles per environment.
- Run Directus under PM2 with an ecosystem config; enable startup on boot; cluster where useful.
- Front with Nginx; terminate TLS; restrict the Directus port to localhost.
- Configure RBAC carefully; separate admin/editor/public roles; enable SSO if required.
- Store media in S3/MinIO; apply lifecycle and access policies; use a CDN for public assets.
- Enable logging, metrics, alerting; test disaster recovery regularly; patch on schedule.
A Directus + PostgreSQL + PM2 + Nginx + SSL stack on Ubuntu 24.04 delivers a secure, flexible, and maintainable data platform. You retain full control of your schema and data, gain real-time REST/GraphQL APIs and a polished admin UI, and rely on a hardened TLS edge and process supervision for uptime. This setup scales cleanly from MVPs to high-traffic, multi-team platforms while keeping operational complexity reasonable.
Step 1: Create an Ubuntu 24.04 VPS on Shape.Host
Go to https://shape.host and log in.
Click “Create”, then select “Instance”.

Choose the server location closest to your users.

Select Ubuntu 24.04 (64-bit) as the operating system.
Pick a plan with at least 2 CPUs, 4 GB RAM, and 20 GB SSD storage.

Click “Create Instance”.

Copy your server IP address from the Resources section.

Step 2: Connect to Your Server
On Linux or macOS
Open a terminal and run:
ssh root@your-server-ip
This connects to the server using SSH (Secure Shell).
On Windows
If you’re on Windows, you can use:
- Command Prompt or PowerShell (Windows 10/11) – run:
ssh root@your-server-ip
- PuTTY (older Windows versions) –
- Download PuTTY from https://www.putty.org/.
- Open PuTTY, enter your server IP, choose SSH connection, and click Open.
- Login as
root
when prompted.
Step 3: Update the System and Install Required Packages
apt update
apt upgrade
apt update
refreshes the package index.apt upgrade
installs the latest available versions of all packages.

apt install curl wget gnupg2 ca-certificates nginx unzip nano -y
- Installs essential tools:
- curl/wget: download files from the internet.
- gnupg2: manage encryption keys.
- ca-certificates: ensures SSL certificates work.
- nginx: web server that will act as reverse proxy.
- unzip: extract
.zip
files. - nano: text editor.

Step 4: Install and Configure PostgreSQL
apt install postgresql postgresql-contrib -y
- Installs PostgreSQL database and extra utilities.

Log in as PostgreSQL user:
su - postgres -c psql
Run the following SQL commands to create database and user:
CREATE DATABASE directusdb;
CREATE USER directususer WITH ENCRYPTED PASSWORD 'YourStrongPassword';
ALTER DATABASE directusdb OWNER TO directususer;
ALTER SCHEMA public OWNER TO directususer;
GRANT ALL PRIVILEGES ON SCHEMA public TO directususer;
\q
- Creates a new database
directusdb
. - Creates a user
directususer
with password. - Grants ownership and privileges so Directus can manage the database.
\q
exits PostgreSQL shell.

Step 5: Install Node.js 20 and NPM
curl -fsSL https://deb.nodesource.com/setup_20.x | bash -
- Adds the NodeSource repository for Node.js 20.

apt install nodejs -y
- Installs Node.js and npm.

node -v
npm -v
- Verify installed versions.

(Optional) Update npm to a specific version:
npm install -g npm@11.5.2

Step 6: Install Directus
Create a project folder:
mkdir -p /var/www/directus
cd /var/www/directus
Install Directus:
npm install directus
- Installs Directus locally in the project directory.

Initialize configuration:
npx directus init .

Edit environment file:
nano .env
Paste:
DB_CLIENT=pg
DB_HOST=127.0.0.1
DB_PORT=5432
DB_DATABASE=directusdb
DB_USER=directususer
DB_PASSWORD=YourStrongPassword
PORT=8055

Install PostgreSQL driver and fix dependencies:
npm install pg
npm audit fix


Step 7: Set Up Directus with PM2
Install PM2:
npm install -g pm2

Create PM2 config file:
nano ecosystem.config.js
Paste:
module.exports = {
apps: [
{
name: 'directus',
cwd: '/var/www/directus',
script: 'npx',
args: 'directus start',
env: {
NODE_ENV: 'production',
DB_CLIENT: 'pg',
DB_HOST: '127.0.0.1',
DB_PORT: '5432',
DB_DATABASE: 'directusdb',
DB_USER: 'directususer',
DB_PASSWORD: 'YourStrongPassword',
PORT: '8055'
}
}
]
};

Start Directus:
pm2 start ecosystem.config.js

Save and enable on boot:
pm2 save
pm2 startup


Step 8: Configure Nginx as Reverse Proxy
Create new site config:
nano /etc/nginx/sites-available/directus
Paste:
server {
listen 80;
server_name your_domain.com;
location / {
proxy_pass http://127.0.0.1:8055;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_cache_bypass $http_upgrade;
}
}

Enable the config and reload Nginx:
ln -s /etc/nginx/sites-available/directus /etc/nginx/sites-enabled/
nginx -t
systemctl reload nginx

Step 9: Secure Directus with SSL
Install Certbot:
apt install certbot python3-certbot-nginx -y

Run certificate request:
certbot --nginx -d ubuntu-tutorials.shape.host -m contact@shape.host --agree-tos
This automatically sets up HTTPS for your domain.

Directus is now installed and running on Ubuntu 24.04 with PostgreSQL, PM2, Nginx, and SSL.
Access it in your browser:
https://ubuntu-tutorials.shape.host


This tutorial was created and tested on a Shape.Host Cloud VPS.
With Shape.Host you can:
- Deploy fast Cloud VPS servers in multiple worldwide locations.
- Run popular Linux distributions like Ubuntu, Debian, AlmaLinux, and Rocky Linux.
- Scale resources instantly (CPU, RAM, Storage) as your project grows.
- Use built-in tools for snapshots, backups, and easy management.
Start your own instance today at https://shape.host and set up Directus, Strapi, or any other application in minutes.