v4.0
- Visitor uploads
- Container hardening
Visitors can now upload photos (OPTIONAL)
Important
To ensure IPP remains read-only by default, uploads work by running an optional companion container alongside IPP. If you don't run that second container, nothing about your IPP deployment will change; it will remain fully read-only.
Both containers are around 63MB :)
How to enable uploads
TL;DR, just add these lines to your compose.yml file: https://docs.ipp.nz/visitor-uploads#add-the-upload-service
The full guide: https://docs.ipp.nz/visitor-uploads
How it works
- In Immich, turn on the Allow public user to upload option for a shared link. The IPP gallery for that share then shows an Add photos button.
- A visitor clicks the button. It opens the upload page for the same share on the upload service's separate container.
- The upload container streams the file straight to Immich with the share's own key. It stores nothing and holds no API key.
- If you want, you can create a workflow to review photos before they appear publicly.
No API key, same as always
IPP 4.0 still never asks for an Immich API key, and the main container is still read-only. The new upload feature runs in a separate, optional container that talks to Immich with the share's own key, exactly as Immich's public share page does when "Allow public user to upload" is on. If you don't add the upload container, nothing about IPP changes.
Keeping control of what arrives
- Every uploaded file is named with an
ipp_upload_prefix, so an Immich workflow can identify and manipulate it if needed. - By default each file is capped at 500 MB, and each share at 10 GB per hour. Set a storage quota on the share owner in Immich as well, so visitors can't fill your disk.
- Optionally, get a notification for every upload through Gotify, ntfy or anything else that takes a JSON webhook.
Thanks to everyone in discussion #277.
Hardened containers
Both images are now built to run locked down. The application code is owned by root and the process runs as the unprivileged node user, so a compromised process cannot rewrite its own code. Nothing is written to disk at runtime, and tini runs as PID 1 so stray healthcheck processes are reaped (fixes #66).
Optionally add these three docker settings to your existing IPP service:
read_only: true
cap_drop:
- ALL
security_opt:
- no-new-privilegesread_onlymakes the container filesystem immutable. IPP needs no writable path, not even a tmpfs.cap_drop: ALLremoves every Linux capability. IPP listens on an unprivileged port and needs none.no-new-privilegesstops any process in the container from gaining privileges through setuid binaries.
Breaking changes from 3.x
- Immich 3.0.0 or newer is required. IPP checks the server version at startup and exits against an older Immich.
- Old config keys are no longer read. Keys that 1.x to 3.x mapped to new names at startup are ignored in 4.0. The full list is at https://docs.ipp.nz/config/upgrading
- IPP will not start while
showMetadata.exif.enabledorshowMetadata.location.enabledis in your config. Remove the key, and set totrueonly the per-field flags for what visitors may see. allowDownloadtakes only0,1or2. Any other value, such astrue, turns downloads off.- A custom
invalidRequestHandler.jsmust be copied again from the 4.0 image. A copy taken from 3.x fails to load.
Upgrading needs no change to your docker-compose.yml. Full details: https://docs.ipp.nz/upgrading#upgrading-to-4-0
Fixes
- Photos that Immich has not finished processing are hidden until their thumbnail exists, instead of showing as broken tiles.
- Downloads of album photos are always sent as attachments with their original filename, and every asset response sends
X-Content-Type-Options: nosniff. - Error responses are never cached, so a 404 can no longer be held by a CDN or browser for 30 days.
- The Docker healthcheck no longer leaves zombie processes on the host. The image now runs
tinias PID 1, and IPP's check of Immich gives up after 3 seconds. Thanks @lukaslindnermusic for reporting (#66). - The example healthcheck now fails when IPP can't reach Immich. The old
curl -sline passed on any response, including the 503. Update thetest:line in your compose file tocurl -sf -m 4 http://localhost:3000/share/healthcheck -o /dev/null || exit 1. - The Docker image is about a third smaller (101 MB to 63 MB compressed).