WebUI unreachable from outside the LAN

Hello all, new user here!

So, everything works fine except I cannot access the WebUI from outside the local network.
BUT! I can access the rock-ons if i reverse-proxy them directly

Set-up:

  • My own domain (“domain.tld”)
  • Domain is linked to a VPS
  • VPS is running Caddy as reverse proxy(by various “subdomainX.domain.tld”, “subdomain-Y.domain.tld” etc) which routes traffic to my home network via Wireguard connections
  • VPS is also running a Wireguard server (and a PiHole w\ unbound but it does not seems to be relevant)
  • I manually added Wireguard to the Rockstor installation, to run as client
    • Do note I also have a raspberry on the same LAN, and, IP aside, the Wireguard configurations are identical and I can access the services reverse-proxie’d on it
  • this is full testing setup so firewall disabled on the router(yeah, yeah, I know it’s not safe)

So this Caddy configuration does not work: I cannot access any webUI outside the LAN\VPN, including using the external domain name.

homelab.domain.tld {
        reverse_proxy 10.98.237.8
        log {
                output file /var/log/caddy/homelab.domain.tld.log {
                        roll_size 100mb
                        roll_keep 5
                        roll_keep_for 720h
                }
        }
}

but this works, letting me access my Airsonic rock-on webUI

homelab.domain.tld {
        reverse_proxy 10.98.237.8:4040
        log {
                output file /var/log/caddy/homelab.domain.tld.log {
                        roll_size 100mb
                        roll_keep 5
                        roll_keep_for 720h
                }
        }
}

I’m guessing it’s some NGINX configuration, But i cannot find what it might be.

So… any idea?
(and any suggestion in general is welcome)

Have some specs & configuration files

# zypper info rockstor

Repository     : Rockstor-Testing                                                                                                                                                                                                          
Name           : rockstor                                                                                                                                                                                                                  
Version        : 5.1.0-0                                                                                                                                                                                                                   
Arch           : x86_64                                                                                                                                                                                                                    
Vendor         : YewTreeApps                                                                                                                                                                                                               
Installed Size : 6,6 MiB                                                                                                                                                                                                                   
Installed      : Yes                                                                                                                                                                                                                       
Status         : up-to-date                                                                                                                                                                                                                
Source package : rockstor-5.1.0-0.src                                                                                                                                                                                                      
Upstream URL   : https://rockstor.com/

# cat /opt/rockstor/poetry-install.txt

JANGO_SETTINGS_MODULE=settings
LANG=en_GB.UTF-8
SYSTEMD_EXEC_PID=1956
INVOCATION_ID=61c5629354ce4a1091e2ec49c7db083b
PWD=/opt/rockstor
PIPX_HOME=/opt/pipx
JOURNAL_STREAM=8:24815
PIPX_MAN_DIR=/usr/local/share/man
PIPX_BIN_DIR=/usr/local/bin
PASSWORD_STORE_DIR=/root/.password-store
SHLVL=1
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
_=/usr/bin/env
Poetry (version 1.7.1)

  • poetry-plugin-export (1.6.0) Poetry plugin to export the dependencies to various formats
      1 application plugin

      Dependencies
        - poetry (>=1.6.0,<2.0.0)
        - poetry-core (>=1.7.0,<2.0.0)

  • poetry-plugin-dotenv (0.6.11) poetry-plugin-dotenv - is the plugin that automatically loads environment variables from a dotenv file into the environment before poetry commands are run.
      1 application plugin

      Dependencies
        - poetry (>=1.5.1,<2.0.0)
Loading configuration file /opt/rockstor/poetry.toml
Creating virtualenv rockstor in /opt/rockstor/.venv
The --no-wheel and --wheel options are deprecated. They have no effect for Python > 3.8 as wheel is no longer bundled in virtualenv.
Using virtualenv: /opt/rockstor/.venv
Loading environment variables from '/opt/rockstor/.env'.
Installing dependencies from lock file

Finding the necessary packages for the current system

