It’s something I need to get around to writing some well-diagrammed guide for. I just know of the vendor documentation, meanwhile I don’t have any comprehensive guides to recommend off-hand.
Effectively there’s two ways to achieve it: HTTP(S) Reverse Proxy: a web browser makes an HTTP or HTTPS connection to a VPS, the VPS then makes an HTTP or HTTPS connection over a tunnel (such as WireGuard) to your basement server (while including the IP address of the original client IP as an HTTP header in the subrequest). Basement server sends it’s response, which the VPS then sends in it’s response to the browser.
In this scenario, the VPS needs to have a valid TLS certificate (and it’s associated private key) on the VPS, if you’re doing HTTPS. If the VPS gets compromised (such as if you don’t trust your VPS host), then any traffic transiting through the VPS is considered compromised. Additionally, whatever web applications you have running on your basement server will need some configuration to handle X-Forwarded-For or Forwarded headers, to properly handle ‘client IP’ info, because otherwise the webapps on the basement server only ever see your VPS as the ‘client’ for every request (which makes blocking bad actors difficult from the basement server without).
If using Apache on the VPS, you need mod_proxy and mod_proxy_http enabled ( https://httpd.apache.org/docs/2.4/howto/reverse_proxy.html ), while Apache will automatically add X-Forwarded-For headers and such for you. You’ll only need ProxyPass, ProxyPassReverse, ProxyPreserveHost in your config.
Say the remote IP of the WireGuard tunnel (your basement server) is 10.12.34.56, the config within a VirtualHost config on the VPS would look like:
ProxyPass "/" "http://10.12.34.56" ProxyPassReverse "/" "http://10.12.34.56" ProxyPreserveHost OnMeanwhile, if nginx on the VPS instead, there’s no modules to enable (it’s built-in), you just use the proxy_pass directive ( https://docs.nginx.com/nginx/admin-guide/web-server/reverse-proxy/ ) within a location { } directive inside of a server { }, and also set the headers too, such as:
location / { proxy_pass http://10.12.34.56; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Port $server_post; }Configuring WireGuard, as well as how to configure your respective hosted webapp for X-Forwarded headers is out-of-scope of this overview, you’ll have to seek out more info elsewhere. But the key detail with the WireGuard tunnel is: on the basement server’s WireGuard config, to have PersistentKeepalive set in the peer declaration for the VPS peer config, in order to keep the tunnel open to be able to receive inbound traffic at any time, to be able to traverse NAT properly.
The other method is:
HAProxy and PROXY Protocol: a web browser tries to make an HTTP or HTTPS connection to the VPS. HAProxy (or nginx with ngx_stream_ssl_preread support) receives the connection: if it’s HTTP, it reads the request and forwards it to the basement server using the PROXY protocol over WireGuard, and forwards any response back to the browser. If it’s HTTPS, it prereads what domain the browser is trying to access in the TLS exchange (for routing the request, in case there’s different backends for different domains), and blindly forwards the rest of the traffic to the basement server using the PROXY protocol over WireGuard, and forwards any response back.
In this scenario, the PROXY protocol is used as a sort of ‘preamble’ to the backend connection, telling the basement server of what client IP it received the connection for, which gets sent before the request itself. Operationally, the VPS serves no more than an application-level router, while any TLS exchange is actually handled at the server forwarded to (e.g. only the basement server decrypts the traffic). In this case, the VPS doesn’t require any sort of private key to handle HTTPS connections, and just routes them instead.
This requires the webserver (Apache/nginx/whatever) on the basement server to be set up with PROXY protocol support, as it has to be configured to expect PROXY protocol preambles: Apache: https://roadrunner2.github.io/mod-proxy-protocol/mod_proxy_protocol.html nginx: https://docs.nginx.com/nginx/admin-guide/load-balancer/using-proxy-protocol/
There’s a lot more involvement in setting it up, and requires competency of HAProxy (for the VPS) to configure. Seek out “HAProxy SNI passthrough” guides to make full use of the SNI-based “routing”, and use “send-proxy” in the ‘server’ declaration in a backend. If the VPS is only to be in front of one server, with no need to route between different backends, then just plain “SSL passthrough” is possible too for simpler setup.
An example with SNI-based forwarding: https://serverfault.com/a/949583