3x-ui3x-ui

Reverse Proxy

Put the 3x-ui panel and subscription behind Nginx or Caddy with Let's Encrypt TLS.

A reverse proxy lets you serve the panel and subscription on a clean domain with automatic HTTPS, and hide the real ports behind ports 80/443. Prefer to let the panel terminate TLS directly? Get a certificate with the x-ui SSL menu instead.

Generate a config

Reverse-proxy config generator

Generate an Nginx or Caddy reverse-proxy config (with WebSocket support) and a matching certificate command.

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

    ssl_certificate     /etc/letsencrypt/live/panel.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/panel.example.com/privkey.pem;

    location /panel/ {
        proxy_pass http://127.0.0.1:2053;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        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;
        proxy_read_timeout 3600s;
        proxy_send_timeout 3600s;
    }
}
Obtain a certificate
certbot certonly --nginx -d panel.example.com

The panel uses WebSockets for live updates, so the proxy must pass the Upgrade/Connection headers (the Nginx output above already does). Caddy handles WebSocket upgrades automatically.

Nginx + certificate

With Nginx, obtain a certificate with certbot (or acme.sh) and reference it in the server block:

certbot
certbot certonly --nginx -d panel.example.com

Reload Nginx after installing the certificate, and set up automatic renewal (certbot renew runs on a timer by default).

Caddy

Caddy obtains and renews certificates for you — point a Caddyfile at the panel and it just works:

Caddyfile
panel.example.com {
    reverse_proxy 127.0.0.1:2053
}

Tips

  • Keep the panel's web base path even behind a proxy; defense in depth.
  • If you terminate TLS at the proxy, you may want XUI_SKIP_HSTS=true on the panel — see the environment variables reference.
  • Proxy the subscription server too, so its contents are served over HTTPS.

On this page