Bỏ qua để đến nội dung

Reverse proxy và TLS

Hướng dẫn thao tác
Dành cho:
Người vận hành máy chủ

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.

  • 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), /mcp và /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ần X-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ạng text/event-stream.
  • 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.
  • 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.

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).

Caddyfile
{
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
}
docker-compose.override.yml
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.

  1. Đặt http.public_url thành địa chỉ HTTPS, không có dấu gạch chéo ở cuối: REPUTECAST_PUBLIC_URL=https://news.example.com trong .env của Compose, hoặc REPUTECAST_HTTP__PUBLIC_URL với tệp nhị phân. Khi URL công khai bắt đầu bằng https://, ReputeCast gửi HSTS và đánh dấu cookie phiên là Secure.

  2. Đặt http.trusted_proxies thành các địa chỉ mà proxy kết nối từ đó: 127.0.0.1 cho 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}}'
  3. 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.

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 Host củ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ọi http://app:8080/p/_/tls-check?domain=<name>, đường dẫn này trả về 200 cho tên miền tùy chỉnh đã xác minh và 404 cho 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ằng curl -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_name cù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.

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ỉ.

  • curl -sI https://news.example.com/healthz trả về 200 kèm header Strict-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/stream

    Bạn thấy retry: 3000 và : connected ngay 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.

  • 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 location của live stream với proxy_buffering off.
  • 413 Request Entity Too Large khi nhập dữ liệu hoặc tải tệp lên: hãy tăng client_max_body_size của nginx.
  • Mọi người đều hiện địa chỉ của proxy: http.trusted_proxies khô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-check trả về 404 vì tên miền chưa được xác minh trong ReputeCast.
  • 502 Bad Gateway từ 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.