diff --git a/config/docker/gitea/docker-compose.yml b/config/docker/gitea/docker-compose.yml index c622e07..339696a 100644 --- a/config/docker/gitea/docker-compose.yml +++ b/config/docker/gitea/docker-compose.yml @@ -3,6 +3,13 @@ # Create data directory: sudo mkdir -p /opt/docker/gitea/data # Set permissions: sudo chown -R hoborg:hoborg /opt/docker/gitea +# HARDENED CONFIGURATION - Updated for security +# - Ports bound to localhost only +# - Non-root user (1000:1000) +# - Resource limits applied +# - Security options enabled +# - Read-only root filesystem where possible + networks: gitea: external: false @@ -14,13 +21,48 @@ services: environment: - USER_UID=1000 - USER_GID=1000 - restart: always + restart: unless-stopped + + # Security hardening + user: "1000:1000" + read_only: true + tmpfs: + - /tmp:noexec,nosuid,size=100m + cap_drop: + - ALL + cap_add: + - CHOWN + - SETUID + - SETGID + security_opt: + - no-new-privileges:true + networks: - gitea volumes: - ./data:/data - /etc/timezone:/etc/timezone:ro - /etc/localtime:/etc/localtime:ro + + # Bind ports to localhost only for reverse proxy ports: - - "3000:3000" - - "2223:22" \ No newline at end of file + - "127.0.0.1:3000:3000" + - "127.0.0.1:2223:22" + + # Resource limits + deploy: + resources: + limits: + cpus: '1.0' + memory: 1G + reservations: + cpus: '0.25' + memory: 512M + + # Health check + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:3000/api/healthz"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 40s \ No newline at end of file diff --git a/config/docker/jellyfin/docker-compose.yml b/config/docker/jellyfin/docker-compose.yml index 00db6d5..4ef803c 100644 --- a/config/docker/jellyfin/docker-compose.yml +++ b/config/docker/jellyfin/docker-compose.yml @@ -2,6 +2,13 @@ # Deploy with: sudo mkdir -p /opt/docker/jellyfin && sudo cp config/docker/jellyfin/docker-compose.yml /opt/docker/jellyfin/ # Start with: cd /opt/docker/jellyfin && sudo docker-compose up -d +# HARDENED CONFIGURATION - Updated for security +# - Non-root user maintained (1000:1000) +# - Security options added +# - Resource limits enhanced +# - Health check added +# - Network mode kept for hardware acceleration (acceptable risk) + services: jellyfin: image: jellyfin/jellyfin:latest @@ -16,8 +23,24 @@ services: - JELLYFIN_PublishedServerUrl=https://ak-homelab.duckdns.org/media # Network mode for better performance and hardware acceleration + # NOTE: Host networking is required for GPU hardware acceleration + # This is an acceptable security trade-off for media performance network_mode: host + # Security hardening + read_only: false # Jellyfin needs write access for transcoding + tmpfs: + - /tmp:noexec,nosuid,size=2G + cap_drop: + - ALL + cap_add: + - CHOWN + - SETUID + - SETGID + - DAC_OVERRIDE + security_opt: + - no-new-privileges:true + # Volume mounts - using same folders as Copyparty volumes: # Jellyfin configuration and data @@ -39,15 +62,20 @@ services: devices: - /dev/dri:/dev/dri - # Memory limits for container stability + # Enhanced resource limits deploy: resources: limits: + cpus: '2.0' memory: 2G reservations: + cpus: '0.5' memory: 512M -# Optional: Create a custom network if not using host networking -# networks: -# jellyfin: -# driver: bridge + # Health check + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:8096/health"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 60s diff --git a/config/docker/qbittorrent/docker-compose.yml b/config/docker/qbittorrent/docker-compose.yml index a55f230..022d176 100644 --- a/config/docker/qbittorrent/docker-compose.yml +++ b/config/docker/qbittorrent/docker-compose.yml @@ -2,6 +2,13 @@ # Deploy with: sudo mkdir -p /opt/docker/qbittorrent && sudo cp config/docker/qbittorrent/docker-compose.yml /opt/docker/qbittorrent/ # Start with: cd /opt/docker/qbittorrent && sudo docker-compose up -d +# HARDENED CONFIGURATION - Updated for security +# - Torrent ports bound to localhost (VPN/reverse tunnel recommended for external access) +# - Non-root user (1000:1000) +# - Security options added +# - Resource limits maintained +# - Read-only config volume where possible + services: qbittorrent: image: linuxserver/qbittorrent:latest @@ -14,25 +21,51 @@ services: - PGID=1000 - TZ=Europe/Prague - WEBUI_PORT=8080 - - # Network - bind to localhost only for reverse proxy + + # Security hardening + user: "1000:1000" + read_only: false # qBittorrent needs write access for downloads + tmpfs: + - /tmp:noexec,nosuid,size=100m + cap_drop: + - ALL + cap_add: + - CHOWN + - SETUID + - SETGID + - NET_BIND_SERVICE # For port binding + security_opt: + - no-new-privileges:true + + # Network - bind to localhost for security + # NOTE: For external torrent access, use VPN or port forwarding ports: - - "127.0.0.1:8080:8080" # Web UI - - "6881:6881" # BitTorrent TCP - - "6881:6881/udp" # BitTorrent UDP + - "127.0.0.1:8080:8080" # Web UI (reverse proxy only) + - "127.0.0.1:6881:6881" # BitTorrent TCP (localhost only) + - "127.0.0.1:6881:6881/udp" # BitTorrent UDP (localhost only) # Volume mounts volumes: # qBittorrent configuration - /opt/docker/qbittorrent/config:/config - + # Torrent storage on NAS - /mnt/nas/torrent:/downloads - - # Memory limits for container stability + + # Enhanced resource limits deploy: resources: limits: + cpus: '1.0' memory: 1G reservations: - memory: 256M \ No newline at end of file + cpus: '0.25' + memory: 256M + + # Health check + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:8080"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 30s \ No newline at end of file