diff --git a/CLAUDE.md b/CLAUDE.md index 8f23e02..aa53678 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -41,8 +41,8 @@ docker compose down - **Local NVME** (/usr/local/plex, /tmp/plex_transcode): High-performance storage for Plex transcoding ### Service Categories -- **Infrastructure**: Traefik, Docker Socket Proxy, Authelia, Portainer, Docker-GC -- **Media**: Plex (GPU-enabled), Sonarr, Radarr, Bazarr, SABnzbd, NZBHydra2 +- **Infrastructure**: Traefik, Docker Socket Proxy, Authelia, Portainer, Task Scheduler +- **Media**: Plex (LinuxServer.io, GPU-enabled), Sonarr, Radarr, Bazarr, SABnzbd, NZBHydra2 - **Books**: Calibre-Web, Lazy Librarian - **DNS/Ad-blocking**: Pi-hole (port 53) - **Home Automation**: Home Assistant (privileged, host network) @@ -54,7 +54,7 @@ docker compose down - `env.example` - Required environment variables template (copy to `.env`) - `acme/acme.json` - Let's Encrypt certificates (Traefik managed) - `pihole/` - Pi-hole DNS configuration -- `docker-gc/` - Garbage collection exclusion rules +- `task-scheduler/` - Scheduled maintenance tasks (Docker cleanup, Plex restart) ## Environment Variables @@ -162,6 +162,9 @@ git push -u origin feature-branch-name ## Notes - Pi-hole runs on host port 53 - may conflict with systemd-resolved -- Plex uses `/dev/dri` for GPU transcoding +- Plex uses LinuxServer.io image (`lscr.io/linuxserver/plex`) with `/dev/dri` for GPU transcoding +- Plex uses `VERSION=public` for auto-updates on container restart - Home Assistant runs privileged with host network for device access -- Docker-GC runs daily at midnight with 7-day grace period +- Task Scheduler runs scheduled maintenance: + - Daily at midnight: Docker cleanup (prune images/containers/volumes older than 7 days) + - Sunday at 3 AM: Plex restart (picks up VERSION=public updates) diff --git a/docker-compose.yml b/docker-compose.yml index c79cf57..f9a2dda 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -342,11 +342,12 @@ services: - "traefik.http.routers.portainer-rtr.service=portainer-svc" - "traefik.http.services.portainer-svc.loadbalancer.server.port=9000" - # Docker-GC - Automatic Docker Garbage Collection - # Runs daily at midnight, removes images/containers/volumes older than 7 days - dockergc: - build: $LOCALDOCKERDIR/docker-gc - container_name: dockergc + # Task Scheduler - Scheduled maintenance tasks + # - Daily at midnight: Docker cleanup (prune images/containers/volumes older than 7 days) + # - Sunday at 3 AM: Plex restart (picks up VERSION=public updates) + task-scheduler: + build: $LOCALDOCKERDIR/task-scheduler + container_name: task-scheduler restart: unless-stopped networks: - socket_proxy @@ -408,17 +409,15 @@ services: # Plex - Media Server plex: container_name: plex - # image: mauimauer/plex # This was an attempt to get HW transcoding working with Ryzen - # image: lscr.io/linuxserver/plex:latest - image: plexinc/pms-docker:plexpass + image: lscr.io/linuxserver/plex:latest restart: unless-stopped networks: - t2_proxy - # security_opt: - # - no-new-privileges:true + security_opt: + - no-new-privileges:true volumes: - - /usr/local/plex:/config # moving to NVME to see if I can get it to go faster - - /tmp/plex_transcode:/transcode # moving transcoder to NVME also, need to monitor for size and then move to ram disk + - /usr/local/plex:/config # NVME for performance + - /tmp/plex_transcode:/transcode # NVME for transcode performance - video:/video - audiobooks:/audiobooks - music:/music @@ -427,20 +426,18 @@ services: - PGID=$PGID - TZ=$TZ - VERSION=public - - PLEX_CLAIM=claim-pKLhV-iyXUFtWX-3Vw3Y devices: - /dev/dri:/dev/dri ports: - - 32469:32469 - - 32400:32400 - - 32401:32401 - - 3005:3005 - - 8324:8324 - # - 1900:1900/udp # This is the SSDP / DNLA port. Currently conflicts with HomeAssistant. If they are moved to different VM's then I can re-enable this - - 32410:32410/udp - - 32412:32412/udp - - 32413:32413/udp - - 32414:32414/udp + - 32400:32400 # Main Plex port (required) + - 3005:3005 # Plex Companion + - 8324:8324 # Roku/Plex Companion + # - 1900:1900/udp # SSDP/DLNA - conflicts with HomeAssistant + - 32410:32410/udp # GDM network discovery + - 32412:32412/udp # GDM network discovery + - 32413:32413/udp # GDM network discovery + - 32414:32414/udp # GDM network discovery + - 32469:32469 # DLNA server logging: *default-logging labels: - "traefik.enable=true" diff --git a/task-scheduler/Dockerfile b/task-scheduler/Dockerfile new file mode 100644 index 0000000..3ac00d7 --- /dev/null +++ b/task-scheduler/Dockerfile @@ -0,0 +1,31 @@ +FROM docker:cli + +# Install dcron (Alpine's cron daemon) +RUN apk add --no-cache dcron + +# Copy task scripts +COPY scripts/ /usr/local/bin/ +RUN chmod +x /usr/local/bin/*.sh + +# Create crontab file +# Daily at midnight: Docker cleanup +# Sunday at 3 AM: Plex restart (for VERSION=public to pick up updates) +RUN echo "0 0 * * * /usr/local/bin/docker-cleanup.sh >> /var/log/tasks.log 2>&1" > /etc/crontabs/root && \ + echo "0 3 * * 0 /usr/local/bin/plex-restart.sh >> /var/log/tasks.log 2>&1" >> /etc/crontabs/root + +# Create log file +RUN touch /var/log/tasks.log + +# Create entrypoint script +RUN echo '#!/bin/sh' > /entrypoint.sh && \ + echo 'echo "Task scheduler started."' >> /entrypoint.sh && \ + echo 'echo "DOCKER_HOST: $DOCKER_HOST"' >> /entrypoint.sh && \ + echo 'echo "Scheduled tasks:"' >> /entrypoint.sh && \ + echo 'cat /etc/crontabs/root' >> /entrypoint.sh && \ + echo '# Run cleanup once on startup' >> /entrypoint.sh && \ + echo '/usr/local/bin/docker-cleanup.sh' >> /entrypoint.sh && \ + echo '# Start cron in foreground' >> /entrypoint.sh && \ + echo 'crond -f -l 2' >> /entrypoint.sh && \ + chmod +x /entrypoint.sh + +ENTRYPOINT ["/entrypoint.sh"] diff --git a/task-scheduler/scripts/docker-cleanup.sh b/task-scheduler/scripts/docker-cleanup.sh new file mode 100644 index 0000000..2ffa1f8 --- /dev/null +++ b/task-scheduler/scripts/docker-cleanup.sh @@ -0,0 +1,26 @@ +#!/bin/sh +# Docker cleanup script using native Docker prune commands + +echo "[$(date)] Starting Docker cleanup..." + +# Remove unused containers older than 7 days (604800 seconds) +echo "Pruning containers..." +docker container prune -f --filter "until=168h" + +# Remove unused images older than 7 days +echo "Pruning images..." +docker image prune -a -f --filter "until=168h" + +# Remove unused volumes +echo "Pruning volumes..." +docker volume prune -f + +# Remove unused networks +echo "Pruning networks..." +docker network prune -f + +# Show disk usage after cleanup +echo "Docker disk usage after cleanup:" +docker system df + +echo "[$(date)] Docker cleanup complete." diff --git a/task-scheduler/scripts/plex-restart.sh b/task-scheduler/scripts/plex-restart.sh new file mode 100644 index 0000000..f184c20 --- /dev/null +++ b/task-scheduler/scripts/plex-restart.sh @@ -0,0 +1,12 @@ +#!/bin/sh +# Plex restart script +# Restarts Plex to pick up updates when using VERSION=public + +echo "[$(date)] Restarting Plex container..." + +if docker restart plex; then + echo "[$(date)] Plex container restarted successfully." +else + echo "[$(date)] ERROR: Failed to restart Plex container." + exit 1 +fi