So konfigurieren Sie Cloudflare R2 für Ihre Discourse-Community

Cloudflare R2 Buckets können zum Speichern statischer Assets wie Bilder und GIFs für die Discourse-Community verwendet werden, jedoch nicht zum Speichern von Community-Backups!

Einleitung:

Cloudflare R2 Object Storage kann als Alternative zu Amazon S3 für die Speicherung von Uploads für Ihr Discourse-Forum verwendet werden. Die folgenden Schritte beschreiben, wie Sie dies konfigurieren.

Konfigurationsschritte:

  1. S3-Uploads aktivieren: Aktivieren Sie das Kontrollkästchen, um S3-Uploads in Ihren Discourse-Einstellungen zu aktivieren.
  2. S3-Zugriffsschlüssel-ID: Geben Sie die API-Schlüssel-ID für Ihren R2-Speicher-Bucket ein. Dies ist die ID, die Sie bei der Erstellung eines API-Tokens für Ihren Bucket erhalten haben.
  3. Geheimer Zugriffsschlüssel: Geben Sie den geheimen Schlüssel ein, der bei der Erstellung des API-Tokens zur Gewährung des Zugriffs auf Ihren Speicher-Bucket bereitgestellt wurde. Wichtig: Dieser geheime Schlüssel wird nur einmal angezeigt. Sichern Sie ihn daher unbedingt.
  4. S3-Region: Sie können eine beliebige Region eingeben, für R2 spielt dies keine Rolle.
  5. S3-Upload-Bucket: Geben Sie den Namen Ihres R2-Speicher-Buckets ein.
  6. S3-Endpunkt: Geben Sie den S3-API-Link für Ihren R2-Bucket ein, der im Format https://xxxxxx.com vorliegt. Diesen Link finden Sie im Cloudflare R2-Dashboard.
  7. S3-CDN-URL: Geben Sie die öffentliche R2.dev-Speicher-Bucket-URL für Ihren Bucket ein. Diese finden Sie ebenfalls in Ihrem Cloudflare R2-Dashboard.

Abschluss:

Sobald diese Einstellungen konfiguriert sind, ist Ihr Discourse-Forum für die Verwendung von Cloudflare R2 zur Speicherung eingerichtet.

Informationen zur kostenlosen Stufe:

Der R2-Dienst von Cloudflare bietet eine kostenlose Stufe, die 10 GB Speicherplatz, 1 Million Uploads und 1 Million Leseoperationen pro Monat umfasst.

5 „Gefällt mir“

Ich empfehle, dass Sie die Beispiele in Konfigurieren Sie einen S3-kompatiblen Objektspeicheranbieter für Uploads befolgen und die Einstellungen in Ihrer yml-Datei anstatt in der Datenbank vornehmen.

Vielen Dank für Ihr Feedback. Ich habe die Anleitung zuvor sorgfältig gelesen und glaube, dass der Rat bezüglich Cloudflare R2 falsch ist. Der Artikel legt nahe, dass die Discourse-Community Cloudflare R2-Buckets nicht unterstützt. In Wirklichkeit ist Cloudflare R2 jedoch sehr gut mit S3 kompatibel und kann Bild- und Dateiuploads und -downloads für die Discourse-Community perfekt verarbeiten. Dies wurde durch praktische Anwendung in meiner Community (starorigin.net) verifiziert.

1 „Gefällt mir“

Und ich vermute, das war zur Zeit der Erstellung richtig.

Es ist viel besser, die S3-Einstellungen in der yml-Datei vorzunehmen, als sie über die Benutzeroberfläche zu konfigurieren und in der Datenbank zu speichern. Haben Sie versucht, Ihre Datenbank auf einen neuen Server wiederherzustellen?

Sobald Sie die Dinge auf die empfohlene Weise eingerichtet haben, können Sie dieses Thema bearbeiten oder einen Kommentar abgeben und jemanden anderen bitten, dies zu tun.

1 „Gefällt mir“

Sie haben Recht, ich verwende einen Cloudflare R2 Storage Bucket, um die Bilder, GIFs und andere Ressourcen meiner Community zu speichern. Dies reduziert die Auslastung des Community-Servers erheblich und beschleunigt das Laden von Seiten.

Ich habe keine automatischen Backups für meine Community eingerichtet, die im Cloudflare R2 Storage Bucket gespeichert werden sollen, da Cloudflare R2 Buckets das Speichern komprimierter Dateien nicht unterstützt. Cloudflare R2 Storage kann jedoch die PDFs, Bilder, GIFs und andere statische Ressourcen der Community speichern, was ebenfalls sehr gut ist.

Lustig. Ich dachte, ich hätte R2 schon einmal für Backups verwendet. Aber vielleicht erinnere ich mich nicht richtig.

Sie können die empfohlenen Anweisungen trotzdem befolgen und sich notieren, dort keine Backups zu speichern.

Vielen Dank für die Erinnerung, ich werde diesen Teil hervorheben.

Cloudflare R2-Buckets können zum Speichern statischer Assets wie Bilder und GIFs für die Discourse-Community verwendet werden, jedoch nicht zum Speichern von Community-Backups!

