Phase: N (End-User Documentation) Step: N.18 Since: 0.18.0
TL;DR
Phlix needs three things to survive a disaster: the database (users, watch history, library metadata), config files (JWT secret, DB credentials, server settings), and metadata images (posters, fanart). You do NOT need to back up the transcode cache, active job state, or scan cache — these are regenerated automatically. Back up regularly (daily is recommended), store off-site, and test restores quarterly.
1. What to Back Up
1. Database
What: All Phlix data — users, watch history, media library metadata, playback state, sessions.
mysqldump -u phlix -p phlix_db > phlix-db-$(date +%Y%m%d).sqlFor MariaDB the command is identical. Verify the dump is valid:
# Check the dump starts correctly
head -5 phlix-db-20250601.sql
# Should show: -- MySQL dump 10.x ... or -- MariaDB dump ...2. Config Files
What: config/ directory — server.php, database.php, ffmpeg.php, backups.php (if present). These contain your JWT_SECRET, DB credentials, and all server settings.
tar czf phlix-config-$(date +%Y%m%d).tar.gz -C /path/to/phlix config/3. Metadata Images
What: data/metadata/ — poster.jpg, fanart.jpg, and all artwork downloaded from TMDB/TVDB. These are not stored in the DB; they live on disk.
tar czf phlix-metadata-images-$(date +%Y%m%d).tar.gz -C /path/to/phlix data/metadata/These can be re-downloaded by re-scanning your library, but re-downloading from TMDB/TVDB takes significant time and may hit rate limits. A local backup is much faster to restore.
4. Plugin Configs
What: data/plugins/ if you have custom plugins installed that store configuration on disk.
tar czf phlix-plugins-$(date +%Y%m%d).tar.gz -C /path/to/phlix data/plugins/5. TLS Certificates
What: config/ssl/ for self-hosted deployments using custom HTTPS certificates.
NOT Needed
| What | Why |
|---|---|
data/transcode/* | Regenerated on next transcode |
| Active transcode job state | Lost on crash, not recoverable |
| Scan cache | Regenerated on library rescan |
*.log files | Regenerated by the logging system |
2. Backup Methods
2.1 Manual Backup (CLI)
# Database
mysqldump -u phlix -p phlix_db > phlix-db-$(date +%Y%m%d).sql
# Full tarball — everything that matters (excluding transcode and logs)
tar czf phlix-backup-$(date +%Y%m%d).tar.gz \
-C /path/to/phlix \
config/ data/metadata/ data/plugins/ \
--exclude='data/transcode/*' \
--exclude='*.log'2.2 Built-in Phlix CLI
php bin/phlix backup:create --output /backups/phlix-$(date +%Y%m%d).tar.gzThe built-in command packages the same paths as the manual tarball above but in a single invocation.
2.3 Automated (Cron / systemd timer)
# /etc/cron.d/phlix-backup — daily at 03:00
0 3 * * * root /usr/bin/php /home/phlix/bin/phlix backup:create \
--output /backups/phlix-$(date +\%Y\%m\%d).tar.gz && \
/usr/bin/find /backups -name 'phlix-*.tar.gz' -mtime +7 -deleteThis creates a daily backup and removes backups older than 7 days. Adjust --mtime +7 to retain more or fewer days.
For systemd instead of cron:
# /etc/systemd/system/phlix-backup.timer
[Unit]
Description=Daily Phlix backup
[Timer]
OnCalendar=daily
Persistent=true
[Install]
WantedBy=timers.target2.4 Third-Party Tools (Restic / Borg / rsync)
Wrap the tarball or point rsync/restic directly at the above paths:
# Restic — backup to S3/B2/NAS
restic -r s3:s3.amazonaws.com/bucket/phlix-backups \
backup /path/to/phlix/config /path/to/phlix/data/metadata
# rsync to NAS
rsync -avz --exclude='data/transcode' --exclude='*.log' \
/path/to/phlix/ backup-server:/backups/phlix/For off-site copies:
rclone copy phlix-backup-$(date +%Y%m%d).tar.gz b2:my-bucket/phlix/3. Restore Process
Critical: Always restore the database and config from the same backup point. Mixing configs from different points can cause JWT_SECRET mismatches (see Failure 2 below).
Step-by-step
- Stop Phlix
systemctl stop phlix
# or
php bin/phlix stop- Restore database
mysql -u phlix -p phlix_db < phlix-db-20250601.sql- Restore config and data
tar -xzf phlix-backup-20250601.tar.gz -C /
# Verify paths match your installation
ls /path/to/phlix/config/
ls /path/to/phlix/data/metadata/- Start Phlix
systemctl start phlix
# or
php bin/phlix start- Verify
Log in, check your library items are visible, confirm watch history is present. If metadata images are missing, trigger a library rescan:
php bin/phlix library:rescan --force4. Docker / docker-compose Backup
Using docker compose exec
# Inside the container — backups land in the named volume
docker compose exec phlix-server phlix backup:create \
--output /backups/phlix-$(date +%Y%m%d).tar.gz
# Copy the backup out of the container
docker compose cp phlix-server:/backups/phlix-20250601.tar.gz ./phlix-backup-20250601.tar.gzBacking up named volumes directly
# Backup the named volumes directly (does not need Phlix running)
docker run --rm \
-v phlix_data:/data \
-v $(pwd):/backup \
alpine \
tar czf /backup/phlix_data.tar.gz -C /data .Restoring Docker volumes
# Restore
docker run --rm \
-v phlix_data:/data \
-v $(pwd):/backup \
alpine \
tar xzf /backup/phlix_data.tar.gz -C /data
# Restart Phlix
docker compose up -d phlix-server5. What Can Go Wrong
Failure 1 — Corrupt or Incomplete Backup
Symptom: Restore succeeds but some tables are empty or SQL errors on import.
Fix: Always verify checksums after backup:
sha256sum phlix-backup-20250601.tar.gz
# Store the checksum alongside the backup or in a separate logTest restores periodically (e.g., monthly) in a staging environment. A backup that was never tested is not a reliable backup.
Failure 2 — JWT Secret Mismatch (Users Can't Log In)
Symptom: Database restored, but all login attempts fail with auth errors.
Cause: JWT_SECRET in config/server.php was not restored, or the backup config used a different secret than the one the server is currently using.
Fix: Restore config/server.php from the same backup as the database. Never rotate JWT_SECRET without also backing up the old value and all existing refresh tokens (stored hashed in the DB).
# Verify JWT_SECRET is consistent between backup and running config
grep JWT_SECRET /path/to/phlix/config/server.phpFailure 3 — Media Not Re-Scanning After Restore (Stale mtime)
Symptom: Library shows items but poster/fanart missing; rescan doesn't re-download metadata.
Cause: FolderWatcher uses mtime as its checksum. If the backup was restored to the same filesystem paths, mtimes are preserved and the watcher sees "no change."
Fix: Force a full rescan after restore:
php bin/phlix library:rescan --force
# OR touch all media files to update mtime
find /path/to/media -type f -exec touch {} \;Failure 4 — Backup Too Large (Transcode Cache Included)
Symptom: Backups are 50 GB+, slow to transfer, fill up backup storage.
Cause: data/transcode/ directory included in tarball.
Fix: Always exclude data/transcode/* from tar commands:
tar czf phlix-backup-$(date +%Y%m%d).tar.gz \
-C /path/to/phlix \
config/ data/metadata/ data/plugins/ \
--exclude='data/transcode/*' \
--exclude='*.log'Active transcode job state is not recoverable anyway — excluding it saves space with zero data loss.
6. Next Steps
- Troubleshooting — general recovery help if restore has unexpected issues
- Logs — reading server logs during and after restore to confirm health
- Server Connectivity — verify your server is correctly configured after restore
- Consider setting up monitoring/alerting on backup job success/failure (e.g., check
backup.logforbackup:create completed)