feat: v0.2.0 — API REST, TTS support, documentazione completa e UI mobile-first
✨ Nuove funzionalità: - Nuovo endpoint API REST /api/v1/query (GET+POST) per consumo programmatico - Campo speakable_text ottimizzato per sintesi vocale (Alexa, Google Home) - Funzione strip_markdown() per conversione Markdown → plain text TTS - Supporto CORS per accesso cross-origin - UI responsive mobile-first con micro-interazioni e stati - Nuovo pulsante 'Nuova ricerca' e metadata bar 📚 Documentazione completa: - docs/ARCHITECTURE.md — architettura di sistema, stack, componenti - docs/FLOW.md — diagrammi Mermaid della pipeline e flussi - docs/API.md — documentazione endpoint REST con esempi curl - docs/WIKI.md — FAQ, glossario, roadmap - docs/DEPLOYMENT.md — guida deployment (Gunicorn, Nginx, Docker, systemd) - docs/CONTRIBUTING.md — guida alla contribuzione 🔧 Migliorie tecniche: - Pipeline di ricerca condivisa in _run_search_pipeline() - Gestione errori Gemini migliorata con _clean_error() - Sanitizzazione HTML con allowlist per prevenzione XSS - .env.example completo con commenti 🧪 Test: 109/109 passati
This commit is contained in:
1 parent
f3fe13c60e
commit
76bc667adf
20 files changed
+3385
-245
No files matched your search
@@ -0,0 +1,402 @@
|
||||
# 🚀 Sibilla — Guida al Deployment
|
||||
|
||||
> **Versione:** 0.2.0
|
||||
> **Ultimo aggiornamento:** 18 Luglio 2026
|
||||
|
||||
---
|
||||
|
||||
## Indice
|
||||
|
||||
1. [Prerequisiti](#prerequisiti)
|
||||
2. [Installazione rapida](#installazione-rapida)
|
||||
3. [Configurazione](#configurazione)
|
||||
4. [Avvio](#avvio)
|
||||
5. [Deployment in produzione](#deployment-in-produzione)
|
||||
6. [Docker Compose](#docker-compose)
|
||||
7. [Reverse Proxy](#reverse-proxy)
|
||||
8. [Systemd Service](#systemd-service)
|
||||
9. [Monitoraggio](#monitoraggio)
|
||||
10. [Troubleshooting](#troubleshooting)
|
||||
|
||||
---
|
||||
|
||||
## Prerequisiti
|
||||
|
||||
### Software
|
||||
|
||||
| Componente | Versione minima | Note |
|
||||
|-----------|----------------|------|
|
||||
| Python | 3.10+ | |
|
||||
| pip | 21.0+ | |
|
||||
| Git | — | Opzionale, per clonare il repo |
|
||||
|
||||
### Servizi esterni
|
||||
|
||||
| Servizio | Obbligatorio? | Come ottenerlo |
|
||||
|----------|:---:|---------------|
|
||||
| Google API Key | ✅ Sì | [Google AI Studio](https://aistudio.google.com/apikey) |
|
||||
| Degoog | Consigliato | `docker run -d -p 4444:4444 ghcr.io/degoog-org/degoog:latest` |
|
||||
| SearXNG | No (fallback) | `docker run -d -p 8080:8080 searxng/searxng` |
|
||||
| DuckDuckGo | No (automatico) | Nessuna configurazione necessaria |
|
||||
|
||||
---
|
||||
|
||||
## Installazione rapida
|
||||
|
||||
```bash
|
||||
# 1. Clona il repository
|
||||
git clone https://github.com/tuo-user/sibilla.git
|
||||
cd sibilla
|
||||
|
||||
# 2. Crea ambiente virtuale
|
||||
python3 -m venv .venv
|
||||
source .venv/bin/activate # Linux/Mac
|
||||
# .venv\Scripts\activate # Windows
|
||||
|
||||
# 3. Installa dipendenze
|
||||
pip install -e ".[dev]"
|
||||
|
||||
# 4. Configura
|
||||
cp .env.example .env # se esiste, altrimenti crealo
|
||||
nano .env # Inserisci GOOGLE_API_KEY
|
||||
|
||||
# 5. Avvia (sviluppo)
|
||||
sibilla
|
||||
# → http://127.0.0.1:5000
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Configurazione
|
||||
|
||||
Crea un file `.env` nella root del progetto:
|
||||
|
||||
```env
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
# Sibilla Configuration
|
||||
# ═══════════════════════════════════════════════════════════════
|
||||
|
||||
# Google Gemini API key (obbligatoria)
|
||||
GOOGLE_API_KEY=AIzaSyD-xxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
|
||||
# Flask secret key (cambiala in produzione!)
|
||||
SECRET_KEY=una-chiave-segreta-molto-lunga-e-casuale
|
||||
|
||||
# ── Server ───────────────────────────────────────────────────
|
||||
|
||||
# Host e porta del server Flask
|
||||
SIBILLA_HOST=127.0.0.1
|
||||
SIBILLA_PORT=5000
|
||||
|
||||
# Debug mode (0 = off, 1 = on)
|
||||
# NON usare in produzione!
|
||||
SIBILLA_DEBUG=1
|
||||
|
||||
# ── Search Engines ────────────────────────────────────────────
|
||||
|
||||
# Degoog (primary)
|
||||
DEGOOG_URL=http://localhost:4444
|
||||
|
||||
# SearXNG (secondary)
|
||||
SEARXNG_URL=http://localhost:8080
|
||||
|
||||
# DuckDuckGo fallback (1 = on, 0 = off)
|
||||
SIBILLA_DDG_FALLBACK=1
|
||||
```
|
||||
|
||||
### Variabili d'ambiente complete
|
||||
|
||||
| Variabile | Default | Descrizione |
|
||||
|-----------|---------|-------------|
|
||||
| `GOOGLE_API_KEY` | `""` | **Obbligatoria.** API key di Google AI |
|
||||
| `SECRET_KEY` | `"dev-secret-key-change-me"` | Secret key Flask |
|
||||
| `SIBILLA_HOST` | `"127.0.0.1"` | Host su cui ascoltare |
|
||||
| `SIBILLA_PORT` | `"5000"` | Porta del server |
|
||||
| `SIBILLA_DEBUG` | `"1"` | Debug mode (0/1) |
|
||||
| `DEGOOG_URL` | `"http://localhost:4444"` | URL dell'istanza Degoog |
|
||||
| `SEARXNG_URL` | `"http://localhost:8080"` | URL dell'istanza SearXNG |
|
||||
| `SIBILLA_DDG_FALLBACK` | `"1"` | Abilita fallback DuckDuckGo (0/1) |
|
||||
|
||||
---
|
||||
|
||||
## Avvio
|
||||
|
||||
### Sviluppo
|
||||
|
||||
```bash
|
||||
# Modo 1: CLI
|
||||
sibilla
|
||||
|
||||
# Modo 2: Python module
|
||||
python -m sibilla
|
||||
|
||||
# Modo 3: Flask diretto (con hot reload)
|
||||
python -c "from sibilla.app import create_app; create_app().run(debug=True)"
|
||||
```
|
||||
|
||||
### Produzione (Gunicorn)
|
||||
|
||||
```bash
|
||||
# Installa Gunicorn
|
||||
pip install gunicorn
|
||||
|
||||
# Avvia
|
||||
gunicorn -w 4 -b 0.0.0.0:5000 "sibilla.app:create_app()"
|
||||
|
||||
# Con opzioni aggiuntive
|
||||
gunicorn \
|
||||
-w 4 \
|
||||
-b 0.0.0.0:5000 \
|
||||
--timeout 120 \
|
||||
--access-logfile /var/log/sibilla/access.log \
|
||||
--error-logfile /var/log/sibilla/error.log \
|
||||
"sibilla.app:create_app()"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Deployment in produzione
|
||||
|
||||
### Checklist pre-deployment
|
||||
|
||||
- [ ] `SIBILLA_DEBUG=0` (MAI in debug in produzione)
|
||||
- [ ] `SECRET_KEY` cambiata con una chiave casuale lunga
|
||||
- [ ] `GOOGLE_API_KEY` configurata
|
||||
- [ ] Reverse proxy (nginx/Caddy) configurato con HTTPS
|
||||
- [ ] Firewall: solo porta 80/443 esposta
|
||||
- [ ] Rate limiting configurato (nginx o middleware)
|
||||
- [ ] Logging configurato
|
||||
- [ ] Health check monitorato
|
||||
|
||||
### Architettura di produzione consigliata
|
||||
|
||||
```
|
||||
Internet
|
||||
│
|
||||
▼
|
||||
┌──────────────────┐
|
||||
│ Nginx / Caddy │ ← Reverse proxy + HTTPS (Let's Encrypt)
|
||||
│ Porta 80/443 │ + Rate limiting
|
||||
└────────┬─────────┘
|
||||
│
|
||||
▼
|
||||
┌──────────────────┐
|
||||
│ Gunicorn │ ← WSGI server
|
||||
│ 4 workers │ Porta 5000 (internal)
|
||||
└────────┬─────────┘
|
||||
│
|
||||
▼
|
||||
┌──────────────────┐
|
||||
│ Sibilla Flask │ ← Application
|
||||
└────────┬─────────┘
|
||||
│
|
||||
┌────┴────┐
|
||||
▼ ▼
|
||||
┌────────┐ ┌────────┐
|
||||
│ Degoog │ │ Gemini │
|
||||
│ :4444 │ │ API │
|
||||
└────────┘ └────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Docker Compose
|
||||
|
||||
Ecco un esempio di `docker-compose.yml` per avviare Sibilla + Degoog + SearXNG:
|
||||
|
||||
```yaml
|
||||
version: "3.8"
|
||||
|
||||
services:
|
||||
sibilla:
|
||||
build: .
|
||||
ports:
|
||||
- "5000:5000"
|
||||
environment:
|
||||
- GOOGLE_API_KEY=${GOOGLE_API_KEY}
|
||||
- SECRET_KEY=${SECRET_KEY:-changeme} # ⚠️ Cambiare in produzione!
|
||||
- SIBILLA_HOST=0.0.0.0
|
||||
- SIBILLA_PORT=5000
|
||||
- SIBILLA_DEBUG=0
|
||||
- DEGOOG_URL=http://degoog:4444
|
||||
- SEARXNG_URL=http://searxng:8080
|
||||
- SIBILLA_DDG_FALLBACK=1
|
||||
depends_on:
|
||||
- degoog
|
||||
- searxng
|
||||
restart: unless-stopped
|
||||
|
||||
degoog:
|
||||
image: ghcr.io/degoog-org/degoog:latest
|
||||
ports:
|
||||
- "4444:4444"
|
||||
restart: unless-stopped
|
||||
|
||||
searxng:
|
||||
image: searxng/searxng:latest
|
||||
ports:
|
||||
- "8080:8080"
|
||||
environment:
|
||||
- SEARXNG_BASE_URL=http://localhost:8080/
|
||||
volumes:
|
||||
- ./searxng:/etc/searxng:rw
|
||||
restart: unless-stopped
|
||||
```
|
||||
|
||||
Avvia con:
|
||||
```bash
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Reverse Proxy
|
||||
|
||||
### Nginx
|
||||
|
||||
```nginx
|
||||
server {
|
||||
listen 80;
|
||||
server_name sibilla.tuo-dominio.com;
|
||||
|
||||
# Rate limiting
|
||||
limit_req_zone $binary_remote_addr zone=sibilla:10m rate=10r/m;
|
||||
limit_req zone=sibilla burst=5 nodelay;
|
||||
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:5000;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_read_timeout 120s;
|
||||
}
|
||||
|
||||
# API endpoint with higher rate limit
|
||||
location /api/ {
|
||||
proxy_pass http://127.0.0.1:5000;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_read_timeout 120s;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Caddy (più semplice, auto-HTTPS)
|
||||
|
||||
```
|
||||
sibilla.tuo-dominio.com {
|
||||
reverse_proxy 127.0.0.1:5000
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Systemd Service
|
||||
|
||||
Crea `/etc/systemd/system/sibilla.service`:
|
||||
|
||||
```ini
|
||||
[Unit]
|
||||
Description=Sibilla AI Search Engine
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=sibilla
|
||||
Group=sibilla
|
||||
WorkingDirectory=/opt/sibilla
|
||||
EnvironmentFile=/opt/sibilla/.env
|
||||
ExecStart=/opt/sibilla/.venv/bin/gunicorn -w 4 -b 127.0.0.1:5000 "sibilla.app:create_app()"
|
||||
Restart=always
|
||||
RestartSec=5
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
|
||||
Attiva:
|
||||
```bash
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl enable --now sibilla
|
||||
sudo systemctl status sibilla
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Monitoraggio
|
||||
|
||||
### Health check endpoint
|
||||
|
||||
```bash
|
||||
curl http://localhost:5000/api/health
|
||||
```
|
||||
|
||||
Monitora con:
|
||||
- **Uptime Kuma** — monitoraggio self-hosted
|
||||
- **Healthchecks.io** — cron monitoring
|
||||
- **Prometheus + Grafana** — metriche avanzate (da aggiungere)
|
||||
|
||||
### Log
|
||||
|
||||
Con Gunicorn:
|
||||
```bash
|
||||
# Access log
|
||||
tail -f /var/log/sibilla/access.log
|
||||
|
||||
# Error log
|
||||
tail -f /var/log/sibilla/error.log
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### "GOOGLE_API_KEY is not set"
|
||||
|
||||
Il file `.env` non è stato caricato o manca la variabile:
|
||||
|
||||
```bash
|
||||
# Verifica che il file .env esista
|
||||
ls -la .env
|
||||
|
||||
# Verifica il contenuto
|
||||
cat .env | grep GOOGLE_API_KEY
|
||||
|
||||
# Se usi systemd, assicurati che EnvironmentFile punti al percorso corretto
|
||||
```
|
||||
|
||||
### "Connection refused" per Degoog/SearXNG
|
||||
|
||||
Il motore di ricerca non è in esecuzione:
|
||||
|
||||
```bash
|
||||
# Verifica se Degoog è attivo
|
||||
curl http://localhost:4444/api/search?q=test
|
||||
|
||||
# Verifica se SearXNG è attivo
|
||||
curl http://localhost:8080/search?q=test&format=json
|
||||
|
||||
# Se non rispondono, Sibilla userà automaticamente DuckDuckGo
|
||||
```
|
||||
|
||||
### "502 Bad Gateway" — Tutti i motori down
|
||||
|
||||
Verifica che DuckDuckGo fallback sia abilitato:
|
||||
```env
|
||||
SIBILLA_DDG_FALLBACK=1
|
||||
```
|
||||
|
||||
Se anche DuckDuckGo non funziona, Gemini risponderà in modalità "pure LLM" (senza fonti).
|
||||
|
||||
### Timeout su richieste lente
|
||||
|
||||
Aumenta il timeout in Gunicorn:
|
||||
```bash
|
||||
gunicorn --timeout 180 ...
|
||||
```
|
||||
|
||||
E nel reverse proxy:
|
||||
```nginx
|
||||
proxy_read_timeout 180s;
|
||||
```
|
||||
Reference in new issue
Block a user