Nur um diesen Beitrag zu aktualisieren, gab es einige Stolpersteine, die ich einbeziehen musste, bevor Cloudflare für mich funktionierte.


1. Region


Das stimmte nicht, ich musste “auto” oder die von mir gewählte Region verwenden, auto ist einfacher, also verwenden Sie auto.
Wenn Sie wissen müssen, welche Optionen Sie verwenden können, versuchen Sie es mit einer beliebigen zufälligen Zeichenfolge in Ihrer Region und:

sudo -E -u discourse bundle exec rake s3:upload_assets

Wenn Sie NixOS verwenden

sudo discourse-rake s3:upload_assets

Dies gibt einen Fehler für Ihre gültigen Optionen aus


2. API-Berechtigungen


Es ist auch wichtig zu wissen, dass restriktive API-Tokens nicht funktionieren. Sie müssen Admin Read & Write verwenden.
Object Read & Write funktionierte nicht

3 „Gefällt mir“

Fehler beim Ausführen von sudo -E -u discourse bundle exec rake s3:upload_assets @Eviepayne

Region auf automatisch setzen.
Möglicherweise müssen Sie auch Folgendes festlegen:
DISCOURSE_S3_INSTALL_CORS_RULE: false

Ich habe beides getan und app.yml neu erstellt:

  ## S3-Konfiguration
  DISCOURSE_USE_S3: true
  DISCOURSE_S3_REGION: auto
  DISCOURSE_S3_ACCESS_KEY_ID: XXX
  DISCOURSE_S3_SECRET_ACCESS_KEY: XXX
  DISCOURSE_S3_CDN_URL: https://pub-XXX.r2.dev
  DISCOURSE_S3_ENDPOINT: https://XXX.r2.cloudflarestorage.com/XXX
  DISCOURSE_S3_BUCKET: XXX
  DISCOURSE_S3_INSTALL_CORS_RULE: false

Ich habe auch bestätigt, dass die API-Schlüssel Konto-API-Schlüssel und keine nur auf Buckets beschränkten Schlüssel sind (wie im Beitrag erwähnt). Außerdem zeigt meine Discourse-Instanz Folgendes an:

Und nach dem Ausführen von sudo -E -u discourse bundle exec rake s3:upload_assets wird Folgendes angezeigt:

`/root` ist nicht beschreibbar.
Bundler wird `/tmp/bundler20250410-2363-zj2g6x2363' vorübergehend als Ihr Home-Verzeichnis verwenden.
CORS-Regeln werden installiert...
übersprungen
rake abgebrochen!
Seahorse::Client::NetworkingError: Leerer oder unvollständiger Antwortkörper (Seahorse::Client::NetworkingError)
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/aws-sdk-core-3.219.0/lib/seahorse/client/plugins/raise_response_errors.rb:17:in `call'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/aws-sdk-s3-1.182.0/lib/aws-sdk-s3/plugins/sse_cpk.rb:24:in `call'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/aws-sdk-s3-1.182.0/lib/aws-sdk-s3/plugins/dualstack.rb:21:in `call'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/aws-sdk-s3-1.182.0/lib/aws-sdk-s3/plugins/accelerate.rb:43:in `call'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/aws-sdk-core-3.219.0/lib/aws-sdk-core/plugins/checksum_algorithm.rb:169:in `call'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/aws-sdk-core-3.219.0/lib/aws-sdk-core/plugins/jsonvalue_converter.rb:16:in `call'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/aws-sdk-core-3.219.0/lib/aws-sdk-core/plugins/invocation_id.rb:16:in `call'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/aws-sdk-core-3.219.0/lib/aws-sdk-core/plugins/idempotency_token.rb:19:in `call'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/aws-sdk-core-3.219.0/lib/aws-sdk-core/plugins/param_converter.rb:26:in `call'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/aws-sdk-core-3.219.0/lib/seahorse/client/plugins/request_callback.rb:89:in `call'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/aws-sdk-core-3.219.0/lib/aws-sdk-core/plugins/response_paging.rb:12:in `call'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/aws-sdk-core-3.219.0/lib/seahorse/client/plugins/response_target.rb:24:in `call'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/aws-sdk-core-3.219.0/lib/aws-sdk-core/plugins/telemetry.rb:39:in `block in call'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/aws-sdk-core-3.219.0/lib/aws-sdk-core/telemetry/no_op.rb:29:in `in_span'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/aws-sdk-core-3.219.0/lib/aws-sdk-core/plugins/telemetry.rb:53:in `span_wrapper'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/aws-sdk-core-3.219.0/lib/aws-sdk-core/plugins/telemetry.rb:39:in `call'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/aws-sdk-core-3.219.0/lib/seahorse/client/request.rb:72:in `send_request'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/aws-sdk-s3-1.182.0/lib/aws-sdk-s3/client.rb:12654:in `list_objects_v2'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/aws-sdk-s3-1.182.0/lib/aws-sdk-s3/bucket.rb:1513:in `block (2 levels) in objects'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/aws-sdk-core-3.219.0/lib/aws-sdk-core/plugins/user_agent.rb:69:in `metric'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/aws-sdk-s3-1.182.0/lib/aws-sdk-s3/bucket.rb:1512:in `block in objects'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/aws-sdk-core-3.219.0/lib/aws-sdk-core/resources/collection.rb:101:in `each'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/aws-sdk-core-3.219.0/lib/aws-sdk-core/resources/collection.rb:101:in `each'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/aws-sdk-core-3.219.0/lib/aws-sdk-core/resources/collection.rb:101:in `block in non_empty_batches'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/aws-sdk-core-3.219.0/lib/aws-sdk-core/resources/collection.rb:52:in `each'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/aws-sdk-core-3.219.0/lib/aws-sdk-core/resources/collection.rb:52:in `each'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/aws-sdk-core-3.219.0/lib/aws-sdk-core/resources/collection.rb:52:in `block in each'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/aws-sdk-core-3.219.0/lib/aws-sdk-core/resources/collection.rb:58:in `each'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/aws-sdk-core-3.219.0/lib/aws-sdk-core/resources/collection.rb:58:in `each'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/aws-sdk-core-3.219.0/lib/aws-sdk-core/resources/collection.rb:58:in `each'
/var/www/discourse/lib/tasks/s3.rake:14:in `map'
/var/www/discourse/lib/tasks/s3.rake:14:in `existing_assets'
/var/www/discourse/lib/tasks/s3.rake:36:in `upload'
/var/www/discourse/lib/tasks/s3.rake:197:in `block (2 levels) in <main>'
/var/www/discourse/lib/tasks/s3.rake:197:in `each'
/var/www/discourse/lib/tasks/s3.rake:197:in `block in <main>'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rake-13.2.1/exe/rake:27:in `<top (required)>'
/usr/local/bin/bundle:25:in `load'
/usr/local/bin/bundle:25:in `<main>'
Tasks: TOP => s3:upload_assets
(Siehe vollständige Spur durch Ausführen der Aufgabe mit --trace)

