업로드를 위해 S3 호환 객체 저장소 제공자 구성하기

감사 인사를 해주셔서 감사합니다! 당시 편집 권한이 없어서 관리자의 주의를 끌기 위해 플래그를 달았었는데, 제가 작성한 게시물 덕분에 이제 권한을 얻게 되었습니다. 정말 아이러니하죠?

하지만 MinIO 섹션 밖에서 전역적인 안내 문구를 추가하기 전에, 이 게시물에서 제 편집을 시작하게 한 것처럼, Discourse 전체가 더 이상 도메인 기반 경로가 아닌 경로를 지원하지 않는지 확인할 수 있을까요?

만약 Discourse 전체가 경로 모드(예: minio.server.com/BUCKET/foo/bar/... 경로)를 지원하지 않고 도메인 경로(예: BUCKET.minio.server.com/foo/bar/...)만 지원한다는 것을 확실하게 알 수 있다면, 위키에 이를 전역 공지 사항으로 만들 수 있으며 저도 기꺼이 그렇게 하겠습니다. 다만, 저는 단순한 커뮤니티 멤버일 뿐이므로, 이것이 실제로 Discourse의 요구 사항이라는 것을 저보다 훨씬 위 계층의 누군가에게서 직접 듣는 것이 필요합니다. 만약 그렇다면 편집을 통해 반영하겠지만, 그렇지 않다면… 글쎄요, MinIO 필수 요건 섹션에 안내 문구로만 남겨두겠습니다.

2개의 좋아요

MinIO는 현재 비권장(deprecated)된 S3 경로 스타일(path style)을 사용해 온 유일한 인기 있는 S3 클론입니다. 따라서 전역적인 경고는 필요 없다고 생각하며, MinIO 섹션에만 언급하면 충분합니다.

4개의 좋아요

고마워요, Falco. MinIO 요구사항에 남겨뒀는데, 위에서 링크한 스레드에서 제가 왜 다시 언급하고 있는지 설명하고 있어서, 해당 주의사항 섹션에도 강조를 좀 더 했습니다.

2개의 좋아요

문제가 있는 것 같습니다:

입력한 내용:

  after_assets_precompile:
    - exec:
        cd: $home
        cmd:
          - sudo -E -u discourse bundle exec rake s3:upload_assets

재구축 결과:

