**Motivations:** - Restore gate on /ollama/; document Cursor streamFromAgentBackend note. **Root causes:** - N/A. **Correctifs:** - location /ollama/ if map + clear Authorization upstream; deploy script emits Bearer + websocket maps with retry bearer_only. **Evolutions:** - README Cursor subsection on streamFromAgentBackend (observed behavior); feature/services/infrastructure aligned. **Pages affectées:** - deploy/nginx/sites/ia.enso.4nkweb.com.conf - deploy/nginx/deploy-ia-enso-to-proxy.sh - deploy/nginx/README-ia-enso.md - deploy/nginx/http-maps/ia-enso-ollama-bearer.map.conf.example - docs/features/ia-enso-nginx-proxy-ollama-anythingllm.md - docs/services.md - docs/infrastructure.md
8.9 KiB
ia.enso.4nkweb.com — Nginx sur le proxy (192.168.1.100)
Reverse TLS vers l’hô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 /ollama/ exige Authorization: Bearer <secret> (fichier map sur le proxy). La valeur n’est pas transmise à Ollama (Authorization effacé en amont). AnythingLLM sous /anythingllm/ : auth applicative uniquement.
| Chemin (relatif) | Backend | Port LAN | Protection |
|---|---|---|---|
/ollama/ |
Ollama | 11434 |
Bearer nginx |
/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 n’est 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 d’architecture : 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 :
export IA_ENSO_OLLAMA_BEARER_TOKEN='secret-ascii-sans-guillemets-ni-backslash'
# accès LAN direct au proxy (.100), sans bastion :
# 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 Let’s Encrypt pour
ia.enso.4nkweb.comaux chemins du fichier site (/etc/letsencrypt/live/ia.enso.4nkweb.com/fullchain.pemetprivkey.pem). Sans eux, le bloclisten 443fait échouernginx -t: voir Bootstrap TLS ci-dessous. sudonon interactif pournginxetsystemctl reload nginx.
Bootstrap TLS (première fois, nginx -t impossible)
- DNS :
ia.enso.4nkweb.comdoit résoudre vers l’entrée publique qui atteint ce proxy (HTTP port 80). - Sur le proxy :
sudo install -d -m 0755 /var/www/certbot
# Remplacer temporairement le vhost par HTTP seul (fichier dans le dépôt : sites/ia.enso.4nkweb.com.http-only.conf)
sudo cp /chemin/smart_ide/deploy/nginx/sites/ia.enso.4nkweb.com.http-only.conf /etc/nginx/sites-available/ia.enso.4nkweb.com.conf
sudo nginx -t && sudo systemctl reload nginx
sudo certbot certonly --webroot -w /var/www/certbot -d ia.enso.4nkweb.com --non-interactive --agree-tos --register-unsafely-without-email
- Déployer la config complète :
./deploy/nginx/deploy-ia-enso-to-proxy.sh(rétablit HTTPS + upstreams).
Fichiers installés par le script
| Chemin sur le proxy | Rôle |
|---|---|
/etc/nginx/conf.d/ia-enso-http-maps.conf |
map_hash_bucket_size, map Bearer $ia_enso_ollama_authorized, et souvent map WebSocket |
/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 d’un doublon map $http_upgrade $connection_upgrade, le script retente avec Bearer seul (sans dupliquer le map WebSocket).
Variables d’environnement du script
| Variable | Défaut | Rôle |
|---|---|---|
IA_ENSO_OLLAMA_BEARER_TOKEN |
généré (openssl rand -hex 32) |
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 l’entrée publique qui atteint ce proxy.
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 (Bearer + WebSocket)
Le script déploie ia-enso-http-maps.conf avec map_hash_bucket_size 256, le map Bearer et le map WebSocket (ou Bearer seul si doublon WebSocket ailleurs). Installation manuelle : combiner http-maps/ia-enso-ollama-bearer.map.conf.example et websocket-connection.map.conf.example dans http { } si besoin.
3. Fichier server
Le fichier dans le dépôt contient le marqueur __IA_ENSO_BACKEND_IP__. Remplacer par l’IPv4 du backend (ex. 192.168.1.164) avant copie, ou utiliser :
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 l’IPv4 réelle, puis :
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
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 Authorization ou secret incorrect.
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 du
mapnginx (sans préfixeBearerdans le champ).
streamFromAgentBackend (comportement observé) : dans l’application Cursor (bundle Electron), le flux Agent / chat appelle une couche interne qui ouvre un stream vers les serveurs Cursor (getAgentStreamResponse, etc.), pas un fetch direct depuis ton poste vers ton URL OpenAI override. Cursor peut donc valider une « User API key » ou des droits avant ou en parallèle de l’usage de l’override. Si curl avec le Bearer vers /ollama/v1/models renvoie 200 mais Cursor affiche ERROR_BAD_USER_API_KEY, l’échec reste côté client / infra Cursor : forum. Le code minifié du produit n’est pas dans ce dépôt ; seuls les noms de fonctions dans la stack trace décrivent ce chemin d’exécution.
Pare-feu backend
Sur 192.168.1.164, n’autoriser 11434 et 3001 TCP que depuis 192.168.1.100 (proxy) si un pare-feu hôte est actif.
Rotation du secret Bearer
- Mettre à jour
"Bearer …"dans/etc/nginx/conf.d/ia-enso-http-maps.conf(ou redéployer avecIA_ENSO_OLLAMA_BEARER_TOKEN). sudo nginx -t && sudo systemctl reload nginx.- 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 l’un des blocs ou laisser le déploiement « Bearer seul » du script. |
could not build map_hash / map_hash_bucket_size |
Secret Bearer long : le fichier généré par le script inclut map_hash_bucket_size 256;. |
401 sur /ollama/ |
Secret différent entre client et map ; en-tête Authorization absent ou mal formé. |
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 |
L’hôte utilisé résout encore vers une IP privée côté infrastructure Cursor ; vérifier DNS public / NAT. |