This guide uses Docker Compose to run Zammad with all required services (PostgreSQL, Elasticsearch, Redis, Memcached).
For Docker installation, see Docker.
Zammad provides official Docker images:
zammad/zammad-docker-compose (official)mkdir -p /opt/zammad
cd /opt/zammad
wget -O .env https://raw.githubusercontent.com/zammad/zammad-docker-compose/master/.env.dist
Edit the .env file with your settings:
nano .env
Required variables:
# Application
ZAMMAD_FQDN=zammad.example.com
ZAMMAD_HTTP_TYPE=https
TZ=Europe/Berlin
# Database
POSTGRES_HOST=zammad-postgresql
POSTGRES_PORT=5432
POSTGRES_USER=zammad
POSTGRES_PASS=change-me-now
POSTGRES_DB=zammad_production
POSTGRES_OPTIONS=?pool=50
# Redis
REDIS_URL=redis://zammad-redis:6379
# Memcached
MEMCACHE_SERVERS=zammad-memcached:11211
# Elasticsearch
ELASTICSEARCH_ENABLED=true
ELASTICSEARCH_HOST=zammad-elasticsearch
ELASTICSEARCH_PORT=9200
ELASTICSEARCH_SCHEMA=http
ELASTICSEARCH_NAMESPACE=zammad
ELASTICSEARCH_JAVA_OPTS=-Xms1g -Xmx1g
# Nginx
NGINX_PORT=8080
NGINX_EXPOSE_PORT=8080
NGINX_CLIENT_MAX_BODY_SIZE=50M
# Trusted Proxies
RAILS_TRUSTED_PROXIES=127.0.0.1,::1
Note on Docker Tags: Zammad provides several Docker tags:
latest - Latest stable release (recommended for most deployments)v7.x.x - Specific version (recommended for production stability)sha-<commit> - Development buildsFor production, use a specific version tag like v7.0.
cat <<'YAML' > docker-compose.yml
services:
zammad-init:
image: zammad/zammad-docker-compose:latest
environment:
MEMCACHE_SERVERS: zammad-memcached:11211
POSTGRESQL_DB: zammad_production
POSTGRESQL_HOST: zammad-postgresql
POSTGRESQL_USER: zammad
POSTGRESQL_PASS: change-me-now
POSTGRESQL_PORT: "5432"
REDIS_URL: redis://zammad-redis:6379
TZ: Europe/Berlin
command: ["zammad-init"]
depends_on:
- zammad-postgresql
restart: on-failure
user: "0:0"
networks:
- zammad_network
zammad-railsserver:
image: zammad/zammad-docker-compose:latest
environment:
MEMCACHE_SERVERS: zammad-memcached:11211
POSTGRESQL_DB: zammad_production
POSTGRESQL_HOST: zammad-postgresql
POSTGRESQL_USER: zammad
POSTGRESQL_PASS: change-me-now
POSTGRESQL_PORT: "5432"
REDIS_URL: redis://zammad-redis:6379
TZ: Europe/Berlin
depends_on:
- zammad-init
- zammad-memcached
- zammad-postgresql
- zammad-redis
restart: unless-stopped
networks:
- zammad_network
volumes:
- zammad-storage:/opt/zammad/storage
zammad-websocket:
image: zammad/zammad-docker-compose:latest
environment:
MEMCACHE_SERVERS: zammad-memcached:11211
POSTGRESQL_DB: zammad_production
POSTGRESQL_HOST: zammad-postgresql
POSTGRESQL_USER: zammad
POSTGRESQL_PASS: change-me-now
POSTGRESQL_PORT: "5432"
REDIS_URL: redis://zammad-redis:6379
TZ: Europe/Berlin
command: ["zammad-websocket"]
depends_on:
- zammad-init
- zammad-memcached
- zammad-postgresql
- zammad-redis
restart: unless-stopped
networks:
- zammad_network
volumes:
- zammad-storage:/opt/zammad/storage
zammad-scheduler:
image: zammad/zammad-docker-compose:latest
environment:
MEMCACHE_SERVERS: zammad-memcached:11211
POSTGRESQL_DB: zammad_production
POSTGRESQL_HOST: zammad-postgresql
POSTGRESQL_USER: zammad
POSTGRESQL_PASS: change-me-now
POSTGRESQL_PORT: "5432"
REDIS_URL: redis://zammad-redis:6379
TZ: Europe/Berlin
command: ["zammad-scheduler"]
depends_on:
- zammad-init
- zammad-memcached
- zammad-postgresql
- zammad-redis
restart: unless-stopped
networks:
- zammad_network
volumes:
- zammad-storage:/opt/zammad/storage
zammad-nginx:
image: zammad/zammad-docker-compose:latest
command: ["zammad-nginx"]
expose:
- "8080"
ports:
- "127.0.0.1:8080:8080"
depends_on:
- zammad-railsserver
environment:
ZAMMAD_FQDN: zammad.example.com
ZAMMAD_HTTP_TYPE: https
restart: unless-stopped
networks:
- zammad_network
zammad-elasticsearch:
image: elasticsearch:9.3.1
environment:
discovery.type: single-node
xpack.security.enabled: "false"
ES_JAVA_OPTS: "-Xms1g -Xmx1g"
volumes:
- elasticsearch-data:/usr/share/elasticsearch/data
restart: unless-stopped
networks:
- zammad_network
zammad-postgresql:
image: postgres:17.9-alpine
environment:
POSTGRES_DB: zammad_production
POSTGRES_USER: zammad
POSTGRES_PASSWORD: change-me-now
volumes:
- postgresql-data:/var/lib/postgresql/data
restart: unless-stopped
networks:
- zammad_network
zammad-redis:
image: redis:8.6.1-alpine
volumes:
- redis-data:/data
restart: unless-stopped
networks:
- zammad_network
zammad-memcached:
image: memcached:1.6.41-alpine
command: memcached -m 256M
restart: unless-stopped
networks:
- zammad_network
volumes:
elasticsearch-data:
driver: local
postgresql-data:
driver: local
redis-data:
driver: local
zammad-storage:
driver: local
networks:
zammad_network:
driver: bridge
YAML
Initialize the Zammad database:
docker compose up -d zammad-init
Wait for initialization to complete (check logs):
docker compose logs -f zammad-init
Start all Zammad services:
docker compose up -d
# Check all services are running
docker compose ps
# Test API endpoint
curl -I http://127.0.0.1:8080/api
For production access, set up Nginx with Let’s Encrypt:
# Install Nginx
apt install nginx certbot python3-certbot-nginx
# Create Nginx config
cat <<'NGINX' > /etc/nginx/sites-available/zammad.example.com
server {
server_name zammad.example.com;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
NGINX
# Enable site
ln -s /etc/nginx/sites-available/zammad.example.com /etc/nginx/sites-enabled/
nginx -t && systemctl reload nginx
# Get SSL certificate
certbot --nginx -d zammad.example.com
cd /opt/zammad
docker compose pull
docker compose up -d zammad-init
docker compose up -d
Use the built-in backup container:
# Create backup
docker compose run --rm zammad-backup zammad-backup create
# List backups
docker compose run --rm zammad-backup zammad-backup list
Running containers in production? We help with:
Need help? office@linux-server-admin.com or Contact Us