This guide covers deploying dbviewer as a persistent systemd service and exposing it publicly via a Cloudflare Tunnel with a custom domain.
Browser → https://db-viewer.vietml.com
↓
Cloudflare Tunnel (cloudflared)
↓
localhost:9876
↓
dbviewer (systemd service)
- dbviewer installed via
install.sh(see DEV_SETUP.md) sudoaccess on the server- A Cloudflare account with your domain added
sudo nano /etc/systemd/system/dbviewer.servicePaste the following content — replace youruser with your actual username:
[Unit]
Description=DB Viewer
After=network.target
[Service]
Type=simple
User=youruser
ExecStart=/home/youruser/.dbviewer/bin/dbviewer --port 9876
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.targetSave and exit: Ctrl+O → Enter → Ctrl+X
# Reload systemd to pick up the new service file
sudo systemctl daemon-reload
# Enable the service to start automatically on boot
sudo systemctl enable dbviewer
# Start the service now
sudo systemctl start dbviewersudo systemctl status dbviewerExpected output:
● dbviewer.service - DB Viewer
Loaded: loaded (/etc/systemd/system/dbviewer.service; enabled)
Active: active (running) since ...
Main PID: 12345 (dbviewer)
Verify it is listening on the correct port:
ss -tlnp | grep 9876Expected output:
LISTEN 0 128 0.0.0.0:9876 0.0.0.0:* users:(("python",pid=12345,...))
Do a quick local test:
curl -s http://localhost:9876/ | head -5# View live logs
journalctl -u dbviewer -f
# View last 50 log lines
journalctl -u dbviewer -n 50
# Restart after config changes
sudo systemctl restart dbviewer
# Stop the service
sudo systemctl stop dbviewer
# Disable autostart on boot
sudo systemctl disable dbviewerCheck if it is already installed:
cloudflared --versionIf not installed, run the following for Debian/Ubuntu:
curl -L https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb \
-o cloudflared.deb
sudo dpkg -i cloudflared.deb
rm cloudflared.deb
# Confirm installation
cloudflared --versioncloudflared tunnel loginThis opens a browser window. Select your domain to grant access. A credentials file will be saved to ~/.cloudflared/cert.pem.
cloudflared tunnel create dbviewerThe output will include a Tunnel ID — save it, you will need it in the next step:
Created tunnel dbviewer with id xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
mkdir -p ~/.cloudflared
nano ~/.cloudflared/config.ymlPaste the following — replace <TUNNEL_ID> with the ID from the previous step, and adjust the hostname and username:
tunnel: <TUNNEL_ID>
credentials-file: /home/youruser/.cloudflared/<TUNNEL_ID>.json
ingress:
- hostname: db-viewer.yourdomain.com
service: http://localhost:9876
- service: http_status:404Save and exit: Ctrl+O → Enter → Ctrl+X
cloudflared tunnel route dns dbviewer db-viewer.yourdomain.comThis automatically creates a CNAME record in Cloudflare DNS pointing db-viewer.yourdomain.com to your tunnel.
Verify the record was created by logging into the Cloudflare dashboard → DNS → check for a CNAME entry for db-viewer.
# Install cloudflared as a system service
sudo cloudflared service install
# Enable autostart on boot
sudo systemctl enable cloudflared
# Start the service now
sudo systemctl start cloudflared
# Verify it is running
sudo systemctl status cloudflaredExpected output:
● cloudflared.service - cloudflared
Active: active (running) since ...
Run all checks in sequence:
# 1. Both services are running
sudo systemctl status dbviewer cloudflared
# 2. dbviewer is listening on port 9876
ss -tlnp | grep 9876
# 3. Local connectivity
curl -s http://localhost:9876/ | head -3
# 4. Public URL (allow up to 30s for DNS to propagate after first setup)
curl -s https://db-viewer.yourdomain.com/ | head -3Then open https://db-viewer.yourdomain.com in a browser — the login dialog should appear.
Log in with the default credentials:
Username: admin
Password: admin123
Since the app is publicly accessible, change the default password immediately:
~/.dbviewer/bin/dbviewer --change-passwordFollow the interactive prompts. Then restart the service to apply:
sudo systemctl restart dbviewerWhen exposing dbviewer to the public internet, keep these points in mind:
- Change the default password — this is critical. Use a strong password.
- Restrict database permissions — the database user configured in
connections.jsonshould have only the permissions needed. Consider using read-only users for production databases. - Review connection configs — ensure
connections.jsondoes not contain credentials for databases you don't want exposed. - Use Cloudflare Access (optional) — for additional security, set up a Cloudflare Access policy that requires authentication before reaching the tunnel.
- Monitor logs — check
journalctl -u dbviewer -fperiodically for unexpected access patterns. - Keep updated — run
dbviewer --updateregularly to get security fixes.
| Symptom | Likely cause | Fix |
|---|---|---|
systemctl status dbviewer shows failed |
Wrong ExecStart path or permission issue |
Check path with which dbviewer or ls ~/.dbviewer/bin/; verify User= is correct |
Port 9876 not in ss -tlnp output |
Service not started or crashed | Run journalctl -u dbviewer -n 50 to see the error |
curl localhost:9876 works but public URL returns 502 |
cloudflared not running or wrong port in config | Check sudo systemctl status cloudflared and verify port in ~/.cloudflared/config.yml |
| Public URL returns a Cloudflare 1033 error | Tunnel is down | Run sudo systemctl restart cloudflared |
| DNS not resolving yet | DNS propagation delay | Wait 1–2 minutes after first setup; check with dig db-viewer.yourdomain.com |
cloudflared service install fails |
Missing sudo or credentials not found |
Ensure you ran cloudflared tunnel login first and ~/.cloudflared/cert.pem exists |
| Database connections fail after reboot | Database service not started yet | Ensure your database starts before dbviewer: add After=mysql.service (or equivalent) to the service file |