網域、HTTPS 與反向代理

使用 compose 檔案中的 Caddy 設定檔或您自己的反向代理,透過 HTTPS 將 Antimatter 部署到網域上,並確保網站網址與用戶端位址設定正確。

網站網址

網站網址(ServiceSettings.SiteURL)是使用者用來存取 Antimatter 的位址,例如 https://chat.example.com。伺服器會將其用於電子郵件與通知中的連結、登入重定向(OAuth、OpenID Connect、SAML)、行動與桌面應用程式,以及檢查請求來源。請將其設定為與瀏覽器位址列中完全一致的位址:包含協定、網域,若非預設埠號則包含埠號,且結尾不要加斜線。

  • 使用該網站的 compose 檔案時:在 .env 中設定 SITE_URL。
  • 其他位置:AM_SERVICESETTINGS_SITEURL,或 系統控制台 › 環境 › 網頁伺服器 › 網站網址。

如果網站網址設定錯誤,使用身分提供者登入將失敗,電子郵件中的連結會指向錯誤位置,且應用程式可能無法連線。變更網域後,請在此處以及每個身分提供者的重定向網址中更新設定。

使用隨附的 Caddy 設定檔啟用 HTTPS

該網站的 compose.yaml 包含 https 設定檔中的 Caddy 服務。它會從 Let's Encrypt 取得憑證並自動更新,將 HTTP 重定向至 HTTPS,並將所有流量(包括 websocket)轉發至 Antimatter。

  1. 將您網域的 DNS 記錄(A 記錄,IPv6 則加上 AAAA 記錄)指向伺服器。
  2. 在防火牆中開啟 80/tcp、443/tcp 和 443/udp(HTTP/3)埠號。Let's Encrypt 必須能從網際網路存取埠號 80 或 443。
  3. 將網域加入 .env 並設定網站網址:
    echo "DOMAIN=chat.example.com" >> .env
    sed -i 's|^SITE_URL=.*|SITE_URL=https://chat.example.com|' .env
  4. 使用該設定檔啟動:
    docker compose --profile https up -d

在之後每次執行 docker compose up 時加上 --profile https,或在 .env 中設定 COMPOSE_PROFILES=https,以便普通的 docker compose up -d 也能包含它。Caddy 會將其憑證儲存在 https 磁碟區中。

Antimatter 自身的埠號仍會在主機上公開(HTTP_PORT,預設為 8065)。當 Caddy 位於前端時,請將其保留給伺服器本身使用:

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

Caddy 透過內部 edge 網路存取 Antimatter,而非透過該埠號,因此這對您的使用者不會有任何影響。

使用您自己的反向代理(nginx)

如果伺服器已經執行 nginx 或其他代理程式,請關閉 https 設定檔,並將代理程式指向 Antimatter 的 8065 埠。代理程式必須:

  • 傳遞 websocket 升級請求(網頁應用程式和行動應用程式會在 /api/v4/websocket 上保持 websocket 連線,某些應用程式會開啟自己的連線);
  • 接受至少與最大上傳檔案(最大檔案大小,預設為 100 MB)一樣大的請求主體;
  • 保持長生命週期連線開啟(websocket、大型上傳和下載);
  • 傳遞 Host 標頭和用戶端位址。

以下是完整的伺服器區塊,改編自 antimatter-docker 中的生產環境範本。請替換網域和憑證路徑:

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;
    }
}

使用 nginx -t 檢查檔案,並使用 systemctl reload nginx 套用設定。伺服器會自行發送 X-Content-Type-Options、Referrer-Policy、Permissions-Policy 和 X-Frame-Options;只有 HSTS 由代理程式負責。一旦 HTTPS 正常運作,請提高其 max-age,並僅在所有子網域都使用 HTTPS 時才加入 includeSubDomains。

如果使用 Docker Compose 且 nginx 執行在主機上,上述的 upstream 應指向已發布的 8065 埠。請僅在 127.0.0.1 上發布該埠(HTTP_PORT=127.0.0.1:8065),以防止任何人繞過代理程式。

antimatter-docker 儲存庫包含完整的設定,其中 nginx 執行在容器中,並透過 certbot 使用 Let's Encrypt,位於 deploy/compose。

其他代理程式

任何代理程式只要符合上述四點即可使用。通話的音訊和視訊從不經過代理程式:它們使用自己的埠,請參閱通話與語音。

代理程式後方的用戶端位址

在代理程式後方,每個請求看起來都來自代理程式。若要記錄真實的用戶端位址、依用戶端套用速率限制並使用 IP 過濾,請告知伺服器哪個標頭攜帶位址,以及它可以信任哪些代理程式。這兩個設定在系統控制台中沒有對應欄位:請在 config.json 中或使用變數設定。

