I had Immich running. Then I lost the config files. The photos were still there — 5,700 of them, 62GB, sitting on a NAS — but the setup was gone.
New Immich install: connection refused. Classic.
Here’s everything I broke and how I fixed it.
The Connection Refused Rabbit Hole
Problem 1: Missing Hostname Variables
docker compose up ran fine. The web interface didn’t load. Logs said:
docker compose logs immich-server
# Error: getaddrinfo EAI_AGAIN databaseThe containers were looking for a host called database. My PostgreSQL container was named immich_postgres.
Fix: Two lines in .env:
DB_HOSTNAME=immich_postgres
REDIS_HOSTNAME=immich_redisProblem 2: Wrong Port (v1.x Habits Die Hard)
Still getting connection resets. Turns out I was using the old port config:
ports:
- 2283:3001 # Outdated. Will break silently.Immich v2.4+ changed the internal port from 3001 to 2283:
ports:
- 2283:2283 # This is what you want.If you’re coming from an older install, this one will absolutely catch you.
Problem 3: Volume Paths Changed Too
Same version, same surprise:
# Before
volumes:
- /srv/immich:/usr/src/app/upload
# After (v2.4+)
volumes:
- /srv/immich:/dataThe cool part is that once you’ve fixed all three of these, everything works. The frustrating part is finding all three.
The Working Config
Here’s the full docker-compose.yml that actually runs:
name: immich
services:
immich-server:
container_name: immich_server
image: ghcr.io/immich-app/immich-server:release
command: ["start.sh", "immich"]
volumes:
- /srv/immich:/data
- /etc/localtime:/etc/localtime:ro
env_file:
- .env
depends_on:
- immich_redis
- immich_postgres
ports:
- 2283:2283
restart: always
networks:
- immich_network
immich-microservices:
container_name: immich_microservices
image: ghcr.io/immich-app/immich-server:release
command: ["start.sh", "microservices"]
volumes:
- /srv/immich:/data:ro
- /etc/localtime:/etc/localtime:ro
env_file:
- .env
depends_on:
- immich_redis
- immich_postgres
restart: always
networks:
- immich_network
immich-machine-learning:
container_name: immich_machine_learning
image: ghcr.io/immich-app/immich-machine-learning:release
volumes:
- /srv/immich/ml-cache:/cache
env_file:
- .env
restart: always
networks:
- immich_network
immich_postgres:
container_name: immich_postgres
image: tensorchord/pgvecto-rs:pg14-v0.2.0
environment:
POSTGRES_PASSWORD: YourSecurePassword
POSTGRES_USER: postgres
POSTGRES_DB: immich
volumes:
- /srv/immich/postgres:/var/lib/postgresql/data
restart: always
networks:
- immich_network
immich_redis:
container_name: immich_redis
image: redis:7.2
restart: always
networks:
- immich_network
networks:
immich_network:
driver: bridgeAnd the .env:
UPLOAD_LOCATION=/usr/src/app/upload
DB_HOSTNAME=immich_postgres
DB_PASSWORD=YourSecurePassword
DB_USERNAME=postgres
DB_DATABASE_NAME=immich
REDIS_HOSTNAME=immich_redis
POSTGRES_PASSWORD=YourSecurePassword
POSTGRES_DB=immich
POSTGRES_USER=postgres
TZ=Europe/Paris
IMMICH_VERSION=releaseNow For the Fun Part: 62GB of Photos
Immich is running. Time to get 5,742 photos back into it.
Step 1: Mount the NAS
Photos were on a Synology NAS over NFS:
showmount -e NAS-IP
sudo mkdir -p /mnt/old-immich
sudo mount -t nfs4 NAS-IP:/volume1/FOLDER /mnt/old-immichStep 2: Know What You’re Dealing With
find /mnt/old-immich/IMMICH/library -type f \
\( -iname "*.jpg" -o -iname "*.jpeg" -o -iname "*.png" \
-o -iname "*.heic" -o -iname "*.mp4" -o -iname "*.mov" \) | wc -l
# 5,742 files
du -sh /mnt/old-immich/IMMICH/library
# 62GBBreakdown: 2,658 JPG, 1,476 HEIC, 1,186 MOV, 405 MP4, 15 PNG.
Step 3: Don’t Just Copy Files (I Did, It Doesn’t Work)
First instinct: rsync everything into /srv/immich/library. Reasonable, right?
sudo rsync -avh --progress /mnt/old-immich/IMMICH/library/ /srv/immich/library/Problem: Immich ignores files dropped directly into the library folder. It only manages content it imported itself. The /data/library path is for External Libraries — a different thing entirely.
You need the Immich CLI.
Step 4: Use the CLI Properly
The CLI handles everything the right way: hashes files, creates database entries, generates thumbnails, extracts EXIF.
Get an API key: Open http://127.0.0.1:2283 → Account Settings → API Keys → New API Key.
Authenticate:
docker exec immich_server immich login-key http://localhost:2283 YOUR_API_KEYThe problem with uploading 5,700+ files at once: it hung on “Crawling for assets…” over NFS and never moved.
The fix: upload folder by folder.
Testing a single folder:
docker exec immich_server immich upload --recursive /data/library/admin/2024/2024-09-25
# Successfully uploaded 9 new assets (92.1 MB)That worked fine.
Step 5: Script the Bulk Upload
532 folders to process. Time for a loop:
#!/bin/bash
LOG_FILE="/tmp/immich-upload-progress.log"
echo "=== Starting Immich Upload ===" | tee -a "$LOG_FILE"
echo "$(date): Starting" | tee -a "$LOG_FILE"
docker exec immich_server find /data/library/admin -type d -mindepth 2 -maxdepth 2 | while read -r folder; do
echo "$(date): Uploading $folder" | tee -a "$LOG_FILE"
docker exec immich_server immich upload --recursive "$folder" 2>&1 | tee -a "$LOG_FILE"
if [ $? -eq 0 ]; then
echo "$(date): ✅ Success for $folder" | tee -a "$LOG_FILE"
else
echo "$(date): ❌ Failed for $folder" | tee -a "$LOG_FILE"
fi
done
echo "$(date): Upload completed!" | tee -a "$LOG_FILE"Run it in the background and watch the log:
chmod +x /tmp/immich-bulk-upload.sh
nohup /tmp/immich-bulk-upload.sh > /tmp/immich-upload.log 2>&1 &
tail -f /tmp/immich-upload-progress.logAbout 1.5-2 hours for 532 folders. Go touch grass.
Cleanup
Once you’ve verified everything landed correctly:
sudo rm -rf /srv/immich/library/admin/ # Recovers 62GB
sudo umount /mnt/old-immich
sudo rmdir /mnt/old-immichTotal recovered: ~124GB (original + the temporary copy).
Quick Reference
# Container status
docker compose ps
# Server logs
docker compose logs immich-server --tail 50
# Test API
curl http://127.0.0.1:2283/api/server/ping
# Expected: {"res":"pong"}
# Check version
curl http://127.0.0.1:2283/api/server/version
# Monitor upload
tail -f /tmp/immich-upload-progress.log
# Disk usage
df -h /srv/immichWhat I Learned
- Check the changelog when upgrading — ports and paths changed between v1.x and v2.4. Old configs will break quietly.
- Environment variables matter — Missing
DB_HOSTNAMEis an easy one to miss, a painful one to debug. - Use the CLI for imports — Don’t drop files directly. The CLI handles metadata, hashing, and deduplication properly.
- Batch large uploads — 5,700 files over NFS at once will time out. Folder by folder is the move.
- Verify before deleting — Obvious in hindsight, painful if skipped.
Resources
Immich is solid once you get past the version migration landmines. The folder-by-folder upload approach is what made the difference. If you’re migrating a large library, don’t try to do it all at once.
Immich Version: v2.4.1 — Platform: Docker Compose on Ubuntu Server