FAILED
--------------------
Pups::ExecError: cd /var/www/discourse && sudo -E -u discourse bundle exec rake s3:upload_assets failed with return #<Process::Status: pid 2064 exit 1>
Location of failure: /usr/local/lib/ruby/gems/2.7.0/gems/pups-1.1.1/lib/pups/exec_command.rb:117:in `spawn'
exec failed with the params {"cd"=>"$home", "cmd"=>["sudo -E -u discourse bundle exec rake s3:upload_assets"]}
bootstrap failed with exit code 1
** FAILED TO BOOTSTRAP ** please scroll up and look for earlier error messages, there may be more than one.
./discourse-doctor may help diagnose the problem.
1개의 좋아요

가이드를 따를 수 있나요?

3개의 좋아요

OP에 S3의 오래된 자산을 정리하는 단계를 추가했습니다. GCP를 제외한 모든 곳에서 작동해야 합니다.

3개의 좋아요

rake s3:migrate_to_s3로 업로드된 17만 개 파일 중 대부분은 성공했지만, 12개 파일에서 다음과 같은 오류가 발생했습니다:

: Unsupported value for canned acl 'private' (Aws::S3::Errors::InvalidArgument)

이 파일들이 개인 메시지(PM)에 있었던 건가요? 이 문제를 해결할 수 있는 방법이 있을까요?

2개의 좋아요

Hey @Falco. 이게 맞나요? 이 토픽에서 30일 후 삭제 기능을 활성화할 수 있도록, 모든 답변이 처리되었는지 확인하고 있습니다.

개인용으로 표시된 몇몇 업로드를 확인해 보니 일반 토픽에 있었고, 왜 보안으로 표시되었는지 알 수 없었습니다. (보안 업로드가 설정되어 있지 않았나요?)

위 내용을 참고하세요.

2개의 좋아요

Secure Uploads는 AWS S3 전용이므로, 실제로는 해당 클론 서비스에서는 작동하지 않습니다.

2개의 좋아요

상당히 일리 있는 설명이네요. 해당 정보를 바탕으로 OP 상단을 업데이트했습니다. S3나 보안 업로드가 활성화되지 않은 사이트에서 로컬 업로드가 왜 보안으로 표시되었을까요? 혹시 원인을 아시는 분이 계신가요?

1개의 좋아요

누군가 잠깐 활성화했다가 작동하지 않는 것을 보고 되돌린 건가요?

2개의 좋아요

Cloudflare R2로 업로드하는 이 문제는 Upload.where(secure: true).update_all(secure: false)로 해결될 수 있다고 생각합니다. 이 메시지가 삭제되기 전에 해당 부분을 확인해 보겠습니다(다만 OP에 참고 사항을 추가해 두었습니다).

2개의 좋아요

음, 저희는 보안이 보장되는 업로드 기능이 없네요. 무료 한도가 꽤 관대하고 (베타) S3 마이그레이터도 있어서 Cloudflare R2를 시도해 볼 생각이에요. 결과를 두고 봐야겠지만, @pfaffman님 혹시 R2가 최종적으로 괜찮은지 확인해 보셨나요?

1개의 좋아요

이미지를 업로드하려고 했을 때 문제가 발생했는지, 아니면 단순히 새 이미지를 업로드했을 때였는지 더 이상 기억이 나지 않습니다. 다시 생각해보면, 완전히 새로운 사이트에서 테스트했을 것 같습니다.

다른 S3 플랫폼으로 이전하는 것은 다소 까다롭습니다. 이에 대한 주제들이 몇 가지 있지만, Cloudflare R2를 사용하려는 경우 테스트 사이트에서 먼저 시도해 보시는 것이 좋습니다. 작동하지 않을 가능성이 매우 높기 때문입니다.

1개의 좋아요

일종의 동작은 하지만, 프로덕션 환경에서 사용하기에는 아직 준비가 되지 않았습니다.

기존에 Discourse 2.7 로컬 개발용 인스톨이 하나 남아 있었는데, 이미지 업로드, CDN 사용, Cloudflare R2 설정 시 프라이빗 버킷으로의 백업 등 모든 기능이 정상적으로 작동했습니다. 최신 버전인 2.9(우리 포럼에서 사용하는 버전)로 업데이트했는데, Jobs::UpdateGravatar catch-up 처리 과정에서 실패하는 것 같습니다. 그 과정에서 Cloudflare R2에 그라바바 원격 이미지를 캐싱하려고 할 때 버킷 표기법을 잘못 사용하고 있습니다. (제 R2 버킷 이름이 'uploads’인 경우의 예시입니다):

Upload Update (0.3ms) UPDATE "uploads" SET "url" = '//uploads.123123redact.r2.cloudflarestorage.com/original/1X/123123example.jpeg', "updated_at" = '2022-12-12 20:44:02.929494', "etag" = '9c02b086b2aa5e2088ed44e1017fa63e' WHERE "uploads"."id" = 3

UI를 시작하면 로컬 테스트/개발 환경의 아바타들이 아래 주소로 지정되어 있습니다:

//uploads.123123redact.r2.cloudflarestorage.com/original/1X/123123example.jpeg

제 추측으로는 S3는 버킷 도트 표기(dot notation)를 문제없이 처리하지만 Cloudflare R2는 그렇지 않거나, 혹은 그라바바 캐싱에 S3 CDN 값을 사용해야 하는 것 같습니다. 꽤 잘 작동하는 것 같은데 아쉬운 부분이네요..

2개의 좋아요

Cloudflare로부터 R2의 경우, 객체 ACL을 올바르게 구현할 때까지 해당 속성에 아직 지원하지 않는 값이 들어오는 경우 200을 반환하도록 변경했다는 답변을 받았습니다. 이 변경된 동작은 apparently 11월 말경 R2에서 적용된 것 같습니다. 당연히 이상적이지는 않지만(공개 버킷인데 API에서는 비공개로 설정하도록 요청하고 있는 상황), 이 이슈에 대해서는 이제 '동작’합니다.

3개의 좋아요

오! 꽤 유망해 보이네요. 업로드를 위해 별도의 버킷이 필요할 것 같긴 한데, 백업 파일 이름을 추측하는 건 꽤나 추측 게임이 될 거예요.

지금 당장 바로 확인해 보겠습니다.

2개의 좋아요

저는 업로드용과 백업용 버킷을 별도로 사용하고 있으며, 실제로 잘 작동하는 것 같습니다. R2 백업 버킷은 공개로 설정되어 있지 않고, Discourse의 관리자 UI를 통해 압축된 백업 파일을 해당 버킷에 정상적으로 저장할 수 있었습니다. 파일을 다운로드해서 확인해 봤는데 이상한 점은 없었습니다(실제 복원 테스트는 아니지만, 월요일 아침에는 충분한 수준이었죠). 업로드 버킷은 S3_CDN에 커스텀 도메인 설정을 적용해 테스트해 봤는데, 이쪽도 잘 작동합니다.

솔직히 제 2.9 버전에서 ember-cli가 UI를 렌더링하지 못하는 문제가 정확히 무엇인지 파악이 잘 안 됩니다(관리자 사용자를 생성한 후 화면이 하얗게 변하거든요). 하지만 아마도 여러분이 보면 바로 원인을 찾을 수 있는 문제일 것입니다.

수정: 아, 플러그인의 JavaScript 에셋을 Pseudo-S3/R2에서 로드하려고 시도하는 것 같습니다. 예를 들어 assets/locales/en.br.js 같은 파일에서 404 오류가 많이 발생하고 있네요.

bundle exec rake s3:upload_assets 명령어로도 해결되지 않아, 현재로서는 이것이 가장 큰 단서입니다.

수정2: 네, 에셋 관련 문제인 것 같습니다. DISCOURSE_S3_CDN_URL을 비우면 UI가 정상적으로 로드되거든요. 당분간 에셋을 수동으로 해당 위치에 업로드하는 방식으로 시도해 보겠습니다.

수정3: 문제는 앱이 에셋이 사전 컴파일되어 DISCOURSE_S3_CDN_URL이 가리키는 위치에 존재해야 한다는 점이며, 로컬 개발 환경에서는 보통 그렇지 않습니다. @pfaffman 님이 어떤 것을 발견할지 궁금합니다. after_assets_precompile 훅을 R2에 사용하는 경우, 정식 Docker 배포된 자체 호스팅 인스턴스에서는 이 방식이 잘 작동할 것이라 생각합니다.

2개의 좋아요

그렇죠. 로컬 개발 환경에 CDN을 쓴다니 상상도 안 가네요. 그게 작동할 것 같지는 않아요. 프로덕션 배포에서는 괜찮을 것 같은 소리가 들리긴 합니다.

1개의 좋아요

역으로 생각해보니 개발 환경에서 예상치 못한 일은 아니었습니다. 제가 예상하지 못했던 점은 DISCOURSE_S3_CDN_URL을 R2용 Cloudflare CDN으로 설정했지만, DISCOURSE_CDN_URL은 비워두거나(또는 로컬 또는 ngrok)로 설정했는데도 불구하고, 업로드나 이미지뿐만 아니라 사전 컴파일된 애셋 등에도 여전히 Cloudflare pull URL을 사용하려 했다는 점입니다. 제대로 된 컨테이너로 프로덕션에서는 잘 작동할 것 같아서 일단 빠르게 테스트해볼까 합니다. 계획은 다음과 같습니다. 미디어 업로드를 임시로 TL4로 설정한 후, app.yaml에서 ID 등을 Cloudflare로 변경하고 테스트해본 뒤, 문제가 없다면 R2로 유지한 다음 rclone을 사용해 기존 S3 객체를 모두 이전합니다. 그 후에는 포스트를 다시 빌드하고, 모든 것이 정상적으로 작동하기를 바랍니다 :crossed_fingers:.

2개의 좋아요