Files
docker-compose/net/compose.yaml
Sebastian Krüger e22936ecbe fix: set Docker API version for Watchtower compatibility
Add DOCKER_API_VERSION=1.44 environment variable to Watchtower
to ensure compatibility with upgraded Docker daemon.

The Watchtower image (v1.7.1) has an older Docker client that
defaults to API version 1.25, which is incompatible with the
new Docker daemon requiring API version 1.44+.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-20 19:24:57 +01:00

331 lines
15 KiB
YAML

services:
# Traefik - Reverse proxy and load balancer
traefik:
image: ${NET_PROXY_DOCKER_IMAGE}
container_name: ${NET_COMPOSE_PROJECT_NAME}_traefik
restart: unless-stopped
command:
# API & Dashboard
- '--api.dashboard=true'
- '--api.insecure=false'
# Ping endpoint for healthcheck
- '--ping=true'
# Experimental plugins
- '--experimental.plugins.sablier.modulename=github.com/acouvreur/sablier'
- '--experimental.plugins.sablier.version=v1.8.0'
# Logging
- '--log.level=${NET_PROXY_LOG_LEVEL:-INFO}'
- '--accesslog=true'
# Global
- '--global.sendAnonymousUsage=false'
- '--global.checkNewVersion=true'
# Docker Provider
- '--providers.docker=true'
- '--providers.docker.exposedbydefault=false'
- '--providers.docker.network=${NETWORK_NAME}'
# File Provider for dynamic configuration
- '--providers.file.directory=/etc/traefik/dynamic'
- '--providers.file.watch=true'
# Entrypoints
- '--entrypoints.web.address=:${NET_PROXY_PORT_HTTP:-80}'
- '--entrypoints.web-secure.address=:${NET_PROXY_PORT_HTTPS:-443}'
# Global HTTP to HTTPS redirect
- '--entrypoints.web.http.redirections.entryPoint.to=web-secure'
- '--entrypoints.web.http.redirections.entryPoint.scheme=https'
- '--entrypoints.web.http.redirections.entryPoint.permanent=true'
# Security Headers (applied globally)
- '--entrypoints.web-secure.http.middlewares=security-headers@file'
# Let's Encrypt
- '--certificatesresolvers.resolver.acme.tlschallenge=true'
- '--certificatesresolvers.resolver.acme.email=${ADMIN_EMAIL}'
- '--certificatesresolvers.resolver.acme.storage=/letsencrypt/acme.json'
healthcheck:
test: ["CMD", "traefik", "healthcheck", "--ping"]
interval: 30s
timeout: 5s
retries: 3
start_period: 10s
environment:
AUTH_USERS: ${AUTH_USERS}
networks:
- compose_network
- coolify
ports:
- "${NET_PROXY_PORT_HTTP:-80}:80"
- "${NET_PROXY_PORT_HTTPS:-443}:443"
volumes:
- letsencrypt_data:/letsencrypt
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./dynamic:/etc/traefik/dynamic:ro
labels:
- 'traefik.enable=true'
# HTTP to HTTPS redirect
- 'traefik.http.middlewares.${NET_COMPOSE_PROJECT_NAME}-traefik-redirect-web-secure.redirectscheme.scheme=https'
- 'traefik.http.routers.${NET_COMPOSE_PROJECT_NAME}-traefik-web.middlewares=${NET_COMPOSE_PROJECT_NAME}-traefik-redirect-web-secure'
- 'traefik.http.routers.${NET_COMPOSE_PROJECT_NAME}-traefik-web.rule=Host(`${NET_PROXY_TRAEFIK_HOST}`)'
- 'traefik.http.routers.${NET_COMPOSE_PROJECT_NAME}-traefik-web.entrypoints=web'
# HTTPS router with auth
- 'traefik.http.routers.${NET_COMPOSE_PROJECT_NAME}-traefik-web-secure.rule=Host(`${NET_PROXY_TRAEFIK_HOST}`)'
- 'traefik.http.routers.${NET_COMPOSE_PROJECT_NAME}-traefik-web-secure.tls.certresolver=resolver'
- 'traefik.http.routers.${NET_COMPOSE_PROJECT_NAME}-traefik-web-secure.entrypoints=web-secure'
- 'traefik.http.routers.${NET_COMPOSE_PROJECT_NAME}-traefik-web-secure.service=api@internal'
- 'traefik.http.routers.${NET_COMPOSE_PROJECT_NAME}-traefik-web-secure.middlewares=${NET_COMPOSE_PROJECT_NAME}-authelia,security-headers@file'
- 'traefik.http.services.${NET_COMPOSE_PROJECT_NAME}-traefik-web-secure.loadbalancer.server.port=8080'
- 'traefik.docker.network=${NETWORK_NAME}'
# Netdata - Real-time monitoring
netdata:
build:
context: .
dockerfile: Dockerfile
image: ${NET_NETDATA_IMAGE:-netdata/netdata:latest}
container_name: ${NET_COMPOSE_PROJECT_NAME}_netdata
restart: unless-stopped
hostname: ${NET_NETDATA_HOSTNAME:-netdata.pivoine.art}
cap_add:
- SYS_PTRACE
- SYS_ADMIN
security_opt:
- apparmor:unconfined
volumes:
- netdata_config:/etc/netdata
- netdata_lib:/var/lib/netdata
- netdata_cache:/var/cache/netdata
- ./go.d/postgres.conf:/etc/netdata/go.d/postgres.conf:ro
- ./go.d/filecheck.conf:/etc/netdata/go.d/filecheck.conf:ro
- ./health_alarm_notify.conf:/etc/netdata/health_alarm_notify.conf:ro
- ./msmtprc:/etc/netdata/msmtprc:ro
- /mnt/hidrive/users/valknar/Backup:/mnt/hidrive/users/valknar/Backup:ro
- /etc/passwd:/host/etc/passwd:ro
- /etc/group:/host/etc/group:ro
- /etc/localtime:/etc/localtime:ro
- /proc:/host/proc:ro
- /sys:/host/sys:ro
- /etc/os-release:/host/etc/os-release:ro
- /var/log:/host/var/log:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
environment:
- NETDATA_CLAIM_TOKEN=${NETDATA_CLAIM_TOKEN:-}
- NETDATA_CLAIM_URL=${NETDATA_CLAIM_URL:-}
- NETDATA_CLAIM_ROOMS=${NETDATA_CLAIM_ROOMS:-}
- MATTERMOST_WEBHOOK_URL=${MATTERMOST_WEBHOOK_URL:-}
networks:
- compose_network
labels:
- 'traefik.enable=${NET_TRAEFIK_ENABLED}'
# HTTP to HTTPS redirect
- 'traefik.http.middlewares.${NET_COMPOSE_PROJECT_NAME}-netdata-redirect-web-secure.redirectscheme.scheme=https'
- 'traefik.http.routers.${NET_COMPOSE_PROJECT_NAME}-netdata-web.middlewares=${NET_COMPOSE_PROJECT_NAME}-netdata-redirect-web-secure'
- 'traefik.http.routers.${NET_COMPOSE_PROJECT_NAME}-netdata-web.rule=Host(`${NET_NETDATA_TRAEFIK_HOST}`)'
- 'traefik.http.routers.${NET_COMPOSE_PROJECT_NAME}-netdata-web.entrypoints=web'
# HTTPS router
- 'traefik.http.routers.${NET_COMPOSE_PROJECT_NAME}-netdata-web-secure.rule=Host(`${NET_NETDATA_TRAEFIK_HOST}`)'
- 'traefik.http.routers.${NET_COMPOSE_PROJECT_NAME}-netdata-web-secure.tls.certresolver=resolver'
- 'traefik.http.routers.${NET_COMPOSE_PROJECT_NAME}-netdata-web-secure.entrypoints=web-secure'
- 'traefik.http.middlewares.${NET_COMPOSE_PROJECT_NAME}-netdata-compress.compress=true'
- 'traefik.http.routers.${NET_COMPOSE_PROJECT_NAME}-netdata-web-secure.middlewares=${NET_COMPOSE_PROJECT_NAME}-netdata-compress,${NET_COMPOSE_PROJECT_NAME}-authelia,security-headers@file'
# Service
- 'traefik.http.services.${NET_COMPOSE_PROJECT_NAME}-netdata.loadbalancer.server.port=19999'
- 'traefik.docker.network=${NETWORK_NAME}'
# Watchtower
- 'com.centurylinklabs.watchtower.enable=${WATCHTOWER_LABEL_ENABLE}'
# Watchtower - Automatic container updates
watchtower:
image: containrrr/watchtower:latest
container_name: ${NET_COMPOSE_PROJECT_NAME}_watchtower
restart: unless-stopped
volumes:
- /var/run/docker.sock:/var/run/docker.sock
environment:
# Docker API version negotiation
DOCKER_API_VERSION: "1.44"
# Check for updates every 5 minutes (300 seconds)
WATCHTOWER_POLL_INTERVAL: ${WATCHTOWER_POLL_INTERVAL:-300}
# Only update containers with the watchtower label
WATCHTOWER_LABEL_ENABLE: ${WATCHTOWER_LABEL_ENABLE:-true}
# Clean up old images after update
WATCHTOWER_CLEANUP: ${WATCHTOWER_CLEANUP:-true}
# Include stopped containers
WATCHTOWER_INCLUDE_STOPPED: ${WATCHTOWER_INCLUDE_STOPPED:-false}
# Include restarting containers
WATCHTOWER_INCLUDE_RESTARTING: ${WATCHTOWER_INCLUDE_RESTARTING:-true}
# Run once and exit (set to false for continuous monitoring)
WATCHTOWER_RUN_ONCE: ${WATCHTOWER_RUN_ONCE:-false}
# Notifications via Shoutrrr
WATCHTOWER_NOTIFICATIONS: ${WATCHTOWER_NOTIFICATIONS:-}
WATCHTOWER_NOTIFICATION_URL: ${WATCHTOWER_NOTIFICATION_URL:-}
# Log level (trace, debug, info, warn, error, fatal, panic)
WATCHTOWER_LOG_LEVEL: ${WATCHTOWER_LOG_LEVEL:-info}
# Rolling restart (update one container at a time)
WATCHTOWER_ROLLING_RESTART: ${WATCHTOWER_ROLLING_RESTART:-false}
labels:
# Allow watchtower to update itself
- com.centurylinklabs.watchtower.enable=true
# Umami - Web analytics
umami:
image: ${NET_TRACK_DOCKER_IMAGE}
container_name: ${NET_COMPOSE_PROJECT_NAME}_umami
restart: unless-stopped
environment:
TZ: ${TIMEZONE:-Europe/Amsterdam}
# Database Configuration
DATABASE_URL: postgresql://${DB_USER}:${DB_PASSWORD}@${CORE_DB_HOST}:${CORE_DB_PORT}/${NET_TRACK_DB_NAME}
DATABASE_TYPE: postgresql
# Application Secret
APP_SECRET: ${TRACK_APP_SECRET}
# Redis Cache Integration
REDIS_URL: redis://${CORE_REDIS_HOST}:${CORE_REDIS_PORT}
CACHE_ENABLED: true
networks:
- compose_network
healthcheck:
test: ["CMD-SHELL", "curl -f http://localhost:3000/api/heartbeat || exit 1"]
interval: 30s
timeout: 10s
retries: 5
start_period: 40s
labels:
# Traefik Configuration
- 'traefik.enable=${NET_TRAEFIK_ENABLED}'
# HTTP to HTTPS redirect
- 'traefik.http.middlewares.${NET_COMPOSE_PROJECT_NAME}-umami-redirect-web-secure.redirectscheme.scheme=https'
- 'traefik.http.routers.${NET_COMPOSE_PROJECT_NAME}-umami-web.middlewares=${NET_COMPOSE_PROJECT_NAME}-umami-redirect-web-secure'
- 'traefik.http.routers.${NET_COMPOSE_PROJECT_NAME}-umami-web.rule=Host(`${NET_TRACK_TRAEFIK_HOST}`)'
- 'traefik.http.routers.${NET_COMPOSE_PROJECT_NAME}-umami-web.entrypoints=web'
- 'traefik.http.routers.${NET_COMPOSE_PROJECT_NAME}-umami-web-secure.rule=Host(`${NET_TRACK_TRAEFIK_HOST}`)'
- 'traefik.http.routers.${NET_COMPOSE_PROJECT_NAME}-umami-web-secure.tls.certresolver=resolver'
- 'traefik.http.routers.${NET_COMPOSE_PROJECT_NAME}-umami-web-secure.entrypoints=web-secure'
- 'traefik.http.routers.${NET_COMPOSE_PROJECT_NAME}-umami-web-secure.middlewares=security-headers@file'
- 'traefik.http.services.${NET_COMPOSE_PROJECT_NAME}-umami-web-secure.loadbalancer.server.port=3000'
- 'traefik.docker.network=${NETWORK_NAME}'
# Watchtower
- 'com.centurylinklabs.watchtower.enable=${WATCHTOWER_LABEL_ENABLE}'
# Mailpit - SMTP server with web UI
mailpit:
image: ${NET_MAILPIT_IMAGE:-axllent/mailpit:latest}
container_name: ${NET_COMPOSE_PROJECT_NAME}_mailpit
restart: unless-stopped
environment:
TZ: ${TIMEZONE:-Europe/Berlin}
# SMTP relay configuration for IONOS
MP_SMTP_AUTH_ACCEPT_ANY: 1
MP_SMTP_AUTH_ALLOW_INSECURE: 1
MP_MAX_MESSAGES: 5000
# SMTP relay to IONOS - relay all emails preserving recipients
MP_SMTP_RELAY_ALL: "true"
MP_SMTP_RELAY_HOST: ${EMAIL_SMTP_HOST}
MP_SMTP_RELAY_PORT: ${EMAIL_SMTP_PORT}
MP_SMTP_RELAY_USERNAME: ${EMAIL_SMTP_USER}
MP_SMTP_RELAY_PASSWORD: ${EMAIL_SMTP_PASSWORD}
MP_SMTP_RELAY_AUTH: plain
MP_SMTP_RELAY_TLS: "true"
volumes:
- mailpit_data:/data
networks:
- compose_network
labels:
- 'traefik.enable=${NET_TRAEFIK_ENABLED}'
# HTTP to HTTPS redirect
- 'traefik.http.middlewares.${NET_COMPOSE_PROJECT_NAME}-mailpit-redirect-web-secure.redirectscheme.scheme=https'
- 'traefik.http.routers.${NET_COMPOSE_PROJECT_NAME}-mailpit-web.middlewares=${NET_COMPOSE_PROJECT_NAME}-mailpit-redirect-web-secure'
- 'traefik.http.routers.${NET_COMPOSE_PROJECT_NAME}-mailpit-web.rule=Host(`${NET_MAILPIT_TRAEFIK_HOST}`)'
- 'traefik.http.routers.${NET_COMPOSE_PROJECT_NAME}-mailpit-web.entrypoints=web'
# HTTPS router with auth
- 'traefik.http.routers.${NET_COMPOSE_PROJECT_NAME}-mailpit-web-secure.rule=Host(`${NET_MAILPIT_TRAEFIK_HOST}`)'
- 'traefik.http.routers.${NET_COMPOSE_PROJECT_NAME}-mailpit-web-secure.tls.certresolver=resolver'
- 'traefik.http.routers.${NET_COMPOSE_PROJECT_NAME}-mailpit-web-secure.entrypoints=web-secure'
- 'traefik.http.routers.${NET_COMPOSE_PROJECT_NAME}-mailpit-web-secure.middlewares=${NET_COMPOSE_PROJECT_NAME}-authelia,security-headers@file'
# Service
- 'traefik.http.services.${NET_COMPOSE_PROJECT_NAME}-mailpit-web-secure.loadbalancer.server.port=8025'
- 'traefik.docker.network=${NETWORK_NAME}'
# Watchtower
- 'com.centurylinklabs.watchtower.enable=${WATCHTOWER_LABEL_ENABLE}'
# Authelia - SSO and authentication portal
authelia:
image: ${NET_AUTHELIA_IMAGE:-authelia/authelia:latest}
container_name: ${NET_COMPOSE_PROJECT_NAME}_authelia
restart: unless-stopped
command: --config /etc/authelia/configuration.yml
environment:
TZ: ${TIMEZONE:-Europe/Berlin}
AUTHELIA_IDENTITY_VALIDATION_RESET_PASSWORD_JWT_SECRET: ${AUTHELIA_JWT_SECRET}
AUTHELIA_SESSION_SECRET: ${AUTHELIA_SESSION_SECRET}
AUTHELIA_STORAGE_ENCRYPTION_KEY: ${AUTHELIA_STORAGE_ENCRYPTION_KEY}
AUTHELIA_STORAGE_POSTGRES_PASSWORD: ${DB_PASSWORD}
volumes:
- authelia_config:/config
- ./authelia:/etc/authelia:ro
networks:
- compose_network
labels:
- 'traefik.enable=${NET_TRAEFIK_ENABLED}'
# HTTP to HTTPS redirect
- 'traefik.http.middlewares.${NET_COMPOSE_PROJECT_NAME}-authelia-redirect-web-secure.redirectscheme.scheme=https'
- 'traefik.http.routers.${NET_COMPOSE_PROJECT_NAME}-authelia-web.middlewares=${NET_COMPOSE_PROJECT_NAME}-authelia-redirect-web-secure'
- 'traefik.http.routers.${NET_COMPOSE_PROJECT_NAME}-authelia-web.rule=Host(`${NET_AUTHELIA_TRAEFIK_HOST}`)'
- 'traefik.http.routers.${NET_COMPOSE_PROJECT_NAME}-authelia-web.entrypoints=web'
# HTTPS router
- 'traefik.http.routers.${NET_COMPOSE_PROJECT_NAME}-authelia-web-secure.rule=Host(`${NET_AUTHELIA_TRAEFIK_HOST}`)'
- 'traefik.http.routers.${NET_COMPOSE_PROJECT_NAME}-authelia-web-secure.tls.certresolver=resolver'
- 'traefik.http.routers.${NET_COMPOSE_PROJECT_NAME}-authelia-web-secure.entrypoints=web-secure'
- 'traefik.http.routers.${NET_COMPOSE_PROJECT_NAME}-authelia-web-secure.middlewares=security-headers@file'
# Service
- 'traefik.http.services.${NET_COMPOSE_PROJECT_NAME}-authelia-web-secure.loadbalancer.server.port=9091'
- 'traefik.docker.network=${NETWORK_NAME}'
# ForwardAuth middleware for other services
- 'traefik.http.middlewares.${NET_COMPOSE_PROJECT_NAME}-authelia.forwardAuth.address=http://net_authelia:9091/api/authz/forward-auth'
- 'traefik.http.middlewares.${NET_COMPOSE_PROJECT_NAME}-authelia.forwardAuth.trustForwardHeader=true'
- 'traefik.http.middlewares.${NET_COMPOSE_PROJECT_NAME}-authelia.forwardAuth.authResponseHeaders=Remote-User,Remote-Groups,Remote-Name,Remote-Email'
- 'traefik.http.middlewares.${NET_COMPOSE_PROJECT_NAME}-authelia.forwardAuth.authResponseHeadersRegex=^Remote-'
# Watchtower
- 'com.centurylinklabs.watchtower.enable=${WATCHTOWER_LABEL_ENABLE}'
volumes:
letsencrypt_data:
name: ${NET_COMPOSE_PROJECT_NAME}_letsencrypt_data
netdata_config:
name: ${NET_COMPOSE_PROJECT_NAME}_netdata_config
netdata_lib:
name: ${NET_COMPOSE_PROJECT_NAME}_netdata_lib
netdata_cache:
name: ${NET_COMPOSE_PROJECT_NAME}_netdata_cache
mailpit_data:
name: ${NET_COMPOSE_PROJECT_NAME}_mailpit_data
authelia_config:
name: ${NET_COMPOSE_PROJECT_NAME}_authelia_config
networks:
compose_network:
name: ${NETWORK_NAME}
external: true
coolify:
name: coolify
external: true