Docker Compose Templates for Every Self-Hosted Tool
·OSSAlt Team
dockerdocker-composeself-hostingtemplatesguide
Docker Compose Templates for Every Self-Hosted Tool
Stop digging through documentation. Here's a copy-paste Docker Compose template for every popular self-hosted tool. Configure your .env, run docker compose up -d, done.
How to Use
- Copy the template for your tool
- Create a
.envfile with your settings - Run
docker compose up -d - Set up reverse proxy (Caddy recommended)
Reverse proxy template (used by all tools below):
# /etc/caddy/Caddyfile
app.yourdomain.com {
reverse_proxy localhost:PORT
}
Team Communication
Mattermost
services:
mattermost:
image: mattermost/mattermost-team-edition:latest
restart: unless-stopped
ports:
- "8065:8065"
volumes:
- mm_config:/mattermost/config
- mm_data:/mattermost/data
- mm_logs:/mattermost/logs
- mm_plugins:/mattermost/plugins
environment:
- MM_SQLSETTINGS_DRIVERNAME=postgres
- MM_SQLSETTINGS_DATASOURCE=postgres://${DB_USER}:${DB_PASS}@db:5432/${DB_NAME}?sslmode=disable
- MM_SERVICESETTINGS_SITEURL=https://${DOMAIN}
depends_on:
- db
db:
image: postgres:16-alpine
restart: unless-stopped
volumes:
- db_data:/var/lib/postgresql/data
environment:
- POSTGRES_DB=${DB_NAME}
- POSTGRES_USER=${DB_USER}
- POSTGRES_PASSWORD=${DB_PASS}
volumes:
mm_config:
mm_data:
mm_logs:
mm_plugins:
db_data:
Rocket.Chat
services:
rocketchat:
image: registry.rocket.chat/rocketchat/rocket.chat:latest
restart: unless-stopped
ports:
- "3000:3000"
environment:
- ROOT_URL=https://${DOMAIN}
- MONGO_URL=mongodb://mongo:27017/rocketchat
- MONGO_OPLOG_URL=mongodb://mongo:27017/local
depends_on:
- mongo
mongo:
image: mongo:6
restart: unless-stopped
volumes:
- mongo_data:/data/db
command: --oplogSize 128 --replSet rs0
volumes:
mongo_data:
Knowledge Base & Documentation
Outline
services:
outline:
image: outlinewiki/outline:latest
restart: unless-stopped
ports:
- "3000:3000"
env_file: .env
depends_on:
- db
- redis
db:
image: postgres:16-alpine
restart: unless-stopped
volumes:
- db_data:/var/lib/postgresql/data
environment:
- POSTGRES_DB=outline
- POSTGRES_USER=outline
- POSTGRES_PASSWORD=${DB_PASS}
redis:
image: redis:7-alpine
restart: unless-stopped
volumes:
- redis_data:/data
volumes:
db_data:
redis_data:
BookStack
services:
bookstack:
image: lscr.io/linuxserver/bookstack:latest
restart: unless-stopped
ports:
- "6875:80"
volumes:
- bookstack_data:/config
environment:
- APP_URL=https://${DOMAIN}
- DB_HOST=db
- DB_PORT=3306
- DB_USER=bookstack
- DB_PASS=${DB_PASS}
- DB_DATABASE=bookstack
depends_on:
- db
db:
image: mariadb:11
restart: unless-stopped
volumes:
- db_data:/var/lib/mysql
environment:
- MYSQL_ROOT_PASSWORD=${DB_ROOT_PASS}
- MYSQL_DATABASE=bookstack
- MYSQL_USER=bookstack
- MYSQL_PASSWORD=${DB_PASS}
volumes:
bookstack_data:
db_data:
Analytics
Plausible
services:
plausible:
image: ghcr.io/plausible/community-edition:latest
restart: unless-stopped
ports:
- "8000:8000"
env_file: .env
depends_on:
- db
- clickhouse
db:
image: postgres:16-alpine
restart: unless-stopped
volumes:
- db_data:/var/lib/postgresql/data
environment:
- POSTGRES_PASSWORD=${DB_PASS}
clickhouse:
image: clickhouse/clickhouse-server:latest
restart: unless-stopped
volumes:
- ch_data:/var/lib/clickhouse
volumes:
db_data:
ch_data:
Umami
services:
umami:
image: ghcr.io/umami-software/umami:postgresql-latest
restart: unless-stopped
ports:
- "3000:3000"
environment:
- DATABASE_URL=postgresql://umami:${DB_PASS}@db:5432/umami
depends_on:
- db
db:
image: postgres:16-alpine
restart: unless-stopped
volumes:
- db_data:/var/lib/postgresql/data
environment:
- POSTGRES_DB=umami
- POSTGRES_USER=umami
- POSTGRES_PASSWORD=${DB_PASS}
volumes:
db_data:
Monitoring
Uptime Kuma
services:
uptime-kuma:
image: louislam/uptime-kuma:latest
restart: unless-stopped
ports:
- "3001:3001"
volumes:
- kuma_data:/app/data
volumes:
kuma_data:
Grafana + Prometheus
services:
grafana:
image: grafana/grafana:latest
restart: unless-stopped
ports:
- "3000:3000"
volumes:
- grafana_data:/var/lib/grafana
environment:
- GF_SECURITY_ADMIN_PASSWORD=${ADMIN_PASS}
prometheus:
image: prom/prometheus:latest
restart: unless-stopped
ports:
- "9090:9090"
volumes:
- prom_data:/prometheus
- ./prometheus.yml:/etc/prometheus/prometheus.yml
node-exporter:
image: prom/node-exporter:latest
restart: unless-stopped
ports:
- "9100:9100"
volumes:
- /proc:/host/proc:ro
- /sys:/host/sys:ro
command:
- '--path.procfs=/host/proc'
- '--path.sysfs=/host/sys'
volumes:
grafana_data:
prom_data:
Automation
n8n
services:
n8n:
image: n8nio/n8n:latest
restart: unless-stopped
ports:
- "5678:5678"
volumes:
- n8n_data:/home/node/.n8n
environment:
- N8N_HOST=${DOMAIN}
- N8N_PROTOCOL=https
- WEBHOOK_URL=https://${DOMAIN}/
- N8N_ENCRYPTION_KEY=${ENCRYPTION_KEY}
- DB_TYPE=postgresdb
- DB_POSTGRESDB_HOST=db
- DB_POSTGRESDB_DATABASE=n8n
- DB_POSTGRESDB_USER=n8n
- DB_POSTGRESDB_PASSWORD=${DB_PASS}
depends_on:
- db
db:
image: postgres:16-alpine
restart: unless-stopped
volumes:
- db_data:/var/lib/postgresql/data
environment:
- POSTGRES_DB=n8n
- POSTGRES_USER=n8n
- POSTGRES_PASSWORD=${DB_PASS}
volumes:
n8n_data:
db_data:
Authentication
Keycloak
services:
keycloak:
image: quay.io/keycloak/keycloak:latest
restart: unless-stopped
ports:
- "8080:8080"
environment:
- KC_DB=postgres
- KC_DB_URL_HOST=db
- KC_DB_URL_DATABASE=keycloak
- KC_DB_USERNAME=keycloak
- KC_DB_PASSWORD=${DB_PASS}
- KC_HOSTNAME=${DOMAIN}
- KC_PROXY_HEADERS=xforwarded
- KC_HTTP_ENABLED=true
- KEYCLOAK_ADMIN=${ADMIN_USER}
- KEYCLOAK_ADMIN_PASSWORD=${ADMIN_PASS}
command: start
depends_on:
- db
db:
image: postgres:16-alpine
restart: unless-stopped
volumes:
- db_data:/var/lib/postgresql/data
environment:
- POSTGRES_DB=keycloak
- POSTGRES_USER=keycloak
- POSTGRES_PASSWORD=${DB_PASS}
volumes:
db_data:
Password Management
Vaultwarden
services:
vaultwarden:
image: vaultwarden/server:latest
restart: unless-stopped
ports:
- "8080:80"
volumes:
- vw_data:/data
environment:
- DOMAIN=https://${DOMAIN}
- SIGNUPS_ALLOWED=${SIGNUPS_ALLOWED:-false}
- ADMIN_TOKEN=${ADMIN_TOKEN}
- SMTP_HOST=${SMTP_HOST}
- SMTP_PORT=587
- SMTP_SECURITY=starttls
- SMTP_USERNAME=${SMTP_USER}
- SMTP_PASSWORD=${SMTP_PASS}
- SMTP_FROM=${SMTP_FROM}
volumes:
vw_data:
Customer Support
Chatwoot
services:
chatwoot:
image: chatwoot/chatwoot:latest
restart: unless-stopped
ports:
- "3000:3000"
env_file: .env
command: bundle exec rails s -p 3000 -b 0.0.0.0
depends_on:
- db
- redis
sidekiq:
image: chatwoot/chatwoot:latest
restart: unless-stopped
env_file: .env
command: bundle exec sidekiq -C config/sidekiq.yml
depends_on:
- db
- redis
db:
image: postgres:16-alpine
restart: unless-stopped
volumes:
- db_data:/var/lib/postgresql/data
environment:
- POSTGRES_DB=chatwoot
- POSTGRES_USER=chatwoot
- POSTGRES_PASSWORD=${DB_PASS}
redis:
image: redis:7-alpine
restart: unless-stopped
volumes:
- redis_data:/data
volumes:
db_data:
redis_data:
Listmonk
services:
listmonk:
image: listmonk/listmonk:latest
restart: unless-stopped
ports:
- "9000:9000"
volumes:
- ./config.toml:/listmonk/config.toml
depends_on:
- db
db:
image: postgres:16-alpine
restart: unless-stopped
volumes:
- db_data:/var/lib/postgresql/data
environment:
- POSTGRES_DB=listmonk
- POSTGRES_USER=listmonk
- POSTGRES_PASSWORD=${DB_PASS}
volumes:
db_data:
Git Hosting
Gitea
services:
gitea:
image: gitea/gitea:latest
restart: unless-stopped
ports:
- "3000:3000"
- "222:22"
volumes:
- gitea_data:/data
environment:
- GITEA__database__DB_TYPE=postgres
- GITEA__database__HOST=db:5432
- GITEA__database__NAME=gitea
- GITEA__database__USER=gitea
- GITEA__database__PASSWD=${DB_PASS}
depends_on:
- db
db:
image: postgres:16-alpine
restart: unless-stopped
volumes:
- db_data:/var/lib/postgresql/data
environment:
- POSTGRES_DB=gitea
- POSTGRES_USER=gitea
- POSTGRES_PASSWORD=${DB_PASS}
volumes:
gitea_data:
db_data:
Search
Meilisearch
services:
meilisearch:
image: getmeili/meilisearch:latest
restart: unless-stopped
ports:
- "7700:7700"
volumes:
- meili_data:/meili_data
environment:
- MEILI_MASTER_KEY=${MASTER_KEY}
- MEILI_ENV=production
volumes:
meili_data:
.env Template
Create a .env file for each service:
# Domain
DOMAIN=app.yourdomain.com
# Database
DB_NAME=myapp
DB_USER=myapp
DB_PASS=CHANGE_ME_GENERATED_PASSWORD
DB_ROOT_PASS=CHANGE_ME_ROOT_PASSWORD
# Admin
ADMIN_USER=admin
ADMIN_PASS=CHANGE_ME_ADMIN_PASSWORD
# SMTP
SMTP_HOST=smtp.resend.com
SMTP_USER=resend
SMTP_PASS=re_your_api_key
SMTP_FROM=app@yourdomain.com
# Secrets (generate with: openssl rand -hex 32)
SECRET_KEY=CHANGE_ME_64_CHAR_HEX
ENCRYPTION_KEY=CHANGE_ME_64_CHAR_HEX
ADMIN_TOKEN=CHANGE_ME_64_CHAR_HEX
MASTER_KEY=CHANGE_ME_64_CHAR_HEX
Generate all secrets at once:
echo "SECRET_KEY=$(openssl rand -hex 32)"
echo "ENCRYPTION_KEY=$(openssl rand -hex 32)"
echo "ADMIN_TOKEN=$(openssl rand -hex 32)"
echo "MASTER_KEY=$(openssl rand -hex 32)"
echo "DB_PASS=$(openssl rand -hex 16)"
echo "DB_ROOT_PASS=$(openssl rand -hex 16)"
echo "ADMIN_PASS=$(openssl rand -base64 24)"
Find the right self-hosted tool for your needs on OSSAlt — features, Docker support, and deployment guides side by side.