Engineering Field guide

SSL/TLS reverse proxy setup for game server web panels

Configure an Nginx reverse proxy with automated Let's Encrypt SSL certificates for game panels: localhost isolation, WebSocket proxying, and rate limits.

SSL/TLS reverse proxy setup for game server web panels

Modern dedicated game servers frequently feature embedded web interfaces and REST/WebSocket APIs for administrative tasks: Minecraft map renders (Dynmap, BlueMap), web-based dashboards, the Palworld REST API, and Rust WebRCON. By default, these services listen over unencrypted HTTP and plain WebSockets (ws://) on non-standard ports. Exposing them directly to the public internet leaves administrative credentials vulnerable to packet sniffing and triggers browser mixed-content rejections.

This operational guide details configuring an enterprise Nginx reverse proxy with automated Let's Encrypt certificates, isolating game web endpoints on loopback interfaces (127.0.0.1), and proxying long-lived WebSocket sessions.

Security risks of raw HTTP and unencrypted WebSockets#

When an administrator authenticates or issues RCON commands across unencrypted transport layers:

  1. Credential Interception (Sniffing): Logins, session bearer tokens, and administrative secrets traverse public networks in plaintext and can be intercepted by rogue intermediate hops.
  2. Mixed Content Rejections: When an administrative web interface is served over secure HTTPS, but an embedded console attempts connecting via ws://, modern browsers enforce strict CSP policies and terminate the session.
  3. Attack Surface Expansion: Multiple arbitrary public listening ports (8123, 8212, 28016) increase firewall complexity and complicate network auditing.

The industry solution is binding game services strictly to the host loopback adapter while exposing a single, hardened HTTPS ingress on port 443.

Isolating game web endpoints to localhost#

Before deploying Nginx, configure each game server daemon so that its HTTP and WebSocket sockets bind exclusively to 127.0.0.1 rather than wildcard 0.0.0.0.

For Minecraft Dynmap in plugins/dynmap/configuration.txt: webserver-bindaddress: 127.0.0.1webserver-port: 8123

For the Palworld REST API in PalWorldSettings.ini: RESTAPIBindAddress="127.0.0.1"RESTAPIPort=8212

Verify that all administrative sockets are locked to the loopback interface:

bash
sudo ss -tlnp | grep -E "8123|8212|28016"

The output must show 127.0.0.1:<port> for all bound endpoints.

Installing and configuring Nginx with WebSocket support#

Install the Nginx web server and Certbot packages:

bash
sudo apt-get update
sudo apt-get install -y nginx certbot python3-certbot-nginx

Create a dedicated virtual host configuration at /etc/nginx/sites-available/game_panels.conf:

bash
sudo nano /etc/nginx/sites-available/game_panels.conf

Populate the file with the following upstream definitions and WebSocket connection upgrade maps:

nginx
map $http_upgrade $connection_upgrade {
    default upgrade;
    '' close;
}

server {
    listen 80;
    server_name panel.example.com;

    location / {
        return 301 https://$host$request_uri;
    }
}

server {
    listen 443 ssl http2;
    server_name panel.example.com;

    # SSL certificates managed via certbot
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;

    # Minecraft Dynmap Web Map
    location /map/ {
        proxy_pass http://127.0.0.1:8123/;
        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 $scheme;
    }

    # Rust WebRCON with WebSocket upgrade
    location /rcon/ {
        proxy_pass http://127.0.0.1:28016/;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
        proxy_set_header Host $host;
        proxy_read_timeout 86400s;
        proxy_send_timeout 86400s;
    }
}

Enable the site configuration:

bash
sudo ln -sf /etc/nginx/sites-available/game_panels.conf /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

With an integrated server management platform, TLS termination, certificate management, and WebSocket routing are handled behind dedicated edge proxies without manual Nginx administration.

Obtaining and auto-renewing Let's Encrypt SSL certificates#

Issue a signed production certificate using Certbot:

bash
sudo certbot --nginx -d panel.example.com --non-interactive --agree-tos -m admin@example.com

Certbot automatically injects the certificate paths into your virtual host and enables a background renewal timer:

bash
sudo systemctl status certbot.timer --no-pager

Verify that the automatic certificate renewal hook operates cleanly:

bash
sudo certbot renew --dry-run

Securing administrative endpoints with rate limits and IP filters#

To shield game APIs from credential brute-forcing, enforce rate limiting and IP access lists:

nginx
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;

location /api/ {
    limit_req zone=api_limit burst=20 nodelay;
    
    # Authorized administrative IP:
    allow 198.51.100.50;
    deny all;

    proxy_pass http://127.0.0.1:8212/;
}

Reload Nginx to activate the firewalling directives:

bash
sudo nginx -t && sudo systemctl reload nginx

Administrative sessions now benefit from TLSv1.3 encryption, while raw game sockets remain unreachable from the public internet.

Sources#