Tên miền, HTTPS và proxy ngược

Đặt Antimatter trên một tên miền có HTTPS, sử dụng hồ sơ Caddy trong tệp compose hoặc proxy ngược của riêng bạn, và thiết lập đúng địa chỉ URL của trang web và địa chỉ máy khách.

Địa chỉ URL của trang web

Địa chỉ URL của trang web (ServiceSettings.SiteURL) là địa chỉ mà mọi người sử dụng để truy cập Antimatter, chẳng hạn như https://chat.example.com. Máy chủ sử dụng địa chỉ này trong các liên kết trong email và thông báo, trong các hướng dẫn đăng nhập (OAuth, OpenID Connect, SAML), cho các ứng dụng di động và máy tính để bàn, và để kiểm tra nơi các yêu cầu đến từ đâu. Hãy thiết lập nó chính xác như địa chỉ trong thanh địa chỉ của trình duyệt: giao thức, tên miền và cổng (nếu không phải mặc định), không có dấu gạch chéo ở cuối.

  • Với tệp compose của trang web: SITE_URL trong .env.
  • Bất kỳ nơi nào khác: AM_SERVICESETTINGS_SITEURL, hoặc Bảng điều khiển Hệ thống › Môi trường › Máy chủ Web › URL trang web.

Nếu địa chỉ URL của trang web không chính xác, việc đăng nhập bằng nhà cung cấp danh tính sẽ thất bại, các liên kết trong email sẽ trỏ đến sai vị trí, và các ứng dụng có thể không kết nối được. Sau khi thay đổi tên miền, hãy cập nhật nó ở đây và trong các URL hướng dẫn của mọi nhà cung cấp danh tính.

HTTPS với hồ sơ Caddy đi kèm

Tệp compose.yaml của trang web bao gồm một dịch vụ Caddy trong hồ sơ https. Nó sẽ lấy chứng chỉ từ Let's Encrypt, tự động gia hạn, chuyển hướng HTTP sang HTTPS và chuyển tiếp mọi thứ, bao gồm cả websocket, đến Antimatter.

  1. Chỉ định một bản ghi DNS (A, và AAAA cho IPv6) của tên miền bạn đến máy chủ.
  2. Mở các cổng 80/tcp, 443/tcp và 443/udp (HTTP/3) trong tường lửa. Let's Encrypt phải có thể truy cập cổng 80 hoặc 443 từ Internet.
  3. Thêm tên miền vào .env và thiết lập địa chỉ URL của trang web:
    echo "DOMAIN=chat.example.com" >> .env
    sed -i 's|^SITE_URL=.*|SITE_URL=https://chat.example.com|' .env
  4. Bắt đầu với hồ sơ:
    docker compose --profile https up -d

Thêm --profile https vào mọi lệnh docker compose up sau đó, hoặc đặt COMPOSE_PROFILES=https trong .env để lệnh docker compose up -d thông thường bao gồm nó. Caddy lưu trữ các chứng chỉ của nó trong volume https.

Cổng riêng của Antimatter vẫn được công bố trên máy chủ (HTTP_PORT, mặc định là 8065). Khi có Caddy ở phía trước, hãy giữ nó chỉ cho chính máy chủ:

echo "HTTP_PORT=127.0.0.1:8065" >> .env
docker compose --profile https up -d

Caddy truy cập Antimatter qua mạng nội bộ edge, không phải thông qua cổng đó, vì vậy điều này không thay đổi gì cho người dùng của bạn.

Với proxy ngược của riêng bạn (nginx)

Nếu máy chủ đã chạy nginx hoặc một proxy khác, hãy tắt hồ sơ https và trỏ proxy đến cổng 8065 của Antimatter. Proxy phải:

  • cho phép nâng cấp websocket (ứng dụng web và ứng dụng di động duy trì một kết nối websocket mở trên /api/v4/websocket, và một số ứng dụng mở kết nối riêng của chúng);
  • chấp nhận các thân yêu cầu (request body) có kích thước ít nhất bằng tệp tải lên lớn nhất (Kích thước tệp tối đa, mặc định là 100 MB);
  • duy trì các kết nối dài (websocket, tải lên và tải xuống tệp lớn);
  • truyền tiêu đề Host và địa chỉ của máy khách.

Một khối máy chủ hoàn chỉnh, được điều chỉnh từ mẫu sản xuất trong antimatter-docker. Thay thế tên miền và đường dẫn chứng chỉ:

upstream antimatter {
    server 127.0.0.1:8065;
    keepalive 64;
}

map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      '';
}

proxy_cache_path /var/cache/nginx/antimatter levels=1:2 keys_zone=antimatter_cache:10m
                 max_size=3g inactive=120m use_temp_path=off;

