Dashboard Setup on Linux
A step-by-step guide to run the optional web dashboard on a Linux server (Apache + systemd) and reach it over HTTPS.
Getting this working means two independent things: a reverse proxy (Apache) that terminates HTTPS and forwards to the dashboard, and a service manager (systemd) that keeps the Node process alive. The reverse proxy does not run the bot, and systemd does not handle HTTPS. You need both.
Prerequisites
- Node.js 22+ and Git installed.
- The bot already set up and running, with a valid
.env(TOKEN,CLIENT_ID,GUILD_ID). - A subdomain for the dashboard, e.g.
tickets.example.com, with a DNS A record pointing to this server. - Apache with the
proxy,proxy_http,headers,rewriteandsslmodules, andcertbotfor the certificate.
Firewall
The dashboard binds to 127.0.0.1 only, so its port (default 3010) is not
reachable from outside and needs no firewall rule. Leave it closed. Only
Apache must be reachable from the internet:
| Direction | Rule | Why |
|---|---|---|
| Inbound | TCP 80 | Let's Encrypt certificate issuance/renewal (ACME) and HTTP → HTTPS redirect |
| Inbound | TCP 443 | HTTPS, the actual dashboard traffic |
| Outbound | TCP 443 | Discord, Let's Encrypt, updates (usually already allowed) |
With UFW:
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
Do not open port 3010. No UDP is required.
1. Run the guided setup
In the bot folder:
npm run dashboard:setup
- Choose b (public, behind a reverse proxy with HTTPS).
- Port: keep
3010(or pick a free one and remember it). - Enter your domain, e.g.
tickets.example.com. - Add the shown Redirect URI in the Discord Developer Portal under OAuth2 → Redirects (it will be
https://tickets.example.com/auth/callback). - Paste your Client Secret (OAuth2 → Client Secret) when asked.
This writes the correct .env. The dashboard binds to 127.0.0.1, so the port is
never exposed directly. The wizard also prints the Apache snippet below.
2. Reverse proxy (Apache)
Save as /etc/apache2/sites-available/ticketbot-dashboard.conf (replace the
domain and, if you changed it, the port):
<VirtualHost *:80>
ServerName tickets.example.com
RewriteEngine On
RewriteRule ^/?(.*) https://tickets.example.com/$1 [R=301,L]
</VirtualHost>
<VirtualHost *:443>
ServerName tickets.example.com
SSLEngine on
# certbot fills in the certificate paths for you
ProxyPreserveHost On
ProxyPass / http://127.0.0.1:3010/
ProxyPassReverse / http://127.0.0.1:3010/
# The dashboard derives the client IP from the RIGHTMOST X-Forwarded-For
# entry. Apache appends the real client here.
RequestHeader set X-Forwarded-Proto "https"
</VirtualHost>
Then enable everything and issue the certificate:
sudo a2enmod proxy proxy_http headers rewrite ssl
sudo a2ensite ticketbot-dashboard
sudo certbot --apache -d tickets.example.com
sudo systemctl reload apache2
certbot fills in the certificate paths and sets up automatic renewal.
3. Keep the bot running as a service (systemd)
Use dashboard.js (not index.js) as the entry point so it also supervises the
bot. Create /etc/systemd/system/ticketbot.service:
This replaces the plain-bot service from Installation — dashboard.js runs the bot itself, so you never run both. If you already set up a ticketbot.service pointing at index.js, this simply overwrites it; stop it first with sudo systemctl stop ticketbot.
[Unit]
Description=Discord Ticket Bot (with dashboard)
After=network.target
[Service]
Type=simple
User=discord
WorkingDirectory=/opt/discord_ticketbot
ExecStart=/usr/bin/node /opt/discord_ticketbot/dashboard.js
Restart=on-failure
RestartSec=10
[Install]
WantedBy=multi-user.target
Then:
sudo systemctl daemon-reload
sudo systemctl enable --now ticketbot
sudo journalctl -u ticketbot -f --output=cat
For a first test, just run npm run dashboard in a terminal to confirm
everything works, then stop it and start the service. Do not run both at once —
they would fight over the port.
4. Open it
Go to https://tickets.example.com and log in with Discord. As the server owner
you are automatically admin. Grant everyone else access under Permissions.
Troubleshooting
- Login redirects back with an error — the redirect URI in the Discord portal must match
DASHBOARD_PUBLIC_URL+/auth/callbackexactly, includinghttps. - 502 / 503 from Apache — the bot process is not running. Check
systemctl status ticketbotand that it listens on the configured port. - The dashboard refuses to start, saying the configuration is not safe — you bound it to a public interface without HTTPS. Keep
DASHBOARD_HOST=127.0.0.1and reach it through Apache.