Patreon 로그인, HTTPS 강제, S3 CDN(세 가지) 문제

이 내용을 세 개의 별도 게시글로 나누어야 할 수도 있지만, 서로 관련이 있으므로 하나부터 시작하겠습니다.

며칠 전, 이 튜토리얼(How to Scale a Discourse Deployment with a Load Balancer and Managed Database Cluster | DigitalOcean)을 거의 그대로 따라하며 Digital Ocean의 스탠드얼론 Discourse Droplet을 로드 밸런서 안의 두 Droplet으로 마이그레이션했는데,까지는 잘 진행되었습니다.

그 다음 이 튜토리얼(Configure an S3 compatible object storage provider for uploads)을 따라갔지만, 커맨드 라인에서 Discourse를 재빌드한 후 제 Discourse 사이트는 백색 화면만 표시되었습니다. 브라우저의 개발자 도구(Inspector)를 확인해 보니, 콘텐츠가 HTTPS가 아닌 HTTP로 서빙되고 있기 때문에 브라우저가 모든 콘텐츠를 차단하고 있었습니다. 이는 아마도 로드 밸런서가 SSL 터미네이션(SSL Terminated)을 수행하고 있기 때문일 것입니다. 즉, 외부에서는 모두 HTTPS이지만, 서버 자체는 HTTP로 실행되고 있는 것이죠.

이 시점에서 로드 밸런서 내에서 HTTPS로 작동하게 하려고 시도하다 서버를 완전히 망가뜨렸지만, 그것은 단순히 불가능했습니다. 이 튜토리얼(Configure an S3 compatible object storage provider for uploads)에 따라 Digital Ocean Space/CDN을 S3/CDN으로 작동하게 만드는 데 실패했습니다. 아주 꼼꼼하게 여러 번 모든 측면을 검토했지만, 작동하지 않았습니다. Discourse를 재빌드할 수 있었던 유일한 방법은 app.yml에서 DISCOURSE_S3_ENDPOINT: https://sfo3.digitaloceanspaces.com 파라미터를 제거하는 것이었지만, 그렇게 해도 빌드는 되었으나 서버에 응답을 받을 수 없었습니다. 로드 밸런서와 DO Space/CDN 설정을 어떻게 조합하느냐에 따라 503 서버 응답 없음错误或, 일반적인 브라우저 서버 응답 없음 또는 서버 연결 끊김 오류가 발생했습니다. 가능한 모든 설정 조합을 시도해 보았지만, 페이지를 서빙할 수 있는 방법은 찾지 못했습니다.

DISCOURSE_S3_ENDPOINT 파라미터를 그대로 두면 Discourse 재빌드 중 다음과 같은 오류가 발생했지만, S3_ENDPOINT 파라미터를 주석 처리하면 이 오류는 사라졌습니다.
Aws::S3::Errors::InvalidAccessKeyId: Aws::S3::Errors::InvalidAccessKeyId

모든 파일이 S3에 동기화되었으므로, 액세스 키에는 문제가 없었을 것이라고 생각하며, 문제는 S3_ENDPOINT 파라미터 때문에 발생한 것으로 추정됩니다.

오늘은 이전 시도를 계속하는 것을 포기하고, HTTP만 로드 밸런싱하던 Droplet의 백업을 복원한 후, 이 튜토리얼(Set up file and image uploads to S3)을 수행하여 마침내 다시 작동하게 만들었습니다. 다만 이번에는 권장 튜토리얼에서처럼 app.yml을 편집하여 S3 설정을 한 것이 아니라, Discourse 관리자 패널을 통해 S3 설정을 편집했습니다. 마침내 작동했지만, 중요한 차이는 제가 의도적으로 S3 CDN 설정을 제외했다는 것입니다. 게시글에 업로드된 이미지가 S3에 저장되고 있음을 확인했고, Discourse를 S3로 직접 백업할 수 있으며, 이것이 제가 원하는 전부이지만, 이제 저를 괴롭히는 세 가지 문제가 있습니다. 그중 하나는 치명적이고, 두 가지는 무시할 수 있지만, 가능하다면 여기서 확인해 보고 싶습니다.

즉, 치명적인 문제는 사용자가 더 이상 Discourse 로그인 페이지의 Patreon 로그인 버튼으로 로그인할 수 없다는 것입니다. 다음과 같은 메시지가 표시됩니다:
죄송합니다. 계정 인증 중 오류가 발생했습니다. 다시 시도해 주세요.

