Apache 리버스 프록시 뒤에 Discourse를 설정하려고 하는데, HTTPS로 제대로 작동하지 않습니다.
지금까지 이 지점까지 도달하는 데 많은 문제를 겪었습니다. 현재 서버에 Discourse를 설치하고, 그 앞에 Apache 서버를 리버스 프록시로 배치해 두었습니다. Discourse가 app.yaml에 설정된 호스트 이름으로 리디렉션하려고 해서 리버스 프록시 뒤에서 실행하는 것 자체가 많은 문제를 일으켰습니다.
어쨌든 지금은 작동은 하지만, 브라우저에서 혼합 콘텐츠(Mixed-content) 경고가 나타납니다.
Apache에 HTTP에서 HTTPS로의 리디렉트가 설정되어 있어 그 부분은 정상적으로 작동합니다. 하지만 Discourse가 여전히 일부 콘텐츠를 HTTP로 서빙하고 있는데, HTTPS로 변경하는 방법을 찾지 못하고 있습니다.
예를 들어, 파비콘(favicon)이 HTTP로 서빙되고 있는데, 이 부분을 어떻게 변경해야 할지 모르겠습니다.
Discourse가 HTTPS 트래픽을 직접 처리하지 않으면서도 모든 링크를 HTTPS로 변경하도록 할 수 있을까요?
Apache에서 다음을 설정해 보았지만 도움이 되지 않았습니다:
Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains"
Discourse의 force https 플래그를 활성화해도 마찬가지입니다. 이 경우 HTTP로 오는 모든 요청을 무시하게 되어 사이트가 깨져 버립니다.
혼합 콘텐츠 문제를 해결하기 위해 무엇을 해야 할까요?
답변 주셔서 감사합니다. 하지만 저는 Discourse와 동일한 서버에 Apache를 설치해 두지 않았습니다. 그 부분이 명확하지 않았던 것 같습니다.
저는 이미 여러 웹사이트를 호스팅 중인 기존 Apache 서버가 있고, 다른 서버에 있는 Discourse를 리버스 프록시해야 하므로 소켓을 사용할 수 없습니다.
마지막으로 그 설정을 apache2와 함께 사용해 봤을 때, discourse 메시지 버스에 대한 연결 실패가 발생했습니다. 이미 1년 넘게 지난 일이긴 하지만요. 사이트는 정상적으로 로드되는 것처럼 보였지만, F12 개발자 콘솔에서는 초기 몇 번의 시도 후 wss 연결이 타임아웃되었다고 명확히 표시되어 있었습니다.
Discourse는 웹사이트가 아닌 애플리케이션입니다. 초기 JavaScript 페이로드가 브라우저로 전달된 후, 많은 기능이 Discourse 서버와의 빠르고 안정적인 연결에 의존합니다. 다른 시스템을 통해 프록시 처리를 하면 지연 시간이 발생하여 사용자 경험이 크게 저하됩니다.
리버스 프록시를 사용하는 이유는 많습니다.
예를 들어, 공용 IP가 하나뿐인데 포트 80/443으로 여러 웹 서버를 대외 공개해야 하고, 해당 웹 서버에서는 이 예시처럼 Discourse를 실행할 수 없는 경우가 있습니다.
SSL 오프로딩으로 사용하여 최종 서버가 암호화를 처리하지 않도록 할 수 있습니다.
리버스 프록시 뒤에 최종 서버를 배치하면 공격 표면이 줄어듭니다.
합법적인 이유가 많음에도 불구하고, 이것이 불가능한 이유를 이해할 수 없습니다.
잠시 후, 이미 Apache 서버 뒤에 Discourse가 실행 중인 다른 서버가 있으며, 최소 2년 동안 잘 작동해 왔다는 것을 떠올랐습니다. 새로운 Discourse를 동일한 방식으로 설정했지만, 일부 콘텐츠를 http로 서빙하는 것을 멈추게 할 수 없습니다. 두 Discourse 서버 간의 유일한 차이는 구버전이 2.4, 신버전이 2.5로 실행되고 있다는 점이며, 이 사이에 차이가 있는지 알 수 없습니다.
첫 번째 게시글에서 언급했듯이 force_https는 사이트를 깨뜨려 로그인, 초대 수락 등이 불가능하게 만듭니다. http로 서빙되는 것으로 보이는 일부 JavaScript가 실행되지 않는 것 같습니다. force_https가 링크를 폐기하는 대신 모든 http 링크를 https로 재작성하도록 하는 것이 더 합리적이지 않나요? 최소한 옵션으로 제공해 주면 좋겠습니다.
Discourse를 대외 공개하기 위한 권장 설정 방법은 무엇인가요? DMZ에 자체 외부 IP가 있는 서버를 설정하는 것이 권장되나요?
리버스 프록시 뒤에 실행해야 하는 이유는 여러 가지가 있습니다. Discourse.org의 인프라가 HAproxy 뒤에 실행되고 있다고 확신합니다.
저는 traefik과 caddyserver를 사용하며, 과거에 nginx, HAproxy, 심지어 apache까지도 동작하도록 설정해 본 경험이 있습니다(서브폴더 설치 환경의 워드프레스용).
이것이 당신의 문제입니다. force_https를 활성화하고 왜 깨지는지 파악해야 합니다. 이를 끄는 것은 옵션이 아닙니다. 당신은 무료 지원을 요청했고, 응답한 사람들은 apache에 대한 해결책을 가지고 있지 않으므로, 당신은 apache 밴드의 리더가 되어야 합니다.
현재 저희는 메인 마이그레이션을 스테이징하는 서버를 제외하고, 프로덕션, 테스트 및 스테이징 환경의 모든 사이트에서 “리버스 프록시를 사용하는 두 개의 컨테이너” 구성을 사용하고 있습니다.
이유는 postgres, mysql, discourse 앱 코드를 모두 단일 컨테이너에서 실행할 때 다양한 마이그레이션 스크립트를 실행하기가 더 쉽기 때문입니다. 이는 프로덕션 환경이 아니므로 디버깅하기도 쉽습니다. 하지만 문제가 없음을 확인하면 백업을 프로덕션으로 이동하여 복원합니다.
이 구성의 한 가지 문제는, 리버스 프록시를 갖춘 초고성능 두 컨테이너 구성이라 하더라도 DB가 하나만 존재하기 때문에 DB 복원 중 발생하는 다운타임을 상쇄할 수 없다는 점입니다.
향후에는 DB 컨테이너를 두 개 사용하여 하나를 복원하고 데이터 측면에서도 전환할 수 있는 구성을 시도해 볼 수 있을 것입니다.
아니면, 더 좋게 말하면, 다른 이름의 데이터베이스로 복원한 후 실시간으로 전환하는 방법이 있지만, 아직 어떻게 해야 하는지 모릅니다. 프로덕션 DB 이름을 discourse에서 discourse2로 변경하는 코드가 어디에 있는지, 앱을 전체적으로 다시 빌드하지 않고 변경할 수 있는 방법을 아신다면 알려주시면 좋겠습니다 아마 창의적이고 혁신적인 @pfaffman 수석 컨설턴트가 아실지도 모르겠네요?
업데이트: templates/postgres.template.yml 파일에 있습니다
(여기서 postgres 폴더 관련 mv 명령어가 몇 가지 흥미롭게 보입니다 :). )
스탠드얼론과 멀티 컨테이너 구성 모두 장단점이 있지만, 프로덕션 환경에서는 리버스 프록시를 사용하는 두 컨테이너 구성을 완전히 채택했습니다. 마이그레이션 테스트와 스테이징 환경에서는 스탠드얼론 구성이 저희에게 가장 적합합니다.
Apache2에 관해서는, 리버스 프록시를 하나의 서버에서, 컨테이너를 다른 서버에서 설정하고 테스트할 시간을 가졌으면 합니다. 죄송합니다…
또한, 두 컨테이너 구성에서 DB 복원을 수행할 때 사이트를 가동 상태로 유지하는 방법을 찾아내야 합니다. (지금 보니) templates/postgres.template.yml 템플릿은 단일 스탠드얼론 컨테이너 구성에 맞춰져 있는 것 같습니다.
이것이 문제의 원인은 아닙니다. @pfaffman 님이 위에서 언급했듯이 (최소 두 번, 메타의 최상위 마이그레이션 전문가 중 한 분):
“반드시” force_https = true를 유지한 상태에서 "실제 문제"를 찾아야 합니다.
제가 그 자리에 있다면, 제가 읽은 내용들을 바탕으로.
첫째, 문제 해결을 단순화하기 위해 테스트 및 트러블슈팅 목적으로만 리버스 프록시를 discourse 컨테이너와 동일한 서버에 설정하겠습니다. 이 간단한 테스트 케이스가 완벽하게 작동하는지 확인하세요. 그런 다음, 동일한 호스트에서 작동하는 것을 확인한 후, 해당 테스트용 리버스 프록시를 끄고 원하는 이중 서버 구성으로 이동하세요.
이것은 흥미로운 문제입니다. force_https = true를 유지하고 체계적이고 단계적인 트러블슈팅 방법을 유지하면 이 문제를 해결할 수 있습니다. 이러한 유형의 문제는 해결되길 바라는 IT 퍼즐에 불과합니다.
당신은 할 수 있습니다.
P.S.: 이 퍼즐에 지치거나 지루해지면, 항상 @pfaffman 또는 다른 경험 많은 메타 직원에게 돈을 지불하여 이 장애물을 넘게 하고 앞으로 더 나은 미래를 향해 나아갈 수 있습니다.
참고: 우리는 동일한 서버에서 유닉스 도메인 소켓을 사용하여 Apache2를 리버스 프록시로 설정하는 데 전혀 문제가 없었습니다. 두 서버 구성을 설정하고 두 다른 서버에서 Apache2 리버스 프록시 방법을 작동시킬 개인적인 시간이 없다는 점에 진심으로 사과드립니다. 우리는 "미친 bbcode 남용"을 마크다운으로 정리하는 최종 마이그레이션 작업으로 바쁘며, 원래 예상했던 것보다 더 많은 시간이 소요되고 있습니다.
새 환경으로 Discourse를 마이그레이트한 후 로그인 시 POST 세션에서 HTTP 403 오류가 발생하고 있습니다. CSRF 문제라고 추측되지만, 현재 디버깅을 어디서 시작해야 할지 막막한 상태입니다. /var/log/discourse-var-log/production.log와 production_error.log 파일 모두 0바이트 상태입니다…
이 문제를 올바르게 디버깅하는 방법에 대한 아이디어가 있으신가요?
현재 구성은 다음과 같습니다: 1. haproxy를 중앙 HTTPS 로드 밸런서/가속기로서 사용 (Discourse 및 기타 서비스 모두 대상)
forum >> develd apache rev. proxy p.82
backend forum-backend
mode http
server forum.netzwissen.de 10.10.10.14:83 cookie A check
http-request set-header X-Forwarded-Port %[dst_port]
http-request add-header X-Forwarded-Proto https if { ssl_fc }
# HSTS 헤더, 16000000초: 약 6개월 이상
http-response set-header Strict-Transport-Security "max-age=16000000; includeSubDomains; preload;"
2. 로컬 apache를 리버스 프록시로 사용
<IfModule proxy_module>
## <https://meta.discourse.org/t/running-other-websites-on-the-same-machine-as-discourse/17247>
ProxyPreserveHost On
# ProxyRequests Off
RequestHeader set X-Forwarded-Proto expr=%{REQUEST_SCHEME}
RequestHeader set X-Real-IP expr=%{REMOTE_ADDR}
ProxyPass / unix:/var/discourse/shared/web-only/apache.http.sock|http://localhost/
ProxyPassReverse / unix:/var/discourse/shared/web-only/apache.http.sock|http://localhost/
</IfModule>
3) Discourse는 별도의 web_only와 data 컨테이너로 운영되며, web_only는 "templates/web.socketed.template.yml"로 배포됨
CSRF 관련 사항이나 nginx에 대해 잘 모르지만 (외부 웹서버는 apache 2.4입니다), CSRF가 제 문제일 것이라고 확신합니다. Discourse는 로그인 없이 정상적으로 작동하며, 로그인에 사용되는 POST 요청만 여기서 실패하기 때문입니다. 제 중앙 haproxy의 내부 IP는 10.10.10.21이므로, web_only 컨테이너의 discourse.conf yml 파일에 다음을 추가했습니다:
set_real_ip_from 10.10.10.21/24;
기본값인 127.0.0.1/24;로 시도해 보기도 했지만, 둘 다 로그인 시 동일한 403 오류가 발생합니다.