Deployn

Immich: Easy Self-Hosted Photo Management Server Setup Guide

Set up Immich, a private photo cloud, on your server. Step-by-step guide for NAS or Ubuntu. Secure alternative to Google Photos.

Immich: Easy Self-Hosted Photo Management Server Setup Guide-heroimage

Immich is a self-hosted, open-source solution for storing and managing photos and videos. It offers an alternative to cloud services like Google Photos and iCloud, focusing on privacy and user control. In this article, I’ll show you how to install Immich on various servers, whether it’s a Synology NAS, a Ugreen NAS, or another computer.

Why Immich?

In an era where privacy is becoming increasingly important, Immich offers the ability to maintain control over your own photos and videos. Without relying on third-party providers, images can be securely stored and managed within your own network. Immich provides a simple and intuitive user interface that allows you to organize and share photos and videos.

Prerequisites

Immich can be installed using Docker on most Linux systems. The following is required:

  • Server with Docker: A server with Docker installed.
  • Hardware Requirements: 6 GB RAM and 4 CPU cores are recommended. However, 4 GB RAM and 2 CPU cores are usually sufficient.
  • Storage Space: Sufficient storage space for photos and videos.
  • Optional:
    • Reverse Proxy: A reverse proxy (e.g., Nginx Proxy Manager, Caddy, Traefik) for external access and domain usage.
    • DNS-Server: A DNS server (e.g., Adguard Home, Pi-Hole, Technitium) for internal forwarding.
    • VPN-Server: If the server is not on your own network, setting up a VPN server like WireGuard or OpenVPN is recommended.
    • SMTP EMail Address: An SMTP address can be used for notifications, e.g., a shared web hosting plan from Netcup.

INFO

If using a NAS, Portainer (Portainer on Synology), Dockge (Dockge on Ugreen) or another Docker management tool should be installed to manage multiple containers. On an Ubuntu Server (Setup Guide), docker compose can be used.

Preparation

Create Folder Structure

First, we’ll create a folder structure for Immich on the server. These folders will be used for the database and storage of photos and videos.

Required Folders:

  • data
  • db
  • db-backup.

Beispiele:

Ubuntu Server
cd ~
mkdir immich
cd immich
mkdir db db-backup data

Result:

/home/user/immich
├── db
├── db-backup
└── data

We can also create an empty docker-compose.yml file here, which we’ll need later.

touch docker-compose.yml

or the data path, we only need the relative reference to the docker-compose.yml file. In this case, it would be ./db, ./db-backup and ./data.

Synology NAS

On a Synology NAS, we can either create a new shared folder for Immich or use a shared folder for all Docker containers. In my configuration, I created a shared folder docker on my SSD and a shared folder dockerhdd on my HDD. In both, I create an immich folder and on the SSD, I additionally create the subfolder db and on the HDD, the subfolder data. This way, I can store the database on the SSD and the photos and videos on the HDD.

New Directory

Wherever the folders are created, the complete path can be found via the properties. This will be needed later for the Docker containers.

Path

Example result:

/volume1/docker/
└── immich
    |── db
    └── db-backup

/volume2/dockerhdd/
└── immich
    └── data
Ugreen NAS

On a Ugreen NAS, we can simply create a new immich folder in the shared folder docker. In this folder, we then create the subfolders data and db.

New Directory

Of course, you can also create another shared folder. This is particularly useful if you want to store the database (db) on an SSD and the images and videos (data) on an HDD.

We need the full path, which we can find through the folder’s properties. This will be needed later for the Docker containers.

Path

Example result:

/volume1/docker/
└── immich
    |── db
    |── db-backup
    └── data
# or
/volume1/docker/
└── immich
    |── db
    └── db-backup

/volume2/dockerhdd/
└── immich
    └── data

Firewall

To ensure that the created containers can communicate with each other, it is recommended to either allow the entire internal IP range or check the IP addresses used by the containers after installation if you have a restrictive firewall. Otherwise, the containers may not be able to communicate with each other.

Installation

