358 lines
12 KiB
Markdown
358 lines
12 KiB
Markdown
# Drivers Hub: Backend Docker Deployment
|
|
|
|
```text
|
|
____ _ __ __ __
|
|
/ __ \_____(_) _____ __________ / / / /_ __/ /_
|
|
/ / / / ___/ / | / / _ \/ ___/ ___/ / /_/ / / / / __ \
|
|
/ /_/ / / / /| |/ / __/ / (__ ) / __ / /_/ / /_/ /
|
|
/_____/_/ /_/ |___/\___/_/ /____/ /_/ /_/\__,_/_.___/
|
|
```
|
|
|
|
Docker deployment for [Drivers Hub: Backend](https://github.com/CharlesWithC/HubBackend).
|
|
The deployment includes MariaDB, Valkey, and the banner generator.
|
|
Use it with the
|
|
[Drivers Hub: Frontend Docker Deployment](https://gitea.kosmos.ac/kosmos/HubFrontendDocker).
|
|
|
|
## Tested upstream version
|
|
|
|
This deployment is tested with Drivers Hub: Backend
|
|
[`v2.12.1`](https://github.com/CharlesWithC/HubBackend/releases/tag/v2.12.1).
|
|
At the time of this test, the release tag and upstream `main` point to commit
|
|
`a460eed`.
|
|
|
|
The clone command below gets the current upstream default branch. A newer
|
|
upstream revision can be incompatible with this deployment. If a build or
|
|
runtime error occurs after an upstream update, compare the checked-out revision
|
|
with the tested version above.
|
|
|
|
## Configure the deployment
|
|
|
|
Get the backend source code. Then, create the deployment configuration and the
|
|
application configuration:
|
|
|
|
```bash
|
|
git clone https://github.com/CharlesWithC/HubBackend.git upstream/HubBackend
|
|
cp .env.example .env
|
|
cp upstream/HubBackend/config_sample.json config/config.json
|
|
```
|
|
|
|
Set secure MariaDB passwords in `.env`. Then, set at least these values in
|
|
`config/config.json`:
|
|
|
|
```json
|
|
{
|
|
"abbr": "vtc",
|
|
"name": "Drivers Hub",
|
|
"domain": "hub.example.com",
|
|
"prefix": "/api",
|
|
"server_host": "0.0.0.0",
|
|
"server_port": 7777,
|
|
"db_host": "mariadb",
|
|
"db_user": "drivershub",
|
|
"db_password": "use the DB_PASSWORD value from .env",
|
|
"db_name": "drivershub",
|
|
"db_data_directory": "/var/lib/mysqlext/",
|
|
"redis_host": "valkey",
|
|
"redis_port": 6379,
|
|
"captcha": {
|
|
"provider": "hcaptcha",
|
|
"secret": "replace with your hCaptcha secret"
|
|
},
|
|
"plugins": [
|
|
"announcement",
|
|
"application",
|
|
"banner",
|
|
"challenge",
|
|
"division",
|
|
"downloads",
|
|
"economy",
|
|
"event",
|
|
"poll",
|
|
"route",
|
|
"task"
|
|
],
|
|
"external_plugins": ["client-config"]
|
|
}
|
|
```
|
|
|
|
The example shows only the values that you must change. Keep all other values
|
|
from `config_sample.json`. Restart the backend after you change
|
|
`config/config.json`.
|
|
|
|
Use the same database password in `.env` and `config/config.json`.
|
|
Set `domain` to the public host name of the backend. Do not include a protocol or
|
|
path.
|
|
Set `abbr` to a short identifier for the VTC. The Docker frontend deployment
|
|
derives the API base URL from its `VITE_CONFIG_URL`, so `abbr` does not have to
|
|
match `prefix`.
|
|
Create an hCaptcha site for the public frontend domain. Set its secret in the
|
|
`captcha.secret` value. Set the related public site key as
|
|
`VITE_HCAPTCHA_SITEKEY` in the frontend deployment.
|
|
|
|
The upstream sample uses plural names for some built-in plugins, but the
|
|
backend expects the singular names shown above. This deployment configuration
|
|
enables all built-in plugins by default. Keep `client-config` separate in
|
|
`external_plugins`.
|
|
|
|
When the backend starts, it synchronizes `abbr` and the plugin list from
|
|
`config/config.json` to the frontend configuration in MariaDB. Other frontend
|
|
settings stay unchanged. Restart the backend after you change `abbr` or enable
|
|
or disable a plugin.
|
|
|
|
## Configure external connections
|
|
|
|
The following connections use the public frontend address. The examples use
|
|
`https://hub.example.com`. Replace this address with your frontend address.
|
|
|
|
### Discord
|
|
|
|
Create an application in the
|
|
[Discord Developer Portal](https://discord.com/developers/applications). Then,
|
|
configure it as follows:
|
|
|
|
1. Open **OAuth2** and add this exact redirect URL:
|
|
`https://hub.example.com/auth/discord/callback`.
|
|
2. Copy the application ID to `discord_client_id` in
|
|
`config/config.json`.
|
|
3. Create a client secret and copy it to `discord_client_secret`.
|
|
|
|
The callback URL points to the frontend. Do not add `/api` to it. The frontend
|
|
requests the `identify`, `email`, and `role_connections.write` OAuth scopes.
|
|
|
|
This configuration is sufficient for Discord sign-in and account connections.
|
|
A Discord bot is optional. Create and install a bot only if the Hub must check
|
|
server membership, use server nicknames, manage roles, or send messages and
|
|
direct notifications. For these functions:
|
|
|
|
1. Add a bot to the Discord application and copy its token to
|
|
`discord_bot_token`.
|
|
2. Copy the ID of the Discord server to `discord_guild_id`.
|
|
3. Install the bot in that server.
|
|
|
|
Give the bot only the permissions that these functions need. It needs access to
|
|
channels where it sends messages. Give it **Manage Roles** if the Hub must
|
|
change roles. Put the bot role above every role that it must manage.
|
|
|
|
If you do not install a bot, use these settings:
|
|
|
|
```json
|
|
"must_join_guild": false,
|
|
"use_server_nickname": false,
|
|
"discord_guild_id": "",
|
|
"discord_bot_token": ""
|
|
```
|
|
|
|
The external `discord-member` plugin also requires the bot, but the built-in
|
|
functions listed above do not depend on that plugin. The
|
|
[Discord OAuth2 documentation](https://docs.discord.com/developers/topics/oauth2)
|
|
explains application installation and OAuth2 settings.
|
|
|
|
The client secret and bot token are secrets. Do not commit
|
|
`config/config.json` or publish these values. Reset a secret or token
|
|
immediately if it becomes public.
|
|
|
|
### Steam
|
|
|
|
Get a Steam Web API key from the
|
|
[Steam Web API key page](https://steamcommunity.com/dev/apikey). Use the public
|
|
Hub domain when Steam asks for a domain. Copy the key to `steam_api_key` in
|
|
`config/config.json`.
|
|
|
|
Steam sign-in uses OpenID. You do not have to register a callback URL with
|
|
Steam. The frontend automatically uses
|
|
`https://hub.example.com/auth/steam/callback`. The backend uses the Web API key
|
|
to read Steam profile information.
|
|
|
|
### TruckersMP
|
|
|
|
TruckersMP account connections use the public TruckersMP API. They do not need
|
|
an API key or secret. After you create the initial administrator, open the Hub
|
|
administration interface and set `truckersmp_vtc_id` in the global client
|
|
configuration. Use the numeric ID from your TruckersMP VTC page URL. For
|
|
example, use `12345` for `https://truckersmp.com/vtc/12345`.
|
|
|
|
A user must connect Steam before the user connects TruckersMP. The backend
|
|
checks that both accounts use the same Steam ID. The `trackers` section in
|
|
`config/config.json` configures telemetry services. It does not configure the
|
|
TruckersMP account connection.
|
|
|
|
### Email
|
|
|
|
Configure SMTP if users must register with email, confirm or change an email
|
|
address, or reset a password. Set the connection and login values in
|
|
`config/config.json`:
|
|
|
|
```json
|
|
"smtp_host": "smtp.example.com",
|
|
"smtp_port": "587",
|
|
"smtp_email": "hub@example.com",
|
|
"smtp_password": "replace with the SMTP password"
|
|
```
|
|
|
|
Use the host, submission port, user name, and password from your email
|
|
provider. The `smtp_email` value is the SMTP login name. Some providers use an
|
|
account name instead of an email address.
|
|
|
|
Set the public frontend confirmation URL. Keep the `{secret}` placeholder:
|
|
|
|
```json
|
|
"frontend_urls": {
|
|
"email_confirm": "https://hub.example.com/auth/email?secret={secret}"
|
|
}
|
|
```
|
|
|
|
Do not replace the other entries in `frontend_urls`. Change each `from_email`
|
|
value in the `register`, `update_email`, and `reset_password` email templates
|
|
to a valid sender. For example:
|
|
|
|
```json
|
|
"from_email": "Drivers Hub <hub@example.com>"
|
|
```
|
|
|
|
The SMTP password is a secret. Do not commit `config/config.json`. Restart the
|
|
backend after you change the SMTP settings. Test email registration and
|
|
password reset before you make email registration available to users.
|
|
|
|
### Registration and required connections
|
|
|
|
Use `register_methods` in `config/config.json` to select the available
|
|
registration methods. Supported values include `email`, `discord`, and
|
|
`steam`. Use `required_connections` to select the accounts that a user must
|
|
connect. Add `truckersmp` if a TruckersMP connection is mandatory. For example:
|
|
|
|
```json
|
|
"register_methods": ["discord", "steam"],
|
|
"required_connections": ["discord", "steam", "truckersmp"]
|
|
```
|
|
|
|
Restart the backend after you change these settings. You do not have to rebuild
|
|
an image for changes in `config/config.json`.
|
|
|
|
## Edit the configuration in the Hub
|
|
|
|
The administration interface can save and apply application configuration
|
|
changes. The container sets the owner of the bind-mounted `config/` directory
|
|
to its internal user, UID and GID `10001`, when it starts. It then runs the
|
|
backend as that unprivileged user. This lets the backend create
|
|
`config.json.saved` and replace `config.json`. Both files stay in the project
|
|
directory on the host.
|
|
|
|
The administrator needs the `update_config` permission to save changes and the
|
|
`reload_config` permission to apply them. The default `administrator`
|
|
permission also grants access to these operations. The administrator must
|
|
enable MFA before applying a saved configuration.
|
|
|
|
The start process can change the numeric owner of files in `config/` to
|
|
`10001:10001` on the host. Use an account with sufficient permissions when you
|
|
edit these files directly. Do not make the directory writable by all users.
|
|
|
|
## Start the deployment
|
|
|
|
```bash
|
|
docker compose build
|
|
docker compose up -d
|
|
docker compose ps
|
|
```
|
|
|
|
Docker reuses its build cache for the Nuitka compilation. The first build can
|
|
take a long time. A later build usually reuses the compiled layer unless the
|
|
backend source, compiler environment, or Docker build cache changed.
|
|
|
|
By default, the API is available at `http://localhost:17777/api`. Swagger UI is
|
|
available at `http://localhost:17777/api/doc`.
|
|
The default bind address is suitable for a reverse proxy on the Docker host.
|
|
The backend reads its active Docker network gateway when it starts. Uvicorn
|
|
trusts forwarded headers only from this gateway and the loopback interface.
|
|
This works with multiple Docker Compose networks and lets audit and security
|
|
records contain the client IP address. Keep `BACKEND_BIND` on `127.0.0.1` and
|
|
let the reverse proxy provide the public endpoint.
|
|
|
|
## Store persistent data
|
|
|
|
The deployment stores all persistent data in these directories:
|
|
|
|
```text
|
|
data/
|
|
├── mariadb/
|
|
├── mariadb-external/
|
|
└── valkey/
|
|
```
|
|
|
|
Docker creates these directories at the first start. MariaDB and Valkey do not
|
|
publish ports on the host.
|
|
|
|
The `docker compose down` command removes the containers and the network. It does
|
|
not remove `config/` or `data/`. Back up these directories separately.
|
|
|
|
## Update the backend
|
|
|
|
Update the backend source code. Then, rebuild the containers:
|
|
|
|
```bash
|
|
git -C upstream/HubBackend pull --ff-only
|
|
docker compose build backend
|
|
docker compose up -d
|
|
```
|
|
|
|
## Operate the deployment
|
|
|
|
```bash
|
|
# Show the backend logs.
|
|
docker compose logs -f backend
|
|
|
|
# Restart the backend after a configuration change.
|
|
docker compose restart backend
|
|
```
|
|
|
|
## Create the initial administrator
|
|
|
|
The upstream sample configuration grants the `administrator` permission to
|
|
role `0`, named `root`. These are excerpts from the configuration. Do not
|
|
replace the complete `perms` object or `roles` list with these excerpts:
|
|
|
|
```json
|
|
"perms": {
|
|
"administrator": [0]
|
|
},
|
|
"roles": [
|
|
{"id": 0, "order_id": 0, "name": "root"}
|
|
]
|
|
```
|
|
|
|
Keep this relation, or select the administrator role from your modified
|
|
configuration. Then, create the user:
|
|
|
|
```bash
|
|
docker compose run --rm backend \
|
|
drivershub --config /app/config/config.json setup create-user user@example.com
|
|
```
|
|
|
|
Enter a secure password when the command prompts for it. The command returns a
|
|
`UID`. Accept the user with that value:
|
|
|
|
```bash
|
|
docker compose run --rm backend \
|
|
drivershub --config /app/config/config.json setup accept-user UID
|
|
```
|
|
|
|
The command returns a separate `user ID`. Assign administrator role `0` to that
|
|
user ID. Replace `0` with your administrator role ID if you changed the
|
|
configuration:
|
|
|
|
```bash
|
|
docker compose run --rm backend \
|
|
drivershub --config /app/config/config.json setup update-roles USER_ID 0
|
|
```
|
|
|
|
Do not interchange `UID` and `USER_ID`. You can now sign in with the email
|
|
address and password from the first command.
|
|
|
|
## Authors and license
|
|
|
|
This Docker deployment is developed by Kosmos <me@kosmos.ac> and is licensed
|
|
under the GNU Affero General Public License v3.0. See [LICENSE](LICENSE).
|
|
|
|
[Drivers Hub: Backend](https://github.com/CharlesWithC/HubBackend) is developed
|
|
by [CharlesWithC](https://charlws.com) and is licensed under the GNU Affero
|
|
General Public License v3.0. Drivers Hub remains a separate upstream project.
|