Definindo links DISCOURSE_S3_CDN_URL para ativos na URL do CDN S3

I had this problem before and decided that I was crazy, confused, or the database on the site was suspect, but this is on a brand new site. Also, I was on Digital Ocean spaces, so I thought it might be a problem somehow.

I’m trying again to figure out how to keep images on AWS S3 like I think the Big Boys do.

Here’s what I have in the env section:

  DISCOURSE_S3_ACCESS_KEY_ID: 'key'
  DISCOURSE_S3_SECRET_ACCESS_KEY: 'lock'
  DISCOURSE_BACKUP_LOCATION: 's3'
  DISCOURSE_S3_BUCKET: 'lc-xyz'
  DISCOURSE_S3_BUCKET_NAME: 'lc-xyz'
  DISCOURSE_S3_BACKUP_BUCKET: 'lc-xyz/backups'
  DISCOURSE_S3_UPLOAD_BUCKET: 'lc-xyz/uploads'
  DISCOURSE_S3_CDN_URL: 'https://lc-rbx.s3.amazonaws.com'

When I include the s3 cdn url the site breaks because all of the links to the assets are on S3 like https://lc-xyz.s3.amazonaws.com/assets/plugin-third-party-01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b.br.js.

Because if you define s3 cdn url Discourse looks for the assets on the s3_cdn_url.

I did a rebuild, but the assets are still missing. I can do a

rake s3:upload_assets

Is there an after_bundling_assets stanza that I could add that to? (I know about after_db_migrate and after_bundle_exec, but don’t know if those would work.)

Do assets get produced some other time? (It would seem like when themes get modified assets would change.)

If I also had a “push CDN like normal”, would that keep this from happening?

Is there some best practice that I’m missing?

You can use after_assets_precompile as the hook for that rake task.

Aha! Thanks very much for that. Where does the list of those things live?

I’m still confused why this is necessary, especially since you seemed confused before. (Or maybe I should be happy that I can push all this stuff to S3, now that I know how to do it–And I think that it was you who said that one could use CloudFlare’s free CDN to front an AWS bucket.)

Estou tentando isso novamente. Tenho uploads sendo enviados para o S3. Isso funciona.

Configurei o Cloudflare para fazer o CDN do site. Se eu inserir https://lc-XXX.literatehosting.com/uploads na configuração do site s3_cdn_url, os novos uploads vão para o bucket do S3 e a imagem é vinculada à URL do CDN, e tudo funciona.

MAS se eu tentar definir o s3_cdn_url com uma variável de ambiente no app.yml (ou editar config/discourse.conf manualmente e executar sv restart unicorn), todos os ativos são carregados do S3 (onde eles não estão). Isso pode não ser um problema, mas se eu tentar executar rake s3:upload_assets, ele reclama que o S3 não está configurado.

Eu acabei encontrando isso enquanto descobria alguns nomes de configurações conflitantes.

Eu acho (e torço, porque isso significa que eu entendi isso e não escrevi besteira absoluta no tópico vinculado acima) que, se você remover essas duas linhas:

DISCOURSE_S3_BUCKET: 'lc-xyz'
DISCOURSE_S3_BUCKET_NAME: 'lc-xyz'

Então você pode definir DISCOURSE_S3_CDN_URL, e ele será usado apenas para uploads, não para ativos.

Acho que você realmente entendeu e, graças a você, estou pelo menos mais perto de entender também! Muito obrigado!

Enfrentei esse problema e ainda estou muito confuso depois de ler este tópico…

Estou tentando servir uploads do S3 (não ativos compilados) via CDN (Cloudfront).

Se eu configurar “s3 cdn url” na tela de configurações, funciona como esperado (bem… exceto por System upload not using s3 cdn url).

No entanto, se eu configurar via DISCOURSE_S3_CDN_URL e reconstruir, o frontend quebra porque ele tenta carregar ativos compilados da minha URL de CDN do S3.

