Skip to content

Immich

Replaces Google Photos / iCloud Photos

Photos & media High resources

Immich is a self-hosted photo and video management server with automatic backup from mobile devices, facial recognition, object detection, and album organization.

Install it from Suite Manager → Apps — once running it lives at immich.<your-domain> and on your Home dashboard.

What you can do

  • Automatic mobile backup — Backup photos and videos automatically from your phone using the official Immich mobile app.
  • Facial recognition — Automatically organize photos by people using on-device machine learning.
  • Smart search — Search photos by objects, locations, dates, and people.

A self-hosted Google Photos alternative

Immich does the job people use Google Photos, iCloud Photos, Amazon Photos, Flickr, SmugMug, and Synology Photos for, on a server you own: the same everyday task, without a subscription and without an account at a company that also keeps your data. If you arrived comparing one of these, this is the app My Own Suite installs in its place — its privacy posture below says exactly what it does and does not send anywhere.

  • Google Photos alternative
  • iCloud Photos alternative
  • Amazon Photos alternative
  • Flickr alternative
  • SmugMug alternative
  • Synology Photos alternative

Good to know

  • Resource needs: High resources — This package requires minimum 4GB RAM and CPU with AVX2 support for optimal machine learning performance. Photo and video libraries grow large, and whole-suite backups include the full library - size your backup drive for the library you plan to store and expect backups to take longer as it grows.
  • Package-provided privacy notes (not independently verified by MOS): Your photos are stored and processed on your own server. MOS disables Immich's version check and keeps the map, one of the features that makes Immich what it is. We assessed the map's outside dependency in detail and consider it privacy respecting: it never learns where your photos were taken.
    • Photo and video library data is stored in package-owned volumes, and machine learning inference runs locally on your server. Turning photo GPS into place names also happens locally, from a 54 MB dataset shipped inside the image.
    • Only the Immich web service is exposed through HTTPS; the database, cache, and machine learning services remain internal.
    • MOS disables the enabled-by-default new-version check, so the server makes no scheduled release-check requests to version.immich.cloud.
    • MOS keeps the map switched on, and that outside dependency is why this app is marked External dependency. Opening the map asks Immich's tile service for plain map imagery, requested by grid square from tiles.immich.cloud and static.immich.cloud, both served via Cloudflare. Your photo locations never leave your server: the markers you see are drawn in your browser from your own server's data. What the tile service can tell is which square of the world map you are looking at, and the smallest square it serves spans about 1.2 km — a neighbourhood, not an address, and never a photo. Immich's privacy policy says it logs the requested tile, your IP address and timing. Requests happen only while the map is open and carry no cookie or account identity.
    • Machine learning models are downloaded on first use, from Hugging Face for smart search and face recognition and from Alibaba Cloud's ModelScope for text recognition. The downloads are unauthenticated, and your photos are never sent out for processing.
Try before you commit

Just want to try Immich?

MOS is the way to grow a suite — apps installed, backed up, and updated together, all in one tailored dashboard. But if you'd rather see Immich on its own first, we've set up a one-click deploy on Railway so you can kick the tires with nothing to install.

Install in MOS

Recommended
  • Yours to controlruns on your own machine or any VPS you pick — and can move anytime
  • One dashboardevery app you run, in one place at your own domain
  • Backups built inback up and restore your apps in a couple of clicks
  • Fully private if you wanton your own hardware, apps can stay off the public internet entirely
  • Updates handledversion-pinned, health-checked, applied for you
  • HTTPS and domainstrusted certificates without touching DNS records
  • Apps that connectfile, calendar, and office apps work together

Try it on Railway

Good for testing
  • Live in minutesdeploy from a template, fill in a few setup fields
  • The real thing, not a demothe same app MOS installs, running for you
  • Free triallimited free trial for new users
  • Railway account requireda third-party cloud with its own sign-up and usage billing
  • Tied to RailwayMOS runs anywhere and can migrate; this deploy lives on their platform

Good for a test drive, not the destination — this runs on Railway's cloud, not hardware you own, and comes without MOS backups, updates, or your own domain.

Deploy on Railway

Referral link — Railway pays MOS a commission on deploys made through this button, at no extra cost to you.

Privacy assessment

This is the assessment behind Immich's posture grade, exactly as it ships inside the package. It describes package version 0.5.1 and nothing else — install a different version and its own assessment travels with it. Reviewed 11 August 2026, due for reassessment by 11 February 2027.

