728 lines
32 KiB
Markdown
728 lines
32 KiB
Markdown
# Upgrade del server alla configurazione ThothII v2
|
|
|
|
Questo runbook è il passaggio di consegne per il Codex che opererà sul server remoto. Porta una
|
|
installazione precedente alla configurazione corrente di ThothII senza modificare Authentik o il
|
|
DWH esterno e senza cancellare lo stack precedente durante il primo cutover.
|
|
|
|
## Scelta preliminare: server autonomo oppure Omics
|
|
|
|
I passaggi di questo runbook che configurano OIDC diretto, gruppi e
|
|
`authentication.runtimeProjection` riguardano **ThothII autonomo**, da rendere
|
|
con `shell.mode: full`. Non applicarli all'integrazione Datamart Builder: Omics
|
|
usa **embedded/upstream** e mantiene il proprio accesso Authentik. Il core riceve
|
|
l'identità verificata dal proxy senza un secondo login né un secondo auth.yaml.
|
|
|
|
Prima dell'inventario identificare quale percorso è approvato. Per Omics seguire
|
|
[autenticazione upstream](../install/authentication-upstream.md) e
|
|
[rilascio coordinato dei due repository](shell-and-localization.md#preparare-il-rilascio-coordinato);
|
|
i gate di backup, isolamento, catalogo, storage e rollback di questo runbook
|
|
rimangono validi, ma non copiare i passi auth del percorso autonomo. Il passaggio
|
|
da issuer `portal` a un issuer OIDC differente non trasferisce automaticamente
|
|
la proprietà delle sessioni.
|
|
|
|
La procedura si applica a `main` quando contiene almeno il commit
|
|
`eba6148511675fc6a187aabb69a975adc5e3c542`. Deve essere presente anche questo file. Il commit
|
|
minimo è un controllo di sicurezza, non un invito a fermarsi a quella revisione: installare sempre
|
|
la `origin/main` approvata dall'operatore.
|
|
|
|
## Regole non negoziabili
|
|
|
|
- Per il rilascio Omics seguire la [consegna corrente a Codex sul server](server-codex-handoff.md).
|
|
Acquisire il branch dedicato da GitHub, verificare SHA e integrarlo con i
|
|
progressi del server; nessuna replica del repository è richiesta.
|
|
- Eseguire prima l'intero inventario in sola lettura e consegnarlo all'operatore.
|
|
- Non stampare mai password, token, chiavi private, cookie, file `.env` o contenuti dei Docker
|
|
secret. Nei report sono ammessi solo percorsi, nomi delle variabili e valori non segreti.
|
|
- Non usare `set -x`, credenziali dentro URL Git, `http.sslVerify=false`, `docker compose down -v`,
|
|
`docker volume rm`, `git reset --hard` o pulizie ricorsive.
|
|
- Non inventare l'indirizzo IP di `git.tylconsulting.it` e non aggiungerlo a `/etc/hosts` senza un
|
|
valore e un fingerprint TLS forniti dall'amministratore.
|
|
- Non sovrascrivere la vecchia configurazione. Creare una nuova installation ID e mantenere
|
|
configurazione, immagini, container e volumi precedenti fino all'accettazione scritta.
|
|
- Fermarsi a ogni **Gate operatore**. Il Codex prepara evidenze e comandi esatti; l'operatore
|
|
autorizza backup con segreti, fermo dello stack, cambio del reverse proxy e rimozioni.
|
|
- Il DWH resta read-only e diretto. Nessuna migrazione o DDL deve essere eseguita sul DWH.
|
|
|
|
## Cosa contiene la nuova release
|
|
|
|
Il confine informale “da auth in poi” non coincide con un singolo commit Git. OIDC/Authentik e il
|
|
CLI host `tht` fanno parte del contratto che il nuovo server deve rispettare, ma la tranche promossa
|
|
da `f5861526` a `eba61485` riguarda soprattutto:
|
|
|
|
- Database Management e il catalogo metadati isolato nel PostgreSQL interno `catalog-db`;
|
|
- sincronizzazione di tabelle, colonne e relazioni, generazione descrizioni e flag di sensibilità;
|
|
- Installation Model Catalog schema v2 come unica sorgente authored per modelli e provider;
|
|
- workspace schema v4 e proiezioni runtime generate;
|
|
- Qdrant per gli indici del workspace e Ollama per il solo modello di embedding;
|
|
- analisi locale deterministica delle colonne sensibili, con NER CPU opzionale;
|
|
- hardening delle proiezioni e stabilizzazione dei gate di test pre-deploy.
|
|
|
|
La topologia base attesa è:
|
|
|
|
| Servizio | Funzione | Persistenza |
|
|
| --- | --- | --- |
|
|
| `frontend` | UI React | nessuna persistenza propria |
|
|
| `core` | Fastify, Pi RPC e catalog API | volumi settings, Pi, registry, secrets e sessioni |
|
|
| `catalog-db` | PostgreSQL del catalogo metadati | volume `catalog-data` |
|
|
| `catalog-migrate` | migrazioni esplicite del catalogo | job one-shot, deve terminare con exit 0 |
|
|
| `qdrant` | indice vettoriale workspace | volume `qdrant-data` |
|
|
| `embedding` | Ollama interno per embedding | volume `embedding-models` |
|
|
| `embedding-model-init` | scarica/verifica il modello | job one-shot, deve terminare con exit 0 |
|
|
|
|
`catalog-db` non è il DWH. Non pubblica porte sull'host e usa credenziali runtime e migrator
|
|
separate. Ollama non controlla le password utente: nel percorso autonomo vale
|
|
OIDC tramite Authentik; nel percorso embedded Omics verifica l'accesso e il core
|
|
usa upstream.
|
|
|
|
Il PostgreSQL per le **sessioni** è un'altra funzione ancora. L'overlay
|
|
`deploy/compose.session-server.yaml.example` è esplicitamente opt-in: non abilitarlo durante questo
|
|
upgrade salvo decisione separata dell'operatore e presenza di un database sessioni già
|
|
provisionato. L'introduzione richiesta qui è soltanto `catalog-db`.
|
|
|
|
## Stato finale desiderato
|
|
|
|
Sono due repository distinti e non devono essere confusi:
|
|
|
|
| Uso | Remote atteso | Branch | Trasporto |
|
|
| --- | --- | --- | --- |
|
|
| codice applicativo ThothII, remote `origin` | `https://git.tylconsulting.it/mptyl/ThothII.git` | `main` | HTTPS |
|
|
| workspace PSD, `workspaceRepository` | `git@github.com:mptyl/tht-workspace-psd.git` | `main` | SSH |
|
|
|
|
Il riferimento locale approvato usa il workspace precedente e questi default di modello:
|
|
|
|
- sessione: `zai/glm-5.3`;
|
|
- generazione metadati: `zai/glm-5.3`;
|
|
- embedding: `ollama/qwen3-embedding:0.6b`, 1024 dimensioni.
|
|
|
|
Non copiare i file generati locali. La sorgente authored è il nuovo
|
|
`thothii-installation.yaml`; i file Pi, settings, catalogo runtime e Compose derivati vengono
|
|
rigenerati da `tht`.
|
|
|
|
## 0. Preparare le variabili di lavoro
|
|
|
|
Usare percorsi assoluti reali. I valori seguenti sono esempi e vanno sostituiti dopo l'inventario:
|
|
|
|
```bash
|
|
THTII_REPO=/absolute/path/to/ThothII
|
|
THTII_GITEA_URL=https://git.tylconsulting.it/mptyl/ThothII.git
|
|
THTII_MIN_COMMIT=eba6148511675fc6a187aabb69a975adc5e3c542
|
|
THTII_NEW_ID=psd-server-v2
|
|
THTII_WORKSPACE_REMOTE=git@github.com:mptyl/tht-workspace-psd.git
|
|
THTII_WORKSPACE_BRANCH=main
|
|
THTII_OLD_INSTALLATION=/absolute/path/to/legacy/thothii-installation.yaml
|
|
THTII_NEW_INSTALLATION=/absolute/path/to/ThothII/deploy/psd-server-v2/thothii-installation.yaml
|
|
THTII_NEW_ENV=/absolute/path/to/ThothII/deploy/psd-server-v2/operator.env
|
|
THTII_BACKUP_ARCHIVE=/protected/backups/thothii-pre-v2-YYYYMMDD.zip
|
|
THTII_SECRETS_FILE=/protected/thothii-v2/thothii.secrets
|
|
THTII_PI_AUTH_FILE=/protected/thothii-v2/pi-auth.json
|
|
THTII_CATALOG_RUNTIME_PASSWORD=/protected/thothii-v2/catalog-runtime-password
|
|
THTII_CATALOG_MIGRATOR_PASSWORD=/protected/thothii-v2/catalog-migrator-password
|
|
THTII_WORKSPACE_SSH_KEY=/protected/thothii-v2/workspace-deploy-key
|
|
THTII_WORKSPACE_KNOWN_HOSTS=/protected/thothii-v2/workspace-known-hosts
|
|
THTII_PUBLIC_URL=https://thothii.example.invalid
|
|
THTII_AUTH_ISSUER=https://authentik.example.invalid/application/o/thothii/
|
|
THTII_AUTH_CLIENT_ID=replace-with-approved-client-id
|
|
THTII_AUTHENTIK_URL=https://authentik.example.invalid
|
|
```
|
|
|
|
Definire inoltre, senza pubblicarne il contenuto:
|
|
|
|
- percorso del descriptor e comando di avvio della vecchia installazione;
|
|
- installation ID, Compose project, porte e reverse-proxy route correnti;
|
|
- percorsi protetti per secret bundle, Pi auth, chiave SSH GitHub e `known_hosts`;
|
|
- Public URL, issuer, client ID, URL Authentik e nomi dei gruppi;
|
|
- host, porta, database, utente e CA del binding diretto DWH;
|
|
- directory persistenti e directory backup della nuova installazione.
|
|
|
|
**Esito richiesto:** tutte le variabili indicano target esistenti o percorsi nuovi approvati; nessun
|
|
valore segreto compare nel terminale condiviso.
|
|
|
|
## 1. Inventario in sola lettura del server
|
|
|
|
Non fare ancora fetch, checkout, stop o modifica di remote. Dal checkout esistente raccogliere:
|
|
|
|
```bash
|
|
cd "$THTII_REPO"
|
|
git status --short --branch
|
|
git branch --show-current
|
|
git rev-parse HEAD
|
|
git remote -v
|
|
git tag --points-at HEAD
|
|
docker ps --format 'table {{.Names}}\t{{.Image}}\t{{.Status}}\t{{.Ports}}'
|
|
docker volume ls
|
|
df -h
|
|
tht version --json
|
|
```
|
|
|
|
Se `tht` non esiste ancora, registrarlo come assente senza installarlo in questo passo. Individuare
|
|
anche i container realmente appartenenti al vecchio stack, i loro image ID, i volumi montati e il
|
|
comando esatto che oggi li avvia. Non assumere nomi dai file della nuova release.
|
|
|
|
Raccogliere in forma redatta:
|
|
|
|
1. configurazione Authentik attuale: Public URL, issuer, client ID, callback, claim gruppi e gruppi
|
|
ruolo; non leggere in output client secret o API token;
|
|
2. binding DWH diretto: tipo `postgres_direct`, endpoint, database e utente; non stampare password;
|
|
3. remote, branch e revisione del vecchio workspace;
|
|
4. stato delle sessioni e directory dati che devono essere conservate;
|
|
5. spazio disponibile per immagini, volume Ollama, Qdrant, catalogo e backup.
|
|
|
|
Se il worktree è sporco o contiene configurazioni non committate, fermarsi: descrivere file e
|
|
proprietario delle modifiche, senza fare stash, reset o checkout.
|
|
|
|
**Esito richiesto:** un report redatto identifica vecchio stack, dati, immagini, rete, Authentik,
|
|
DWH e workspace; il worktree è pulito oppure l'operatore ha risolto esplicitamente le differenze.
|
|
|
|
## 2. Rendere Gitea raggiungibile e assegnarlo a `origin`
|
|
|
|
“Impostare Gitea come origin” e “risolvere il dominio Gitea” sono due operazioni diverse. Verificare
|
|
prima DNS e TLS:
|
|
|
|
```bash
|
|
getent hosts git.tylconsulting.it
|
|
curl --fail --silent --show-error --head https://git.tylconsulting.it/
|
|
```
|
|
|
|
Se `getent` non è disponibile, usare il resolver diagnostico già installato, per esempio
|
|
`dig +short git.tylconsulting.it`. Se il nome non risolve, fermarsi e chiedere la correzione DNS o
|
|
la mappatura IP ufficiale. Se TLS fallisce per una CA interna, installare la CA fornita
|
|
dall'amministratore nel trust store; non disabilitare la verifica.
|
|
|
|
Quando rete e TLS sono validi, registrare l'URL corrente di `origin` nel report e configurare Gitea:
|
|
|
|
```bash
|
|
cd "$THTII_REPO"
|
|
git remote get-url origin
|
|
git remote set-url origin "$THTII_GITEA_URL"
|
|
git remote -v
|
|
git ls-remote --exit-code origin refs/heads/main
|
|
```
|
|
|
|
Se `origin` non esiste, usare `git remote add origin "$THTII_GITEA_URL"` al posto di
|
|
`set-url`. Se serve autenticazione HTTPS, configurare il credential helper o il token nel secret
|
|
store del server; non inserire il token nell'URL o nella shell history.
|
|
|
|
**Esito richiesto:** `origin` mostra l'URL Gitea esatto per fetch e push e `ls-remote` restituisce
|
|
`refs/heads/main`. Non eseguire push dal server.
|
|
|
|
## 3. Fare fetch e aggiornare `main` senza perdere il rollback
|
|
|
|
Con worktree pulito:
|
|
|
|
```bash
|
|
cd "$THTII_REPO"
|
|
git fetch --prune origin
|
|
git branch rollback/server-pre-v2-YYYYMMDD HEAD
|
|
git switch main
|
|
git merge --ff-only origin/main
|
|
git merge-base --is-ancestor "$THTII_MIN_COMMIT" HEAD
|
|
test -f docs/operations/server-upgrade-gitea-workspace-v2.md
|
|
git status --short --branch
|
|
git rev-parse HEAD
|
|
```
|
|
|
|
Sostituire `YYYYMMDD` con la data reale e registrare hash precedente, rollback branch e nuovo hash.
|
|
Un merge non fast-forward, un file mancante o il fallimento di `merge-base` sono condizioni di stop.
|
|
Non risolvere divergenze con reset o rebase sul server.
|
|
|
|
**Esito richiesto:** `main` coincide con la `origin/main` approvata, contiene il commit minimo e il
|
|
runbook, e il rollback branch punta ancora al vecchio HEAD.
|
|
|
|
## 4. Salvare vecchia installazione, dati e immagini
|
|
|
|
### Gate operatore A — custodia del backup
|
|
|
|
Prima di leggere o archiviare secret, presentare l'elenco esatto dei file e volumi da salvare e
|
|
ottenere l'autorizzazione. Il backup deve stare fuori dal repository, su storage protetto, con
|
|
permessi restrittivi e checksum registrato separatamente.
|
|
|
|
Se il vecchio CLI espone `backup` e accetta il suo descriptor, usare il percorso esplicito:
|
|
|
|
```bash
|
|
umask 077
|
|
tht --installation "$THTII_OLD_INSTALLATION" backup \
|
|
--output "$THTII_BACKUP_ARCHIVE" --include-secrets --yes --drain
|
|
sha256sum "$THTII_BACKUP_ARCHIVE"
|
|
```
|
|
|
|
Se il vecchio formato non è accettato, usare la procedura di backup già approvata sul server. Non
|
|
improvvisare un archivio ricorsivo di `/srv` o della root. Il backup deve includere almeno:
|
|
|
|
- descriptor, env non segreto, configurazione auth canonica, secret bundle, Pi auth e certificati;
|
|
- repository/configurazione workspace precedente e sessioni persistite;
|
|
- inventario di container, reti, volumi, mount, image name e image ID;
|
|
- configurazione del reverse proxy necessaria a ripristinare il servizio.
|
|
|
|
Conservare anche le immagini effettivamente in uso: assegnare tag di rollback agli image ID
|
|
espliciti identificati al passo 1 oppure salvarli in un archivio Docker protetto. Non selezionare
|
|
immagini tramite glob. Il nuovo build può riutilizzare gli stessi tag mentre i container vecchi
|
|
continuano a funzionare.
|
|
|
|
Il backup integrato va considerato sufficiente per un volume solo se il suo manifest lo elenca e la
|
|
procedura di restore è stata verificata. In questa migrazione il nuovo `catalog-data` nasce vuoto;
|
|
non esiste quindi un vecchio catalogo da importare. Per upgrade successivi, il catalogo PostgreSQL
|
|
dovrà avere un dump consistente esplicito se il backup corrente non lo comprende.
|
|
|
|
**Esito richiesto:** archivio, checksum, immagini di rollback e comando di ripristino sono
|
|
verificati; nessun vecchio container o volume è stato eliminato.
|
|
|
|
## 5. Installare il CLI corrente e creare una installation v2 affiancata
|
|
|
|
Dal nuovo checkout:
|
|
|
|
```bash
|
|
cd "$THTII_REPO"
|
|
./scripts/install-tht.sh
|
|
tht version --json
|
|
```
|
|
|
|
Preparare fuori dal repository file protetti distinti per:
|
|
|
|
- secret bundle applicativo;
|
|
- Pi auth;
|
|
- password runtime e migrator di `catalog-db`;
|
|
- chiave privata e `known_hosts` del repository workspace GitHub.
|
|
|
|
Le due password del catalogo devono essere casuali, non vuote e diverse. I file devono essere
|
|
leggibili solo dall'operatore autorizzato. Nel secret bundle servono i riferimenti approvati per i
|
|
provider (`ZAI_API_KEY` e, se mantenuto, `DEEPSEEK_API_KEY`) e per Authentik
|
|
(`THT_OIDC_CLIENT_SECRET`, `THT_AUTHENTIK_API_TOKEN`), mai i valori nel descriptor YAML.
|
|
|
|
Verificare l'accesso SSH al workspace con la chiave e il file `known_hosts` approvati. Non costruire
|
|
`known_hosts` accettando alla cieca il primo fingerprint restituito dalla rete:
|
|
|
|
```bash
|
|
ssh-keygen -F github.com -f "$THTII_WORKSPACE_KNOWN_HOSTS"
|
|
GIT_SSH_COMMAND="ssh -i $THTII_WORKSPACE_SSH_KEY -o IdentitiesOnly=yes -o UserKnownHostsFile=$THTII_WORKSPACE_KNOWN_HOSTS" \
|
|
git ls-remote --exit-code "$THTII_WORKSPACE_REMOTE" refs/heads/main
|
|
```
|
|
|
|
Creare la configurazione server in modalità `configure-only`; il profilo server richiede root per
|
|
creare la proiezione auth con UID/GID del container. La versione corrente di `setup` non scrive
|
|
ancora i due path catalogo nell'env generato: passarli all'ambiente del comando per validare
|
|
Compose, quindi aggiungerli subito a `operator.env` nel passo successivo.
|
|
|
|
```bash
|
|
cd "$THTII_REPO"
|
|
sudo env \
|
|
THT_CATALOG_RUNTIME_PASSWORD_SOURCE="$THTII_CATALOG_RUNTIME_PASSWORD" \
|
|
THT_CATALOG_MIGRATOR_PASSWORD_SOURCE="$THTII_CATALOG_MIGRATOR_PASSWORD" \
|
|
tht setup --configure-only \
|
|
--installation-id "$THTII_NEW_ID" \
|
|
--profile server \
|
|
--workspace-remote "$THTII_WORKSPACE_REMOTE" \
|
|
--workspace-branch "$THTII_WORKSPACE_BRANCH" \
|
|
--workspace-access ssh \
|
|
--secrets-file "$THTII_SECRETS_FILE" \
|
|
--pi-auth-file "$THTII_PI_AUTH_FILE" \
|
|
--git-ssh-key-file "$THTII_WORKSPACE_SSH_KEY" \
|
|
--git-known-hosts-file "$THTII_WORKSPACE_KNOWN_HOSTS" \
|
|
--auth-mode oidc \
|
|
--auth-public-url "$THTII_PUBLIC_URL" \
|
|
--auth-issuer "$THTII_AUTH_ISSUER" \
|
|
--auth-client-id "$THTII_AUTH_CLIENT_ID" \
|
|
--auth-authentik-base-url "$THTII_AUTHENTIK_URL" \
|
|
--auth-user-group 'TOT Users' \
|
|
--auth-admin-group 'TOT Admin'
|
|
```
|
|
|
|
Se sul server i gruppi hanno nomi diversi, usare i nomi verificati al passo 1. Non indovinarli.
|
|
Registrare il descriptor prodotto, normalmente
|
|
`deploy/<installation-id>/thothii-installation.yaml`, e usarlo esplicitamente in ogni comando
|
|
successivo. Aggiungere all'`operator.env` generato, usando un editor che non stampi i valori:
|
|
|
|
```dotenv
|
|
THT_CATALOG_RUNTIME_PASSWORD_SOURCE=/protected/thothii-v2/catalog-runtime-password
|
|
THT_CATALOG_MIGRATOR_PASSWORD_SOURCE=/protected/thothii-v2/catalog-migrator-password
|
|
THT_CATALOG_SYNC_TIMEOUT_MS=600000
|
|
```
|
|
|
|
I valori a destra devono essere i percorsi assoluti reali preparati sopra. Verificare che
|
|
`THTII_NEW_INSTALLATION` e `THTII_NEW_ENV` corrispondano ai file appena creati.
|
|
|
|
**Esito richiesto:** esistono descriptor schema v2, env operatore e directory auth canonica/runtime
|
|
della nuova installation; lo stack precedente è ancora in esecuzione.
|
|
|
|
## 6. Allineare il descriptor alla configurazione locale approvata
|
|
|
|
Il `setup` genera un catalogo modelli valido ma generico. Sostituire il suo blocco `modelCatalog`
|
|
con questo riferimento corrente, soltanto dopo aver verificato che il server raggiunga gli endpoint
|
|
necessari:
|
|
|
|
```yaml
|
|
modelCatalog:
|
|
defaults:
|
|
session: zai/glm-5.3
|
|
metadataGeneration: zai/glm-5.3
|
|
embedding:
|
|
id: ollama/qwen3-embedding:0.6b
|
|
dimensions: 1024
|
|
providers:
|
|
deepseek:
|
|
authentication:
|
|
mode: pi_auth
|
|
session:
|
|
mode: pi_builtin
|
|
models:
|
|
deepseek-v4-pro:
|
|
session: {}
|
|
deepseek-v4-flash:
|
|
session: {}
|
|
deepseek-metadata:
|
|
authentication:
|
|
mode: secret_env
|
|
apiKeyEnv: DEEPSEEK_API_KEY
|
|
metadataGeneration:
|
|
litellmProvider: deepseek
|
|
models:
|
|
deepseek-v4-pro:
|
|
label: DeepSeek V4 Pro
|
|
metadataGeneration: {}
|
|
deepseek-v4-flash:
|
|
label: DeepSeek V4 Flash
|
|
metadataGeneration: {}
|
|
zai:
|
|
endpoint:
|
|
baseUrl: https://api.z.ai/api/coding/paas/v4
|
|
authentication:
|
|
mode: secret_env
|
|
apiKeyEnv: ZAI_API_KEY
|
|
session:
|
|
mode: openai_compatible
|
|
metadataGeneration:
|
|
litellmProvider: openai
|
|
models:
|
|
glm-5.3:
|
|
label: GLM 5.3
|
|
session:
|
|
reasoning: true
|
|
contextWindow: 200000
|
|
maxTokens: 131072
|
|
metadataGeneration: {}
|
|
local-qwen:
|
|
endpoint:
|
|
baseUrl: https://ml-aritmolab.policlinicosandonato.it/v1
|
|
authentication:
|
|
mode: none
|
|
session:
|
|
mode: openai_compatible
|
|
metadataGeneration:
|
|
litellmProvider: openai
|
|
models:
|
|
qwen3.6-35b-a3b:
|
|
label: AritmoLab Qwen 3.6 35B A3B
|
|
session:
|
|
reasoning: false
|
|
input: [text]
|
|
cost: {input: 0, output: 0, cacheRead: 0, cacheWrite: 0}
|
|
contextWindow: 131072
|
|
maxTokens: 16384
|
|
compatibility:
|
|
supportsDeveloperRole: false
|
|
supportsReasoningEffort: false
|
|
supportsStore: false
|
|
maxTokensField: max_tokens
|
|
metadataGeneration:
|
|
disableThinking: true
|
|
```
|
|
|
|
Controllare inoltre:
|
|
|
|
- `profile: server` e `projectDirectory` uguale al checkout reale;
|
|
- `workspaceRepository` uguale alla riga PSD della tabella iniziale;
|
|
- `authentication.configDirectory` nella nuova directory canonica;
|
|
- `authentication.runtimeProjection` in una directory separata, con `uid: 10001` e `gid: 10001`;
|
|
- un solo override Git SSH;
|
|
- nessun riferimento a vecchi `deploy/pi/models.json`, `deploy/pi/settings.json` o model metadata
|
|
nel workspace;
|
|
- nessun overlay session PostgreSQL salvo approvazione separata.
|
|
|
|
La proiezione Compose dell'auth runtime è automatica: non aggiungere manualmente
|
|
`deploy/compose.auth-runtime-projection.yaml` agli override. Se un endpoint di modello non è
|
|
raggiungibile dal server, fermarsi e chiedere quale provider mantenere; non cambiare silenziosamente
|
|
i default.
|
|
|
|
Aggiornare l'env operatore usando `deploy/env/server.env.example` come checklist. Devono essere
|
|
valorizzati almeno i percorsi `THT_CATALOG_RUNTIME_PASSWORD_SOURCE`,
|
|
`THT_CATALOG_MIGRATOR_PASSWORD_SOURCE`, `THT_DATA_ROOT`, `THT_PI_STATE_ROOT`,
|
|
`THT_WORKSPACE_REGISTRY_ROOT`, `THT_BACKUP_ROOT`, le sorgenti auth/Git e le porte. Le directory
|
|
persistenti della nuova installation non devono coincidere accidentalmente con quelle legacy.
|
|
|
|
**Esito richiesto:** descriptor e env contengono soltanto configurazione non segreta, puntano ai
|
|
secret file protetti e descrivono esattamente workspace, auth e modelli approvati.
|
|
|
|
## 7. Verificare Authentik senza ricrearlo
|
|
|
|
Se Public URL resta invariato, non creare una seconda applicazione/provider in Authentik. Il
|
|
provider esistente deve avere:
|
|
|
|
- callback esatta `<PUBLIC_URL>/api/auth/oidc/callback`;
|
|
- scope `openid profile email`;
|
|
- claim `groups` non vuoto come array JSON;
|
|
- gruppi applicativi attesi, normalmente `TOT Users` e `TOT Admin`;
|
|
- token del service account con sola lettura dei gruppi.
|
|
|
|
Configurare o rigenerare soltanto la configurazione canonica della nuova installation:
|
|
|
|
```bash
|
|
sudo tht --installation "$THTII_NEW_INSTALLATION" auth configure \
|
|
--mode oidc \
|
|
--public-url "$THTII_PUBLIC_URL" \
|
|
--issuer "$THTII_AUTH_ISSUER" \
|
|
--client-id "$THTII_AUTH_CLIENT_ID" \
|
|
--authentik-base-url "$THTII_AUTHENTIK_URL" \
|
|
--user-group 'TOT Users' \
|
|
--admin-group 'TOT Admin'
|
|
tht --installation "$THTII_NEW_INSTALLATION" auth status --json
|
|
```
|
|
|
|
Il comando non riceve secret come argomenti: li risolve dai riferimenti nel secret bundle. La nuova
|
|
directory `auth-state` può partire vuota. Le vecchie sessioni browser non devono essere migrate e
|
|
gli utenti dovranno autenticarsi di nuovo dopo il cutover.
|
|
|
|
**Esito richiesto:** lo status redatto indica `mode: oidc`, URL e gruppi corretti; nessun secret è
|
|
presente in YAML, argomenti, log o report.
|
|
|
|
## 8. Preflight e preparazione dei servizi interni
|
|
|
|
`tht start` rigenera le proiezioni e avvia i servizi, ma non esegue il job esplicito
|
|
`catalog-migrate`. Preparare quindi immagini e servizi interni con la stessa identità Compose della
|
|
nuova installation mentre il vecchio frontend/core sono ancora attivi.
|
|
|
|
Per prima cosa validare il descriptor e il render Compose:
|
|
|
|
```bash
|
|
tht --installation "$THTII_NEW_INSTALLATION" update --check-only
|
|
```
|
|
|
|
Questo comando carica e valida il descriptor; dopo la modifica del `modelCatalog`, la proiezione
|
|
generata da `setup` resta intenzionalmente precedente fino a `tht start`. Non usare `doctor` come
|
|
gate in questo momento: i servizi sono fermi e il suo controllo di drift deve ancora fallire. Il
|
|
gate completo viene eseguito al passo 10, dopo che `start` ha rigenerato la proiezione.
|
|
|
|
Calcolare il Compose project name con la stessa regola del CLI e costruire l'array dei file. Questo
|
|
blocco è esatto per il descriptor atteso, che ha il solo override Git SSH. Se nel descriptor ci sono
|
|
altri override approvati, inserirli nello stesso ordine subito dopo `compose.git-ssh.yaml`; non
|
|
ometterli e non aggiungere l'overlay sessioni per comodità.
|
|
|
|
```bash
|
|
THTII_NEW_INSTALLATION=$(realpath "$THTII_NEW_INSTALLATION")
|
|
THTII_INSTALL_DIR=$(dirname "$THTII_NEW_INSTALLATION")
|
|
THTII_COMPOSE_PROJECT="thothii-$(printf '%s' "$THTII_NEW_INSTALLATION" | sha256sum | cut -c1-12)"
|
|
THTII_COMPOSE=(
|
|
docker compose
|
|
--project-name "$THTII_COMPOSE_PROJECT"
|
|
--project-directory "$THTII_REPO"
|
|
--env-file "$THTII_NEW_ENV"
|
|
-f "$THTII_REPO/compose.yaml"
|
|
-f "$THTII_REPO/deploy/compose.server.yaml"
|
|
-f "$THTII_REPO/deploy/compose.git-ssh.yaml"
|
|
-f "$THTII_INSTALL_DIR/generated/compose.models.yaml"
|
|
-f "$THTII_REPO/deploy/compose.auth-runtime-projection.yaml"
|
|
)
|
|
"${THTII_COMPOSE[@]}" config --quiet
|
|
```
|
|
|
|
Non stampare il render completo. Costruire le immagini e avviare soltanto i servizi interni privi
|
|
di porte host:
|
|
|
|
```bash
|
|
"${THTII_COMPOSE[@]}" build core frontend
|
|
"${THTII_COMPOSE[@]}" up --detach catalog-db qdrant embedding
|
|
"${THTII_COMPOSE[@]}" run --rm catalog-migrate
|
|
"${THTII_COMPOSE[@]}" run --rm embedding-model-init
|
|
"${THTII_COMPOSE[@]}" ps --all
|
|
```
|
|
|
|
Il comando `catalog-migrate` deve terminare con exit 0 prima che `core` venga avviato. Anche
|
|
`embedding-model-init` deve terminare con exit 0 e lasciare il modello nel volume della nuova
|
|
installation. Questi comandi non pubblicano la nuova applicazione e non toccano i volumi legacy.
|
|
|
|
Confermare inoltre che il server abbia accesso in uscita necessario al primo pull del modello
|
|
Ollama e spazio sufficiente per `embedding-models`. Qdrant e `catalog-db` devono restare sulla rete
|
|
Compose privata, senza porte host pubblicate.
|
|
|
|
L'overlay NER `deploy/compose.sensitivity-ner.yaml` non è richiesto per il primo avvio. La policy
|
|
deterministica funziona senza NER. Abilitare il modello CPU soltanto con la procedura e i gate in
|
|
[Analisi locale della sensibilità](sensitivity-analysis.md).
|
|
|
|
**Esito richiesto:** render Compose valido, immagini costruite, `catalog-db` healthy, migrazione exit
|
|
0, Qdrant/Ollama healthy e modello embedding inizializzato; `core` e `frontend` nuovi sono ancora
|
|
fermi.
|
|
|
|
## 9. Cutover controllato
|
|
|
|
### Gate operatore B — finestra di manutenzione
|
|
|
|
Presentare prima:
|
|
|
|
- hash release, descriptor nuovo e risultato del preflight;
|
|
- comando esatto per fermare e riavviare il vecchio stack;
|
|
- comando di rollback, image ID conservati e durata stimata;
|
|
- porte e route del reverse proxy che resteranno invariate o verranno cambiate.
|
|
|
|
Dopo approvazione, bloccare nuove attività applicative e fermare solo lo stack legacy con il comando
|
|
registrato al passo 1. Non rimuoverne container o volumi. Avviare quindi la nuova installation:
|
|
|
|
```bash
|
|
tht --installation "$THTII_NEW_INSTALLATION" start
|
|
```
|
|
|
|
Il primo avvio deve:
|
|
|
|
1. rigenerare le proiezioni del model catalog aggiornato;
|
|
2. riutilizzare le immagini costruite e il catalogo già migrato al passo 8;
|
|
3. confermare healthy `catalog-db` e Qdrant;
|
|
4. avviare Ollama ed eseguire/verificare `embedding-model-init` per
|
|
`qwen3-embedding:0.6b`;
|
|
5. avviare `core` soltanto dopo le dipendenze richieste;
|
|
6. avviare `frontend` sulla bind address prevista per il reverse proxy.
|
|
|
|
Non interrompere il primo pull perché è lento se log e avanzamento restano regolari. In caso di
|
|
errore, raccogliere soltanto i log sanitizzati:
|
|
|
|
```bash
|
|
tht --installation "$THTII_NEW_INSTALLATION" status
|
|
tht --installation "$THTII_NEW_INSTALLATION" logs
|
|
```
|
|
|
|
`embedding-model-init` è one-shot: `exited (0)` è lo stato corretto, non un guasto. Il job
|
|
`catalog-migrate` è stato eseguito con `run --rm`, quindi fa fede l'exit 0 registrato al passo 8.
|
|
Qualsiasi exit diverso da zero blocca il cutover.
|
|
|
|
**Esito richiesto:** servizi persistenti healthy/running, job one-shot terminati con exit 0 e
|
|
reverse proxy diretto alla nuova UI; i volumi legacy esistono ancora.
|
|
|
|
## 10. Verificare autenticazione e runtime
|
|
|
|
Eseguire:
|
|
|
|
```bash
|
|
tht --installation "$THTII_NEW_INSTALLATION" status
|
|
tht --installation "$THTII_NEW_INSTALLATION" doctor --json
|
|
tht --installation "$THTII_NEW_INSTALLATION" auth status --json
|
|
tht --installation "$THTII_NEW_INSTALLATION" auth check
|
|
tht --installation "$THTII_NEW_INSTALLATION" pi test
|
|
```
|
|
|
|
Dal browser verificare:
|
|
|
|
1. redirect ad Authentik e ritorno alla callback corretta;
|
|
2. login di un membro `TOT Users`;
|
|
3. accesso amministrativo soltanto a un membro `TOT Admin`;
|
|
4. logout e nuova autenticazione;
|
|
5. assenza di loop OIDC, cookie error o `502` del reverse proxy.
|
|
|
|
È previsto che le sessioni browser precedenti non siano più valide. Non è previsto modificare
|
|
issuer, client o gruppi per aggirare un errore: diagnosticare prima callback, claim e secret refs.
|
|
|
|
**Esito richiesto:** `doctor`, `auth check` e `pi test` passano e i due ruoli Authentik sono mappati
|
|
correttamente.
|
|
|
|
## 11. Ripuntare e materializzare il workspace PSD
|
|
|
|
Il vecchio workspace runtime non è una sorgente da copiare. La nuova installation deve clonare e
|
|
validare il repository Git approvato:
|
|
|
|
```text
|
|
git@github.com:mptyl/tht-workspace-psd.git, branch main, access ssh
|
|
```
|
|
|
|
Nella UI amministrativa, nell'ordine:
|
|
|
|
1. usare **Update workspace repository** per fetch/clone e validazione;
|
|
2. selezionare il workspace PSD; l'ID atteso è `psd-clinical`, ma confermarlo dal catalogo
|
|
`thoth-workspaces.yaml` anziché forzarlo;
|
|
3. usare **Validate workspace source**;
|
|
4. aprire **Database Management** e creare/aggiornare il database del workspace;
|
|
5. configurare il binding `postgres_direct` con gli stessi endpoint, ruolo read-only e CA già
|
|
approvati sul server; reinserire la password nel secret store write-only, non nel repository;
|
|
6. eseguire **Test workspace connections**;
|
|
7. eseguire una sincronizzazione completa dello schema nel nuovo catalogo;
|
|
8. selezionare quel workspace come workspace globale dell'installation.
|
|
|
|
Poi verificare e materializzare con il CLI:
|
|
|
|
```bash
|
|
tht --installation "$THTII_NEW_INSTALLATION" workspace inspect \
|
|
--workspace psd-clinical --json
|
|
tht --installation "$THTII_NEW_INSTALLATION" workspace preprocess run \
|
|
--workspace psd-clinical --json
|
|
```
|
|
|
|
Se il preprocessing fallisce, correggere il Catalog o la configurazione e rilanciare lo stesso
|
|
comando dall'inizio: non esistono resume o rollback. Il comando completo materializza LSH e vettori
|
|
di schema dal Metadata Catalog e ricostruisce la slice Evidence. Le nuove sessioni pinzano la
|
|
revisione Git attiva del workspace.
|
|
|
|
Non copiare nel nuovo descriptor i legacy `harness/workspaces/*.yaml` come catalogo authored e non
|
|
trasferire vecchi indici vettoriali incompatibili. Il repository workspace schema v4 definisce
|
|
identità ed Evidence; database, metadati, binding, segreti e selezione attiva restano locali
|
|
all'installation.
|
|
|
|
**Esito richiesto:** `workspace inspect` mostra repository, branch e revisione PSD corretti; test
|
|
DWH diretto, schema sync e preprocess completo terminano con successo; Qdrant contiene la nuova
|
|
generazione Evidence.
|
|
|
|
## 12. Accettazione finale
|
|
|
|
Prima di dichiarare concluso l'upgrade, consegnare una checklist con evidenze redatte:
|
|
|
|
- `git rev-parse HEAD` uguale alla release approvata e worktree pulito;
|
|
- `origin` uguale al Gitea ThothII e workspace remote uguale al GitHub PSD;
|
|
- `tht doctor --json`, `auth check` e `pi test` senza errori;
|
|
- `catalog-db`, Qdrant, Ollama, core e frontend healthy;
|
|
- `catalog-migrate` ed `embedding-model-init` terminati con exit 0;
|
|
- login Authentik utente/admin verificato;
|
|
- binding DWH diretto read-only verificato;
|
|
- catalogo sincronizzato e preprocess workspace completato;
|
|
- una nuova sessione di prova crea artifact e usa la revisione workspace attiva;
|
|
- backup, checksum, rollback branch e immagini legacy ancora disponibili;
|
|
- nessun secret aggiunto al repository o ai log condivisi.
|
|
|
|
### Gate operatore C — fine osservazione
|
|
|
|
Non rimuovere ancora stack, immagini, volumi o backup legacy. La loro eliminazione è un'attività
|
|
successiva e distruttiva, autorizzata soltanto dopo un periodo di osservazione e un backup completo
|
|
della nuova installazione che includa esplicitamente anche il catalogo PostgreSQL.
|
|
|
|
## Rollback
|
|
|
|
Eseguire il rollback se il nuovo stack non diventa healthy, Authentik non completa il login, il DWH
|
|
diretto non passa il test o il workspace non si materializza entro la finestra approvata.
|
|
|
|
1. Raccogliere `status` e log sanitizzati della nuova installation.
|
|
2. Fermarla senza volumi:
|
|
|
|
```bash
|
|
tht --installation "$THTII_NEW_INSTALLATION" stop
|
|
```
|
|
|
|
3. Ripristinare i tag immagine legacy dagli image ID/tag conservati se il nuovo build li ha
|
|
sostituiti.
|
|
4. Riportare il checkout al rollback branch soltanto se il comando legacy legge file dal checkout:
|
|
|
|
```bash
|
|
cd "$THTII_REPO"
|
|
git switch rollback/server-pre-v2-YYYYMMDD
|
|
```
|
|
|
|
5. Riavviare il vecchio stack con il comando esatto registrato al passo 1.
|
|
6. Ripristinare la route reverse proxy precedente se era cambiata.
|
|
7. Verificare vecchia UI, Authentik e DWH; non montare i nuovi volumi nel vecchio stack.
|
|
8. Lasciare intatti i volumi della nuova installation per l'analisi post-mortem.
|
|
|
|
**Esito richiesto:** il servizio precedente è nuovamente disponibile con i suoi dati originali e
|
|
la nuova installazione è ferma ma ispezionabile.
|
|
|
|
## Riferimenti operativi
|
|
|
|
- [Installazione e primo avvio](../install/first-start.md)
|
|
- [Authentik](../install/authentik.md)
|
|
- [OIDC generico](../install/authentication-oidc.md)
|
|
- [Operazioni workspace](workspaces.md)
|
|
- [Configurazione dei modelli Pi](../general/pi-configuration.md)
|
|
- [Contesti Docker](../installazione-docker-4-contesti.md)
|
|
- [Database Management](database-management.md)
|
|
- [Analisi locale della sensibilità](sensitivity-analysis.md)
|