Tobserver/docs/forgejo-operations.md
2026-08-01 13:56:44 +07:00

216 lines
6.4 KiB
Markdown

# Forgejo trial operations
This runbook covers the initial Forgejo trial on Tobserver. The complete
service, SQLite, package, and nginx configuration lives in
`modules/forgejo.nix`.
> **Warning:** This trial is unprotected. It has no Forgejo backup job, and its
> data must be treated as disposable. Keep the authoritative copy of anything
> important somewhere else.
Run deployment commands from the Tobserver checkout unless noted otherwise.
Never place passwords or other credentials in Git, Nix expressions, command
arguments, shell history, logs, or issue comments.
## Pre-deployment checks
Confirm that the dedicated hostname points only to Tobserver:
```console
test "$(dig +short git.tobiasostner.de A)" = "162.55.103.218"
test -z "$(dig +short git.tobiasostner.de AAAA)"
```
On a workstation, evaluate the configuration and build it on a compatible Linux
builder when one is available:
```console
nix flake check --no-build
nix build .#nixosConfigurations.tobserver.config.system.build.toplevel
```
Commit and push the reviewed changes. On Tobserver, update a clean checkout and
build without activating it:
```console
cd ~/tobserver
test -z "$(git status --porcelain)" || {
echo "Refusing to deploy from a dirty checkout" >&2
exit 1
}
git pull --ff-only
git rev-parse HEAD
nix flake check --no-build
if sudo test -e /var/lib/forgejo \
&& sudo find /var/lib/forgejo -mindepth 1 -print -quit | grep -q .; then
echo "Refusing to reuse non-empty Forgejo state" >&2
exit 1
fi
sudo nixos-rebuild build --flake .#tobserver
```
Compare the printed commit with the reviewed deployment commit. Do not continue
if evaluation, the full host build, or the empty-state check fails.
## Activation and service checks
Activate the configuration only after reviewing the successful build. Immediately
before switching, recheck that the checkout is clean and still at the reviewed
commit printed during the build step:
```console
read -r -p 'Reviewed commit hash: ' reviewed_commit
test -z "$(git status --porcelain)" || {
echo "Refusing to switch from a dirty checkout" >&2
exit 1
}
current_commit="$(git rev-parse HEAD)"
printf 'Switching commit: %s\n' "$current_commit"
test "$current_commit" = "$reviewed_commit" || {
echo "Refusing to switch an unreviewed commit" >&2
exit 1
}
sudo nixos-rebuild switch --flake .#tobserver
unset current_commit reviewed_commit
```
Verify the services, loopback-only backend, local API, rendered nginx
configuration, and public HTTPS endpoint:
```console
sudo systemctl is-active forgejo.service nginx.service
sudo ss -H -ltn 'sport = :3001'
curl --fail --silent --show-error \
-H 'Host: git.tobiasostner.de' \
http://127.0.0.1:3001/api/v1/version \
| jq -e .
sudo nginx -t
(
set -euo pipefail
nginx_config="$(sudo nginx -T 2>&1)"
for required_line in \
'git.tobiasostner.de' \
'merge_slashes off' \
'client_max_body_size 512M' \
'proxy_set_header Host $host' \
'proxy_set_header X-Real-IP $remote_addr' \
'proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for' \
'proxy_set_header X-Forwarded-Proto $scheme' \
'proxy_set_header Connection $http_connection' \
'proxy_set_header Upgrade $http_upgrade'
do
printf '%s\n' "$nginx_config" | grep -F -- "$required_line" >/dev/null
done
)
curl --fail --silent --show-error --location \
--output /dev/null \
--write-out '%{http_code} %{url_effective}\n' \
http://git.tobiasostner.de/
```
The listener output must contain `127.0.0.1:3001` and no non-loopback address.
The public request must report HTTP 200 at `https://git.tobiasostner.de/`.
Port 3001 must not be reachable from an external machine:
```console
! nc -z git.tobiasostner.de 3001
```
If a check fails, inspect logs before restarting or changing state:
```console
sudo journalctl \
-u forgejo.service \
-u nginx.service \
--since '-15 minutes' \
--no-pager
```
## Create the first administrator
Run this once in an interactive shell on Tobserver. Enter the administrator
email when prompted; it stays in the shell variable and is not recorded in this
runbook or shell history.
```console
read -r -p 'Admin email: ' admin_email
sudo -u forgejo env \
HOME=/var/lib/forgejo \
USER=forgejo \
FORGEJO_WORK_DIR=/var/lib/forgejo \
FORGEJO_CUSTOM=/var/lib/forgejo/custom \
forgejo --config /var/lib/forgejo/custom/conf/app.ini \
admin user create \
--username "oibot" \
--email "$admin_email" \
--admin \
--random-password
unset admin_email
```
The command prints a generated password once. Copy it directly into the
approved password manager immediately, then clear the terminal. Do not redirect,
pipe, log, or save the output in a temporary file, and do not choose a password
on the command line.
Confirm that the account is an administrator:
```console
sudo -u forgejo env \
HOME=/var/lib/forgejo \
USER=forgejo \
FORGEJO_WORK_DIR=/var/lib/forgejo \
FORGEJO_CUSTOM=/var/lib/forgejo/custom \
forgejo --config /var/lib/forgejo/custom/conf/app.ini \
admin user list --admin \
| grep -F -- 'oibot'
```
Sign in at `https://git.tobiasostner.de/` and confirm that the interface does
not offer public registration.
## Disposable HTTPS and SSH smoke test
In the Forgejo interface:
1. Add the external client's public SSH key to the `oibot` account.
2. Create an empty repository named `clone-smoke`.
From an external client, exercise HTTPS clone and push with a disposable commit:
```console
workdir="$(mktemp -d)"
git clone https://git.tobiasostner.de/oibot/clone-smoke.git \
"$workdir/clone-smoke-https"
cd "$workdir/clone-smoke-https"
printf '%s\n' 'Forgejo trial' > README.md
git add README.md
git commit -m 'Test Forgejo trial'
git push origin HEAD:main
```
Then exercise host OpenSSH clone and fetch:
```console
git clone forgejo@git.tobiasostner.de:oibot/clone-smoke.git \
"$workdir/clone-smoke-ssh"
git -C "$workdir/clone-smoke-ssh" fetch origin
rm -rf -- "$workdir"
```
All clone, push, and fetch commands must exit successfully. The repository and
commit are disposable trial data.
## Trial rollback boundary
Tobserver hosts unrelated services, so do not use a broad live NixOS generation
rollback as a routine Forgejo test. If the service is unhealthy, collect its
status and journals first. Prepare and review a narrow change that removes only
the `modules/forgejo.nix` import and its Forgejo service and nginx virtual host.
Preserve `/var/lib/forgejo`; never delete trial state as an automatic rollback
action.