What was reviewed

  • Package — version 0.5.1, content digest d287518b7ad7… at commit d74ed44a0a60
  • Immich Server — version 3.1.0 from ghcr.io/immich-app/immich-server pinned at 079cc990b26a…
  • Immich Machine Learning — version 3.1.0 from ghcr.io/immich-app/immich-machine-learning pinned at a25ddad7d6d2…
  • Immich PostgreSQL (VectorChord / pgvecto.rs) — version 14-vectorchord0.4.3-pgvectors0.2.0 from ghcr.io/immich-app/postgres pinned at b1d33572a9a0…
  • Valkey — version 9 from docker.io/valkey/valkey pinned at 64f6e8025b9a…

Deliberately outside this assessment:

  • The Immich mobile apps (iOS and Android) and their automatic photo/video backup behaviour
  • Device or vendor cloud backups configured within those client apps
  • Third-party Immich API clients

Evidence

Observed Watched on the wire, in a running instance of this package.

  • Runtime network capture of this package: a logging DNS resolver was the only upstream resolver for all four containers and every packet crossing the package-network boundary was recorded, across first boot and interactive use (admin creation, 11 asset uploads, and the machine-learning jobs those triggered). The immich-server, immich-postgres and immich-valkey containers made no outbound connection and no external DNS query at any point. Control requests injected from inside the containers appeared in both channels, so the silence is an observation rather than a failed capture.

    Source: MOS runtime projection of apps/immich 0.5.0 (Immich v3.1.0), observed 2026-08-10 · checked 2026-08-10

  • The disabled new-version check was observed not to fire. Immich runs handleVersionCheck() at server bootstrap and hourly thereafter, and that method returns Skipped before issuing any request when newVersionCheck.enabled is false; the capture covers bootstrap and immich-server contacted nothing. The observation is scoped to the boot-time check, because no hourly tick was separately isolated.

    Source: MOS runtime projection of apps/immich 0.5.0 observed 2026-08-10, and server/src/services/version.service.ts at v3.1.0 · checked 2026-08-10

  • The new-version check contacts Immich's own infrastructure, not GitHub. The only version endpoints present in the pinned server image are https://version.immich.cloud/version and https://version.dev.immich.cloud/version, and the image contains no api.github.com endpoint at all. Earlier revisions of this review described the check as a request to GitHub; that description was incorrect and has been corrected here.

    Source: grep of /usr/src/app/server/dist in the pinned immich-server image (sha256:079cc990b26a88d71f96027341c67329cb11829d4c341ce33b3718fe0f84cbfa), observed 2026-08-11 · checked 2026-08-11

  • Client-side capture of the browser surface, which earlier revisions of this review excluded from scope. A full HAR of an authenticated 77-second session (sign-in, timeline browsing, opening individual photos, the map view with zooming, search and explore) recorded 378 entries: 8 inline data: URIs that touch no network, and 370 real requests. Exactly three hosts were contacted in the entire session: 127.0.0.1:2283, tiles.immich.cloud and static.immich.cloud. 316 requests were local and 54 external. No raw-IP request bypassed DNS, no request reached any analytics, error-reporting or advertising host, and the single WebSocket connection was to the local server.

    Source: Firefox HAR capture of the MOS runtime projection of apps/immich 0.5.0 (Immich v3.1.0), captured by the human reviewer 2026-08-10 and analysed 2026-08-11 · checked 2026-08-11

  • External requests from the browser are read-only and carry no identity. All 54 external requests were GET, none carried a request body, none carried a cookie, and no external response set a cookie; the only Set-Cookie headers in the capture came from the local Immich server setting its own session. Approximately 20.1 KB left the browser as request headers against 2.9 MB received. The session cookie immich_access_token was never sent across the package boundary.

    Source: Firefox HAR capture of apps/immich 0.5.0, analysed 2026-08-11 · checked 2026-08-11

  • Map tiles are fetched only while the map is open, not on every page view. The first 14.2 seconds of the session produced 315 local requests and zero external ones. External traffic began 0.1 seconds after the map component mounted and 0.0 seconds after the browser requested /api/map/markers from the local server, and ended 11 seconds later when the reviewer left the map; a further 52 seconds of browsing, including a search, produced no external request at all.

    Source: Firefox HAR capture of apps/immich 0.5.0, analysed 2026-08-11 · checked 2026-08-11

  • Photo coordinates are not sent to the tile service. The browser obtains photo markers, including latitude and longitude, from the operator's own server via /api/map/markers and assembles the map overlay locally; requests to the tile service are of the form GET /v1/<zoom>/<x>/<y>.mvt with no query string, no body and no cookie. The tile operator therefore observes that an IP address requested a map square covering a geographic area at a point in time, but never learns which photo, which coordinate, or which user that square relates to. In this reviewer's judgement this is a deliberate and effective privacy design: the feature could have been made fully local and was not, but where an external service was chosen it was built so that the operator is structurally unable to reconstruct where a user has been or taken photographs. It is a middle ground rather than a perfect outcome, and it is disclosed accurately by the publisher.

    Source: Firefox HAR capture of apps/immich 0.5.0 analysed 2026-08-11, with the assessment recorded by the human reviewer · checked 2026-08-11

  • What the tile requests reveal is a map viewport, at low precision, not a location. A tile is a fixed square of the world map addressed by zoom level and grid position, so GET /v1/<z>/<x>/<y>.mvt tells the operator which square of the map the browser is drawing and nothing about what is drawn on top of it. Across the captured session, which included the reviewer zooming the map, the deepest zoom requested was level 6, where one tile spans roughly 626 km at the equator. The service's own TileJSON advertises maxzoom 15, so the finest square it will ever serve spans roughly 1.2 km: that is the upper bound on the precision available to the operator under any use, and it describes a neighbourhood rather than a street address, a person or a photograph. The underlying map data is OpenStreetMap, per the attribution the service returns. The honest residual is that someone who zooms fully into the area where they photograph would request the square containing it, so repeated use could indicate a coarse area of interest over time; even then no request carries a photo, a coordinate, an account, a cookie or a session, and the operator cannot distinguish a place someone lives from a place they were merely looking at.

    Source: Firefox HAR capture of apps/immich 0.5.0 analysed 2026-08-11, including the TileJSON body returned by https://tiles.immich.cloud/v1.json · checked 2026-08-11

  • static.immich.cloud is contacted in normal use and serves map rendering assets. It received 11 requests during the map session: nine Noto Sans glyph ranges (label fonts) and the dark sprite atlas (dark@2x.json and dark@2x.png). This host is listed in Immich's own Content-Security-Policy but is not referenced anywhere in the built web client or the server, because its URLs are constructed at runtime from the style document served by tiles.immich.cloud. Static analysis of the shipped bundle could not have found it; only the runtime capture did. It shares the trust boundary, timing and operator of the tile service and should be treated as part of the same map dependency.

    Source: Firefox HAR capture of apps/immich 0.5.0 analysed 2026-08-11, and grep of /build/www in the pinned immich-server image · checked 2026-08-11

  • Both map hosts are served by Cloudflare rather than by Immich-operated origin servers. tiles.immich.cloud and static.immich.cloud both resolve to 188.114.96.0 / 188.114.97.0 and 2a06:98c1:31xx::, and responses carry server: cloudflare with cf-ray identifiers ending -AMS, indicating the Amsterdam edge. 50 of the 54 external responses reported cf-cache-status: HIT with cache ages of 5.1 and 13.9 days, so those requests were answered at the Cloudflare edge and did not reach an Immich origin. The party observing the requesting IP address is therefore Cloudflare in the first instance; Cloudflare is a United States company operating an EU edge, which is a transfer consideration this review records rather than resolves.

    Source: Firefox HAR capture of apps/immich 0.5.0 analysed 2026-08-11, and DNS resolution of tiles.immich.cloud · checked 2026-08-11

  • Google Cast is present in the Content-Security-Policy but is not loaded by default. www.gstatic.com is permitted in Immich's script-src for the Google Cast SDK, and one file in the web bundle references cast_sender.js. The feature is a per-user preference, gCastEnabled, which upstream defaults to false, and www.gstatic.com was never contacted during the captured session. The only Google-named assets loaded were GoogleSans.ttf and GoogleSansCode.ttf, both served from the operator's own server rather than from a Google font CDN. pay.futo.org, permitted for supporter licence purchase and gated on administrator action, was likewise never contacted.

    Source: server/helmet.json and server/src/utils/preferences.ts at v3.1.0, grep of /build/www in the pinned image, and the Firefox HAR capture analysed 2026-08-11 · checked 2026-08-11

  • Reverse geocoding runs entirely on the operator's own server. The pinned immich-server image ships 54 MB of geodata at /build/geodata, including cities500.txt, admin1CodesASCII.txt, admin2Codes.txt and ne_10m_admin_0_countries.geojson. Turning a photograph's GPS coordinates into a place name therefore requires no external lookup, and the server was observed making no network request while processing uploaded assets.

    Source: MOS runtime projection of apps/immich 0.5.0 (Immich v3.1.0), observed 2026-08-10 · checked 2026-08-10

  • On first machine-learning use the immich-machine-learning container downloaded models from five hosts across two operators: huggingface.co, cas-server.xethub.hf.co and us.aws.cdn.hf.co for the CLIP and facial-recognition models, and www.modelscope.cn and cdn-lfs-cn-1.modelscope.cn for the OCR models. ModelScope is operated by Alibaba Cloud. Requests were unauthenticated with no HF_TOKEN configured, so no account identity was attached, though the server's IP address, the timing of first use, and which models are fetched are visible to both operators.

    Source: MOS runtime projection of apps/immich 0.5.0 (Immich v3.1.0), observed 2026-08-10 · checked 2026-08-10

  • Across the whole interactive session the machine-learning container received 1068.62 MB from the internet and sent 0.07 MB to it. The outbound total is consistent with TLS handshakes and HTTP request headers for the observed connections and is orders of magnitude too small to carry the uploaded assets; immich-server contacted nothing while processing them. Model artifacts are therefore fetched inbound, and photo and metadata content was not observed leaving the package. TLS payloads were not decrypted, so this bounds behaviour by destination and volume rather than asserting request contents.

    Source: MOS runtime projection of apps/immich 0.5.0 (Immich v3.1.0), observed 2026-08-10 · checked 2026-08-10