Parece que DISCOURSE_S3_CDN_URL / s3_cdn_url devem afetar apenas uploads, e DISCOURSE_CDN_URL deve afetar apenas ativos.

Essa é a minha experiência também. Acabei criando um plugin para definir o S3_CDN_URL.

@pfaffman parece que isso deveria ser registrado como um bug, certo?

Talvez. Não é um recurso que provavelmente será usado por auto-hospedeiros comuns, então terá baixa prioridade. Além disso, acho que haverá em breve uma mudança na forma como as configurações globais e as sombras globais funcionam, então isso provavelmente será resolvido na época.

Parece que o mesmo problema me rejeitou aqui.
@pfaffman, preciso da sua ajuda.
Você usa o CloudFront para alcançar a URL de CDN de domínio personalizado ou apenas usa o prefixo público dos objetos do bucket na URL da CDN?

Acabei de me deparar com isso. @pfaffman, você conseguiu resolver isso?

Consegui fazer os uploads funcionarem configurando manualmente o s3_cdn_url nas configurações do site, mas idealmente preciso poder definir a variável de ambiente globalmente ao fazer o deploy. Quando faço isso, tenho o mesmo problema: o Discourse tenta buscar os assets no s3_cdn_url, o que parece ser um bug para mim em discourse/lib/content_security_policy/default.rb at main · discourse/discourse · GitHub

Acho que acabei de definir o valor no banco de dados.

Minha suposição é que a solução seja encontrar a tarefa rake que enviará os ativos para o S3.

Estava me perguntando se alguém da @team poderia confirmar se esse é o comportamento esperado, de que não é possível usar uma CDN S3 (configurada globalmente) para uploads sem que o Discourse também procure os ativos lá. Parece um comportamento inesperado, a menos que eu esteja entendendo algo errado.

Sim, esse é o comportamento.

Configurar o CDN do S3 fará com que ele seja usado para tudo o que seja um arquivo estático, sejam uploads ou ativos JS.

Aqui estão algumas informações sobre isso; eu lidei com isso no mês passado.

Corrigi o problema configurando ambas as variáveis (DISCOURSE_S3_CDN_URL e DISCOURSE_CDN_URL) e criando duas distribuições do CloudFront: uma para os uploads, com origem no bucket S3, e outra para os ativos, com origem no servidor.

Aqui está o código que usamos para isso:

Aqui está nosso arquivo app.yml (que chamamos de web.yml), onde substituímos as variáveis no momento da construção: infra/modules/services/discourse/web.yml at master · debtcollective/infra · GitHub

Incrível. Muito obrigado. Parece não haver muita documentação sobre isso, e as configurações sugerem que você pode usar o S3 apenas para uploads, o que, creio eu, é o que está confundindo a todos nós.

Está na minha lista escrever um howto sobre isso. Espero fazer isso até o final de semana.

Sim, assim que você entende que precisa de duas distribuições do CloudFront, faz mais sentido. Além disso, lembre-se de fazer upload dos ativos para o S3 após cada reconstrução. Há um problema nas atualizações a partir do Docker Manager, onde é necessário executar bundle exec rake s3:upload_assets manualmente dentro do contêiner Docker. Se você fizer uma reconstrução em vez disso, deve funcionar se adicionar estas linhas ao seu app.yml

hooks:
  after_assets_precompile:
    - exec:
        cd: $home
        cmd:
          - 'bundle exec rake s3:upload_assets'

Essa tarefa está reclamando que eu não configurei o S3. Eu reduzi o problema a este método em global_setting.rb:

def self.use_s3?
    (@use_s3 ||=
      begin
        s3_bucket &&
        s3_region && (
          s3_use_iam_profile || (s3_access_key_id && s3_secret_access_key)
        ) ? :true : :false
      end) == :true
  end

Onde GlobalSetting.s3_bucket deve ser definido? Parece-me que precisamos definir as variáveis de ambiente DISCOURSE_S3_UPLOAD_BUCKET e DISCOURSE_S3_BUCKET. Qual é a diferença entre as duas?