Estou tentando configurar uploads para o S3 e parece que os uploads estão funcionando corretamente, mas as requisições GET estão falhando por um motivo estranho. Parece que o Discourse está adicionando um “.cn” ao URI do objeto carregado.
Após fazer o upload da imagem no meu bucket S3, a URL pública é:
Parece que você pode ter colado acidentalmente o mesmo guia duas vezes.
Quando você menciona “configurações no seu arquivo yml”, você poderia esclarecer a qual arquivo YAML está se referindo? Você talvez esteja falando sobre o arquivo app.yml localizado na pasta /var/discourse/containers?
Além disso, se eu configurar minha integração S3/CloudFront diretamente através do arquivo YAML, essas configurações substituiriam o que está configurado na seção de administração do Discourse?
Eu tenho meu bucket S3, configuração do CloudFront e a origem do CloudFront configurada para o meu bucket S3. Aqui está a minha configuração atual do app.yml:
Após reconstruir o aplicativo com ./launcher rebuild app, quando visito o site, ele apenas mostra o loader sem carregar nada. Ao inspecionar a aba de rede, descobri que ele não consegue buscar os ativos estáticos pré-compilados (principalmente .js), o que presumo ser porque eles não estão no meu bucket S3. Você pode verificar aqui: forum.hobiguru.com.
Também tentei executar a tarefa rake de migração, mas sem sucesso:
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
Por favor, note que migrar para S3 atualmente não pode ser revertido!
[CTRL+c] para cancelar, [ENTER] para continuar
Migrando uploads para S3 para 'default'...
Alguns uploads não foram migrados para o novo esquema. Executando a migração, isso pode levar algum tempo...
rake aborted!
FileStore::ToS3MigrationError: Alguns uploads não puderam ser migrados para o novo esquema. Você precisa corrigir isso 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'
Minha intenção original era usar o S3 apenas para armazenar uploads de usuários, e adicionei o CDN apenas para lidar com isso. No entanto, agora estou enfrentando um novo problema: os ativos estáticos do meu aplicativo também estão sendo servidos através do CDN, o que eu não pretendia.
Existe alguma maneira de fazer upload de todos os ativos estáticos no lançamento do aplicativo para o bucket S3 e, em seguida, servi-los através do CDN, ou talvez uma maneira de servir apenas os uploads de usuários através do CDN, ou existe uma solução melhor para isso?
Talvez eu ainda esteja perdendo algo óbvio? sei lá
Obrigado pela sua ajuda!
Suspeito que seja porque você não seguiu as instruções.
Sim. Entendo. Isso é possível, mas você não conseguiu fazer funcionar. Esta é a maneira recomendada; é bem documentada e centenas de pessoas fazem dessa forma.
No guia a que você se refere, há esta seção que parece relevante:
DISCOURSE_CDN_URL é uma CDN que aponta para o seu hostname Discourse e armazena em cache as requisições. Ela será usada principalmente para assets que podem ser puxados: CSS e outros assets de tema.
DISCOURSE_S3_CDN_URL é uma CDN que aponta para o seu bucket de armazenamento de objetos e armazena em cache as requisições. Ela será usada principalmente para assets que podem ser enviados: JS, imagens e uploads de usuários.
Recomendamos que sejam diferentes e que os administradores configurem ambos.
No entanto, não tenho certeza do que definir como DISCOURSE_CDN_URL? Devo defini-lo com o mesmo valor de DISCOURSE_S3_CDN_URL: https://dsxxxxx2qn.cloudfront.net ou ter uma instância de CDN separada criada?
Por outro lado, talvez seja algo totalmente diferente
Olá Jake, não tenho certeza se entendi corretamente o que você quis dizer. Você poderia elaborar um pouco mais?
Você talvez quis dizer que, em vez de configurar o bucket S3 como a origem da CDN, eu deveria configurar meu domínio forum.hobiguru.com como a origem? Se for o caso, não acho que isso mudaria nada, já que é o fórum discourse que gera esses URLs que não levam a lugar nenhum, por exemplo, //my-bucket-eu.my-bucket-eu/original/1X/7f242572bdb45b65ded727c13366fe490541358f.jpeg
Eu adicionei DISCOURSE_CDN_URL: https://dsuxxxhrz2qn.cloudfront.net também e agora estou esperando o aplicativo ser reconstruído
Você simplesmente não pode nomear um subdomínio apenas em app.yml. Ninguém pode usá-lo sem as informações corretas de DNS. E como o envio de seus arquivos acontece a partir da AWS, você também precisa configurar esse lado, se quiser usar CDN.
Mas, novamente. Os usuários veem a URL do Discourse, se quiserem vê-la. Raramente alguém que não seja um administrador está fazendo algo que deseja. E os usuários praticamente nunca veem a URL de mídias ou outros arquivos estáticos.
Portanto, meu ponto de vista é que você está perdendo tempo à toa se não quiser usar CDN. E isso pode ser inteligente se você tiver um público global, e alguns deles estiverem em conexões de nível estadual ruins.
Eu moro na Finlândia. Não obtenho nenhum benefício real se um site do outro lado do mundo, na Austrália, usa CDN (de um servidor localizado a 1000 km de mim). O gargalo real vem de como esse site é construído, como se muitas chamadas PHP desnecessárias fossem usadas sem recursos suficientes.
Mas, basicamente, você não pode usar uma URL cdn.example.tld sem colocar cdn pelo menos no DNS.
Na verdade, eu não quero usar um CDN — só quero que todos os uploads de usuários sejam armazenados no S3 e servidos diretamente de lá, embora o CloudFront seja realmente uma solução melhor do que o S3 diretamente.
“Você simplesmente não pode nomear um subdomínio apenas em app.yml. Ninguém pode usá-lo sem informações de DNS adequadas. E como o carregamento dos seus arquivos acontece a partir da AWS, você também tem que configurar esse lado, se quiser usar CDN.”
Desculpe, mas não entendi bem o que você quis dizer com este parágrafo. Você poderia elaborar um pouco mais ou esclarecer? Você está dizendo que preciso configurar registros de DNS para o meu bucket S3 ou que há algo específico que preciso ajustar no lado da AWS?
Queria dar seguimento ao meu post anterior e partilhar que fiz alguns progressos.
O que está a funcionar agora
Os uploads de utilizadores estão a ser servidos corretamente do meu bucket S3 através do CDN (CloudFront), o que é ótimo!
No entanto, ainda estou a enfrentar um problema com os assets pré-compilados
Os assets pré-compilados ainda não estão a ser servidos corretamente do CDN.
Quando defino o DISCOURSE_CDN_URL para o URL do CloudFront (ou seja, https://dsuqioxhrz2qn.cloudfront.net), os URLs dos assets pré-compilados tornam-se:
O problema é que estes caminhos não existem no meu bucket S3. Os assets pré-compilados são carregados sob a pasta /assets/* no S3 (por exemplo, /assets/locales, /assets/plugins, /assets/scripts), mas não existe uma pasta /stylesheets/ e, claro, o carregamento desses URLs resulta em 403 forbidden.
Se, no entanto, altero o DISCOURSE_CDN_URL: https://forum.hobiguru.com, então o meu fórum está a funcionar corretamente, mas os assets estão agora a ser servidos do servidor (por exemplo, https://forum.hobiguru.com/) e não do CDN (por exemplo, https://forum.hobiguru.com/stylesheets/admin_308d905aa5c03567866fec50e9a28d8721ab0463.css?__ws=forum.hobiguru.com)
Parece que, após a pré-compilação dos assets, eles são carregados para o S3 numa determinada estrutura, mas depois, quando carregados através do CDN, o caminho para os objetos está um pouco incorreto.