Package operations: 55 installs, 1 update, 0 removals

  • Installing pycparser (2.22)
  • Installing cffi (1.17.1)
  • Installing backports-tarfile (1.2.0)
  • Installing cryptography (45.0.3)
  • Installing h11 (0.16.0)
  • Installing jeepney (0.9.0)
  • Installing more-itertools (10.7.0)
  • Installing zipp (3.22.0)
  • Installing importlib-metadata (8.7.0)
  • Installing jaraco-classes (3.4.0)
  • Installing jaraco-context (6.0.1)
  • Installing jaraco-functools (4.1.0)
  • Installing secretstorage (3.3.3)
  • Installing wsproto (1.2.0)
  • Installing asgiref (3.8.1)
  • Installing certifi (2025.4.26)
  • Installing idna (3.10)
  • Installing keyring (25.6.0)
  • Installing charset-normalizer (3.4.2)
  • Installing sqlparse (0.5.3)
  • Installing simple-websocket (1.1.0)
  • Downgrading setuptools (82.0.0 -> 80.9.0)
  • Installing typing-extensions (4.13.2)
  • Installing urllib3 (2.4.0)
  • Installing bidict (0.23.1)
  • Installing django (4.2.21)
  • Installing greenlet (3.2.2)
  • Installing jwcrypto (1.5.6)
  • Installing keyring-pass (0.9.3)
  • Installing packaging (25.0)
  • Installing python-engineio (4.8.0)
  • Installing oauthlib (3.2.2)
  • Installing pytz (2025.2)
  • Installing requests (2.32.3)
  • Installing rpm (0.4.0)
  • Installing wheel (0.45.1)
  • Installing zope-event (5.0)
  • Installing zope-interface (7.2)
  • Installing dbus-python (1.3.2)
  • Installing distro (1.9.0)
  • Installing django-pipeline (4.0.0)
  • Installing djangorestframework (3.15.2)
  • Installing docutils (0.21.2)
  • Installing gevent (24.2.1)
  • Installing django-oauth-toolkit (2.4.0)
  • Installing gunicorn (23.0.0)
  • Installing huey (2.5.3)
  • Installing psutil (5.9.4)
  • Installing psycogreen (1.0)
The --no-wheel and --wheel options are deprecated. They have no effect for Python > 3.8 as wheel is no longer bundled in virtualenv.
  • Installing psycopg (3.2.9)
  • Installing python-socketio (5.9.0)
  • Installing pyzmq (26.4.0)
  • Installing six (1.16.0)
  • Installing supervisor (4.2.4)
  • Installing urlobject (2.1.1)
The --no-wheel and --wheel options are deprecated. They have no effect for Python > 3.8 as wheel is no longer bundled in virtualenv.
The --no-wheel and --wheel options are deprecated. They have no effect for Python > 3.8 as wheel is no longer bundled in virtualenv.
The --no-wheel and --wheel options are deprecated. They have no effect for Python > 3.8 as wheel is no longer bundled in virtualenv.
  • Installing zypper-changelog-lib (0.7.9)

Installing the current project: rockstor (5.1.0)
  - Building package rockstor in editable mode
  - Adding rockstor.pth to /opt/rockstor/.venv/lib/python3.11/site-packages for /opt/rockstor
  - Adding the backup-config script to /opt/rockstor/.venv/bin
  - Adding the bootstrap script to /opt/rockstor/.venv/bin
  - Adding the data-collector script to /opt/rockstor/.venv/bin
  - Adding the debug-mode script to /opt/rockstor/.venv/bin
  - Adding the delete-api-key script to /opt/rockstor/.venv/bin
  - Adding the delete-rockon script to /opt/rockstor/.venv/bin
  - Adding the flash-optimize script to /opt/rockstor/.venv/bin
  - Adding the initrock script to /opt/rockstor/.venv/bin
  - Adding the mnt-share script to /opt/rockstor/.venv/bin
  - Adding the ovpn-client-gen script to /opt/rockstor/.venv/bin
  - Adding the ovpn-client-print script to /opt/rockstor/.venv/bin
  - Adding the ovpn-initpki script to /opt/rockstor/.venv/bin
  - Adding the prep_db script to /opt/rockstor/.venv/bin
  - Adding the pwreset script to /opt/rockstor/.venv/bin
  - Adding the qgroup-clean script to /opt/rockstor/.venv/bin
  - Adding the qgroup-maxout-limit script to /opt/rockstor/.venv/bin
  - Adding the replicad script to /opt/rockstor/.venv/bin
  - Adding the send-replica script to /opt/rockstor/.venv/bin
  - Adding the st-pool-scrub script to /opt/rockstor/.venv/bin
  - Adding the st-snapshot script to /opt/rockstor/.venv/bin
  - Adding the st-system-power script to /opt/rockstor/.venv/bin
  - Adding the rockstor-5.1.0.dist-info directory to /opt/rockstor/.venv/lib/python3.11/site-packages

