Self-hosted photo and video management solution
Enable Immich by setting COMPOSE_PROFILES=immich.
Set the IMMICH_HOSTNAME, since it does not support
running in a subfolder.
Add the necessary DNS records in your domain.
| Variable | Description | Default |
|---|---|---|
IMMICH_HOSTNAME |
URL Immich will be accessible from | |
IMMICH_UPLOAD_LOCATION |
Path where the assets will be stored | /mnt/data/photos |
IMMICH_API_KEY |
Immich API key to show information in the homepage | 1000 |
IMMICH_DB_PASSWORD |
Postgres database password, change for more security | postgres |
Immich's database and media files can be backed up to any cloud storage product using Restic via resticker.
Restic provides:
- Incremental backups: Only changed data is backed up
- Deduplication: Identical content across snapshots uses minimal space
- Encryption: All data encrypted with your repository password
- Compression: Optional, doesn't interfere with deduplication
- Remote backends: S3, B2, SFTP, Rclone remotes, and more
- Upload directory (
${IMMICH_UPLOAD_LOCATION}): All original photos and videos uploaded by users - PostgreSQL database: Dumped as SQL before each backup
- Library data: Library-stored assets (if enabled in Immich settings)
- User profiles: User profile images
To save space, the following non-critical data is excluded and can be regenerated if needed:
- Thumbnails (
/data/thumbs/): ~20-30% space savings - Encoded videos (
/data/encoded-video/): Transcoded versions - Auto backups (
/data/backups/): Immich's built-in database backups
Copy the backup environment template and customize it:
cp immich/backup.env.example immich/backup.envEdit immich/backup.env and set the following:
| Variable | Description | Example |
|---|---|---|
RESTIC_REPOSITORY |
Backup destination URI for Restic | See examples below |
RESTIC_PASSWORD |
Strong password to encrypt the repository | Generate with openssl rand -base64 32 |
CRON |
Backup schedule (cron format with seconds) | 0 30 3 * * * (3:30 AM daily) |
TIMEZONE |
Timezone for cron scheduling | America/New_York |
RESTIC_FORGET_ARGS |
Backup retention policy | --keep-last 7 --keep-daily 7 --keep-weekly 4 --keep-monthly 3 |
Restic supports multiple backends. Pick one based on your infrastructure:
Rclone Remote (Optional - reuse existing rclone configuration):
Rclone is optional. Use this only if your RESTIC_REPOSITORY URI starts with rclone:. If you prefer to use Rclone, it allows you to back up to any service supported by Rclone (S3, B2, SFTP, Google Drive, OneDrive, Dropbox, etc.) without direct Restic support, or if you want to reuse existing Rclone configurations.
First, configure your rclone remote destination:
docker compose run --rm -it immich-backup rclone configThis interactive command will guide you through:
- Creating a new remote (choose
n) - Naming your remote (e.g.,
backup-s3,backup-b2,backup-sftp, etc.) - Selecting your storage type (S3, B2, SFTP, etc.)
- Entering credentials and configuration
The configuration will be saved to immich/.rclone/rclone.conf. Do not manually edit this file; use the rclone config command above to modify it.
Then set in backup.env:
RESTIC_REPOSITORY=rclone:myremote:/nas-backups/immichThis allows you to use any rclone-supported backend seamlessly.
S3-Compatible (Direct) (AWS, Wasabi, MinIO, DigitalOcean Spaces, etc. - no Rclone needed):
You can also back up directly to S3-compatible services without using Rclone:
# Set in backup.env:
RESTIC_REPOSITORY=s3:s3.amazonaws.com/my-bucket/immich
# Or for S3-compatible services:
RESTIC_REPOSITORY=s3:https://s3.wasabisys.com/my-bucket/immich
# Additional environment variables:
AWS_ACCESS_KEY_ID=your_key
AWS_SECRET_ACCESS_KEY=your_secretBackblaze B2 (Direct - no Rclone needed):
# Set in backup.env:
RESTIC_REPOSITORY=b2:my-bucket:immich
# And provide credentials:
B2_ACCOUNT_ID=your_account_id
B2_ACCOUNT_KEY=your_account_keySFTP (Direct - no Rclone needed):
# Set in backup.env:
RESTIC_REPOSITORY=sftp://user@backup.example.com/immich
# Password authentication is interactive or set:
SFTP_PASSWORD=your_sftp_passwordLocal Path (NAS mounted volume or local directory - no Rclone needed):
# Set in backup.env:
RESTIC_REPOSITORY=/mnt/backup-drive/immich
# Ensure the directory exists and is writable:
mkdir -p /mnt/backup-drive/immichGoogle Cloud Storage (Direct - no Rclone needed):
# Set in backup.env:
RESTIC_REPOSITORY=gs://my-bucket/immich
# And provide credentials (via service account JSON):
GOOGLE_APPLICATION_CREDENTIALS=/path/to/credentials.jsonAzure Blob Storage (Direct - no Rclone needed):
# Set in backup.env:
RESTIC_REPOSITORY=azure://immich-container/immich
# And provide credentials:
AZURE_ACCOUNT_NAME=myaccount
AZURE_ACCOUNT_KEY=mykey# Generate a strong random password
openssl rand -base64 32
# Copy the output and paste it into backup.env as RESTIC_PASSWORDImportant: Store this password securely. You'll need it to restore backups. If lost, your backup data becomes inaccessible.
docker compose run --rm immich-backup snapshotsThis will list all backup snapshots. If the repository doesn't exist yet, it will be initialized automatically on the first scheduled backup.
Perform a one-time backup:
docker compose run --rm immich-backup backup /dataThen apply the retention policy to clean up old snapshots:
docker compose run --rm immich-backup c forget --prune --keep-last 7 --keep-daily 7 --keep-weekly 4 --keep-monthly 3(Note: Replace the --keep-* arguments with your configured RESTIC_FORGET_ARGS from backup.env)
docker compose run --rm immich-backup checkStart the Immich service with the backup profile enabled:
COMPOSE_PROFILES=immich-backup docker compose up -dThen monitor backup logs:
docker compose logs -f immich-backupThe backup will run automatically according to the schedule in backup.env (default: 3:30 AM daily).
For detailed instructions on restoring Immich from backups, see the Immich Restore Documentation.
Quick restore overview:
- Stop the Immich service
- Restore the database dump:
psql -U postgres < db-dump.sql - Restore the upload directory from the Restic snapshot
- Start Immich again
To restore a specific snapshot:
docker compose run --rm immich-backup restore <snapshot-id> --target /restoredThen copy the files and database from /restored back to their original locations.