Directus Headless CMS
Directus data platform with PostgreSQL and Redis.
Overview
Directus is a modern, open-source headless CMS and data platform that automatically generates REST and GraphQL APIs from your database schema. Founded in 2004 and completely rebuilt in 2019, Directus acts as a wrapper around SQL databases, providing a powerful admin interface, user management, and API layer without vendor lock-in. Unlike traditional CMSs that force content into predefined structures, Directus works with your existing database or creates new schemas dynamically, making it ideal for developers who need database flexibility with content management convenience.
This stack combines Directus with PostgreSQL as the primary database and Redis for caching and session management. PostgreSQL provides ACID compliance, complex querying capabilities, and JSON support that complements Directus's flexible content modeling, while Redis accelerates response times by caching frequently accessed data and managing user sessions. The combination delivers enterprise-grade performance with the ability to handle both structured relational data and flexible document-style content through PostgreSQL's JSONB support.
This configuration is perfect for development teams building headless applications, agencies managing multiple client projects, and organizations migrating from legacy CMSs while maintaining database control. The stack scales from prototype to production, supporting complex content relationships, multi-user collaboration, and API-first architectures that power modern web applications, mobile apps, and IoT dashboards.
Key Features
- Auto-generated REST and GraphQL APIs from PostgreSQL schema changes with real-time updates
- Advanced content modeling with PostgreSQL's JSONB support for flexible field types and nested data structures
- Redis-powered caching system that dramatically improves API response times and reduces database load
- Role-based permissions with granular field-level access control tied to PostgreSQL user management
- Real-time collaboration features using Redis pub/sub for live content editing and user presence indicators
- PostgreSQL full-text search integration with ranking and highlighting for advanced content discovery
- File asset management with automatic image transformations and PostgreSQL metadata indexing
- Webhook system for triggering external integrations when content changes in PostgreSQL tables
Common Use Cases
- 1Headless e-commerce platforms requiring complex product catalogs with PostgreSQL's advanced querying for inventory management
- 2Multi-tenant SaaS applications where each client needs isolated content management with shared infrastructure
- 3News and publishing platforms leveraging PostgreSQL's full-text search and Redis caching for high-traffic article delivery
- 4Mobile app backends requiring real-time content updates through Directus APIs with Redis session management
- 5Digital asset management systems for marketing teams with PostgreSQL's robust file metadata indexing
- 6IoT data dashboards where Directus provides user-friendly interfaces for PostgreSQL time-series data visualization
- 7Agency portfolio sites managing multiple client projects with Directus's flexible content modeling and user permissions
Prerequisites
- Docker Engine 20.10+ and Docker Compose V2 for container orchestration support
- Minimum 2GB RAM (PostgreSQL needs 1GB+, Redis 512MB+, Directus 512MB+) for stable operation
- Port 8055 available for Directus admin interface and API endpoints
- Basic understanding of PostgreSQL schema design for effective content modeling in Directus
- Generated secure random values for KEY and SECRET environment variables (minimum 32 characters each)
- Valid email configuration if using Directus email features for user invitations and password resets
For development & testing. Review security settings, change default credentials, and test thoroughly before production use. See Terms
docker-compose.yml
docker-compose.yml
1services: 2 postgres: 3 image: postgres:16-alpine4 container_name: directus-postgres5 restart: unless-stopped6 environment: 7 POSTGRES_USER: ${POSTGRES_USER:-directus}8 POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-directus}9 POSTGRES_DB: ${POSTGRES_DB:-directus}10 volumes: 11 - postgres_data:/var/lib/postgresql/data12 networks: 13 - directus-network1415 redis: 16 image: redis:alpine17 container_name: directus-redis18 restart: unless-stopped19 volumes: 20 - redis_data:/data21 networks: 22 - directus-network2324 directus: 25 image: directus/directus:latest26 container_name: directus27 restart: unless-stopped28 ports: 29 - "${DIRECTUS_PORT:-8055}:8055"30 environment: 31 KEY: ${KEY:-replace-with-random-value}32 SECRET: ${SECRET:-replace-with-random-value}33 DB_CLIENT: pg34 DB_HOST: postgres35 DB_PORT: 543236 DB_DATABASE: ${POSTGRES_DB:-directus}37 DB_USER: ${POSTGRES_USER:-directus}38 DB_PASSWORD: ${POSTGRES_PASSWORD:-directus}39 CACHE_ENABLED: "true"40 CACHE_STORE: redis41 REDIS: redis://redis:637942 ADMIN_EMAIL: ${ADMIN_EMAIL:-admin@example.com}43 ADMIN_PASSWORD: ${ADMIN_PASSWORD:-admin123}44 volumes: 45 - directus_uploads:/directus/uploads46 depends_on: 47 - postgres48 - redis49 networks: 50 - directus-network5152volumes: 53 postgres_data: 54 redis_data: 55 directus_uploads: 5657networks: 58 directus-network: 59 driver: bridge.env Template
.env
1# Directus2DIRECTUS_PORT=80553KEY=your-random-key-here4SECRET=your-random-secret-here5POSTGRES_USER=directus6POSTGRES_PASSWORD=directus7POSTGRES_DB=directus8ADMIN_EMAIL=admin@example.com9ADMIN_PASSWORD=admin123Usage Notes
- 1Directus at http://localhost:8055
- 2Login with admin credentials
- 3Generate random KEY and SECRET
- 4Access API at /items/{collection}
Individual Services(3 services)
Copy individual services to mix and match with your existing compose files.
postgres
postgres:
image: postgres:16-alpine
container_name: directus-postgres
restart: unless-stopped
environment:
POSTGRES_USER: ${POSTGRES_USER:-directus}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-directus}
POSTGRES_DB: ${POSTGRES_DB:-directus}
volumes:
- postgres_data:/var/lib/postgresql/data
networks:
- directus-network
redis
redis:
image: redis:alpine
container_name: directus-redis
restart: unless-stopped
volumes:
- redis_data:/data
networks:
- directus-network
directus
directus:
image: directus/directus:latest
container_name: directus
restart: unless-stopped
ports:
- ${DIRECTUS_PORT:-8055}:8055
environment:
KEY: ${KEY:-replace-with-random-value}
SECRET: ${SECRET:-replace-with-random-value}
DB_CLIENT: pg
DB_HOST: postgres
DB_PORT: 5432
DB_DATABASE: ${POSTGRES_DB:-directus}
DB_USER: ${POSTGRES_USER:-directus}
DB_PASSWORD: ${POSTGRES_PASSWORD:-directus}
CACHE_ENABLED: "true"
CACHE_STORE: redis
REDIS: redis://redis:6379
ADMIN_EMAIL: ${ADMIN_EMAIL:-admin@example.com}
ADMIN_PASSWORD: ${ADMIN_PASSWORD:-admin123}
volumes:
- directus_uploads:/directus/uploads
depends_on:
- postgres
- redis
networks:
- directus-network
Quick Start
terminal
1# 1. Create the compose file2cat > docker-compose.yml << 'EOF'3services:4 postgres:5 image: postgres:16-alpine6 container_name: directus-postgres7 restart: unless-stopped8 environment:9 POSTGRES_USER: ${POSTGRES_USER:-directus}10 POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-directus}11 POSTGRES_DB: ${POSTGRES_DB:-directus}12 volumes:13 - postgres_data:/var/lib/postgresql/data14 networks:15 - directus-network1617 redis:18 image: redis:alpine19 container_name: directus-redis20 restart: unless-stopped21 volumes:22 - redis_data:/data23 networks:24 - directus-network2526 directus:27 image: directus/directus:latest28 container_name: directus29 restart: unless-stopped30 ports:31 - "${DIRECTUS_PORT:-8055}:8055"32 environment:33 KEY: ${KEY:-replace-with-random-value}34 SECRET: ${SECRET:-replace-with-random-value}35 DB_CLIENT: pg36 DB_HOST: postgres37 DB_PORT: 543238 DB_DATABASE: ${POSTGRES_DB:-directus}39 DB_USER: ${POSTGRES_USER:-directus}40 DB_PASSWORD: ${POSTGRES_PASSWORD:-directus}41 CACHE_ENABLED: "true"42 CACHE_STORE: redis43 REDIS: redis://redis:637944 ADMIN_EMAIL: ${ADMIN_EMAIL:-admin@example.com}45 ADMIN_PASSWORD: ${ADMIN_PASSWORD:-admin123}46 volumes:47 - directus_uploads:/directus/uploads48 depends_on:49 - postgres50 - redis51 networks:52 - directus-network5354volumes:55 postgres_data:56 redis_data:57 directus_uploads:5859networks:60 directus-network:61 driver: bridge62EOF6364# 2. Create the .env file65cat > .env << 'EOF'66# Directus67DIRECTUS_PORT=805568KEY=your-random-key-here69SECRET=your-random-secret-here70POSTGRES_USER=directus71POSTGRES_PASSWORD=directus72POSTGRES_DB=directus73ADMIN_EMAIL=admin@example.com74ADMIN_PASSWORD=admin12375EOF7677# 3. Start the services78docker compose up -d7980# 4. View logs81docker compose logs -fOne-Liner
Run this command to download and set up the recipe in one step:
terminal
1curl -fsSL https://docker.recipes/api/recipes/directus-cms/run | bashTroubleshooting
- Directus shows 'Database connection failed': Check PostgreSQL container logs and verify POSTGRES_PASSWORD matches DB_PASSWORD in environment variables
- API responses are slow despite Redis setup: Verify CACHE_ENABLED is 'true' and check Redis container connectivity with docker exec directus-redis redis-cli ping
- Admin login fails with 'Invalid credentials': Reset admin password by setting new ADMIN_PASSWORD and restarting Directus container to recreate admin user
- File uploads return 500 errors: Ensure directus_uploads volume has proper write permissions and check available disk space on Docker host
- PostgreSQL container fails to start with 'data directory not empty': Remove postgres_data volume or check for conflicting PostgreSQL instances on port 5432
- Directus shows 'Invalid key/secret' errors: Generate cryptographically secure random strings for KEY and SECRET environment variables using openssl rand -hex 32
Community Notes
Loading...
Loading notes...
Download Recipe Kit
Get all files in a ready-to-deploy package
Includes docker-compose.yml, .env template, README, and license
Ad Space
Shortcuts: C CopyF FavoriteD Download