This guide deploys Zammad with Docker Compose including all required services (PostgreSQL, Elasticsearch, Redis, Memcached).
It supports Debian 10 to latest stable, Ubuntu LTS, and RHEL 9+ compatible hosts.
- name: Deploy Zammad with Docker
hosts: zammad
become: true
vars:
app_root: /opt/zammad
app_port: 8080
zammad_fqdn: zammad.example.com
postgres_pass: "change-me-now"
elasticsearch_heap: "1g"
timezone: "Europe/Berlin"
tasks:
- name: Install Docker on Debian/Ubuntu
apt:
name:
- docker.io
- docker-compose-plugin
state: present
update_cache: true
when: ansible_os_family == "Debian"
- name: Install Docker on RHEL family
dnf:
name:
- docker
- docker-compose-plugin
state: present
when: ansible_os_family == "RedHat"
- name: Enable and start Docker
service:
name: docker
state: started
enabled: true
- name: Create app directory
file:
path: "{{ app_root }}"
state: directory
mode: "0755"
- name: Write Zammad .env file
copy:
dest: "{{ app_root }}/.env"
mode: "0600"
content: |
# Application
ZAMMAD_FQDN={{ zammad_fqdn }}
ZAMMAD_HTTP_TYPE=https
TZ={{ timezone }}
# Database
POSTGRES_HOST=zammad-postgresql
POSTGRES_PORT=5432
POSTGRES_USER=zammad
POSTGRES_PASS={{ postgres_pass }}
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=-Xms{{ elasticsearch_heap }} -Xmx{{ elasticsearch_heap }}
# Nginx
NGINX_PORT=8080
NGINX_EXPOSE_PORT={{ app_port }}
NGINX_CLIENT_MAX_BODY_SIZE=50M
# Trusted Proxies
RAILS_TRUSTED_PROXIES=127.0.0.1,::1
- name: Write Docker Compose file
copy:
dest: "{{ app_root }}/docker-compose.yml"
mode: "0644"
content: |
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: {{ postgres_pass }}
POSTGRESQL_PORT: "5432"
REDIS_URL: redis://zammad-redis:6379
TZ: {{ timezone }}
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: {{ postgres_pass }}
POSTGRESQL_PORT: "5432"
REDIS_URL: redis://zammad-redis:6379
TZ: {{ timezone }}
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: {{ postgres_pass }}
POSTGRESQL_PORT: "5432"
REDIS_URL: redis://zammad-redis:6379
TZ: {{ timezone }}
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: {{ postgres_pass }}
POSTGRESQL_PORT: "5432"
REDIS_URL: redis://zammad-redis:6379
TZ: {{ timezone }}
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:
- "{{ app_port }}"
ports:
- "127.0.0.1:{{ app_port }}:8080"
depends_on:
- zammad-railsserver
environment:
ZAMMAD_FQDN: {{ zammad_fqdn }}
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: "-Xms{{ elasticsearch_heap }} -Xmx{{ elasticsearch_heap }}"
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: {{ postgres_pass }}
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
- name: Initialize Zammad database
command: docker compose up -d zammad-init
args:
chdir: "{{ app_root }}"
run_once: true
- name: Wait for initialization
wait_for:
timeout: 30
delegate_to: localhost
- name: Start Zammad stack
command: docker compose up -d
args:
chdir: "{{ app_root }}"
ELASTICSEARCH_JAVA_OPTS)./opt/zammad/storage volume.zammad-backup container for database and storage backups.https://zammad.example.comAny questions?
Feel free to contact us. Find all contact information on our contact page.