Files
fuji-photo-processor/README.md
Nick Roodenrijs 88db0c1b24 Fix SQLite threading bug, correct FTP upload path
- 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>
2026-03-08 19:44:27 +01:00

6.1 KiB

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)

  1. Open Control Panel → File Services → FTP
  2. Enable FTP service on port 21
  3. Enable FTP SSL/TLS encryption (FTPS)
  4. Set passive port range: 50000-50100
  5. Create a dedicated user fujiftp with 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

  1. In Immich, go to Administration → External Libraries
  2. Add a new library with import path: /volume1/data/photos/processed
  3. Set scan interval (e.g., every 15 minutes)
  4. Mount /volume1/data/photos/processed into 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.db to 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).