Configured Read from the configuration MOS actually ships.

  • The MOS package bakes an immich-config.json into the server image and points IMMICH_CONFIG_FILE at it, setting newVersionCheck.enabled to false. The primary motivation is product coherence rather than privacy: MOS controls when Immich updates are offered, so an in-app 'new version available' prompt for a release MOS does not yet ship is misleading to the operator. Suppressing the outbound request to version.immich.cloud is a real privacy side effect of that decision, not its purpose. The map remains enabled at its upstream default; MOS has deliberately not disabled it.

    Source: apps/immich/manifest.json, apps/immich/Dockerfile, and apps/immich/immich-config.json

  • MOS keeps the map enabled by decision, and its packaging makes that a property of the app as shipped rather than a per-owner setting. MOS points IMMICH_CONFIG_FILE at a baked-in configuration file, and Immich treats that file as the authority for system settings: updateSystemConfig() returns BadRequestException('Cannot update configuration while IMMICH_CONFIG_FILE is in use') instead of accepting a change. map.enabled is a system setting with no per-user equivalent, since Immich's user-preference schema covers albums, avatar, cast, download, email notifications, folders, memories, people, purchase, ratings, shared links and tags but not the map. The tile requests are therefore part of the package rather than something an owner opts into, which is why this review records telemetry as unavoidable rather than optional; changing it would be a package decision. This follows from MOS's packaging rather than from Immich, which lets an administrator toggle the map in the settings UI when no config file is in use.

    Source: server/src/services/system-config.service.ts and server/src/dtos/user-preferences.dto.ts at v3.1.0, apps/immich/manifest.json (IMMICH_CONFIG_FILE), and apps/immich/immich-config.json · checked 2026-08-11

  • Only immich-server is published through the generated app route; immich-postgres, immich-valkey, and immich-machine-learning are internal-only services, and the first admin account is created locally in the Immich web UI without any upstream Immich account.

    Source: apps/immich/manifest.json and apps/immich/onboarding setup guide

  • The photo and video library, database, thumbnail cache, and machine learning model cache persist to package-owned volumes, and DISABLE_MACHINE_LEARNING=false runs a local machine-learning service so facial recognition and smart-search inference execute on the MOS server.

    Source: apps/immich/manifest.json and apps/immich/README.md