server {
    listen 80;
    listen [::]:80;
    server_name chat.example.com;
    location / {
        return 301 https://$host$request_uri;
    }
}

server {
    listen 443 ssl;
    listen [::]:443 ssl;
    http2 on;
    server_name chat.example.com;

    ssl_certificate     /etc/ssl/chat.example.com/fullchain.pem;
    ssl_certificate_key /etc/ssl/chat.example.com/privkey.pem;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_session_timeout 1d;
    ssl_session_cache shared:AntimatterSSL:10m;
    ssl_session_tickets off;

    add_header Strict-Transport-Security "max-age=31536000" always;

    # At least FileSettings.MaxFileSize (100 MB by default).
    client_max_body_size 100M;

    proxy_http_version 1.1;
    proxy_set_header Host              $host;
    proxy_set_header X-Real-IP         $remote_addr;
    proxy_set_header X-Forwarded-For   $remote_addr;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header Upgrade           $http_upgrade;
    proxy_set_header Connection        $connection_upgrade;
    proxy_buffers 256 16k;
    proxy_buffer_size 16k;

    location ~ ^/api/v[0-9]+/(users/)?websocket$ {
        client_body_timeout 60s;
        send_timeout 300s;
        lingering_timeout 5s;
        proxy_connect_timeout 90s;
        proxy_send_timeout 300s;
        proxy_read_timeout 90s;
        proxy_pass http://antimatter;
    }

    location / {
        proxy_read_timeout 600s;
        proxy_cache antimatter_cache;
        proxy_cache_revalidate on;
        proxy_cache_min_uses 2;
        proxy_cache_use_stale timeout;
        proxy_cache_lock on;
        proxy_pass http://antimatter;
    }
}

Kiểm tra tệp bằng nginx -t và áp dụng bằng systemctl reload nginx. Máy chủ tự gửi X-Content-Type-Options, Referrer-Policy, Permissions-Policy và X-Frame-Options; chỉ HSTS là do proxy quản lý. Tăng max-age của nó khi HTTPS hoạt động, và chỉ thêm includeSubDomains nếu mọi tên miền con đều sử dụng HTTPS.

Với Docker Compose và nginx trên máy chủ, upstream ở trên trỏ đến cổng 8065 đã được công bố. Chỉ công bố nó trên 127.0.0.1 (HTTP_PORT=127.0.0.1:8065), để không ai có thể bỏ qua proxy.

Kho antimatter-docker có một cấu hình đầy đủ với nginx trong một container và Let's Encrypt thông qua certbot, trong deploy/compose.

Các proxy khác

Bất kỳ proxy nào cũng hoạt động nếu nó đáp ứng bốn điểm nêu trên. Âm thanh và video không bao giờ đi qua proxy: chúng sử dụng cổng riêng, xem Cuộc gọi và thoại.

Địa chỉ máy khách phía sau proxy

Phía sau proxy, mọi yêu cầu dường như đến từ proxy. Để ghi lại địa chỉ máy khách thực, hãy áp dụng giới hạn tần suất theo máy khách và sử dụng lọc IP, hãy cho máy chủ biết tiêu đề nào mang địa chỉ và proxy nào mà nó có thể tin tưởng. Không có cài đặt nào có trường trong Bảng điều khiển Hệ thống: hãy đặt chúng trong config.json hoặc bằng biến.

Khóa và biếnMặc địnhChức năng
ServiceSettings.TrustedProxyIPHeader, AM_SERVICESETTINGS_TRUSTEDPROXYIPHEADERtrống: máy chủ sử dụng địa chỉ của kết nốiCác tiêu đề mang địa chỉ của máy khách, ví dụ X-Forwarded-For. Tiêu đề đầu tiên có mặt trong yêu cầu sẽ được sử dụng.
ServiceSettings.TrustedProxyIPs, AM_SERVICESETTINGS_TRUSTEDPROXYIPStrốngCác địa chỉ hoặc dải CIDR của proxy của bạn, ví dụ 172.29.71.0/28. Các tiêu đề chỉ có hiệu lực đối với các yêu cầu đến từ một trong số chúng.

Trong một biến, phân tách nhiều giá trị bằng khoảng trắng: AM_SERVICESETTINGS_TRUSTEDPROXYIPHEADER="X-Forwarded-For X-Real-IP". Máy chủ sẽ từ chối cấu hình có mục trong TrustedProxyIPs không phải là địa chỉ IP hay dải CIDR.

Cách máy chủ xác định địa chỉ của client