# cat /etc/wireguard/wg0.conf

[Interface]
PrivateKey = [redacted]
Address = 10.98.237.8/24,fd11:5ee:bad:c0de::a62:ed08/64
DNS = 10.98.237.1

[Peer]
PublicKey = [redacted]
PresharedKey = [redacted]
Endpoint = [redacted]:51820
AllowedIPs = 10.98.237.0/24, 2002:0a62:ed01::0/64
PersistentKeepalive = 25

# iptables -S

-P INPUT ACCEPT
-P FORWARD DROP
-P OUTPUT ACCEPT
-N DOCKER
-N DOCKER-BRIDGE
-N DOCKER-CT
-N DOCKER-FORWARD
-N DOCKER-ISOLATION-STAGE-1
-N DOCKER-ISOLATION-STAGE-2
-N DOCKER-USER
-A FORWARD -j DOCKER-USER
-A FORWARD -j DOCKER-FORWARD
-A DOCKER -d 172.17.0.4/32 ! -i docker0 -o docker0 -p tcp -m tcp --dport 4040 -j ACCEPT
-A DOCKER -d 172.17.0.3/32 ! -i docker0 -o docker0 -p udp -m udp --dport 6881 -j ACCEPT
-A DOCKER -d 172.17.0.3/32 ! -i docker0 -o docker0 -p tcp -m tcp --dport 6881 -j ACCEPT
-A DOCKER -d 172.17.0.3/32 ! -i docker0 -o docker0 -p tcp -m tcp --dport 5345 -j ACCEPT
-A DOCKER -d 172.17.0.2/32 ! -i docker0 -o docker0 -p udp -m udp --dport 7396 -j ACCEPT
-A DOCKER -d 172.17.0.2/32 ! -i docker0 -o docker0 -p tcp -m tcp --dport 7396 -j ACCEPT
-A DOCKER ! -i docker0 -o docker0 -j DROP
-A DOCKER-BRIDGE -o docker0 -j DOCKER
-A DOCKER-CT -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A DOCKER-FORWARD -j DOCKER-CT
-A DOCKER-FORWARD -j DOCKER-ISOLATION-STAGE-1
-A DOCKER-FORWARD -j DOCKER-BRIDGE
-A DOCKER-FORWARD -i docker0 -j ACCEPT
-A DOCKER-ISOLATION-STAGE-1 -i docker0 ! -o docker0 -j DOCKER-ISOLATION-STAGE-2
-A DOCKER-ISOLATION-STAGE-2 -o docker0 -j DROP

# ss --ipv4 --tcp --listening --numeric --processes