Documented Taken from upstream documentation, policies or source.

  • Immich's published privacy policy discloses the tile service collection accurately and completely, and the disclosure matches what was independently measured. The policy states that requests to tiles.immich.cloud collect the requested tile, the IP address and timing metrics, and marks the feature optional with a link to the setting that disables it. The runtime capture found exactly that and nothing further: no cookie, no identifier, no request body, no additional field. The same policy section states that hosted services including the Tile Server and the Version Service collect request metadata 'in order to better understand our user base', which is the publisher characterising this metadata as analytics rather than purely operational data. Immich publishes no separate terms of service: the privacy policy is the only policy document on its site, and the AGPL licence is the only other instrument that binds an operator. The policy exposure recorded here is therefore complete rather than partially surveyed.

    Source: Immich Privacy Policy, last updated 6 April 2026 (source text at immich-app/static-pages, apps/root.immich.app/src/routes/privacy-policy/+page.md) · checked 2026-08-11

  • The OCR model download endpoint is chosen by a third-party dependency rather than by Immich or MOS. Immich's OCR feature is enabled by default (machineLearning.ocr.enabled, model PP-OCRv5_mobile), and its TextDetector._download() resolves the URL through the rapidocr package instead of the Hugging Face path every other model uses. That package's bundled default_models.yaml hardcodes www.modelscope.cn URLs for every PP-OCR artifact and pins a SHA256 for each, so the downloads are integrity-checked against an unexpected host rather than merely trusted. MOS keeps OCR enabled because in-photo text search is a substantive feature, and discloses the operator by name instead.

    Source: machine-learning/immich_ml/models/ocr/detection.py at v3.1.0, and rapidocr/default_models.yaml as installed in the pinned machine-learning image · checked 2026-08-10