Ich glaube, Sie müssen den Bucket-Namen aus dem Endpunkt entfernen.
Das nachgestellte /xxx sollte entfernt werden, sodass es nur noch .com lautet.

Wird neu aufgebaut und wird den Befehl erneut ausführen, vielen Dank für Ihre Hilfe!

Meine app.yml sieht jetzt wie folgt aus:

  ## S3-Konfiguration
  DISCOURSE_USE_S3: true
  DISCOURSE_S3_REGION: auto
  DISCOURSE_S3_ACCESS_KEY_ID: XXX
  DISCOURSE_S3_SECRET_ACCESS_KEY: XXX
  DISCOURSE_S3_CDN_URL: https://pub-XXX.r2.dev
  DISCOURSE_S3_ENDPOINT: https://XXX.r2.cloudflarestorage.com
  DISCOURSE_S3_BUCKET: XXX
  DISCOURSE_S3_INSTALL_CORS_RULE: false

Ich glaube, das ist alles korrekt.
Stellen Sie sicher, dass die CDN_URL (https://pub-xxx.r2.dev)
öffentlichen Lesezugriff hat, damit anonyme Benutzer die Assets sehen können.
Sie können in den Entwicklertools des Browsers sehen, was vor sich geht. Wenn die Berechtigungen falsch sind, erhalten Sie viele 403er und rote Anfragen im Netzwerk-Tab.

Ja, ich glaube schon:

Ist dies die richtige Einstellung:

Das ist eine Möglichkeit, es zu tun, aber nicht die empfohlene Methode, und Sie werden Probleme haben.
Angenommen, Sie haben bereits Ihre Domain und Cloudflare ist bereits Ihr DNS:

Cloudflare wird automatisch als Proxy fungieren und Caching für diese Domain durchführen.
Sie können dann CDN_URL zu dieser benutzerdefinierten Domain ändern.

Muss ich die benutzerdefinierte Domain mit dem Bucket verbinden?

Innerhalb der S3-Bucket-Einstellungen gibt es eine Einstellung für den öffentlichen Zugriff.
Setzen Sie eine eindeutige Subdomain dafür. (Cloudflare erstellt automatisch den DNS-Eintrag sowie das Proxying und Caching für Sie.)

Ich glaube, ich habe es?

Haben Sie auch Backups für Cloudflare R2 zum Laufen gebracht, und ist es möglich (vorausgesetzt, Backups für Cloudflare R2 sind möglich), es so einzurichten, dass sowohl lokal als auch auf Cloudflare R2 gesichert wird?

Bedeutet das Skript, das alle Assets hochlädt, auch, dass sie lokal gelöscht werden (um Speicherplatz freizugeben)? Oder gibt es ein separates Verfahren, das ich dafür durchführen muss?

Vielen Dank, dass Sie sich die Zeit nehmen, mir dabei zu helfen :slight_smile:

Ich habe es persönlich noch nicht ausprobiert.
Mein Forum fällt in die Kategorie „nicht unterstützt“, da meine Datenbank extern ist und ich eine andere Backup-Strategie habe als die pg_dumps, die das Forum verwendet.
Soweit ich höre, funktionieren Backups nicht auf Cloudflare, aber nichts hindert Sie daran, es auszuprobieren.

1 „Gefällt mir“