Proxy inverse et HTTPS
Avec Aivory app Le conteneur est 8787 L’accès au spa à l’avant et /api L'arrière-plan ne parle que d'HTTP. L'environnement de production suggère d'y placer une couche de proxy inverse responsable de la résiliation du TLS. Cette page fournit les deux configurations complètes de Nginx et Caddy qui peuvent être collées directement et explique pourquoi chacune d'entre elles est ainsi écrite.
Le front end et l'API sont gérés par le même processus, le même port, les deux sont toujours à la même source sous la perspective du navigateur. PUBLIC_ORIGIN Il n'est pas nécessaire de configurer la liste blanche CORS par nom de domaine. ALLOWED_ORIGINS Il suffit de vous débarrasser de l’apogée. ** différentes sources ** Le déploiement n’a de sens que sous la forme du déploiement, le déploiement de conteneur unique n’est pas possible.
Avant de commencer: ajuster la cartographie des ports
Déploiement rapide Le document composé est défini app L’appareil est équipé d’un port 80 ("80:8787" Lorsque vous ajoutez Nginx/Caddy sur la même machine, 80/443 doit être app Remplacement de l'écoute de l'appareil :
# deploy/docker-compose.prod.yml 中 app 服务的 ports 段
ports:
- "127.0.0.1:8787:8787"
Modifier l’exécution docker compose -f docker-compose.prod.yml up -d Reconstruire app Ensuite, le conteneur est remis à l'unité. http://127.0.0.1:8787。
A la racine des chemins GET / Le retour 200 représente la survie et peut être utilisé directement comme voie de détection d'inspection de la santé pour l'équilibre de la génération ou de la charge dans le cloud.
Prémisse clé : sortie de flux SSE
Les réponses d’AI d’Aivory sont diffusées via le flux SSE (Server-Sent Events). ** Pas de WebSocket ** Donc pas besoin de quoi que ce soit. Upgrade Configuration pertinente. Le serveur envoie un ping toutes les 15 secondes pour empêcher l'agent intermédiaire de se déconnecter en raison de son manque de temps. L'opposant doit faire deux choses:
- ** Fermer le buffer de réponse ** Si l'agent buffer réagit, le jeton va économiser en un gros morceau, puis le navigateur, l'effet de la machine à écrire disparaît immédiatement, se traduisant par "les cartes sont longues puis toute la partie est sortie".
- ** La lecture en excès de temps ** Une réponse à Deep Research ou à une longue chaîne d’outils peut durer plusieurs dizaines de minutes, ce qui donne suffisamment de temps de lecture.
Les deux configurations suivantes contiennent déjà ces traitements.
Étiquette : Nginx
Configuration complète
Conservé pour /etc/nginx/sites-available/aivory.conf et remplacer chat.example.com Pour votre nom de domaine :
# HTTP:仅用于 certbot 验证与跳转 HTTPS
server {
listen 80;
listen [::]:80;
server_name chat.example.com;
# certbot webroot 验证路径(用 --nginx 插件时可省略)
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
location / {
return 301 https://$host$request_uri;
}
}
# HTTPS 主站
server {
listen 443 ssl;
listen [::]:443 ssl;
http2 on; # nginx < 1.25.1 请删除此行,改为在上面两行 listen 末尾追加 http2
server_name chat.example.com;
ssl_certificate /etc/letsencrypt/live/chat.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/chat.example.com/privkey.pem;
# 普通上传默认上限 50MB(MAX_UPLOAD_BYTES),此处留出余量。
# 管理员备份导入可达 20GiB,见下文「大请求体」一节。
client_max_body_size 100m;
location / {
proxy_pass http://127.0.0.1:8787;
# --- SSE 流式输出三件套 ---
proxy_buffering off;
proxy_read_timeout 3600s;
proxy_http_version 1.1;
proxy_set_header Connection "";
# --- 真实客户端 IP 与协议 ---
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;
}
}
Activer et recharger :
sudo ln -s /etc/nginx/sites-available/aivory.conf /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
Explication par élément
| Instructions | Rôle |
|---|---|
proxy_pass http://127.0.0.1:8787 | Transmettre àapp Conteneur, Spa et /api Le même endroit, il n’y a pas besoin de séparation. |
proxy_buffering off | Éteignez le buffer de réponse et chaque événement de SSE est immédiatement transmis au navigateur, sinon l'effet de la machine à écrire disparaît. |
proxy_read_timeout 3600s | L'excès de temps de lecture est allongé jusqu'à 1 heure. Une fréquence cardiaque de 15 secondes sur le service peut couvrir la plupart des scènes libres, c'est le fond supplémentaire pour éviter que les réponses trop longues soient écrasées par l'agent |
proxy_http_version 1.1 | amont utilise HTTP/1.1, prend en charge les connexions longues et est une condition préalable pour le streaming |
proxy_set_header Connection "" | nettoyage Connection tête, maintenir le keepalive avec amont, pour éviter d'être dégradé à une connexion courte |
client_max_body_size 100m | Limite de la requête.Nginx n'est par défaut que de 1 MB, et la conférence non réglée entraîne un retour direct des fichiers téléchargés à 413 |
proxy_set_header Host $host | Transmettre les noms de domaine originaux. Tout nom de domaine peut être utilisé dans une architecture de conteneur unique, à condition que l'hôte soit correctement transféré (toutes les transgénérations sont par défaut) |
X-Real-IP / X-Forwarded-For | Le transfert de l'IP client réel, directement lié au flux limité, voir la section ci-dessous |
X-Forwarded-Proto $scheme | L’extérieur est HTTPS. |
Demander un certificat avec certbot
# Debian / Ubuntu
sudo apt install certbot python3-certbot-nginx
# 自动修改 Nginx 配置并签发证书
sudo certbot --nginx -d chat.example.com
# 验证自动续期
sudo certbot renew --dry-run
--nginx Le plugin complète automatiquement la vérification et l'écriture du nom de domaine. ssl_certificate Parcourez et définissez des tâches à temps de renouvellement. Si vous souhaitez contrôler vos profils entièrement manuellement, passez au mode webroot :
sudo mkdir -p /var/www/certbot
sudo certbot certonly --webroot -w /var/www/certbot -d chat.example.com
Le certificat est délivré avec succès. /etc/letsencrypt/live/chat.example.com/ correspondant à la configuration ci-dessus.
Chapitre 2 : Caddy
Caddy applique automatiquement et renouvelle le certificat Let's Encrypt, HTTP saute automatiquement HTTPS, Caddyfile Il suffit de trois lignes :
chat.example.com {
reverse_proxy 127.0.0.1:8787
}
sudo systemctl reload caddy
Caddy V2 détectéContent-Type: text/event-stream Les buffets de réponse sont automatiquement désactivés, de sorte que les trois lignes ci-dessus sont généralement ouvertes. Si votre version est plus ancienne ou que d'autres couches intermédiaires sont superposées, vous pouvez l'éteindre explicitement:
chat.example.com {
reverse_proxy 127.0.0.1:8787 {
flush_interval -1
}
}
flush_interval -1 Chaque byte reçu est immédiatement imprimé au client, ce qui équivaut à Nginx. proxy_buffering off。
Caddy ne limite pas la taille de la requête par défaut. X-Forwarded-For Par conséquent, le téléchargement de fichiers, l'importation de sauvegarde et l'IP réelle ne nécessitent pas de configuration supplémentaire.
Grande demande : téléchargement et import de sauvegarde
Aivory a deux catégories de grandes requêtes. client_max_body_size Traiter séparément :
| scène | Limites de service | Respecter les variables environnementales | Recommandé |
|---|---|---|---|
| Envoi de documents/dossiers ordinaires | Par défaut 50 MB | MAX_UPLOAD_BYTES | client_max_body_size 100m Il est couvert |
| Administrateur de sauvegarde d'importation | 20 Gb par défaut | MAX_BACKUP_BYTES | Voir les deux méthodes ci-dessous. |
L’administrateur en arrière-plan Importation de sauvegarde L’archivage peut aller jusqu’à 20 Gb. 100m Deux pratiques :
- ** Les contraintes temporaires **: Le
client_max_body_sizeRemplacer21g并nginx -s reloadUne fois l'importation terminée, les modifications sont effectuées.Scenes de grands documents suggèrent d'ajouter simultanémentproxy_request_buffering offPermet à Nginx d’envoyer le fichier de côté et d’éviter d’envoyer tout l’archive sur le disque local. - ** Connexion Internet (recommandée) ** Accès direct sur le serveur local ou en interne
http://127.0.0.1:8787Exécuter l'importation et contourner complètement les limites de volume et de dépassement de temps.
Le plafond du service lui-même MAX_UPLOAD_BYTES / MAX_BACKUP_BYTES Contrôle et détails. Variables environnementales avancées。
Véritable IP et limites de flux
Aivory compte les limites de flux en fonction de l'IP de maintenance du client (le compteur est stocké dans Redis).
- ** Seulement si la connexion directe est un réseau interne ou une adresse de retour. ** (C’est-à-dire que la demande vient de la réaction de votre déploiement)
X-Forwarded-For/X-Real-IPet prendreX-Forwarded-For中** L'article non interne en haut à droite ** Une véritable IP. - Lorsque l’adresse du site est en ligne, ces adresses ** Tout ignoré** TCP par end-to-end, c’est pourquoi les pirates de réseaux publics sont faussés
X-Forwarded-ForImpossible de faire semblant d’utiliser les IP d’autrui.
La signification de cette règle pour le fonctionnement :
Si l’opposition n’est pas établie proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for Toutes les demandes que vous voyez à l'arrière-plan proviennent de votre propre adresse IP. Les utilisateurs du site partagent le même nombre de limites de flux : un seul déclenche une limite de flux et tous les utilisateurs sont limités. La configuration Nginx ci-dessus contient la bonne écriture et le comportement par défaut de Caddy est correct.
** Scènes Cloudflare ** Les voies de circulation deviennent 访客 -> Cloudflare -> 源站 Nginx -> app Le nœud de source de Nginx est le nœud de Cloudflare. Il faut un module real_ip avec Nginx, basé sur Cloudflare. CF-Connecting-IP Récupérez d’abord l’IP du visiteur réel, puis entrez dans le lien de redirection ci-dessus :
# 在 http 或 server 块中声明信任的 Cloudflare 回源网段(节选,完整列表见 Cloudflare 官方发布)
set_real_ip_from 173.245.48.0/20;
set_real_ip_from 103.21.244.0/22;
# ...其余 Cloudflare 网段...
real_ip_header CF-Connecting-IP;
ainsi $remote_addr Le véritable IP du visiteur. $proxy_add_x_forwarded_for Les valeurs ajoutées sont également correctes. La liste complète des sections de réseau est maintenue et configurée progressivement Accès Cloudflare。
Peut-on utiliser HTTPS ?
Il est possible, mais pas recommandé.Aivory reste entièrement disponible dans un contexte non sécurisé (HTTP pur) : les algorithmes de signature de requête dans l'application sont intégrés avec une mise en œuvre de retour JS pur et ne dépendent pas de l'interface de cryptage du navigateur ouverte uniquement sous HTTPS.
HTTP signifie que les identifiants de connexion et le contenu de la conversation sont tous nus sur la chaîne, tout nœud intermédiaire peut être écouté ou manipulé.
Questions fréquemment posées
| phénomène | Cause | Traitement |
|---|---|---|
| Il n'y a pas de réponses, c'est le cas après l'arrivée de Katie. | Réagir avec le buzz. | Nginx confirméproxy_buffering off Vérifiez s’il y a d’autres couches de buffer au milieu (comme certains CDN). |
| Réponse interrompue au milieu. | La lecture est trop courte. | Confirméproxy_read_timeout 3600s Si vous passez par le CDN, synchronisez le temps libre du CDN. |
| Téléchargement des documents 413 | Le plafond de la demande est trop petit. | Améliorer client_max_body_size |
| L'importation de sauvegarde échoue | L’archivage dépasse les limites | Augmentation temporaire 21g Connexion directe au port 8787 |
| Tous les utilisateurs sont limités en même temps | X-Forwarded-For Ajout incorrect | Complétez comme ci-dessus proxy_set_header Deux lignes |
| Cloudflare permet de calculer l’IP par nœud CF | L’adresse IP n’est pas rétablie. | Configuration du module real_ip +CF-Connecting-IP voir Accès Cloudflare |