Using NGINX Proxy Manager With Immich
Hi, so glad to see some of the great support here in the discord for this awesome app. I cant quite find the info I need (or I just am not fully understanding the API gateway for Immich)
Everything is running perfectly with the app, the issues come in when I attempt to add my reverse proxy in front. It seems any type of API request is broken, I can even load and upload assets (unless is uses API I think, then I get an error) but I cannot save any settings. I need this to make my Immich instance easily available to anyone anywhere.
We can pretend my domain is photos.mydomain.com, and my docker host internal IP is 192.168.1.2. In NGINX Proxy Manager I have set up a simple proxy host with no advanced config, allowed websockets, blocked common exploits, using an SSL cert with a wildcard for *.mydomain.com
docker-compose.yml has very slightly tweaked ports, and I use my own postgresql server so I removed that container completely, all sql functions seem to work find. Posting this second due to length
.env file is pretty much basic, no crazy modifications:
UPLOAD_LOCATION=/data/immich-uploads
IMMICH_VERSION=release
TYPESENSE_API_KEY=uniqueKey
DB_PASSWORD=immich-user-password
DB_HOSTNAME=192.168.1.3
DB_USERNAME=immich-user
DB_DATABASE_NAME=immichdb
REDIS_HOSTNAME=immich_redis
REVERSE_GEOCODING_PRECISION=2


31 Replies
here is my docker-compose.yml file
here are the errors I see in the inspection console of the browser
and again everything works perfectly using http://192.168.1.2:2282 in a browser or app, also worth mentioning I cant even get the app to act normal and connect I just end up in a login loop using photos.mydomain.com
sorry for the so many follow ups but I also just realized that navigating to https://photos.mydomain.com/api/server-info does indeed work and give me all my server info in JSON format
Can you record a video of it not working?
And are there any errors in the log for immich_server or your proxy?
I should be able to get a video and DM it, and I will have to check for errors, sorry I totally forgot before posting but I want to say couldnt find anything before
so not really much in the immich-server or immich-proxy logs I can see, I dont think that timeout error is related since they dont pop up when I get the error trying to set settings
also my reverse proxy I am using this fork of NPM which is actually starting to age and hasnt seen an updated release in a bit: https://github.com/baudneo/nginx-proxy-manager
I am thinking of switching to this other fork since it still includes open resty bouncer for crowdsec but has very recent releases and is more "vanilla" in comparison: https://github.com/LePresidente/docker-nginx-proxy-manager
still gotta get that video but from seeing others on the internet using NPM no problem with Immich I am wondering if it might be this very different fork most others are not using that I happen to be using
GitHub
GitHub - baudneo/nginx-proxy-manager: Docker container for managing...
Docker container for managing Nginx proxy hosts with a simple, powerful interface. Now includes ModSecurity WAF and CrowdSec OpenResty Bouncer. - GitHub - baudneo/nginx-proxy-manager: Docker contai...
GitHub
GitHub - LePresidente/docker-nginx-proxy-manager: Docker container ...
Docker container for Nginx Proxy Manager. Contribute to LePresidente/docker-nginx-proxy-manager development by creating an account on GitHub.


