Configurar upload de arquivos e imagens para S3

O primeiro post em https://meta.discourse.org/t/set-up-file-and-image-uploads-to-s3
ainda é um guia válido que permite aos administradores fazê-lo? Se não, existe algum outro local onde o guia correto para S3 para 2024 está localizado? É dito que este é oficial e suportado pela equipe do Discourse.

Implementamos como no guia acima e as imagens estão quebradas na instância do Discourse, embora estejam sendo carregadas no S3.

Nosso fluxo

  1. Configurar o próprio bucket S3 e a política no S3 como no guia acima (todos os passos foram seguidos com precisão)

  2. Configurar o ambiente em app.yml e no admin (idêntico) como no guia acima

  3. reconstruir o aplicativo com o launcher

  4. qualquer CDN NÃO é usada, pois nosso entendimento é que é opcional e deve funcionar sem CDN.

Resultado:

  1. As imagens estão sendo carregadas no bucket pelo Discourse
  2. os links nas postagens são corretamente substituídos pelo Discourse por links da Amazon como
    xxx-bucket.s3.dualstack.us-east-1.amazonaws.com/original/1X/a1b21eb5de071799d4b5e5215619d11d28602dfe.jpeg
  3. os links não são acessíveis (supostamente por causa da política S3 no guia oficial)

Mudança assumida para a política S3 oficial no guia. Principal: Esta política não especifica um Principal, o que significa que se aplica a quem foi autenticado com as permissões corretas. Se for para permitir acesso anônimo (público), precisamos especificar \"Principal\": \"*\". Isso também pode não ser uma boa solução, pois torna o bucket público.
esta é uma suposição, pois agradecemos se alguém atualizar o guia para torná-lo correto em 2024

Oi,
Estamos usando o Cloudflare R2 para armazenamento S3 (já funciona agora) e eu queria mover o Discourse para outro servidor.
No entanto, as fotos de perfil estavam faltando ao restaurar a partir de um backup, mesmo marcando a opção “backup uploads”.

Então, executei o comando de migração S3 no servidor antigo para migrar as imagens que ainda estão locais, mas está falhando com este rastreamento. Não está claro qual é o motivo.

rake uploads:migrate_to_s3 --trace
** Invoke uploads:migrate_to_s3 (first_time)
** Invoke environment (first_time)
** Execute environment
** Execute uploads:migrate_to_s3
Observe que a migração para S3 atualmente não é reversível!
[CTRL+c] para cancelar, [ENTER] para continuar

Migrando uploads para S3 para 'default'...
Fazendo upload de arquivos para S3...
 - Listando arquivos locais
..... => 5123 arquivos
 - Listando arquivos S3
....... => 6871 arquivos
 - Sincronizando arquivos para S3
