docs: adopt clean PSD replacement model
This commit is contained in:
@@ -6,30 +6,25 @@ root="$(cd "$(dirname "$0")/.." && pwd -P)"
|
||||
image='golang:1.26.5-bookworm@sha256:1ecb7edf62a0408027bd5729dfd6b1b8766e578e8df93995b225dfd0944eb651'
|
||||
|
||||
docker run --rm --volume "$root:/repository:ro" "$image" /bin/bash -ceu '
|
||||
groupadd --gid 10001 thothii
|
||||
useradd --uid 10001 --gid 10001 --home-dir /srv/thothii --create-home --shell /usr/sbin/nologin thothii
|
||||
# Reproduce the conservative home mode permitted by the documented useradd sequence.
|
||||
chmod 0700 /srv/thothii
|
||||
groupadd --gid 20001 operator-primary
|
||||
groupadd --gid 20002 thothii-ops
|
||||
groupadd --gid 20003 docker
|
||||
useradd --uid 20001 --gid 20001 --groups 20002,20003 --create-home --shell /bin/bash operator
|
||||
useradd --uid 20001 --gid 20001 --groups 20003 --create-home --shell /bin/bash operator
|
||||
|
||||
install -d -o 10001 -g 20002 -m 2750 /srv/thothii
|
||||
install -d -o 10001 -g 20002 -m 2750 /srv/thothii/source
|
||||
install -d -o 10001 -g 20002 -m 2770 /srv/thothii/operator
|
||||
install -d -o 10001 -g 20002 -m 2750 /srv/thothii/secrets
|
||||
install -d -o 20001 -g 10001 -m 0750 /srv/thothii
|
||||
install -d -o 20001 -g 20001 -m 0750 /srv/thothii/source
|
||||
install -d -o 20001 -g 20001 -m 0750 /srv/thothii/operator
|
||||
install -d -o 10001 -g 20001 -m 0750 /srv/thothii/secrets
|
||||
install -d -o 10001 -g 10001 -m 0750 /srv/thothii/data /srv/thothii/pi-state /srv/thothii/workspace-registry
|
||||
install -d -o 10001 -g 10001 -m 0700 /srv/thothii/data/workspace-secrets
|
||||
install -d -o 10001 -g 20002 -m 2750 /srv/thothii/source/ThothII /srv/thothii/source/ThothII/scripts
|
||||
install -o 10001 -g 20002 -m 0750 /repository/scripts/build-tht.sh /srv/thothii/source/ThothII/scripts/build-tht.sh
|
||||
install -o 10001 -g 20002 -m 0750 /repository/scripts/prepare-server-pi-state.sh /srv/thothii/source/ThothII/scripts/prepare-server-pi-state.sh
|
||||
install -d -o 20001 -g 20001 -m 0750 /srv/thothii/source/ThothII /srv/thothii/source/ThothII/scripts
|
||||
install -o 20001 -g 20001 -m 0750 /repository/scripts/build-tht.sh /srv/thothii/source/ThothII/scripts/build-tht.sh
|
||||
install -o 20001 -g 20001 -m 0750 /repository/scripts/prepare-server-pi-state.sh /srv/thothii/source/ThothII/scripts/prepare-server-pi-state.sh
|
||||
/srv/thothii/source/ThothII/scripts/prepare-server-pi-state.sh /srv/thothii/pi-state 10001 10001
|
||||
|
||||
printf "%s\n" "PLACEHOLDER=replace-me" > /srv/thothii/operator/server.env
|
||||
printf "%s\n" "projectDirectory: replace-me" > /srv/thothii/operator/thothii-installation.yaml
|
||||
chown 10001:20002 /srv/thothii/operator/server.env /srv/thothii/operator/thothii-installation.yaml
|
||||
chmod 0660 /srv/thothii/operator/server.env /srv/thothii/operator/thothii-installation.yaml
|
||||
chown 20001:20001 /srv/thothii/operator/server.env /srv/thothii/operator/thothii-installation.yaml
|
||||
chmod 0600 /srv/thothii/operator/server.env /srv/thothii/operator/thothii-installation.yaml
|
||||
|
||||
printf "%s\n" \
|
||||
"#!/bin/bash" \
|
||||
@@ -45,10 +40,10 @@ printf "%s\n" \
|
||||
chmod 0755 /usr/local/bin/docker
|
||||
|
||||
runuser --user operator -- /bin/bash -ceu '\''
|
||||
umask 0007
|
||||
umask 0077
|
||||
sed -i "s/replace-me/ready/" /srv/thothii/operator/server.env
|
||||
sed -i "s#replace-me#/srv/thothii/source/ThothII#" /srv/thothii/operator/thothii-installation.yaml
|
||||
for protected in /srv/thothii /srv/thothii/source /srv/thothii/secrets \
|
||||
for protected in /srv/thothii/secrets \
|
||||
/srv/thothii/data /srv/thothii/pi-state /srv/thothii/workspace-registry; do
|
||||
if touch "$protected/operator-must-not-write" 2>/dev/null; then exit 42; fi
|
||||
done
|
||||
@@ -66,18 +61,29 @@ rm -f "$root_output_error"
|
||||
--installation /srv/thothii/operator/thothii-installation.yaml start
|
||||
'\''
|
||||
|
||||
test "$(stat -c %u:%g /srv/thothii)" = 10001:20002
|
||||
test "$(stat -c %a /srv/thothii)" = 2750
|
||||
test "$(stat -c %u:%g /srv/thothii)" = 20001:10001
|
||||
test "$(stat -c %a /srv/thothii)" = 750
|
||||
test "$(stat -c %u:%g /srv/thothii/pi-state/agent)" = 10001:10001
|
||||
test "$(stat -c %a /srv/thothii/pi-state/agent)" = 700
|
||||
for target in auth.json models.json settings.json; do
|
||||
test "$(stat -c %u:%g /srv/thothii/pi-state/agent/$target)" = 10001:10001
|
||||
test "$(stat -c %a /srv/thothii/pi-state/agent/$target)" = 600
|
||||
done
|
||||
test "$(stat -c %u:%g /srv/thothii/operator/build-output/tht-linux-amd64)" = 20001:20002
|
||||
test "$(stat -c %u:%g /srv/thothii/operator/build-output/tht-linux-amd64)" = 20001:20001
|
||||
if getent passwd 10001 >/dev/null || getent group 10001 >/dev/null; then
|
||||
printf "%s\n" "numeric runtime identity unexpectedly mapped on host fixture" >&2
|
||||
exit 47
|
||||
fi
|
||||
test "$(stat -c %u:%g /srv/thothii)" = 20001:10001
|
||||
test "$(stat -c %a /srv/thothii)" = 750
|
||||
test "$(stat -c %u:%g /srv/thothii/source)" = 20001:20001
|
||||
test "$(stat -c %u:%g /srv/thothii/operator)" = 20001:20001
|
||||
test "$(stat -c %u:%g /srv/thothii/secrets)" = 10001:20001
|
||||
test "$(stat -c %a /srv/thothii/operator/server.env)" = 600
|
||||
test "$(stat -c %a /srv/thothii/operator/thothii-installation.yaml)" = 600
|
||||
test "$(stat -c %a /srv/thothii/operator/build-output/tht-linux-amd64)" = 750
|
||||
test -f /srv/thothii/operator/start.marker
|
||||
for protected in /srv/thothii /srv/thothii/source /srv/thothii/secrets \
|
||||
for protected in /srv/thothii/secrets \
|
||||
/srv/thothii/data /srv/thothii/pi-state /srv/thothii/workspace-registry; do
|
||||
test ! -e "$protected/operator-must-not-write"
|
||||
done
|
||||
|
||||
@@ -70,12 +70,15 @@ grep -Fq 'scripts/prepare-server-pi-state.sh /srv/thothii/pi-state 10001 10001'
|
||||
echo "server guide does not initialize nested Pi-state targets before Compose" >&2
|
||||
exit 1
|
||||
}
|
||||
grep -Eq '^sudo install -d -o 10001 -g thothii-ops -m 2750 /srv/thothii$' "$server_guide" || {
|
||||
grep -Fq 'sudo install -d -o "$operator_uid" -g 10001 -m 0750 /srv/thothii' "$server_guide" || {
|
||||
echo "server operations guide does not set the parent traversal boundary" >&2
|
||||
exit 1
|
||||
}
|
||||
for required in \
|
||||
'thothii-ops' \
|
||||
'does not require or permit creation' \
|
||||
'getent passwd 10001' \
|
||||
'getent group 10001' \
|
||||
'chmod 0600 /srv/thothii/operator/server.env' \
|
||||
'THT_BACKUP_ROOT=/srv/thothii-backups' \
|
||||
'sessions migrate --yes' \
|
||||
'"pending":[]' \
|
||||
@@ -90,6 +93,12 @@ for required in \
|
||||
exit 1
|
||||
}
|
||||
done
|
||||
for forbidden in 'sudo useradd' 'sudo groupadd' 'sudo usermod' 'sudo -u thothii' 'thothii-ops'; do
|
||||
if grep -Fq -- "$forbidden" "$server_guide"; then
|
||||
echo "server operations guide creates or depends on a host identity: $forbidden" >&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
grep -Fq '"$THT_BIN" --help' "$server_guide" || {
|
||||
echo "server guide lacks plain tht --help" >&2
|
||||
exit 1
|
||||
@@ -702,7 +711,10 @@ switch (mutation) {
|
||||
changed += "\nFor host-gateway, keep the external service listening on 127.0.0.1.\n";
|
||||
break;
|
||||
case "server-parent-traversal":
|
||||
changed = original.replace("sudo install -d -o 10001 -g thothii-ops -m 2750 /srv/thothii\n", "");
|
||||
changed = original.replace('sudo install -d -o "$operator_uid" -g 10001 -m 0750 /srv/thothii\n', '');
|
||||
break;
|
||||
case "server-host-account":
|
||||
changed += "\n```sh\nsudo useradd --system --uid 10001 thothii\n```\n";
|
||||
break;
|
||||
case "server-raw-remove":
|
||||
changed += "\n```sh\ndocker rm thothii-core thothii-frontend\n```\n";
|
||||
@@ -885,6 +897,10 @@ expect_guide_rejected \
|
||||
"server parent traversal boundary" verify_server_guide \
|
||||
"$root/docs/install/server.md" docs/install/server.md server-parent-traversal \
|
||||
"server installation guide does not set parent traversal boundary"
|
||||
expect_guide_rejected \
|
||||
"server host account creation" verify_server_guide \
|
||||
"$root/docs/install/server.md" docs/install/server.md server-host-account \
|
||||
"server installation guide creates or depends on a host identity"
|
||||
expect_guide_rejected \
|
||||
"server raw container removal" verify_server_guide \
|
||||
"$root/docs/install/server.md" docs/install/server.md server-raw-remove \
|
||||
|
||||
@@ -1233,9 +1233,11 @@ verify_server_guide() {
|
||||
"frontend" \
|
||||
"core" \
|
||||
"UID/GID 10001" \
|
||||
"thothii-ops" \
|
||||
"-m 2770 /srv/thothii/operator" \
|
||||
"chmod 0660 /srv/thothii/operator/server.env" \
|
||||
"does not require or permit creation" \
|
||||
"getent passwd 10001" \
|
||||
"getent group 10001" \
|
||||
"-m 0750 /srv/thothii/operator" \
|
||||
"chmod 0600 /srv/thothii/operator/server.env" \
|
||||
"THT_THT_OUTPUT_DIRECTORY=/srv/thothii/operator/build-output" \
|
||||
"/srv/thothii" \
|
||||
"example operator root" \
|
||||
@@ -1268,10 +1270,14 @@ verify_server_guide() {
|
||||
"docker compose down --volumes" \
|
||||
"reverse-proxy-nginx.md" \
|
||||
"reverse-proxy-caddy.md"
|
||||
if ! grep -Eq '^sudo install -d -o 10001 -g thothii-ops -m 2750 /srv/thothii$' "$guide"; then
|
||||
if ! grep -Fq 'sudo install -d -o "$operator_uid" -g 10001 -m 0750 /srv/thothii' "$guide"; then
|
||||
echo "server installation guide does not set parent traversal boundary" >&2
|
||||
return 1
|
||||
fi
|
||||
if grep -Eq '(^|[[:space:]])(sudo[[:space:]]+)?(useradd|groupadd|usermod)([[:space:]]|$)|sudo[[:space:]]+-u[[:space:]]+thothii|thothii-ops' "$guide"; then
|
||||
echo "server installation guide creates or depends on a host identity" >&2
|
||||
return 1
|
||||
fi
|
||||
node - "$guide" <<'NODE'
|
||||
const fs = require("fs");
|
||||
const source = fs.readFileSync(process.argv[2], "utf8");
|
||||
|
||||
Reference in New Issue
Block a user