---
title: Immich on ZFS
description: Moving Immich to its own ZFS dataset
published: true
date: 2026-02-20T04:13:02.502Z
tags: service zfs immich dataset
editor: markdown
dateCreated: 2026-02-06T15:57:04.261Z
---

# Moving Immich to a ZFS Dataset

## Overview
This guide covers moving an existing Immich installation to its own ZFS dataset to enable `zfs send` backups.

## Prerequisites
- ZFS pool mounted at `/srv/vault`
- Existing Immich installation at `/srv/vault/immich`
- Immich running via Docker Compose

## Steps

### 1. Stop Immich Services
```bash
cd /srv/vault/immich  # or wherever your docker-compose.yml is
docker compose down
```

### 2. Create the New Dataset
```bash
sudo zfs create vault/immich
```

### 3. Move Existing Data Temporarily
```bash
sudo mv /srv/vault/immich /srv/vault/immich_old
```

### 4. Set Mountpoint and Mount Dataset
```bash
sudo zfs set mountpoint=/srv/immich vault/immich
sudo zfs mount vault/immich
```

### 5. Copy Data to New Dataset
```bash
sudo rsync -avxHAX /srv//immich_old/ /srv/immich/
```

Flags preserve permissions, ownership, and special attributes.

### 6. Verify Data Copy
```bash
sudo du -sh /srv/vault/immich_old
sudo du -sh /srv/vault/immich
```

Sizes should match closely.

### 7. Start Immich
```bash
cd /srv/vault/immich
docker compose up -d
```

### 8. Test and Clean Up
Verify everything works, then remove old data:
```bash
sudo rm -rf /srv/vault/immich_old
```

## ZFS Dataset Properties

### Recommended Settings
```bash
# Compression - helps with photos and database
sudo zfs set compression=lz4 vault/immich

# Record size - balance for mixed workload
sudo zfs set recordsize=128K vault/immich

# Better database performance
sudo zfs set primarycache=all vault/immich
sudo zfs set atime=off vault/immich
```

### Property Explanations
- **compression=lz4**: Fast, low CPU overhead, works well for both photos and database
- **recordsize=128K**: Good compromise between database (8K blocks) and photos (larger files)
- **atime=off**: Disables access time updates, reduces unnecessary writes
- **primarycache=all**: Keeps both metadata and data in ARC cache (default)

## Backup with ZFS Send/Receive

### Create Snapshot
```bash
zfs snapshot vault/immich@backup-$(date +%Y%m%d)
```

### Send to Remote Server
```bash
zfs send vault/immich@backup-$(date +%Y%m%d) | ssh backup-server zfs receive tank/backups/immich
```

### Incremental Backups
```bash
# After first full backup
zfs snapshot vault/immich@backup-$(date +%Y%m%d)
zfs send -i vault/immich@previous-snapshot vault/immich@backup-$(date +%Y%m%d) | \
  ssh backup-server zfs receive tank/backups/immich
```

## Optional: Separate Datasets for Database and Photos

For optimal performance, split into separate datasets:
```bash
sudo zfs create vault/immich/database
sudo zfs create vault/immich/photos

# Database optimized
sudo zfs set recordsize=16K vault/immich/database
sudo zfs set logbias=latency vault/immich/database

# Photos optimized  
sudo zfs set recordsize=1M vault/immich/photos
```

Then update your Docker Compose volume mounts accordingly.