Immich has rapidly become the go-to solution for self-hosters looking to replace Google Photos. It is a high-performance, self-hosted photo and video backup application that boasts mobile apps, smooth timeline scrolling, and robust machine-learning capabilities for facial recognition and object detection.
While the official documentation heavily leans on Docker Compose, deploying Immich using Podman Quadlets is an excellent choice for a daemonless, systemd-native setup. Quadlets allow you to define container workloads directly via systemd unit files, making management, auto-updating, and logging incredibly clean.
Here is a brief, straightforward guide to deploying the Immich stack using Podman Quadlets. Note this is rootful setup, I prefer running my containers as root, but I keep SELinux turned on.
We will be creating a pod and four distinct containers (database, machine
learning, Redis, and the main server). Since we are doing a system-wide
installation, all of these configuration files must be placed in
/etc/containers/systemd/.
Create the following files with your preferred text editor:
File: /etc/containers/systemd/immich.pod
[Pod]
PodName=immich-stack
PublishPort=2283:2283
File: /etc/containers/systemd/immich-db.container
[Container]
ContainerName=immich-db
Pod=immich.pod
AutoUpdate=registry
Image=docker.io/tensorchord/pgvecto-rs:pg16-v0.2.0
Environment=POSTGRES_DB=immich POSTGRES_USER=immich POSTGRES_PASSWORD=immich_pass
Volume=immich-db:/var/lib/postgresql/data:Z
File: /etc/containers/systemd/immich-ml.container
[Container]
ContainerName=immich-ml
Pod=immich.pod
AutoUpdate=registry
Image=ghcr.io/immich-app/immich-machine-learning:release-openvino
Environment=TZ=Europe/Prague
Environment=MACHINE_LEARNING_CACHE_FOLDER=/cache
Environment=IMMICH_ML_DEVICE=openvino
AddDevice=/dev/dri/renderD128:/dev/dri/renderD128
Volume=immich-ml-cache:/cache:z
User=0:0
I host my immich on Intel NUC 13th gen with integrated Intel GPU, therefore
this configuration utilizes OpenVINO for hardware-accelerated machine learning
tasks. Ensure your hardware supports this and that /dev/dri/renderD128 is the
correct path for your system’s GPU.
File: /etc/containers/systemd/immich-redis.container
[Container]
ContainerName=immich-redis
Pod=immich.pod
Image=docker.io/library/redis:7-alpine
AutoUpdate=registry
Volume=immich-redis-data:/data:Z
File: /etc/containers/systemd/immich-server.container
[Unit]
Description=Immich Photo Manager
After=network-online.target immich-db.service immich-redis.service
Requires=immich-db.service immich-redis.service
[Container]
ContainerName=immich
Pod=immich.pod
AutoUpdate=registry
Image=ghcr.io/immich-app/immich-server:release
Environment=DB_HOSTNAME=immich-db DB_USERNAME=immich DB_PASSWORD=immich_pass DB_DATABASE_NAME=immich
Environment=REDIS_HOSTNAME=immich-redis
Environment=IMMICH_MACHINE_LEARNING_URL=http://immich-ml:3003
Environment=TZ=Europe/Prague
Environment=IMMICH_TRANSCODE_HW_ACCEL=vaapi
Volume=immich-server-data:/data:Z
Volume=/mnt/big/photos:/usr/src/app/upload:z
AddDevice=/dev/dri/renderD128:/dev/dri/renderD128
User=0:0
HealthCmd=curl -fs --connect-timeout 5 --max-time 10 -o /dev/null http://localhost:2283/favicon.ico
HealthInterval=10m
HealthRetries=3
[Install]
WantedBy=multi-user.target
Update the volume mount (/mnt/big/photos) to point to the actual directories
on your host where you want your photos stored.
Once your files are safely situated in /etc/containers/systemd/, you need to
tell systemd to generate the service files and load them. Podman’s systemd
generator will automatically parse these .container and .pod files and
create standard .service units behind the scenes.
sudo systemctl daemon-reload
Quadlet units do not need to be enabled, just start it.
sudo systemctl start immich-pod
You can check the status of your newly created stack by inspecting the systemd service or viewing the Podman logs:
sudo systemctl status immich-server.service
sudo podman logs -f immich
Once the containers are running and the database has initialized, you can
access your Immich instance by navigating to http://<your-server-ip>:2283 in
your web browser.
At the time of writing this, Immich cannot be hosted via a dedicated path, you will need a dedicated domain or subdomain. here is how to do it in Apache httpd:
<VirtualHost *:80>
ServerName xxxxx.zapletalovi.com
RewriteEngine On
RewriteCond %{REQUEST_URI} !^/.well-known/acme-challenge/
RewriteRule ^(.*)$ https://%{HTTP_HOST}$1 [R=301,L]
</VirtualHost>
<VirtualHost *:443>
ServerName xxxxx.zapletalovi.com
Protocols h2 http/1.1
SSLEngine On
SSLCertificateFile /var/lib/acme/certs/xxxxx.zapletalovi.com.crt
SSLCertificateKeyFile /etc/pki/tls/private/xxxxx.zapletalovi.com.key
LimitRequestBody 0
ProxyTimeout 2000
ProxyPreserveHost On
RequestHeader set X-Forwarded-Proto "https"
RequestHeader set X-Forwarded-Port "443"
RewriteEngine On
RewriteCond %{HTTP:Upgrade} websocket [NC]
RewriteCond %{HTTP:Connection} upgrade [NC]
RewriteRule ^/?(.*) "ws://192.168.1.9:2283/$1" [P,L]
ProxyPass / http://192.168.1.9:2283/
ProxyPassReverse / http://192.168.1.9:2283/
</VirtualHost>
Of course, you need a TLS cert for HTTPS to work, I use tiny-acme. Search my
blog for an article on how to set it up.
That is all for now. Cheers!