Reverse proxy và TLS
Khi cấu hình reverse proxy cho ReputeCast, proxy phải kết thúc TLS cho URL công khai của bạn và chuyển tiếp mọi yêu cầu
đến cổng 8080 của ReputeCast với header Host gốc, đồng thời truyền các phản hồi streaming đi ngay mà không đệm. Các
cấu hình dưới đây đã được kiểm thử với caddy:2 (2.11), nginx:stable-alpine (1.30) và traefik:v3 (3.7) đặt trước
ReputeCast vào tháng 10/2026.
Proxy phải làm gì
Phần tiêu đề “Proxy phải làm gì”- Kết thúc TLS cho tên máy chủ của URL công khai, và cho tên miền tùy chỉnh nếu các không gian làm việc dùng chúng.
- Chuyển tiếp mọi đường dẫn đến ReputeCast: ứng dụng và API,
/hooks/…(webhook của nhà cung cấp gửi thư),/p/…(trang công khai),/t/…(theo dõi lượt mở và lượt nhấp),/mcpvà/healthz, đường dẫn mà kiểm tra URL công khai gọi đến. - Giữ nguyên header
Host. ReputeCast nhận diện tên miền tùy chỉnh dựa vào header này. - Gửi
X-Forwarded-For. ReputeCast chỉ đọc header này từ proxy tin cậy. ReputeCast không cầnX-Forwarded-Proto: nó biết mình chạy trên HTTPS nhờhttp.public_url. - Truyền không đệm hai loại phản hồi:
- theo dõi trực tiếp, dùng Server-Sent Events tại
GET /api/v1/workspaces/{workspace}/campaigns/{campaignId}/live/stream(heartbeat mỗi 15 giây,retry: 3000); - endpoint MCP
/mcp(Streamable HTTP), có phản hồi dạngtext/event-stream.
- theo dõi trực tiếp, dùng Server-Sent Events tại
- Chấp nhận phần thân yêu cầu lớn. ReputeCast đặt giới hạn riêng cho từng thao tác; lớn nhất là 105 MiB (nhập mẫu giao dịch), còn nhập liên hệ chấp nhận 100 MiB.
Trước khi bắt đầu
Phần tiêu đề “Trước khi bắt đầu”- ReputeCast chạy bằng Docker Compose hoặc tệp nhị phân.
- Tên máy chủ công khai (ở đây là
news.example.com) trỏ đến máy chủ, và cổng 80, 443 đang mở cho tổ chức cấp chứng chỉ và khách truy cập của bạn.
Cấu hình proxy
Phần tiêu đề “Cấu hình proxy”Ví dụ Caddy và Traefik thêm proxy vào project Compose trong docker-compose.override.yml, nên proxy truy cập ReputeCast
qua app:8080. Khi proxy chạy ngay trên máy chủ (cài bằng tệp nhị phân, hoặc Compose với
REPUTECAST_PORT=127.0.0.1:8080), hãy dùng 127.0.0.1:8080.
Caddy tự lấy và gia hạn chứng chỉ, giữ header Host, đặt X-Forwarded-For và đẩy ngay các phản hồi
text/event-stream, nên theo dõi trực tiếp và MCP không cần thêm dòng nào
(tài liệu reverse_proxy, kiểm tra tháng 10/2026).
{ email [email protected] on_demand_tls { ask http://app:8080/p/_/tls-check }}
news.example.com { reverse_proxy app:8080}
# Workspaces' custom domains for public pages: a certificate only for verified domains.https:// { tls { on_demand } reverse_proxy app:8080}services: caddy: image: caddy:2 restart: unless-stopped ports: - "80:80" - "443:443" volumes: - ./Caddyfile:/etc/caddy/Caddyfile:ro - caddy_data:/data - caddy_config:/config app: environment: # The subnet of the reputecast_default network (see below). REPUTECAST_HTTP__TRUSTED_PROXIES: 172.18.0.0/16
volumes: caddy_data: caddy_config:Hãy bỏ khối https:// nếu không có không gian làm việc nào dùng tên miền tùy chỉnh.
Cấu hình này dành cho nginx 1.25.1 trở lên (chỉ thị http2) chạy ngay trên máy chủ, với chứng chỉ Let’s Encrypt ở vị
trí mặc định của Certbot. Mặc định nginx đệm các phản hồi được proxy, nên hai đường dẫn streaming tắt chế độ đệm.
upstream reputecast { server 127.0.0.1:8080; keepalive 16;}
server { listen 80; server_name news.example.com; return 301 https://$host$request_uri;}
server { listen 443 ssl; http2 on; server_name news.example.com;
ssl_certificate /etc/letsencrypt/live/news.example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/news.example.com/privkey.pem;
# ReputeCast enforces its own size limit per operation (largest: 105 MiB). client_max_body_size 110m;
proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header Connection "";
location / { proxy_pass http://reputecast; }
# Live monitor (Server-Sent Events) and the MCP endpoint: no buffering. location ~ ^/api/v1/workspaces/[^/]+/campaigns/[^/]+/live/stream$ { proxy_pass http://reputecast; proxy_buffering off; proxy_cache off; proxy_read_timeout 1h; }
location = /mcp { proxy_pass http://reputecast; proxy_buffering off; proxy_cache off; proxy_read_timeout 1h; }}- Khi bật chế độ đệm, các sự kiện của theo dõi trực tiếp đến trình duyệt muộn và rời rạc trong lúc kiểm thử; với cấu hình trên, chúng đến đều đặn mỗi giây.
client_max_body_sizemặc định của nginx là 1 MiB, quá nhỏ cho việc nhập liên hệ và tệp đính kèm.- Khi nginx chạy như một dịch vụ Compose, hãy dùng
server app:8080;và khởi động nginx sau ứng dụng (depends_on: [app]): nginx phân giải tên upstream lúc khởi động.
Traefik đọc route từ label của container ứng dụng, lấy chứng chỉ từ Let’s Encrypt, giữ header Host, đặt
X-Forwarded-For và truyền Server-Sent Events mà không cần thiết lập thêm
(tài liệu Traefik, kiểm tra tháng 10/2026).
services: traefik: image: traefik:v3 restart: unless-stopped command: - --providers.docker=true - --providers.docker.exposedbydefault=false - --entrypoints.web.address=:80 - --entrypoints.web.http.redirections.entrypoint.to=websecure - --entrypoints.websecure.address=:443 - --certificatesresolvers.le.acme.storage=/letsencrypt/acme.json - --certificatesresolvers.le.acme.httpchallenge.entrypoint=web ports: - "80:80" - "443:443" volumes: - /var/run/docker.sock:/var/run/docker.sock:ro - letsencrypt:/letsencrypt app: labels: - traefik.enable=true - traefik.http.routers.reputecast.rule=Host(`news.example.com`) - traefik.http.routers.reputecast.entrypoints=websecure - traefik.http.routers.reputecast.tls.certresolver=le - traefik.http.services.reputecast.loadbalancer.server.port=8080 environment: # The subnet of the reputecast_default network (see below). REPUTECAST_HTTP__TRUSTED_PROXIES: 172.18.0.0/16
volumes: letsencrypt:Đặt URL công khai và proxy tin cậy
Phần tiêu đề “Đặt URL công khai và proxy tin cậy”-
Đặt
http.public_urlthành địa chỉ HTTPS, không có dấu gạch chéo ở cuối:REPUTECAST_PUBLIC_URL=https://news.example.comtrong.envcủa Compose, hoặcREPUTECAST_HTTP__PUBLIC_URLvới tệp nhị phân. Khi URL công khai bắt đầu bằnghttps://, ReputeCast gửi HSTS và đánh dấu cookie phiên là Secure. -
Đặt
http.trusted_proxiesthành các địa chỉ mà proxy kết nối từ đó:127.0.0.1cho proxy trên cùng máy chủ với tệp nhị phân, hoặc subnet của network Compose:Terminal window docker network inspect reputecast_default --format '{{(index .IPAM.Config 0).Subnet}}' -
Khởi động lại ReputeCast (
docker compose up -d, hoặc khởi động lại dịch vụ).
ReputeCast đọc X-Forwarded-For từ phải sang trái và lấy địa chỉ đầu tiên không phải proxy tin cậy, nếu không có thì
dùng X-Real-IP. Khi đứng sau một chuỗi proxy (một CDN, rồi đến nginx), hãy tin cậy mọi chặng. Nếu không có thiết lập
này, phiên, giới hạn tốc độ và nhật ký kiểm tra sẽ hiện địa chỉ của proxy cho mọi người: khi kiểm thử, một phiên mở qua
nginx hiện địa chỉ 172.19.0.6 của container proxy cho đến khi subnet được tin cậy.
Tên miền tùy chỉnh
Phần tiêu đề “Tên miền tùy chỉnh”Một không gian làm việc có thể phục vụ trang đăng ký, trung tâm tùy chọn, trang lưu trữ và các trang công khai khác tại
gốc tên miền riêng của nó, thiết lập trong Biểu mẫu và trang, rồi Thương hiệu và tên miền
(đặt thương hiệu cho trang và dùng tên miền riêng). Tên miền trỏ đến máy chủ của bạn
bằng một bản ghi CNAME tới tên máy chủ của URL công khai. Với proxy, điều đó có nghĩa là:
- Chuyển tiếp tên miền đến ReputeCast kèm header
Hostcủa nó. ReputeCast tra tên máy chủ trong các tên miền đã xác minh và phục vụ trang của không gian làm việc tương ứng; tên máy chủ không xác định sẽ nhận ứng dụng. - Cung cấp chứng chỉ cho tên miền. Với Caddy, khối
https://cấp chứng chỉ theo yêu cầu. Trước mỗi lần cấp, Caddy gọihttp://app:8080/p/_/tls-check?domain=<name>, đường dẫn này trả về200cho tên miền tùy chỉnh đã xác minh và404cho mọi trường hợp khác, nên chứng chỉ chỉ được cấp cho tên miền đã xác minh. Bạn có thể tự kiểm tra một tên miền bằngcurl -i "http://127.0.0.1:8080/p/_/tls-check?domain=news.acme.io". - nginx và Traefik không có kiểm tra này: hãy thêm từng tên miền đã xác minh vào
server_namecùng chứng chỉ của nó (nginx), hoặc vào quy tắc router, nhưHost(`news.example.com`) || Host(`news.acme.io`)(Traefik).
Email vẫn liên kết đến URL công khai; tên miền tùy chỉnh chỉ dành cho trang công khai.
Cổng SMTP relay
Phần tiêu đề “Cổng SMTP relay”SMTP relay tự nói giao thức SMTP trên cổng 587 (STARTTLS) và 465 (TLS), với chứng chỉ riêng, nên proxy HTTP không chuyển tiếp được:
-
Công bố các cổng trực tiếp từ container ứng dụng, ví dụ trong
docker-compose.override.yml:docker-compose.override.yml services:app:ports:- "587:587"- "465:465"Hoặc chuyển tiếp chúng ở tầng 4 (TCP) mà không kết thúc TLS. Relay lấy địa chỉ client từ kết nối TCP và không đọc PROXY protocol, nên khi đứng sau một bộ chuyển tiếp TCP, địa chỉ dùng gần nhất của khóa sẽ là địa chỉ của bộ chuyển tiếp.
-
Với chứng chỉ Let’s Encrypt, ReputeCast trả lời thử thách HTTP-01 cho tên máy chủ của relay tại
/.well-known/acme-challenge/…trên cổng web của nó. Let’s Encrypt lấy thử thách qua cổng 80 và đi theo chuyển hướng sang HTTPS (các loại thử thách, kiểm tra tháng 10/2026), nên proxy phải chuyển tiếp đường dẫn đó cho tên máy chủ của relay. Nếu proxy của bạn tự trả lời đường dẫn đó, hãy cấp cho relay các tệp chứng chỉ.
Kiểm tra kết quả
Phần tiêu đề “Kiểm tra kết quả”-
curl -sI https://news.example.com/healthztrả về200kèm headerStrict-Transport-Security. -
Kiểm tra URL công khai trong Quản trị hệ thống, rồi Hệ thống và cập nhật cho thấy DNS, TLS và Reachable đều đạt (đăng nhập lần đầu).
-
Stream của theo dõi trực tiếp gửi dữ liệu ngay lập tức. Với một khóa API có quyền
campaigns:view:Terminal window curl -N -H "Authorization: Bearer rc_live_…" \https://news.example.com/api/v1/workspaces/acme-newsletter/campaigns/<campaign id>/live/streamBạn thấy
retry: 3000và: connectedngay lập tức, rồi: heartbeat …mỗi 15 giây. -
Danh sách phiên đang hoạt động trong tài khoản của bạn hiện địa chỉ IP của chính bạn, không phải của proxy.
Khắc phục sự cố
Phần tiêu đề “Khắc phục sự cố”- Theo dõi trực tiếp không cập nhật, hoặc vài giây mới nhảy một lần: proxy đang đệm stream. Trong nginx, hãy thêm
locationcủa live stream vớiproxy_buffering off. 413 Request Entity Too Largekhi nhập dữ liệu hoặc tải tệp lên: hãy tăngclient_max_body_sizecủa nginx.- Mọi người đều hiện địa chỉ của proxy:
http.trusted_proxieskhông chứa địa chỉ mà proxy kết nối từ đó. - Tên miền tùy chỉnh mở ứng dụng ReputeCast thay vì trang công khai: proxy thay header
Host, hoặc tên miền chưa được xác minh. - Caddy từ chối TLS cho tên miền tùy chỉnh (
tlsv1 alert internal error):/p/_/tls-checktrả về404vì tên miền chưa được xác minh trong ReputeCast. 502 Bad Gatewaytừ nginx trong Docker sau khi ứng dụng được tạo lại: nginx vẫn giữ địa chỉ container cũ. Hãy khởi động lại nginx (docker compose restart nginx).- Kiểm tra URL công khai cảnh báo
Answered with HTTP …: proxy có trả lời nhưng không chuyển tiếp/healthzđến ReputeCast.
Liên quan
Phần tiêu đề “Liên quan”- Cài đặt bằng Docker Compose
- Mở rộng với các vai trò web, ingest và worker: chuyển
/hooks/đến các tiến trình ingest. - Tham chiếu cấu hình: mọi khóa
http.*.