The console listens on 127.0.0.1:8092 — this host and nothing else. That is deliberate: an admin interface hung directly on the public internet becomes a door somebody can take their time with.
So opening it from another machine means choosing a route first. Neither route needs port 8092 opened in your firewall.
| SSH tunnel | Reverse proxy | |
|---|---|---|
| Configuration needed | None at all | Yes, plus a service restart |
| Who can reach it | You, and only with SSH access | Anyone who can reach that URL |
| What you need | An SSH account | A domain, a certificate, Apache or nginx |
| Suits | Occasional checks, one person | Several people, day to day, from a phone |
| Cost of getting it wrong | It does not connect | Your admin interface is public |
⭐ If you are unsure, take the tunnel. It makes you prove you can get into the host every single time, so getting it wrong means "cannot connect", not "somebody else connected".
This changes nothing on the host. It opens one more channel inside your SSH session: you connect to 127.0.0.1:8092 on your own machine, the traffic travels through SSH and arrives at the host's own 127.0.0.1 — so as far as the console is concerned, this is a local connection.
ssh -L 8092:127.0.0.1:8092 you@your-host
Leave that window open, then in a browser:
http://127.0.0.1:8092
Close the window and the tunnel is gone. That is exactly what makes it safe: nothing was left behind.
Change the left-hand number only. The right-hand side is the port on the host:
ssh -L 18092:127.0.0.1:8092 you@your-host
Then open http://127.0.0.1:18092.
Before connecting, go to Connection → SSH → Tunnels:
8092127.0.0.1:8092Without the Add click nothing is applied. It is the step most people miss.
listen_addr = 0.0.0.0:8092, because Package Center's Open button has to be able to reach it. In other words the console on DSM is already open to your whole local network. What you usually want on DSM is not to open it but to narrow it: choose "This machine only" under Console access on the console's settings page, or run svrguard console-listen lan on the host to allow private networks only (every connection from the internet is refused; the settings page prints the full command for that host). After "This machine only", only a tunnel or a reverse proxy gets in — and the Open button stops working.svrguard service status on the host.listen_addr in the [web] section. If it was changed to one interface's address rather than 127.0.0.1, the right-hand side of -L has to match it.http://, not https://. SSH already encrypted the tunnel; the console end has no certificate.Where the configuration file lives, how to edit it and how to restart afterwards are on the settings page.
For several people using it day to day, or to read it on a phone, put the console behind your own Apache or nginx and let that handle HTTPS and access control.
On the console side there is one thing to set — and possibly nothing at all:
[web] listen_addr = 127.0.0.1:8092 ; stay local, so the proxy is the only way in base_path = /agent ; only when mounting under a sub-path
On its own subdomain (https://guard.example.com/), leave base_path out. Set it only when sharing a domain with something else, under https://example.com/agent.
⚠️ Restart the service afterwards. The configuration file is read once, at start-up.
<VirtualHost *:443>
ServerName guard.example.com
# certificate directives omitted
# Worth keeping — see "How the source address is decided" below
RequestHeader unset X-Forwarded-For
ProxyPreserveHost On
ProxyPass / http://127.0.0.1:8092/
ProxyPassReverse / http://127.0.0.1:8092/
</VirtualHost>
Under a sub-path (with base_path = /agent in the file):
ProxyPass /agent http://127.0.0.1:8092/agent ProxyPassReverse /agent http://127.0.0.1:8092/agent
server {
listen 443 ssl;
server_name guard.example.com;
# certificate directives omitted
location / {
proxy_pass http://127.0.0.1:8092;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
# ⛔ $remote_addr, NOT $proxy_add_x_forwarded_for
proxy_set_header X-Forwarded-For $remote_addr;
}
}
The console has to be able to say who signed in, and its sign-in lockout counts per source address: ten failures from one address within fifteen minutes and it locks. So where a request came from cannot be something the caller gets to declare.
It decides in two steps:
127.0.0.1:8092 as in both configurations above ⇒ X-Forwarded-For is believed, and only its last element. Apache and nginx both append the peer they actually saw, so the last element is the real one; anything an outsider put in stays in front of it and is ignored.X-Forwarded-For is not read at all and the connecting address is used.One line in each configuration above is worth keeping: it leaves the header clean and makes the result predictable when more than one proxy is involved.
RequestHeader unset X-Forwarded-For. Clear what came from outside; mod_proxy then fills in the peer it actually saw.proxy_set_header X-Forwarded-For $remote_addr;. ⚠️ The $proxy_add_x_forwarded_for copied all over the internet means "keep what arrived and append the real source" — still correct here, but it leaves a stranger's text in the header for no reason.Secure flag follows X-Forwarded-Proto on its own, so with that header set there is nothing to do. To force it, set [web] cookie_secure = true. ⚠️ Do not set true before HTTPS is actually in place — you will not be able to sign in, because the browser will never send the cookie back.On the host:
ss -ltnp | grep 8092
Read the address on the left:
127.0.0.1:8092 — this host only. That is what you want.0.0.0.0:8092 or *:8092 — anyone whose network reaches this host can connect. That is the DSM default; on any other platform it means somebody changed listen_addr.⭐ Reading the configuration file is not enough. The file says what it will listen on next time it starts; ss says what it is listening on now. Edit without restarting and the two disagree.
Hosts with no browser can be paired from the command line. The steps are on the Get Started page.