Add Backrest backup service and schedule Kometa to 3 AM
- Add Backrest (restic web UI) to advanced-compose.yml with Traefik labels, backing up NFS configs and local SQLite DBs to TrueNAS backup pool - Schedule Kometa to run daily at 3 AM instead of immediately on container start, avoiding IO contention with Plex streaming - Update README with Backrest in tool analysis, overview, and ports - Update CLAUDE.md with backup strategy and Kometa scheduling note
This commit is contained in:
parent
01549e4b4c
commit
39b58d5ca5
3 changed files with 172 additions and 1 deletions
131
CLAUDE.md
Normal file
131
CLAUDE.md
Normal file
|
|
@ -0,0 +1,131 @@
|
|||
# CLAUDE.md
|
||||
|
||||
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||
|
||||
## Project Overview
|
||||
|
||||
This is a Docker Compose configuration repository for setting up a comprehensive media server stack centered around Plex. It provides two compose templates:
|
||||
|
||||
- **basic-compose.yaml**: Core services (Plex, Radarr, Sonarr, Prowlarr, Overseerr, qBittorrent)
|
||||
- **advanced-compose.yml**: Extended stack with 30+ additional services (Tdarr, Tautulli, Bazarr, Lidarr, Recyclarr, Backrest, etc.)
|
||||
|
||||
This is not application code—it's infrastructure configuration meant to be forked and customized.
|
||||
|
||||
## Commands
|
||||
|
||||
```bash
|
||||
# Validate compose file syntax
|
||||
docker compose -f docker-compose.yaml config
|
||||
|
||||
# Start the stack
|
||||
docker compose up -d
|
||||
|
||||
# Stop the stack
|
||||
docker compose down
|
||||
|
||||
# View logs for a specific service
|
||||
docker compose logs -f <service-name>
|
||||
|
||||
# Restart a specific service
|
||||
docker compose restart <service-name>
|
||||
|
||||
# Pull latest images and recreate
|
||||
docker compose pull && docker compose up -d
|
||||
```
|
||||
|
||||
## Environment Variables
|
||||
|
||||
Required variables that must be set (via `.env` file or Portainer):
|
||||
|
||||
| Variable | Example | Purpose |
|
||||
|----------|---------|---------|
|
||||
| `PUID` | `99` | User ID for container permissions |
|
||||
| `GUID` | `101` | Group ID for container permissions |
|
||||
| `TZ` | `Europe/Dublin` | Timezone |
|
||||
| `BASE_PATH` | `/mnt/truenas/config` | Config directory for all services (bind mounts) |
|
||||
| `DOCKER_PATH` | `/mnt/truenas/docker` | Persistent volumes for services (generated files, cache, etc.) |
|
||||
| `MEDIA_SHARE` | `/mnt/truenas` | Root media storage path |
|
||||
| `PLEX_CLAIM` | (from plex.tv/claim) | Plex server claim token |
|
||||
|
||||
Advanced stack may require additional variables: `PLEX_URL`, `PLEX_TOKEN`, `SERVER_IP`, `SONARR_KEY`, `RADARR_KEY`, `MEMBARR_TOKEN`.
|
||||
|
||||
## Architecture Patterns
|
||||
|
||||
### Volume Mounting Strategy
|
||||
All *arr apps mount the entire `MEDIA_SHARE` to `/share` to enable hardlinking:
|
||||
```yaml
|
||||
volumes:
|
||||
- ${MEDIA_SHARE}:/share # Enables hardlinks across downloads/media
|
||||
```
|
||||
|
||||
Expected folder structure under `MEDIA_SHARE` (TrueNAS NFS mounts):
|
||||
```
|
||||
/mnt/truenas/ # MEDIA_SHARE
|
||||
├── config/ # BASE_PATH - container configs
|
||||
├── docker/ # DOCKER_PATH - persistent volumes
|
||||
├── downloads/ # Torrent/Usenet downloads
|
||||
├── movies/ # Movie library
|
||||
├── tv/ # TV shows library
|
||||
├── music/ # Music library
|
||||
└── xxx/ # Adult content library
|
||||
```
|
||||
|
||||
### Service Conventions
|
||||
- All services use LinuxServer.io images (`lscr.io/linuxserver/*`) where available
|
||||
- Restart policy: `unless-stopped` for all services
|
||||
- Config volumes: `${BASE_PATH}/<service>/config:/config`
|
||||
- Persistent data (cache, generated files): `${DOCKER_PATH}/<service>/`
|
||||
- Plex uses `network_mode: host`; other services use bridge networking
|
||||
- Hardware transcoding: `/dev/dri:/dev/dri` device mapping for Intel QuickSync
|
||||
|
||||
### Adding New Services
|
||||
When adding services, follow these patterns:
|
||||
1. Use LinuxServer.io images if available
|
||||
2. Include `PUID`, `PGID`, `TZ` environment variables
|
||||
3. Mount config to `${BASE_PATH}/<service>/config:/config`
|
||||
4. Mount persistent data (cache, generated) to `${DOCKER_PATH}/<service>/`
|
||||
5. Mount media share as `/share` if the service needs media access
|
||||
6. Use `restart: unless-stopped`
|
||||
|
||||
## Known Issues
|
||||
|
||||
### Gluetun breaks Docker image pulls
|
||||
Gluetun uses `NET_ADMIN` + `cap_add` which modifies iptables rules on the host. This causes Docker to lose connectivity to container registries (ghcr.io, lscr.io, Docker Hub CDN). The issue persists even after stopping Gluetun.
|
||||
|
||||
**Workaround — always stop Gluetun before pulling images:**
|
||||
```bash
|
||||
docker stop gluetun qbittorrent
|
||||
docker compose -f advanced-compose.yml pull
|
||||
docker compose -f advanced-compose.yml up -d
|
||||
```
|
||||
|
||||
If pulls still fail after stopping Gluetun, restart the Docker daemon:
|
||||
```bash
|
||||
sudo systemctl restart docker
|
||||
docker compose -f advanced-compose.yml up -d
|
||||
```
|
||||
|
||||
### Authelia pinned to v4.37
|
||||
Authelia v4.38+ requires HTTPS for `authelia_url` in session cookies. Since this homelab uses HTTP internally with `.homelab` domains (no TLS), Authelia is pinned to `authelia/authelia:4.37` which supports the legacy `domain` config without HTTPS.
|
||||
|
||||
### Byparr zombie processes
|
||||
Byparr spawns Camoufox/Firefox child processes that can accumulate as zombies. The `init: true` flag is set in compose to use tini as PID 1 and reap them automatically. Do not remove this flag.
|
||||
|
||||
### Kometa scheduled at 3 AM
|
||||
Kometa (`KOMETA_TIME=03:00`) runs daily at 3 AM to avoid IO contention with Plex streaming. Do not set `KOMETA_RUN=true` in production — it triggers an immediate run on container start, which can cause buffering for active Plex streams.
|
||||
|
||||
## Backup Strategy
|
||||
|
||||
Backrest (restic web UI) backs up all service configs to TrueNAS:
|
||||
|
||||
- **Source 1:** `/mnt/truenas/config/` — all NFS-hosted service configs (`/sources/truenas-config` inside container)
|
||||
- **Source 2:** `/opt/docker-configs/` — local SQLite DBs for *arr apps, Stash (`/sources/local-configs` inside container)
|
||||
- **Destination:** `/mnt/truenas/backup-appdata/` — 2TB backup pool on TrueNAS (`/repos/truenas-backups` inside container)
|
||||
- **Schedule:** Daily at 2 AM, prune weekly
|
||||
- **Retention:** 7 daily, 4 weekly, 6 monthly
|
||||
- **Management:** Web UI at https://backups.homelab
|
||||
|
||||
## External References
|
||||
|
||||
- [Trash Guides](https://trash-guides.info/) - Quality profiles and hardlink configuration
|
||||
- [Hardlinks and Instant Moves](https://trash-guides.info/Hardlinks/Hardlinks-and-Instant-Moves/) - Storage architecture guide
|
||||
|
|
@ -60,6 +60,7 @@ Everything runs behind a single `docker compose up -d` with Traefik routing `*.h
|
|||
| **IT-Tools** | :white_check_mark: | Collection of 80+ developer and networking tools in a web UI. | Keep. |
|
||||
| **Mealie** | :white_check_mark: | Recipe management with meal planning, shopping lists, and URL import. | Keep. |
|
||||
| **Actual Budget** | :white_check_mark: | Privacy-focused personal finance with envelope budgeting. Local-first, no cloud dependency. | Keep. |
|
||||
| **Backrest** | :white_check_mark: | Web UI for restic backups. Backs up all homelab configs to TrueNAS with scheduling and retention policies. | Keep. |
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -149,6 +150,7 @@ Everything runs behind a single `docker compose up -d` with Traefik routing `*.h
|
|||
- **IT-Tools:** Collection of developer and networking utilities.
|
||||
- **Mealie:** Recipe management and meal planning.
|
||||
- **Actual Budget:** Privacy-focused personal finance and budgeting.
|
||||
- **Backrest:** Web UI for restic backups — backs up all service configs with scheduling and retention.
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -262,6 +264,7 @@ To allow hardlinking to work (which you will definitely want!) you will have to
|
|||
| IT-Tools | 8085 | http://IP:8085 |
|
||||
| Mealie | 9925 | http://IP:9925 |
|
||||
| Actual Budget | 5006 | http://IP:5006 |
|
||||
| Backrest | 9898 | http://IP:9898 |
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -430,7 +430,8 @@ services:
|
|||
- TZ=${TZ}
|
||||
#- KOMETA_OVERLAYS_ONLY=true #Tells Kometa to run overlays only
|
||||
- KOMETA_CONFIG=/config/config.yml
|
||||
- KOMETA_RUN=true #Runs Kometa Immediately
|
||||
- KOMETA_TIME=03:00 #Runs daily at 3 AM
|
||||
#- KOMETA_RUN=true #Runs Kometa immediately (use for one-off manual runs)
|
||||
#- KOMETA_RUN_LIBRARIES=Movies #Tells Kometa to process only a library called "Movies"
|
||||
volumes:
|
||||
- ${BASE_PATH}/kometa/config:/config
|
||||
|
|
@ -976,6 +977,42 @@ services:
|
|||
- "traefik.http.services.mealie.loadbalancer.server.port=9000"
|
||||
restart: unless-stopped
|
||||
|
||||
# ============================================
|
||||
# BACKUP & RECOVERY
|
||||
# ============================================
|
||||
|
||||
#Backrest - Web UI for restic backups
|
||||
#
|
||||
#Backs up all homelab configs (NFS + local SQLite DBs) to TrueNAS
|
||||
#First run: Access https://backups.homelab to create admin account
|
||||
#https://github.com/garethgeorge/backrest
|
||||
backrest:
|
||||
image: ghcr.io/garethgeorge/backrest:latest
|
||||
container_name: backrest
|
||||
environment:
|
||||
- TZ=${TZ}
|
||||
- BACKREST_DATA=/data
|
||||
- BACKREST_CONFIG=/config/config.json
|
||||
- XDG_CACHE_HOME=/cache
|
||||
volumes:
|
||||
- ${BASE_PATH}/backrest/data:/data
|
||||
- ${BASE_PATH}/backrest/config:/config
|
||||
- ${BASE_PATH}/backrest/cache:/cache
|
||||
- /mnt/truenas/config:/sources/truenas-config:ro
|
||||
- /opt/docker-configs:/sources/local-configs:ro
|
||||
- /mnt/truenas/backup-appdata:/repos/truenas-backups
|
||||
networks:
|
||||
- proxy
|
||||
ports:
|
||||
- 9898:9898
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.backrest.rule=Host(`backups.homelab`)"
|
||||
- "traefik.http.routers.backrest.entrypoints=websecure"
|
||||
- "traefik.http.routers.backrest.tls=true"
|
||||
- "traefik.http.services.backrest.loadbalancer.server.port=9898"
|
||||
restart: unless-stopped
|
||||
|
||||
#Actual Budget - Personal finance and budgeting (YNAB alternative)
|
||||
#
|
||||
#Local-first architecture, works offline, syncs across devices
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue