網域、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。
- 將您網域的 DNS 記錄(A 記錄,IPv6 則加上 AAAA 記錄)指向伺服器。
- 在防火牆中開啟 80/tcp、443/tcp 和 443/udp(HTTP/3)埠號。Let's Encrypt 必須能從網際網路存取埠號 80 或 443。
- 將網域加入
.env並設定網站網址:echo "DOMAIN=chat.example.com" >> .env sed -i 's|^SITE_URL=.*|SITE_URL=https://chat.example.com|' .env - 使用該設定檔啟動:
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.ReadTimeout | 300 秒 |
| 寫入逾時 | ServiceSettings.WriteTimeout | 300 秒 |
| 閒置逾時(系統控制台中無對應欄位) | ServiceSettings.IdleTimeout | 60 秒 |
| 最大有效負載大小(位元組數) | ServiceSettings.MaximumPayloadSizeBytes | 請參閱 安全性 |
請確保代理程式自身的逾時時間至少與這些設定值相同,且其主體大小至少為 最大檔案大小。