7.4 KiB
7.4 KiB
Seafile & Immich Backup Strategy Analysis
When to Use
When planning offsite/backup strategy for Seafile (558 GB) or Immich on bandwidth-limited remote PBS, and deciding what to back up vs. what to leave on Ceph-only redundancy.
Seafile Backup Strategies (6 Options)
Context
- Seafile Pro 13.0.19 MC Docker edition on CT111
- File blocks:
/opt/seafile-data/seafile/seafile-data/storage/blocks/(intrinsically deduplicated, content-addressable) - Config:
/opt/seafile/.env,seafile.conf,seahub_settings.py - DB: MySQL (
seafile_db,ccnet_db,seahub_db) — currently inseafile-mysqlcontainer, migration to Galera planned - Total size: ~558 GB (mostly file blocks)
- Ceph redundancy: blocks stored on Ceph EC4+1 (5 HDD OSDs, 1-failure tolerance)
Option Matrix
| # | Strategy | Offsite Volume | Pros | Cons |
|---|---|---|---|---|
| 1 | PBS Full (current) | 558 GB init, then delta | Simple, everything included | Huge for offsite, slow restore |
| 2 | Config+DB only | <1 GB | Fast daily offsite, trivial restore | Blocks only in Ceph — total Ceph loss = all files gone |
| 3 | SeafGC + PBS exclude blocks | ~2 GB | Clean, regularly garbage-collected | Blocks only in Ceph, needs GC discipline |
| 4 | Seafile Native Backup | Variable | Official way, incremental | Needs second Seafile server (not S3) |
| 5 | RBD Snapshot + PBS | 558 GB init, delta like #1 | Point-in-time consistent | Ceph pool must support snapshots |
| 6 | Blocks on S3 (Pro feature) | Rootfs ~2 GB offsite, blocks on S3 | Clean separation, Ceph relieved | Migration effort, S3 costs |
Recommendation
- Short-term: Option 2 (Config+DB offsite) + regular
seaf-gc.sh. Blocks are redundant in Ceph EC4+1. For DR against total Ceph loss: Option 4 as second pillar. - Long-term: Option 6 (S3 storage backend) — moves blocks out of Ceph entirely, making PBS offsite trivial (~2 GB) and Ceph only hosts config+DB.
Seafile Pro S3 Storage Backend
Seafile Pro supports S3 as primary storage backend (not backup target). All file blocks are stored directly on S3 instead of local disk/Ceph.
Configuration (in seafile.conf)
[storage_backend]
name = s3
bucket = seafile-data
key_id = XXX
key = XXX
region = eu-central-1
endpoint = https://s3.example.com
Key Distinctions
- Primary storage — replaces local/Ceph block storage entirely
- NOT a backup target — S3 is where live data lives, not a backup copy
- Migration required — existing blocks must be migrated to S3
- Ceph relief — once on S3, Ceph only holds config+DB (~2 GB), making PBS offsite backup trivial and fast
When to Choose S3 Backend
- Ceph capacity is constrained (OSDs near full)
- Offsite backup of 558 GB blocks is impractical (bandwidth-limited)
- S3 storage is cheaper than maintaining Ceph OSDs
- Want clean separation: config+DB on Ceph (small, fast), blocks on S3 (large, cheap)
Seafile Native Backup (seaf-backup-cmd)
How It Works
- Uses Seafile's internal RPC API to synchronize libraries to a second Seafile server
- Incremental — only changed commits/blocks are transferred
- The second server must be a full Seafile server (same version)
- Commands:
seaf-backup-cmd status,seaf-backup-cmd sync <repo-id>
Limitations
- Needs a second Seafile server — not a simple file/rsync target
- Not S3-compatible — target must be Seafile server with storage backend
- Setup complexity — must configure backup server in
seafile.conf - Per-library sync — no global "backup everything" by default
Location
# In the seafile container:
docker exec seafile /opt/seafile/seafile-server-latest/seahub/scripts/seaf-backup-cmd.sh
# Error without proper SEAFILE_DATA_DIR env — needs server running
When to Choose
- Need true DR replica (second running Seafile instance)
- Have infrastructure for a second server
- Want incremental, deduplicated replication (not full copies)
Immich Backup Considerations
Architecture
- CT115 (immich): stopped, 20 GB rootfs — upload directory location unclear
- CT117 (immich-postgresql): running, 914 MB DB on proxmox6
- Photos/videos are NOT deduplicated (unlike Seafile blocks)
Strategy Options
| # | Strategy | Offsite Volume | Notes |
|---|---|---|---|
| 1 | PBS Full both CTs | ~21 GB | Simple but may grow |
| 2 | DB dump + upload-dir rsync | DB ~1 GB + uploads | Selective |
| 3 | DB only offsite | <1 GB | Photos only in Ceph |
| 4 | Uploads on Ceph, DB on Galera | DB offsite <1 GB | Clean separation |
Key Question
Where are the actual photo/video uploads stored? CT115 is stopped — uploads may be on a mount point, external volume, or within the PostgreSQL CT. Must identify before choosing a strategy.
Bandwidth-Aware Offsite Backup Prioritization
When adding services to a bandwidth-limited offsite PBS:
Tier 1: Small + Critical Infrastructure (add first)
- Traefik (~3 GB) — reverse proxy config, all routes
- Gitea (~1.2 GB) — code repositories
- Authelia, DNS — tiny but critical
- Paperless (~16 GB) — documents (medium size, high value)
Tier 2: Medium + Important
- Litellm (~3.4 GB) — API config
- Seafile config+DB (~2 GB) — without blocks
Tier 3: Evaluate Separately
- Seafile blocks (~558 GB) — consider S3 backend or native backup
- Immich uploads — identify storage location first
Skip
- Frigate (~40 GB) — rewritable video, low value
- High-churn data that's easily regenerated
PBS Offsite Job Configuration
Adding CTs to Offsite Job
# Edit /etc/pve/jobs.cfg from any PVE node (pmxcfs replicates)
# Current: vmid 106
# Target: vmid 106,108,104,99999
sed -i '/offsite-ha-daily/,/^$/{s/vmid 106/vmid 106,108,104,99999/}' /etc/pve/jobs.cfg
Initial Full Backup (Manual)
Must run vzdump on the node where each CT actually runs (see
proxmox-ve-administration → references/pbs-lxc-setup-2026-07.md
pitfall #17 for the silent-skip issue):
# Determine node for each CT first
pvesh get /cluster/resources --type vm --output-format json | python3 -c "
import json,sys
for v in json.load(sys.stdin):
if v.get('vmid') in [108,99999,104]:
print(f\"CT{v['vmid']:5d} node={v['node']}\")"
# Run on correct nodes
ssh root@10.0.20.60 "vzdump 108 --storage noris_offsite --mode snapshot --compress zstd"
ssh root@10.0.20.70 "vzdump 99999 --storage noris_offsite --mode snapshot --compress zstd"
ssh root@10.0.20.91 "vzdump 104 --storage noris_offsite --mode snapshot --compress zstd"
Verification
# Check backups arrived at PBS (may need content cache refresh)
pvesh get /nodes/proxmox1/storage/noris_offsite/content --output-format json | \
python3 -c "
import json,sys,datetime
for b in sorted(json.load(sys.stdin), key=lambda x: x.get('ctime',0), reverse=True)[:10]:
print(f\"{b['volid']:55s} {b.get('size',0)//1024//1024:>8} MB {datetime.datetime.fromtimestamp(b.get('ctime',0)).strftime('%Y-%m-%d %H:%M')}\")"
Session Context (2026-07-07)
- Offsite job expanded:
vmid 106→vmid 106,108,104,99999 - Initial full backups triggered manually on correct nodes
- CT111 (Seafile) backup showed 0 MB on noris_s3 — empty/failed backup (previous valid: 558 GB on 2026-07-06)
- Frigate excluded from all backups per user decision
- Seafile backup strategy discussion: user exploring alternatives to 558 GB full backup, considering S3 storage backend (Pro feature)
- Immich: CT115 stopped, upload location unidentified