Configure automatic backups for Discourse

Backblaze B2 자동 백업

**example.com**에 호스팅된 가상의 사이트를 위해 설정한 방법을 공유합니다.

  1. Backblaze 계정을 만듭니다 (현재 10GB 미만은 무료이므로 결제 정보를 입력할 필요가 없습니다)
  2. 버킷을 생성합니다 (Backblaze > B2 Cloud Storage)
    • 이름: $sitename-discourse-$random를 30자까지 채움
      • 이 예시에서는: example-discourse-g87he56ht8vg
      • Discourse는 버킷 이름에 소문자, 숫자, 대시만 허용합니다
      • Backblaze 웹 UI에서 줄바꿈 없이 잘 표시되도록 30자 이하로 유지하는 것을 권장합니다
    • 비공개 버킷
    • 암호화 활성화 (SSE-B2)
    • 오브젝트 락(Object Lock) 활성화
  3. 애플리케이션 키를 생성합니다 (Backblaze > Account > App Keys)
    • keyName: example-discourse
    • bucketName (Allow access to Bucket(s)): example-discourse-g87he56ht8vg
    • capabilities: 읽기 및 쓰기
    • namePrefix와 validDurationSeconds는 비워 둡니다
  4. Discourse B2 설정을 구성합니다 (Discourse > Admin > Settings)
    • backup_location: s3
    • s3_backup_bucket: example-discourse-g87he56ht8vg
    • s3_endpoint: 버킷 페이지에 표시됩니다 – https://를 앞에 붙여야 합니다
    • s3_access_key_id: (이전 단계에서 생성한 값)
    • s3_secret_access_key: (이전 단계에서 생성한 값)
      • Backblaze는 키를 한 번만 표시합니다(생성 시)!
    • 참고: 컨테이너 yml 파일에 환경 변수로 설정하는 것도 가능합니다. 이렇게 하면 해당 파일만으로 복구가 가능합니다:
env:
  ## Backblaze B2 Backups
  # DISCOURSE_BACKUP_LOCATION: 's3' # CLI에서 복구하려면 주석 해제
  DISCOURSE_S3_ENDPOINT: 'https://....backblazeb2.com'
  DISCOURSE_S3_BACKUP_BUCKET: 'example-discourse-g87he56ht8vg'
  DISCOURSE_S3_ACCESS_KEY_ID: '...'
  DISCOURSE_S3_SECRET_ACCESS_KEY: '...'
  # DISCOURSE_DISABLE_EMAILS: 'non-staff' # 테스트 복구 중 이메일 비활성화하려면 주석 해제
  ## 이 컨테이너 yml 파일 외의 데이터 없이 복구할 수 있습니다.
  ## 위의 DISCOURSE_BACKUP_LOCATION 주석을 해제하고 컨테이너를 빌드한 후 (./launcher rebuild ...),
  ## 컨테이너 내부에서 다음을 실행하세요 (B2 버킷에서 복구됩니다):
  ##   discourse enable_restore
  ##   discourse restore <example-com-...tar.gz> # B2 웹 UI에서 복구 파일 이름 선택
  ## 복구 후 복구 모드를 비활성화하는 것을 잊지 마세요
  1. 백업 보관 기간(retention)을 구성합니다
    • Discourse:
      • backup_frequency: 1 (이 예시에서는 매일 백업, 주간 백업도 가능합니다)
      • maximum_backups: 이 설정은 무시하세요 – Backblaze가 처리하도록 둡니다 :sunglasses:
      • s3_disable_cleanup: true (최대 허용 수를 초과할 때 S3에서 오래된 백업이 삭제되는 것을 방지합니다)
    • Backblaze (버킷 설정으로 이동):
      • Object Lock (Default Retention Policy): 7일
      • Lifecycle Settings (custom):
        • fileNamePrefix: default/example-com (선택 사항)
        • daysFromUploadingToHiding: 8일
          • 이는 오브젝트 락 기간 + 1일이어야 합니다
        • daysFromHidingToDeleting: 1일

요약하면, 이 예시의 보관 기간은 다음과 같습니다:

  • Discourse는 1일마다 백업을 생성합니다
  • 각 백업 파일은 B2에 업로드된 후 7일 동안 변경 불가능(immutable)합니다 (오브젝트 락). 이는 실수, 랜섬웨어 등으로부터 보호해 줍니다.
  • 업로드 후 8일이 지나면 백업의 오브젝트 락이 만료됩니다. 다시 변경 가능(mutable)해지므로 라이프사이클 규칙이 백업 파일을 숨길 수 있습니다.
  • 라이프사이클 규칙의 다음 단계는 숨겨진 파일이 1일 후에 삭제되도록 합니다

따라서 매일 백업이 생성됩니다. 백업이 절대 삭제될 수 없는 1주간의 보관 기간이 있고, 그 후 2일 뒤에 백업이 삭제됩니다. 즉, 실제로 백업은 약 9일간 유지됩니다.

도움이 되길 바랍니다 :slight_smile:


다시 생각해 보니, Discourse가 보관 기간(maximum_backups)을 처리하는 것이 더 나을 수 있습니다. 이렇게 하면 Discourse가 다운되어도 백업이 자동으로 만료되지 않습니다. 복구 작업을 하다가 시계가 흘러가는 상황을 원하지 않을 것입니다. 이 방식을 선택한다면, 이 예시에서는 maximum_backups=8과 s3_disable_cleanup=false를 설정하고 B2에서 라이프사이클 정책을 사용하지 않는 것이 좋습니다. 그래도 오브젝트 락 정책(7일)은 사용해야 합니다.

수정: 실제로는 B2 라이프사이클 정책이 여전히 필요하다고 생각합니다. S3 클라이언트가 파일을 삭제할 때 파일이 삭제되지 않고 ‘숨겨지는’ 것 같기 때문입니다. 저는 “Keep only the last version of the file” 정책을 사용 중인데, 이는 daysFromHidingToDeleting=1, daysFromUploadingToHiding=null과 동등합니다.

어느 접근 방식이 자신에게 적합한지 잘 생각해 보시길 권합니다.

참고로, 이 게시물에 오가는 내용이 있다는 것을 인식하고 있습니다. 현재 상태가 정보적으로 유용하다고 생각하지만, 누군가 원한다면 제 실제 권장 사항을 담은 좀 더 단순한 게시물을 따로 만들 수 있습니다.

7개의 좋아요