.......................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................^[[B............................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................
Atualizando as URLs no banco de dados...
Removendo imagens otimizadas antigas...
Marcando todas as postagens contendo lightboxes para rebake...
828 postagens foram marcadas para rebake
rake aborted!
FileStore::ToS3MigrationError: 4898 de 5838 uploads não foram migrados para S3. A migração S3 falhou para db 'default'. (FileStore::ToS3MigrationError)
/var/www/discourse/lib/file_store/to_s3_migration.rb:132:in `raise_or_log'
/var/www/discourse/lib/file_store/to_s3_migration.rb:73:in `migration_successful?'
/var/www/discourse/lib/file_store/to_s3_migration.rb:383: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'
/usr/local/bin/bundle:25:in `<main>'

Parece que essas imagens ainda estão armazenadas localmente por algum motivo, mesmo que eu tenha executado esse script de migração antes.

1 curtida

Minha suposição é que você alterou algo na sua configuração do s3 e as imagens ausentes estão em um bucket diferente ou em um caminho diferente das novas.

Você pode olhar em

Upload.pluck(:url)

Para ver o que está errado, talvez

1 curtida

Tive o mesmo problema recentemente e consegui resolver. Fiz isso atualizando as permissões do IAM com esta role

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
               "s3:List*",
               "s3:Get*",
               "s3:AbortMultipartUpload",
               "s3:DeleteObject",
               "s3:PutObject",
               "s3:PutObjectAcl",
               "s3:PutObjectVersionAcl",
               "s3:PutLifecycleConfiguration",
               "s3:CreateBucket",
               "s3:PutBucketCORS"
      ],
      "Resource": [
        "arn:aws:s3:::my-bucket",
        "arn:aws:s3:::my-bucket/*"
      ]
    },
    {
       "Effect": "Allow",
       "Action": [
           "s3:ListAllMyBuckets",
           "s3:ListBucket"
       ],
       "Resource": "*"
    }
  ]
}

Também tive que habilitar a propriedade de objetos ACL

Aqui estão minhas configurações completas quando pesquiso por s3

4 curtidas

Configurar CORS no bucket junto com as configurações acima para uploads de várias partes.

[
    {
        "AllowedHeaders": [
            "content-type",
            "x-amz-acl",
            "x-amz-meta-sha1-checksum"
        ],
        "AllowedMethods": [
            "GET",
            "HEAD",
            "PUT"
        ],
        "AllowedOrigins": [
            "*"
        ],
        "ExposeHeaders": [],
        "MaxAgeSeconds": 3000
    }
]

É possível mudar de provedor de serviços S3?

Gostaria de saber se haverá algum problema se eu tentar mudar de provedor de serviços S3, ignorando a questão das imagens já carregadas. Não tenho grandes problemas com isso, já que o site ainda não está no ar; ainda estou desenvolvendo-o.

É possível salvar as imagens localmente e depois ativar o S3 novamente com o novo provedor de serviços?

Você pode definir siteSettings.include_s3_uploads_in_backups=true no Rails e depois fazer um backup, alterar as configurações do S3 e restaurar o backup.

1 curtida

Tudo bem, entendi. Muito obrigado!

1 curtida

O tópico vinculado menciona um PR para remover uma tarefa migrate_from_s3, e não vi nenhuma razão para acreditar que ela tenha sido adicionada novamente mais tarde, mas queria verificar se isso ainda era verdade. Estou considerando migrar para MinIO e estou um pouco preocupado em torná-lo uma dependência.

Gostaria de saber se isso poderia fornecer uma solução alternativa para o que mencionei acima. Inclua essa configuração, faça um backup, desative as configurações do S3 e restaure o backup.

Sim. Eu restauraria para um novo servidor para que, se algo der errado, você ainda tenha um servidor funcionando.

Deste tópico, parece que essa configuração baixa os arquivos individuais do S3, mas me pergunto se pode haver problemas com postagens referenciando URLs do S3 em vez de arquivos locais. Não tenho certeza de como isso é tratado no banco de dados. Teria interesse em saber se sua migração para outro provedor foi bem-sucedida, @Rhod.

1 curtida

Fiz a transição tranquilamente. Enfatizo que não tive grandes problemas, pois o número de imagens ou backups era mínimo. O fórum era inteiramente para fins de teste, ainda não estava em “produção”. Finalmente, após várias tentativas e erros, reinstalei o fórum em um novo servidor (Hetzner) e configurei o S3 (Cloudflare R2) para backups e imagens com o servidor que finalmente me convenceu.

Sinto muito por não poder ajudar muito. Vou ver se consigo testá-lo em outro servidor no futuro.

Com o CF R2, suas miniaturas de chat funcionam bem?

1 curtida

Eu não tinha notado esse erro; a verdade é que tenho o chat desativado no meu site.

Acho que não vou usá-lo, mas ainda tenho o mesmo erro que você mencionou em seu post.

No entanto, ficarei de olho no seu post para ver se eles te ajudam a encontrar uma solução.

1 curtida

Obrigado, Walter! Eu vim aqui para postar o mesmo, apenas para ver que você já o tinha feito.

@Discourse há alguma chance de integrar o conteúdo da postagem de Walter na postagem inicial?

Posso fazer upload de vídeos para o S3? Atualmente, quando faço upload de vídeos, apenas a imagem de capa do vídeo é enviada para o S3, mas o vídeo em si não é enviado.