What this review does not settle

Published rather than smoothed over. Each of these is a limit of the method, not a finding against the app.

  • MOS's use of IMMICH_CONFIG_FILE to disable the version check has a wider effect than the privacy control it was chosen for: while that variable is set Immich rejects every system-configuration change, so storage templates, transcoding, machine-learning options, job concurrency, the backup schedule and the map are all frozen for the owner as well. Whether MOS should keep that trade, expose the settings it freezes, or disable the version check by another means is a packaging decision outside the scope of this review.
  • Requests to the tile service carry a Referer header identifying the origin the Immich web client is served from. The capture was taken over loopback, so only http://127.0.0.1:2283/ was sent; a MOS deployment reached through a public domain would send that domain to Cloudflare alongside the tile coordinates under the browser default referrer policy. This is an inference from the observed header rather than a measured result, and has not been confirmed against a domain-based deployment.
  • The /photos document returned no Content-Security-Policy and no Referrer-Policy header, and still carried X-Powered-By: Express, which suggests the helmet configuration shipped at server/helmet.json is not enforced on that response. The captured session contacted no host outside that policy, so nothing was observed escaping it, but the policy should be treated as a declaration of intent rather than an enforced control. Only one document response was examined.
  • Machine learning models are downloaded on first use from Hugging Face and from Alibaba Cloud's ModelScope, and the map loads tiles from Immich's Cloudflare-fronted infrastructure. These optional external touchpoints remain unless an operator disables machine learning or the map, and this review deliberately does not disable them.
  • TLS payloads were not decrypted in either the server-side or client-side capture, so conclusions bound behaviour by destination, method, header content and volume rather than by asserting the contents of encrypted request bodies.
  • The Immich mobile applications, and any device or vendor cloud backups configured within them, remain outside the reviewed package boundary. The browser-based web client is now inside the boundary and was captured directly.

Policies read

  • privacy — Immich project (FUTO) · retrieved 2026-08-11
  • license — Immich project · retrieved 2026-08-11

How this review was produced

  • Method — AI-assisted review, checked by Rasmus Puls
  • Model — Claude Opus 5 (Anthropic)
  • Workflowassess-app-privacy at 6a741118713a
  • Repository commitd74ed44a0a60

Technical reference

Maintained alongside the package at apps/immich/README.md and rendered here as-is.

Immich

High performance self-hosted photo and video backup solution.

Services

ServiceImagePort
immich-serverImmich Server2283
immich-machine-learningImmich ML3003
immich-postgresImmich PostgreSQL 14 with VectorChord5432
immich-valkeyValkey 96379

Volumes

VolumePathDescription
library/usr/src/app/uploadPrimary photo and video storage
postgres-data/var/lib/postgresql/dataDatabase metadata
cache/usr/src/app/cacheThumbnails and previews
model-cache/cacheMachine learning model cache

Environment Variables

VariableSource
DB_PASSWORDGenerated secret
JWT_SECRETGenerated secret
PUBLIC_HOSTNAMERuntime app route
POSTGRES_INITDB_ARGSEnables data checksums for Immich database initialization

Health Check

Endpoint: GET /api/server/ping (returns {"res":"pong"}; the same path the upstream image’s own immich-healthcheck uses)

Notes

  • First admin account is created directly in Immich web UI after first startup
  • The server and machine-learning images are pinned to the amd64 manifests for Immich v3.1.0. The database and Valkey images follow the digests pinned by the official Immich v3.1.0 Docker Compose file rather than their moving tags, so the package runs the combination upstream tests.
  • Immich database migrations are forward-only. Once a v3.1.0 instance has started and migrated, repinning the images to an earlier Immich version is not supported by upstream.
  • Machine learning requires CPU with AVX2 support for optimal performance
  • All services are internal except the main Immich server port
  • Startup may take several minutes on first run while database is initialized