Come configurare Cloudflare R2 per la tua Community Discourse

I bucket Cloudflare R2 possono essere utilizzati per archiviare asset statici come immagini e GIF per la community di Discourse, ma non possono essere utilizzati per archiviare backup della community!

Introduzione:

Cloudflare R2 object storage può essere utilizzato come alternativa ad Amazon S3 per archiviare caricamenti per il tuo forum Discourse. I passaggi seguenti descrivono come configurarlo.

Passaggi di configurazione:

  1. Abilita caricamenti S3: Seleziona la casella per abilitare i caricamenti S3 nelle impostazioni di Discourse.
  2. ID chiave di accesso S3: Inserisci l’ID della chiave API per il tuo bucket di archiviazione R2. Questo è l’ID fornito quando hai creato un token API per il tuo bucket.
  3. Chiave di accesso segreta: Inserisci la chiave segreta che è stata fornita quando hai creato il token API che concede l’accesso al tuo bucket di archiviazione. Importante: questa chiave segreta viene visualizzata solo una volta, quindi assicurati di effettuarne un backup sicuro.
  4. Regione S3: Puoi inserire qualsiasi regione, non ha importanza per R2.
  5. Bucket di caricamento S3: Inserisci il nome del tuo bucket di archiviazione R2.
  6. Endpoint S3: Inserisci il link API S3 per il tuo bucket R2, che è nel formato https://xxxxxx.com. Fai riferimento alla dashboard di Cloudflare R2 per trovare questo link.
  7. URL CDN S3: Inserisci l’URL pubblico del bucket di archiviazione R2.dev per il tuo bucket. Questo si troverà anche nella tua dashboard di Cloudflare R2.

Completamento:

Una volta configurate queste impostazioni, il tuo forum Discourse sarà impostato per utilizzare Cloudflare R2 per l’archiviazione.

Informazioni sul livello gratuito:

Il servizio R2 di Cloudflare fornisce un livello gratuito che include 10 GB di spazio di archiviazione, 1 milione di caricamenti e 1 milione di operazioni di lettura al mese.

5 Mi Piace

Ti consiglio di seguire gli esempi in Configurare un provider di archiviazione di oggetti compatibile con S3 per i caricamenti e di inserire le impostazioni nel tuo file yml anziché nel database.

Grazie per il tuo feedback. Ho letto attentamente la guida in precedenza e ritengo che il consiglio riguardante Cloudflare R2 sia errato. L’articolo suggerisce che la community di Discourse non supporti i bucket Cloudflare R2. Tuttavia, in realtà, Cloudflare R2 è altamente compatibile con S3 e può gestire perfettamente caricamenti e download di immagini e file per la community di Discourse. Questo è stato verificato attraverso l’applicazione pratica sulla mia community (starorigin.net).

1 Mi Piace

E sospetto che fosse vero quando è stato scritto.

È molto meglio inserire le impostazioni S3 nel file yml piuttosto che configurarle tramite l’UX e memorizzarle nel database. Hai provato a ripristinare il tuo database su un nuovo server?

Una volta che hai configurato le cose nel modo consigliato, puoi modificare quell’argomento o fare un commento e chiedere a qualcun altro di farlo.

1 Mi Piace

Hai ragione, uso un bucket di archiviazione Cloudflare R2 per archiviare le immagini, le GIF e altre risorse della mia community. Ciò riduce notevolmente il carico sul server della community e accelera il caricamento delle pagine.

Non ho configurato backup automatici per la mia community da archiviare nel bucket di archiviazione Cloudflare R2 perché i bucket Cloudflare R2 non supportano l’archiviazione di file compressi. Tuttavia, l’archiviazione Cloudflare R2 può archiviare PDF, immagini, GIF e altre risorse statiche della community, il che è anche molto buono.

Divertente. Pensavo di aver usato R2 per i backup in passato. Ma forse non ricordo correttamente.

Puoi comunque seguire le istruzioni consigliate e prendere nota di non mettere lì i backup.

Grazie per il promemoria, evidenzierò questa parte.

I bucket Cloudflare R2 possono essere utilizzati per archiviare asset statici come immagini e GIF per la community di Discourse, ma non possono essere utilizzati per archiviare backup della community!

Per aggiornare questo post, ho riscontrato alcuni problemi che dovevano essere inclusi prima che Cloudflare funzionasse per me.


1. Regione


Questo non era vero, ho dovuto usare “auto” o la regione che ho selezionato, auto è più facile quindi usa auto.
se hai bisogno di sapere quali opzioni puoi usare, prova con una stringa casuale qualsiasi nella tua regione e:

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

Se usi nixos

sudo discourse-rake s3:upload_assets

Questo genererà un errore per le tue opzioni valide


2. Permessi API


È anche importante sapere che i token API restrittivi non funzionano. Devi usare Admin Read & Write
Object Read & Write non ha funzionato

3 Mi Piace

Errore durante l’esecuzione di sudo -E -u discourse bundle exec rake s3:upload_assets @Eviepayne

Imposta la regione su automatico.
Potrebbe anche essere necessario impostare:
DISCOURSE_S3_INSTALL_CORS_RULE: false

Ho eseguito entrambi e ricostruito app.yml:

  ## Configurazione 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

Ho anche confermato che le chiavi API sono chiavi API dell’account anziché solo chiavi specifiche del bucket (come menzionato nel post). Inoltre, la mia istanza di Discourse mostra questo:

E dopo aver eseguito sudo -E -u discourse bundle exec rake s3:upload_assets mostra:

`/root` non è scrivibile.
Bundler utilizzerà `/tmp/bundler20250410-2363-zj2g6x2363' come directory home temporaneamente.
Installazione delle regole CORS...
saltando
rake interrotto!
Seahorse::Client::NetworkingError: Corpo della risposta vuoto o incompleto (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
(Vedi la traccia completa eseguendo il task con --trace)

Penso che potresti dover rimuovere il nome del bucket dall’endpoint.
La /xxx finale dovrebbe essere rimossa in modo che sia solo .com

Ricostruzione e rieseguirò il comando, grazie per l’aiuto!

Il mio app.yml ora è così:

  ## Configurazione 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

Credo che tutto ciò sia corretto.
Assicurati che il CDN_URL (https://pub-xxx.r2.dev)
abbia accesso in lettura pubblico in modo che gli utenti anonimi possano vedere gli asset.
Puoi vedere cosa sta succedendo negli strumenti per sviluppatori del browser. Otterrai un sacco di 403 e richieste rosse nella scheda di rete se le autorizzazioni sono errate.

Sì, credo di sì:

Questa è l’impostazione corretta:

Questo è un modo per farlo, ma non è il modo consigliato e si verificheranno problemi.
Supponendo che tu abbia già il tuo dominio e Cloudflare sia già il tuo DNS:

Cloudflare eseguirà automaticamente il proxy e potrà memorizzare nella cache quel dominio.
Puoi quindi modificare CDN_URL in quel dominio personalizzato.

Devo collegare il dominio personalizzato al bucket?

nelle impostazioni del bucket S3 c’è un’impostazione di accesso pubblico. imposta un sottodominio univoco per essa. (cloudflare creerà automaticamente anche il record DNS così come il proxy e la cache)

Penso di averlo?

Sei riuscito a far funzionare anche i backup su Cloudflare R2, ed è possibile (supponendo che i backup su Cloudflare R2 siano possibili) fare in modo che esegua il backup sia localmente che su Cloudflare R2?

Inoltre, lo script che carica tutte le risorse significa che le eliminerà localmente (per liberare spazio)? O c’è una procedura separata che devo eseguire?

Grazie per aver dedicato del tempo ad aiutarmi con questo :slight_smile:

Personalmente non ho provato.
Il mio forum rientra nella categoria “non supportata” perché il mio database è esterno e ho una strategia di backup diversa rispetto ai pg_dumps che utilizza il forum.
Da quello che sento, i backup non funzionano su cloudflare ma nulla ti impedisce di provarci.

1 Mi Piace