金鑰與變數預設值功能說明
ServiceSettings.TrustedProxyIPHeader, AM_SERVICESETTINGS_TRUSTEDPROXYIPHEADER留空:伺服器使用連線的位址攜帶用戶端位址的標頭,例如 X-Forwarded-For。將使用請求中出現的第一個標頭。
ServiceSettings.TrustedProxyIPs, AM_SERVICESETTINGS_TRUSTEDPROXYIPS留空您的代理程式的位址或 CIDR 範圍,例如 172.29.71.0/28。這些標頭僅對來自其中一個代理程式的請求有效。

在變數中,使用空格分隔多個值:AM_SERVICESETTINGS_TRUSTEDPROXYIPHEADER="X-Forwarded-For X-Real-IP"。如果 TrustedProxyIPs 中的項目既不是 IP 位址,也不是 CIDR 範圍,伺服器將拒絕該設定。

伺服器如何找到客戶端的位址

每個代理程式都會將它收到請求的來源位址附加到 X-Forwarded-For 的右側。客戶端本身在標頭中傳送的內容則保留在左側。因此,伺服器會從右側讀取該標頭,略過您信任的代理程式位址,並將第一個其他位址視為客戶端位址。客戶端無法透過自行傳送標頭來選擇其位址。

  • 在單一代理程式後方,僅設定 TrustedProxyIPHeader 即可獲得正確的位址:伺服器會採用該標頭中最右側的位址。在您也設定 TrustedProxyIPs 之前,伺服器會在啟動時記錄警告。若未設定,任何能直接存取 8065 端口的使用者都可以設定該標頭,因此請僅在 127.0.0.1 或私人網路上公開該端口。
  • 在多個代理程式後方(例如在您自己的代理程式前方有 CDN 或負載平衡器),請將所有代理程式都列在 TrustedProxyIPs 中。否則,伺服器會將最外層代理程式的位址誤認為客戶端位址。
  • 代理程式可以用它看到的位址取代該標頭(如上方的 nginx 範例所示:X-Forwarded-For $remote_addr),或者附加到該標頭上(nginx 的 $proxy_add_x_forwarded_for)。兩者皆可運作。

要列出哪些位址

請列出代理程式請求的來源位址,也就是 Antimatter 所看到的位址。

  • 使用該網站的 compose 檔案和 Caddy 時,這已經完成:Caddy 透過 edge 網路連接到 Antimatter,而 compose 檔案將 TrustedProxyIPHeader 設定為 X-Forwarded-For,並將 TrustedProxyIPs 設定為該網路的範圍 EDGE_SUBNET(除非您在 .env 中修改,否則預設為 172.29.71.0/28)。如果 EDGE_SUBNET 與您的其他網路重疊,請予以修改。
  • antimatter-docker 中的生產環境設定對其 nginx 容器也採取相同做法,使用 FRONTEND_SUBNET。
  • 如果 nginx 位於主機上,而 Antimatter 在 Docker 中,請求會透過公開的端口到達 Antimatter,通常來自 compose 專案網路的閘道位址(可使用 docker network inspect 查看)。請在 compose.override.yaml 中將 AM_SERVICESETTINGS_TRUSTEDPROXYIPS 設定為該位址。
  • 若未使用 Docker,且 nginx 位於同一主機上,則為 127.0.0.1(若 nginx 透過 IPv6 連線,則為 ::1)。

無代理程式的 TLS

伺服器也可以自行提供 HTTPS,在 系統控制台 › 環境 › 網頁伺服器 中:連線安全性 設為 TLS(ServiceSettings.ConnectionSecurity),並設定 TLS 憑證檔案 和 TLS 金鑰檔案(ServiceSettings.TLSCertFile、ServiceSettings.TLSKeyFile),或 使用 Let's Encrypt(ServiceSettings.UseLetsEncrypt)。此時伺服器必須監聽 443 埠(監聽位址、ServiceSettings.ListenAddress,預設為 :8065),且 ServiceSettings.Forward80To443 會將 80 埠的流量轉發。反向代理較易執行與更新憑證,本指南即以此為前提。

伺服器逾時與請求大小

伺服器自身網頁伺服器的設定,位於 系統控制台 › 環境 › 網頁伺服器:

設定金鑰預設值
監聽位址ServiceSettings.ListenAddress:8065
讀取逾時ServiceSettings.ReadTimeout300 秒
寫入逾時ServiceSettings.WriteTimeout300 秒
閒置逾時(系統控制台中無對應欄位)ServiceSettings.IdleTimeout60 秒
最大有效負載大小(位元組數)ServiceSettings.MaximumPayloadSizeBytes請參閱 安全性

請確保代理程式自身的逾時時間至少與這些設定值相同,且其主體大小至少為 最大檔案大小。