immich – Foto und Video Management (nginx, https, Let’s Encrypt)

Die self-hosted Foto und Video Managementlösung. Einfaches Sichern, Organisiern und Verwalten Ihrer Fotos und Videos auf Ihren eigenen Servern. Wir zeigen Ihnen, wie sie die Software installieren und per https absichern.

Stand: 08. August 2025
Hersteller-Webseite: Link

  1. Installation
  2. Einrichten https (Let’s Encrypt)

1. Installation

Melden Sie sich als Benutzer mit priviligierten Rechten an und aktualisieren das System.

sudo -s
apt update && apt upgrade -V && apt full-upgrade

Fügen Sie die Docker-Repositories hinzu

for pkg in docker.io docker-doc docker-compose podman-docker containerd runc; do apt remove $pkg; done
apt install ca-certificates curl pwgen
install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
chmod a+r /etc/apt/keyrings/docker.asc

echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian \
  $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
  tee /etc/apt/sources.list.d/docker.list > /dev/null
for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do apt remove $pkg; done
apt install ca-certificates curl pwgen
install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
chmod a+r /etc/apt/keyrings/docker.asc

echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
  $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}") stable" | \
  tee /etc/apt/sources.list.d/docker.list > /dev/null

Richten Sie nun Docker ein und führen die Docker (compose) – Installation durch:

apt update && apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

Somit ist die Basisinstallation der notwendigen Dockerpakete bereits abgeschlossen. Folgen wir nun den Anweisungen des Herstellers. Erstellen Sie das IMMICH-Verzeichnis:

mkdir -p /var/opt/docker/immich/daten
cd /var/opt/docker/immich

Laden Sie das docker-compose.yml sowie die .env-Datei herunter:

wget -O docker-compose.yml https://github.com/immich-app/immich/releases/latest/download/docker-compose.yml
wget -O .env https://github.com/immich-app/immich/releases/latest/download/example.env

Passen Sie die .env-Datei an und nutzen dafür ein zufällig genieriertes Passwort:

pwgen -N 1 32

Bearbeiten Sie nun die .env-Datei

nano .env

Passen Sie die rot markierten Stellen an

# You can find documentation for all the supported env variables at https://immich.app/docs/install/environment-variables

# The location where your uploaded files are stored
UPLOAD_LOCATION=./daten

# The location where your database files are stored. Network shares are not supported for the database
DB_DATA_LOCATION=./postgres

# To set a timezone, uncomment the next line and change Etc/UTC to a TZ identifier from this list: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones#List
# TZ=Etc/UTC

# The Immich version to use. You can pin this to a specific version like "v1.71.0"
IMMICH_VERSION=release

# Connection secret for postgres. You should change it to a random password
# Please use only the characters `A-Za-z0-9`, without special characters or spaces
DB_PASSWORD=<siehe oben: pwgen -N 1 32>

# The values below this line do not need to be changed
###################################################################################
DB_USERNAME=postgres
DB_DATABASE_NAME=immich

Starten Sie nun die IMMICH Software.

docker compose up -d

Die Anwendung ist nun bereits einsatzfähig und kann im Browser aufgerufen werden:

http://<IP-DES-SERVERS>:2283

Klicken Sie auf „Erste Schritte“, führen die Admin-Registrierung durch

und melden sich dann das erste mal an der SOftware an:

Konfigurieren Sie die Anwendung nach Ihren Bedürfnissen:

2. Let’s Encrypt (https)

Richten Sie das nginx-Repository ein

apt install -y curl gnupg2 ca-certificates lsb-release ubuntu-keyring

curl https://nginx.org/keys/nginx_signing.key | gpg --dearmor \
| sudo tee /usr/share/keyrings/nginx-archive-keyring.gpg >/dev/null

echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] \
http://nginx.org/packages/mainline/ubuntu `lsb_release -cs` nginx" \
| sudo tee /etc/apt/sources.list.d/nginx.list

echo -e "Package: *\nPin: origin nginx.org\nPin: release o=nginx\nPin-Priority: 900\n" \
| sudo tee /etc/apt/preferences.d/99nginx
apt install -y curl gnupg2 ca-certificates lsb-release debian-archive-keyring

curl https://nginx.org/keys/nginx_signing.key | gpg --dearmor \
| sudo tee /usr/share/keyrings/nginx-archive-keyring.gpg >/dev/null

echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] \
http://nginx.org/packages/mainline/debian `lsb_release -cs` nginx" \
| sudo tee /etc/apt/sources.list.d/nginx.list

echo -e "Package: *\nPin: origin nginx.org\nPin: release o=nginx\nPin-Priority: 900\n" \
| sudo tee /etc/apt/preferences.d/99nginx

Für das Zertifikatshandling erstellen wir nun einen dedizierten Benutzer und fügen diesen der www-data Gruppe hinzu:

adduser acmeuser --gecos "" --disabled-password
usermod -aG www-data acmeuser

Diesem technischen Benutzer erteilen wir noch die notwendigen Berechtigungen, um bei einer Zertifikatserneuerung den notwendigen Webserverstart initiieren zu können.

touch /etc/sudoers.d/acmeuser
cat <<EOF >/etc/sudoers.d/acmeuser
acmeuser ALL=NOPASSWD: /bin/systemctl reload nginx.service
EOF

Installieren Sie nun für den Benutzer acmeuser das acme.sh-Tool und aktivieren zudem das automatische Upgrade:

su - acmeuser -c "/usr/bin/curl https://get.acme.sh | sh"
su - acmeuser -c ".acme.sh/acme.sh --set-default-ca --server letsencrypt"
su - acmeuser -c ".acme.sh/acme.sh --upgrade --auto-upgrade"

Um die hinzugefügten Repositories einzulesen und das System damit zu präparieren aktualisieren wir das System abermals und generieren temporäre „self-signed“-Zertifikate, die im späteren Verlauf durch vollwertige Zertifikate von Let’s Encrypt ersetzt werden.

apt update && make-ssl-cert generate-default-snakeoil -y

Nun sind die Vorbereitungen komplett abgeschlossen und wir können mit der Installation des Webservers nginx beginnen.

apt install -y nginx

Den automatischen Start des Dienstes setzen wir wie folgt:

systemctl enable nginx.service

Mit Blick auf die späteren Anpassungen wird die Standardkonfiguration gesichert und eine neue Konfigurationsdatei geöffnet:

mv /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak
touch /etc/nginx/nginx.conf && nano /etc/nginx/nginx.conf

Kopieren Sie den gesamten nachfolgenden Inhalt in die Datei:

