# Deploying forge to RustForge RustForge is a Debian 13 (trixie) Proxmox LXC on Hetzner: `ssh -p 2222 rust@88.99.212.146`, private IP **172.16.10.10**. forge listens on `0.0.0.0:8090` inside the container. TLS and the public ports 80/443 belong to a separate proxy-manager container (e.g. Nginx Proxy Manager). ## Proxy manager setting Point the proxy host at: ``` http://172.16.10.10:8090 ``` Scheme `http`, forward host `172.16.10.10`, port `8090`. Websockets and caching are not needed. Leave request buffering off if you can, so large clones stream. Once the domain exists, set `clone_base_url` in `/etc/forge/forge.toml` (it's a TODO there) and run `sudo systemctl restart forge`. ## Layout on the server | Path | What | Owner | |------|------|-------| | `/opt/forge/bin/forge` | the binary, built on the dev box (CSS is compiled in, no static files needed) | root, 755 | | `/opt/forge/README.md` | docs | root | | `/etc/forge/forge.toml` | config (from `deploy/forge.toml.example`) | root:forge, 640 | | `/etc/systemd/system/forge.service` | unit (from `deploy/forge.service`) | root | | `/srv/git/.git` | bare mirrors that forge serves | forge:forge | The service runs as the system user `forge` (no login shell, home `/srv/git`). It has `Restart=on-failure` and a read-only view of the whole filesystem (`ProtectSystem=strict`, `NoNewPrivileges`, `PrivateTmp`, no capabilities). Logs go to `journalctl -u forge`. Packages installed on the server: `git` (forge runs `git upload-pack` for clones), `ca-certificates`, `rsync` (receiving end of the mirror sync), `curl` (for checks), and `unattended-upgrades` (Debian security updates). ## First-time setup (already done) ```sh sudo apt-get update && sudo apt-get install -y --no-install-recommends git ca-certificates rsync curl unattended-upgrades sudo useradd --system --user-group --home-dir /srv/git --no-create-home --shell /usr/sbin/nologin forge sudo install -d -m 755 -o forge -g forge /srv/git ``` ## Updating forge From the dev box (it never builds on the server): ```sh scripts/deploy.sh # build --release, copy binary + unit, restart scripts/deploy.sh --config # same, and overwrite /etc/forge/forge.toml from the example ``` ## Syncing the repos The working repos in `/workspace` must never get a git remote or be pushed from (other agents work in them). `scripts/sync-mirrors.sh` publishes them anyway: 1. It keeps a private bare mirror per repo in `/workspace/.forge-mirrors/.git` (`git clone --mirror` once, then `git remote update --prune` *inside the mirror*). Only branches and tags are published. 2. It rsyncs the mirror over ssh to `/srv/git/.git`, objects first and refs second, so a half-finished sync never points at missing objects. The server keeps its own `config` and `hooks`. 3. It runs `chown -R forge:forge` on the server. ```sh scripts/sync-mirrors.sh # all repos scripts/sync-mirrors.sh rust-kernel # just one ``` It is idempotent, so run it whenever you want the site updated (or from cron). To add a repo, add `name=/path` to `REPOS` in the script and a `[[repo]]` entry to `/etc/forge/forge.toml`, then restart forge. `/workspace/rustbelt-os` is already in the list and is skipped until it exists. ## Checks ```sh curl -s -o /dev/null -w '%{http_code}\n' localhost:8090/ git clone http://127.0.0.1:8090/rust-kernel /tmp/x systemctl status forge ```