Why a dashboard needs HTTPS
Dashboards sign people in with Discord (OAuth2): your page sends the visitor to Discord, Discord asks them to allow it, then sends them back to your redirect URI with a one-time code, which your server trades for the person's access token. Over plain http://, that code and the session cookie that follows cross the network unencrypted, and anyone on the same Wi-Fi can lift them and be that person on your dashboard. Browsers mark the page Not secure, and a cookie marked Secure, as a session cookie should be, is never sent at all.
So http://203.0.113.10:25570/callback, the address a bot server gives you, is fine for trying it out and wrong for real users. You want a domain with a certificate.
1. Run the web server in the bot's process
The dashboard and the bot can be one program, so the page can read the bot's state directly. In discord.py, start an aiohttp server from setup_hook; in discord.js, start Express next to the client. Listen on 0.0.0.0 and the port in SERVER_PORT:
# discord.py
import os
from aiohttp import web
async def home(request):
return web.Response(text="Dashboard")
async def setup_hook():
app = web.Application()
app.router.add_get("/", home)
runner = web.AppRunner(app)
await runner.setup()
await web.TCPSite(runner, "0.0.0.0", int(os.environ["SERVER_PORT"])).start()
bot.setup_hook = setup_hookA bigger dashboard can be its own program on a second port, or its own server; the steps below are the same.
2. Put it on your domain
On SnowServers, open the bot server's Website tab, add a name such as dash.yourdomain.com and the port, and add the two DNS records it shows: a CNAME that points the name here, and a TXT record that proves it is yours. The certificate follows by itself and renews by itself. Elsewhere, you would put a reverse proxy such as nginx or Caddy in front of the port and get a certificate from Let's Encrypt.
3. Register the redirect URI
In the Developer Portal, open your application, then OAuth2, and add https://dash.yourdomain.com/callback under Redirects. It must match exactly, path included, or Discord refuses with Invalid OAuth2 redirect_uri.
Ask for as little as you need: the identify and guilds scopes are enough to know who someone is and which servers they share with your bot. To decide who may change a server's settings, check the permissions field on the guilds you get back for Manage Server, rather than trusting anything the browser sends.
4. Trust the proxy
HTTPS ends at the proxy in front of your app, so your code sees plain HTTP. The proxy says what really happened in X-Forwarded-Proto and gives the visitor's address in X-Real-IP. Tell your framework to believe exactly one proxy: app.set("trust proxy", 1) in Express, ProxyFix in Flask, or read the headers yourself in aiohttp. Then generated links say https:// and Secure cookies are sent.
5. Keep the secrets secret
- The client secret from the OAuth2 page, the bot token and the session secret go in environment variables or a
.envfile, never in the code or the repository. - Check the OAuth2
statevalue on the way back, so nobody can log a visitor into someone else's account. - Store Discord's access token on the server side of the session, not in a cookie the browser can read.
Hosting it on SnowServers
Every Discord bot plan has the Website tab, so the bot and its dashboard can share one server and one domain. If the dashboard grows into its own app, a website plan gives it a server of its own. The web server docs show the bot side in more detail.