Files
HubBackendDocker/README.md
T

352 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.
## 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`.
## 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": "api",
"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 `prefix` to `/{abbr}` when you use the official frontend. The
`client-config` plugin uses this relation to create frontend API URLs.
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`.
The deployment patch synchronizes the plugin list from `config/config.json` to
the stored frontend configuration when the backend starts. Other frontend
settings in MariaDB stay unchanged. Restart the backend after you 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
```
The Python builder image is pinned to a tested image digest. Update this digest
deliberately when the compiler environment needs an update. A runtime base
image update does not invalidate the Nuitka build layer. Docker reuses its
normal internal build cache. A complete build is necessary after that cache is
removed.
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.