A reverse-proxy gateway is a public server whose only job is to receive web traffic, terminate HTTPS, and forward requests to services that aren’t directly exposed: an app on a home server, a dashboard on a private network, or several backend servers. The backends stay hidden; only the gateway faces the internet.

When this is useful

  • Self-hosting at home behind CGNAT or a dynamic IP — the VPS provides a stable public IP and HTTPS.
  • Hiding backend servers — attackers only see the gateway.
  • One place for TLS, authentication and rate limits across many services.
  • Combining services from different locations under one domain.

Architecture

Internet ──HTTPS──▶ VPS gateway (Nginx) ──WireGuard──▶ home server 10.20.0.2:8080
                                          └────────▶ backend VPS 10.20.0.3:3000

The backends connect to the gateway over an encrypted WireGuard tunnel, so you don’t need to open any ports at home.

1. Build the tunnel

On the gateway (10.20.0.1) and each backend, install WireGuard and create peers. The home server initiates the connection (with PersistentKeepalive = 25) so it works behind NAT. Full walkthrough: site-to-site VPN tunnel.

Check from the gateway:

ping 10.20.0.2
curl -I http://10.20.0.2:8080

2. Nginx on the gateway

upstream home_app {
    server 10.20.0.2:8080;
    keepalive 16;
}

server {
    server_name app.example.com;
    listen 443 ssl;
    http2 on;
    # certificates from certbot

    location / {
        proxy_pass http://home_app;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto https;
    }
}
certbot --nginx -d app.example.com --redirect

3. Add authentication for private tools

Admin dashboards shouldn’t be public just because they’re behind a proxy. Options from simplest to most capable:

HTTP basic auth

apt install -y apache2-utils
htpasswd -c /etc/nginx/.htpasswd alice
location / {
    auth_basic "Restricted";
    auth_basic_user_file /etc/nginx/.htpasswd;
    proxy_pass http://home_app;
}

IP allow-list — allow 203.0.113.50; deny all; inside the location.

Single sign-on — put an identity provider such as Authentik in front with Nginx auth_request, giving every service one login with 2FA.

4. Rate limiting and size limits

# http {} block
limit_req_zone $binary_remote_addr zone=gw:10m rate=20r/s;

# server/location
limit_req zone=gw burst=40 nodelay;
client_max_body_size 100m;

5. Lock down the gateway

  • Firewall: allow only 22 (restricted), 80, 443 and the WireGuard UDP port.
  • Backends: allow their service ports only on the wg0 interface.
  • Keep the gateway minimal — no databases or apps on it.
  • Automatic security updates — see unattended upgrades.

6. Performance considerations

Every request travels visitor → gateway → backend and back. To keep it fast:

  • Place the gateway close to the backend (or to your users if the backend is close to them too).
  • Use keepalive connections to upstreams.
  • Cache static files on the gateway with proxy_cache.

Home upload bandwidth often becomes the limit for self-hosted media; cache aggressively or keep large files on the VPS.

Alternatives

  • Caddy — simpler config with automatic HTTPS.
  • Traefik — dynamic configuration from Docker labels.
  • Managed tunnels (Cloudflare Tunnel, Tailscale Funnel) — no gateway to run, but traffic flows through a third party.

Summary

A small VPS with Nginx and WireGuard makes a secure, stable front door for services anywhere. Even an entry-level KVM VPS handles a lot of proxied traffic. Related: reverse proxy on Linux and Nginx for Docker containers.

  • Reverse Proxy
  • Nginx
  • WireGuard
  • Security