State              Recv-Q             Send-Q                         Local Address:Port                          Peer Address:Port            Process                                                                                      
LISTEN             0                  4096                                 0.0.0.0:5345                               0.0.0.0:*                users:(("docker-proxy",pid=5102,fd=7))                                                      
LISTEN             0                  50                                   0.0.0.0:139                                0.0.0.0:*                users:(("smbd",pid=9930,fd=32))                                                             
LISTEN             0                  4096                                 0.0.0.0:111                                0.0.0.0:*                users:(("rpcbind",pid=687,fd=4),("systemd",pid=1,fd=121))                                   
LISTEN             0                  128                                  0.0.0.0:22                                 0.0.0.0:*                users:(("sshd",pid=867,fd=3))                                                               
LISTEN             0                  50                                   0.0.0.0:445                                0.0.0.0:*                users:(("smbd",pid=9930,fd=31))                                                             
LISTEN             0                  4096                                 0.0.0.0:443                                0.0.0.0:*                users:(("nginx",pid=9601,fd=6),("nginx",pid=9600,fd=6),("nginx",pid=9599,fd=6))             
LISTEN             0                  2048                               127.0.0.1:8000                               0.0.0.0:*                users:(("gunicorn",pid=14859,fd=7),("gunicorn",pid=14854,fd=7))                             
LISTEN             0                  100                                127.0.0.1:25                                 0.0.0.0:*                users:(("master",pid=1300,fd=13))                                                           
LISTEN             0                  4096                               127.0.0.1:4200                               0.0.0.0:*                users:(("shellinaboxd",pid=20363,fd=4))                                                     
LISTEN             0                  4096                                 0.0.0.0:4040                               0.0.0.0:*                users:(("docker-proxy",pid=22544,fd=7))                                                     
LISTEN             0                  4096                                 0.0.0.0:7396                               0.0.0.0:*                users:(("docker-proxy",pid=31553,fd=7))                                                     
LISTEN             0                  4096                                 0.0.0.0:48517                              0.0.0.0:*                users:(("rpc.statd",pid=21208,fd=8))                                                        
LISTEN             0                  4096                                 0.0.0.0:6881                               0.0.0.0:*                users:(("docker-proxy",pid=5118,fd=7))                                                      
LISTEN             0                  244                                127.0.0.1:5432                               0.0.0.0:*                users:(("postgres",pid=877,fd=7))  

@sirtao, welcome.

Could it be, since the Rockstor WebUI is always using https that you need to explicitly call out the 443 port?

As in

`reverse_proxy 10.98.237.8:443`

I found some discussion here about proxying to an upstream https server, and how to deal with the self-signed certificate that Rockstor has … though I admit, I am no caddy expert, but maybe this helps you (essentially making the self-signed certificate known, though in the same breath the author mentions that tls_trusted_ca_certs is deprecated, so not sure how it needs to be handled instead then).

1 Like

In addition to @Hooverdan’s feedback, I wanted to briefly answer that part. Rockstor uses nginx for all its “communication” needs and we do setup nginx using systemd drop-ins. It is done here:

If you want to try adjusting this nginx config, you should be able to add your own drop-ins there as needed. Be careful, of course, that affecting the current rockstor drop-in is susceptible to break something in rockstor :wink:.

On a side note: how do you like Caddy? I’ve been curious about it for my personal use for years but never found the time to actually test or play with it.

2 Likes

Thank you for your answers.
@Hooverdan setting to 443 did not help.

I did end up changing the listening address on Gunicorn from 127.0.0.1:8000 to 0.0.0.0:8000 and have Caddy reverse-proxy to that port specifically.

Now it connects! And the certificate generated by Caddy is accepted!

…but every call to static contents(scripts, images, etc) is answered with a Zero-lenght payload.

And, obviously,everything works perfectly when called from inside the VPN\LAN(aside now the certificate not matching the internal LAN but that’s another matter)

@Flox I’m liking Caddy quite enough. I actully went with it instead of NGINX as reverse proxy because it’s much easier to setup for “simpler” uses in my opinion.
As I’m moving stuff to my home system, though, I might need to find a proxy for non-HTTP stuff like IRC and XMPP.

current configs:

/opt/rockstor/conf/gunicorn.conf.py

#  https://docs.gunicorn.org/en/stable/settings.html#config-file

# APP
#bind = ["127.0.0.1:8000"]
bind = ["0.0.0.0:8000"]

# WORKERS
workers = 1
worker_class = "gthread"
worker_connections = 100
threads = 2
timeout = 30
graceful_timeout = 30

# LOGS
accesslog = "./var/log/gunicorn.log"
# Default access_log_format = '%(h)s %(l)s %(u)s %(t)s "%(r)s" %(s)s %(b)s "%(f)s" "%(a)s"'
# Add milliseconds (#ms) to end of default access_log_format:
access_log_format = '%(h)s %(l)s %(u)s %(t)s "%(r)s" %(s)s %(b)s "%(f)s" "%(a)s" %(M)sms'
errorlog = "./var/log/gunicorn.log"
# loglevel = "debug"

Caddyfile(relevant part)


homelab.domain.tld {
        reverse_proxy / 10.98.237.8:8000
        log {
                format console
                level INFO
                output file /var/log/caddy/homelab.domain.tld.log {
                        roll_size 100mb
                        roll_keep 5
                        roll_keep_for 720h
                }
        }
}
1 Like