Comment configurer Cloudflare R2 pour votre communauté Discourse

Les buckets Cloudflare R2 peuvent être utilisés pour stocker des ressources statiques telles que des images et des GIF pour la communauté Discourse, mais ils ne peuvent pas être utilisés pour stocker des sauvegardes de communauté !

Introduction :

Le stockage objet Cloudflare R2 peut être utilisé comme alternative à Amazon S3 pour stocker les téléchargements de votre forum Discourse. Les étapes suivantes décrivent comment le configurer.

Étapes de configuration :

  1. Activer les téléchargements S3 : Cochez la case pour activer les téléchargements S3 dans vos paramètres Discourse.
  2. ID de clé d’accès S3 : Entrez l’ID de clé d’API pour votre bucket de stockage R2. Il s’agit de l’ID fourni lors de la création d’un jeton d’API pour votre bucket.
  3. Clé d’accès secrète : Entrez la clé secrète qui a été fournie lors de la création du jeton d’API accordant l’accès à votre bucket de stockage. Important : Cette clé secrète n’est affichée qu’une seule fois, assurez-vous donc de la sauvegarder en toute sécurité.
  4. Région S3 : Vous pouvez entrer n’importe quelle région, cela n’a pas d’importance pour R2.
  5. Bucket de téléchargement S3 : Entrez le nom de votre bucket de stockage R2.
  6. Point de terminaison S3 : Entrez le lien de l’API S3 pour votre bucket R2, qui est au format https://xxxxxx.com. Référez-vous au tableau de bord Cloudflare R2 pour trouver ce lien.
  7. URL CDN S3 : Entrez l’URL publique du bucket de stockage R2.dev pour votre bucket. Vous la trouverez également dans votre tableau de bord Cloudflare R2.

Achèvement :

Une fois ces paramètres configurés, votre forum Discourse sera configuré pour utiliser Cloudflare R2 pour le stockage.

Informations sur le niveau gratuit :

Le service R2 de Cloudflare offre un niveau gratuit qui comprend 10 Go de stockage, 1 million de téléchargements et 1 million d’opérations de lecture par mois.

5 « J'aime »

Je vous recommande de suivre les exemples de Configurer un fournisseur de stockage d’objets compatible S3 pour les téléchargements et de placer les paramètres dans votre fichier yml plutôt que dans la base de données.

Merci pour votre retour. J’ai lu attentivement le guide précédemment, et je pense que les conseils concernant Cloudflare R2 sont incorrects. L’article suggère que la communauté Discourse ne prend pas en charge les buckets Cloudflare R2. Cependant, en réalité, Cloudflare R2 est très compatible avec S3 et peut parfaitement gérer les téléchargements et les téléversements d’images et de fichiers pour la communauté Discourse. Cela a été vérifié par une application pratique sur ma communauté (starorigin.net).

1 « J'aime »

Et je soupçonne que c’était vrai au moment où il a été écrit.

Il est beaucoup mieux de mettre les paramètres S3 dans le fichier yml que de les configurer via l’UX et de les stocker dans la base de données. Avez-vous essayé de restaurer votre base de données sur un nouveau serveur ?

Une fois que vous avez configuré les choses de la manière recommandée, vous pouvez modifier ce sujet ou faire un commentaire et demander à quelqu’un d’autre de le faire.

1 « J'aime »

Vous avez raison, j’utilise un compartiment de stockage Cloudflare R2 pour stocker les images, les GIF et autres ressources de ma communauté. Cela réduit considérablement la charge sur le serveur communautaire et accélère le chargement des pages.

Je n’ai pas configuré de sauvegardes automatiques pour que ma communauté soit stockée dans le compartiment de stockage Cloudflare R2 car les compartiments Cloudflare R2 ne prennent pas en charge le stockage de fichiers compressés. Cependant, le stockage Cloudflare R2 peut stocker les PDF, images, GIF et autres ressources statiques de la communauté, ce qui est également très bien.

Drôle. Je pensais avoir déjà utilisé R2 pour des sauvegardes. Mais peut-être que je ne me souviens pas correctement.

Vous pouvez toujours suivre les instructions recommandées et prendre note de ne pas y mettre de sauvegardes.

Merci pour le rappel, je vais mettre en évidence cette partie.

