smart_ide/deploy/nginx/README-ia-enso.md
Nicolas Cantu a8a922f3e8 README ia.enso: curl example for /ollama/api/tags
**Motivations:**
- Match documented full URL with verification command.

**Root causes:**
- N/A.

**Correctifs:**
- N/A.

**Evolutions:**
- Native Ollama curl check in README.

**Pages affectées:**
- deploy/nginx/README-ia-enso.md
2026-03-23 01:30:21 +01:00

172 lines
8.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# ia.enso.4nkweb.com — Nginx sur le proxy (192.168.1.100)
Reverse TLS vers lhôte LAN **`192.168.1.164`** (Ollama + AnythingLLM ; IP substituée au déploiement via `__IA_ENSO_BACKEND_IP__` / `IA_ENSO_BACKEND_IP`).
## URLs publiques complètes (HTTPS)
| Service | URL |
|---------|-----|
| **AnythingLLM** (interface) | `https://ia.enso.4nkweb.com/anythingllm/` |
| **Ollama** API native (ex. liste des modèles) | `https://ia.enso.4nkweb.com/ollama/api/tags` |
| **Ollama** API compatible OpenAI (Cursor, etc.) | base URL `https://ia.enso.4nkweb.com/ollama/v1` — ex. `https://ia.enso.4nkweb.com/ollama/v1/models` |
**Bearer nginx** : tout ce qui est sous `/ollama/` exige `Authorization: Bearer <secret>` (sauf si tu modifies le `map`). Le secret nest **pas** transmis à Ollama en aval. AnythingLLM sous `/anythingllm/` utilise lauth **applicative**, pas ce Bearer.
| Chemin (relatif) | Backend | Port LAN | Protection |
|------------------|---------|----------|------------|
| `/ollama/` | Ollama | `11434` | **Bearer** nginx puis `Authorization` effacé vers Ollama |
| `/anythingllm/` | AnythingLLM | `3001` | Login AnythingLLM |
**Contexte Cursor :** une URL en IP privée (ex. `http://192.168.1.164:11434`) peut être refusée par Cursor (`ssrf_blocked`). Un **nom public** HTTPS vers le proxy évite ce blocage si le DNS résolu depuis Internet nest pas une IP RFC1918.
**Fichiers dans le dépôt :** `sites/ia.enso.4nkweb.com.conf`, `http-maps/*.example`, `deploy-ia-enso-to-proxy.sh`. Détails darchitecture : [docs/features/ia-enso-nginx-proxy-ollama-anythingllm.md](../../docs/features/ia-enso-nginx-proxy-ollama-anythingllm.md).
---
## Déploiement recommandé : script SSH
Depuis la racine du dépôt **`smart_ide`**, sur une machine avec accès SSH au bastion puis au proxy :
```bash
export IA_ENSO_OLLAMA_BEARER_TOKEN='secret-long-ascii-sans-guillemets-ni-backslash'
# accès LAN direct au proxy (.100), sans bastion (variable vide = pas de ProxyJump) :
# export DEPLOY_SSH_PROXY_HOST=
./deploy/nginx/deploy-ia-enso-to-proxy.sh
```
Si `IA_ENSO_OLLAMA_BEARER_TOKEN` est absent, le script génère un token hex (affichage unique) à conserver pour Cursor.
### Prérequis sur le proxy
- `http { include /etc/nginx/conf.d/*.conf; ... }` dans `/etc/nginx/nginx.conf` (sinon le script échoue avec un message explicite).
- **Certificats** Lets Encrypt pour `ia.enso.4nkweb.com` **déjà présents** aux chemins du fichier site (`/etc/letsencrypt/live/ia.enso.4nkweb.com/fullchain.pem` et `privkey.pem`) — sans cela `nginx -t` échoue ; voir section TLS / certbot **avant** le premier déploiement.
- **`sudo` non interactif** pour `nginx` et `systemctl reload nginx`.
### Fichiers installés par le script
| Chemin sur le proxy | Rôle |
|---------------------|------|
| `/etc/nginx/conf.d/ia-enso-http-maps.conf` | `map` Bearer (`$ia_enso_ollama_authorized`) et, si besoin, `map` WebSocket (`$connection_upgrade`) |
| `/etc/nginx/sites-available/ia.enso.4nkweb.com.conf` | `server` HTTP→HTTPS + HTTPS |
| Lien `sites-enabled/ia.enso.4nkweb.com.conf` | Activation du vhost |
Si `nginx -t` échoue à cause dun **doublon** `map $http_upgrade $connection_upgrade` déjà présent ailleurs, le script retente avec **Bearer seul** dans `ia-enso-http-maps.conf`.
### Variables denvironnement du script
| Variable | Défaut | Rôle |
|----------|--------|------|
| `IA_ENSO_OLLAMA_BEARER_TOKEN` | généré | Secret pour `Authorization: Bearer …` |
| `IA_ENSO_SSH_KEY` | `~/.ssh/id_ed25519` | Clé privée SSH |
| `IA_ENSO_PROXY_USER` | `ncantu` | Utilisateur SSH sur le proxy |
| `IA_ENSO_PROXY_HOST` | `192.168.1.100` | Cible SSH (IP ou hostname LAN) |
| `DEPLOY_SSH_PROXY_HOST` | `4nk.myftp.biz` | Bastion ProxyJump ; vide = SSH direct |
| `DEPLOY_SSH_PROXY_USER` | idem proxy | Utilisateur sur le bastion |
| `IA_ENSO_BACKEND_IP` | `192.168.1.164` | Hôte Ollama + AnythingLLM (IPv4) |
Bibliothèque utilisée : `ia_dev/deploy/_lib/ssh.sh` (`BatchMode=yes`).
---
## Déploiement manuel (sans script)
### 1. DNS et TLS
Le DNS doit résoudre `ia.enso.4nkweb.com` vers lentrée publique qui atteint ce proxy.
```bash
sudo certbot certonly --webroot -w /var/www/certbot -d ia.enso.4nkweb.com
```
Adapter dans `sites/ia.enso.4nkweb.com.conf` les directives `ssl_certificate` / `ssl_certificate_key` si le répertoire `live/` diffère.
### 2. Maps HTTP (`$ia_enso_ollama_authorized`, WebSocket)
**Option A — un seul fichier sous `conf.d` (équivalent au script)**
Créer `/etc/nginx/conf.d/ia-enso-http-maps.conf` en reprenant le contenu généré par le script ou en combinant :
- `http-maps/websocket-connection.map.conf.example` (uniquement si `$connection_upgrade` nexiste pas déjà dans linstance),
- et un `map $http_authorization $ia_enso_ollama_authorized { ... "Bearer <secret>" 1; }`.
**Option B — fichiers séparés sous `/etc/nginx/http-maps/`**
Copier les `.example` sans suffixe, éditer le secret Bearer, puis dans `http { }` :
```nginx
include /etc/nginx/http-maps/websocket-connection.map.conf;
include /etc/nginx/http-maps/ia-enso-ollama-bearer.map.conf;
```
Ne pas commiter un fichier contenant le secret réel.
### 3. Fichier `server`
Le fichier dans le dépôt contient le marqueur `__IA_ENSO_BACKEND_IP__`. Remplacer par lIPv4 du backend (ex. `192.168.1.164`) avant copie, ou utiliser :
```bash
sed "s/__IA_ENSO_BACKEND_IP__/192.168.1.164/g" deploy/nginx/sites/ia.enso.4nkweb.com.conf | sudo tee /etc/nginx/sites-available/ia.enso.4nkweb.com.conf >/dev/null
```
Sans `sed` : éditer le fichier sur le proxy pour remplacer `__IA_ENSO_BACKEND_IP__` par lIPv4 réelle, puis :
```bash
sudo ln -sf /etc/nginx/sites-available/ia.enso.4nkweb.com.conf /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx
```
---
## Vérifications
### API Ollama via le proxy
```bash
curl -sS -o /dev/null -w "%{http_code}\n" \
-H "Authorization: Bearer <secret>" \
https://ia.enso.4nkweb.com/ollama/v1/models
```
Attendu : **200** avec le bon secret ; **401** sans en-tête ou secret incorrect.
API native Ollama (même Bearer) :
```bash
curl -sS -H "Authorization: Bearer <secret>" https://ia.enso.4nkweb.com/ollama/api/tags
```
### AnythingLLM
Navigateur : `https://ia.enso.4nkweb.com/anythingllm/` (redirection vers `/anythingllm/`). Connexion avec les identifiants **AnythingLLM**.
Si les assets statiques échouent, vérifier la doc upstream (sous-chemin, en-têtes `X-Forwarded-*`).
### Cursor
- URL de base OpenAI : `https://ia.enso.4nkweb.com/ollama/v1`
- Clé API : **identique** au secret Bearer (sans préfixe `Bearer ` dans le champ ; Cursor envoie `Authorization: Bearer <clé>`).
---
## Pare-feu backend
Sur **`192.168.1.164`**, nautoriser **11434** et **3001** TCP que depuis **192.168.1.100** (proxy) si un pare-feu hôte est actif.
---
## Rotation du secret Bearer
1. Mettre à jour la ligne `"Bearer …"` dans `/etc/nginx/conf.d/ia-enso-http-maps.conf` (ou le fichier `map` manuel équivalent).
2. `sudo nginx -t && sudo systemctl reload nginx`.
3. Mettre à jour la clé API dans Cursor (et tout autre client).
---
## Dépannage
| Symptôme | Piste |
|----------|--------|
| `nginx -t` erreur sur `connection_upgrade` | Doublon de `map $http_upgrade $connection_upgrade` : retirer lun des blocs ou ninstaller que le `map` Bearer. |
| `could not build map_hash` / `map_hash_bucket_size` | Secret Bearer trop long pour la valeur par défaut ; le fichier `ia-enso-http-maps.conf` du script inclut `map_hash_bucket_size 256;` — mettre à jour le déploiement ou ajouter cette directive dans `http { }`. |
| `401` sur `/ollama/` | Secret différent entre client et `map` ; en-tête `Authorization` absent ou mal formé (`Bearer ` + secret exact). |
| `502` / timeout | Ollama ou AnythingLLM arrêtés sur le backend ; pare-feu ; mauvaise IP dans `upstream` (vérifier `grep server /etc/nginx/sites-available/ia.enso.4nkweb.com.conf` sur le proxy ; redéployer avec `IA_ENSO_BACKEND_IP=192.168.1.164`). |
| Erreur SSL / `cannot load certificate` | Certificat absent : exécuter certbot sur le proxy pour `ia.enso.4nkweb.com`, ou adapter les chemins `ssl_certificate` dans le fichier site. |
| Cursor `ssrf_blocked` | Lhôte utilisé résout encore vers une IP privée côté infrastructure Cursor ; vérifier DNS public / NAT. |