50 Self-Hosted Services You Can Deploy with Docker Compose in Minutes
Self-hosting has never been easier. Docker Compose reduces deploying complex applications to a single YAML file and a docker compose up -d command. Whether you are building a homelab, replacing SaaS subscriptions, or setting up internal tools for your team, there is likely a Docker image for what you need.
This guide organizes 50 self-hosted services into categories, each with a minimal Compose snippet you can use immediately. Every snippet includes volumes for data persistence and reasonable default configurations. Adapt ports, passwords, and domain names to your environment.
Productivity and Office
1. Nextcloud - Cloud Storage and Collaboration
services:
nextcloud:
image: nextcloud:29
ports:
- "8080:80"
volumes:
- nextcloud_data:/var/www/html
environment:
POSTGRES_HOST: nextcloud-db
POSTGRES_DB: nextcloud
POSTGRES_USER: nextcloud
POSTGRES_PASSWORD: ${NC_DB_PASSWORD}
depends_on:
- nextcloud-db
nextcloud-db:
image: postgres:16-alpine
volumes:
- nextcloud_pgdata:/var/lib/postgresql/data
environment:
POSTGRES_DB: nextcloud
POSTGRES_USER: nextcloud
POSTGRES_PASSWORD: ${NC_DB_PASSWORD}
volumes:
nextcloud_data:
nextcloud_pgdata:
2. BookStack - Documentation Wiki
services:
bookstack:
image: lscr.io/linuxserver/bookstack
ports:
- "6875:80"
volumes:
- bookstack_data:/config
environment:
APP_URL: https://docs.example.com
DB_HOST: bookstack-db
DB_DATABASE: bookstack
DB_USERNAME: bookstack
DB_PASSWORD: ${BS_DB_PASSWORD}
bookstack-db:
image: mariadb:11
volumes:
- bookstack_dbdata:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: ${BS_ROOT_PASSWORD}
MYSQL_DATABASE: bookstack
MYSQL_USER: bookstack
MYSQL_PASSWORD: ${BS_DB_PASSWORD}
volumes:
bookstack_data:
bookstack_dbdata:
3. Vikunja - Task Management (Todoist alternative)
services:
vikunja:
image: vikunja/vikunja
ports:
- "3456:3456"
volumes:
- vikunja_data:/app/vikunja/files
environment:
VIKUNJA_DATABASE_TYPE: sqlite
volumes:
vikunja_data:
4. Paperless-ngx - Document Management
services:
paperless:
image: ghcr.io/paperless-ngx/paperless-ngx:latest
ports:
- "8000:8000"
volumes:
- paperless_data:/usr/src/paperless/data
- paperless_media:/usr/src/paperless/media
- ./consume:/usr/src/paperless/consume
environment:
PAPERLESS_REDIS: redis://paperless-redis:6379
PAPERLESS_OCR_LANGUAGE: eng
PAPERLESS_SECRET_KEY: ${PAPERLESS_SECRET}
paperless-redis:
image: redis:7-alpine
volumes:
paperless_data:
paperless_media:
5. Stirling PDF - PDF Tools
services:
stirling-pdf:
image: frooodle/s-pdf:latest
ports:
- "8080:8080"
volumes:
- stirling_data:/usr/share/tessdata
volumes:
stirling_data:
Development Tools
6. Gitea - Git Hosting (GitHub alternative)
services:
gitea:
image: gitea/gitea:latest
ports:
- "3000:3000"
- "2222:22"
volumes:
- gitea_data:/data
environment:
GITEA__database__DB_TYPE: postgres
GITEA__database__HOST: gitea-db:5432
GITEA__database__NAME: gitea
GITEA__database__USER: gitea
GITEA__database__PASSWD: ${GITEA_DB_PASSWORD}
gitea-db:
image: postgres:16-alpine
volumes:
- gitea_pgdata:/var/lib/postgresql/data
environment:
POSTGRES_DB: gitea
POSTGRES_USER: gitea
POSTGRES_PASSWORD: ${GITEA_DB_PASSWORD}
volumes:
gitea_data:
gitea_pgdata:
7. Drone CI - Continuous Integration
services:
drone:
image: drone/drone:latest
ports:
- "8080:80"
volumes:
- drone_data:/data
environment:
DRONE_GITEA_SERVER: https://git.example.com
DRONE_GITEA_CLIENT_ID: ${DRONE_CLIENT_ID}
DRONE_GITEA_CLIENT_SECRET: ${DRONE_CLIENT_SECRET}
DRONE_RPC_SECRET: ${DRONE_RPC_SECRET}
DRONE_SERVER_HOST: ci.example.com
DRONE_SERVER_PROTO: https
drone-runner:
image: drone/drone-runner-docker:latest
volumes:
- /var/run/docker.sock:/var/run/docker.sock
environment:
DRONE_RPC_HOST: drone
DRONE_RPC_PROTO: http
DRONE_RPC_SECRET: ${DRONE_RPC_SECRET}
DRONE_RUNNER_CAPACITY: 2
volumes:
drone_data:
8. Code Server - VS Code in the Browser
services:
code-server:
image: lscr.io/linuxserver/code-server
ports:
- "8443:8443"
volumes:
- codeserver_config:/config
- ./projects:/config/workspace
environment:
PASSWORD: ${CODE_PASSWORD}
SUDO_PASSWORD: ${CODE_SUDO_PASSWORD}
DEFAULT_WORKSPACE: /config/workspace
volumes:
codeserver_config:
9. Vault - Secrets Management
services:
vault:
image: hashicorp/vault:latest
ports:
- "8200:8200"
volumes:
- vault_data:/vault/data
environment:
VAULT_ADDR: http://0.0.0.0:8200
cap_add:
- IPC_LOCK
command: server -dev
volumes:
vault_data:
10. Registry - Docker Registry
services:
registry:
image: registry:2
ports:
- "5000:5000"
volumes:
- registry_data:/var/lib/registry
environment:
REGISTRY_STORAGE_DELETE_ENABLED: "true"
volumes:
registry_data:
Monitoring and Observability
11. Uptime Kuma - Uptime Monitoring
services:
uptime-kuma:
image: louislam/uptime-kuma:latest
ports:
- "3001:3001"
volumes:
- uptime_data:/app/data
restart: unless-stopped
volumes:
uptime_data:
12. Grafana + Prometheus - Metrics Stack
services:
prometheus:
image: prom/prometheus:latest
ports:
- "9090:9090"
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
- prometheus_data:/prometheus
grafana:
image: grafana/grafana:latest
ports:
- "3000:3000"
volumes:
- grafana_data:/var/lib/grafana
environment:
GF_SECURITY_ADMIN_PASSWORD: ${GRAFANA_PASSWORD}
volumes:
prometheus_data:
grafana_data:
13. Netdata - Real-time System Monitoring
services:
netdata:
image: netdata/netdata
ports:
- "19999:19999"
cap_add:
- SYS_PTRACE
security_opt:
- apparmor:unconfined
volumes:
- netdata_config:/etc/netdata
- netdata_lib:/var/lib/netdata
- /proc:/host/proc:ro
- /sys:/host/sys:ro
volumes:
netdata_config:
netdata_lib:
14. Dozzle - Docker Log Viewer
services:
dozzle:
image: amir20/dozzle:latest
ports:
- "8080:8080"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
15. Glances - System Monitoring
services:
glances:
image: nicolargo/glances:latest-full
ports:
- "61208:61208"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
environment:
GLANCES_OPT: "-w"
pid: host
Media and Entertainment
16. Jellyfin - Media Server
services:
jellyfin:
image: jellyfin/jellyfin:latest
ports:
- "8096:8096"
volumes:
- jellyfin_config:/config
- jellyfin_cache:/cache
- /path/to/media:/media:ro
volumes:
jellyfin_config:
jellyfin_cache:
17. Navidrome - Music Server
services:
navidrome:
image: deluan/navidrome:latest
ports:
- "4533:4533"
volumes:
- navidrome_data:/data
- /path/to/music:/music:ro
environment:
ND_SCANSCHEDULE: 1h
ND_LOGLEVEL: info
ND_BASEURL: ""
volumes:
navidrome_data:
18. Immich - Photo Management (Google Photos alternative)
services:
immich:
image: ghcr.io/immich-app/immich-server:release
ports:
- "2283:2283"
volumes:
- immich_upload:/usr/src/app/upload
environment:
DB_HOSTNAME: immich-db
DB_USERNAME: postgres
DB_PASSWORD: ${IMMICH_DB_PASSWORD}
DB_DATABASE_NAME: immich
REDIS_HOSTNAME: immich-redis
immich-db:
image: tensorchord/pgvecto-rs:pg16-v0.2.0
volumes:
- immich_pgdata:/var/lib/postgresql/data
environment:
POSTGRES_PASSWORD: ${IMMICH_DB_PASSWORD}
POSTGRES_DB: immich
immich-redis:
image: redis:7-alpine
volumes:
immich_upload:
immich_pgdata:
19. Audiobookshelf - Audiobook Server
services:
audiobookshelf:
image: ghcr.io/advplyr/audiobookshelf:latest
ports:
- "13378:80"
volumes:
- /path/to/audiobooks:/audiobooks
- /path/to/podcasts:/podcasts
- audiobookshelf_config:/config
- audiobookshelf_metadata:/metadata
volumes:
audiobookshelf_config:
audiobookshelf_metadata:
20. Calibre-web - eBook Library
services:
calibre-web:
image: lscr.io/linuxserver/calibre-web
ports:
- "8083:8083"
volumes:
- calibre_config:/config
- /path/to/books:/books
volumes:
calibre_config:
Networking and DNS
21. Pi-hole - Network Ad Blocker
services:
pihole:
image: pihole/pihole:latest
ports:
- "53:53/tcp"
- "53:53/udp"
- "8080:80"
volumes:
- pihole_data:/etc/pihole
- pihole_dnsmasq:/etc/dnsmasq.d
environment:
WEBPASSWORD: ${PIHOLE_PASSWORD}
TZ: UTC
volumes:
pihole_data:
pihole_dnsmasq:
22. AdGuard Home - DNS Filtering
services:
adguard:
image: adguard/adguardhome
ports:
- "53:53/tcp"
- "53:53/udp"
- "3000:3000"
- "8080:80"
volumes:
- adguard_work:/opt/adguardhome/work
- adguard_conf:/opt/adguardhome/conf
volumes:
adguard_work:
adguard_conf:
23. WireGuard - VPN Server
services:
wireguard:
image: lscr.io/linuxserver/wireguard
ports:
- "51820:51820/udp"
volumes:
- wireguard_config:/config
environment:
SERVERURL: vpn.example.com
PEERS: 5
PEERDNS: auto
cap_add:
- NET_ADMIN
- SYS_MODULE
sysctls:
- net.ipv4.conf.all.src_valid_mark=1
volumes:
wireguard_config:
24. Nginx Proxy Manager - Reverse Proxy GUI
services:
npm:
image: jc21/nginx-proxy-manager:latest
ports:
- "80:80"
- "443:443"
- "81:81"
volumes:
- npm_data:/data
- npm_letsencrypt:/etc/letsencrypt
volumes:
npm_data:
npm_letsencrypt:
25. Traefik - Cloud Native Reverse Proxy
services:
traefik:
image: traefik:v3.0
ports:
- "80:80"
- "443:443"
- "8080:8080"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- traefik_certs:/letsencrypt
command:
- "--api.insecure=true"
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
- "--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web"
- "[email protected]"
- "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
volumes:
traefik_certs:
Communication
26. Matrix (Synapse) + Element - Encrypted Chat
services:
synapse:
image: matrixdotorg/synapse:latest
ports:
- "8008:8008"
volumes:
- synapse_data:/data
environment:
SYNAPSE_SERVER_NAME: matrix.example.com
SYNAPSE_REPORT_STATS: "no"
element:
image: vectorim/element-web:latest
ports:
- "8080:80"
volumes:
- ./element-config.json:/app/config.json:ro
volumes:
synapse_data:
27. Mattermost - Team Chat (Slack alternative)
services:
mattermost:
image: mattermost/mattermost-team-edition:latest
ports:
- "8065:8065"
volumes:
- mattermost_data:/mattermost/data
- mattermost_config:/mattermost/config
environment:
MM_SQLSETTINGS_DRIVERNAME: postgres
MM_SQLSETTINGS_DATASOURCE: "postgres://mattermost:${MM_DB_PASSWORD}@mattermost-db:5432/mattermost?sslmode=disable"
mattermost-db:
image: postgres:16-alpine
volumes:
- mattermost_pgdata:/var/lib/postgresql/data
environment:
POSTGRES_DB: mattermost
POSTGRES_USER: mattermost
POSTGRES_PASSWORD: ${MM_DB_PASSWORD}
volumes:
mattermost_data:
mattermost_config:
mattermost_pgdata:
Security and Authentication
28. Vaultwarden - Password Manager (Bitwarden compatible)
services:
vaultwarden:
image: vaultwarden/server:latest
ports:
- "8080:80"
volumes:
- vaultwarden_data:/data
environment:
SIGNUPS_ALLOWED: "false"
ADMIN_TOKEN: ${VW_ADMIN_TOKEN}
volumes:
vaultwarden_data:
29. Authentik - Identity Provider
services:
authentik:
image: ghcr.io/goauthentik/server:latest
command: server
ports:
- "9000:9000"
- "9443:9443"
environment:
AUTHENTIK_REDIS__HOST: authentik-redis
AUTHENTIK_POSTGRESQL__HOST: authentik-db
AUTHENTIK_POSTGRESQL__PASSWORD: ${AUTHENTIK_DB_PASSWORD}
AUTHENTIK_SECRET_KEY: ${AUTHENTIK_SECRET}
authentik-worker:
image: ghcr.io/goauthentik/server:latest
command: worker
environment:
AUTHENTIK_REDIS__HOST: authentik-redis
AUTHENTIK_POSTGRESQL__HOST: authentik-db
AUTHENTIK_POSTGRESQL__PASSWORD: ${AUTHENTIK_DB_PASSWORD}
AUTHENTIK_SECRET_KEY: ${AUTHENTIK_SECRET}
authentik-db:
image: postgres:16-alpine
volumes:
- authentik_pgdata:/var/lib/postgresql/data
environment:
POSTGRES_PASSWORD: ${AUTHENTIK_DB_PASSWORD}
POSTGRES_DB: authentik
POSTGRES_USER: authentik
authentik-redis:
image: redis:7-alpine
volumes:
authentik_pgdata:
30. CrowdSec - Collaborative Security
services:
crowdsec:
image: crowdsecurity/crowdsec:latest
ports:
- "8080:8080"
volumes:
- crowdsec_data:/var/lib/crowdsec/data
- crowdsec_config:/etc/crowdsec
- /var/log:/var/log:ro
volumes:
crowdsec_data:
crowdsec_config:
Databases and Caches
31-34. Database Engines
# PostgreSQL
services:
postgres:
image: postgres:16-alpine
ports: ["5432:5432"]
volumes: [pgdata:/var/lib/postgresql/data]
environment:
POSTGRES_PASSWORD: ${PG_PASSWORD}
# Redis
redis:
image: redis:7-alpine
ports: ["6379:6379"]
command: redis-server --requirepass ${REDIS_PASSWORD}
volumes: [redisdata:/data]
# MongoDB
mongodb:
image: mongo:7
ports: ["27017:27017"]
volumes: [mongodata:/data/db]
environment:
MONGO_INITDB_ROOT_USERNAME: admin
MONGO_INITDB_ROOT_PASSWORD: ${MONGO_PASSWORD}
# MariaDB
mariadb:
image: mariadb:11
ports: ["3306:3306"]
volumes: [mariadbdata:/var/lib/mysql]
environment:
MARIADB_ROOT_PASSWORD: ${MARIADB_PASSWORD}
volumes:
pgdata:
redisdata:
mongodata:
mariadbdata:
Backup and Storage
35. MinIO - S3-Compatible Object Storage
services:
minio:
image: minio/minio
ports:
- "9000:9000"
- "9001:9001"
volumes:
- minio_data:/data
environment:
MINIO_ROOT_USER: ${MINIO_USER}
MINIO_ROOT_PASSWORD: ${MINIO_PASSWORD}
command: server /data --console-address ":9001"
volumes:
minio_data:
36. Duplicati - Backup with GUI
services:
duplicati:
image: lscr.io/linuxserver/duplicati
ports:
- "8200:8200"
volumes:
- duplicati_config:/config
- /path/to/backups:/backups
- /path/to/source:/source:ro
volumes:
duplicati_config:
Analytics and Dashboards
37. Plausible - Privacy-Friendly Analytics
services:
plausible:
image: ghcr.io/plausible/community-edition:latest
ports:
- "8000:8000"
environment:
BASE_URL: https://analytics.example.com
SECRET_KEY_BASE: ${PLAUSIBLE_SECRET}
DATABASE_URL: postgres://plausible:${PL_DB_PASSWORD}@plausible-db:5432/plausible
CLICKHOUSE_DATABASE_URL: http://plausible-events-db:8123/plausible_events_db
plausible-db:
image: postgres:16-alpine
volumes: [plausible_pgdata:/var/lib/postgresql/data]
environment:
POSTGRES_PASSWORD: ${PL_DB_PASSWORD}
POSTGRES_DB: plausible
plausible-events-db:
image: clickhouse/clickhouse-server:latest
volumes: [plausible_clickhouse:/var/lib/clickhouse]
volumes:
plausible_pgdata:
plausible_clickhouse:
38. Homepage - Dashboard
services:
homepage:
image: ghcr.io/gethomepage/homepage:latest
ports:
- "3000:3000"
volumes:
- homepage_config:/app/config
- /var/run/docker.sock:/var/run/docker.sock:ro
volumes:
homepage_config:
39. Homarr - Homelab Dashboard
services:
homarr:
image: ghcr.io/ajnart/homarr:latest
ports:
- "7575:7575"
volumes:
- homarr_config:/app/data/configs
- homarr_icons:/app/public/icons
- /var/run/docker.sock:/var/run/docker.sock:ro
volumes:
homarr_config:
homarr_icons:
Automation and Utilities
40. n8n - Workflow Automation
services:
n8n:
image: n8nio/n8n
ports:
- "5678:5678"
volumes:
- n8n_data:/home/node/.n8n
environment:
N8N_BASIC_AUTH_ACTIVE: "true"
N8N_BASIC_AUTH_USER: admin
N8N_BASIC_AUTH_PASSWORD: ${N8N_PASSWORD}
volumes:
n8n_data:
41. Watchtower - Auto-Update Containers
services:
watchtower:
image: containrrr/watchtower
volumes:
- /var/run/docker.sock:/var/run/docker.sock
environment:
WATCHTOWER_CLEANUP: "true"
WATCHTOWER_SCHEDULE: "0 0 4 * * *"
WATCHTOWER_NOTIFICATIONS: email
42. Portainer - Docker Management GUI
services:
portainer:
image: portainer/portainer-ce:latest
ports:
- "9443:9443"
volumes:
- portainer_data:/data
- /var/run/docker.sock:/var/run/docker.sock
volumes:
portainer_data:
43. Speedtest Tracker - Network Speed Monitoring
services:
speedtest:
image: lscr.io/linuxserver/speedtest-tracker
ports:
- "8080:80"
volumes:
- speedtest_config:/config
environment:
DB_CONNECTION: sqlite
SPEEDTEST_SCHEDULE: "0 */6 * * *"
volumes:
speedtest_config:
Knowledge and Notes
44. Outline - Knowledge Base (Notion alternative)
services:
outline:
image: outlinewiki/outline:latest
ports:
- "3000:3000"
environment:
DATABASE_URL: postgres://outline:${OL_DB_PASSWORD}@outline-db:5432/outline
REDIS_URL: redis://outline-redis:6379
SECRET_KEY: ${OL_SECRET_KEY}
UTILS_SECRET: ${OL_UTILS_SECRET}
URL: https://wiki.example.com
outline-db:
image: postgres:16-alpine
volumes: [outline_pgdata:/var/lib/postgresql/data]
environment:
POSTGRES_PASSWORD: ${OL_DB_PASSWORD}
POSTGRES_DB: outline
POSTGRES_USER: outline
outline-redis:
image: redis:7-alpine
volumes:
outline_pgdata:
45. Trilium - Hierarchical Notes
services:
trilium:
image: zadam/trilium:latest
ports:
- "8080:8080"
volumes:
- trilium_data:/home/node/trilium-data
volumes:
trilium_data:
File Sharing and Transfer
46. FileBrowser - Web File Manager
services:
filebrowser:
image: filebrowser/filebrowser:latest
ports:
- "8080:80"
volumes:
- /path/to/files:/srv
- filebrowser_db:/database
volumes:
filebrowser_db:
47. Syncthing - File Synchronization
services:
syncthing:
image: lscr.io/linuxserver/syncthing
ports:
- "8384:8384"
- "22000:22000/tcp"
- "22000:22000/udp"
volumes:
- syncthing_config:/config
- /path/to/sync:/data
volumes:
syncthing_config:
More Essential Services
48. Changedetection.io - Website Change Monitoring
services:
changedetection:
image: ghcr.io/dgtlmoon/changedetection.io
ports:
- "5000:5000"
volumes:
- changedetection_data:/datastore
volumes:
changedetection_data:
49. IT-Tools - Developer Utilities
services:
it-tools:
image: corentinth/it-tools:latest
ports:
- "8080:80"
50. Mealie - Recipe Manager
services:
mealie:
image: ghcr.io/mealie-recipes/mealie:latest
ports:
- "9925:9000"
volumes:
- mealie_data:/app/data
environment:
BASE_URL: https://recipes.example.com
ALLOW_SIGNUP: "false"
volumes:
mealie_data:
Deployment Tips
- Use a reverse proxy: Traefik or Caddy handles HTTPS certificates automatically via Let's Encrypt.
- Back up your volumes: Every named volume in these snippets contains your data. Back them up regularly.
- Set resource limits: Add
deploy.resources.limitsto prevent any single service from consuming all resources. - Use .env files: Store passwords and configuration in
.envfiles, not in the Compose file directly. - Monitor everything: Uptime Kuma for availability, Grafana for metrics, Dozzle for logs.
Managing dozens of self-hosted services becomes considerably easier with a Docker management platform like usulnet, which provides a unified view of all containers, their health status, resource usage, and logs across multiple servers. Whether you are running 5 services or 50, having centralized visibility into your infrastructure saves time and prevents outages.