Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HJhXuLD2Z6hv3Wqeq9UL9K
131 lines
4.9 KiB
Markdown
131 lines
4.9 KiB
Markdown
# Running it on a Linux server
|
|
|
|
Goal: the app runs as its own unprivileged user, only nginx can reach it, and everything is behind HTTPS.
|
|
|
|
## 1. Dedicated user with rootless Docker
|
|
|
|
Members of the `docker` group are effectively root on the machine, so do **not** add the new user to it. Use *rootless* Docker instead: the daemon, the images and the container processes all belong to that one user. If something breaks out of the container, it only gets that user's rights. This runs separately from any existing (root) Docker, for example the one AMP uses.
|
|
|
|
```bash
|
|
# as an admin user
|
|
sudo adduser --disabled-password --gecos "" awcc # no password, no sudo
|
|
sudo apt install -y uidmap dbus-user-session slirp4netns docker-ce-rootless-extras
|
|
sudo loginctl enable-linger awcc # user services start at boot
|
|
```
|
|
|
|
Leave the system Docker alone if other things (AMP) use it; rootless Docker runs next to it.
|
|
`docker-ce-rootless-extras` comes from Docker's own apt repository. If Docker was installed from your distribution (`docker.io`), add Docker's repository first (see docs.docker.com/engine/install).
|
|
|
|
Switch to the user and install the rootless daemon:
|
|
|
|
```bash
|
|
sudo -iu awcc
|
|
export XDG_RUNTIME_DIR=/run/user/$(id -u)
|
|
export DBUS_SESSION_BUS_ADDRESS=unix:path=$XDG_RUNTIME_DIR/bus
|
|
dockerd-rootless-setuptool.sh install
|
|
systemctl --user enable --now docker
|
|
echo 'export DOCKER_HOST=unix://$XDG_RUNTIME_DIR/docker.sock' >> ~/.bashrc
|
|
echo 'export XDG_RUNTIME_DIR=/run/user/$(id -u)' >> ~/.bashrc
|
|
source ~/.bashrc
|
|
docker run --rm hello-world # test
|
|
```
|
|
|
|
## 2. Get the code
|
|
|
|
Use a read-only **deploy key** so this user never holds your personal Gitea credentials:
|
|
|
|
```bash
|
|
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519 -N "" -C "awcc deploy key"
|
|
cat ~/.ssh/id_ed25519.pub # Gitea: repository -> Settings -> Deploy Keys -> add, leave "write access" off
|
|
git clone ssh://git@git.bitrux.de/otto/AWCharacterCreator.git # adjust the SSH port/URL to your Gitea
|
|
cd AWCharacterCreator
|
|
```
|
|
|
|
## 3. Configure and start
|
|
|
|
```bash
|
|
cp .env.example .env
|
|
nano .env # set AW_REGISTRATION_CODE, and AW_TRUST_PROXY=1 (nginx is in front)
|
|
chmod 600 .env
|
|
docker compose up -d --build
|
|
curl -sI http://127.0.0.1:8090 | head -1 # should print HTTP/1.1 200 OK
|
|
```
|
|
|
|
The container only listens on `127.0.0.1:8090` (change it with `AW_PORT` in `.env` if the port is taken, e.g. AMP uses 8080), so it is not reachable from outside until nginx forwards to it. The database is `./db/aw.db`; changes from the rules editor are in `./db/rules_overrides.json` (back up the whole `db` folder). Set `AW_ADMINS` in `.env` to choose who may use the editor (default: the first account).
|
|
|
|
## 4. nginx + HTTPS
|
|
|
|
Point a DNS name (for example `aw.yourdomain.tld`) at the server, then create `/etc/nginx/sites-available/aw`:
|
|
|
|
```nginx
|
|
server {
|
|
listen 80;
|
|
server_name aw.yourdomain.tld;
|
|
|
|
client_max_body_size 1m;
|
|
|
|
location / {
|
|
proxy_pass http://127.0.0.1:8090; # same as AW_PORT in .env
|
|
proxy_set_header Host $host;
|
|
proxy_set_header X-Forwarded-For $remote_addr; # overwrite, so clients cannot fake their address
|
|
proxy_set_header X-Forwarded-Proto $scheme;
|
|
proxy_set_header X-Forwarded-Host $host;
|
|
}
|
|
}
|
|
```
|
|
|
|
```bash
|
|
sudo ln -s /etc/nginx/sites-available/aw /etc/nginx/sites-enabled/aw
|
|
sudo nginx -t && sudo systemctl reload nginx
|
|
sudo certbot --nginx -d aw.yourdomain.tld # gets the certificate, adds HTTPS and the redirect
|
|
```
|
|
|
|
Then add inside the HTTPS `server` block: `add_header Strict-Transport-Security "max-age=31536000" always;`
|
|
|
|
Firewall: only SSH, 80 and 443 should be open. The app port (AW_PORT, default 8090) is not published to the outside at all.
|
|
|
|
Open the site, choose "Create account" and register with your registration code.
|
|
|
|
## 5. Updating
|
|
|
|
```bash
|
|
cd ~/AWCharacterCreator
|
|
git pull
|
|
docker compose up -d --build # only needed when code changed
|
|
```
|
|
|
|
If only `backend/data/rules.json` changed, `git pull` is enough (it is re-read on every request).
|
|
|
|
## 6. Backups
|
|
|
|
```bash
|
|
sudo apt install -y sqlite3
|
|
mkdir -p ~/backups
|
|
crontab -e
|
|
# add:
|
|
0 3 * * * sqlite3 $HOME/AWCharacterCreator/db/aw.db ".backup '$HOME/backups/aw-$(date +\%F).db'" && find $HOME/backups -name 'aw-*.db' -mtime +14 -delete
|
|
```
|
|
|
|
Copy `~/backups` somewhere off the server now and then.
|
|
|
|
## 7. Handy commands
|
|
|
|
```bash
|
|
docker compose logs -f # logs
|
|
docker compose exec awcc python -m app.admin list # users
|
|
docker compose exec awcc python -m app.admin passwd NAME # reset a password
|
|
docker compose down # stop
|
|
```
|
|
|
|
If `docker` says it cannot connect to the daemon, check the two `export` lines from step 1 and `systemctl --user status docker`.
|
|
|
|
## Updating
|
|
|
|
```bash
|
|
cd ~/AWCharacterCreator
|
|
git pull
|
|
docker compose up -d --build
|
|
```
|
|
|
|
The `db` folder (database and rules editor changes) is kept. New settings from `.env.example` have to be added to your `.env` by hand.
|