URL은 다음과 같습니다:
https://mbp.community/auth/failure?message=invalid_credentials&origin=https%3A%2F%2Fmbp.community%2Flogin&strategy=patreon

이를 작동하게 하려면 무엇을 시도해 볼 수 있는지 조언을 정말로 듣고 싶습니다. 하지만 다시 한번, 내부적으로 서버가 HTTPS로 실행되지 않기 때문일지 궁금합니다. URL에서 볼 수 있듯이 외부에서는 HTTPS로 실행되고 있으므로, 확실히 알기 어렵습니다. 아마도 여기에서 Digital Ocean 로드 밸런싱 등을 Discourse와 함께 사용해 본 경험이 있는 분이 계실 것이라 기대합니다.

나머지 두 문제는 관리 콘솔에서 다음과 같이 경고되고 있습니다:

현재 사이트 설정에 기반한 조언

  • 웹사이트는 SSL을 사용 중입니다. 그러나 [force_https](https://mbp.community/admin/site_settings/category/all_results?filter=force_https)가 아직 사이트 설정에서 활성화되어 있지 않습니다.
  • 서버는 파일을 S3로 업로드하도록 구성되었지만, S3 CDN이 구성되지 않았습니다. 이로 인해 높은 S3 비용과 느린 사이트 성능이 발생할 수 있습니다. 자세한 내용은 "업로드용 오브젝트 스토리지 사용"을 참고하세요.

force_https를 켜는 것을 시도해 보는 것은 괜찮지만, 내부적으로 로드 밸런싱된 서버가 HTTPS로 실행되지 않기 때문에 서버에 접근이 차단될까 봐 걱정됩니다. 그리고 어제 겪었던 문제들로 인해, Discourse를 15분씩 수없이 재빌드하면서도 아무런 진전도 없이 벽에 머리를 부딪는 12시간을 더 보내고 싶지 않습니다. 다시 한번, 제 구성에서 force_https를 켜는 것이 안전하다는 것을 아시는 분이 계시다면 알려 주세요.

두 번째 문제는 다시 한번 app.yml 파일에 추가된 파라미터를 통해 시도했을 때 잘 작동하지 않았기 때문에, 이것도 다시 시도하기가 꺼려집니다. 이것이 app.yml 파일에 추가된 파라미터와 본질적으로 동일한 효과를 내는지 확인해 주실 수 있나요? 그렇다면 이 두 번째 메시지는 무시하겠습니다. 반대로, 어떤 이유로든 시도하는 것이 안전하다면 알려 주세요. 백업을 하고 시도해 보겠습니다.

긴 게시글을 올려 죄송합니다. 제가 조언을 구하려는 것이 무엇인지 파악해 주실 수 있기를 바랍니다.

그렇다면 실제로 도움이 필요합니다. 여기에서 공식적으로 지원하는 것은 표준 설치뿐이므로요.

하루 페이지 뷰가 200,000회 이상을 예상하나요? 아니라면, CDN이 적용된 단일 8GB Droplet을 사용하는 것이 관리가 훨씬 쉽고 아마도 더 저렴할 것입니다. 제가 볼 때, 그 지침은 아무에게도 작동하지 않을 가능성이 높은 부분이 최소 두 군데 있습니다.

첫째, 5단계에 설명된 대로 외부 Redis를 설정했나요? 아니라면, 시스템이 적어도 약간은 깨져 있을 것으로 예상됩니다. 그들은 sticky 세션을 사용하면 이를 "수정"한다고 암시하지만, 실제로는 그렇지 않습니다. 따라서 진단하기 어려운 무작위 오류가 발생할 수 있습니다. 또한 모든 인스턴스가 정확히 동일한 버전의 Discourse를 실행하도록 보장하는 방법을 명시하지 않아, 이것 또한 시스템이 깨지는 원인이 될 가능성이 높습니다.

실제로는 그 작업을 먼저 해야 했습니다. 그렇지 않으면, 실제로 그 설정은 작동할 수 없습니다. 왜냐하면 일부 업로드는 한 서버에, 일부는 다른 서버에 저장되기 때문입니다. 그리고 그 지침에는 "업로드"라는 단어조차 언급되지 않으므로, 테스트 이상으로 이를 사용해 왔다면 상당한 혼란 상태에 빠졌을 것이며, 여러 Droplet 간의 업로드를 동기화해야 할 것입니다.

그 튜토리얼은 Digital Ocean CDN이 Discourse와 함께 작동하지 않는다고 명시하고 있습니다.

권장된 대로 다른 CDN을 사용했나요? Bunny.net은 설정이 꽤 쉽고 간단합니다.

아, 그 가이드를 누가 썼는지 모르겠지만, 확실히 대규모 Discourse에 대해 잘 아는 사람이 쓴 것은 아니었습니다.

마지막 단계에서는 Droplet 스냅샷 기능을 사용하여 로더 밸런서에 더 많은 백엔드를 추가할 수 있다고 안내하지만, 가이드에서 업로드에 객체 스토리지를 사용하는 방법에 대해 언급하지 않기 때문에 그렇게 하면 사용자 업로드가 완전히 깨집니다. 또한 그 가이드를 따르게 되면 업데이트 과정이 간단하지 않게 됩니다.

@Martin_Bailey 님께 드리는 조언은 거기 있는 내용을 따라 하지 마시라는 것입니다. 이미 경험하신 것처럼 깨진 설치 환경만 초래할 뿐입니다.

빠르고 합리적인 Discourse 설치를 원하신다면 공식 설치 가이드를 따르시기 바랍니다. 그 경로에서 벗어나면 금세 전업으로 해야 할 일이 될 수 있습니다.

유머러스하네요. 저는 거기에 몇 가지 문제를 정리하고 라파엘의 게시물을 링크하는 댓글을 남겼는데, 삭제되어 있었어요.

와! 잘 된 줄 알았어요. 물론 몇 가지 잘못된 점을 발견했지만, 이제 로드 밸런싱이 적용된 환경을 갖추게 됐거든요. 그런데 제일 먼저 발견한 문제는 이미지 업로드가 깨져 있다는 거였어요. 그래서 이미지를 S3에 저장하도록 했죠.

현재 상황으로는 단일 서버로 돌아가려면 또 한 트럭 분량의 작업이 필요할 것 같은데, 패트레온 로그인 문제는 어떻게 해결할 수 있을까요? 나머지 두 문제는 무시하겠습니다.

어쨌든 도움 주셔서 감사합니다. 여기에서 정말 잘하고 계신 것 같아요.

제이, 도움을 주셔서 감사합니다. 질문에 대한 답변은 다음과 같습니다.

이것은 폐쇄적인 Patreon 커뮤니티이기 때문에 많은 사용자를 기대하고 있지는 않습니다. 제 주요 목표는 사이트가 다운되지 않으면서도 서버 하나를 업데이트할 수 있는 것이었습니다. 실제로 이것이 가능하다는 것을 확인했기 때문에 현재 설정에 만족하고 있었습니다. 네, 5단계도 수행했으므로 상태(state)는 외부 Redis 드롭렛에 저장되고 있습니다.

잠시 동안 저를 막았던 또 다른 문제는 app.yml에 아래 매개변수도 추가해야 한다는 것이었습니다. 그렇지 않으면 실제 포트가 DISCOURSE_DB 매개변수에 설정되어 있음에도 불구하고 재빌드 시 기본 포트의 Postgres에 연결을 시도하려고 해서 계속 실패했습니다.

DISCOURSE_DB_BACKUP_PORT: 25060

처음 튜토리얼을 기반으로 모든 것이 작동하도록 설정한 후에야 업로드를 생각하게 되었습니다. 처음에는 S3를 설정하려고 했을 때 모든 것이 깨졌지만, 그 이유는 여기에서 여러분이 제공하는 DO Space CDN 설정이 작동하지 않기 때문이었습니다.

Digital Ocean CDN은 Discourse와 함께 작동하지 않는다고 명시적으로 나와 있습니다.

알고 있습니다. 하지만 튜토리얼에서 이렇게 추가하라고 합니다:
DISCOURSE_S3_ENDPOINT: https://sfo3.digitaloceanspaces.com

이것은 DO Space에서 온 것이죠? 제가 이 튜토리얼에서 읽은 모든 것을 바탕으로 다른 CDN을 어떻게 사용해야 하는지 전혀 모르겠습니다. 하지만 곧 설명드릴 것처럼, 이 시점에서는 걱정하지 않습니다.

아니요, 다른 CDN을 사용하지 않았습니다. 실제로 CDN을 사용하지 않는 것이 괜찮습니다. CDN 설정을 비워둘 것입니다. 추가로, 지금까지 여러분이 친절하게 제공해 주신 조언을 바탕으로 지난주 백업으로 되돌리려 했다가, 먼저 force_https 옵션을 활성화해 보려고 했습니다. 그리고 예상대로 그것을 활성화하니 Patreon 로그인 문제가 해결되었습니다. 서버에서 변경된 것이 없었으므로 Patreon 로그인 문제는 아마도 Discourse 내부 로직으로 인해 발생한 것으로 보입니다. 다만, (지금에서야) 제가 권장하거나 지원되지 않는 것을 하고 있다는 점을 인식하고 있습니다.

따라서 이 시점에서 제 설정은 첫 번째 튜토리얼에서 권장하는 것과 거의 동일하지만, 이미지와 백업은 모두 CDN 없이 S3로 전송됩니다. 정말 잘 작동하고 있습니다. 스탠드얼론 설치만 사용하라고 권장하시는 점은 이해하지만, 업데이트가 나올 때마다 15분씩 사이트를 다운시키는 것은 정말 고통스럽습니다. 바로 어제 멀티서버 설정을 위한 data.yml과 web_only.yml에 대한 여러분의 언급을 찾았지만, 제가 무엇을 해야 하는지 이해할 수 없어서 그 부분은 포기했습니다.

지금은 현재 가지고 있는 설정대로 진행할 것입니다. 도움을 주셔서, 그리고 여러분이 하시는 모든 일에 감사드립니다.

알겠습니다, 여러분이 이겼네요. :slight_smile:

이미지가 http로 공유되는 경우가 있어 https로 공유되지 않으면 다시 로드되지 않는 문제가 더 자주 발생하기 시작했거든요. 여러분이 맞아요, 정말 엉망이었네요.

결국 대부분의 설정을 되돌렸습니다. Postgres 데이터베이스는 그대로 두되, 로드 밸런서를 제거하고 서버 드롭렛을 하나로만 남겼으며, 이미지와 Redis는 로컬에 저장하도록 했습니다. 다만 사이트 백업용 S3는 그대로 유지했습니다. 그 방식이 얼마나 부드럽게 작동하는지 정말 마음에 듭니다.

아마도 업그레이드할 때마다 15분 정도 중단되는 상태로 돌아간 것 같습니다. 하지만 이 문제로 이미 총 5일 정도를 소비했고, 더 이상 시간을 쓸 수 없으니, 제가 처음 따랐던 그 튜토리얼에 대해 여러분이 제 생각을 바로잡아 주셔서 감사합니다. 마치 사람들이 더 많은 드롭렛을 구매하도록 유도하려는 것처럼 느껴집니다. :slight_smile:

다시 한번 도움을 주셔서 감사합니다.

실제로 하나만 여쭤봐도 될까요? 업데이트 시마다 발생하는 15분간의 장애를 피할 수 있도록 Discourse를 설정하는 방법이 담긴 튜토리얼이 있는지요. data.yml과 web_only.yml에 대한 참고사항은 확인했지만, 이를 위해 무엇을 해야 하는지 전혀 감이 잡히지 않습니다.

별도의 data와 web_only yml 파일이 있는 이유는 두 개의 컨테이너로 구성된 환경 때문입니다:

이 방법은 작동하며 일부 문제를 해결해 줄 것입니다. 만약 다른 (어떤) 이유로 인해 잠금 상태가 될 경우에도 항상 launcher enter app 명령으로 다시 진입하여 Rails 콘솔에서 사이트 설정을 원래대로 되돌릴 수 있습니다.

다른 분들이 이미 말했듯이, 다른 가이드를 따르는 것이 더 좋습니다.

여러분 안녕하세요,

저는 해당 DigitalOcean 기사를 작성한 사람입니다. 몇 가지 실수를 저질렀네요. 죄송합니다!

문제를 수정하기 위해 기사를 업데이트하고 싶습니다.

수정된 버전에서 내용을 정확히 반영하기 위해 몇 가지 질문을 드리고자 합니다.

기사에서 Managed Redis 인스턴스를 선택적으로 사용할 수 있다고 언급했는데, 당시 제 생각은 스티키 세션(sticky sessions)을 사용하면 Discourse 이미지 내장 Redis를 사용할 수 있을 것이라는 것이었습니다. 이것이 맞을까요? 아니면 이것이 충분하지 않아 외부 Redis 인스턴스가 필수 요구 사항이 되어야 하는 것일까요.

@Falco 님의 Object Storage에 대한 의견에 동의합니다. 제 실수였습니다. 이미지 업로드를 처리하기 위해 DigitalOcean Spaces를 사용하는 방법을 기사에 추가하겠습니다.

Droplet에서 모든 상태를 제거하는 것이 설치 문제를 해결하는 방법이라고 생각합니다. 스티키 세션 덕분에 외부 Redis 사용이 선택적일 것이라고 기대했지만, 제 생각이 틀렸을 수도 있습니다.

이 방식이 Discourse 설치 업그레이드를 더 복잡하게 만든다는 점에도 동의합니다. 다만 Droplet에서 모든 상태를 제거하면 Droplet 하나만 업그레이드한 후 스냅샷을 찍고, 나머지 Droplet을 해당 스냅샷으로 생성된 새 Droplet으로 교체하면 될 것이라고 생각합니다. (Kubernetes Deployments와 비슷하지만, 재배치를 수동으로 수행하는 방식입니다.)

Discourse를 확장하는 더 나은 방법이 있을 것이라고 생각하지만, 그래도 사람들이 따라 할 수 있도록 기사를 수정하고 싶습니다.

감사합니다.
Francis

저는 Digital Ocean의 만족스러운 고객이며, 클라이언트들이 API 키와 호스트명을 입력하면 자동으로 드롭렛을 생성하고, Mailgun을 설정하고, DNS 레코드가 설정될 때까지 대기한 다음 Discourse를 설치하는 대시보드를 가지고 있습니다.

제안하신 대로 전혀 작동하지 않습니다. Digital Ocean에 당신의 포럼을 통해 연락을 했습니다(다른 방법을 찾을 수 없었기 때문에) 알려드리려 했는데, 제 메시지는 삭제되었습니다. 그리고 9개월 후에야 여기에 답글을 남기셨습니다.

올바르게 실행하는 것은 꽤 복잡한 작업이며, 유용할 만한 경우는 상당히 드뭅니다. 저는 8GB 드롭렛에서 하루 10만 페이지뷰를 기록하는 사이트를 운영하고 있습니다. 이 가이드의 대상 독자가 누구라고 생각하시나요?

네, 외부 Redis, Postgres, 그리고 CDN이 있는 S3 버킷이 필요하고, Digital Ocean의 CDN은 작동하지 않으므로 당신의 가이드는 다른 회사의 CDN을 설정하는 방법을 안내해야 합니다. 당신이 그렇게 하기를 원하지 않을 것 같습니다. 그리고 그것은 설정하는 것뿐입니다. 만약 그들이 업그레이드를 원한다면, 그것은 지구의 다른 누구도 어떻게 도와줄지 모를 또 다른 절차가 될 것입니다.

당신이 할 수 있는 가장 좋은 일은 그 가이드를 아예 삭제하는 것입니다. 진정한 영웅이 되고 싶다면, 이메일 설정 등에 자체적인 스크립트를 사용하지 않도록 1클릭 설치를 수정하여 실제로 표준 설치와 같게 만들 수 있습니다. Discourse에 도달하기 위해 Ctrl+C를 눌러야 하는 것은 꽤 혼란스럽고, 1클릭을 사용한 사람들은 표준 Discourse 도구를 사용하지 않았기 때문에 커맨드라인 업그레이드 시점에 어떻게 사용하는지 모릅니다. 당신이 그렇게 해준다면 정말, 정말 좋겠습니다.

여기서 그것을 사용하다가 어려움을 겪은 사람들을 볼 수 있습니다: Search results for 'digital ocean one-click' - Discourse Meta

아니요, Redis는 단순한 캐시가 아니라 카운팅, 레이트 리미트, 백그라운드 작업, pub sub 등을 처리하기 때문입니다. 여러 개의 Redis를 사용하면 카운팅이 손상되고 동작이 깨집니다.

그렇게 하면 해결되겠지만, 관리형 Redis, 관리형 PostgreSQL, 관리형 로드 밸런서, 객체 저장소, 컨테이너 레지스트리를 추가하는 것은 표준 호스팅 비용을 지불하는 것보다 훨씬 비싸고 유지보수도 훨씬 복잡해집니다.

그 시점에서, 월 수백 달러를 지불하되 SPOF(단일 장애 지점)로 인해 서비스가 중단되는 것에 신경 쓰지 않는 사람들의 교집합은 매우 작으며, 이는 포럼 관리자에게 권장하는 것보다 더 취미용 설정에 가깝게 됩니다.