ドメイン、HTTPS、リバースプロキシ

AntimatterをHTTPS対応のドメイン名に配置します。composeファイルのCaddyプロファイルまたは独自のリバースプロキシを使用し、サイト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 にあります。

その他のプロキシ

上記の4つの条件を満たすプロキシであれば、何でも使用できます。通話の音声と動画はプロキシを通過しません。独自のポートを使用します。通話と音声を参照してください。

プロキシ背後のクライアントアドレス

プロキシの背後では、すべてのリクエストがプロキシから来たように見えます。実際のクライアントアドレスをログに記録し、クライアントごとのレート制限や 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 の右側に追加します。クライアントがヘッダー自体に送信した内容は左側に残ります。そのため、サーバーはヘッダーを右から読み取り、信頼できるプロキシのアドレスをスキップし、最初の他のアドレスをクライアントのアドレスとして採用します。クライアントは独自のヘッダーを送信してアドレスを指定することはできません。

  • プロキシが1つの場合、TrustedProxyIPHeader だけで正しいアドレスを取得できます。サーバーはヘッダーの右端のアドレスを採用します。TrustedProxyIPs も設定するまで、起動時に警告がログに記録されます。設定しないと、ポート 8065 に直接アクセスできる誰でもヘッダーを設定できてしまうため、そのポートは 127.0.0.1 またはプライベートネットワークでのみ公開してください。
  • プロキシが複数ある場合(例: 自社プロキシの前に CDN やロードバランサーがある場合)、TrustedProxyIPs にすべてをリストアップしてください。そうしないと、サーバーは外側のプロキシのアドレスをクライアントのアドレスとして採用してしまいます。
  • プロキシは、上記の nginx の例のように (X-Forwarded-For $remote_addr) 確認したアドレスでヘッダーを置き換えるか、追加 ($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、Docker に Antimatter を配置する場合、リクエストは公開ポート経由で 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
ReadタイムアウトServiceSettings.ReadTimeout300 秒
WriteタイムアウトServiceSettings.WriteTimeout300 秒
アイドルタイムアウト(システムコンソールにフィールドなし)ServiceSettings.IdleTimeout60 秒
最大ペイロードサイズ (バイト)ServiceSettings.MaximumPayloadSizeBytesセキュリティを参照

プロキシ自身のタイムアウトは、通常のリクエストに対してこれらの値以上、ボディサイズは 最大ファイルサイズ 以上に設定してください。