I needed a way to access Deluge’s web UI remotely without opening another port to the world. The answer is the same as it always is: stick Nginx in front of it.

This took me longer than I’d like to admit, mostly because Deluge’s web UI has some quirks around base paths that aren’t obvious from the docs.

What we’re working with

  • Debian 12
  • Deluge 2.1.1 (the deluged daemon + deluge-web)
  • Nginx already handling SSL via Let’s Encrypt
  • Goal: https://torrent.yourdomain.com → Deluge web UI

Installing Deluge

If you haven’t already:

apt install deluged deluge-web

Enable and start the services:

systemctl enable --now deluged
systemctl enable --now deluge-web

By default deluge-web listens on 127.0.0.1:8112. Confirm it’s up:

ss -tlnp | grep 8112

The Nginx config

Here’s the block that actually works. The proxy_pass trailing slash and the sub_filter lines are the parts that tripped me up:

server {
    listen 443 ssl;
    server_name torrent.yourdomain.com;

    ssl_certificate     /etc/letsencrypt/live/torrent.yourdomain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/torrent.yourdomain.com/privkey.pem;

    location / {
        proxy_pass         http://127.0.0.1:8112/;
        proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header   Host $host;
        proxy_http_version 1.1;
        proxy_set_header   Upgrade $http_upgrade;
        proxy_set_header   Connection "upgrade";
    }
}

Note the trailing slash on proxy_pass — without it, Deluge’s static assets 404.

Locking it down with HTTP basic auth

Deluge has its own password, but adding a second layer at Nginx is trivial and stops bots from even reaching the login page:

apt install apache2-utils
htpasswd -c /etc/nginx/.htpasswd yourusername

Then add to the location block:

auth_basic           "Deluge";
auth_basic_user_file /etc/nginx/.htpasswd;

Reload and test

nginx -t && systemctl reload nginx

Hit the URL, enter your basic-auth credentials, then the Deluge password (default: deluge). Change that immediately.

What didn’t work

I first tried running Deluge under a subdirectory (/deluge/) instead of a subdomain. Don’t. Deluge’s web UI hardcodes some absolute paths internally and it breaks in non-obvious ways — assets load, but WebSocket connections fail silently and the UI appears stuck on “connecting”.

Subdomain is the path of least resistance here.