216 lines
6.4 KiB
Markdown
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.
|