Objectif¶
Mettre en place un serveur de stockage et de services divers à la maison en réemployant un PC inutilisé.
- Jellyfin / Radarr / Sonarr / Usenet
- Archivage de données
- Accès réseau local
En second temps :
- Accès à distance à Jellyfin et aux données archivées
- Hébergement d'applications persos / tests de développement (Git, Node.js)
- Hébergement d'applications en production (site web, blog, base de données, ex. Umami...)
- Interface de gestion des services
Materiel disponible¶
PC inutilisé avec les caractéristiques suivantes :
CPU: Intel Core i7 2600 3.4GHz GPU: PNY GeForce GTX 970 4Go MBD: Asus P8P67 LE Rev 3.0 (Révision B3) RAM: 16Go Crucial Ballistix Sport (2x8Go) DDR3 1600CL9 1.5V RAM: 16Go Crucial Ballistix Sport (2x8Go) DDR3 1600CL9 1.5V SSD: Samsung EVO 850 MZ-75E250B/EU 250 Go SATA III (Windows 10) SSD: Samsung EVO 850 MZ-75E250B/EU 250 Go SATA III (pas de données à conserver) HDD: Western Digital Caviar Green S-ATA - 1 To - 64 Mo (pas de données à conserver) HDD: Hitachi - Ultrastar 7K4000 4TB 3.5" 7200RPM (contiens Environ 1Tb d'archives à conserver) VRD: Ventirad Noctua avec 2xNF-P12 120 mm PSU: Seasonic M12II 82+ - 520W CAS: Lian Li PC-A05N DVD: Samsung SH-222AB
Disques inutilisés :
- 1 x WD Caviar Green 1To SATA2 7200trs/m 32Mo 3 plateaux
- 1 x HGST Touro mobile 1To (2.5" externe, boitier USB3)
- 1 x Maxtor M3 portable 4To (2.5" externe, boitier USB3)
L'achat de matériel supplémentaire est envisageable si nécessaire.
Le serveur sera connecté en Ethernet Gigabit à la box.
Système d'exploitation¶
Ubuntu server ? TrueNAS ? Proxmox ?
COMPREHENSIVE RESEARCH & RECOMMENDATIONS (2026)¶
Executive Summary¶
Recommended Setup:
- OS: Proxmox VE (virtualization platform)
- Storage: ZFS on 4TB for data protection, ext4 on SSDs for apps
- Services: Docker containers in LXC containers
- GPU: Intel iGPU (HD 2000) for transcoding (power efficient)
- Remote Access: Tailscale (secure mesh VPN)
- Backups: Local USB 4TB + cloud (Backblaze B2)
- Management: Portainer + Homepage dashboard
Annual Costs: ~€85/year (electricity + backup storage) Setup Time: 4 weeks to full deployment Difficulty: Intermediate (good documentation available)
1. Platform Comparison: Ubuntu Server vs TrueNAS vs Proxmox¶
Proxmox VE ⭐ RECOMMENDED¶
Why Proxmox wins for your use case:
- Run both VMs and LXC containers (flexibility)
- Start with Docker services, add VMs later (Windows, dev environments)
- Built-in web GUI (no SSH required for most tasks)
- ZFS support with excellent snapshot tools
- GPU passthrough well-documented for Jellyfin
- Free and open source, all enterprise features included
- Huge homelab community (r/homelab, r/proxmox)
Setup:
- Install on Samsung EVO 250GB #1
- Create LXC containers for services (lightweight)
- Reserve second SSD for VM/container storage
- Use ZFS on 4TB HDD for media
Resource usage: ~2GB RAM for host, rest available for containers
Ubuntu Server¶
Pros: Simplest setup, minimal overhead, huge community Cons: Less flexible (no easy VM isolation), harder to migrate services later, all services share kernel
Best for: Users who only need Docker, comfortable with CLI, won't need VMs
TrueNAS SCALE¶
Pros: Best-in-class ZFS management, excellent for pure NAS use Cons: Storage-first design (compute secondary), less flexible for running diverse services, requires 8GB+ RAM for ZFS
Best for: Primary NAS with apps as secondary priority
Why NOT TrueNAS for you:¶
Your use case is services-first (Jellyfin, *arr stack, dev apps) with storage as supporting role. TrueNAS optimizes the opposite direction.
2. Storage Configuration Strategy¶
Recommended Layout:¶
Samsung EVO 250GB #1 → Proxmox OS (ext4)
Samsung EVO 250GB #2 → LXC/Docker storage (ext4)
Hitachi 4TB → mergerfs pool (data disk)
WD Green 1TB #1 → mergerfs pool (data disk)
WD Green 1TB #2 → SnapRAID parity (INTERNE, pas USB!)
HGST 1TB USB3 → Offsite rotation backup
Maxtor 4TB USB3 → Local backup target (automated)
Total disponible: ~5TB (4TB + 1TB data)
Protection: 1TB parity SnapRAID
⚠️ IMPORTANT - Limitation SnapRAID:
Problème: Le disque de parité de 1TB ne peut protéger que jusqu'à 1TB de données!
- Règle SnapRAID: Capacité parity ≥ plus gros disque data
- Votre config: Parity 1TB, mais data disk 4TB → seulement 1TB du Hitachi sera protégé
Solutions:
Option A - Démarrage économique (recommandé):
Utiliser seulement 1TB du Hitachi 4TB au début
- Créer partition 1TB sur Hitachi: /dev/sdb1 (1TB protégée)
- Partition 3TB restante: /dev/sdb2 (non protégée, pour médias jetables)
- Total protégé: 2TB (1TB Hitachi + 1TB WD Green)
- Investissement: €0
Option B - Protection complète (investissement):
Acheter disque interne 4TB pour parity (~€80-100)
- WD Red 4TB ou Seagate IronWolf 4TB
- Total protégé: 5TB (4TB Hitachi + 1TB WD Green)
- Investissement: €80-100
Option C - Upgrade futur:
Démarrer avec Option A (1TB protégé)
Upgrade quand nécessaire (quand >1TB de données critiques)
- Ajouter disque 4TB parity plus tard
- Redéployer partition Hitachi complète
Recommandation: Option A pour démarrer, upgrade vers Option B si besoin dépasse 1TB de données critiques.
⚠️ CRITIQUE - Pas de disque USB pour parity!
Pourquoi PAS le Maxtor 4TB USB comme parity:
- ❌ Connexion USB instable (déconnexions corrompent parity)
- ❌ Disques USB s'endorment (interruption pendant sync)
- ❌ Si USB se déconnecte pendant
snapraid sync, parity invalide - ❌ SnapRAID documentation déconseille fortement USB
Utiliser uniquement disques SATA internes pour parity!
Pourquoi mergerfs + SnapRAID ? ⭐ OPTIMAL pour disques mixtes¶
Problème avec ZFS/RAID classique:
- Disques de tailles différentes (4TB + 1TB) gaspillent de l'espace
- Impossible d'ajouter un seul disque sans tout reconstruire
- ZFS exige des disques identiques pour vdev
- RAID⅚ nécessite disques de même taille
Avantages mergerfs + SnapRAID:
✅ Flexibilité totale: Mélangez n'importe quelles tailles de disques ✅ Expansion facile: Ajoutez un disque 8TB demain sans toucher aux autres ✅ Données accessibles: Chaque disque garde son filesystem (ext4), lisible individuellement ✅ Protection parity: SnapRAID calcule parité comme RAID5 mais sans RAID ✅ Économie d'énergie: Disques peuvent s'arrêter indépendamment ✅ Récupération: Perte d'un disque = récupération via parity
Comment ça marche:
# mergerfs fusionne les disques en un seul point de montage
/mnt/disk1 (4TB Hitachi)
/mnt/disk2 (1TB WD Green)
↓ mergerfs
/mnt/storage (5TB virtuels)
# SnapRAID calcule parité des fichiers (pas en temps réel)
/mnt/parity (1TB WD Green #2)
Configuration mergerfs + SnapRAID:¶
1. Formatter les disques:
# Formatter en ext4 (simple, fiable)
mkfs.ext4 -L data1 /dev/sdb # Hitachi 4TB
mkfs.ext4 -L data2 /dev/sdc # WD Green 1TB
mkfs.ext4 -L parity /dev/sdd # WD Green 1TB (parity)
# Créer points de montage
mkdir -p /mnt/disk{1,2,parity,storage}
# Monter dans /etc/fstab
LABEL=data1 /mnt/disk1 ext4 defaults,noatime 0 2
LABEL=data2 /mnt/disk2 ext4 defaults,noatime 0 2
LABEL=parity /mnt/parity ext4 defaults,noatime 0 2
2. Installer mergerfs:
# Télécharger dernière version (vérifier sur GitHub)
wget https://github.com/trapexit/mergerfs/releases/download/2.40.2/mergerfs_2.40.2.debian-bookworm_amd64.deb
sudo dpkg -i mergerfs_*.deb
# Monter temporairement pour test
sudo mergerfs /mnt/disk1:/mnt/disk2 /mnt/storage \
-o allow_other,use_ino,cache.files=auto-full,moveonenospc=true,\
category.create=mfs,dropcacheonclose=true
# Vérifier
df -h /mnt/storage # Doit afficher somme des disques
touch /mnt/storage/test.txt && rm /mnt/storage/test.txt # Test écriture
IMPORTANT: Rendre permanent via /etc/fstab:
# Éditer /etc/fstab
sudo nano /etc/fstab
# Ajouter cette ligne (à la fin):
/mnt/disk* /mnt/storage fuse.mergerfs allow_other,use_ino,cache.files=auto-full,moveonenospc=true,category.create=mfs,dropcacheonclose=true 0 0
# Sauvegarder (Ctrl+O, Enter, Ctrl+X)
# Tester montage fstab AVANT reboot
sudo umount /mnt/storage
sudo mount -a
df -h /mnt/storage # Doit fonctionner
⚠️ Sans cette étape fstab, mergerfs ne sera PAS monté après redémarrage!
3. Configurer SnapRAID:
apt install snapraid
# /etc/snapraid.conf
parity /mnt/parity/snapraid.parity
content /var/snapraid.content
content /mnt/disk1/.snapraid.content
content /mnt/disk2/.snapraid.content
data d1 /mnt/disk1
data d2 /mnt/disk2
exclude *.tmp
exclude /downloads/incomplete/
exclude .Trash-*/
# Initialiser
snapraid sync
4. Automation SnapRAID (avec gestion d'erreurs):
#!/bin/bash
# Script SnapRAID avec gestion d'erreurs et logging
set -euo pipefail # Exit on error, undefined var, pipe failure
LOGFILE="/var/log/snapraid.log"
THRESHOLD=50 # Nombre max de fichiers modifiés avant alerte
EMAIL="votre@email.com" # Optionnel: pour notifications
# Fonction logging avec timestamp
log() {
echo "[$(date +'%Y-%m-%d %H:%M:%S')] $*" | tee -a "$LOGFILE"
}
# Fonction notification erreur (optionnel)
notify_error() {
log "ERROR: $1"
# Décommenter si email configuré:
# echo "$1" | mail -s "SnapRAID Error" "$EMAIL"
# Ou utiliser ntfy.sh:
# curl -d "$1" ntfy.sh/votre-topic
}
log "=== SnapRAID run started ==="
# Vérifier qu'une instance n'est pas déjà en cours
if pidof -x snapraid > /dev/null; then
notify_error "SnapRAID déjà en cours d'exécution, abandon"
exit 1
fi
# Étape 1: Diff pour détecter changements
log "Running snapraid diff..."
DIFF_OUT=$(snapraid diff 2>&1 || true)
echo "$DIFF_OUT" >> "$LOGFILE"
# Extraire nombre de fichiers modifiés
CHANGED=$(echo "$DIFF_OUT" | grep -oP '\d+(?= modified)' | head -1 || echo "0")
ADDED=$(echo "$DIFF_OUT" | grep -oP '\d+(?= added)' | head -1 || echo "0")
REMOVED=$(echo "$DIFF_OUT" | grep -oP '\d+(?= removed)' | head -1 || echo "0")
TOTAL_CHANGES=$((CHANGED + ADDED + REMOVED))
log "Changes detected: $ADDED added, $REMOVED removed, $CHANGED modified (total: $TOTAL_CHANGES)"
# Vérifier seuil de sécurité
if [ "$TOTAL_CHANGES" -gt "$THRESHOLD" ]; then
notify_error "ATTENTION: $TOTAL_CHANGES fichiers modifiés (seuil: $THRESHOLD). Vérification manuelle requise!"
log "Sync aborted due to threshold exceeded"
exit 1
fi
# Étape 2: Sync si changements dans seuil acceptable
if [ "$TOTAL_CHANGES" -gt 0 ]; then
log "Running snapraid sync..."
if snapraid sync >> "$LOGFILE" 2>&1; then
log "Sync completed successfully"
else
notify_error "Sync failed! Check $LOGFILE"
exit 1
fi
else
log "No changes detected, skipping sync"
fi
# Étape 3: Scrub (vérification intégrité)
# Vérifie 8% des données, fichiers non vérifiés depuis 30+ jours
log "Running snapraid scrub..."
if snapraid scrub -p 8 -o 30 >> "$LOGFILE" 2>&1; then
log "Scrub completed successfully"
else
notify_error "Scrub failed! Possible data corruption. Check $LOGFILE"
exit 1
fi
log "=== SnapRAID run completed successfully ==="
# Nettoyer vieux logs (garder 90 jours)
find "$(dirname "$LOGFILE")" -name "snapraid.log.*" -mtime +90 -delete 2>/dev/null || true
exit 0
# Rendre exécutable
sudo chmod +x /usr/local/bin/snapraid-runner.sh
# Tester manuellement
sudo /usr/local/bin/snapraid-runner.sh
# Ajouter au cron (tous les jours à 2h du matin)
sudo crontab -e
# Ajouter:
0 2 * * * /usr/local/bin/snapraid-runner.sh
# Monitoring: vérifier logs
tail -f /var/log/snapraid.log
Seuil de sécurité explications:
- Si >50 fichiers modifiés en 24h → possible corruption filesystem ou ransomware
- Script demande vérification manuelle avant sync
- Ajuster THRESHOLD selon votre usage (50 = conservateur)
/mnt/storage/
├── archives/ # Archives statiques (1TB)
├── media/
│ ├── movies/ # Films Jellyfin
│ ├── tv/ # Séries Jellyfin
│ └── downloads/ # Téléchargements temporaires
├── google-drive-backup/ # Snapshots Google Drive
├── google-photos-backup/ # Snapshots Google Photos
└── docker-volumes/ # Volumes Docker persistants
Préserver les archives du Hitachi 4TB:¶
Option A: Migration sans risque (recommandé)
# 1. Copier archives vers Maxtor 4TB USB (backup temporaire)
rsync -avhP /mnt/hitachi-actuel/ /mnt/maxtor/backup-archives/
# 2. Vérifier intégrité
cd /mnt/hitachi-actuel && find . -type f -exec md5sum {} \; > /tmp/checksums-source.txt
cd /mnt/maxtor/backup-archives && find . -type f -exec md5sum {} \; > /tmp/checksums-backup.txt
diff /tmp/checksums-source.txt /tmp/checksums-backup.txt # Doit être vide
# 3. Reformater Hitachi en ext4
umount /dev/sdb
mkfs.ext4 -L data1 /dev/sdb
# 4. Restaurer archives
rsync -avhP /mnt/maxtor/backup-archives/ /mnt/disk1/archives/
# 5. Vérifier à nouveau
cd /mnt/disk1/archives && find . -type f -exec md5sum {} \; > /tmp/checksums-restored.txt
diff /tmp/checksums-source.txt /tmp/checksums-restored.txt
Option B: Migration progressive (si pas assez d'espace USB)
# Utiliser le 2e disque comme stockage temporaire
# Déplacer par parties, vérifier checksums, reformater zone libérée
Expansion future:¶
Scénario 1: Ajouter un disque 8TB
# Formatter le nouveau disque
mkfs.ext4 -L data3 /dev/sde
# Ajouter à fstab
LABEL=data3 /mnt/disk3 ext4 defaults,noatime 0 2
# mergerfs le détecte automatiquement (grâce à /mnt/disk*)
mount -a
# Ajouter à SnapRAID config
echo "data d3 /mnt/disk3" >> /etc/snapraid.conf
# Remplacer disque parity 1TB par 8TB (optionnel)
snapraid sync # Recalculer parity sur nouveau disque
Capacité avec 8TB:
- Avant: 5TB utilisables (4+1)
- Après: 13TB utilisables (4+1+8)
- Parity: upgrade vers 8TB recommandé (protège le plus gros disque)
Scénario 2: Remplacer petit disque par gros
# 1. Copier données du 1TB vers autres disques
# 2. Retirer 1TB de SnapRAID config
# 3. Remplacer physiquement par 8TB
# 4. Ajouter 8TB à config
# 5. Resync parity
Pourquoi PAS ZFS pour votre cas ?¶
❌ Disques mixtes: ZFS vdev exige disques identiques
❌ Expansion: Impossible d'ajouter 1 disque à un vdev existant
❌ RAM: ZFS idle consomme 4-8GB RAM (gaspillage pour votre usage)
❌ Complexité: Récupération difficile en cas de problème
❌ Overkill: Checksumming en temps réel inutile pour média/archives
✅ mergerfs+SnapRAID: Parfait pour homelab avec disques hétérogènes et croissance organique
3. Docker vs VMs: Service Deployment Strategy¶
Containers (LXC/Docker) - RECOMMENDED¶
Why containers for media stack:
- Performance: Near-native (shared kernel)
- Efficiency: Jellyfin uses ~300MB RAM vs 2GB+ in VM
- Speed: Container starts in 2 seconds
- Portability: docker-compose.yml = reproducible setup
- Updates:
docker-compose pull && docker-compose up -d
Example docker-compose.yml:
version: "3.8"
services:
jellyfin:
image: jellyfin/jellyfin:latest
container_name: jellyfin
network_mode: host
environment:
- PUID=1000
- PGID=1000
- TZ=Europe/Paris
volumes:
- ./jellyfin/config:/config
- /mnt/media:/media
devices:
- /dev/dri:/dev/dri # Intel QuickSync
restart: unless-stopped
sonarr:
image: linuxserver/sonarr:latest
container_name: sonarr
ports:
- 8989:8989
volumes:
- ./sonarr:/config
- /mnt/media:/data
restart: unless-stopped
radarr:
image: linuxserver/radarr:latest
container_name: radarr
ports:
- 7878:7878
volumes:
- ./radarr:/config
- /mnt/media:/data
restart: unless-stopped
prowlarr:
image: linuxserver/prowlarr:latest
container_name: prowlarr
ports:
- 9696:9696
volumes:
- ./prowlarr:/config
restart: unless-stopped
qbittorrent:
image: linuxserver/qbittorrent:latest
container_name: qbittorrent
environment:
- WEBUI_PORT=8080
ports:
- 8080:8080
- 6881:6881
volumes:
- ./qbittorrent:/config
- /mnt/media/downloads:/downloads
restart: unless-stopped
Deploy: docker-compose up -d
When to Use VMs:¶
Future use cases:
- Windows 11 (dev/testing)
- Full OS isolation for security-critical apps
- Testing different Linux distros
Hybrid approach (Proxmox):
Proxmox Host (32GB RAM)
├── LXC: Media Stack (4GB, all *arr + Jellyfin)
├── LXC: Download Client (2GB, qBittorrent + VPN)
├── LXC: Web Apps (2GB, Umami, databases)
├── LXC: Management (1GB, Portainer, Homepage)
├── VM: Windows 11 (8GB, future dev work)
└── Remaining 15GB for host + cache
TRaSH Guides Integration:¶
Reference: https://trash-guides.info/
Best practices from TRaSH:
- Hardlinks for instant moves (no duplication)
- Proper folder structure:
/data/media/{movies,tv} - Quality profiles for optimal size/quality balance
- Custom formats for preferred releases
4. GPU Transcoding: GTX 970 vs Intel iGPU¶
Intel HD Graphics 2000 (Built-in) ⭐ RECOMMENDED¶
Why use iGPU instead of GTX 970:
- Power: iGPU uses ~5-10W vs GTX 970's 145W
- Cost: €0.35/day saved (at €0.20/kWh) = €128/year
- Heat: Much cooler, quieter operation
- Reliability: No moving parts (GTX 970 fans)
- H.264 support: HD Graphics 2000 can encode H.264
Jellyfin setup with Intel QuickSync:
jellyfin:
devices:
- /dev/dri:/dev/dri
environment:
- JELLYFIN_PublishedServerUrl=http://192.168.1.x
Enable in Jellyfin Dashboard:
- Playback → Transcoding
- Hardware acceleration: "Intel QuickSync (QSV)"
- Enable hardware decoding for: H264, MPEG2
Performance: Handles 2-3 simultaneous 1080p transcodes
GTX 970 Considerations:¶
When to use GTX 970:
- Need 4+ simultaneous transcodes
- Heavy HEVC (H.265) transcoding required
- iGPU insufficient (test first)
Limitations:
- No AV1 support (need RTX 30-series)
- HEVC limited to 2 concurrent streams (Maxwell)
- NVIDIA drivers required in container
LXC Passthrough (if needed):
# In Proxmox LXC config (/etc/pve/lxc/XXX.conf)
lxc.cgroup2.devices.allow: c 195:* rwm
lxc.cgroup2.devices.allow: c 509:* rwm
lxc.mount.entry: /dev/nvidia0 dev/nvidia0 none bind,create=file
lxc.mount.entry: /dev/nvidiactl dev/nvidiactl none bind,create=file
i7-2600 IOMMU Check:¶
Before committing to GPU passthrough:
# Verify IOMMU enabled
dmesg | grep -e DMAR -e IOMMU
# Check IOMMU groups
for d in /sys/kernel/iommu_groups/*/devices/*; do
n=${d#*/iommu_groups/*}; n=${n%%/*}
printf 'IOMMU Group %s ' "$n"
lspci -nns "${d##*/}"
done
Sandy Bridge note: 2nd gen Intel has basic IOMMU, may have group issues
Verdict: Start with iGPU. Add GTX 970 only if performance insufficient.
5. Remote Access: Modern Solutions (2026)¶
Tailscale ⭐ EASIEST & MOST SECURE¶
What it is: Zero-config mesh VPN using WireGuard
Why Tailscale is perfect:
- 5-minute setup: Install, authenticate, done
- No port forwarding: Works behind CGNAT/strict NAT
- Fast: Direct peer connections (WireGuard speeds)
- Free tier: Up to 100 devices, 3 users
- MagicDNS: Access by name (jellyfin.tailnet-name.ts.net)
- ACLs: Restrict what each user can access
Setup:
# On server (Proxmox host or Ubuntu)
curl -fsSL https://tailscale.com/install.sh | sh
tailscale up
# On phone/laptop/tablet
# Install Tailscale app from app store
# Login with same account
# Access Jellyfin: http://100.x.x.x:8096
Access from anywhere:
- Phone: Tailscale app running
- Laptop: Tailscale in system tray
- Work computer: Install Tailscale
Security: Encrypted mesh, no exposed ports, identity-based access
Alternative: WireGuard (DIY)¶
When to use:
- Want full control
- Don't trust third-party coordination
- Advanced networking needs
Setup complexity: Medium (need to manage keys, configs)
# Server
apt install wireguard
wg genkey | tee privatekey | wg pubkey > publickey
# Create /etc/wireguard/wg0.conf
[Interface]
Address = 10.0.0.1/24
ListenPort = 51820
PrivateKey = <server-private-key>
[Peer]
PublicKey = <client-public-key>
AllowedIPs = 10.0.0.2/32
Router: Forward UDP port 51820 to server
Cloudflare Tunnel (For Web Apps)¶
Use for: Umami, blogs, public websites (not Jellyfin)
Why NOT for Jellyfin: Violates Cloudflare TOS (streaming media)
Setup:
Pros: No exposed ports, free SSL, DDoS protection Cons: Routes through Cloudflare (privacy), bandwidth limits
Reverse Proxy (Local Network)¶
For internal network organization:
Nginx Proxy Manager:
- Beautiful GUI for managing proxies
- Free Let's Encrypt SSL
- Easy subdomain routing
Caddy:
- Simplest config (3 lines for basic proxy)
- Automatic HTTPS
- Best for power users
Example Caddyfile:
jellyfin.home.local {
reverse_proxy localhost:8096
}
sonarr.home.local {
reverse_proxy localhost:8989
}
Security Recommendation:¶
Never expose directly:
- Port 22 (SSH)
- Port 8096 (Jellyfin)
- Any admin panel
Safe approach:
- Primary: Tailscale for all remote access
- Secondary: Reverse proxy for local network only
- Public services: Cloudflare Tunnel (non-media)
6. Stratégie de Backup: Par Criticité (Sans Cloud Tiers)¶
Hiérarchie des données par criticité:¶
| Type | Criticité | Fréquence accès | Stratégie |
|---|---|---|---|
| Configs serveur | 🔴 Critique | Modif rare | Git + backup quotidien local + offsite |
| Google Drive | 🟠 Important | Quotidien | Snapshot hebdo sur serveur (filet sécurité) |
| Google Photos | 🟠 Important | Quotidien | Snapshot hebdo sur serveur (filet sécurité) |
| Archives | 🟡 Modéré | Très rare | Stockage serveur + disque externe offsite |
| Médias Jellyfin | 🟢 Faible | Fréquent | SnapRAID parity seulement |
Situation existante à optimiser:¶
Google One Familial: 2TB pour €100/an
- 600GB Google Drive (docs travail/admin)
- 400GB Google Photos (photos/vidéos quotidiennes)
- Redondance avec 1TB archives locales à éliminer
Objectif: Utiliser Google One comme PRIMARY, serveur comme BACKUP (inverse de l'approche classique)
1. Configs Serveur (CRITIQUE) 🔴¶
Quoi sauvegarder:
- Proxmox:
/etc/pve/(configs VMs/LXC) - Docker:
docker-compose.yml+.envfiles - Configs apps: Jellyfin, Sonarr, Radarr settings
- Scripts personnalisés
- Liste des paquets installés
Stratégie: Git + rsync
# Initialiser dépôt Git
mkdir -p /opt/backup-configs
cd /opt/backup-configs
git init
# Script de backup configs
#!/bin/bash
# /usr/local/bin/backup-configs.sh
BACKUP_DIR="/opt/backup-configs"
DATE=$(date +%Y%m%d-%H%M)
# Copier configs Proxmox
rsync -a /etc/pve/ $BACKUP_DIR/proxmox/
# Copier docker-compose et configs
rsync -a /opt/docker/ $BACKUP_DIR/docker/ \
--exclude '*/cache/*' \
--exclude '*/logs/*' \
--exclude '*/transcodes/*'
# Sauvegarder liste paquets
dpkg --get-selections > $BACKUP_DIR/packages.list
apt-mark showauto > $BACKUP_DIR/packages-auto.list
# Commit dans Git
cd $BACKUP_DIR
git add -A
git commit -m "Backup $DATE" || true
# Copier vers USB local (Maxtor 4TB)
rsync -a $BACKUP_DIR/ /mnt/maxtor-backup/configs/
# Copier vers USB offsite (à swapper régulièrement)
if mountpoint -q /mnt/offsite-backup; then
rsync -a $BACKUP_DIR/ /mnt/offsite-backup/configs/
echo "Offsite backup updated: $DATE"
fi
# Créer archive tar datée (pour garder historique)
tar -czf /mnt/storage/backups/configs-$DATE.tar.gz -C /opt backup-configs
# Garder seulement 30 dernières archives
find /mnt/storage/backups/ -name "configs-*.tar.gz" -mtime +30 -delete
echo "Config backup completed: $DATE"
Automation:
Restauration rapide:
# Réinstaller Proxmox sur nouveau SSD
# Restaurer configs:
cd /opt
tar -xzf /mnt/maxtor-backup/backups/configs-latest.tar.gz
rsync -a /opt/backup-configs/docker/ /opt/docker/
rsync -a /opt/backup-configs/proxmox/ /etc/pve/
# Réinstaller paquets
dpkg --set-selections < /opt/backup-configs/packages.list
apt-get dselect-upgrade
# Redémarrer containers
cd /opt/docker && docker-compose up -d
RTO (Recovery Time Objective): 2-3 heures
2. Google Drive Snapshot (IMPORTANT) 🟠¶
Objectif: Filet de sécurité si problème avec compte Google (suppression accidentelle, piratage, fermeture compte)
Solution: rclone (meilleur outil 2026)
Installation:
# Méthode recommandée: package manager (plus sécurisé)
sudo apt update && sudo apt install rclone
# Vérifier version (doit être ≥1.65 pour Google Drive moderne)
rclone version
# Alternative: installation manuelle si version apt obsolète
# wget https://downloads.rclone.org/rclone-current-linux-amd64.zip
# unzip rclone-current-linux-amd64.zip
# sudo cp rclone-*/rclone /usr/local/bin/
# sudo chmod 755 /usr/local/bin/rclone
Configuration initiale Google Drive (OBLIGATOIRE):
# Lancer configuration interactive
rclone config
# Répondre aux questions:
# n) New remote
# name> gdrive
# Storage> 15 (Google Drive)
# client_id> (laisser vide, utilise app rclone par défaut)
# client_secret> (laisser vide)
# scope> 1 (Full access)
# service_account_file> (laisser vide)
# Advanced config? n
# Auto config? y (ouvre navigateur pour authentification)
Étape d'authentification:
- Le navigateur s'ouvre automatiquement
- Sélectionner compte Google approprié
- Accepter les permissions rclone
- Copier le code fourni dans terminal (si headless)
- Vérifier:
rclone lsd gdrive:(doit lister dossiers Drive)
⚠️ Note légale: Utiliser rclone avec Google Drive est techniquement contre les ToS de Google, mais largement toléré. Risque: Google pourrait révoquer accès API (rare). Mitigation: garder backup offsite à jour.
Script de snapshot:
#!/bin/bash
# /usr/local/bin/sync-gdrive.sh
SOURCE="gdrive:/"
DEST="/mnt/storage/google-drive-backup"
LOG="/var/log/gdrive-sync.log"
DATE=$(date +%Y%m%d-%H%M)
echo "=== Google Drive Snapshot: $DATE ===" >> $LOG
# Sync avec --backup-dir pour versioning
rclone sync "$SOURCE" "$DEST" \
--backup-dir "$DEST/../gdrive-versions/$DATE" \
--drive-skip-gdocs \
--exclude ".Trash-*/**" \
--exclude "*.tmp" \
--fast-list \
--transfers 8 \
--checkers 16 \
--stats 1m \
--log-file=$LOG \
--log-level INFO
if [ $? -eq 0 ]; then
echo "✓ Sync completed successfully" >> $LOG
# Cleanup: garder versions des 60 derniers jours
find "$DEST/../gdrive-versions" -mindepth 1 -maxdepth 1 -type d -mtime +60 -exec rm -rf {} \;
# Copier vers USB backup
rsync -a --delete "$DEST/" /mnt/maxtor-backup/google-drive/
else
echo "✗ Sync failed!" >> $LOG
# Envoyer notification (ntfy, email, etc.)
fi
Automation:
Espace utilisé: 600GB Drive → besoin ~650GB avec versions (1 mois)
Restauration:
- Fichiers récents: réupload depuis
/mnt/storage/google-drive-backup/ - Versions antérieures: chercher dans
/mnt/storage/gdrive-versions/YYYYMMDD/
3. Google Photos Snapshot (IMPORTANT) 🟠¶
Solution: rclone avec Google Photos
Configuration initiale Google Photos:
rclone config
# Répondre:
# n) New remote
# name> gphotos
# Storage> 18 (Google Photos)
# client_id> (laisser vide)
# client_secret> (laisser vide)
# read_only> false (accès lecture pour backup)
# Advanced config? n
# Auto config? y (authentification navigateur)
⚠️ LIMITATIONS CRITIQUES Google Photos via rclone:
- Qualité des téléchargements:
- ❌ Google peut ré-encoder les photos/vidéos (pas bit-perfect)
- ❌ Motion Photos/Live Photos peuvent perdre composant vidéo
- ❌ Métadonnées EXIF parfois incomplètes
- Structure:
- ❌ Albums partagés non synchronisables
- ❌ Structure d'albums non préservée (toutes photos en vrac)
-
❌ Doublons possibles entre albums et bibliothèque
-
API limitations:
- ⚠️ Rate limiting: Google limite à ~10,000 requêtes/jour
- ⚠️ Sync initial 400GB peut prendre 24-48 heures
- ⚠️ Vidéos >10MB téléchargées en qualité réduite via API
Recommandation double stratégie:
# 1. rclone hebdomadaire pour sync incrémental (photos récentes)
# Acceptable pour 95% des cas d'usage
# 2. Google Takeout trimestriel pour backup archival
# Qualité originale garantie, mais manuel
# https://takeout.google.com/settings/takeout
# Sélectionner: Google Photos > Exporter
# Télécharger archives ZIP > décompresser sur serveur
Script de snapshot:
#!/bin/bash
# /usr/local/bin/sync-gphotos.sh
SOURCE="gphotos:album/All"
DEST="/mnt/storage/google-photos-backup"
LOG="/var/log/gphotos-sync.log"
DATE=$(date +%Y%m%d-%H%M)
echo "=== Google Photos Snapshot: $DATE ===" >> $LOG
rclone copy "$SOURCE" "$DEST" \
--gphotos-include-archived \
--transfers 8 \
--checkers 16 \
--stats 1m \
--log-file=$LOG \
--log-level INFO
if [ $? -eq 0 ]; then
echo "✓ Photos sync completed" >> $LOG
# Copier vers USB backup
rsync -a --delete "$DEST/" /mnt/maxtor-backup/google-photos/
else
echo "✗ Photos sync failed!" >> $LOG
fi
Automation:
Espace utilisé: 400GB Photos → besoin ~420GB
Note: Google Photos API limite les téléchargements. Sync hebdomadaire évite rate limiting.
4. Archives (MODÉRÉ) 🟡¶
Objectif:
- Consolider/dédupliquer archives dispersées
- Retirer de Google Drive (libérer espace)
- Stocker sur serveur (accès rare acceptable)
- Copie offsite sur disque externe
Étape 1: Déduplication
# Installer jdupes (meilleur en 2026)
apt install jdupes
# Identifier doublons entre sources
jdupes -r -S \
/mnt/storage/google-drive-backup/Archives/ \
/mnt/disk1/archives-anciennes/ \
> /tmp/duplicates-report.txt
# Review manuel, puis supprimer doublons
jdupes -r -d -N \
/mnt/storage/google-drive-backup/Archives/ \
/mnt/disk1/archives-anciennes/
Étape 2: Consolidation
# Créer structure unique
mkdir -p /mnt/storage/archives/{documents,photos-old,videos,projects}
# Déplacer depuis Google Drive backup
rsync -av --remove-source-files \
/mnt/storage/google-drive-backup/Archives/ \
/mnt/storage/archives/
# Vérifier intégrité
find /mnt/storage/archives -type f -exec md5sum {} \; > /tmp/archives-checksums.txt
# Supprimer de Google Drive (via web ou rclone)
rclone delete gdrive:/Archives/
Étape 3: Backup offsite
# Copier vers HGST 1TB USB (offsite)
rsync -av --progress \
/mnt/storage/archives/ \
/mnt/offsite-usb/archives/
# Déconnecter et stocker hors site (chez famille, bureau, coffre...)
Gain: 1TB libéré dans Google Drive → plus d'espace pour Drive/Photos actifs
Accès:
- Fréquent: depuis
/mnt/storage/archives/sur serveur via Samba/Tailscale - Récupération disaster: depuis disque offsite
5. Médias Jellyfin (FAIBLE) 🟢¶
Philosophie: Données non critiques, retéléchargement possible
Protection minimale: SnapRAID parity
# Sync SnapRAID après ajout de films/séries
snapraid sync
# Vérifier intégrité mensuellement
snapraid scrub -p 10 # Vérifie 10% des données
En cas de perte:
- 1 disque mort:
snapraid fixrécupère données via parity - 2+ disques morts: retélécharger (Sonarr/Radarr gardent historique)
- Corruption fichier: retélécharger ce fichier uniquement
Pas de backup complet → trop volumineux, pas critique
Stratégie de rotation offsite (recommandé)¶
Investissement: Acheter 1 disque externe supplémentaire (2-4TB, ~€70)
Rotation A/B:
Semaine 1-2: Disque A à la maison (backup actif)
Disque B offsite (version N-2)
Semaine 3-4: Swap!
Disque B à la maison (backup actif)
Disque A offsite (version N-2)
Script de préparation avant swap:
#!/bin/bash
# /usr/local/bin/prepare-offsite-swap.sh
OFFSITE_DISK="/mnt/offsite-usb"
echo "Preparing offsite disk for rotation..."
# Backup configs (critique)
rsync -a --delete /opt/backup-configs/ $OFFSITE_DISK/configs/
# Backup Google Drive/Photos (important)
rsync -a --delete /mnt/storage/google-drive-backup/ $OFFSITE_DISK/google-drive/
rsync -a --delete /mnt/storage/google-photos-backup/ $OFFSITE_DISK/google-photos/
# Backup archives (modéré)
rsync -a /mnt/storage/archives/ $OFFSITE_DISK/archives/
# Créer manifest
find $OFFSITE_DISK -type f > $OFFSITE_DISK/manifest-$(date +%Y%m%d).txt
echo "Offsite disk ready. You can safely swap it now."
echo "Don't forget to bring back the other disk!"
Fréquence: Swap tous les 15 jours (2 semaines)
Monitoring des backups:¶
Healthchecks.io (gratuit, simple)
# Créer checks sur https://healthchecks.io
# Ajouter à chaque script:
HC_CONFIGS="https://hc-ping.com/UUID-configs"
HC_GDRIVE="https://hc-ping.com/UUID-gdrive"
HC_GPHOTOS="https://hc-ping.com/UUID-gphotos"
# Début du backup
curl -fsS -m 10 $HC_CONFIGS/start
# ... commandes backup ...
# Succès
curl -fsS -m 10 $HC_CONFIGS
# Échec (dans trap)
curl -fsS -m 10 $HC_CONFIGS/fail
Alertes: Email/SMS si backup ne s'exécute pas dans le délai prévu
Récapitulatif de la stratégie:¶
| Donnée | Production | Local | Offsite | RPO* | RTO** |
|---|---|---|---|---|---|
| Configs | Serveur | Maxtor 4TB (quotidien) | USB rotation (2 sem) | 24h | 2-3h |
| Google Drive | Google Cloud | Serveur (hebdo) | USB rotation (2 sem) | 7j | Immédiat |
| Google Photos | Google Cloud | Serveur (hebdo) | USB rotation (2 sem) | 7j | Immédiat |
| Archives | Serveur | Maxtor 4TB | USB dédié offsite | N/A | 1-2h |
| Médias | Serveur | SnapRAID parity | Aucun | Perte acceptée | Redownload |
*RPO = Recovery Point Objective (perte max de données)
**RTO = Recovery Time Objective (temps de restauration)
Coût total: €70 one-time (disque USB supplémentaire) + €0/an (pas de cloud tiers)
Testing Plan:¶
| Test | Frequency | Method |
|---|---|---|
| Random file restore | Monthly | Pick 1 file, restore, verify |
| Config restore | Quarterly | Restore docker configs to test env |
| Full disaster recovery | Annually | Wipe test drive, restore everything |
Recovery Scenarios:¶
1. Container config corruption:
# Restore from daily backup
cp -r /mnt/backup/docker/jellyfin/config /opt/docker/jellyfin/
docker-compose restart jellyfin
2. HDD failure:
# Replace drive, restore from USB
zpool replace storage old-drive new-drive
zfs receive storage/media < /mnt/backup/latest-snapshot
3. Complete server loss:
- Reinstall Proxmox on new SSD
- Restore docker-compose files from cloud
- Restore data from USB backup
- Recreate containers:
docker-compose up -d
Recovery Time Objective: 4 hours for full system
7. Power Consumption & Hardware Longevity¶
Power Analysis:¶
Current system (measured):
| Component | Idle | Light | Full |
|---|---|---|---|
| i7-2600 | 30W | 50W | 95W |
| Motherboard | 15W | 15W | 20W |
| 32GB RAM | 10W | 10W | 10W |
| 2x SSD | 4W | 6W | 8W |
| 2x HDD | 12W | 15W | 18W |
| Fans | 5W | 5W | 5W |
| Total (no GPU) | 76W | 101W | 156W |
| GTX 970 (if used) | +30W | +50W | +145W |
24/7 operation cost:
Idle: 76W × 24h × 365 days = 666 kWh/year
At €0.20/kWh = €133/year
With GTX 970 idle: 106W = €186/year
Difference: €53/year to run GPU unused
Recommendation: Remove GTX 970, use iGPU → save €53/year
Optimization:¶
BIOS settings:
Enable: C-states, SpeedStep, EIST
Disable: Unused controllers (serial, parallel)
Set: Fan curves to "quiet" profile
Linux power management:
# Install powertop
apt install powertop
# Tune system
powertop --auto-tune
# Make permanent (Ubuntu)
systemctl enable powertop
# Verify savings
powertop --html=power-report.html
HDD spin-down:
# Spin down media HDD after 20 min idle
hdparm -S 240 /dev/sda # 240 * 5sec = 20 min
# Permanent (/etc/hdparm.conf)
/dev/sda {
spindown_time = 240
}
Expected savings: 10-15W when HDDs spun down = €18-26/year
Hardware Longevity Assessment:¶
i7-2600 (2011, 14 years old):
- Reliability: Sandy Bridge very stable, no major issues
- Expected life: 5+ more years with good cooling
- Warning signs: Check thermal paste (replace if temps >80°C under load)
- Monitoring:
sensorscommand, watch for throttling
RAM (DDR3):
- Current status: 32GB is excellent for this workload
- Test: Run memtest86+ if experiencing crashes
- Expected life: 10+ more years (RAM rarely fails)
Samsung EVO 850 (2014-2018, 8-11 years old):
- Technology: TLC NAND, rated for 75-150 TBW (terabytes written)
- Check wear:
smartctl -a /dev/sdX | grep -i "wear\|life" - Warning: Replace when <20% life remaining
- Expected life: 2-5 more years depending on wear
Hitachi Ultrastar (Enterprise HDD):
- Reliability: Enterprise-class, excellent reputation
- SMART monitoring: Check weekly for reallocated sectors
- Expected life: 5+ years (enterprise HDDs rated for 1-2M hours)
WD Green (Consumer HDD):
- Known issue: Aggressive head parking (IntelliPark)
- Fix:
wdidle3.exe /D(disable parking) - Expected life: 3-5 years
- Use: Non-critical data only
Monitoring script:
#!/bin/bash
# /usr/local/bin/smart-check.sh
for drive in /dev/sd{a,b,c,d}; do
echo "=== $drive ==="
smartctl -H $drive | grep -i "PASSED\|FAILED"
smartctl -a $drive | grep -i "reallocated\|pending\|uncorrectable"
done
Cron: Weekly on Sunday
Upgrade Considerations:¶
Replace WHEN:
- i7-2600: Transcoding becomes too slow, temps >85°C, crashes
- RAM: memtest86+ errors (rare)
- SSDs: SMART shows <10% life, performance degrades
- HDDs: Reallocated sectors >5, pending sectors >0
DON'T upgrade just because new hardware exists - Your system is capable of 5+ more years
8. Security: Defense in Depth¶
Layer 1: Network Perimeter¶
Firewall (UFW):
# Default deny
ufw default deny incoming
ufw default allow outgoing
# SSH (non-standard port)
ufw allow 2222/tcp comment 'SSH'
# Tailscale
ufw allow in on tailscale0
# Enable
ufw enable
ufw status verbose
Fail2Ban (brute force protection):
apt install fail2ban
# /etc/fail2ban/jail.local
[sshd]
enabled = true
port = 2222
maxretry = 3
bantime = 3600
findtime = 600
[proxmox]
enabled = true
port = 8006
logpath = /var/log/daemon.log
maxretry = 3
NEVER port forward:
- 22 (SSH)
- 8006 (Proxmox)
- 8096 (Jellyfin)
- Any admin panel
ONLY forward (if needed): VPN port (51820 WireGuard)
Layer 2: Access Control¶
SSH hardening:
# /etc/ssh/sshd_config
Port 2222
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
MaxAuthTries 3
ClientAliveInterval 300
ClientAliveCountMax 2
# Restart
systemctl restart sshd
Generate strong SSH key:
# On your laptop/desktop
ssh-keygen -t ed25519 -a 100 -C "your-email@example.com"
# Copy to server
ssh-copy-id -p 2222 user@server-ip
Tailscale ACLs (restrict access):
{
"acls": [
{
"action": "accept",
"users": ["you@example.com"],
"ports": ["*:*"]
},
{
"action": "accept",
"users": ["family@example.com"],
"ports": ["server:8096"]
}
]
}
Layer 3: Application Security¶
Reverse proxy with authentication:
Option 1: Authelia (2FA for all services)
# docker-compose.yml
authelia:
image: authelia/authelia
container_name: authelia
volumes:
- ./authelia:/config
ports:
- 9091:9091
Option 2: Nginx Proxy Manager + Authelia
- NPM manages proxies
- Authelia provides 2FA gateway
- All services behind auth layer
Jellyfin security:
Dashboard → Networking
- Bind to 127.0.0.1 (localhost only)
- Disable UPnP/DLNA
- Require strong passwords
- Enable HTTPS (if exposed)
Sonarr/Radarr/Prowlarr:
Settings → General → Security
- Authentication: Forms (Login Page)
- Use strong API keys
- Bind to localhost if behind reverse proxy
Layer 4: System Hardening¶
Automatic updates:
# Ubuntu/Debian
apt install unattended-upgrades
# /etc/apt/apt.conf.d/50unattended-upgrades
Unattended-Upgrade::Automatic-Reboot "true";
Unattended-Upgrade::Automatic-Reboot-Time "03:00";
# Enable
dpkg-reconfigure -plow unattended-upgrades
Docker security:
# docker-compose.yml security best practices
services:
jellyfin:
security_opt:
- no-new-privileges:true
read_only: true
tmpfs:
- /tmp
cap_drop:
- ALL
cap_add:
- CHOWN
- SETGID
- SETUID
user: "1000:1000" # Non-root user
AppArmor (Ubuntu default):
Layer 5: Monitoring & Alerts¶
Logwatch (daily summaries):
OSSEC (file integrity monitoring):
# Watches for unauthorized file changes
apt install ossec-hids
# /var/ossec/etc/ossec.conf
<syscheck>
<directories check_all="yes">/etc</directories>
<directories check_all="yes">/opt/docker</directories>
</syscheck>
Uptime monitoring:
- UptimeRobot (free, external): Checks if services respond
- Healthchecks.io (free): Monitors backup cron jobs
Security Checklist:¶
- SSH: Key-only auth, non-standard port, Fail2Ban
- Firewall: UFW enabled, only VPN port open
- VPN: Tailscale or WireGuard for remote access
- Reverse proxy: HTTPS, authentication layer
- Passwords: Unique, strong, in password manager (Bitwarden)
- 2FA: Enabled on critical services
- Updates: Automatic security updates
- Backups: Tested monthly, 3-2-1 rule
- Monitoring: Fail2Ban alerts, uptime checks
- Docker: Non-root users, security options
9. Service Management Dashboards¶
Portainer ⭐ BEST FOR DOCKER¶
What it is: Web UI for Docker management
Features:
- Visual container management (start/stop/restart)
- Edit docker-compose.yml in GUI
- View logs, stats, console access
- Template library (one-click app deployments)
- Multi-host support
- User management (RBAC)
Setup:
docker run -d \
-p 9443:9443 \
--name=portainer \
--restart=always \
-v /var/run/docker.sock:/var/run/docker.sock \
-v portainer_data:/data \
portainer/portainer-ce:latest
Access: https://server-ip:9443
Why Portainer:
- Most mature Docker GUI
- Free Community Edition (all features for homelab)
- Excellent for beginners and pros
- Active development
Homepage (Service Status Dashboard)¶
What it is: Beautiful dashboard showing all services
Setup:
# docker-compose.yml
homepage:
image: ghcr.io/gethomepage/homepage:latest
container_name: homepage
ports:
- 3000:3000
volumes:
- ./homepage:/app/config
Config (services.yaml):
- Media:
- Jellyfin:
href: http://{{HOSTNAME}}:8096
description: Media server
widget:
type: jellyfin
url: http://jellyfin:8096
key: { { JELLYFIN_API_KEY } }
- Sonarr:
href: http://{{HOSTNAME}}:8989
widget:
type: sonarr
url: http://sonarr:8989
key: { { SONARR_API_KEY } }
- Radarr:
href: http://{{HOSTNAME}}:7878
widget:
type: radarr
url: http://radarr:7878
key: { { RADARR_API_KEY } }
- Downloads:
- qBittorrent:
href: http://{{HOSTNAME}}:8080
widget:
type: qbittorrent
url: http://qbittorrent:8080
username: { { QB_USER } }
password: { { QB_PASS } }
Features:
- Real-time stats from API integrations
- Customizable layout
- Dark/light themes
- Search across all services
Cockpit (System Administration)¶
What it is: Web-based Linux system management
Setup:
apt install cockpit cockpit-pcp cockpit-podman
systemctl enable --now cockpit.socket
# Access: https://server-ip:9090
Features:
- System monitoring (CPU, RAM, disk, network)
- Service management (systemd units)
- Storage management (disks, RAID, LVM)
- Terminal access
- User management
- Software updates
When to use: System-level tasks (not Docker-specific)
Proxmox Web UI (If using Proxmox)¶
Built-in features:
- VM/LXC container management
- Resource monitoring
- ZFS pool status
- Backup scheduling
- Firewall configuration
- Node clustering
Access: https://proxmox-ip:8006
No additional software needed!
Optional: Grafana + Prometheus¶
For advanced monitoring:
# docker-compose.yml
prometheus:
image: prom/prometheus
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
- prometheus_data:/prometheus
grafana:
image: grafana/grafana
ports:
- 3001:3000
volumes:
- grafana_data:/var/lib/grafana
cadvisor:
image: gcr.io/cadvisor/cadvisor
volumes:
- /:/rootfs:ro
- /var/run:/var/run:ro
- /sys:/sys:ro
- /var/lib/docker/:/var/lib/docker:ro
Use case: Detailed metrics, historical data, custom alerts
Complexity: High (overkill for most homelabs)
Recommended Dashboard Stack:¶
For Proxmox setup:
- Proxmox Web UI (VM/LXC management)
- Portainer (Docker containers)
- Homepage (service dashboard)
For Ubuntu Server:
- Cockpit (system management)
- Portainer (Docker management)
- Homepage (service overview)
Access via Tailscale (never expose publicly)
10. Implementation Roadmap¶
Week 1: Foundation¶
Day 1-2: OS Installation
- Backup data from Hitachi 4TB to USB Maxtor 4TB
- Install Proxmox VE on Samsung EVO 250GB #1
- Configure static IP, update system
- Access web UI, familiarize with interface
Day 3-4: Storage Setup
- Create ZFS pool on Hitachi 4TB
- Mount second Samsung SSD for container storage
- Configure Samba shares (if needed for initial data access)
- Test write/read speeds
Day 5-7: Network & Security
- Configure UFW firewall
- Install Fail2Ban
- Set up SSH keys, harden SSH config
- Install Tailscale
- Test remote access from phone
Week 2: Core Services¶
Day 8-9: Docker Environment
- Create LXC container for Docker
- Install Docker + Docker Compose
- Set up directory structure (/opt/docker/)
- Deploy Portainer
Day 10-12: Media Stack
- Deploy Jellyfin, Sonarr, Radarr, Prowlarr
- Configure iGPU passthrough for transcoding
- Set up quality profiles (use TRaSH Guides)
- Configure indexers in Prowlarr
Day 13-14: Download Client
- Deploy qBittorrent
- Configure download paths
- Connect Sonarr/Radarr to qBittorrent
- Test automation (add show → download → import)
Week 3: Refinement¶
Day 15-16: Reverse Proxy
- Deploy Nginx Proxy Manager or Caddy
- Configure local domain names (jellyfin.home, sonarr.home)
- Set up SSL certificates (Let's Encrypt or self-signed)
Day 17-18: Dashboard
- Deploy Homepage dashboard
- Configure widgets with API keys
- Customize layout, test all links
Day 19-21: Monitoring
- Set up Uptime Kuma or similar
- Configure SMART monitoring
- Set up email alerts (or Ntfy)
- Test alert workflow
Week 4: Protection & Polish¶
Day 22-24: Backups
- Configure ZFS snapshots (automated)
- Set up rsync to USB Maxtor 4TB
- Configure Backblaze B2 + rclone
- Test restore process
Day 25-26: Documentation
- Document all passwords (in Bitwarden)
- Write down server access procedures
- Create disaster recovery runbook
- Take screenshots of important configs
Day 27-28: Testing & Optimization
- Full system test (access all services)
- Measure power consumption
- Verify transcoding works
- Fine-tune settings
Post-Deployment: Maintenance Schedule¶
Daily (Automated):
- Sonarr/Radarr checks for new episodes/movies
- Jellyfin metadata updates
- Docker container health checks
- ZFS scrub (if scheduled)
Weekly (5 minutes):
- Check Portainer dashboard for updates
- Review fail2ban logs for suspicious activity
- Verify backup completed successfully
- Glance at Homepage for any service issues
Monthly (30 minutes):
- Test restore random file from backup
- Review disk space usage
- Check SMART status on all drives
- Update Docker images:
docker-compose pull && docker-compose up -d - Review security logs
Quarterly (1 hour):
- Full backup verification (restore to test environment)
- Review and clean up old snapshots
- Check for Proxmox/system updates
- Audit user accounts and passwords
Annually (2 hours):
- Disaster recovery drill (simulate full system loss)
- Review and update documentation
- Plan for hardware refresh (if needed)
- Renew domain/SSL certificates (if manual)
Budget & Analyse des Coûts¶
Hardware (Déjà possédé):¶
- Tous composants PC: €0 ✓
- Disques existants: €0 ✓
- Achat recommandé: 1x disque externe 2-4TB pour rotation offsite: €70
Coûts d'exploitation:¶
| Item | Coût | Fréquence | Annuel |
|---|---|---|---|
| Électricité (70-80W) | €0.20/kWh | 24/7 | €123-140 |
| Google One Family (déjà payé) | €100/an | Annuel | €100 (existant) |
| Nom de domaine (optionnel) | €10 | Annuel | €10 |
| Total serveur | €133-150/an | ||
| Total avec Google One | €233-250/an |
Comparaison Cloud (Services équivalents):¶
Scénario SANS serveur (tout cloud):
| Service | Coût/an | Notes |
|---|---|---|
| Plex Pass ou Emby Premiere | €120 | Streaming média |
| Google One 2TB (existant) | €100 | Drive + Photos |
| Backblaze backup 2TB | €84 | Backup archives |
| DigitalOcean VPS (4GB) | €96 | Apps web (Umami, etc.) |
| Netlify/Vercel Pro | €60 | Hébergement sites |
| Total cloud complet | €460/an |
Scénario AVEC serveur maison:
| Service | Coût/an | Notes |
|---|---|---|
| Google One 2TB (existant) | €100 | Primary pour Drive/Photos |
| Serveur électricité | €140 | 80W 24/7 |
| Nom de domaine | €10 | Optionnel |
| Total serveur maison | €250/an |
Économies annuelles: €460 - €250 = €210/an
Retour sur investissement: €70 / €210/an = 4 mois
Optimisation électrique:¶
Configuration actuelle (avec GTX 970):
- Idle: 106W × 24h × 365j = 929 kWh/an = €186/an
Configuration optimisée (sans GTX 970, iGPU uniquement):
- Idle: 76W × 24h × 365j = 666 kWh/an = €133/an
- Économie: €53/an
Optimisation spin-down disques:
- HDDs en veille après 20min inactivité: -10W moyen
- Économie supplémentaire: €18/an
Coût électricité optimisé: €133 - €18 = €115/an
Total Cost of Ownership (TCO) sur 5 ans:¶
Serveur maison:
- Initial: €70 (disque offsite)
- Électricité: €115/an × 5 = €575
- Google One: €100/an × 5 = €500
- Domaine: €10/an × 5 = €50
- Total 5 ans: €1,195
- Moyenne annuelle: €239/an
Solution 100% cloud:
- Pas d'investissement initial
- Services: €460/an × 5 = €2,300
- Total 5 ans: €2,300
- Moyenne annuelle: €460/an
Économie sur 5 ans: €2,300 - €1,195 = €1,105
Avantages non monétaires:¶
✅ Contrôle total des données (pas de censure, fermeture compte)
✅ Pas de limite de bande passante ou stockage
✅ Confidentialité (données chez vous)
✅ Performances réseau local (Gigabit vs Internet)
✅ Apprentissage compétences sysadmin/DevOps
✅ Flexibilité pour tester nouvelles apps
Coûts cachés potentiels:¶
⚠️ Remplacement disques: 1 disque tous les 5 ans = €50-150/disque
⚠️ Maintenance temps: ~2h/mois = 24h/an (valeur selon votre temps)
⚠️ Upgrades: RAM, CPU, carte mère si obsolescence (mais 5-10 ans)
Verdict: Rentable dès 4 mois, très rentable sur 5+ ans
Power Optimization Impact:¶
Removing GTX 970:
- Current: 106W → 76W = 30W saved
- Annual savings: 30W × 24h × 365d × €0.20/kWh = €53/year
HDD spin-down (media drive):
- Savings: ~10W average
- Annual: €18/year
Total optimized cost: €140 - €53 - €18 = €69/year
Troubleshooting Guide¶
Common Issues & Solutions:¶
1. Can't access Proxmox web UI
# Check network config
ip addr show
# Should see IP address
# Restart networking
systemctl restart networking
# Check firewall
ufw status
# If enabled, allow 8006: ufw allow 8006/tcp
2. Docker container won't start
# Check logs
docker logs container-name
# Common issues:
# - Port already in use: change port in docker-compose.yml
# - Permission denied: check volume permissions
# - Network conflict: docker network prune
3. Jellyfin transcoding not working
# Check if GPU accessible in container
docker exec jellyfin ls -la /dev/dri
# Should see: renderD128, card0
# If missing, verify device passthrough in docker-compose.yml
4. ZFS pool degraded
# Check pool status
zpool status
# If disk failed:
zpool replace storage old-disk new-disk
# Verify resilver progress
zpool status -v
5. Slow network transfers
# Test network speed
iperf3 -s # On server
iperf3 -c server-ip # On client
# Should see ~900 Mbps on Gigabit
# Check: Bad cable, switch port issue, NIC driver
Emergency Recovery:¶
Boot failure:
- Boot from Proxmox USB installer
- Choose "Rescue" mode
- Mount root filesystem
- Check /etc/fstab for errors
Data loss:
- Stop all services immediately
- Mount drives read-only
- Run photorec/testdisk recovery
- Restore from backup
Compromised system:
- Disconnect from network
- Check /var/log/auth.log for intrusion
- Rotate all passwords
- Reinstall from scratch
- Restore data from backup
Resources & Community¶
Documentation:¶
- Proxmox: https://pve.proxmox.com/wiki/
- TRaSH Guides: https://trash-guides.info/
- Jellyfin: https://jellyfin.org/docs/
- Servarr: https://wiki.servarr.com/
- Docker: https://docs.docker.com/
Communities:¶
- r/homelab: Hardware & infrastructure discussions
- r/selfhosted: Self-hosted services & tutorials
- r/proxmox: Proxmox-specific help
- r/DataHoarder: Storage & backup strategies
- Servarr Discord: https://discord.gg/M6BvZn5
Tools:¶
- Tailscale: https://tailscale.com/
- Portainer: https://www.portainer.io/
- Homepage: https://gethomepage.dev/
- Caddy: https://caddyserver.com/
Monitoring:¶
- Uptime Kuma: https://github.com/louislam/uptime-kuma
- Healthchecks.io: https://healthchecks.io/
- Grafana: https://grafana.com/
Learning:¶
- TechnoTim YouTube: Homelab tutorials
- Awesome-Selfhosted: https://github.com/awesome-selfhosted/awesome-selfhosted
- HomelabOS: https://homelabos.com/
Final Recommendations¶
Your Optimal Configuration:¶
Proxmox VE Host
├── SSD 250GB #1: Proxmox OS
├── SSD 250GB #2: LXC/VM storage
├── HDD 4TB: ZFS media pool
└── USB 4TB: Automated backups
LXC Containers:
├── Media (4GB RAM): Jellyfin, Sonarr, Radarr, Prowlarr
├── Downloads (2GB): qBittorrent + VPN (optional)
├── Management (1GB): Portainer, Homepage
└── Web Apps (2GB): Umami, databases (future)
Networking:
├── Tailscale for remote access
├── Caddy for local reverse proxy
└── Firewall: only Tailscale port open
Backups:
├── ZFS snapshots (hourly)
├── USB 4TB (daily rsync)
├── HGST 1TB (monthly offsite rotation)
└── Backblaze B2 (weekly, critical data)
Why This Works:¶
✅ Flexible: Start simple, add complexity as needed ✅ Secure: Multiple layers of protection ✅ Reliable: RAID alternative (ZFS + backups) ✅ Efficient: 70W power consumption (€70/year) ✅ Scalable: Easy to add services/storage ✅ Proven: Thousands use this exact stack
Your First Steps:¶
- This weekend: Install Proxmox, set up storage
- Next week: Deploy media stack (Jellyfin + *arr)
- Week after: Configure remote access (Tailscale)
- Ongoing: Add services as needed
When to Ask for Help:¶
- Proxmox Forum: Configuration issues
- r/selfhosted: "Is this normal?" questions
- Servarr Discord: Media automation help
- r/homelab: Hardware compatibility
Success Metrics:¶
After 1 month, you should have:
- Jellyfin streaming to phone over Tailscale
- Sonarr/Radarr automatically downloading shows
- Homepage dashboard showing all services
- Automated backups running nightly
- Zero exposed ports to internet
- Power usage <100W
- System uptime >99%
You're ready to build! 🚀
Questions? Check the communities linked above. Good luck!