Files
AWCharacterCreator/DEPLOY.md
T

4.5 KiB

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.

# 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:

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:

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

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.

4. nginx + HTTPS

Point a DNS name (for example aw.yourdomain.tld) at the server, then create /etc/nginx/sites-available/aw:

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;
    }
}
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

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

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

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.