docs: add autonomous server installation guide

This commit is contained in:
2026-08-05 10:22:02 +02:00
parent df21046472
commit a707fb442c
7 changed files with 1056 additions and 53 deletions
+46 -45
View File
@@ -1,8 +1,9 @@
# Server workspace-registry installation
This is the production operator guide. The application image is read-only, secrets are mounted
read-only, and sessions use immutable Git-validated snapshots. Expose the application only behind
an authenticated same-origin reverse proxy; never publish the core port directly.
This is the production workspace-registry companion to [the autonomous Linux server guide](server.md).
The application image is read-only, secrets are mounted read-only, and sessions use immutable
Git-validated snapshots. Expose the application only behind an authenticated same-origin reverse
proxy; never publish the core port directly.
## Service account, storage, and firewall
@@ -142,52 +143,50 @@ The Git registry itself may still use SSH normally.
Use the repository's canonical `compose.yaml` plus `deploy/compose.server.yaml`; they always
start the mandatory `frontend` and `core` services. Do not copy or maintain a standalone
application Compose file. Review `deploy/workspaces/server-sessions.yaml.example`, materialize it
as a protected host file, and set its absolute `THT_SERVER_WORKSPACE_CONFIG` path. Copy the
bindings env example into the operator directory, then set absolute `PI_AUTH_FILE`,
`THT_SECRETS_FILE`, `THT_WORKSPACE_BINDINGS_ENV_FILE`, and connector `*_SOURCE` paths.
The same operator env must set
application Compose file. Copy `docs/install/examples/thothii-installation.server.yaml` to the
protected operator directory and preserve its required session-server overlay, exactly one Git
transport override, and generated connector-secret override.
Review `deploy/workspaces/server-sessions.yaml.example`, materialize it as a protected host file,
and set its absolute `THT_SERVER_WORKSPACE_CONFIG` path. Copy the bindings env example into the
operator directory, then set absolute `PI_AUTH_FILE`, `THT_SECRETS_FILE`,
`THT_WORKSPACE_BINDINGS_ENV_FILE`, and connector `*_SOURCE` paths. The same operator env must set
`THT_SESSION_DB_HOST`, `THT_SESSION_DB_NAME`, `THT_SESSION_RUNTIME_USER`,
`THT_SESSION_RUNTIME_PASSWORD_SOURCE`, and `THT_SESSION_CA_SOURCE`;
`deploy/compose.session-server.yaml.example` wires `postgres`, `verify-full`, and separate
runtime/CA Docker secret mount paths. This is the public server profile,
not a filesystem-session fallback. A Compose `.env` file is not a shell environment, so do not
import it into the maintenance shell. Explicitly export the non-secret source and bindings paths
before running the commands below.
runtime/CA secret targets under `/run/secrets`. This public server profile never falls back to
filesystem sessions. The path-only environment file is not shell code; do not source it.
Configure the portal proxy so the frontend and `/api` share one origin. It authenticates first and
clears client identity headers, carries auth-request claims over the private hop as
`X-Thoth-Trusted-*`, and lets the frontend proxy inject only the normalized
`X-Thoth-Principal-Issuer`, `X-Thoth-Principal-Subject`, `X-Thoth-Principal-Display-Name`, and
`X-Thoth-Is-Admin` claims expected by `AUTH_MODE=upstream`; it is the only public listener. Use
`deploy/nginx-authenticated-proxy.conf.example` as the forwarding contract.
From a trusted maintenance shell:
Generate the connector override, then use the installation-aware operator CLI. Building
`thothctl` requires only Docker and no Go knowledge. From a trusted maintenance shell:
```sh
export THT_SOURCE_ROOT=/absolute/path/to/ThothII
export THT_OPERATOR_ENV=/srv/thothii/operator/server.env
export THT_WORKSPACE_BINDINGS_ENV_FILE=/srv/thothii/operator/workspace-bindings.env
export THT_CONNECTOR_OVERRIDE=/srv/thothii/operator/connector-secrets.local.yaml
"$THT_SOURCE_ROOT/scripts/generate-connector-secrets-override.sh" --bindings-env "$THT_WORKSPACE_BINDINGS_ENV_FILE" --operator-env "$THT_OPERATOR_ENV" --output "$THT_CONNECTOR_OVERRIDE"
"$THT_SOURCE_ROOT/scripts/compose-with-preflight.sh" --env-file "$THT_OPERATOR_ENV" \
-f "$THT_SOURCE_ROOT/compose.yaml" -f "$THT_SOURCE_ROOT/deploy/compose.server.yaml" \
-f "$THT_SOURCE_ROOT/deploy/compose.session-server.yaml.example" \
-f "$THT_SOURCE_ROOT/deploy/compose.git-ssh.yaml" -f "$THT_CONNECTOR_OVERRIDE" up --build -d
"$THT_SOURCE_ROOT/scripts/compose-with-preflight.sh" --env-file "$THT_OPERATOR_ENV" \
-f "$THT_SOURCE_ROOT/compose.yaml" -f "$THT_SOURCE_ROOT/deploy/compose.server.yaml" \
-f "$THT_SOURCE_ROOT/deploy/compose.session-server.yaml.example" \
-f "$THT_SOURCE_ROOT/deploy/compose.git-ssh.yaml" -f "$THT_CONNECTOR_OVERRIDE" \
exec -T core curl --fail --silent http://127.0.0.1:8787/health
"$THT_SOURCE_ROOT/scripts/compose-with-preflight.sh" --env-file "$THT_OPERATOR_ENV" \
-f "$THT_SOURCE_ROOT/compose.yaml" -f "$THT_SOURCE_ROOT/deploy/compose.server.yaml" \
-f "$THT_SOURCE_ROOT/deploy/compose.session-server.yaml.example" \
-f "$THT_SOURCE_ROOT/deploy/compose.git-ssh.yaml" -f "$THT_CONNECTOR_OVERRIDE" \
exec -T core curl --fail --silent http://127.0.0.1:8787/workspace-registry/status
THT_SOURCE_ROOT=/srv/thothii/source/ThothII
THT_OPERATOR_ENV=/srv/thothii/operator/server.env
THT_WORKSPACE_BINDINGS_ENV_FILE=/srv/thothii/operator/workspace-bindings.env
THT_CONNECTOR_OVERRIDE=/srv/thothii/operator/connector-secrets.server.yaml
THTCTL=/srv/thothii/operator/thothctl
INSTALLATION=/srv/thothii/operator/thothii-installation.yaml
"$THT_SOURCE_ROOT/scripts/generate-connector-secrets-override.sh" \
--bindings-env "$THT_WORKSPACE_BINDINGS_ENV_FILE" \
--operator-env "$THT_OPERATOR_ENV" --output "$THT_CONNECTOR_OVERRIDE"
"$THTCTL" --installation "$INSTALLATION" update --check-only
"$THTCTL" --installation "$INSTALLATION" start
"$THTCTL" --installation "$INSTALLATION" status
"$THTCTL" --installation "$INSTALLATION" doctor
"$THTCTL" --installation "$INSTALLATION" pi doctor
"$THTCTL" --installation "$INSTALLATION" pi test
```
`/health` is liveness. Registry status verifies branch/head/degraded state and the active validated
snapshot; authenticated `/workspaces` verifies application access. A server with no active snapshot
is not ready for workspace sessions even if liveness succeeds.
Configure [Nginx](reverse-proxy-nginx.md) or [Caddy](reverse-proxy-caddy.md) so frontend and `/api`
share one TLS origin. The proxy authenticates first, clears client identity headers, and carries
only successful authentication claims over the private `X-Thoth-Trusted-*` hop. Forwarding claims
without authenticating the request is not an identity boundary.
`/health` is liveness. The authenticated Workspace Management page's registry status verifies
branch/head/degraded state and the active validated snapshot; its workspace listing verifies
application access. A server with no active snapshot is not ready for workspace sessions even if
liveness succeeds.
## Pull, publish, upgrade, backup, and recovery
@@ -196,10 +195,12 @@ browser-local. Publish takes a canonical diff, validates before commit, and push
lock. On `workspace_conflict`, pull, resolve the reviewed field-level draft, validate/test, and
publish; never edit `repo/` inside a running volume.
For upgrades, record active status/head, drain active Pi work, stop `core`, and take a
filesystem-consistent backup of `/srv/thothii/workspace-registry` plus `/srv/thothii/data`. Exclude
`/srv/thothii/secrets`. Render Compose, deploy the compatible image, verify health/status, then
resume proxy traffic.
For upgrades, record active status/head, finish active work, use the documented `thothctl pi update
--drain` transaction when Pi/core changes, and take a stopped, filesystem-consistent backup of
`/srv/thothii/workspace-registry` plus `/srv/thothii/data` and Pi state. Exclude
`/srv/thothii/secrets` from the ordinary archive. Validate the descriptor with `thothctl update
--check-only`, deploy the compatible image through `thothctl`, verify health/status, then resume
proxy traffic.
For legacy descriptor migration, use a temporary review clone and the legacy transformer with absolute paths.
Its schema-v1 output is `migration_required`; explicitly supply vector database/schema, collection