Files
serverconfig/docker-compose.yml

235 lines
6.9 KiB
YAML

volumes:
ssl-data: { name: ssl }
wireguard-data: { name: wireguard }
portainer-data: { name: portainer }
gitea-mirror-data: { name: gitea_mirror }
networks:
# Secured internal bridge for read-only and read-write
# Docker socket access
socket-ro-bridge: { name: socket_ro_bridge, internal: true }
socket-rw-bridge: { name: socket_rw_bridge, internal: true }
# Public-facing network for Nginx Proxy and web services
web-network:
name: web_network
enable_ipv6: true
services:
# Read-Only Proxy: Restricts access to metadata only (GET requests)
socket-ro:
container_name: socket-ro
image: lscr.io/linuxserver/socket-proxy:latest
environment:
- CONTAINERS=1 # Monitor container status
- EVENTS=1 # Real-time discovery
- IMAGES=1 # View image info
- INFO=1 # Engine info
- NETWORKS=1 # Network mapping
- PING=1 # Connectivity check
- SYSTEM=1 # System metadata
- VOLUMES=1 # Volume inspection
- LOG_LEVEL=info
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
networks:
- socket-ro-bridge
# Read-Write Proxy: Allows modifications (POST/EXEC) for administrative tasks
socket-rw:
container_name: socket-rw
image: lscr.io/linuxserver/socket-proxy:latest
environment:
- CONTAINERS=1
- EVENTS=1
- EXEC=1 # Required for triggering tasks inside containers
- IMAGES=1
- INFO=1
- NETWORKS=1
- PING=1
- POST=1 # Allows container start/stop/restart
- SYSTEM=1
- VOLUMES=1
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
networks:
- socket-rw-bridge
# Automated Volume Backups: Daily S3 sync with container pausing
backup:
container_name: backup
image: offen/docker-volume-backup
restart: unless-stopped
environment:
AWS_S3_BUCKET_NAME: ${AWS}
AWS_ENDPOINT: ${ENDPOINT}
AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID}
AWS_SECRET_ACCESS_KEY: ${AWS_SECRET_ACCESS_KEY}
BACKUP_CRON_EXPRESSION: "0 0 * * *"
BACKUP_RETENTION_DAYS: 3
DOCKER_HOST: tcp://socket-rw:2375 # Uses RW proxy to pause containers during backup
volumes:
- wireguard-data:/backup/wireguard:ro
- ./data/synapse:/backup/synapse:ro
- ssl-data:/backup/ssl:ro
- ./data/backup:/archive
networks:
- socket-rw-bridge
- web-network
# Automated Nginx Reverse Proxy: Routes traffic based on VIRTUAL_HOST labels
nginx-proxy:
image: nginxproxy/nginx-proxy:alpine
container_name: nginx-proxy
restart: unless-stopped
ports:
- "80:80"
- "443:443"
environment:
- DOCKER_HOST=tcp://socket-ro:2375 # Discovers containers via RO proxy
- ENABLE_IPV6=true
volumes:
- ssl-data:/etc/nginx/certs:ro
- ./data/nginx/default_html:/usr/share/nginx/html
- ./data/nginx/vhost.d:/etc/nginx/vhost.d
labels:
- "docker-volume-backup.stop-during-backup=true" # Ensure consistency during backup
depends_on:
- socket-ro
networks:
- socket-ro-bridge
- web-network
# ACME Companion: Automated Let's Encrypt certificate issuance/renewal
acme-companion:
image: nginxproxy/acme-companion
container_name: acme-companion
restart: unless-stopped
environment:
- DEFAULT_EMAIL=${EMAIL}
- NGINX_PROXY_CONTAINER=nginx-proxy
- DOCKER_HOST=tcp://socket-rw:2375 # Needs RW to restart Nginx after renewal
volumes:
- ssl-data:/etc/nginx/certs
- ./data/nginx/vhost.d:/etc/nginx/vhost.d
- ./data/nginx/default_html:/usr/share/nginx/html
- ./data/nginx/acme_config:/etc/acme.sh
labels:
- "docker-volume-backup.stop-during-backup=true"
depends_on:
- nginx-proxy
networks:
- socket-rw-bridge
- web-network
# Main Portfolio/Website: Built from local repository
# website:
# container_name: web
# # Reference to your internal Gitea registry
# image: // self website repo
# restart: unless-stopped
# environment:
# - VIRTUAL_HOST=${HOSTNAME}, www.${HOSTNAME}
# - LETSENCRYPT_HOST=${HOSTNAME}, www.${HOSTNAME}
# - LETSENCRYPT_EMAIL=${EMAIL}
# volumes:
# - /data/public:/usr/share/nginx/html/data
# networks:
# - web-network
# Portainer: Web UI for container and stack management
portainer:
container_name: portainer
image: portainer/portainer-ce:lts
restart: unless-stopped
environment:
- VIRTUAL_HOST=mtr.${HOSTNAME}
- LETSENCRYPT_HOST=mtr.${HOSTNAME}
- LETSENCRYPT_EMAIL=${EMAIL}
- VIRTUAL_PORT=9000
- DOCKER_HOST=socket-ro:2375 # Securely monitor engine via RO proxy
volumes:
- portainer-data:/data
networks:
- web-network
- socket-ro-bridge
# WireGuard VPN: Secure remote access with Web UI (wg-easy)
wg-easy:
image: ghcr.io/wg-easy/wg-easy:15
container_name: wg-easy
restart: unless-stopped
cap_add:
- NET_ADMIN
- SYS_MODULE
sysctls:
- net.ipv4.ip_forward=1
- net.ipv6.conf.all.disable_ipv6=0
environment:
- TZ=Europe/Paris
- VIRTUAL_HOST=vpn.${HOSTNAME}
- LETSENCRYPT_HOST=vpn.${HOSTNAME}
- LETSENCRYPT_EMAIL=${EMAIL}
- VIRTUAL_PORT=51821
volumes:
- wireguard-data:/etc/wireguard
- /lib/modules:/lib/modules:ro
ports:
- "51820:51820/udp"
labels:
- "docker-volume-backup.stop-during-backup=true"
networks:
- web-network
# Synapse: Matrix homeserver for decentralized communication
synapse:
image: matrixdotorg/synapse:latest
container_name: synapse
restart: unless-stopped
volumes:
- ./data/synapse:/data
environment:
- SYNAPSE_CONFIG_PATH=/data/homeserver.yaml
- VIRTUAL_HOST=msg.${HOSTNAME}
- LETSENCRYPT_HOST=msg.${HOSTNAME}
- LETSENCRYPT_EMAIL=${EMAIL}
- VIRTUAL_PORT=8008
networks:
- web-network
# Gitea: Self-hosted Git forge (Lightweight alternative to GitHub)
gitea:
image: gitea/gitea:latest
container_name: gitea
restart: unless-stopped
environment:
- VIRTUAL_HOST=git.${HOSTNAME}
- LETSENCRYPT_HOST=git.${HOSTNAME}
- LETSENCRYPT_EMAIL=${EMAIL}
- VIRTUAL_PORT=3000
- GITEA__server__DOMAIN=git.${HOSTNAME}
- GITEA__server__ROOT_URL=https://git.${HOSTNAME}/
- DISABLE_REGISTRATION=true # Private instance security
volumes:
- ./data/gitea:/data
- /etc/localtime:/etc/localtime:ro
ports:
- "222:22" # SSH port mapping for Git operations
networks:
- web-network
# Gitea Mirror: Repository synchronization and backup tool
gitea-mirror:
image: ghcr.io/raylabshq/gitea-mirror:latest
container_name: gitea-mirror
restart: unless-stopped
environment:
- VIRTUAL_HOST=mirror.${HOSTNAME}
- LETSENCRYPT_HOST=mirror.${HOSTNAME}
- LETSENCRYPT_EMAIL=${EMAIL}
- VIRTUAL_PORT=4321
- BETTER_AUTH_SECRET=${GITHUB_AUTH_SECRET}
volumes:
- gitea-mirror-data:/app/data
networks:
- web-network