Files
docker-compose/net/compose.yaml
Sebastian Krüger ea6587f176 fix: configure Mailpit relay via environment variables
- Remove mailpit-relay.yaml file (env vars not substituted in mounts)
- Use MP_SMTP_RELAY_* environment variables directly
- Fixes crash loop due to missing relay host configuration

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-15 18:46:01 +01:00

286 lines
12 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.middlewares.${NET_COMPOSE_PROJECT_NAME}-traefik-auth.basicauth.users=${AUTH_USERS}'
- 'traefik.http.routers.${NET_COMPOSE_PROJECT_NAME}-traefik-web-secure.middlewares=${NET_COMPOSE_PROJECT_NAME}-traefik-auth'
- '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.middlewares.${NET_COMPOSE_PROJECT_NAME}-netdata-auth.basicauth.users=${AUTH_USERS}'
- 'traefik.http.routers.${NET_COMPOSE_PROJECT_NAME}-netdata-web-secure.middlewares=${NET_COMPOSE_PROJECT_NAME}-netdata-auth,${NET_COMPOSE_PROJECT_NAME}-netdata-compress,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:
# 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.services.${NET_COMPOSE_PROJECT_NAME}-umami-web-secure.loadbalancer.server.port=3000'
- 'traefik.docker.network=${NETWORK_NAME}'
# 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 via environment variables
MP_SMTP_RELAY_HOST: ${EMAIL_SMTP_HOST}
MP_SMTP_RELAY_PORT: ${EMAIL_SMTP_PORT}
MP_SMTP_RELAY_USER: ${EMAIL_SMTP_USER}
MP_SMTP_RELAY_PASS: ${EMAIL_SMTP_PASSWORD}
MP_SMTP_RELAY_AUTH: plain
MP_SMTP_RELAY_STARTTLS: "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.middlewares.${NET_COMPOSE_PROJECT_NAME}-mailpit-auth.basicauth.users=${AUTH_USERS}'
- '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}-mailpit-auth,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}'
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
networks:
compose_network:
name: ${NETWORK_NAME}
external: true
coolify:
name: coolify
external: true