Domaine personnalisé et proxy de première partie
Distribuez les fichiers du widget, la connexion du chat, le formulaire hors ligne et Smart Answer via un sous-domaine de votre site, avec une clé de proxy, l’adresse réelle du visiteur et des modèles nginx, Apache et Caddy.
Avec un domaine personnalisé, le chat passe par un sous-domaine de votre site, par exemple chat.your-company.com. Votre serveur reçoit les requêtes du widget et les transmet à reactive.chat en tant que proxy inverse. Cette page s’adresse à la personne qui exploite ce serveur. La version courte destinée aux rédacteurs figure dans Domaine personnalisé (première partie).
Ce qui passe par le sous-domaine
- Fichiers du widget –
loader.js, le noyau chargé ensuite (core.<hash>.js) et les autres modules. - Connexion du chat – WebSocket sous
/rc_wss/, y compris le repli HTTP sous/rc_wss/h/et les envois de fichiers sous/rc_wss/upload/. - Formulaire hors ligne –
POST /api/offline/<SITE_KEY>, lorsqu’aucune connexion de chat ne peut être établie. - Smart Answer –
/api/suche/, si vous utilisez la réponse IA dans la recherche de votre site.
Les avantages :
- Aucune requête vers des domaines tiers. Pour ces routes, les navigateurs de vos visiteurs communiquent uniquement avec votre sous-domaine.
- Une seule adresse dans votre Content Security Policy.
script-srcetconnect-srcindiquent votre sous-domaine à la place des adresses reactive.chat (détails dans Sécurité et CSP). - L’adresse réelle du visiteur est transmise. Votre proxy la signale dans un en-tête dédié, protégé par une clé secrète. Les limitations et blocages sont alors comptabilisés par visiteur plutôt que par proxy.
Ce que cela n’est pas :
- Ce n’est pas de l’auto-hébergement. Les conversations, pièces jointes et réglages sont toujours traités et stockés par reactive.chat.
- Cela ne détermine pas le consentement requis. Votre propre domaine ne change pas qui traite les données.
- Votre proxy voit le trafic. TLS se termine à votre proxy ; n’y journalisez pas les corps des requêtes et excluez
/rc_wss/h/du journal d’accès (ces requêtes contiennent un jeton de connexion de courte durée dans les paramètres de requête).
Prérequis
- Un serveur ou proxy inverse accessible publiquement via HTTPS sur le port 443 et capable d’établir des connexions HTTPS sortantes. Des modèles sont disponibles pour nginx (avec le module ssl), Apache 2.4.47 ou version ultérieure et Caddy 2.
- Pour Apache, les modules
mod_ssl,mod_proxy,mod_proxy_http,mod_proxy_wstunnel,mod_headersetmod_setenvif. - Un sous-domaine réservé au chat. Le chat nécessite l’hôte entier ; un chemin comme
www.your-company.com/chat/ne fonctionne pas. Saisissez uniquement le nom, sanshttps://, port ni chemin. Sont interdits : les adresses IP, les terminaisons internes comme.local,.lan,.internalet les noms sousreactive.chat. - Le même domaine que le site. Le chat n’est de première partie que si le sous-domaine appartient au domaine du site où il est intégré.
- DNS (A et/ou AAAA) avec uniquement des adresses publiques.
- Un certificat TLS pour le sous-domaine (les modèles nginx/Apache attendent les chemins certbot ; Caddy l’obtient lui-même).
- L’autorisation de modifier le projet.
Configuration
- Dans votre compte, ouvrez le projet, section Intégration → Configurer votre domaine personnalisé.
- Sous 1. Hôte, saisissez le nom, par exemple
chat.your-company.com, puis enregistrez. - Sous 2. Clé du proxy, cliquez sur Créer une clé. La clé commence par
rcpx_et n’est affichée qu’une seule fois ; seul un hachage est stocké. Elle doit figurer uniquement dans la configuration du proxy, jamais dans une page web, un script de navigateur ou un dépôt. - Sous 3. Configuration du serveur, prenez le modèle adapté à votre serveur. Juste après la création de la clé, il la contient ; plus tard, il affiche
__RC_PROXY_KEY__. Testez la configuration (nginx -touapachectl configtest) et rechargez le serveur. - Sous 5. Vérifier, cliquez sur Vérifier maintenant (au plus toutes les 10 secondes). Aucun message n’est créé.
- Remplacez le code d’intégration par celui de 4. Code d’intégration uniquement lorsque les cinq étapes de contrôle affichent « OK » :
<script src="https://chat.your-company.com/loader.js"
data-rc-site-key="SITE_KEY"
data-rc-ws-url="wss://chat.your-company.com/rc_wss/"
async></script>
Le widget détermine l’emplacement de ses fichiers à partir de src, la connexion du chat à partir de data-rc-ws-url, et en déduit les adresses du formulaire hors ligne, des envois de fichiers et du repli HTTP. Tous les autres attributs restent inchangés (Référence de la balise script).
Ce que le proxy doit transmettre
/rc_wss/→ serveur de chathttps://ws.reactive.chat/rc_wss/, avec mise à niveau WebSocket, délai long (modèles : 3600 s), sans mise en tampon et limite de corps d’au moins 32 MB (envois de fichiers)./api/offline/→https://ws.reactive.chat/api/offline/(petit corps, modèle : 32 kB, 30 s)./api/suche/→https://ws.reactive.chat/api/suche/, sans mise en tampon (la réponse est un flux Server-Sent Events), corps jusqu’à 8 kB, 120 s.- tout le reste → réseau de distribution
https://cdn.reactive.chat/.
Pour toutes les routes :
- L’en-tête Host et le SNI correspondent au nom de la cible, pas à votre sous-domaine. Un hôte inconnu reçoit une réponse HTTP 421.
- Le certificat de la cible est vérifié.
- Aucun cookie ni identifiant d’accès. Les en-têtes
CookieetAuthorizationdu navigateur ne sont pas transmis etSet-Cookien’est pas renvoyé. - Aucune redirection. Un cache n’est pas nécessaire ; si vous en configurez un, choisissez une durée courte pour
loader.js: le nom du fichier ne contient aucun numéro de version (celui du noyau en contient un, voir Architecture).
Pour /rc_wss/, /api/offline/ et /api/suche/, le proxy définit deux en-têtes à chaque requête :
- X-RC-Proxy-Key – votre clé
rcpx_…. - X-RC-Client-IP – l’adresse du visiteur telle que votre proxy la voit.
« Définit » signifie que toute valeur envoyée par un navigateur sous ces noms est remplacée. Sur la route vers le réseau de distribution, les deux sont effacés.
Derrière un répartiteur de charge ou un CDN, votre proxy voit d’abord l’adresse de cet équipement. Configurez alors la reprise de l’adresse réelle : nginx real_ip (set_real_ip_from, real_ip_header), Apache mod_remoteip (RemoteIPHeader, RemoteIPTrustedProxy), Caddy trusted_proxies et {client_ip} à la place de {remote_host}. Le contrôle ne détecte pas ce cas ; il voit uniquement qu’une adresse valide est définie.
Modèle nginx
La page du compte remplit déjà l’hôte, les adresses cibles et la clé ; il vaut mieux copier le modèle depuis cette page. La version ci-dessous sert de référence ; les valeurs à remplacer sont chat.your-company.com, SITE_KEY et __RC_PROXY_KEY__. Sur RHEL/CentOS, le paquet de certificats d’autorités se trouve sous /etc/pki/tls/certs/ca-bundle.crt.
server {
listen 80;
listen [::]:80;
server_name chat.your-company.com;
location /.well-known/acme-challenge/ { root /var/www/html; }
location / { return 301 https://$host$request_uri; }
}
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name chat.your-company.com;
ssl_certificate /etc/letsencrypt/live/chat.your-company.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/chat.your-company.com/privkey.pem;
# HTTP fallback (SSE / long polling): token in the query, do not log
location /rc_wss/h/ {
access_log off;
proxy_pass https://ws.reactive.chat/rc_wss/h/;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host ws.reactive.chat;
proxy_ssl_server_name on;
proxy_ssl_name ws.reactive.chat;
proxy_ssl_verify on;
proxy_ssl_verify_depth 3;
proxy_ssl_trusted_certificate /etc/ssl/certs/ca-certificates.crt;
proxy_set_header X-RC-Proxy-Key "__RC_PROXY_KEY__";
proxy_set_header X-RC-Client-IP $remote_addr;
proxy_set_header Cookie "";
proxy_set_header Authorization "";
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
proxy_buffering off;
proxy_cache off;
}
# Chat connection (WebSocket) and uploads
location /rc_wss/ {
proxy_pass https://ws.reactive.chat/rc_wss/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host ws.reactive.chat;
proxy_ssl_server_name on;
proxy_ssl_name ws.reactive.chat;
proxy_ssl_verify on;
proxy_ssl_verify_depth 3;
proxy_ssl_trusted_certificate /etc/ssl/certs/ca-certificates.crt;
proxy_set_header X-RC-Proxy-Key "__RC_PROXY_KEY__";
proxy_set_header X-RC-Client-IP $remote_addr;
proxy_set_header Cookie "";
proxy_set_header Authorization "";
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
proxy_buffering off;
proxy_cache off;
client_max_body_size 32m;
proxy_request_buffering off;
}
# Offline form
location /api/offline/ {
proxy_pass https://ws.reactive.chat/api/offline/;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host ws.reactive.chat;
proxy_ssl_server_name on;
proxy_ssl_name ws.reactive.chat;
proxy_ssl_verify on;
proxy_ssl_verify_depth 3;
proxy_ssl_trusted_certificate /etc/ssl/certs/ca-certificates.crt;
proxy_set_header X-RC-Proxy-Key "__RC_PROXY_KEY__";
proxy_set_header X-RC-Client-IP $remote_addr;
proxy_set_header Cookie "";
proxy_set_header Authorization "";
proxy_hide_header Set-Cookie;
client_max_body_size 32k;
proxy_read_timeout 30s;
}
# Smart Answer (website search), answer as a stream
location /api/suche/ {
proxy_pass https://ws.reactive.chat/api/suche/;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host ws.reactive.chat;
proxy_ssl_server_name on;
proxy_ssl_name ws.reactive.chat;
proxy_ssl_verify on;
proxy_ssl_verify_depth 3;
proxy_ssl_trusted_certificate /etc/ssl/certs/ca-certificates.crt;
proxy_set_header X-RC-Proxy-Key "__RC_PROXY_KEY__";
proxy_set_header X-RC-Client-IP $remote_addr;
proxy_set_header Cookie "";
proxy_set_header Authorization "";
proxy_hide_header Set-Cookie;
client_max_body_size 8k;
proxy_buffering off;
proxy_cache off;
proxy_read_timeout 120s;
}
# Widget files
location / {
proxy_pass https://cdn.reactive.chat/;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host cdn.reactive.chat;
proxy_ssl_server_name on;
proxy_ssl_name cdn.reactive.chat;
proxy_ssl_verify on;
proxy_ssl_verify_depth 3;
proxy_ssl_trusted_certificate /etc/ssl/certs/ca-certificates.crt;
proxy_set_header X-RC-Proxy-Key "";
proxy_set_header X-RC-Client-IP "";
proxy_set_header Cookie "";
proxy_set_header Authorization "";
proxy_hide_header Set-Cookie;
}
}
Modèle Apache (2.4.47 ou version ultérieure)
Uniquement le VirtualHost du port 443 ; configurez la redirection depuis le port 80 et le certificat comme pour vos autres hôtes. SSLProxyVerifyDepth 5 est obligatoire ; sinon, Apache ne vérifie la chaîne de la cible que sur un niveau et signale « Certificate Chain too long ».
<VirtualHost *:443>
ServerName chat.your-company.com
SetEnvIf Request_URI "^/rc_wss/h/" rc_no_log
CustomLog ${APACHE_LOG_DIR}/chat.your-company.com_access.log combined env=!rc_no_log
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/chat.your-company.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/chat.your-company.com/privkey.pem
SSLProxyEngine on
SSLProxyVerify require
SSLProxyVerifyDepth 5
SSLProxyCheckPeerName on
SSLProxyCACertificateFile /etc/ssl/certs/ca-certificates.crt
ProxyRequests Off
ProxyPreserveHost Off
ProxyAddHeaders Off
RequestHeader unset X-RC-Proxy-Key early
RequestHeader unset X-RC-Client-IP early
RequestHeader unset Cookie early
RequestHeader unset Authorization early
ProxyPass "/rc_wss/" "https://ws.reactive.chat/rc_wss/" upgrade=websocket timeout=3600 flushpackets=on
ProxyPass "/api/offline/" "https://ws.reactive.chat/api/offline/" timeout=30
ProxyPass "/api/suche/" "https://ws.reactive.chat/api/suche/" timeout=120 flushpackets=on
ProxyPass "/" "https://cdn.reactive.chat/"
<Location "/rc_wss/">
RequestHeader set X-RC-Proxy-Key "__RC_PROXY_KEY__"
RequestHeader set X-RC-Client-IP "expr=%{REMOTE_ADDR}"
</Location>
<Location "/api/offline/">
RequestHeader set X-RC-Proxy-Key "__RC_PROXY_KEY__"
RequestHeader set X-RC-Client-IP "expr=%{REMOTE_ADDR}"
Header unset Set-Cookie
</Location>
<Location "/api/suche/">
RequestHeader set X-RC-Proxy-Key "__RC_PROXY_KEY__"
RequestHeader set X-RC-Client-IP "expr=%{REMOTE_ADDR}"
Header unset Set-Cookie
</Location>
</VirtualHost>
Les versions d’Apache antérieures à 2.4.47 ne reconnaissent pas upgrade=websocket. Dans ce cas, remplacez la première ligne ProxyPass par :
RewriteEngine on
RewriteCond %{HTTP:Upgrade} =websocket [NC]
RewriteRule ^/rc_wss/(.*) "wss://ws.reactive.chat/rc_wss/$1" [P,L]
ProxyPass "/rc_wss/" "https://ws.reactive.chat/rc_wss/" timeout=3600 flushpackets=on
Modèle Caddy 2
header_up avec une valeur remplace ce que le navigateur a envoyé sous ce nom. Si vous activez les journaux d’accès, excluez /rc_wss/h/* (log_skip, avant Caddy 2.8 skip_log).
chat.your-company.com {
handle /rc_wss/* {
reverse_proxy https://ws.reactive.chat {
header_up Host ws.reactive.chat
header_up X-RC-Proxy-Key "__RC_PROXY_KEY__"
header_up X-RC-Client-IP {remote_host}
header_up -Cookie
header_up -Authorization
transport http {
tls_server_name ws.reactive.chat
}
flush_interval -1
}
}
handle /api/offline/* {
reverse_proxy https://ws.reactive.chat {
header_up Host ws.reactive.chat
header_up X-RC-Proxy-Key "__RC_PROXY_KEY__"
header_up X-RC-Client-IP {remote_host}
header_up -Cookie
header_up -Authorization
header_down -Set-Cookie
transport http {
tls_server_name ws.reactive.chat
}
}
}
handle /api/suche/* {
reverse_proxy https://ws.reactive.chat {
header_up Host ws.reactive.chat
header_up X-RC-Proxy-Key "__RC_PROXY_KEY__"
header_up X-RC-Client-IP {remote_host}
header_up -Cookie
header_up -Authorization
header_down -Set-Cookie
transport http {
tls_server_name ws.reactive.chat
}
flush_interval -1
}
}
handle {
reverse_proxy https://cdn.reactive.chat {
header_up Host cdn.reactive.chat
header_up -X-RC-Proxy-Key
header_up -X-RC-Client-IP
header_up -Cookie
header_up -Authorization
header_down -Set-Cookie
transport http {
tls_server_name cdn.reactive.chat
}
}
}
}
Les cinq étapes de contrôle
Chaque étape affiche « OK », « Erreur », « Remarque » ou « non vérifié ». Le contrôle n’est réussi qu’avec cinq « OK ». Les vérifications utilisent uniquement HTTPS sur le port 443, sans redirection, avec 5 secondes par étape.
- Résolution de nom – A/AAAA présents, toutes les adresses publiques. Toutes les étapes suivantes se connectent exactement à cette adresse.
- loader.js via votre domaine – le fichier est chargé et comparé au nôtre. Sans connexion, réponse ou certificat valide, les étapes restantes sont ignorées. Une redirection est une erreur ; un fichier différent indique un cache ou une mauvaise cible pour
/. - Clé et adresse du visiteur – appel de
/rc_wss/eigene-domain-probe. Erreurs possibles :X-RC-Proxy-Keyabsent ; clé inconnue (juste après sa création, délai jusqu’à 30 secondes) ;X-RC-Client-IPabsent ou invalide ; clé appartenant à un autre projet. Une remarque apparaît si la clé est valide mais enregistrée pour un autre hôte. - WebSocket –
wss://chat.your-company.com/rc_wss/doit répondre avec HTTP 101 et le sous-protocolerc.v1. - Formulaire hors ligne –
GET /api/offline/SITE_KEYdoit répondre 405 (le point de terminaison n’accepte que POST ; aucun message n’est ainsi créé).
Vous pouvez appeler vous-même l’adresse de contrôle de l’étape 3 :
curl -s https://chat.your-company.com/rc_wss/eigene-domain-probe
Avec une configuration correcte :
{"rc":"eigene-domain-probe","v":1,"schluessel":"gueltig","client_ip":"gesetzt","site":"SITE_KEY","host":"chat.your-company.com"}
- schluessel –
gueltig(valide),unbekannt(inconnue) oufehlt(absente). - client_ip –
gesetzt(définie),fehlt(absente) ouungueltig(invalide). - site, host – uniquement avec une clé valide. La réponse ne renvoie jamais d’adresse.
La clé du proxy
- Rotation : Créer une nouvelle clé en émet une immédiatement ; l’ancienne reste valable 24 heures. Il y a au maximum deux clés valides ; une nouvelle rotation pendant ces 24 heures invalide immédiatement la plus ancienne.
- Suppression : Supprimer la clé l’invalide immédiatement (y compris une ancienne clé issue d’une rotation en cours). Supprimer le domaine supprime l’hôte et la clé ensemble ; remettez d’abord le code d’intégration précédent sur votre site.
- Clé absente ou erronée : le chat continue de fonctionner, mais les deux en-têtes sont ignorés. Tous les visiteurs apparaissent alors avec l’adresse de votre proxy. Comme la protection contre les abus compte par adresse, elle peut limiter l’ensemble de votre proxy, donc tous les visiteurs à la fois.
- Un projet par clé : si un widget portant la clé de site d’un autre projet se connecte via un proxy avec une clé valide, la connexion est refusée. Pour un autre projet, il faut un sous-domaine distinct avec sa propre clé.
- Clé divulguée : quiconque la connaît peut déclarer des adresses de visiteurs arbitraires pour votre projet. Supprimez-la, créez-en une nouvelle et configurez-la.
Dépannage
- HTTP 421 (Misdirected Request) : le proxy envoie votre nom comme hôte à la place du nom de la cible. nginx :
proxy_set_header Hostavecproxy_ssl_server_name on/proxy_ssl_name; Apache :ProxyPreserveHost Off; Caddy :header_up Hostettls_server_name. - HTTP 502 / erreur TLS vers la cible : Apache sans
SSLProxyVerifyDepth 5; nginx avec un chemin incorrect dansproxy_ssl_trusted_certificateou sansproxy_ssl_server_name on; HTTPS sortant bloqué. - HTTP 413 à l’envoi d’un fichier : sans réglage, nginx n’accepte que 1 MB ;
client_max_body_size 32mdans la section/rc_wss/(et au moins la même limite dans un répartiteur de charge en amont). - Aucune mise à niveau WebSocket :
Upgrade/Connectionne sont pas transmis. Le chat utilise alors le repli HTTP, mais ne se connecte qu’après deux tentatives WebSocket infructueuses. - 401 pour le formulaire hors ligne : une protection par mot de passe précède
/api/offline/. - 403 avec une remarque sur l’origine : le domaine du site (pas le sous-domaine du chat !) manque dans les Origines autorisées du projet.
- 403 « La réponse ne provient pas de reactive.chat » : un pare-feu ou une règle d’accès devant la cible refuse la requête.
- Le DNS pointe vers une adresse privée (
10.0.0.0/8,192.168.0.0/16,100.64.0.0/10,fc00::/7…) : l’enregistrement public doit indiquer une adresse publique.
Suite : Transport et protocole · Sécurité et CSP
Senest opdateret: