So, I have some idea on what a reverse proxy does and will be using nginx (with the neat proxy manager UI) for my setup.
However, I’m not completely clear what exactly I want it to do and how I cn use it to run different services on one machine. I’m especially unclear on the ports configuration … tutorials will say things like “change the listening port to xxx for that service and to port yyy for the other service”
How does this work, which ports can I use and how do I need to configure the respective services?
EDIT: thanks everybody, your replies did help me a lot! I have my basic setup now up and running using portainer + nginx + fail2ban.
ELI5
So it’s saturday afternoon, a very hot one, so you ask your daddy for an ice cream (hosted service). The shop you go in is very bizarre though, as there is one vendor (TCP port) for each flavor (docker service/virtualhost). But it’s tricky because they’re all roaming in the shop, and you don’t know who’s responsible for each flavor. Your dad is also not very comfortable paying these vendors directly because they only accept cash and do not provide any receipt (self-signed certificate/no TLS).
Hopefully, there is the manager (reverseproxy) ! This girl is right where you expect her: behind the counter (port 80/443), accept credit cards and has a receipt machine (Domain name + associated certificate). She also knows everyone on her team, and who’s responsible for each flavor !
So you and your dad come to see the nice lady, ask for a strawberry + chocolate ice cream, and pay her directly. Once done, she forwards your request directly to the vendors responsible for each flavor, and give you back your ice cream + receipt. Life is good, and tasty !
That one is easy ! Because in a few years (remember, you’re 5), you’ll be a scout ! And to collect a few dollars for your summer camp, you’ll sell pastries to the neighborhood. It’s easier than ever because it’s 2030, and everyone can just order the pastries on your website, and pay online. All you have to do now is hop on your bike, and deliver the pastries (network connections) to your neighbors (online servers). So you grab the first package, and read the label on it:
- Mrs. Britneak
And that’s it ! You have no idea who this person is, or where they live ! So you call out your leader (DNS server):
- Hi Mr. Leader !
- … (nobody ever get my UDP jokes)
- So I got this package to deliver to mrs. Brtineak. But I don’t know where she lives
- Oh sure, let me lookup the register (zone file). Hold on for a sec… Alright, she’s here: 62.644888, -160.194309
And then he hangs up immediately (this is UDP, remember?).
You write it down (local caching DNS server), and look it up. You’re a scout, so you’re trained to read and find GPS coordinates. You go there in a few minutes and deliver the package in time ! Mrs Britneak is happy, and you go on to the next package:
- Mr. Tomburgh
Time to call leader again !
I’ll provide an ELI5, though if you actually want to use it you’ll have to go beyond ELI5.
You contact a web service via a combination of IP address and port. For the sake of simplicity, we can assume that domain name is equivalent to IP address. You can then compare domain name/port with street name/street number: you need both to actually find someone. By default, some street numbers are really standard, like 443 is for regular encrypted connection. But you can have any service on any street number, it’s just less nice and less standard. This is usually done on closed networks.
Now what happens if you have a lot of services and you want all of them reachable at address 443? Well basically you are now in the same situation as a business building with a lobby. Whenever you want to contact a service, you go to 443, ask the reception what floor they are in, and they will direct you there. The reception desk is your proxy: just making sure you talk to the right people.
A reverse proxy is a service that takes incoming traffic on an IP address and port. It reads the URL the connection came into and passes it to the service it is configured for.
Example: A server runs Plex. There is a DNS entry plex.myhome.nework that points to the IP of that server. Nginx listens on port 80 and 443. If a client connects to port 80 using plex.myhome.network nginx will pass it to Plex. If it comes in on 443 nginx will still pass it to Plex but it will also provide the configured SSL cert to the client connecting to Plex.
If the server is also running jellyfin and DNS is setup for jellyfin.myhome.network with the same IP. The user connects to jellyfin.myhome.network on port 80 Nginx instead passes it to jellyfin.
So from our example you can see that we have both jellyfin and Plex using the same IP address and port 80.
Since you already got a lot of ELI5s, here is a basic to-do to get you up and running. From my experience, since I use the exact same setup as you describe.
- Set up your containers in a way you can reach them from you local network (e.g. http://123.456.789.10:123)
- Get a domain name (you can get one at the registrar of your choice, e.g. mydomain.com)
- Set up NGINX proxy manager (NPM) (default address of webui would be http://123.456.789.10:81)
- Set up a new proxy host in NPM:
- Domain name: mycontainer.mydomain.com
- Scheme: http
- Forward Hostname/IP: 123.456.789.10 (if you get an error later on, you can use the docker container name if NPM and your container are connected to the same Docker network)
- Port: 123
- Via access lists you can provide a very basic username/pw login to protect your sites (you can do more and cooler stuff with Authelia)
- In the SSL tab you can (and should) setup the SSL encryption: https://www.youtube.com/watch?v=TBGOJA27m_0
- Go to the DNS management of your registrar
- Add an A-record for mydomain.com and the public IP of your server (you can google public IP to find it out)
- Add a CNAME record for the subdomain with name mycontainer and target mydomain.com
- open port 443 of your server in your router If everything worked right, you can visit mycontainer.mydomain.com, your DNS server will resolve this to your public IP and forwards the request to nginx, which will serve the data of your local container
Here is an alternative Piped link(s): https://piped.video/watch?v=TBGOJA27m_0
Piped is a privacy-respecting open-source alternative frontend to YouTube.
I’m open-source, check me out at GitHub.
So a reverse proxy is sort of like a phonebook or directory, it routes outside requests to the appropriate place. So imagine your reverse proxy is a receptionist, someone comes in and says “hey I am looking for plex.mydomain.com” the receptionist would then use the phonebook and say “ok if you are looking for plex.mydomain.com, go to building 192.168.1.10 (the ip), room 9000 (the port)”
Since you are asking about dockerized services, the networking for those can be done in several different ways, but the one thing that really matters is that each service needs to have a unique combination of ip and port, because only 1 service can live at each address. With docker, you could set up multiple services that use the host server’s ip, in which case each container will need to be on different ports, or you could have it so each container has its own ip, in which case the port can be anything.
This makes it clearer to my, would you mind helping me to understand all steps for my usecase. I want to run a lemmy instance and a mastodon instance on the same VPS, using the same domain but different subdomains - lmy.my-domain.tld and mstdn.my-domain.tld. I have my VPS IP address and setup the 2 subdomains with my domain provider (both subdomains are resolving the same IP).
I also did setup nginx on my server and can install SSL certificates for both of these domains. I’m now at the step where lmy.my-domain.tld should by directed to the lemmy service and mstdn.my-domain.tld to the mastodon service. As I understand it, both services listen to the ports 80 (http) and 443 (https). Do I now setup a room/building for Lemmy / Mastodon respectively where I tell nginx that lmy.my-domain.tld is at 0.0.0.0:3001 and mstdn.my-domain.tld is at 0.0.0.0:3002 for example. And in the config files for each of these installs I’d specify “0.0.0.0:300x” respectivly? (also have to make sure, that these docker installs don’t mess with my nginx config by themselves, right?)
It sounds like what you need to do at this point is find what IP address your lemmy instance and mastodon instance containers are using on your VPS. you can do “docker inspect containername” and look for the IP address in there. it might be something like 172.16.0.1 for lemmy and 172.17.0.1 for mastodon. then you want to set up your reverse proxy to point lmy.my-domain.tld to 172.16.0.1:80 (or whatever port you set lemmy to use) and then mstdn.my-domain.tld to point to 172.17.0.1:80 (again, port might be different, i dont know what the default port is)
-IF- both of the containers are using the same IP, then you will need to make sure that they are using different ports. if they are on the same ip and same port, whichever container loads 2nd will fail to properly load, because when a port is taken on an IP address, it is reserved and nothing else can try to listen on that port.