域名、HTTPS 与反向代理

使用 compose 文件中的 Caddy 配置文件或您自己的反向代理,将 Antimatter 部署到带有 HTTPS 的域名上,并正确设置站点 URL 和客户端地址。

站点 URL

站点 URL(ServiceSettings.SiteURL)是用户访问 Antimatter 的地址,例如 https://chat.example.com。服务器会在电子邮件和通知中的链接、登录重定向(OAuth、OpenID Connect、SAML)、移动和桌面应用,以及验证请求来源时使用它。请将其设置为与浏览器地址栏中完全一致的地址:包括协议、域名,以及非默认端口(如有),末尾不要加斜杠。

  • 使用站点的 compose 文件时:在 .env 中设置 SITE_URL。
  • 其他位置:AM_SERVICESETTINGS_SITEURL,或 系统控制台 › 环境 › 网页服务器 › 站点 URL。

如果站点 URL 设置错误,使用身份提供商登录将会失败,电子邮件中的链接会指向错误的位置,且应用可能无法连接。更改域名后,请在此处以及所有身份提供商的重定向 URL 中更新该设置。

使用内置的 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 并设置站点 URL:
    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 升级(Web 应用和移动应用会在 /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参见 安全性

请确保代理自身的超时时间至少与这些值一样长,其请求体大小至少为 最大文件大小。