AWS CloudFront를 사용한 전체 사이트 CDN

안녕하세요. 최근 AWS CloudFront(CF)을 사용하여 전체 사이트 가속을 설정하고, CF에 있는 AWS 인증서를 이용해 SSL 오프로딩을 적용하여 Discourse 설치를 완료했습니다. 이 설치 방법은 공식 가이드의 CDN 및 SSL 구성과 다르기 때문에 논란이 될 수 있으며, 향후 지원 가능성에 문제가 될 수도 있습니다. 따라서 미리 경고드립니다… 여기에는 함정이 있습니다. 제가 성공적으로 적용한 구성을 공유합니다:

  1. Discourse가 포트 80에서만 경청하도록 설정하고, app.yml의 지정된 줄을 주석 처리하여 Let’s Encrypt를 비활성화합니다:

  2. Discourse가 x-forwarded-proto(CF는 이를 전달하지 않으며, 기원으로 전달하도록 구성할 수도 없어 정말 답답합니다! :angry:) 대신 CF 헤더인 cloudfront-forwarded-proto를 인식하도록 설정합니다.

  3. 생성한 AWS ACM 인증서를 사용하여 의도된 공개 호스트네임(예: forum.example.com)에 대한 CNAME으로 CF 배포를 설정합니다.

  4. Discourse를 호스팅하는 EC2 서버의 공개 엘라스틱 IP(예: ec2-xxx-xxx-xxx-xxx.compute-1.amazonaws.com)를 사용하여 CF 원시를 설정합니다. HTTP 전용(즉, 포트 80만, 443은 아님)으로 구성합니다. DNS에서 forum-origin.example.com과 같은 화려한 호스트네임으로 원시를 설정할 필요는 없습니다. ec2 호스트네임 또는 IP가 잘 작동합니다.

  5. 다른 요청 경로에 대해 CF "behaviors"를 설정합니다. 여기서 핵심은 명백히 정적 리소스인 것들에 대해 캐싱 동작을 구성하고, 나머지는 모두 캐싱하지 않도록 구성하는 것입니다(즉, 해당 요청은 캐싱 없이 그대로 원시로 전달됩니다). 또 다른 핵심은 마지막 패스스루 규칙(“default”)이 CF cloudfront-forwarded-proto 헤더 외에도 모든 원래 헤더를 원시로 전달하는 사용자 지정 "origin request policy"를 사용한다는 점입니다. 또한 behaviors에서 http에서 https로의 리다이렉트를 구성하여 모든 최종 사용자 요청이 CF에 의해 https로 강제되도록 합니다.

  6. "DISCOURSE_CDN_URL"을 구성하지 마십시오.

  7. "force https"를 활성화하십시오.

  8. "long polling base url"을 구성하지 마십시오 - 비워 두세요. 프록시를 통해 전달할 때 문제가 될 수 있다는 모든 심각한 경고에도 불구하고, 지금까지 제게는 잘 작동하고 있습니다. 아마도 CF의 기본 keep alive가 충분히 길어서 연결이 끊기는 것을 방지하는 것 같습니다.

이것으로 끝인 것 같습니다… :thinking:

최종 결과는 모든 요청, http/문서, 모든 지원 정적 리소스, 모든 ajax 호출 등이 모두 동일한 도메인 이름(예: forum.example.com)에서 서비스된다는 것입니다. 캐싱 동작(및 패스스루 동작)은 CF에서 구성한 "behaviors"에 의해 결정됩니다. 그리고 모든 연결은 CF 엣지에서 종결되는 AWS ACM 인증서를 사용하여 암호화되고, 이후 암호화되지 않은/http 트래픽이 원시 서버로 전송됩니다.

감히 말하건대, 이는 현재 meta.discourse.org에서 이루어지고 있는 것보다 더 깔끔할 수 있습니다 :shushing_face:.

안녕하세요 @jaffadog

저는 비슷한 상황을 겪고 있지만, 전체 사이트(full site)에 다른 CDN을 사용하고 있습니다. Jeremy님의 실험에서 웹사이트 도메인 URL을 DISCOURSE_CDN_URL로 설정하여 테스트해 보신 적이 있나요? 예를 들어, 전체 CDN 모드에서 웹사이트 URL이 https://foo.bar.com이라면, CDN URL 역시 https://foo.bar.com이어야 합니다. DISCOURSE_CDN_URL을 비워 두면 웹사이트 에셋 URL이 상대 경로로 시작하게 됩니다. 아래 스니펫과 같이요.

      <link rel="preload" href="/extra-locales/admin?v=8f522e122c802d1ed66dfa7fecafbb35" as="script">
<script defer src="/extra-locales/admin?v=8f522e122c802d1ed66dfa7fecafbb35"></script>

프로덕션 웹사이트에서는 이렇게 보이는 것이 별로 좋지 않지만, 두 URL 모두 https://foo.bar.com으로 요청을 보내게 됩니다.