Directus Headless CMS Stack
Open-source headless CMS with PostgreSQL, Redis caching, S3 storage, and full-text search.
Overview
Directus is an open-source headless CMS that transforms any SQL database into a powerful API and elegant admin interface. Founded in 2004 and rebuilt from the ground up in 2018, Directus follows an API-first approach that wraps your database with RESTful and GraphQL endpoints while maintaining complete data portability. Unlike traditional CMSes that lock you into proprietary formats, Directus works directly with your existing database schema. This stack combines Directus with PostgreSQL for robust relational data storage, Redis for high-performance caching and session management, MinIO for S3-compatible object storage, and Meilisearch for lightning-fast search capabilities. Together, these components create a production-ready content management platform that can handle everything from simple blogs to complex enterprise applications with media-rich content and advanced search requirements. This configuration is ideal for developers building modern web applications, mobile apps, or IoT platforms that need flexible content management without the constraints of traditional monolithic CMSes, offering the scalability of microservices with the convenience of integrated tooling.
Key Features
- Dynamic API generation with RESTful and GraphQL endpoints auto-created from PostgreSQL schema
- PostgreSQL JSONB support for flexible schema evolution alongside relational data structures
- Redis-powered session management and query result caching for sub-100ms response times
- MinIO S3-compatible storage with automatic image transformations and CDN-style asset delivery
- Meilisearch integration for typo-tolerant full-text search with instant results under 50ms
- Role-based access control with granular field-level permissions and API key management
- Real-time collaboration with WebSocket connections for live content editing
- Database introspection that automatically generates admin interfaces from existing schemas
Common Use Cases
- 1E-commerce platforms requiring product catalogs with search, media management, and inventory tracking
- 2Multi-tenant SaaS applications needing per-client content management and API endpoints
- 3Mobile app backends with user-generated content, file uploads, and push notification management
- 4Documentation websites with search functionality and collaborative editing workflows
- 5Digital asset management systems for marketing teams with approval workflows and media transformations
- 6IoT dashboards collecting sensor data with real-time visualization and historical analysis
- 7Multi-language websites requiring translation management and localized content delivery
Prerequisites
- Minimum 4GB RAM (2GB for PostgreSQL + Directus, 512MB each for Redis/MinIO/Meilisearch)
- Docker Engine 20.10+ with Docker Compose V2 for proper health check and dependency support
- Available ports 8055 (Directus), 9000-9001 (MinIO), and 7700 (Meilisearch) on your host system
- Basic understanding of PostgreSQL schema design and SQL queries for data modeling
- Familiarity with REST/GraphQL APIs and JSON data structures for frontend integration
- SSL certificate and reverse proxy knowledge for production HTTPS deployment
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 directus: 3 image: directus/directus:latest4 ports: 5 - "8055:8055"6 environment: 7 KEY: ${DIRECTUS_KEY}8 SECRET: ${DIRECTUS_SECRET}9 DB_CLIENT: pg10 DB_HOST: postgres11 DB_PORT: 543212 DB_DATABASE: ${POSTGRES_DB}13 DB_USER: ${POSTGRES_USER}14 DB_PASSWORD: ${POSTGRES_PASSWORD}15 CACHE_ENABLED: "true"16 CACHE_STORE: redis17 REDIS_HOST: redis18 REDIS_PORT: 637919 STORAGE_LOCATIONS: s320 STORAGE_S3_DRIVER: s321 STORAGE_S3_KEY: ${MINIO_ACCESS_KEY}22 STORAGE_S3_SECRET: ${MINIO_SECRET_KEY}23 STORAGE_S3_BUCKET: directus24 STORAGE_S3_ENDPOINT: http://minio:900025 STORAGE_S3_FORCE_PATH_STYLE: "true"26 ADMIN_EMAIL: ${ADMIN_EMAIL}27 ADMIN_PASSWORD: ${ADMIN_PASSWORD}28 volumes: 29 - directus_uploads:/directus/uploads30 - directus_extensions:/directus/extensions31 depends_on: 32 postgres: 33 condition: service_healthy34 redis: 35 condition: service_started36 minio: 37 condition: service_started38 networks: 39 - directus-net40 restart: unless-stopped4142 postgres: 43 image: postgres:16-alpine44 environment: 45 POSTGRES_USER: ${POSTGRES_USER}46 POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}47 POSTGRES_DB: ${POSTGRES_DB}48 volumes: 49 - postgres_data:/var/lib/postgresql/data50 healthcheck: 51 test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]52 interval: 10s53 timeout: 5s54 retries: 555 networks: 56 - directus-net57 restart: unless-stopped5859 redis: 60 image: redis:7-alpine61 volumes: 62 - redis_data:/data63 networks: 64 - directus-net65 restart: unless-stopped6667 minio: 68 image: minio/minio:latest69 ports: 70 - "9000:9000"71 - "9001:9001"72 environment: 73 MINIO_ROOT_USER: ${MINIO_ACCESS_KEY}74 MINIO_ROOT_PASSWORD: ${MINIO_SECRET_KEY}75 volumes: 76 - minio_data:/data77 command: server /data --console-address ":9001"78 networks: 79 - directus-net80 restart: unless-stopped8182 meilisearch: 83 image: getmeili/meilisearch:latest84 ports: 85 - "7700:7700"86 environment: 87 MEILI_MASTER_KEY: ${MEILI_MASTER_KEY}88 volumes: 89 - meili_data:/meili_data90 networks: 91 - directus-net92 restart: unless-stopped9394volumes: 95 directus_uploads: 96 directus_extensions: 97 postgres_data: 98 redis_data: 99 minio_data: 100 meili_data: 101102networks: 103 directus-net: 104 driver: bridge.env Template
.env
1# Directus Configuration2DIRECTUS_KEY=random-key-here3DIRECTUS_SECRET=random-secret-here4ADMIN_EMAIL=admin@example.com5ADMIN_PASSWORD=secure_admin_password67# PostgreSQL8POSTGRES_USER=directus9POSTGRES_PASSWORD=secure_postgres_password10POSTGRES_DB=directus1112# MinIO13MINIO_ACCESS_KEY=minioadmin14MINIO_SECRET_KEY=secure_minio_password1516# Meilisearch17MEILI_MASTER_KEY=secure_meili_master_keyUsage Notes
- 1Directus Admin at http://localhost:8055
- 2MinIO Console at http://localhost:9001
- 3Meilisearch at http://localhost:7700
- 4Configure Meilisearch extension in Directus for search
Individual Services(5 services)
Copy individual services to mix and match with your existing compose files.
directus
directus:
image: directus/directus:latest
ports:
- "8055:8055"
environment:
KEY: ${DIRECTUS_KEY}
SECRET: ${DIRECTUS_SECRET}
DB_CLIENT: pg
DB_HOST: postgres
DB_PORT: 5432
DB_DATABASE: ${POSTGRES_DB}
DB_USER: ${POSTGRES_USER}
DB_PASSWORD: ${POSTGRES_PASSWORD}
CACHE_ENABLED: "true"
CACHE_STORE: redis
REDIS_HOST: redis
REDIS_PORT: 6379
STORAGE_LOCATIONS: s3
STORAGE_S3_DRIVER: s3
STORAGE_S3_KEY: ${MINIO_ACCESS_KEY}
STORAGE_S3_SECRET: ${MINIO_SECRET_KEY}
STORAGE_S3_BUCKET: directus
STORAGE_S3_ENDPOINT: http://minio:9000
STORAGE_S3_FORCE_PATH_STYLE: "true"
ADMIN_EMAIL: ${ADMIN_EMAIL}
ADMIN_PASSWORD: ${ADMIN_PASSWORD}
volumes:
- directus_uploads:/directus/uploads
- directus_extensions:/directus/extensions
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_started
minio:
condition: service_started
networks:
- directus-net
restart: unless-stopped
postgres
postgres:
image: postgres:16-alpine
environment:
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB}
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test:
- CMD-SHELL
- pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}
interval: 10s
timeout: 5s
retries: 5
networks:
- directus-net
restart: unless-stopped
redis
redis:
image: redis:7-alpine
volumes:
- redis_data:/data
networks:
- directus-net
restart: unless-stopped
minio
minio:
image: minio/minio:latest
ports:
- "9000:9000"
- "9001:9001"
environment:
MINIO_ROOT_USER: ${MINIO_ACCESS_KEY}
MINIO_ROOT_PASSWORD: ${MINIO_SECRET_KEY}
volumes:
- minio_data:/data
command: server /data --console-address ":9001"
networks:
- directus-net
restart: unless-stopped
meilisearch
meilisearch:
image: getmeili/meilisearch:latest
ports:
- "7700:7700"
environment:
MEILI_MASTER_KEY: ${MEILI_MASTER_KEY}
volumes:
- meili_data:/meili_data
networks:
- directus-net
restart: unless-stopped
Quick Start
terminal
1# 1. Create the compose file2cat > docker-compose.yml << 'EOF'3services:4 directus:5 image: directus/directus:latest6 ports:7 - "8055:8055"8 environment:9 KEY: ${DIRECTUS_KEY}10 SECRET: ${DIRECTUS_SECRET}11 DB_CLIENT: pg12 DB_HOST: postgres13 DB_PORT: 543214 DB_DATABASE: ${POSTGRES_DB}15 DB_USER: ${POSTGRES_USER}16 DB_PASSWORD: ${POSTGRES_PASSWORD}17 CACHE_ENABLED: "true"18 CACHE_STORE: redis19 REDIS_HOST: redis20 REDIS_PORT: 637921 STORAGE_LOCATIONS: s322 STORAGE_S3_DRIVER: s323 STORAGE_S3_KEY: ${MINIO_ACCESS_KEY}24 STORAGE_S3_SECRET: ${MINIO_SECRET_KEY}25 STORAGE_S3_BUCKET: directus26 STORAGE_S3_ENDPOINT: http://minio:900027 STORAGE_S3_FORCE_PATH_STYLE: "true"28 ADMIN_EMAIL: ${ADMIN_EMAIL}29 ADMIN_PASSWORD: ${ADMIN_PASSWORD}30 volumes:31 - directus_uploads:/directus/uploads32 - directus_extensions:/directus/extensions33 depends_on:34 postgres:35 condition: service_healthy36 redis:37 condition: service_started38 minio:39 condition: service_started40 networks:41 - directus-net42 restart: unless-stopped4344 postgres:45 image: postgres:16-alpine46 environment:47 POSTGRES_USER: ${POSTGRES_USER}48 POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}49 POSTGRES_DB: ${POSTGRES_DB}50 volumes:51 - postgres_data:/var/lib/postgresql/data52 healthcheck:53 test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]54 interval: 10s55 timeout: 5s56 retries: 557 networks:58 - directus-net59 restart: unless-stopped6061 redis:62 image: redis:7-alpine63 volumes:64 - redis_data:/data65 networks:66 - directus-net67 restart: unless-stopped6869 minio:70 image: minio/minio:latest71 ports:72 - "9000:9000"73 - "9001:9001"74 environment:75 MINIO_ROOT_USER: ${MINIO_ACCESS_KEY}76 MINIO_ROOT_PASSWORD: ${MINIO_SECRET_KEY}77 volumes:78 - minio_data:/data79 command: server /data --console-address ":9001"80 networks:81 - directus-net82 restart: unless-stopped8384 meilisearch:85 image: getmeili/meilisearch:latest86 ports:87 - "7700:7700"88 environment:89 MEILI_MASTER_KEY: ${MEILI_MASTER_KEY}90 volumes:91 - meili_data:/meili_data92 networks:93 - directus-net94 restart: unless-stopped9596volumes:97 directus_uploads:98 directus_extensions:99 postgres_data:100 redis_data:101 minio_data:102 meili_data:103104networks:105 directus-net:106 driver: bridge107EOF108109# 2. Create the .env file110cat > .env << 'EOF'111# Directus Configuration112DIRECTUS_KEY=random-key-here113DIRECTUS_SECRET=random-secret-here114ADMIN_EMAIL=admin@example.com115ADMIN_PASSWORD=secure_admin_password116117# PostgreSQL118POSTGRES_USER=directus119POSTGRES_PASSWORD=secure_postgres_password120POSTGRES_DB=directus121122# MinIO123MINIO_ACCESS_KEY=minioadmin124MINIO_SECRET_KEY=secure_minio_password125126# Meilisearch127MEILI_MASTER_KEY=secure_meili_master_key128EOF129130# 3. Start the services131docker compose up -d132133# 4. View logs134docker 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-advanced/run | bashTroubleshooting
- Directus fails to start with 'Database connection failed': Ensure PostgreSQL health check passes before Directus startup using depends_on conditions
- File uploads return 500 errors: Verify MinIO bucket 'directus' exists and STORAGE_S3_FORCE_PATH_STYLE is set to true for local MinIO
- Search queries return empty results: Install and configure Directus Meilisearch extension, then sync your collections to create search indexes
- Redis connection timeouts during high load: Increase Redis memory limit and enable AOF persistence to prevent data loss during restarts
- PostgreSQL crashes with 'out of memory': Tune shared_buffers and effective_cache_size in postgresql.conf based on available system RAM
- MinIO console shows 'InvalidAccessKeyId': Ensure MINIO_ROOT_USER matches STORAGE_S3_KEY and both are at least 3 characters long
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
Components
directuspostgresqlredisminiomeilisearch
Tags
#directus#headless-cms#api-first#postgresql#meilisearch
Category
CMS & BloggingAd Space
Shortcuts: C CopyF FavoriteD Download