- Add check_same_thread=False to SQLite connection (watchdog callbacks run in a separate thread) - Camera upload dir is /data/photos/incoming (not /incoming) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fuji Photo Processor
Automatic photo processing pipeline for Fuji X-H2 photos: camera uploads via FTPS (FTP over TLS) to Synology NAS, files are automatically resized and organized, then picked up by Immich for library management.
Architecture
┌─────────────┐ FTPS ┌──────────────────┐ watchdog ┌─────────────┐
│ Fuji X-H2 │ ──────────→ │ Synology NAS │ ────────────→ │ Processor │
│ (camera) │ port 21 │ /volume1/data/photos/ │ polling │ container │
└─────────────┘ (TLS) │ incoming/ │ └──────┬──────┘
└──────────────────┘ │
│ resize + move
┌─────────────┴─────────────┐
│ │
┌─────▼─────┐ ┌───────▼───────┐
│ /originals │ │ /processed │
│ YYYY/MM/ │ │ YYYY/MM/ │
│ (full-res) │ │ (1080px max) │
└────────────┘ └───────┬───────┘
│
┌───────▼───────┐
│ Immich │
│ external lib │
└───────────────┘
Prerequisites
- Synology NAS with Docker (Container Manager) installed
- FTPS (FTP over TLS) enabled on DSM
- Immich running (for photo management)
Setup
1. FTPS Server (DSM)
- Open Control Panel → File Services → FTP
- Enable FTP service on port 21
- Enable FTP SSL/TLS encryption (FTPS)
- Set passive port range: 50000-50100
- Create a dedicated user
fujiftpwith write access to/volume1/data/photos/incoming
2. Camera Configuration (Fuji X-H2)
Configure an FTP profile on the camera:
| Setting | Value |
|---|---|
| FTP Server Type | FTPS |
| Server IP | 192.168.175.141 |
| Port | 21 |
| Passive Mode | ON |
| Username | fujiftp |
| Password | (your password) |
| Upload Dir | /data/photos/incoming |
| Auto Transfer | ON (or manual trigger) |
Note
: Bij FTPS kun je via FTP OPTIONAL SETTING → ROOT CERTIFICATE een self-signed root certificaat laden als je NAS er een gebruikt.
3. Deploy
./deploy.sh
The deploy script will:
- Create required directories on the NAS
- Transfer and build the Docker image on the NAS
- Start the container with appropriate volume mounts
4. Immich Integration
- In Immich, go to Administration → External Libraries
- Add a new library with import path:
/volume1/data/photos/processed - Set scan interval (e.g., every 15 minutes)
- Mount
/volume1/data/photos/processedinto the Immich container as a read-only volume
Container Details
Volumes
| Container Path | Host Path | Purpose |
|---|---|---|
/incoming |
/volume1/data/photos/incoming |
FTP upload landing zone |
/originals |
/volume1/data/photos/originals |
Full-resolution originals |
/processed |
/volume1/data/photos/processed |
Resized copies for Immich |
/data |
/volume2/docker/photo-processor/data |
SQLite tracking database |
Environment Variables
| Variable | Default | Description |
|---|---|---|
POLL_INTERVAL |
30 |
Filesystem poll interval in seconds |
JPEG_QUALITY |
85 |
JPEG compression quality (1-100) |
MAX_WIDTH |
1080 |
Maximum width for resized images |
MAX_HEIGHT |
1920 |
Maximum height for resized images |
TZ |
Europe/Amsterdam |
Container timezone |
Troubleshooting
Check container logs
ssh -i ../SynologyDocker/synology_ssh_key ssh@192.168.175.141 \
'sudo /usr/local/bin/docker logs -f photo-processor'
Common Issues
- Files not detected: Check that the FTP user has write permissions to
/volume1/data/photos/incoming. The processor uses polling (not inotify) so there may be up to a 30-second delay. - Permission denied on originals/processed: Ensure the directories exist and are writable. The deploy script creates them automatically.
- Duplicate filenames: The processor tracks files by filename in SQLite. If you re-upload a file with the same name, it will be skipped. Delete the entry from
/volume2/docker/photo-processor/data/processed.dbto reprocess. - Container keeps restarting: Check logs for Python errors. Common cause: missing directories or permission issues on volume mounts.
- EXIF data lost: The processor preserves EXIF data from the original. If EXIF is missing, the original file may not have contained it (check camera settings).
Description
Automatic photo processing pipeline - Fuji X-H2 FTP to Synology NAS with auto-resize for Immich
Languages
Python
59.7%
Shell
38.9%
Dockerfile
1.4%