Skip to content

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

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

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):

# Créer script robuste
sudo nano /usr/local/bin/snapraid-runner.sh
#!/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

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

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)

TailscaleEASIEST & 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:

cloudflared tunnel create homeserver
cloudflared tunnel route dns homeserver umami.yourdomain.com

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:

  1. Primary: Tailscale for all remote access
  2. Secondary: Reverse proxy for local network only
  3. 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 + .env files
  • 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:

# Quotidien à 3h du matin
0 3 * * * /usr/local/bin/backup-configs.sh

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:

  1. Le navigateur s'ouvre automatiquement
  2. Sélectionner compte Google approprié
  3. Accepter les permissions rclone
  4. Copier le code fourni dans terminal (si headless)
  5. 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:

# Tous les dimanches à 4h (hebdomadaire suffisant)
0 4 * * 0 /usr/local/bin/sync-gdrive.sh

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:

  1. Qualité des téléchargements:
  2. ❌ Google peut ré-encoder les photos/vidéos (pas bit-perfect)
  3. ❌ Motion Photos/Live Photos peuvent perdre composant vidéo
  4. ❌ Métadonnées EXIF parfois incomplètes
  5. Structure:
  6. ❌ Albums partagés non synchronisables
  7. ❌ Structure d'albums non préservée (toutes photos en vrac)
  8. ❌ Doublons possibles entre albums et bibliothèque

  9. API limitations:

  10. ⚠️ Rate limiting: Google limite à ~10,000 requêtes/jour
  11. ⚠️ Sync initial 400GB peut prendre 24-48 heures
  12. ⚠️ 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:

# Tous les dimanches à 5h
0 5 * * 0 /usr/local/bin/sync-gphotos.sh

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:

  1. Consolider/dédupliquer archives dispersées
  2. Retirer de Google Drive (libérer espace)
  3. Stocker sur serveur (accès rare acceptable)
  4. 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 fix ré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:

  1. Reinstall Proxmox on new SSD
  2. Restore docker-compose files from cloud
  3. Restore data from USB backup
  4. 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: sensors command, 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

0 6 * * 0 /usr/local/bin/smart-check.sh | mail -s "SMART Report" your@email.com

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):

# Check status
aa-status

# Enforce all profiles
aa-enforce /etc/apparmor.d/*

Layer 5: Monitoring & Alerts

Logwatch (daily summaries):

apt install logwatch

# Configured to email daily
# Check /etc/cron.daily/00logwatch

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

PortainerBEST 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)

For Proxmox setup:

  1. Proxmox Web UI (VM/LXC management)
  2. Portainer (Docker containers)
  3. Homepage (service dashboard)

For Ubuntu Server:

  1. Cockpit (system management)
  2. Portainer (Docker management)
  3. 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:

  1. Boot from Proxmox USB installer
  2. Choose "Rescue" mode
  3. Mount root filesystem
  4. Check /etc/fstab for errors

Data loss:

  1. Stop all services immediately
  2. Mount drives read-only
  3. Run photorec/testdisk recovery
  4. Restore from backup

Compromised system:

  1. Disconnect from network
  2. Check /var/log/auth.log for intrusion
  3. Rotate all passwords
  4. Reinstall from scratch
  5. Restore data from backup

Resources & Community

Documentation:

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:

Monitoring:

Learning:


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:

  1. This weekend: Install Proxmox, set up storage
  2. Next week: Deploy media stack (Jellyfin + *arr)
  3. Week after: Configure remote access (Tailscale)
  4. 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!