20 KiB
Installazione Docker nei quattro contesti operativi
Questa guida descrive l'installazione di ThothII usando le due immagini applicative:
thothii-core: backend Fastify, harnessthte Pi;thothii-frontend: frontend React servito da nginx.
I database e i servizi di embedding restano esterni, salvo il profilo opzionale
local-vector, che avvia un PostgreSQL/pgvector nello stesso progetto Compose.
Prerequisiti comuni
Installare Docker Engine/Compose v2 sul server oppure Docker Desktop su macOS/Windows. La macchina deve poter raggiungere:
- il DWH/DWH REST, se usato dal workspace;
- il vector DB REST o pgvector;
- il servizio di embedding (Ollama o endpoint compatibile);
- il provider del modello Pi, se si usano provider hosted.
Clonare il repository e lavorare dalla sua radice:
git clone <URL-REPOSITORY> ThothII
cd ThothII
cp deploy/env.example deploy/.env
mkdir -p deploy/secrets deploy/workspaces
chmod 600 deploy/.env
La configurazione installativa rimane tutta dentro ThothII/:
ThothII/
├── deploy/.env # riferimenti ai file e valori non riservati
├── deploy/secrets/ # file secret locali, esclusi da Git
└── deploy/workspaces/ # workspace YAML senza password/token
I soli file da creare o modificare dopo il clone sono questi:
File interno a ThothII/ |
Operazione | Contenuto |
|---|---|---|
deploy/.env |
copiare da deploy/env.example e modificare |
endpoint, nomi, profili e percorsi relativi dei secret |
deploy/secrets/dwh-api-key |
creare | una API key DWH, una riga/valore |
deploy/secrets/dwh_password |
creare solo con postgres_direct |
password dell'utente DWH diretto |
deploy/secrets/vector-reader-api-key |
creare | chiave reader vector REST, se usata |
deploy/secrets/vector-writer-api-key |
creare | chiave writer vector REST, se usata |
deploy/secrets/model-api-key |
creare | chiave del provider Pi a chiave singola |
deploy/secrets/ca-chain.pem |
creare, se serve TLS privato | catena CA PEM pubblica |
deploy/secrets/vector_bootstrap_password |
creare con local-vector |
password bootstrap pgvector |
deploy/secrets/vector_migrator_password |
creare con local-vector |
password migrator |
deploy/secrets/vector_reader_password |
creare con local-vector |
password reader pgvector |
deploy/secrets/vector_writer_password |
creare con local-vector |
password writer pgvector |
deploy/workspaces/<nome>.yaml |
copiare/modificare | adapter, endpoint non riservati, roots e sorgente Evidence |
Non occorre creare file in /etc, /opt, ~/.thothii o in altre directory esterne per seguire
questa guida. I file secret sono ignorati da Git tramite .gitignore, ma restano disponibili a
Docker perché Compose li legge dal progetto locale.
I secret non devono essere inseriti in deploy/.env, nei file workspace o negli URL.
deploy/.env contiene solo host, porte, nomi di database e percorsi relativi come
THT_DWH_API_KEY_SECRET_FILE=deploy/secrets/dwh-api-key. Un workspace YAML deve contenere al
massimo un riferimento come password_file, mai la password stessa; gli URL non devono
contenere user, password o token. Dopo aver modificato deploy/.env, caricarlo nella shell da
cui si eseguono i comandi Docker:
set -a
. ./deploy/.env
set +a
Le tre righe fanno questo:
set -adice alla shell di esportare automaticamente tutte le variabili assegnate da questo momento in poi;. ./deploy/.env(il punto iniziale è l'abbreviazione disource) legge ed esegue il file nella shell corrente. Le variabili diventano quindi disponibili adocker composee ai processi figli, senza aprire una nuova shell;set +adisattiva l'esportazione automatica per evitare che assegnazioni successive vengano esportate accidentalmente.
Esempio: se deploy/.env contiene
THT_MODEL_API_KEY_SECRET_FILE=deploy/secrets/model-api-key
dopo il comando source la shell possiede THT_MODEL_API_KEY_SECRET_FILE e Compose può usare
quel percorso per leggere il secret file. Il valore della API key non viene caricato in
deploy/.env: resta nel file separato sotto deploy/secrets/.
La forma equivalente, senza modificare l'ambiente della shell, è passare il file direttamente a Compose:
docker compose --env-file deploy/.env -f compose.yaml -f deploy/compose.production.yaml \
--profile external up --build --wait
Non usare source/. con file ricevuti da terzi senza averne verificato il contenuto: un file
.env sourced è codice shell, non un semplice formato dati. In questa guida il file viene creato
localmente da deploy/env.example e contiene solo assegnazioni di configurazione e percorsi.
Per i comandi successivi si può quindi scegliere una sola delle due modalità: fare source
una volta all'inizio della sessione, oppure aggiungere --env-file deploy/.env a ogni comando
docker compose.
Salvare invece ogni credenziale in un file separato dentro ThothII/deploy/secrets/. Sul sistema
host il file deve essere leggibile solo dall'utente/servizio che esegue Docker (0400 se solo
lettura, 0600 se l'operatore deve poterlo aggiornare). Compose lo monta poi nel container come secret
read-only sotto /run/secrets. Il 0444 osservabile dentro il container è normale per il
mount dei secret Docker e non rende il file host pubblico: il file host resta protetto e il
container riceve una copia/mount temporaneo non scrivibile.
Il modello Pi usa THT_MODEL_API_KEY_SECRET_FILE per i provider autenticati con una singola
chiave. Provider composti (Bedrock, Azure OpenAI Responses, Cloudflare Workers AI/Gateway)
sono rifiutati esplicitamente: richiedono un bundle di credenziali non rappresentabile da un
solo file.
1. Server applicativo insieme a DWH e vector DB
Questo profilo è adatto quando ThothII, il database relazionale e il vector DB sono nella
stessa rete/server, ma i database non devono necessariamente essere containerizzati da
ThothII. Si usa il profilo external; gli endpoint possono essere nomi DNS, IP privati o
nomi di servizio della rete Docker.
Configurazione
Prima si definiscono in ThothII/deploy/.env i percorsi host nelle variabili
THT_*_SECRET_FILE:
THT_DWH_API_KEY_SECRET_FILE=deploy/secrets/dwh-api-key
THT_VEC_API_KEY_SECRET_FILE=deploy/secrets/vector-reader-api-key
THT_VEC_WRITE_API_KEY_SECRET_FILE=deploy/secrets/vector-writer-api-key
THT_MODEL_API_KEY_SECRET_FILE=deploy/secrets/model-api-key
THT_CA_SECRET_FILE=deploy/secrets/ca-chain.pem
Queste righe vanno scritte nel file interno ThothII/deploy/.env, non eseguite solo
temporaneamente nella shell.
Nella forma documentale, i cinque target sono indicati come
<THT_DWH_API_KEY_SECRET_FILE>, <THT_VEC_API_KEY_SECRET_FILE>,
<THT_VEC_WRITE_API_KEY_SECRET_FILE>, <THT_MODEL_API_KEY_SECRET_FILE> e
<THT_CA_SECRET_FILE>. Le parentesi angolari sono segnaposto e non vanno digitate nella
shell: nei comandi eseguibili si usano le variabili tra virgolette doppie:
for secret_file in \
"$THT_DWH_API_KEY_SECRET_FILE" "$THT_VEC_API_KEY_SECRET_FILE" \
"$THT_VEC_WRITE_API_KEY_SECRET_FILE" "$THT_MODEL_API_KEY_SECRET_FILE" "$THT_CA_SECRET_FILE"; do
sudo install -d -m 700 "$(dirname "$secret_file")"
done
sudo install -m 600 /dev/null "$THT_DWH_API_KEY_SECRET_FILE"
sudo install -m 600 /dev/null "$THT_VEC_API_KEY_SECRET_FILE"
sudo install -m 600 /dev/null "$THT_VEC_WRITE_API_KEY_SECRET_FILE"
sudo install -m 600 /dev/null "$THT_MODEL_API_KEY_SECRET_FILE"
sudo install -m 600 /dev/null "$THT_CA_SECRET_FILE"
Così ogni sudo install usa la variabile corretta e non si rischia di creare il file in un
percorso diverso da quello che Compose leggerà. Se i secret sono forniti da un secret manager,
si impostano le stesse variabili ai file materializzati dal manager e si saltano i comandi
install.
install è un comando Unix per creare/copiare un file impostando contestualmente i permessi.
In install -m 600 /dev/null DEST:
/dev/nullè una sorgente vuota, quindi il comando crea (o sostituisce)DESTsenza inserire una password;-m 600imposta i permessirw-------(lettura/scrittura solo per il proprietario);DESTè il file che l'operatore deve poi riempire con il secret.
Dopo la creazione, scrivere il contenuto in ogni target (l'esempio seguente usa un file sorgente protetto; ripeterlo per le altre variabili):
sudo sh -c 'umask 077; cat > "$1"' sh "$THT_DWH_API_KEY_SECRET_FILE" \
< /percorso/protetto/dwh-api-key
Il percorso deploy/secrets/ è la directory interna al clone usata da questa guida: il software
non cerca automaticamente le API key in /etc né in una directory speciale. Il percorso host è
quello indicato nelle variabili THT_*_SECRET_FILE; Compose legge quel file e lo monta nel
container al percorso interno dichiarato dal servizio, normalmente /run/secrets/dwh_api_key,
/run/secrets/vector_reader_api_key o /run/secrets/model_api_key.
Il comando non è un gestore di password e non va usato per stampare il secret sulla riga di
comando. Su Windows è preferibile usare WSL2 per creare il file con permessi Unix, oppure
creare un file locale ACL-protetto tramite uno strumento aziendale di gestione dei secret. Non
usare ConvertFrom-SecureString come contenuto del file: produce una rappresentazione cifrata
che ThothII non può usare come API key.
# Dentro WSL2, dalla directory radice del clone ThothII.
mkdir -p deploy/secrets
umask 077
read -r -s secret; printf '%s' "$secret" > deploy/secrets/dwh-api-key
unset secret
Per i secret usati da Docker Desktop è preferibile una directory locale non sincronizzata e
accessibile a Docker Desktop; non usare una cartella Git o OneDrive condivisa. In alternativa,
creare i file dentro WSL2 con umask 077 e passare a Compose il path Windows risultante.
Impostare gli endpoint e i riferimenti ai secret nel servizio core (preferibilmente tramite un file .env
gestito dall'operatore, non committato):
export THT_DB_NAME=warehouse
export THT_DWH_REST_URL=https://dwh.internal.example
export THT_VEC_REST_URL=https://vectors.internal.example
export THT_OLLAMA_URL=https://embeddings.internal.example
export AUTH_MODE=none
export THOTH_PUBLIC_EXPOSURE=false
Queste variabili con suffisso _SECRET_FILE sono input di Compose sul server host. Non vanno
confuse con le variabili _FILE viste dal processo dentro il container: ad esempio
THT_MODEL_API_KEY_SECRET_FILE=deploy/secrets/model-api-key viene trasformata dal file
deploy/compose.production.yaml in THT_MODEL_API_KEY_FILE=/run/secrets/model_api_key.
Il backend legge quindi /run/secrets/model_api_key, non il file host sotto deploy/secrets.
Preparare un file YAML in deploy/workspaces/. Il workspace è la configurazione logica di una
installazione: seleziona gli adapter, gli endpoint non riservati e le radici persistenti. Per
esempio, con DWH REST e vector DB HTTP:
language: en
dwh:
type: thoth_rest
database: {database: warehouse, schema: datawarehouse}
endpoint: {base_url: https://dwh.internal.example}
vectors:
type: thoth_vector_http
reader: {base_url: https://vectors.internal.example}
writer: {base_url: https://vectors.internal.example}
roots: {artifacts: artifacts, indexes: indexes, sessions: sessions}
evidence: {source_root: /data/source, evidence_dir: evidence}
embeddings: {base_url: https://embeddings.internal.example, model: nomodel, dim: 768}
Con DWH PostgreSQL e pgvector raggiungibili direttamente dalla rete Docker:
language: en
dwh:
type: postgres_direct
connection: {host: dwh.internal.example, database: warehouse, schema: public,
user: thoth_reader, password_file: /run/secrets/dwh_password}
vectors:
type: pgvector_direct
reader: {host: vector.internal.example, database: thoth, schema: vectors,
user: thoth_vector_reader, password_file: /run/secrets/vector_reader_password}
writer: {host: vector.internal.example, database: thoth, schema: vectors,
user: thoth_vector_writer, password_file: /run/secrets/vector_writer_password}
roots: {artifacts: artifacts, indexes: indexes, sessions: sessions}
I nomi dei type sono contratti applicativi, non descrizioni libere: usare quelli esposti da
tht doctor e dagli esempi del repository (thoth_rest, thoth_vector_http,
postgres_direct, pgvector_direct). dwh.type sceglie come interrogare il DWH; vectors.type
sceglie come leggere/scrivere il vector DB. Cambiare questi valori può richiedere anche campi
specifici dell'adapter e secret file coerenti.
roots contiene percorsi logici, non percorsi host arbitrari. Con THT_DATA_ROOT=/data,
artifacts: artifacts diventa /data/workspaces/<workspace>/artifacts (e analogamente per
indexes e sessions), evitando che un YAML possa scrivere fuori dal volume applicativo.
Un path host va esposto esplicitamente con un bind mount read-only/read-write nel Compose e poi
referenziato dal workspace secondo le regole di sicurezza; non inserire /Users/... o
C:\\... direttamente in un workspace destinato a più sistemi operativi.
Avvio e verifica
docker compose -f compose.yaml -f deploy/compose.production.yaml \
--profile external up --build --wait
docker compose -f compose.yaml -f deploy/compose.production.yaml \
--profile external exec core /opt/venv/bin/tht doctor --json
./scripts/docker-smoke.sh
Il frontend è pubblicato su 127.0.0.1:8080 per default. Per esposizione pubblica usare un
reverse proxy autenticato TLS; non impostare THOTH_PUBLIC_EXPOSURE=true senza AUTH_MODE=upstream
e senza il proxy che inietta X-Authenticated-User.
2. Mac locale con DWH esterno e vector DB locale
Questo è il profilo consigliato per un Mac Apple Silicon o Intel: Docker Desktop ospita
pgvector e ThothII, mentre DWH ed embeddings possono essere remoti. Ollama eseguito sul Mac è
raggiungibile dai container con host.docker.internal.
Creare quattro password locali dentro ThothII/deploy/secrets/ (la directory è esclusa da Git):
mkdir -p deploy/secrets
for name in bootstrap migrator reader writer; do
umask 077; openssl rand -base64 32 >"deploy/secrets/$name"
done
export THT_VECTOR_BOOTSTRAP_PASSWORD_SECRET_FILE=deploy/secrets/bootstrap
export THT_VECTOR_MIGRATOR_PASSWORD_SECRET_FILE=deploy/secrets/migrator
export THT_VECTOR_READER_PASSWORD_SECRET_FILE=deploy/secrets/reader
export THT_VECTOR_WRITER_PASSWORD_SECRET_FILE=deploy/secrets/writer
export THT_OLLAMA_URL=http://host.docker.internal:11434
Avviare il profilo:
docker compose -f compose.yaml -f deploy/compose.local-vector.yaml \
--profile local-vector up --build --wait
Per eseguire i job di preprocessing usare anche l'overlay che abilita la catena health-check → reconcile → migrate:
docker compose -f compose.yaml -f deploy/compose.local-vector.yaml \
-f deploy/compose.preprocess.yaml -f deploy/compose.preprocess-local-vector.yaml \
--profile local-vector --profile preprocess build preprocess-evidence
docker compose -f compose.yaml -f deploy/compose.local-vector.yaml \
-f deploy/compose.preprocess.yaml -f deploy/compose.preprocess-local-vector.yaml \
--profile local-vector --profile preprocess run --rm preprocess-evidence
Montare i testi Evidence in /data/source/evidence tramite il workspace o un override Compose.
Il volume thoth_data contiene sessioni, artefatti e corpus; vector_data contiene solo
pgvector. Per verificare rotazione credenziali e recovery:
./scripts/local-vector-smoke.sh
./scripts/local-vector-smoke.sh --backup-restore
3. PC Windows locale
Usare Docker Desktop con backend WSL2, abilitare l'integrazione con la distribuzione WSL e conservare il repository in un percorso condiviso con Docker. È preferibile lavorare da PowerShell nella directory del progetto.
$secretDir = Join-Path (Get-Location) "deploy\secrets"
New-Item -ItemType Directory -Force $secretDir | Out-Null
foreach ($name in @("bootstrap", "migrator", "reader", "writer")) {
$bytes = New-Object byte[] 32
[Security.Cryptography.RandomNumberGenerator]::Fill($bytes)
[Convert]::ToBase64String($bytes) | Set-Content -NoNewline (Join-Path $secretDir $name)
}
$env:THT_VECTOR_BOOTSTRAP_PASSWORD_SECRET_FILE = Join-Path $secretDir "bootstrap"
$env:THT_VECTOR_MIGRATOR_PASSWORD_SECRET_FILE = Join-Path $secretDir "migrator"
$env:THT_VECTOR_READER_PASSWORD_SECRET_FILE = Join-Path $secretDir "reader"
$env:THT_VECTOR_WRITER_PASSWORD_SECRET_FILE = Join-Path $secretDir "writer"
$env:THT_OLLAMA_URL = "http://host.docker.internal:11434"
Da PowerShell, i path assoluti vengono passati a Compose tramite le variabili precedenti; non scrivere password direttamente nello YAML. Avviare lo stesso profilo del Mac:
docker compose -f compose.yaml -f deploy/compose.local-vector.yaml `
--profile local-vector up --build --wait
docker compose -f compose.yaml -f deploy/compose.local-vector.yaml `
-f deploy/compose.preprocess.yaml -f deploy/compose.preprocess-local-vector.yaml `
--profile local-vector --profile preprocess run --rm preprocess-evidence
Se Docker Desktop segnala un bind mount non condiviso, aggiungere la directory del repository
in Docker Desktop → Settings → Resources → File Sharing. Se Ollama gira su Windows, usare
host.docker.internal; se gira in WSL2, usare l'endpoint raggiungibile dalla rete Docker.
Verificare il profilo con:
docker compose -f compose.yaml -f deploy/compose.local-vector.yaml --profile local-vector config
docker compose -f compose.yaml -f deploy/compose.local-vector.yaml --profile local-vector ps
4. Server applicativo distinto da DB e Evidence
Questo profilo separa il server Docker di ThothII dal DWH, vector DB e repository Evidence.
Usare compose.production.yaml e configurare gli adapter con endpoint raggiungibili dal
server applicativo. Le Evidence non devono essere copiate nel container se sono già accessibili
via HTTP/S3 o tramite un filesystem montato dal sistema operativo.
Configurare firewall e DNS in modo che il server applicativo possa raggiungere solo gli endpoint necessari. Esempi di sorgente Evidence:
filesystem: NFS/SMB montato sul server e passato come root read-only al workspace;http: URL HTTPS con allowlist/limiti SSRF e cache condizionata;s3: bucket/prefix con secret references e endpoint custom solo con trust boundary esplicito.
Impostare THT_DOCS_ROOT/il workspace per il path montato oppure configurare il tipo HTTP/S3,
poi avviare:
docker compose -f compose.yaml -f deploy/compose.production.yaml \
--profile external config --quiet
docker compose -f compose.yaml -f deploy/compose.production.yaml \
--profile external up --build --wait
docker compose -f compose.yaml -f deploy/compose.production.yaml \
--profile external exec core /opt/venv/bin/tht doctor --json
Per un vector DB remoto usare le chiavi reader/writer distinte quando il servizio lo consente;
per un DWH REST usare THT_DWH_REST_URL e il relativo secret, senza introdurre connessioni
dirette nel container. Il preprocessing DWH/Evidence può essere eseguito sullo stesso server
applicativo con un volume /data persistente, mantenendo separati i lock e gli artefatti dei
job.
Controlli comuni post-installazione
docker compose ... config --quietnon deve mostrare password o token in chiaro.docker compose ... psdeve mostrarecoreefrontendhealthy.tht doctor --jsondeve restituire JSON valido; errori di dipendenza devono restare diagnostici e non esporre secret.- Eseguire lo smoke coerente col profilo (
docker-smoke.sh,preprocess-smoke.sholocal-vector-smoke.sh). - Conservare il volume
thoth_datae i backup pgvector fuori dal ciclo di deploy; usaredown --volumessolo per ambienti effimeri o dopo aver verificato il backup.
Risoluzione rapida dei problemi
- Core healthy ma nessun modello: controllare
THT_MODEL_API_KEY_SECRET_FILE, il provider selezionato e che non sia uno dei provider composti non supportati. - Preprocess fallisce subito: verificare l'overlay
compose.preprocess-local-vector.yaml, i quattro secret pgvector e che il mount Evidence sia leggibile. - Vector health non disponibile: controllare
vector-db,vector-reconcile,vector-migratee le password reader/writer; non usare la password bootstrap nelle query applicative. - Evidence non trovate: controllare il path nel workspace, la rete HTTP/S3 e i limiti di dimensione/paginazione; verificare che il corpus ACTIVE appartenga allo stesso workspace.