docs: adopt clean PSD replacement model

This commit is contained in:
User
2026-08-21 16:05:11 +02:00
parent 9974fb4bc0
commit 042af932ee
10 changed files with 527 additions and 128 deletions
+48 -48
View File
@@ -40,53 +40,53 @@ Read [server workspace-registry installation](server-workspace-registry.md),
## Service account and directories
The container runtime identity is fixed at UID/GID 10001. Reserve the same host ID for a dedicated
non-login `thothii` account so bind-mounted ownership is obvious. Stop if either ID is already used
by another account; choose a reviewed host mapping instead of changing the image identity.
The container runtime identity is fixed at UID/GID 10001. It does not require or permit creation of
a matching host account or group. Keep the number unmapped and use numeric ownership only for the
dedicated bind paths that the non-root container must read or write. If either lookup below finds a
host identity, stop and design an explicit remapping before installation.
```sh
getent passwd 10001
getent group 10001
sudo useradd --system --uid 10001 --user-group --home-dir /srv/thothii \
--create-home --shell /usr/sbin/nologin thothii
if getent passwd 10001 >/dev/null || getent group 10001 >/dev/null; then
printf '%s\n' 'UID/GID 10001 is already mapped; stop' >&2
exit 1
fi
operator_uid="$(id -u)"
operator_gid="$(id -g)"
test "$operator_uid" -ne 0
id -nG | tr ' ' '\n' | grep -Fx docker >/dev/null
```
Use a dedicated `thothii-ops` group for the small set of human operators. A human who runs
`tht` must be in both `thothii-ops` (to traverse operator paths and read declared secret files
for output redaction) and the host `docker` group (to invoke Docker). Docker-group membership is
effectively host-root access; grant both memberships only to reviewed administrators. The
non-login `thothii` account owns files and writable data but does not need Docker access.
```sh
sudo groupadd --system thothii-ops
sudo usermod --append --groups thothii-ops,docker "$USER"
```
Log out and back in before continuing; `id` must show both groups. Do not run `tht` through
`sudo -u thothii`: that account deliberately lacks Docker access. Do not grant the human direct
write access to runtime bind trees.
The invoking, pre-existing administrator owns source and operator files. It must already have the
site-approved Docker access required to run `tht`; this guide never changes group membership.
Docker-group membership is effectively host-root access and must remain limited to reviewed
administrators. Do not grant the operator direct write access to container runtime trees.
Create explicit directories. `source` contains the clone; `operator` contains untracked path-only
configuration; the three writable trees are bind-mounted into `core`; `secrets` contains regular
files only. Backups are separate from live data. Reset the account home explicitly because
distribution `useradd` defaults may otherwise leave `/srv/thothii` non-traversable by
`thothii-ops`.
files only. The parent is owned by the operator with numeric group 10001 so both the operator and
container can traverse it. Numeric ownership does not add entries to `/etc/passwd` or `/etc/group`.
```sh
sudo install -d -o 10001 -g thothii-ops -m 2750 /srv/thothii
sudo install -d -o 10001 -g thothii-ops -m 2750 /srv/thothii/source
sudo install -d -o 10001 -g thothii-ops -m 2770 /srv/thothii/operator
sudo install -d -o 10001 -g thothii-ops -m 2750 /srv/thothii/secrets
operator_uid="$(id -u)"
operator_gid="$(id -g)"
sudo install -d -o "$operator_uid" -g 10001 -m 0750 /srv/thothii
sudo install -d -o "$operator_uid" -g "$operator_gid" -m 0750 /srv/thothii/source
sudo install -d -o "$operator_uid" -g "$operator_gid" -m 0750 /srv/thothii/operator
sudo install -d -o 10001 -g "$operator_gid" -m 0750 /srv/thothii/secrets
sudo install -d -o 10001 -g 10001 -m 0750 /srv/thothii/data
sudo install -d -o 10001 -g 10001 -m 0750 /srv/thothii/pi-state
sudo install -d -o 10001 -g 10001 -m 0750 /srv/thothii/workspace-registry
sudo install -d -o root -g root -m 0700 /srv/thothii-backups
stat -c '%u:%g %a %n' \
/srv/thothii /srv/thothii/source /srv/thothii/operator /srv/thothii/secrets \
/srv/thothii/data /srv/thothii/pi-state /srv/thothii/workspace-registry \
/srv/thothii-backups
```
Verify `/srv/thothii` is owned by `10001:thothii-ops` with mode `2750`. The human operator can
traverse the parent but can write only `operator`; setgid keeps generated files in `thothii-ops`.
`source`, `secrets`, and all runtime bind trees remain non-group-writable. Do not make
`/srv/thothii` a shared application directory.
Expected: the parent is `operator_uid:10001 750`; source/operator are
`operator_uid:operator_gid 750`; secrets are `10001:operator_gid 750`; the three runtime trees are
`10001:10001 750`; backups are `0:0 700`. Re-run the empty `getent` checks after creation. Do not
make `/srv/thothii` a shared application directory.
## Firewall and network boundaries
@@ -187,10 +187,10 @@ Never add those services to ThothII's mandatory Compose files. Follow
Clone with LF line endings, then verify before every build:
```sh
sudo -u thothii git -c core.autocrlf=false clone \
git -c core.autocrlf=false clone \
https://github.example.invalid/your-org/ThothII.git /srv/thothii/source/ThothII
cd /srv/thothii/source/ThothII
sudo -u thothii git config --local core.autocrlf false
git config --local core.autocrlf false
bash scripts/verify-line-endings.sh
sudo /srv/thothii/source/ThothII/scripts/prepare-server-pi-state.sh \
/srv/thothii/pi-state 10001 10001
@@ -206,17 +206,15 @@ after restoring `pi-state`; run it before any `tht start`, Compose render/start,
Copy the path-only server environment and installation descriptor:
```sh
sudo -u thothii cp deploy/env/server.env.example /srv/thothii/operator/server.env
sudo -u thothii cp docs/install/examples/thothii-installation.server.yaml \
cp deploy/env/server.env.example /srv/thothii/operator/server.env
cp docs/install/examples/thothii-installation.server.yaml \
/srv/thothii/operator/thothii-installation.yaml
sudo chown 10001:thothii-ops /srv/thothii/operator/server.env \
/srv/thothii/operator/thothii-installation.yaml
sudo chmod 0660 /srv/thothii/operator/server.env \
chmod 0600 /srv/thothii/operator/server.env \
/srv/thothii/operator/thothii-installation.yaml
```
The named human operator can now edit both placeholder files without `sudo`; use an editor that
preserves the group, or create replacements under `umask 0007` in the setgid operator directory.
The invoking operator owns both placeholder files; use an editor that preserves ownership and mode,
or create replacements under `umask 0077` in the operator directory.
Replace every placeholder with an absolute path. Use exactly one Git transport override. For
HTTPS, replace `deploy/compose.git-ssh.yaml` with `deploy/compose.git-https.yaml`. Keep the required
session-server overlay. Optional host-gateway or pinned
@@ -224,17 +222,18 @@ image overrides go after them.
Create each installation credential (Pi/application, Git, and session storage) as an independent
regular file in `/srv/thothii/secrets`, owned by
UID 10001, group `thothii-ops`, and mode `0640`. Owner access lets the UID 10001 container read a
file mounted under `/run/secrets`; group access lets the reviewed human run `tht`. The
UID 10001, the invoking operator's numeric primary GID, and mode `0640`. Owner access lets the UID
10001 container read a file mounted under `/run/secrets`; group access lets the operator run `tht`. The
operator environment records only absolute `*_FILE` or `*_SOURCE` paths for those installation
credentials. DWH and Evidence values are entered later through Workspace management and persist
as ciphertext under `/data/workspace-secrets`; the frontend receives no secret values. Do not
print file contents while testing permissions.
```sh
sudo find /srv/thothii/secrets -type f -exec chown 10001:thothii-ops {} +
operator_gid="$(id -g)"
sudo find /srv/thothii/secrets -type f -exec chown "10001:$operator_gid" {} +
sudo find /srv/thothii/secrets -type f -exec chmod 0640 {} +
sudo find /srv/thothii/secrets -type f \( ! -user thothii -o ! -group thothii-ops -o ! -perm 0640 \) -print
sudo find /srv/thothii/secrets -type f \( ! -uid 10001 -o ! -gid "$operator_gid" -o ! -perm 0640 \) -print
```
Configure the remote repository and exactly one read-only Git transport as described in
@@ -250,7 +249,7 @@ Compose; copy the reviewed path-only server environment to the launcher's untrac
```sh
cd /srv/thothii/source/ThothII
sudo -u thothii cp /srv/thothii/operator/server.env deploy/env/local.env
cp /srv/thothii/operator/server.env deploy/env/local.env
bash scripts/build-local.sh
```
@@ -286,12 +285,13 @@ Build the operator binaries with Docker. No Go installation or Go knowledge is r
cd /srv/thothii/source/ThothII
THT_THT_OUTPUT_DIRECTORY=/srv/thothii/operator/build-output \
bash scripts/build-tht.sh
sudo install -o root -g thothii-ops -m 0750 \
operator_gid="$(id -g)"
sudo install -o root -g "$operator_gid" -m 0750 \
/srv/thothii/operator/build-output/tht-linux-amd64 \
/srv/thothii/operator/tht
```
The source checkout stays read-only to the human. The explicit output directory is the only build
The source checkout remains controlled by the invoking operator. The explicit output directory is the only build
write boundary; the build script rejects relative or non-canonical output paths. After installation,
remove or retain `build-output` according to the site's reviewed artifact policy.