Les buckets Cloudflare R2 peuvent être utilisés pour stocker des ressources statiques comme des images et des GIF pour la communauté Discourse, mais ils ne peuvent pas être utilisés pour stocker des sauvegardes de la communauté !

Juste pour mettre à jour ce post, j’ai eu quelques pièges qui devaient être inclus avant que Cloudflare ne fonctionne pour moi.


1. Région


Ce n’était pas vrai, j’ai dû utiliser “auto” ou la région que j’ai sélectionnée, auto est plus facile, donc utilisez auto.
si vous avez besoin de savoir quelles options vous pouvez utiliser, essayez avec n’importe quelle chaîne aléatoire dans votre région et :

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

Si vous utilisez nixos

sudo discourse-rake s3:upload_assets

Cela produira une erreur pour vos options valides.


2. Permissions API


Il est également important de savoir que les jetons d’API restrictifs ne fonctionnent pas. Vous devez utiliser Admin Read & Write
Object Read & Write n’a pas fonctionné.

3 « J'aime »

Erreur lors de l’exécution de sudo -E -u discourse bundle exec rake s3:upload_assets @Eviepayne

Définir la région sur auto.
Vous devrez peut-être également définir :
DISCOURSE_S3_INSTALL_CORS_RULE : false

J’ai fait les deux et reconstruit app.yml :

  ## Configuration S3
  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

J’ai également confirmé que les clés API sont des clés API de compte et non des clés spécifiques au bucket (comme mentionné dans le post). Mon instance Discourse affiche également ceci :

Et après avoir exécuté sudo -E -u discourse bundle exec rake s3:upload_assets, il affiche :

`/root` n'est pas accessible en écriture.
Bundler utilisera `/tmp/bundler20250410-2363-zj2g6x2363' comme répertoire personnel temporairement.
Installation des règles CORS...
en cours d'exécution
rake avorté !
Seahorse::Client::NetworkingError: Corps de réponse vide ou incomplet (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:24:in `should_skip?'
/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
(Voir la trace complète en exécutant la tâche avec --trace)

Je pense que vous devrez peut-être supprimer le nom du bucket du point de terminaison.
Le /xxx final doit être supprimé pour qu’il ne reste que .com.

Reconstruction et réexécution de la commande, merci de votre aide !

Mon app.yml ressemble maintenant à ceci :

  ## Configuration S3
  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

Je pense que tout cela est correct.
Assurez-vous que le CDN_URL (https://pub-xxx.r2.dev)
a un accès public en lecture afin que les utilisateurs anonymes puissent voir les ressources.
Vous pouvez voir ce qui se passe dans les outils de développement du navigateur. Vous obtiendrez un tas de 403 et de requêtes rouges dans l’onglet réseau si les autorisations sont incorrectes.

Oui, je crois bien :

Est-ce le bon réglage :

C’est une façon de faire, mais ce n’est pas la méthode recommandée, et vous rencontrerez des problèmes.
En supposant que vous ayez déjà votre domaine et que Cloudflare soit déjà votre DNS :

Cloudflare proxy automatiquement et peut mettre en cache ce domaine.
Vous pouvez ensuite changer le CDN_URL pour ce domaine personnalisé.

Ah, je dois connecter le domaine personnalisé au bucket ?

Dans les paramètres du compartiment S3, il y a un paramètre d’accès public.
Définissez un sous-domaine unique pour celui-ci. (Cloudflare créera automatiquement l’enregistrement DNS pour vous, ainsi que le proxy et le cache)

Je pense que j’ai compris ?

Avez-vous réussi à faire fonctionner les sauvegardes vers Cloudflare R2, et est-il possible (en supposant que les sauvegardes vers Cloudflare R2 soient possibles) de faire en sorte qu’elles soient sauvegardées à la fois localement et sur Cloudflare R2 ?

De plus, le script qui télécharge tous les actifs signifie-t-il qu’il les supprimera localement (pour libérer de l’espace de stockage) ? Ou y a-t-il une procédure distincte que je dois suivre ?

Merci de prendre le temps de m’aider avec ça :slight_smile:

Je n’ai pas essayé personnellement.
Mon forum entre dans la catégorie « non prise en charge » car ma base de données est externe et j’ai une stratégie de sauvegarde différente de celle des pg_dumps utilisés par le forum.
D’après ce que j’ai entendu, les sauvegardes ne fonctionnent pas sur Cloudflare, mais rien ne vous empêche d’essayer.

1 « J'aime »