Install Immich on Raspberry Pi
Why Raspberry Pi for Immich?
A Raspberry Pi is the cheapest way to run Immich at home. It draws 5-15 watts, runs silently, and costs under $100. The trade-off is performance: ML processing is slow, large uploads take longer, and you need to tune the configuration carefully to avoid running out of memory.
This guide is specifically for the Pi. It covers ARM64 compatibility, memory management, storage choices, and how to disable or limit ML features so Immich runs reliably on constrained hardware.
Pi 3 and older are not supported. Immich requires a minimum of 4 GB RAM. The Pi 3 maxes out at 1 GB and will not run the stack.
Prerequisites
- Raspberry Pi 4 (4 GB or 8 GB model) or Raspberry Pi 5 (4 GB or 8 GB model)
- Raspberry Pi OS (64-bit) — Bullseye or Bookworm. The 64-bit (arm64) image is required. Immich does not publish 32-bit ARM images.
- USB SSD (strongly recommended) — running the database on an SD card will cause poor performance and premature card failure. A 256 GB+ USB SSD is the minimum practical setup.
- SD card (32 GB+ if not booting from SSD) — for the OS if you are not boot-from-USB
- Adequate power supply:
- Pi 4: Official USB-C 5V/3A (15W) power supply
- Pi 5: Official USB-C 5V/5A (27W) power supply
- Cooling: Active cooling (fan case or heatsink with fan). Immich will sustain high CPU loads during ML processing and the Pi will thermal throttle without cooling.
- Ethernet connection (recommended) — more reliable than WiFi for upload syncing
Platform Setup
Flash Raspberry Pi OS (64-bit)
Use the Raspberry Pi Imager to flash Raspberry Pi OS Lite (64-bit) to your SD card or USB SSD. The Lite image (no desktop) is preferred — you do not need a GUI for a headless server.
In the imager’s advanced settings, enable SSH and set a username/password before flashing.
Boot the Pi, SSH in, and verify you are running 64-bit:
uname -m
# Expected output: aarch64
If it shows armv7l, you flashed the 32-bit image. Re-flash with the 64-bit version.
Set Up USB SSD Storage
If you booted from an SD card but want your data on a USB SSD (recommended), connect the SSD and identify it:
lsblk
Format and mount the SSD:
# Create a partition (replace /dev/sda with your device)
sudo fdisk /dev/sda
# Type: n (new partition), p (primary), accept defaults, w (write)
# Format as ext4
sudo mkfs.ext4 /dev/sda1
# Create mount point and mount
sudo mkdir -p /mnt/ssd
sudo mount /dev/sda1 /mnt/ssd
# Add to fstab for auto-mount on boot
echo "/dev/sda1 /mnt/ssd ext4 defaults,noatime 0 2" | sudo tee -a /etc/fstab
Boot from USB SSD (Pi 4/5): For best performance, boot the entire OS from the SSD. Use sudo raspi-config > Advanced Options > Boot Order > USB Boot. This eliminates the SD card bottleneck entirely.
Increase Swap
The default swap on Raspberry Pi OS is 100 MB, which is far too little for Immich. Increase it to 2 GB:
# Disable current swap
sudo dphys-swapfile swapoff
# Edit swap configuration
sudo nano /etc/dphys-swapfile
# Change CONF_SWAPSIZE=100 to:
# CONF_SWAPSIZE=2048
# If running from SSD, also set the swap file location:
# CONF_SWAPFILE=/mnt/ssd/swapfile
# Re-enable swap
sudo dphys-swapfile setup
sudo dphys-swapfile swapon
# Verify
free -h
The swap should show ~2 GB. On an SSD, swap performance is acceptable. On an SD card, swap will be slow but still better than OOM kills.
Install Docker
# Install Docker using the official convenience script
curl -fsSL https://get.docker.com | sudo sh
# Add your user to the docker group
sudo usermod -aG docker $USER
newgrp docker
# Verify
docker --version
docker compose version
Install Cooling
This is not optional for Immich. During ML processing, the Pi’s CPU will sustain 100% load for hours. Without active cooling, the CPU will thermal throttle to 600-800 MHz, making processing painfully slow. A Pi case with a fan (like the official Pi 5 Active Cooler or a Flirc case with a fan hat) is the minimum.
Check CPU temperature:
vcgencmd measure_temp
If idle temperature is above 60 C, your cooling is insufficient. Under load, aim to stay below 80 C.
Docker Compose Configuration
Create the project directory on the SSD:
sudo mkdir -p /mnt/ssd/immich && cd /mnt/ssd/immich
If you are running everything on the SD card (not recommended), use /opt/immich instead.
Create a .env file:
# /mnt/ssd/immich/.env
# Photo and video storage -- put this on the SSD.
UPLOAD_LOCATION=/mnt/ssd/immich/library
# PostgreSQL data -- MUST be on the SSD. SD card IOPS will destroy database performance.
DB_DATA_LOCATION=/mnt/ssd/immich/postgres
# Timezone
TZ=America/New_York
# Immich version -- always pin.
IMMICH_VERSION=v1.131.3
# PostgreSQL credentials. Change DB_PASSWORD to a strong random value.
DB_PASSWORD=CHANGE_ME_TO_A_RANDOM_STRING
DB_USERNAME=postgres
DB_DATABASE_NAME=immich
Create the docker-compose.yml. This configuration is tuned for the Pi’s limited resources:
# /mnt/ssd/immich/docker-compose.yml
name: immich
services:
immich-server:
container_name: immich_server
image: ghcr.io/immich-app/immich-server:${IMMICH_VERSION}
volumes:
- ${UPLOAD_LOCATION}:/data
- /etc/localtime:/etc/localtime:ro
env_file:
- .env
ports:
- "2283:2283"
depends_on:
redis:
condition: service_healthy
database:
condition: service_healthy
restart: unless-stopped
healthcheck:
disable: false
immich-machine-learning:
container_name: immich_machine_learning
image: ghcr.io/immich-app/immich-machine-learning:${IMMICH_VERSION}
volumes:
- model-cache:/cache
env_file:
- .env
environment:
# Limit ML to a single worker to reduce memory usage
MACHINE_LEARNING_WORKERS: "1"
# Unload models quickly to free RAM when not processing
MACHINE_LEARNING_MODEL_TTL: "60"
restart: unless-stopped
healthcheck:
disable: false
redis:
container_name: immich_redis
image: docker.io/valkey/valkey:8-alpine
healthcheck:
test: valkey-cli ping || exit 1
interval: 10s
timeout: 5s
retries: 5
restart: unless-stopped
database:
container_name: immich_postgres
image: docker.io/tensorchord/pgvecto-rs:pg16-v0.4.0
environment:
POSTGRES_PASSWORD: ${DB_PASSWORD}
POSTGRES_USER: ${DB_USERNAME}
POSTGRES_DB: ${DB_DATABASE_NAME}
POSTGRES_INITDB_ARGS: "--data-checksums"
volumes:
- ${DB_DATA_LOCATION}:/var/lib/postgresql/data
# Limit PostgreSQL memory usage on the Pi
command: >
postgres
-c shared_buffers=256MB
-c effective_cache_size=512MB
-c work_mem=4MB
-c maintenance_work_mem=64MB
restart: unless-stopped
healthcheck:
test: pg_isready -U ${DB_USERNAME} -d ${DB_DATABASE_NAME} || exit 1
interval: 10s
timeout: 5s
retries: 5
volumes:
model-cache:
Create directories and start the stack:
sudo mkdir -p /mnt/ssd/immich/library /mnt/ssd/immich/postgres
cd /mnt/ssd/immich
docker compose up -d
First start takes longer on the Pi — pulling images (especially the ML image at ~1.5 GB) and initializing the database will take 5-10 minutes on a typical internet connection.
Verify everything is running:
docker compose ps
First-Time Setup
- Open
http://PI_IP_ADDRESS:2283in a browser from another device on your network. - Click Getting Started to create your admin account.
- Navigate to Administration and configure:
- Storage Template: Set a file organization pattern like
{{y}}/{{y}}-{{MM}}-{{dd}}/{{filename}}. - Machine Learning: Keep enabled but be aware initial processing will be very slow (see below).
- Video Transcoding: Set quality to “lower” or disable transcoding entirely to reduce CPU load. The Pi 4/5 has no hardware video encoder accessible via Docker.
- Storage Template: Set a file organization pattern like
Platform-Specific Optimization
Disable or Limit Machine Learning
The ML service is the heaviest component. On a Pi 4 with 4 GB RAM, running the full ML stack alongside the server, database, and cache is tight. You have three options:
Option 1: Keep ML enabled with tuning (recommended for 8 GB models)
The Compose file above already sets MACHINE_LEARNING_WORKERS=1 and MACHINE_LEARNING_MODEL_TTL=60. This limits memory usage at the cost of processing speed. Expect face detection to take 3-5x longer than on a desktop CPU.
Option 2: Disable ML entirely (recommended for 4 GB models)
If you are running the 4 GB Pi 4 and experience OOM kills, disable the ML container:
docker compose stop immich-machine-learning
Or remove the immich-machine-learning service from docker-compose.yml entirely. You lose facial recognition, smart search, and object detection, but uploads, browsing, albums, and sharing all work fine.
Option 3: Run ML on a separate machine
If you have another machine (even a cheap x86 mini PC), run the ML container there and point the Pi’s Immich server at it. Set the IMMICH_MACHINE_LEARNING_URL environment variable on the immich-server service:
immich-server:
environment:
IMMICH_MACHINE_LEARNING_URL: "http://OTHER_MACHINE_IP:3003"
Remove the immich-machine-learning service from the Pi’s Compose file.
Processing Speed Expectations
Be realistic about what the Pi can handle:
| Task | Pi 4 (4 GB) | Pi 5 (8 GB) | x86 Desktop (reference) |
|---|---|---|---|
| Initial ML processing (1,000 photos) | 8-12 hours | 4-6 hours | 30-60 minutes |
| Photo upload + thumbnail generation | ~2 seconds/photo | ~1 second/photo | ~0.3 seconds/photo |
| Face detection per photo | ~3-5 seconds | ~1.5-3 seconds | ~0.3 seconds |
| Video transcoding (1080p, 1 min) | 10-15 minutes | 5-8 minutes | 30-60 seconds |
These are rough estimates. Actual performance depends on photo resolution, video codec, and whether other services are competing for resources.
Storage Recommendations
| Setup | Recommendation |
|---|---|
| OS boot device | USB SSD (best) or SD card (acceptable) |
Database (DB_DATA_LOCATION) | Must be on SSD. SD cards cannot handle database write patterns. |
Photo library (UPLOAD_LOCATION) | SSD for best performance. External USB HDD acceptable for large libraries if you tolerate slower thumbnailing. |
| ML model cache | Named Docker volume on the SSD. Models are ~2-4 GB total. |
Automatic Updates
Create a simple update script:
sudo tee /opt/update-immich.sh > /dev/null <<'EOF'
#!/bin/bash
cd /mnt/ssd/immich
# Backup database before update
docker exec immich_postgres pg_dump -U postgres -d immich > /mnt/ssd/immich/backups/pre-update-$(date +%Y%m%d).sql
# Pull new images and restart
docker compose pull
docker compose up -d
docker image prune -f
EOF
sudo chmod +x /opt/update-immich.sh
Run it manually after updating the IMMICH_VERSION in .env. Do not automate version bumps — always read the release notes first.
Troubleshooting
OOM Kills (Container Exits with Code 137)
Symptom: The immich_machine_learning or immich_postgres container exits with code 137 (killed by the kernel).
Fix: The Pi is running out of memory. Check with:
dmesg | grep -i "out of memory"
Solutions in order of effectiveness:
- Increase swap to 2 GB (see Platform Setup above).
- Disable the ML container if running 4 GB Pi 4.
- Reduce PostgreSQL shared_buffers to
128MBin the Composecommand. - Close any other services running on the Pi.
SD Card Corruption
Symptom: After a power loss, the Pi fails to boot or Docker containers show filesystem errors.
Fix: SD cards are vulnerable to corruption on unclean shutdown. Prevention:
- Use a UPS (even a small USB battery pack) to allow clean shutdown on power loss.
- Move the database and upload directory to a USB SSD (this guide recommends this by default).
- Mount the SD card with
noatimeandcommit=60in/etc/fstabto reduce writes:
/dev/mmcblk0p2 / ext4 defaults,noatime,commit=60 0 1
If corruption has occurred, re-flash the SD card and restore from backup.
Thermal Throttling During ML Processing
Symptom: ML processing is extremely slow. vcgencmd get_throttled returns a non-zero value.
Fix: Check:
vcgencmd measure_temp
vcgencmd get_throttled
If temperature is above 80 C, your cooling is insufficient. Solutions:
- Add a fan (the official Pi 5 Active Cooler works well).
- Use a metal heatsink case (Flirc, Argon ONE) with a fan.
- Place the Pi in a well-ventilated location, not inside an enclosed cabinet.
ARM64 Image Pull Fails
Symptom: Docker pull fails with no matching manifest for linux/arm64.
Fix: Verify you are running a 64-bit OS:
dpkg --print-architecture
This must return arm64. If it returns armhf, you installed the 32-bit Raspberry Pi OS. Re-flash with the 64-bit image.
All Immich images (immich-server, immich-machine-learning, pgvecto-rs) publish multi-arch manifests that include linux/arm64. If a specific version lacks ARM64 support, check the Immich GitHub releases for notes.
Slow Web UI
Symptom: The Immich web UI is sluggish, especially when scrolling through the timeline.
Fix: This is normal on the Pi. Thumbnail generation is CPU-bound and happens on first view. After all thumbnails are generated, browsing speeds up. To pre-generate thumbnails for your entire library, go to Administration > Jobs and run the Generate Thumbnails job. Let it run overnight.
Resource Requirements
- RAM: 3-4 GB with ML enabled (tight on 4 GB Pi), 1.5-2 GB with ML disabled. 8 GB Pi models are strongly recommended.
- CPU: All 4 cores will be used during ML processing. Idle usage is ~5-10% CPU.
- Disk: 15 GB for the application, database, and ML model cache on SSD. Photo storage depends on library size.
- Power: Pi 4 draws ~7-12 W under load, Pi 5 draws ~10-18 W. Ensure your power supply meets the requirement.
Related
Get self-hosting tips in your inbox
Get the Docker Compose configs, hardware picks, and setup shortcuts we don't put in articles. Weekly. No spam.
Comments