-
Notifications
You must be signed in to change notification settings - Fork 167
[WIP] Serving the admin panel online
Warning
This guide is still a work in progress, it hasn't been tested yet to be recommended. Please report issues to the Discord server if you decide to follow this guide anyway.
If you want to leverage your experience and be able to access your admin panel from anywhere and share it with your staff, you can host it on a server and expose it to the internet! It's not an easy process but I will try to guide you there.
Before doing this, you must have the following:
It is extremely important that you do not host Ballsdex or the website on your own personal network. This would require you to open your firewall and expose your entire family to tons of dangers. DO NOT DO THIS and look for a provider, there are even free options.
I recommend checking this page for VPS and server recommendations.
The reason Linux is a requirement in this tutorial is simply because I don't know how this works on Windows or macOS, I cannot teach that. Besides, it would be weird to pay an additional sum for a paid OS when Linux is the recommended OS.
You must have a domain name to hide your IP. This is pretty cheap honestly, I recommend you to use Namecheap for cheap domain names, it's what I use myself.
Once you got this, you should also use Cloudflare as a DNS and proxy provider, it's free, faster than the default DNS, and comes with many good features. Your server's IP will be hidden thanks to that.
Caution
It is very important that you follow these requirements, they have security implications.
Failing to follow these will result in being exposed to a lot of risks and vulnerabilities if you don't exactly know what you're doing and how it works.
On Cloudflare, create a new configuration for your domain example.com
. It will ask you to replace nameservers with its own on Namecheap's side. Do this and wait for the changes to take effect (can take a while).
Once Cloudflare is ready, go to the DNS page, create an A
record and redirect it to your server's IP. If you don't know your server's IP, you can run curl http://ipinfo.io/ip
. Be sure to tick "Proxy" on.
We are going to use the nginx
program to handle the routing part, as well as certbot
for getting HTTPS working. We will also need pwgen
to generate our secret key. On Debian/Ubuntu, run this:
sudo apt update
sudo apt install nginx certbot python3-certbot-nginx pwgen
If you are using a different distribution, look up your package manager to see how to install those dependencies.
Before opening yourself to the internet, ensure that your OS is configured to only allow what we need.
Distributions have different firewall programs, but the most common one is ufw
(preinstalled on Ubuntu). Let's configure it together.
- Disallow all incoming connections:
sudo ufw default deny incoming
- Allow all outgoing connections:
sudo ufw default allow outgoing
- Allow SSH connections:
sudo ufw allow OpenSSH
- Allow HTTPS connections:
sudo ufw allow 'Nginx Full'
- Disallow HTTP connections:
sudo ufw delete allow 'Nginx HTTP'
- Enable ufw:
sudo ufw enable
If you do not have ufw
on your system, look up what program is recommended for your distribution and allow ports 22 and 443.
Let's create a configuration file for Ballsdex. Assuming your domain name is example.com
, run:
sudo nano /etc/nginx/sites-available/example.com
Assuming your Ballsdex instance is located at /home/user/Ballsdex-DiscordBot
, write the following contents into the file:
server {
listen 80;
listen [::]:80;
client_max_body_size 100m;
server_name example.com; # Change this
location / {
proxy_set_header Host $http_host;
proxy_pass http://localhost:8000; # if you have a different port number, change here
}
# django doesn't serve static files with DEBUG=False
location ~ ^/(static|media)/ {
root /home/user/Ballsdex-DiscordBot/admin_panel; # change the path here
}
}
Exit and save with Ctrl+X, yes
and enter. Then run sudo nginx -s reload
to instruct nginx to load the new configuration.
Let's run the following command to generate us certificates
sudo certbot --nginx -d example.com
Certbot will ask if you want to redirect HTTP to HTTPS, which I recommend to enable (2).
We're slowly getting there! Now we just need to configure the last few bits on Ballsdex's side.
In production, we need different settings for Django. An example production.py
file is provided, which we will copy and fill. Open a shell and type the following commands:
cd admin_panel/admin_panel/settings
cp production.example.py production.py
- Generate a random string of characters with
pwgen -n 64 1
and copy that -
nano production.py
(or your preferred editor) - Find the line that says
SECRET_KEY = None
and replace it withSECRET_KEY = "paste your random string here"
- Look down for the
ALLOWED_HOSTS
section and replacelocalhost
by your domain - Exit and save with Ctrl+x,
yes
and enter.
This production.py
file should remain secret and never be pushed. It will be ignored by git.
Warning
Keep your SECRET_KEY
secret. Running Django with a known SECRET_KEY
defeats many of Django’s security protections, and can lead to privilege escalation and remote code execution vulnerabilities.
https://docs.djangoproject.com/en/5.1/ref/settings/#secret-key
Tip
Feel free to edit the production.py
file to extend the configuration and add more settings, such as extensions or custom admin themes.
Future updates will change settings in base.py
and automatically apply to your configuration.
To make use of that production.py
file, you need to tell Django via the DJANGO_SETTINGS_MODULE
environment variable.
You will find in docker-compose.yml
there is already a commented environment variable, simply uncomment that line. If you're not using docker compose, simply run export DJANGO_SETTINGS_MODULE=admin_panel.settings.production
before running the server.
At this point, restart your admin panel and you should now be able to access it at your domain name, in https, from anywhere!
Now that your admin panel is online, there are some additional settings that may interest you.
If you followed the first guide, you may have configured Discord OAuth2 to login with Discord and not create accounts. This now applies to your staff too! Here's how the Discord pipeline works:
- Does the user have Two-factor authentication enabled?
- If not, login is immediately denied.
- Is the user ID in the
co-owners
section ofconfig.yml
?- If yes, the user is granted the superuser status.
- Is the user ID the owner of the Discord application?
- If yes, the user is granted the superuser status.
- Is
team-members-are-owners
set totrue
inconfig.yml
, and is the user ID part of the Discord developer team that owns the application (regardless of its role)?- If yes, the user is granted the superuser status.
- Does the user possess one of the roles defined in
root-role-ids
inconfig.yml
?- If yes, the user is granted the staff status and is assigned the Admin group (detailed below).
- Does the user possess one of the roles defined in
admin-role-ids
inconfig.yml
?- If yes, the user is granted the staff status and is assigned the Staff group (detailed below).
If you have configured a Discord webhook, you will be notified for each new user that registers successfully on your admin panel. It is highly recommended to have this setup!
Caution
Here's the very important part, staff status is not automatically unassigned if you demote a user in Discord!!
When demoting someone (admin/root role removed, removed from the Developer team or the co-owners
list), you must also go to the admin panel, "Users", edit the user (if they registered on the panel) and untick the "Is Active" box.
You do not need to untick "Is staff", "Is superuser" or remove permissions groups. Unticking "Is Active" completely disables logging in and invalidates all sessions. If you want to re-enable the user, simply tick this box back.
It is important that you do not delete the user, or you will be losing all audit logs!
If you prefer creating admin accounts yourself and not automatically give access to all your staff, you can disable the "Login with Discord" button by adding the following lines to your production.py
file:
AUTHENTICATION_BACKENDS = [
# "social_core.backends.discord.DiscordOAuth2",
"django.contrib.auth.backends.ModelBackend",
]
Simply uncomment the line if you want to re-enable this.
Whether you have Discord OAuth2 or not, you can always choose to create manual admin accounts with a login and a password.
For that, open the admin panel and click the "+ Add" button next to "Users". Choose a login and a password. Once created, you can then edit the user's permissions.
It is recommended that you ask users to reset their password as soon as they login for the first time. They can do so by clicking the button on the top right of the admin panel.
Important
If you need to delete a user, do not actually delete it as you will be losing all audit logs! Instead, untick the "Is active" checkbox, that will prevent them from logging in and invalidate all existing sessions.
To re-enable access, simply tick that box again. The previous permissions will apply.
If you need to create a new superuser account without accessing the admin panel (for instance, the first admin account), you can use the following command and follow the prompts.
- With docker:
docker compose exec admin-panel python3 manage.py createsuperuser
- Without docker:
cd admin_panel && poetry run python3 manage.py createsuperuser
If you want to exclusively rely on Discord OAuth2 for authentication, you can disable password-based accounts by adding the following lines to your production.py
file:
AUTHENTICATION_BACKENDS = [
"social_core.backends.discord.DiscordOAuth2",
# "django.contrib.auth.backends.ModelBackend",
]
Simply uncomment the line if you want to re-enable this.
Django has an extensive permission system described here.
Put simply, each model (Ball, BallInstance, Regime, Player, ...) has 4 permissions by default: view, change, add, delete. Users with the "superuser" status bypasses all permissions and has access to everything.
You can assign permissions to individual users by editing their user object, but you can also use permission groups.
Under the "Authorization & Authentication" section, you will find a "Group" section, allowing you to create named groups with a set of permissions.
If you have staff members logging in, you will get two groups created automatically, with the corresponding permissions assigned.
Click to unroll the default groups and permissions
Permission | Staff | Admin | |
---|---|---|---|
Ball | View | ❌ | ✅ |
Change | ❌ | ✅ | |
Add | ❌ | ✅ | |
Delete | ❌ | ✅ | |
Regime | View | ❌ | ✅ |
Change | ❌ | ✅ | |
Add | ❌ | ✅ | |
Delete | ❌ | ✅ | |
Economy | View | ❌ | ✅ |
Change | ❌ | ✅ | |
Add | ❌ | ✅ | |
Delete | ❌ | ✅ | |
Special | View | ❌ | ✅ |
Change | ❌ | ✅ | |
Add | ❌ | ✅ | |
Delete | ❌ | ✅ | |
BallInstance | View | ✅ | ✅ |
Change | ❌ | ✅ | |
Add | ❌ | ✅ | |
Delete | ❌ | ✅ | |
BlacklistedID | View | ✅ | ✅ |
Change | ✅ | ✅ | |
Add | ✅ | ✅ | |
Delete | ✅ | ✅ | |
BlacklistedGuild | View | ✅ | ✅ |
Change | ✅ | ✅ | |
Add | ✅ | ✅ | |
Delete | ✅ | ✅ | |
BlacklistHistory | View | ✅ | ✅ |
Change | ❌ | ❌ | |
Add | ❌ | ❌ | |
Delete | ❌ | ❌ | |
Block | View | ✅ | ✅ |
Change | ✅ | ✅ | |
Add | ✅ | ✅ | |
Delete | ✅ | ✅ | |
Friendship | View | ✅ | ✅ |
Change | ✅ | ✅ | |
Add | ✅ | ✅ | |
Delete | ✅ | ✅ | |
GuildConfig | View | ✅ | ✅ |
Change | ✅ | ✅ | |
Add | ❌ | ✅ | |
Delete | ❌ | ✅ | |
Player | View | ✅ | ✅ |
Change | ✅ | ✅ | |
Add | ❌ | ✅ | |
Delete | ❌ | ✅ | |
Trade | View | ✅ | ✅ |
Change | ❌ | ❌ | |
Add | ❌ | ❌ | |
Delete | ❌ | ❌ | |
TradeObject | View | ✅ | ✅ |
Change | ❌ | ❌ | |
Add | ❌ | ❌ | |
Delete | ❌ | ❌ |
Tip
You are free to edit those permissions after they were created.
Support my work on Patreon and get exclusive rewards!
For $7.50/month, I will be hosting your custom bot on my server, with immediate updates, secure and shared admin panel, and stats on https://grafana.laggron.red !