Immich requires the following Docker containers:

  • Redis-Brocker
  • PostgreSQL Database with pgvecto.rs extension
  • Immich Server
  • Immich Machine (for machine learning)

CAUTION

Both the pgvector container and Immich are in beta. Updates may lead to fundamental changes. Therefore, updates should be performed with caution, and backups should always be created.

Docker Compose File

First, we need the container commands to perform the installation.

Docker Compose Generator

Generated Docker Compose:

1
2networks:
3 internal:
4 name: internal
5 external: false
6
7
8volumes:
9 model-cache:
10
11services:
12 redis:
13 container_name: immich_redis
14 image: redis:7-alpine
15 restart: unless-stopped
16 networks:
17 - internal
18 healthcheck:
19 test: redis-cli ping || exit 1
20
21 db:
22 container_name: immich_db
23 image: tensorchord/pgvecto-rs:pg16-v0.3.0
24 restart: unless-stopped
25 networks:
26 - internal
27 volumes:
28 - /volume1/docker/immich/db:/var/lib/postgresql/data
29 environment:
30 POSTGRES_DB: immich
31 POSTGRES_USER: immich
32 POSTGRES_PASSWORD: changeMeIamAPassword
33 POSTGRES_INITDB_ARGS: '--data-checksums'
34 healthcheck:
35 test: pg_isready --dbname='immich' --username='immich' || exit 1; Chksum="$$(psql --dbname='immich' --username='immich' --tuples-only --no-align --command='SELECT COALESCE(SUM(checksum_failures), 0) FROM pg_stat_database')"; echo "checksum failure count is $$Chksum"; [ "$$Chksum" = '0' ] || exit 1
36 interval: 5m
37 start_interval: 30s
38 start_period: 5m
39 command:
40 [
41 'postgres',
42 '-c',
43 'shared_preload_libraries=vectors.so',
44 '-c',
45 'search_path="$$user", public, vectors',
46 '-c',
47 'logging_collector=on',
48 '-c',
49 'max_wal_size=2GB',
50 '-c',
51 'shared_buffers=512MB',
52 '-c',
53 'wal_compression=on',
54 ]
55
56 db_backup:
57 container_name: immich_db_backup
58 image: prodrigestivill/postgres-backup-local:16
59 restart: unless-stopped
60 environment:
61 POSTGRES_HOST: db
62 POSTGRES_CLUSTER: 'TRUE'
63 POSTGRES_USER: immich
64 POSTGRES_PASSWORD: changeMeIamAPassword
65 POSTGRES_DB: immich
66 SCHEDULE: "@daily"
67 POSTGRES_EXTRA_OPTS: '--clean --if-exists'
68 TZ: Europe/Berlin
69 volumes:
70 - /volume1/docker/immich/db-backup:/backups
71 depends_on:
72 - db
73 networks:
74 - internal
75
76 immich:
77 container_name: immich
78 image: ghcr.io/immich-app/immich-server:v1.118.2
79 restart: unless-stopped
80 depends_on:
81 - db
82 - redis
83 networks:
84 - internal
85
86 ports:
87 - 2283:2283
88 volumes:
89 - /etc/localtime:/etc/localtime:ro
90 - /volume1/docker/immich/data:/usr/src/app/upload
91 environment:
92 DB_HOSTNAME: db
93 DB_USERNAME: immich
94 DB_DATABASE_NAME: immich
95 DB_PASSWORD: changeMeIamAPassword
96 TZ: Europe/Berlin
97 healthcheck:
98 disable: false
99
100 immich-machine-learning:
101 container_name: immich-machine-learning
102 image: ghcr.io/immich-app/immich-machine-learning:v1.118.2
103 restart: unless-stopped
104 depends_on:
105 - db
106 - redis
107 networks:
108 - internal
109 volumes:
110 - model-cache:/cache
111 environment:
112 DB_HOSTNAME: db
113 DB_USERNAME: immich
114 DB_DATABASE_NAME: immich
115 DB_PASSWORD: changeMeIamAPassword
116 TZ: Europe/Berlin
117 healthcheck:
118 disable: false
119

