I have a dedicated server with one public IP that runs a KVM virtualization and it's hosting several VMs. These VMs expose ports of running applications via port-forwarding at the moment and we will need to add HTTPS to it. Currently only to one VM but there will probably be more coming in the future - each VM would have its own subdomain.
So the questions is, what's the right approach to tackle it? I can see two options
Having nginx with certbot running on top of the bare metal machine itself, use it to create a wildcard certificate and relay requests to a different VMs/subdomains.
Have an instance of nginx/certbot on each VM and have the subdomains validated separately.
I would prefer option 2 but I am not sure whether this setup is going to work with only public IP.
Thanks a lot for any hints how to correctly approach this scenario!
Are we talking webservers only or also other services?
Because for webservers where you want to share port 80/443 on multiple VMs, it might be possible in your situation to set up a reverse proxy on one of the VMs (or the "bare metal machine") which will answer to all external requests on port 80/443, which will forward those requests to separate VMs internally based on e.g. the hostname of the request using SNI.
Nope, dns-01 wouldn't work because our DNS provider is NameCheap - there's no official plugin (and unofficial doesn't work) and it's quite unsafe to do it because you can even transfer domain of the API key is leaked.
So, some sort of reverse proxy would have to running on the "bare metal" itself in either case?
Or on one of the VMs. Unless you have another idea on how to "redistribute" requests for /.well-known/acme-challenge/ on port 80 between the different VMs.
Although running the reverse proxy on the bare metal machine is probably, I think, more elegant. If you'd like you could have multiple certificates next to each other. Or a single one covering everything.
One option I personally like for a reverse proxy is the Caddy server, which has support built-in for getting certificates from any ACME Certificate Authority. You may find it easier than running both certbot and nginx, but that’s a popular combination too.
I'm still unsure about your desired end state.
Is the intent to hide the VMs behind one IP and have them all use the exact same port?
Like all behind https://[FQDNs that all resolve to same IP]/ ?
Can you hide the VMs behind one IP, but use separate ports for each of them?
Like: https://[FQDNs that all resolve to same IP]:[various ports]/ ?
Will you operate all the VMs?
[Will any VM require getting their own separate cert and private key?]
In a scenario where, let's say, you will operate/manage all the VMs:
Then you can use HTTP authentication [even via --standalone web server] and handle all the cert requests on the (bare metal) host.
Reverse proxy those HTTP requests (via SNI) inwards to their respective VMs.
Then, if each VM can use its' own secure port (via the shared external IP), you can simply port forward their secure ports to them directly (without the need for a reverse proxy for the secured ports).
As an example:
External port 10001 > VM1:443
External port 10002 > VM2:443
External port 10003 > VM3:443
In the case that each VM must be accessed via the same IP and the same port: https://vm1.example.com https://vm2.example.com https://vm3.example.com
Then you are left with no choice but to use a reverse proxy to handle that one-to-many problem.
Thanks for reply! Option number two is correct - for the services needing the HTTPS, each of them can run under a different port. Yes, I am operating all of them and each VM can have it's won cert if needed but it doesn't have to be this way (I guess that's a question of best setup).
So, if I get it right, with the standalone option I can get a wildcard certificate for my domain and then route specific requests to the corresponding VM via its exposed port, is that correct? Therefore there's no HTTPS authorization going on in the VMs.
You can open a second namecheap account and have their customer support give it api access. you can then provision ONLY your dns records for the selected domains to be controlled via that second account. IMHO, they actually have one of the best Security and ACL systems of all the major providers – they just have the worst DNS system.
IMHO, I think terminating SSL on the bare metal (essentially. Option 1) like a traditional gateway is your best option. You can do Option 2 with each system having their own nginx/certbot within a VM and terminate SSL there, but you will need to run nginx or similar on the bare metal and use that for port forwarding to the correct VM -- which you will likely need to do anyways if you have more than 1 domain that will answering https on that IP.