user www-data;
worker_processes auto;
pid /var/run/nginx.pid;
events {
worker_connections 2048;
multi_accept on;
use epoll;
}
http {
log_format criegerde escape=json
'{'
'"time_local":"$time_local",'
'"remote_addr":"$remote_addr",'
'"remote_user":"$remote_user",'
'"request":"$request",'
'"status": "$status",'
'"body_bytes_sent":"$body_bytes_sent",'
'"request_time":"$request_time",'
'"http_referrer":"$http_referer",'
'"http_user_agent":"$http_user_agent"'
'}';
server_names_hash_bucket_size 64;
access_log /var/log/nginx/access.log criegerde;
error_log /var/log/nginx/error.log warn;
set_real_ip_from 127.0.0.1;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
include /etc/nginx/mime.types;
default_type application/octet-stream;
sendfile on;
send_timeout 3600;
tcp_nopush on;
tcp_nodelay on;
open_file_cache max=500 inactive=10m;
open_file_cache_errors on;
keepalive_timeout 65;
reset_timedout_connection on;
server_tokens off;
resolver 127.0.0.53 176.9.93.198 176.9.1.117 valid=30s;
resolver_timeout 5s;
include /etc/nginx/conf.d/*.conf;
}

Sichern Sie die Standard vhost-Datei namens default.conf und legen zuerst leere vHost-Dateien zum Konfigurieren an.

[ -f /etc/nginx/conf.d/default.conf ] && mv /etc/nginx/conf.d/default.conf /etc/nginx/conf.d/default.conf.bak
touch /etc/nginx/conf.d/default.conf
touch /etc/nginx/conf.d/http.conf
touch /etc/nginx/conf.d/immich.conf

Somit ist durch die leere „default.conf“ Datei auch bei späteren Aktualisierungen des Webservers sichergestellt, dass diese Standardkonfiguration den Betrieb nicht beeinflußt. Erstellen Sie die globale vhost-Datei, um die http-Standardanfragen permanent auf https umzuleiten und zudem die SSL-Zertifikatskommunikation mit Let’sEncrypt zu ermöglichen:

nano /etc/nginx/conf.d/http.conf

Kopieren Sie alle nachfolgenden Zeilen in die Datei http.conf und passen den rot markierten Domainnamen entsprechend Ihres Systems an:

server {
listen 80 default_server;
listen [::]:80 default_server;
server_name ihre.domain.de 192.168.0.170;
root /var/www;
location ^~ /.well-known/acme-challenge {
default_type text/plain;
root /var/www/letsencrypt;
}
location / {
return 301 https://$host$request_uri;
}
}

Speichern und schließen Sie diese Datei. Bearbeiten Sie nun die eigentliche immich vHost-Datei namens immich.conf, die sämtliche Konfigurationen für den sicheren Webserverbetrieb der immich-Software enthält.

nano /etc/nginx/conf.d/immich.conf

Fügen Sie alles hinzu und passen die rot markierten Werte an:

server {
listen 443 ssl;
listen [::]:443 ssl;
http2 on;
server_name ihre.domain.de 192.168.0.170;
ssl_certificate /etc/ssl/certs/ssl-cert-snakeoil.pem;
ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key;
ssl_trusted_certificate /etc/ssl/certs/ssl-cert-snakeoil.pem;
#ssl_certificate /etc/letsencrypt/rsa-certs/fullchain.pem;
#ssl_certificate_key /etc/letsencrypt/rsa-certs/privkey.pem;
#ssl_certificate /etc/letsencrypt/ecc-certs/fullchain.pem;
#ssl_certificate_key /etc/letsencrypt/ecc-certs/privkey.pem;
#ssl_trusted_certificate /etc/letsencrypt/ecc-certs/chain.pem;
ssl_dhparam /etc/ssl/certs/dhparam.pem;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
ssl_protocols TLSv1.3 TLSv1.2;
ssl_ciphers 'TLS-CHACHA20-POLY1305-SHA256:TLS-AES-256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384';
ssl_ecdh_curve X448:secp521r1:secp384r1;
ssl_prefer_server_ciphers on;
client_max_body_size 10G;
client_body_timeout 3600s;
client_body_buffer_size 512k;
fastcgi_buffers 64 4K;
gzip on;
gzip_vary on;
gzip_comp_level 4;
gzip_min_length 256;
gzip_proxied expired no-cache no-store private no_last_modified no_etag auth;
gzip_types application/atom+xml text/javascript application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject application/wasm application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard text/vnd.rim.location.xloc text/vtt text/x-component text/x-cross-domain-policy;
add_header Strict-Transport-Security            "max-age=15768000; includeSubDomains; preload;" always;
add_header Permissions-Policy                   "interest-cohort=()";
add_header Referrer-Policy                      "no-referrer"   always;
add_header X-Content-Type-Options               "nosniff"       always;
add_header X-Download-Options                   "noopen"        always;
add_header X-Frame-Options                      "SAMEORIGIN"    always;
add_header X-Permitted-Cross-Domain-Policies    "none"          always;
add_header X-Robots-Tag                         "noindex, nofollow" always;
add_header X-XSS-Protection                     "1; mode=block" always;
add_header Alt-Svc                              'h3=":$server_port"; ma=86400';
add_header x-quic                               'h3';
add_header Alt-Svc                              'h3-29=":$server_port"';
fastcgi_hide_header X-Powered-By;
location / {
client_max_body_size                51200M;
proxy_max_temp_file_size            51200M;
proxy_connect_timeout               3600;
proxy_read_timeout                  3600;
proxy_send_timeout                  3600;
send_timeout                        3600;
proxy_redirect                      off;
proxy_buffering                     off;
proxy_request_buffering             off;
proxy_set_header X-Real-IP          $remote_addr;
proxy_set_header X-Forwarded-Proto  $scheme;
proxy_set_header X-Forwarded-For    $proxy_add_x_forwarded_for;
proxy_set_header Host               $host;
proxy_set_header Upgrade            $http_upgrade;
proxy_set_header Connection         "upgrade";
proxy_http_version                  1.1;
proxy_pass http://192.168.0.170:2283;
}
}

Generieren Sie noch den dh-key und starten dann den Webser neu:

openssl dhparam -dsaparam -out /etc/ssl/certs/dhparam.pem 4096
systemctl restart nginx.service

Vorbereitend legen Sie die notwendigen Ordner an und setzen die korrekten Berechtigungen:

mkdir -p /var/www/letsencrypt/.well-known/acme-challenge /etc/letsencrypt/rsa-certs /etc/letsencrypt/ecc-certs
chmod -R 775 /var/www/letsencrypt && chmod -R 770 /etc/letsencrypt
chown -R www-data:www-data /var/www/ /etc/letsencrypt

Wechseln Sie in die Shell des acme-Benutzers

su - acmeuser

und beantragen dann die SSL-Zertifikate von Let’s Encrypt. Ersetzen Sie dafür bitte ihre.domain.de mit Ihrer „echten“ Domain:

acme.sh --issue -d ihre.domain.de --server letsencrypt --keylength 4096 -w /var/www/letsencrypt --key-file /etc/letsencrypt/rsa-certs/privkey.pem --ca-file /etc/letsencrypt/rsa-certs/chain.pem --cert-file /etc/letsencrypt/rsa-certs/cert.pem --fullchain-file /etc/letsencrypt/rsa-certs/fullchain.pem --reloadcmd "sudo /bin/systemctl reload nginx.service"
acme.sh --issue -d ihre.domain.de --server letsencrypt --keylength ec-384 -w /var/www/letsencrypt --key-file /etc/letsencrypt/ecc-certs/privkey.pem --ca-file /etc/letsencrypt/ecc-certs/chain.pem --cert-file /etc/letsencrypt/ecc-certs/cert.pem --fullchain-file /etc/letsencrypt/ecc-certs/fullchain.pem --reloadcmd "sudo /bin/systemctl reload nginx.service"

Verlassen Sie die Shell des acme-Benutzers

exit

Entfernen Sie Ihre bisher verwendeten Self-Signed-Zertifikate aus nginx und aktivieren Sie die neuen, vollwertigen und bereits gültigen SSL Zertifikate von Let’s Encrypt. Starten Sie dann den Webserver neu:

sed -i '/ssl-cert-snakeoil/d' /etc/nginx/conf.d/immich.conf
sed -i s/#\ssl/\ssl/g /etc/nginx/conf.d/immich.conf
systemctl restart nginx.service

Rufen Sie nun im Browser ihre Domain auf: https://ihre.domain.de und nutzen ihre abgesicherte immich-Lösung.

Das war’s schon! Über Ihre Unterstützung (diese wird ordnungsgemäß versteuert!) würden sich meine Frau, meine Zwillinge und ich sehr freuen.