Mỗi proxy sẽ thêm địa chỉ mà nó nhận được yêu cầu vào bên phải của X-Forwarded-For. Địa chỉ mà client tự gửi trong header sẽ nằm ở bên trái. Do đó, máy chủ sẽ đọc header từ phải sang trái, bỏ qua các địa chỉ của các proxy đáng tin cậy của bạn, và lấy địa chỉ khác đầu tiên làm địa chỉ của client. Client không thể tự chọn địa chỉ của mình bằng cách gửi header riêng.

  • Khi đứng sau một proxy, chỉ cần TrustedProxyIPHeader là đủ để lấy đúng địa chỉ: máy chủ sẽ lấy địa chỉ ở vị trí phải nhất trong header. Hệ thống sẽ ghi một cảnh báo khi khởi động cho đến khi bạn cũng thiết lập TrustedProxyIPs. Nếu không có nó, bất kỳ ai truy cập trực tiếp vào cổng 8065 đều có thể đặt header, vì vậy hãy chỉ công khai cổng đó trên 127.0.0.1 hoặc trên mạng nội bộ.
  • Khi đứng sau nhiều proxy, ví dụ một CDN hoặc bộ cân bằng tải đặt trước proxy của bạn, hãy liệt kê tất cả chúng trong TrustedProxyIPs. Nếu không, máy chủ sẽ lấy địa chỉ của proxy ngoài cùng làm địa chỉ của client.
  • Proxy có thể thay thế header bằng địa chỉ mà nó nhìn thấy, như trong ví dụ nginx ở trên (X-Forwarded-For $remote_addr), hoặc thêm vào header (dùng $proxy_add_x_forwarded_for của nginx). Cả hai cách đều hoạt động.

Những địa chỉ nào cần liệt kê

Hãy liệt kê địa chỉ mà các yêu cầu từ proxy xuất phát, theo cách Antimatter nhìn thấy.

  • Khi sử dụng tệp compose của trang web và Caddy, điều này đã được thực hiện: Caddy kết nối với Antimatter qua mạng edge, và tệp compose thiết lập TrustedProxyIPHeader thành X-Forwarded-For và TrustedProxyIPs thành dải của mạng đó, EDGE_SUBNET (mặc định là 172.29.71.0/28 trừ khi bạn thay đổi nó trong .env). Hãy thay đổi EDGE_SUBNET nếu nó trùng với một trong các mạng của bạn.
  • Cấu hình production trong antimatter-docker cũng làm tương tự cho container nginx của nó, sử dụng FRONTEND_SUBNET.
  • Khi nginx chạy trên host và Antimatter chạy trong Docker, các yêu cầu sẽ đến Antimatter thông qua cổng đã được công khai, thường là từ địa chỉ gateway của mạng thuộc dự án compose (có thể xem bằng lệnh docker network inspect). Hãy thiết lập AM_SERVICESETTINGS_TRUSTEDPROXYIPS thành địa chỉ đó trong compose.override.yaml.
  • Nếu không dùng Docker và nginx chạy trên cùng một máy chủ, địa chỉ là 127.0.0.1 (hoặc ::1 nếu nginx kết nối qua IPv6).

TLS không qua proxy

Máy chủ cũng có thể tự phục vụ HTTPS trong Bảng điều khiển Hệ thống › Môi trường › Máy chủ Web: đặt Bảo mật kết nối thành TLS (ServiceSettings.ConnectionSecurity), kèm Tệp chứng chỉ TLS và Tệp khóa TLS (ServiceSettings.TLSCertFile, ServiceSettings.TLSKeyFile), hoặc Sử dụng Let's Encrypt (ServiceSettings.UseLetsEncrypt). Khi đó, máy chủ phải nghe trên cổng 443 (Địa chỉ nghe, ServiceSettings.ListenAddress, mặc định là :8065), và ServiceSettings.Forward80To443 sẽ chuyển hướng cổng 80. Việc sử dụng proxy ngược dễ vận hành và gia hạn hơn, và đây là cách hướng dẫn này giả định.

Thời gian chờ và kích thước yêu cầu của máy chủ

Các cài đặt của máy chủ web riêng của máy chủ, trong Bảng điều khiển Hệ thống › Môi trường › Máy chủ Web:

Cài đặtKhóaMặc định
Địa chỉ ngheServiceSettings.ListenAddress:8065
Hết thời gian đọcServiceSettings.ReadTimeout300 giây
Thời gian chờ ghiServiceSettings.WriteTimeout300 giây
Thời gian chờ nhàn rỗi (không có trường trong Bảng điều khiển Hệ thống)ServiceSettings.IdleTimeout60 giây
Kích thước tải tối đa (byte)ServiceSettings.MaximumPayloadSizeBytesxem Bảo mật

Giữ thời gian chờ của chính proxy ít nhất bằng các giá trị này cho các yêu cầu thông thường, và kích thước body ít nhất bằng Kích thước tệp tối đa.