The images can be customized, but I advise against using latest or release as it can lead to problems if a new incompatible image is published. Especially while Immich is in beta, you should not simply specify other tags. You can check on the container page to see which image is currently the newest.

Installation ĂĽber Docker-Compose (Ubuntu Server)

The Docker-Compose code can be copied into the docker-compose.yml file. For the paths, relative paths (e.g., ./db) or absolute paths (e.g., /home/user/immich/db) can be used. The paths should lead to the previously created folders.

Then the containers can be started with the command docker compose up -d or sudo docker compose up -d.

Installation ĂĽber Portainer

Under Stacks, a new stack can now be added.

New Stack

If you can’t see this menu item, make sure you have selected the local environment and are running Portainer with the image portainer/portainer-ce and not portainer/portainer.

Here we insert the Docker Compose code.

Compose Datei in den Stack einfĂĽgen

Then the containers can be started. This may take a few minutes.

Container gestartet

Installation ĂĽber Dockge

In Dockge, a new stack can be created. To do this, the Docker-Compose code is pasted into the text field and the stack is created. Then the containers can be started.

Neuer Stack

The initial installation can take a few minutes.

Reverse Proxy

To make Immich accessible via a domain like immich.domain.com, we set up a reverse proxy in the meantime.

Nginx Proxy

I enter the address of my Synology NAS and the port number chosen above. I can also use an access list to set whether only local access is possible.

If the Nginx Proxy Manager is on the NAS and the web server is in the same Docker network, you can enter the container name immich here and the port 2283.

Nginx Proxy Manager

If not, I enter the IP address of the server and the port number. The port number can be changed in the Docker-Compose file. The IP address is the internal IP address of the server.

After I’ve obtained the SSL certificate for the proxy host, I also add a few additional settings to the “Custom Nginx Configuration”.

client_max_body_size 50000M;
proxy_redirect off;

This ensures that larger files (50,000 MB) can also be uploaded to Immich.

Caddy Proxy

Alternatively, other proxy servers can be used. Especially if you’re using a different device for it, there are many options. With Caddy, it might look like this:

{
    acme_ca https://acme-v02.api.letsencrypt.org/directory
    email   mail@domain.com
}

immich.domain.de {
    @blocked not remote_ip private_ranges
    respond @blocked 403
    reverse_proxy 192.168.1.123:8010
    client_max_body_size 50G
}

Or (if you want access from everywhere):

{
    acme_ca https://acme-v02.api.letsencrypt.org/directory
    email   mail@domain.de
}

immich.domain.de {
    reverse_proxy 192.168.1.123:8010
    client_max_body_size 50G
}

First Login

Immich should now be accessible under the domain or the IP address of the server (with port 2283).

Anmeldung

The first user is an admin user. This user can add additional users and change settings.

The setup is self-explanatory. In the administration, you can now add new users and assign them a storage quota. Users can then log in with their email address and a password.

Benachrichtigungen

If you have an SMTP address, you can also set up notifications. This is particularly useful if multiple users access Immich and share images. For example, a web hosting plan from Netcup with an email inbox can be used here. Costs start at €2.17 per month.

Apps

Immich also offers apps for Android and iOS. These can be downloaded from the respective app stores. The apps are free and allow photos and videos to be uploaded directly from devices.

Immich App Android

Immich App iOS

Features:

  • Automatic Upload: New photos and videos are automatically uploaded.
  • Sharing and Collaboration: Albums can be shared with family and friends.

Create Backup

For a complete backup, the folders db-backup (database) and data (images and videos) should be secured. This can be done manually. Alternatively, it can be automated with a script or a backup tool like rsync or Duplicati.

An advantage (and simultaneously a disadvantage) of Immich is that the images are stored in a normal file system. This means that if something goes wrong and Immich no longer works, you can simply copy the images and restore them on another system (provided the images have not been deleted).

Conclusion

Immich should now be running. I appreciate any comments. Enjoy managing your images!


This website uses cookies. These are necessary for the functionality of the website. You can find more information in the privacy policy