- Python 52%
- JavaScript 29.3%
- Shell 16.6%
- Dockerfile 1%
- CSS 0.8%
- Other 0.3%
Console in stile Brainsight su console.aigov.localhost (profilo compose `mockup`): 9 schermate sui dati vivi di gateway e observability via proxy read-only con fixture di riserva, 22 controlli in demo-check, verifica manuale in demo/verifica-mockup.md. Piano e decisioni in demo/piano-mockup.md; il seguito (console operativa, fasi 8-11) in demo/piano-console-operativa.md. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|---|---|---|
| authelia | ||
| brainsight/docker/brainsight-quickstart | ||
| demo | ||
| langflow | ||
| litellm | ||
| mockup | ||
| postgres | ||
| presidio | ||
| scripts | ||
| traefik/dynamic | ||
| .env.example | ||
| .gitignore | ||
| AGENTS.md | ||
| CLAUDE.md | ||
| compose.yaml | ||
| HANDOFF.md | ||
| README.md | ||
Brainsight AI Governance — Ambiente Demo/PoC
Stack runtime self-contained per una demo/PoC dell'impianto AI Governance, pensato per essere tirato su con Docker o Podman e poi passato al team DevOps per il deploy sugli ambienti Brain.
Ambito: è il piano runtime (superfici + gateway + observability). Non include il piano P1 (Brainsight, la governance dei metadati) né l'assurance-drift del modello (ML cube). L'observability qui è di tipo tracing/eval del GenAI (Langfuse), non drift del modello. I contenuti (modelli, flussi, prompt) sono volutamente vuoti: si popolano dopo.
Building blocks
| Servizio | Ruolo | Accesso (dietro SSO) | Immagine |
|---|---|---|---|
| OpenWebUI | Chat assistant (superficie utente) | https://chat.aigov.localhost | ghcr.io/open-webui/open-webui:main |
| LangFlow | Orchestrazione pipeline agentiche (superficie) | https://flow.aigov.localhost | langflowai/langflow:latest |
| LiteLLM | LLM Gateway — control plane (P2) | https://gw.aigov.localhost · API :4000 | ghcr.io/berriai/litellm:main-stable |
| Langfuse | Observability del traffico GenAI | https://obs.aigov.localhost | langfuse/langfuse:2 |
| Traefik | Reverse proxy (unico ingresso :80) | — | traefik:v3.3 |
| Authelia | SSO / forward-auth (login unico) | https://auth.aigov.localhost | authelia/authelia:4.38 |
| Postgres | Datastore condiviso (LiteLLM/Langfuse/LangFlow) | — (interno) | postgres:16-alpine |
Come si parlano: OpenWebUI e LangFlow puntano a LiteLLM (endpoint OpenAI-compatible
http://litellm:4000/v1). LiteLLM traccia ogni chiamata su Langfuse (callback nativo).
Le chiavi Langfuse vengono create al primo avvio (provisioning headless) e coincidono con quelle
usate da LiteLLM → l'osservabilità funziona senza configurazione manuale.
OpenWebUI ─┐
├──► LiteLLM (gateway, :4000) ──► provider LLM
LangFlow ──┘ │
└── trace ──► Langfuse (:3000)
tutti su Postgres
Avvio
cp .env.example .env
# genera i segreti: openssl rand -hex 32 (riempi ogni "change-me")
docker compose up -d # oppure: podman compose up -d
Le UI stanno dietro SSO (vedi sezione seguente), agli hostname *.aigov.localhost:
- Chat (OpenWebUI) → https://chat.aigov.localhost
- Orchestrazione (LangFlow) → https://flow.aigov.localhost
- Observability (Langfuse) → https://obs.aigov.localhost
- Gateway UI (LiteLLM) → https://gw.aigov.localhost · API diretta (key-auth): http://localhost:4000
- Login (Authelia) → https://auth.aigov.localhost
SSO (Authelia + Traefik)
Un unico login (Authelia) davanti a tutte le superfici, tramite un reverse proxy (Traefik)
in forward-auth. Scelto perché è l'unico modo semplice di proteggere anche LangFlow, che
in OSS non ha SSO nativo. Gli hostname *.aigov.localhost si risolvono da soli su 127.0.0.1
(niente /etc/hosts). Su OpenWebUI l'SSO è trasparente (login automatico dall'identità
Authelia via header fidato); Langfuse/LangFlow/LiteLLM restano protetti dal gate Authelia e
mantengono il proprio login applicativo.
Passo obbligatorio prima del primo avvio — crea il file utenti dal template (il file reale è git-ignored, non finisce nel repo) e genera l'hash della password demo:
cp authelia/users_database.example.yml authelia/users_database.yml
podman run --rm docker.io/authelia/authelia:4.38 \
authelia crypto hash generate argon2 --password 'ScegliUnaPassword'
# incolla la riga "$argon2id$v=19$..." nel campo password di authelia/users_database.yml
HTTPS self-signed: lo stack gira in HTTPS (Authelia 4.38 lo richiede). Il primo accesso a ogni sottodominio darà un avviso «connessione non sicura» del browser: è il certificato di sviluppo di Traefik — accetta e prosegui. In produzione DevOps metterà un certificato vero. Serve una volta anche:
sudo sysctl -w net.ipv4.ip_unprivileged_port_start=80(Traefik usa :80/:443).
Aggiungi anche i 3 segreti Authelia al .env:
cat >> .env <<EOF
AUTHELIA_SESSION_SECRET=$(openssl rand -hex 32)
AUTHELIA_STORAGE_ENCRYPTION_KEY=$(openssl rand -hex 32)
AUTHELIA_JWT_SECRET=$(openssl rand -hex 32)
EOF
Poi up, apri https://chat.aigov.localhost → vieni rediretto al login Authelia
(utente demo, la password che hai scelto) → entri, e OpenWebUI ti logga in automatico.
Se il login va in loop / cookie non impostato: alcuni ambienti non accettano cookie sul TLD
.localhost. Fallback: in/etc/hostsmetti127.0.0.1 auth.aigov.local chat.aigov.local flow.aigov.local gw.aigov.local obs.aigov.locale sostituisciaigov.localhost→aigov.localinauthelia/configuration.yml(domain + authelia_url + default_redirection_url) e intraefik/dynamic/config.yml(le regole Host). Riavvia traefik+authelia.
Primo contenuto (quando ci ragioniamo)
- Modelli: aggiungi le voci in
litellm/config.yaml→model_list(vedi esempi commentati), metti le eventuali API key nel.env, poidocker compose restart litellm. - OpenWebUI: i modelli del gateway appaiono da soli nel selettore.
- LangFlow: nei componenti LLM usa base URL
http://litellm:4000/v1e come API key la master del gateway. - Langfuse: le tracce arrivano da sole appena passa traffico dal gateway.
Note per DevOps (deploy Brain)
- Segreti: sostituire tutti i
change-me; gestire via secret manager, non.envin chiaro. - Immagini: qui sono su tag mobili (
main/latest/main-stable) per comodità PoC → pinnare a digest/versione per gli ambienti reali. - Rete/TLS: mettere un reverse proxy (Traefik/Nginx) con TLS davanti; non esporre le porte in chiaro.
- Postgres: qui è un singolo container con volume; in produzione valutare istanza gestita + backup.
- Podman/Fedora: volumi named (no SELinux issue); bind-mount di config con
:z. Rootless: Traefik usa :80/:443 → serve una voltasudo sysctl -w net.ipv4.ip_unprivileged_port_start=80(persisti in/etc/sysctl.d/99-rootless-ports.conf). In alternativa mappare Traefik su porte alte. - TLS: nel PoC è il cert self-signed di default di Traefik. Per gli ambienti reali: certificato aziendale / ACME, e sostituire Authelia con l'IdP del cliente (Entra ID/Keycloak) mantenendo il forward-auth.
- Langfuse: questo PoC usa la v2 (leggera, 2 componenti). Per gli ambienti reali valutare la v3 (aggiunge worker + ClickHouse + Redis + object storage): più scalabile, più pesante.
- Risorse/limiti: aggiungere
deploy.resources/healthcheck agli altri servizi prima del deploy.
Struttura
compose.yaml # i 7 servizi
.env.example # segreti (copia in .env)
litellm/config.yaml # modelli del gateway (vuoto) + callback Langfuse
postgres/10-extra-dbs.sql # crea i DB langfuse/langflow al primo init
traefik/dynamic/config.yml # routing per hostname + TLS + forward-auth
authelia/configuration.yml # config SSO (one_factor, cookie *.aigov.localhost)
authelia/users_database.example.yml # template utenti (copia in users_database.yml, git-ignored)