Architecture changes: - Created VM 100 "docker-services" (Debian 12 Cloud Image) - 10GB RAM, 6 Cores, 50GB system disk - Separate 100GB LVM data volume for service data - WireGuard moved from host to VM (10.0.0.2) - All containers migrated and running Updated documentation to reflect new architecture 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
314 lines
7.8 KiB
YAML
314 lines
7.8 KiB
YAML
services:
|
|
# ============================================
|
|
# NEXTCLOUD - Cloud Storage
|
|
# ============================================
|
|
nextcloud:
|
|
image: nextcloud:latest
|
|
container_name: nextcloud
|
|
restart: unless-stopped
|
|
security_opt:
|
|
- apparmor=unconfined
|
|
- seccomp=unconfined
|
|
ports:
|
|
- "8081:80"
|
|
volumes:
|
|
- /opt/docker/nextcloud/data:/var/www/html
|
|
environment:
|
|
- MYSQL_HOST=nextcloud-db
|
|
- MYSQL_DATABASE=nextcloud
|
|
- MYSQL_USER=nextcloud
|
|
- MYSQL_PASSWORD=${NEXTCLOUD_DB_PASSWORD}
|
|
depends_on:
|
|
nextcloud-db:
|
|
condition: service_healthy
|
|
healthcheck:
|
|
test: ["CMD", "curl", "-f", "http://localhost/status.php"]
|
|
interval: 30s
|
|
timeout: 10s
|
|
retries: 3
|
|
start_period: 60s
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
cpus: '2.0'
|
|
memory: 2G
|
|
logging:
|
|
driver: "json-file"
|
|
options:
|
|
max-size: "10m"
|
|
max-file: "3"
|
|
networks:
|
|
- nextcloud-net
|
|
|
|
nextcloud-db:
|
|
image: mariadb:10
|
|
container_name: nextcloud-db
|
|
restart: unless-stopped
|
|
security_opt:
|
|
- apparmor=unconfined
|
|
- seccomp=unconfined
|
|
volumes:
|
|
- /opt/docker/nextcloud/db:/var/lib/mysql
|
|
environment:
|
|
- MYSQL_ROOT_PASSWORD=${NEXTCLOUD_DB_ROOT_PASSWORD}
|
|
- MYSQL_DATABASE=nextcloud
|
|
- MYSQL_USER=nextcloud
|
|
- MYSQL_PASSWORD=${NEXTCLOUD_DB_PASSWORD}
|
|
healthcheck:
|
|
test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
|
|
interval: 30s
|
|
timeout: 10s
|
|
retries: 3
|
|
start_period: 30s
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
cpus: '1.0'
|
|
memory: 1G
|
|
logging:
|
|
driver: "json-file"
|
|
options:
|
|
max-size: "10m"
|
|
max-file: "3"
|
|
networks:
|
|
- nextcloud-net
|
|
|
|
# ============================================
|
|
# VAULTWARDEN - Password Manager
|
|
# ============================================
|
|
vaultwarden:
|
|
image: vaultwarden/server:latest
|
|
container_name: vaultwarden
|
|
restart: unless-stopped
|
|
security_opt:
|
|
- apparmor=unconfined
|
|
- seccomp=unconfined
|
|
ports:
|
|
- "8083:80"
|
|
volumes:
|
|
- /opt/docker/vaultwarden:/data
|
|
environment:
|
|
- ADMIN_TOKEN=${VAULTWARDEN_ADMIN_TOKEN}
|
|
- SIGNUPS_ALLOWED=false
|
|
- INVITATIONS_ALLOWED=true
|
|
- SHOW_PASSWORD_HINT=false
|
|
healthcheck:
|
|
test: ["CMD", "curl", "-f", "http://localhost/alive"]
|
|
interval: 30s
|
|
timeout: 10s
|
|
retries: 3
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
cpus: '0.5'
|
|
memory: 256M
|
|
logging:
|
|
driver: "json-file"
|
|
options:
|
|
max-size: "10m"
|
|
max-file: "3"
|
|
networks:
|
|
- vaultwarden-net
|
|
|
|
# ============================================
|
|
# N8N - Workflow Automation
|
|
# ============================================
|
|
n8n:
|
|
image: n8nio/n8n:latest
|
|
container_name: n8n
|
|
restart: unless-stopped
|
|
security_opt:
|
|
- apparmor=unconfined
|
|
- seccomp=unconfined
|
|
ports:
|
|
- "5678:5678"
|
|
volumes:
|
|
- /opt/docker/n8n:/home/node/.n8n
|
|
environment:
|
|
- N8N_BASIC_AUTH_ACTIVE=true
|
|
- N8N_BASIC_AUTH_USER=${N8N_USER}
|
|
- N8N_BASIC_AUTH_PASSWORD=${N8N_PASSWORD}
|
|
- N8N_PATH=/n8n/
|
|
- N8N_EDITOR_BASE_URL=https://eckardt-vault.duckdns.org/n8n/
|
|
- WEBHOOK_URL=https://eckardt-vault.duckdns.org/n8n/
|
|
healthcheck:
|
|
test: ["CMD", "wget", "-q", "--spider", "http://localhost:5678/healthz"]
|
|
interval: 30s
|
|
timeout: 10s
|
|
retries: 3
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
cpus: '1.0'
|
|
memory: 1G
|
|
logging:
|
|
driver: "json-file"
|
|
options:
|
|
max-size: "10m"
|
|
max-file: "3"
|
|
networks:
|
|
- n8n-net
|
|
|
|
# ============================================
|
|
# AUDIOBOOKSHELF - Audiobook Server
|
|
# ============================================
|
|
audiobookshelf:
|
|
image: ghcr.io/advplyr/audiobookshelf:latest
|
|
container_name: audiobookshelf
|
|
restart: unless-stopped
|
|
security_opt:
|
|
- apparmor=unconfined
|
|
- seccomp=unconfined
|
|
ports:
|
|
- "13378:80"
|
|
volumes:
|
|
- /opt/docker/audiobookshelf/audiobooks:/audiobooks
|
|
- /opt/docker/audiobookshelf/podcasts:/podcasts
|
|
- /opt/docker/audiobookshelf/config:/config
|
|
- /opt/docker/audiobookshelf/metadata:/metadata
|
|
healthcheck:
|
|
test: ["CMD", "wget", "-q", "--spider", "http://localhost:80/healthcheck"]
|
|
interval: 30s
|
|
timeout: 10s
|
|
retries: 3
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
cpus: '1.0'
|
|
memory: 512M
|
|
logging:
|
|
driver: "json-file"
|
|
options:
|
|
max-size: "10m"
|
|
max-file: "3"
|
|
networks:
|
|
- audiobookshelf-net
|
|
|
|
# ============================================
|
|
# WEBSITES - Static Website Hosting
|
|
# ============================================
|
|
websites:
|
|
image: nginx:alpine
|
|
container_name: websites
|
|
restart: unless-stopped
|
|
security_opt:
|
|
- apparmor=unconfined
|
|
- seccomp=unconfined
|
|
ports:
|
|
- "8082:80"
|
|
volumes:
|
|
- /opt/docker/websites/html:/usr/share/nginx/html:ro
|
|
- /opt/docker/websites/conf:/etc/nginx/conf.d:ro
|
|
healthcheck:
|
|
test: ["CMD", "wget", "-q", "--spider", "http://localhost/"]
|
|
interval: 30s
|
|
timeout: 10s
|
|
retries: 3
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
cpus: '0.5'
|
|
memory: 128M
|
|
logging:
|
|
driver: "json-file"
|
|
options:
|
|
max-size: "10m"
|
|
max-file: "3"
|
|
networks:
|
|
- websites-net
|
|
|
|
# ============================================
|
|
# SAMSUNG TV API - Smart TV Steuerung
|
|
# ============================================
|
|
samsung-tv-api:
|
|
build:
|
|
context: ./samsung-tv-api
|
|
dockerfile: Dockerfile
|
|
container_name: samsung-tv-api
|
|
restart: unless-stopped
|
|
security_opt:
|
|
- apparmor=unconfined
|
|
- seccomp=unconfined
|
|
ports:
|
|
- "5050:5000"
|
|
volumes:
|
|
- /opt/docker/samsung-tv-api:/data
|
|
environment:
|
|
- SAMSUNG_TV_IP=${SAMSUNG_TV_IP:-192.168.178.100}
|
|
- SAMSUNG_TV_MAC=${SAMSUNG_TV_MAC:-}
|
|
- SAMSUNG_TV_NAME=n8n-proxmox
|
|
- SAMSUNG_TV_PORT=8002
|
|
- SAMSUNG_TV_TOKEN_FILE=/data/tv-token.txt
|
|
healthcheck:
|
|
test: ["CMD", "curl", "-f", "http://localhost:5000/health"]
|
|
interval: 30s
|
|
timeout: 10s
|
|
retries: 3
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
cpus: '0.5'
|
|
memory: 128M
|
|
logging:
|
|
driver: "json-file"
|
|
options:
|
|
max-size: "10m"
|
|
max-file: "3"
|
|
networks:
|
|
- samsung-tv-net
|
|
- n8n-net # Damit n8n direkt zugreifen kann
|
|
|
|
# ============================================
|
|
# API - FastAPI Backend
|
|
# ============================================
|
|
api:
|
|
image: python:3.11-slim
|
|
container_name: api-server
|
|
restart: unless-stopped
|
|
security_opt:
|
|
- apparmor=unconfined
|
|
- seccomp=unconfined
|
|
working_dir: /app
|
|
ports:
|
|
- "8000:8000"
|
|
volumes:
|
|
- /opt/docker/api:/app
|
|
command: sh -c "pip install --quiet fastapi uvicorn httpx && python -m uvicorn main:app --host 0.0.0.0 --port 8000"
|
|
healthcheck:
|
|
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
|
|
interval: 30s
|
|
timeout: 10s
|
|
retries: 3
|
|
start_period: 30s
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
cpus: '1.0'
|
|
memory: 512M
|
|
logging:
|
|
driver: "json-file"
|
|
options:
|
|
max-size: "10m"
|
|
max-file: "3"
|
|
networks:
|
|
- api-net
|
|
|
|
# ============================================
|
|
# NETWORKS - Isolierte Netzwerke pro Service
|
|
# ============================================
|
|
networks:
|
|
nextcloud-net:
|
|
driver: bridge
|
|
vaultwarden-net:
|
|
driver: bridge
|
|
n8n-net:
|
|
driver: bridge
|
|
audiobookshelf-net:
|
|
driver: bridge
|
|
websites-net:
|
|
driver: bridge
|
|
api-net:
|
|
driver: bridge
|
|
samsung-tv-net:
|
|
driver: bridge
|