services: # ===== DATABASE LAYER ===== next-db: image: docker.io/postgres:18 container_name: next-db restart: unless-stopped environment: - POSTGRES_DB={{ db_name }} - POSTGRES_USER={{ db_user }} - POSTGRES_PASSWORD={{ db_password }} - POSTGRES_INITDB_ARGS=--encoding=UTF-8 --lc-collate=C --lc-ctype=C volumes: - pg_data:/var/lib/postgresql/data networks: - nextcloud_network labels: - "com.centurylinklabs.watchtower.enable=false" healthcheck: test: ["CMD-SHELL", "pg_isready -U {{ db_user }}"] interval: 10s timeout: 5s retries: 5 next-redis: image: docker.io/redis:7-alpine container_name: next-redis restart: unless-stopped command: redis-server --requirepass {{ redis_password }} --maxmemory 256mb --maxmemory-policy allkeys-lru volumes: - redis_data:/data networks: - nextcloud_network labels: - "com.centurylinklabs.watchtower.enable=false" healthcheck: test: ["CMD", "redis-cli", "--raw", "incr", "ping"] interval: 10s timeout: 5s retries: 5 # ===== APPLICATION LAYER ===== next: image: docker.io/nextcloud:latest container_name: next restart: unless-stopped depends_on: next-db: condition: service_healthy next-redis: condition: service_healthy mem_swappiness: -1 environment: - POSTGRES_DB={{ db_name }} - POSTGRES_USER={{ db_user }} - POSTGRES_PASSWORD={{ db_password }} - POSTGRES_HOST=next-db - REDIS_HOST=next-redis - REDIS_HOST_PASSWORD={{ redis_password }} - NEXTCLOUD_TRUSTED_DOMAINS={{ subdomain_nextcloud }}.{{ domain }} - NEXTCLOUD_ADMIN_USER={{ admin_user }} - NEXTCLOUD_ADMIN_PASSWORD={{ admin_password }} - OVERWRITEPROTOCOL=https - OVERWRITEHOST={{ subdomain_nextcloud }}.{{ domain }} - TRUSTED_PROXIES=caddy - PHP_MEMORY_LIMIT=512M - PHP_UPLOAD_LIMIT=10G volumes: - nextcloud_data:/var/www/html - {{ deployment_dir }}/configs/nextcloud:/var/www/html/config:Z - nextcloud_apps:/var/www/html/custom_apps networks: - nextcloud_network labels: - "com.centurylinklabs.watchtower.enable=false" healthcheck: test: ["CMD", "curl", "-f", "http://localhost/status.php"] interval: 30s timeout: 10s retries: 3 onlyoffice: image: docker.io/onlyoffice/documentserver:latest container_name: onlyoffice restart: unless-stopped environment: - JWT_ENABLED=false - JWT_HEADER=Authorization - JWT_IN_BODY=true volumes: - onlyoffice_data:/var/www/onlyoffice/Data - onlyoffice_logs:/var/log/onlyoffice networks: - nextcloud_network labels: - "com.centurylinklabs.watchtower.monitor-only=true" excalidraw: image: docker.io/excalidraw/excalidraw:latest container_name: excalidraw restart: unless-stopped environment: - NODE_ENV=production - TZ={{ timezone }} networks: - nextcloud_network labels: - "com.centurylinklabs.watchtower.enable=true" obsidian: image: lscr.io/linuxserver/obsidian:latest container_name: obsidian restart: unless-stopped security_opt: - seccomp:unconfined environment: - PUID=1000 - PGID=1000 - TZ={{ timezone }} volumes: - {{ deployment_dir }}/data/obsidian/config:/config:z - {{ deployment_dir }}/data/obsidian/vault:/vault:z networks: - nextcloud_network labels: - "com.centurylinklabs.watchtower.enable=true" shm_size: "1gb" # ===== INFRASTRUCTURE LAYER ===== caddy: image: docker.io/caddy:latest container_name: caddy restart: unless-stopped ports: - "80:80" - "443:443" - "443:443/udp" volumes: - {{ deployment_dir }}/configs/caddy/Caddyfile:/etc/caddy/Caddyfile:ro - caddy_data:/data - caddy_config:/config environment: - DOMAIN={{ domain }} - EMAIL={{ user_email }} networks: - nextcloud_network labels: - "com.centurylinklabs.watchtower.enable=true" homarr: image: ghcr.io/homarr-labs/homarr:latest container_name: homarr restart: unless-stopped volumes: - /var/run/docker.sock:/var/run/docker.sock:ro - {{ deployment_dir }}/data/homarr:/appdata environment: - SECRET_ENCRYPTION_KEY={{ homarr_secret }} - TZ={{ timezone }} networks: - nextcloud_network labels: - "com.centurylinklabs.watchtower.enable=true" dockhand: image: fnsys/dockhand:latest container_name: dockhand restart: unless-stopped ports: - "3003:3000" volumes: - /var/run/docker.sock:/var/run/docker.sock:ro - dockhand_data:/app/data networks: - nextcloud_network labels: - "com.centurylinklabs.watchtower.enable=true" uptime-kuma: image: louislam/uptime-kuma:latest container_name: uptime-kuma restart: unless-stopped volumes: - uptime_kuma_data:/app/data environment: - TZ={{ timezone }} networks: - nextcloud_network labels: - "com.centurylinklabs.watchtower.enable=true" watchtower: image: containrrr/watchtower:latest container_name: watchtower restart: unless-stopped volumes: - /var/run/docker.sock:/var/run/docker.sock environment: - WATCHTOWER_CLEANUP=true - WATCHTOWER_LABEL_ENABLE=true - WATCHTOWER_POLL_INTERVAL=86400 - WATCHTOWER_ROLLING_RESTART=true - WATCHTOWER_INCLUDE_RESTARTING=true - TZ={{ timezone }} networks: - nextcloud_network # ===== PERSISTENT STORAGE ===== volumes: pg_data: redis_data: nextcloud_data: nextcloud_apps: onlyoffice_data: onlyoffice_logs: caddy_data: caddy_config: dockhand_data: uptime_kuma_data: # ===== NETWORKING ===== networks: nextcloud_network: name: nextcloud_network driver: bridge