Do you run npm and immich on the same host via docker?
yes I do, I recently joined my npm container to the immich docker network, so it can ping all the containers by name, I was hoping changing the config to use the container names would help but it seems to give me the same result
the thing I can't understand is
what exactly is the problem ?
I did quite the same as you
(deployed my immich instance with docker-compose up -d)
and then I deployed an other stack with nginx
with Nginx I call the port of the machine, I'm not using docker network at all (it's a pain in the a** :cryge: )
(if my machine ip is 192.168.0.10, nginx is on 192.168.0.10:81 and immich is on 192.168.0.10:2283 and I call this ip)
I half figured it out lol
So, I have two different machines that are docker hosts, a newer one and my older docker host machine. I had not started any new docker containers yet on the new machine so I decided to spin up a fresh version of NGINX Proxy Manger, but this fork: https://github.com/LePresidente/docker-nginx-proxy-manager
I had been using a different fork that had not been updated in like a year
Once I got the new docker container for NPM up and running I forwarded traffic to the local IP and port for the immich-proxy container (on a different docker host so no using docker networks between them).
Now it seems like the immich app and browser functions work perfectly over the internet using the domain name(just have to put the trailing /api like https://photos.mydomain.com/api).
GitHub
GitHub - LePresidente/docker-nginx-proxy-manager: Docker container ...
Docker container for Nginx Proxy Manager. Contribute to LePresidente/docker-nginx-proxy-manager development by creating an account on GitHub.
I did just finish updating my internal DNS that points to NPM if mydomain.com is queried from within my LAN network (makes the domain work within the same network it exists on) and I am still getting the same errors I had before when trying to save settings, and if I try to connect from the app using domain name from home (inside LAN) I just get the login loop where it just flashes back to empty login screen with no error
so, halfway there, everything is working externally, I just gotta figure out why I am having issues with my internal DNS that points to NPMs private IP itself if my domain is queried from within my LAN network
☝️
Question sir
Why are you complicating your life setting up an internal dns instead of using a "classical" DNS ?
I am using both, but from what I understand I need to setup an internal DNS server since I am using the same public IP my server is at, at home, if I try to connect to my public IP from itself it will not work
so internal DNS is already running as a sinkhole for ads/tracking, there I just added a zone for mydomain.com that responds to any query from within my internal network with the internal IP for NPM
here is my NPM proxy-host config if anyone sees anything related to what I am describing, I cannot say I do:
bash-5.1# cat /config/nginx/proxy_host/3.conf
------------------------------------------------------------
photos.mydomain.com
------------------------------------------------------------
server {
set $forward_scheme http;
set $server "192.168.1.2";
set $port 2282;
listen 8080;
listen [::]:8080;
listen 4443 ssl http2;
listen [::]:4443 ssl http2;
server_name photos.mydomain.com;
# Let's Encrypt SSL
include conf.d/include/letsencrypt-acme-challenge.conf;
include conf.d/include/ssl-ciphers.conf;
ssl_certificate /etc/letsencrypt/live/npm-26/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/npm-26/privkey.pem;
# Block Exploits
include conf.d/include/block-exploits.conf;
# HSTS (ngx_http_headers_module is required) (63072000 seconds = 2 years)
add_header Strict-Transport-Security "max-age=63072000;includeSubDomains; preload" always;
# Force SSL
include conf.d/include/force-ssl.conf;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $http_connection;
proxy_http_version 1.1;
access_log /data/logs/proxy-host-3_access.log proxy;
error_log /data/logs/proxy-host-3_error.log warn;
location / {
# HSTS (ngx_http_headers_module is required) (63072000 seconds = 2 years)
add_header Strict-Transport-Security "max-age=63072000;includeSubDomains; preload" always;
proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $http_connection; proxy_http_version 1.1;
# Proxy! include conf.d/include/proxy.conf; } # Custom include /data/nginx/custom/server_proxy[.]conf; } but yeah if that makes sense, you need a DNS server running inside your LAN network to tell your devices what private IPs to connect to if you query your domain (unless you have a seperate public IP for your server stuff and residential internet circuit). In my case I usually just respond to all queries with the private IP of my NPM instance, and then NPM usually handles the proxy forwarding from there like any other traffic, it seems I am missing something related here cause what I want to achieve here is set and forget the configuration of my app and then it should work no matter what long as I have mobile data or wifi, anywhere with my hostname I am already to the point where I can give family members accounts and they should be able to access everything from anywhere outside my home network, so that is awesome within itself, still happy I have gotten this far xD also just tested now after thinking about it and I get the same behavior whether I set my internal DNS record to point at NPM private IP OR Immich-proxy private IP
proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $http_connection; proxy_http_version 1.1;
# Proxy! include conf.d/include/proxy.conf; } # Custom include /data/nginx/custom/server_proxy[.]conf; } but yeah if that makes sense, you need a DNS server running inside your LAN network to tell your devices what private IPs to connect to if you query your domain (unless you have a seperate public IP for your server stuff and residential internet circuit). In my case I usually just respond to all queries with the private IP of my NPM instance, and then NPM usually handles the proxy forwarding from there like any other traffic, it seems I am missing something related here cause what I want to achieve here is set and forget the configuration of my app and then it should work no matter what long as I have mobile data or wifi, anywhere with my hostname I am already to the point where I can give family members accounts and they should be able to access everything from anywhere outside my home network, so that is awesome within itself, still happy I have gotten this far xD also just tested now after thinking about it and I get the same behavior whether I set my internal DNS record to point at NPM private IP OR Immich-proxy private IP
What port does npm run on?
So it works via local IP and via domain name, but only from an external connection?
Do you forward your router port 443 to npm port 4443?
correct
so NPM currently is running 8181 for web GUI 8080 for HTTP and 4443 for HTTPS
port forwarded accordingly from the router for 80 and 443
Does it work with domain and port 4443 on your local network?
Or does your router support hairpinning?
yes I am running a Mikrotik router with RouterOS 7, if you dont know what that is it can basically do everything lol
very interesting test though
https://mydomain.com:4443 works
but
https://photos.mydomain.com:4443/ fails

If your router supports hairpinning why do you have split DNS for that domain in the first place?
i should mention mydonain.com just takes you to very simple static HTML content
so without an internal DNS server to catch requests for my domain I dont see how else to get my services to work internally from a browser.
for example if I check something like whatismyipaddress.com and I get 100.100.100.100 as my public IP from inside my network
just using my public facing authoritative DNS server, when I query my domain I would get 100.100.100.100, this works from everywhere except itself, if that makes sense
I cannot connect to 100.100.100.100 from 100.100.100.100, thus I implemented a zone for mydomain.com that instead replies to the queries with the internal IP of NPM, and this is configured on my internal DNS server I already use for ad sinkholing
is there a better way to achieve that for external domain name usage internally just the same?
lol i hope that makes sense
You can connect to 100.100.100.100 from 100.100.100.100 this is called hairpinning.
And on different ports.
The request to your domain:
- gets public IP from external DNS server
- resolves to the public IP of the router (port 443)
- the router applies port forwarding rules and sends the connection to private IP/target port
The connection goes out to the router and the immediately back into the lan, which is why they call it a hairpin.
Either way, usually the connection doesn't work at all if there is an issue. Your initial report seemed to indicate some stuff works and some stuff doesn't, which seems to imply something else might be misconfigured, since some traffic is making it to the immich server.
Is it normal for npm to listen for http2? Or is that custom?
ah yes that makes total sense, I am an admin at an ISP actually and we use the term hairpin nat completely differently but I understand now xD
I could just make rules in my router that are similar to the port forwards from WAN port 80 or 443 to NPM, but they would be like from LAN port 80 or 443 destined for 100.100.100.100 forward to NPM
does that sound right?
I would initially think the private/local DNS server is cleaner then adding NAT rules, but honestly it all sounds kinda complicated saying it out loud lol
I think the cleanest is only using external DNS and port forwarding rules. The next best is split DNS.
Personally, I have always run into issues when using split DNS and npm using a different port external vs internal.
hmm ok you think it could help to change my NPM ports to 80 and 443 instead? its only default for the fork I am using to have 8080 and 4443
DNS only resolves to IP. If you resolve domain.com to a local IP, then domain.com:443 resolves to 192.168.0.1:443
a quick test of the hairpin nat method is not working right so I might have to read some and mess with that more
Also DNS can be complicated to test because of caching. You can always set it in your hosts file to make sure, when properly pointing to the right IP, it is working correctly.
lmao was just about to say scratch what I just said its not valid cause of the DNS caches xD
ah also forgot to answer your question about HTTP2, I think its just an option I have checked in NPM
I have an ISP provided gateway, which has a public IP and I forward it to my actual router so I can't do hairpin myself as the ISP provided gateway kind of sucks
You may want to try leaving everything like your had it and turn this off
For me though:
- split DNS resolves local IP to npm
- npm runs on 443/80
- external port 443/80 forwards to npm 443/80
I got it!!! so I think my old NPM instance was broken within somehow to begin with, but when I set up the new NPM fork using 8080 and 4443 instead of 80 and 443, I just needed to add portforwards for LAN traffic destined for NPM like 80 > 8080 and 443 > 4443, which I already had rules to redirect internet traffic destined to my public IP for these odd ports. And I did not need these port forwards for my LAN when NPM was running on the regular 80 and 443 ports
also I did disable the HTTP/2 config for my immich proxy-host since we shouldnt need that.
thanks for all the help, it definitely helped me out a lot!!
everything works as expected within LAN or outside internet, success
for anyone following, I wouldnt use this fork of NPM until the maintainer updates it more, I had issues even setting it up before, and obviously it wasnt working correctly here:
https://hub.docker.com/r/baudneo/nginx-proxy-manager
:Clapclap: