Impossibile configurare il bucket S3

Ciao,

Sto cercando di configurare i caricamenti S3 e sembra che i caricamenti funzionino correttamente, ma le richieste GET falliscono per uno strano motivo. Sembra che discourse stia aggiungendo un “.cn” all’URI dell’oggetto caricato.

Dopo aver caricato l’immagine nel mio bucket S3, l’URL pubblico è:

https://hobig...bucket-eu.s3.eu-central-1.amazonaws.com/original/1X/5e894113...48918.jpeg

ma quando ispeziono il browser, il mio forum discourse sta cercando di caricare (nota il .cn)

https://hobig...bucket-eu.s3.eu-central-1.amazonaws.com.cn/original/1X/5e894113...48918.jpeg

Qualcuno sa perché sta succedendo questo?

Ecco le mie impostazioni di amministrazione:

Dovresti seguire le istruzioni in Configurare un provider di storage di oggetti compatibile con S3 per i caricamenti e/o Set up file and image uploads to S3 e inserire tali impostazioni nel tuo file yml anziché nel database/UX.

Non è necessario configurare un endpoint per AWS. Vuoi configurare una CDN.

1 Mi Piace

Ciao @pfaffman,

Sembra che tu possa aver inavvertitamente incollato la stessa guida due volte.

Quando menzioni “impostazioni nel tuo file yml”, potresti chiarire a quale file YAML ti riferisci? Stai forse parlando del file app.yml situato nella cartella /var/discourse/containers?

Inoltre, se configuro la mia integrazione S3/CloudFront direttamente tramite il file YAML, tali impostazioni sovrascriveranno quelle configurate nella sezione admin di Discourse?

Grazie!

Mi dispiace. Uno di questi avrebbe dovuto essere Set up file and image uploads to S3.

Vedi gli argomenti collegati che descrivono come configurare S3, ma sì, app.yml è ciò che vuoi cambiare (poiché non hai menzionato web_only.yml)

Sì. Inserirli nel file YML li nasconde dall’interfaccia utente.

Ciao @pfaffman,

Ho il mio bucket S3, la configurazione di CloudFront e l’origine di CloudFront impostata sul mio bucket S3. Ecco la mia attuale configurazione di app.yml:

ENV:
  DISCOURSE_USE_S3: true
  DISCOURSE_S3_REGION: eu-central-1
  DISCOURSE_S3_ACCESS_KEY_ID: AKIAWPLPUxxxxxx
  DISCOURSE_S3_SECRET_ACCESS_KEY: PaXQu7pKxxxx
  DISCOURSE_S3_CDN_URL: https://dsuxxxhrz2qn.cloudfront.net
  DISCOURSE_S3_BUCKET: hobigxxxxbucket-eu

Dopo aver ricostruito l’app con ./launcher rebuild app, quando visito il sito web, viene visualizzato solo il loader senza caricare nulla. Ispezionando la scheda di rete, ho scoperto che non riesce a recuperare gli asset statici precompilati (principalmente .js), il che presumo sia perché non sono nel mio bucket S3. Puoi controllarlo qui: forum.hobiguru.com.

Ho anche provato a eseguire il task di migrazione rake, ma senza successo:

root@ubuntu-s-1vcpu-1gb-fra1-01-app:/var/www/discourse# rake uploads:migrate_to_s3 --trace


** Invoke uploads:migrate_to_s3 (first_time)
** Invoke environment (first_time)
** Execute environment


** Execute uploads:migrate_to_s3
Si prega di notare che la migrazione a S3 non è attualmente reversibile!
[CTRL+c] per annullare, [ENTER] per continuare
Migrazione degli upload a S3 per 'default'...
Alcuni upload non sono stati migrati al nuovo schema. Eseguendo la migrazione, questo potrebbe richiedere del tempo...
rake aborted!
FileStore::ToS3MigrationError: Alcuni upload non hanno potuto essere migrati al nuovo schema. Devi risolverlo manualmente. (FileStore::ToS3MigrationError)
/var/www/discourse/lib/file_store/to_s3_migration.rb:156:in `migrate_to_s3'
/var/www/discourse/lib/file_store/to_s3_migration.rb:59:in `migrate'
/var/www/discourse/lib/tasks/uploads.rake:126:in `migrate_to_s3'
/var/www/discourse/lib/tasks/uploads.rake:106:in `block in migrate_to_s3_all_sites'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rails_multisite-6.1.0/lib/rails_multisite/connection_management/null_instance.rb:49:in `with_connection'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rails_multisite-6.1.0/lib/rails_multisite/connection_management/null_instance.rb:36:in `each_connection'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rails_multisite-6.1.0/lib/rails_multisite/connection_management.rb:21:in `each_connection'
/var/www/discourse/lib/tasks/uploads.rake:104:in `migrate_to_s3_all_sites'
/var/www/discourse/lib/tasks/uploads.rake:100:in `block in <main>'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rake-13.2.1/lib/rake/task.rb:281:in `block in execute'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rake-13.2.1/lib/rake/task.rb:281:in `each'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rake-13.2.1/lib/rake/task.rb:281:in `execute'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rake-13.2.1/lib/rake/task.rb:219:in `block in invoke_with_call_chain'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rake-13.2.1/lib/rake/task.rb:199:in `synchronize'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rake-13.2.1/lib/rake/task.rb:199:in `invoke_with_call_chain'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rake-13.2.1/lib/rake/task.rb:188:in `invoke'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rake-13.2.1/lib/rake/application.rb:188:in `invoke_task'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rake-13.2.1/lib/rake/application.rb:138:in `block (2 levels) in top_level'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rake-13.2.1/lib/rake/application.rb:138:in `each'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rake-13.2.1/lib/rake/application.rb:138:in `block in top_level'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rake-13.2.1/lib/rake/application.rb:147:in `run_with_threads'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rake-13.2.1/lib/rake/application.rb:132:in `top_level'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rake-13.2.1/lib/rake/application.rb:83:in `block in run'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rake-13.2.1/lib/rake/application.rb:214:in `standard_exception_handling'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rake-13.2.1/lib/rake/application.rb:80:in `run'
bin/rake:13:in `<top (required)>'
/usr/local/lib/ruby/gems/3.3.0/gems/bundler-2.5.18/lib/bundler/cli/exec.rb:58:in `load'
/usr/local/lib/ruby/gems/3.3.0/gems/bundler-2.5.18/lib/bundler/cli/exec.rb:58:in `kernel_load'
/usr/local/lib/ruby/gems/3.3.0/gems/bundler-2.5.18/lib/bundler/cli/exec.rb:23:in `run'
/usr/local/lib/ruby/gems/3.3.0/gems/bundler-2.5.18/lib/bundler/cli.rb:455:in `exec'
/usr/local/lib/ruby/gems/3.3.0/gems/bundler-2.5.18/lib/bundler/vendor/thor/lib/thor/command.rb:28:in `run'
/usr/local/lib/ruby/gems/3.3.0/gems/bundler-2.5.18/lib/bundler/vendor/thor/lib/thor/invocation.rb:127:in `invoke_command'
/usr/local/lib/ruby/gems/3.3.0/gems/bundler-2.5.18/lib/bundler/vendor/thor/lib/thor.rb:527:in `dispatch'
/usr/local/lib/ruby/gems/3.3.0/gems/bundler-2.5.18/lib/bundler/cli.rb:35:in `dispatch'
/usr/local/lib/ruby/gems/3.3.0/gems/bundler-2.5.18/lib/bundler/vendor/thor/lib/thor/base.rb:584:in `start'
/usr/local/lib/ruby/gems/3.3.0/gems/bundler-2.5.18/lib/bundler/cli.rb:29:in `start'
/usr/local/lib/ruby/gems/3.3.0/gems/bundler-2.5.18/exe/bundle:28:in `block in <top (required)>'
/usr/local/lib/ruby/gems/3.3.0/gems/bundler-2.5.18/lib/bundler/friendly_errors.rb:117:in `with_friendly_errors'
/usr/local/lib/ruby/gems/3.3.0/gems/bundler-2.5.18/exe/bundle:20:in `<top (required)>'
/usr/local/bin/bundle:25:in `load'

La mia intenzione originale era di utilizzare S3 solo per archiviare gli upload degli utenti e ho aggiunto il CDN solo per gestirli. Tuttavia, ora sto affrontando un nuovo problema: gli asset statici della mia app vengono serviti anche tramite CDN, cosa che non avevo previsto. :confused:

C’è un modo per caricare tutti gli asset statici al lancio dell’app nel bucket S3 e poi farli servire tramite CDN, o un modo per servire solo gli upload degli utenti tramite CDN, o c’è una soluzione migliore per questo?

Forse mi manca ancora qualcosa di ovvio? Non lo so.
Grazie per il tuo aiuto!

Sospetto che sia perché non hai seguito le istruzioni.

Sì. Capisco. È possibile, ma non sei riuscito a farlo funzionare. Questo è il modo consigliato; è ben documentato e centinaia di persone lo fanno in questo modo.

1 Mi Piace

Mi dispiace, hai ragione, ho saltato quella parte. Ho aggiunto quanto segue nel mio app.yml e ora sta caricando correttamente il forum:

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

Tuttavia, i caricamenti degli utenti non funzionano ancora correttamente. Dopo il caricamento nel bucket S3 (correttamente), l’immagine viene servita come:

//my-bucket-eu.my-bucket-eu/original/1X/7f242572bdb45b65ded727c13366fe490541358f.jpeg

che ovviamente non è un percorso S3 o CDN valido.

Nella guida a cui ti riferisci c’è questa sezione che sembra pertinente:

DISCOURSE_CDN_URL è una CDN che punta al tuo hostname Discourse e memorizza nella cache le richieste. Verrà utilizzata principalmente per gli asset "pullable": CSS e altri asset del tema.

DISCOURSE_S3_CDN_URL è una CDN che punta al tuo bucket di object storage e memorizza nella cache le richieste. Verrà utilizzata principalmente per gli asset "pushable": JS, immagini e caricamenti utente.

Raccomandiamo che questi siano diversi e che gli amministratori impostino entrambi.

Tuttavia, non sono sicuro di cosa impostare come DISCOURSE_CDN_URL? Dovrei impostarlo allo stesso valore di DISCOURSE_S3_CDN_URL: https://dsxxxxx2qn.cloudfront.net o creare un’istanza CDN separata?

Di nuovo, forse è qualcosa di totalmente diverso :confused:

Grazie mille per tutto l’aiuto!

Devi configurare la CDN e utilizzarla con il tuo dominio desiderato sul lato AWS. Più nel DNS.

Ma perché? Praticamente nessuno vede mai quell’URL.

1 Mi Piace

Ciao Jake, non sono sicuro di capire bene cosa intendi. Potresti spiegare un po’ meglio?

Intendevi forse che invece di impostare il bucket S3 come origine della CDN, dovrei impostare il mio dominio forum.hobiguru.com come origine? Se è così, non credo che cambierebbe nulla dato che è il forum discourse a generare quegli URL che non portano da nessuna parte, ad esempio //my-bucket-eu.my-bucket-eu/original/1X/7f242572bdb45b65ded727c13366fe490541358f.jpeg

Ho aggiunto anche DISCOURSE_CDN_URL: https://dsuxxxhrz2qn.cloudfront.net e ora sto aspettando che l’app si ricostruisca :crossed_fingers:

AGGIORNAMENTO: no, anche questo non ha funzionato :confused:

Apprezzo molto l’aiuto.
Grazie

Non puoi semplicemente nominare un sottodominio solo in app.yml. Nessuno può usarlo senza le corrette informazioni DNS. E poiché la distribuzione dei tuoi file avviene da AWS, devi configurare anche quel lato, se vuoi usare la CDN.

Ma di nuovo. Gli utenti vedono l’URL di Discourse, se vogliono vederlo. Molto raramente qualcun altro oltre a un amministratore sta facendo qualcosa che lo desidera. E gli utenti praticamente non vedono mai l’URL dei media o di altri file statici.

Quindi, dal mio punto di vista, stai sprecando tempo inutilmente se non vuoi usare la CDN. E questo potrebbe essere intelligente se hai un pubblico globale e alcuni di loro sono dietro connessioni di livello statale scadenti.

Vivo in Finlandia. Non ottengo alcun beneficio reale se un sito dall’altra parte del mondo, in Australia, utilizza la CDN (da un server che si trova a 1000 km da me). Il vero collo di bottiglia deriva da come è costruito quel sito, ad esempio se vengono utilizzate molte chiamate PHP non necessarie senza risorse sufficienti.

Ma fondamentalmente non puoi usare un URL cdn.example.tld senza inserire almeno cdn nel DNS.

Ciao @Jagster

In realtà, non voglio usare affatto una CDN: voglio solo che tutti gli upload degli utenti vengano archiviati in S3 e serviti direttamente da lì, anche se CloudFront è davvero una soluzione migliore di S3 direttamente.

Il mio problema è sorto quando ho provato a configurare S3 (specificamente per servire asset, non upload), e @pfaffman mi ha suggerito di seguire la guida Configura un provider di object storage compatibile con S3 per gli upload e configurare una CDN.

Riguardo al tuo commento:

“Non puoi semplicemente nominare un sottodominio solo in app.yml. Nessuno può usarlo senza le informazioni DNS corrette. E poiché i tuoi file vengono serviti da AWS, devi configurare anche quel lato, se vuoi usare una CDN.”

Mi dispiace, ma non ho capito bene cosa intendevi con questo paragrafo. Potresti elaborare un po’ di più o chiarire? Stai dicendo che devo configurare i record DNS per il mio bucket S3 o che c’è qualcosa di specifico che devo regolare sul lato AWS?

Grazie in anticipo per il tuo aiuto!

Ciao di nuovo a tutti,

Volevo dare seguito al mio post precedente e condividere che ho fatto dei progressi.

Cosa funziona ora

  • Caricamenti utente vengono serviti correttamente dal mio bucket S3 tramite la CDN (CloudFront), quindi è fantastico!

Tuttavia, sto ancora riscontrando un problema con gli asset precompilati

Gli asset precompilati non vengono ancora serviti correttamente dalla CDN

Quando imposto DISCOURSE_CDN_URL sull’URL di CloudFront (cioè https://dsuqioxhrz2qn.cloudfront.net), gli URL degli asset precompilati diventano:

Il problema è che questi percorsi non esistono nel mio bucket S3. Gli asset precompilati vengono caricati nella cartella /assets/* in S3 (ad esempio, /assets/locales, /assets/plugins, /assets/scripts), ma non c’è una cartella /stylesheets/ e naturalmente il caricamento di tali URL risulta in un 403 forbidden.

Se, invece, cambio DISCOURSE_CDN_URL: https://forum.hobiguru.com, allora il mio forum funziona correttamente, ma gli asset vengono ora serviti dal server (ad esempio https://forum.hobiguru.com/) e non dalla CDN (ad esempio https://forum.hobiguru.com/stylesheets/admin_308d905aa5c03567866fec50e9a28d8721ab0463.css?__ws=forum.hobiguru.com)

La mia configurazione attuale (per contesto) è:

app.yaml

DISCOURSE_USE_S3: true
DISCOURSE_S3_REGION: eu-central-1
DISCOURSE_S3_ACCESS_KEY_ID: AKIA......LQMB
DISCOURSE_S3_SECRET_ACCESS_KEY: PaXQu7pKN.....fJNY
DISCOURSE_S3_CDN_URL: https://dsuqioxhrz2qn.cloudfront.net  # Ensure CDN URL points to CloudFront
DISCOURSE_CDN_URL: https://forum.hobigur.com # NOTICE THIS!
DISCOURSE_S3_BUCKET: hobiguru-s3-bucket-eu

e gli hook di precompilazione:

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

Sembra che dopo la precompilazione gli asset vengano caricati in S3 in una certa struttura, ma poi quando vengono caricati tramite la CDN il percorso degli oggetti sia un po’ fuori posto.