도메인, 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이 잘못 설정되면 ID 제공자를 통한 로그인에 실패하고, 이메일 내 링크가 잘못된 위치를 가리키며, 앱이 연결되지 않을 수 있습니다. 도메인을 변경한 후에는 여기와 모든 ID 제공자의 리디렉션 URL을 업데이트해야 합니다.
번들된 Caddy 프로필을 사용한 HTTPS
사이트의 compose.yaml 파일에는 https 프로필에 Caddy 서비스가 포함되어 있습니다. 이 서비스는 Let's Encrypt에서 인증서를 발급받아 자동으로 갱신하고, HTTP를 HTTPS로 리디렉션하며, 웹소켓을 포함해 모든 트래픽을 Antimatter로 전달합니다.
- 도메인의 DNS 레코드(A, IPv6의 경우 AAAA)를 서버를 가리키도록 설정합니다.
- 방화벽에서 80/tcp, 443/tcp 및 443/udp(HTTP/3) 포트를 개방합니다. Let's Encrypt가 인터넷에서 포트 80 또는 443에 접근할 수 있어야 합니다.
- 도메인을
.env파일에 추가하고 사이트 URL을 설정합니다: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을 유지하며, 일부 앱은 자체 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 | 보안 참고 |
일반 요청에 대해 프록시 자체의 타임아웃은 위 값보다 길거나 같게, 바디 크기는 최대 파일 크기보다 크거나 같게 설정하세요.