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.

Tip: For all services, pair them with a reverse proxy (Traefik, Caddy, or Nginx Proxy Manager) for HTTPS and proper domain routing. See our reverse proxy guide for setup details.

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.limits to prevent any single service from consuming all resources.
  • Use .env files: Store passwords and configuration in .env files, 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.