Pular para o conteúdo principal

Armazenamento

Configure o armazenamento de objetos de que o Fluxo precisa para os uploads, a leitura pública de recursos e a entrega opcional por CDN.

Comece pela visão geral de auto-hospedagem se você quiser ver antes o panorama completo e depois volte aqui para configurar o armazenamento. Quando os uploads funcionarem, conclua a sua infraestrutura com a configuração de e-mail.

O Fluxo precisa de armazenamento de objetos para os uploads dos usuários, os recursos de marca e os anexos das conversas. Em deploys auto-hospedados, o caminho recomendado é o Amazon S3, porque o repositório já inclui um módulo do Terraform que combina com a forma como o app gera hoje as URLs de upload.

Por que o Fluxo precisa de armazenamento

O app foi construído em torno de uploads diretos a partir do navegador, em vez de fazer arquivos grandes passarem pelo servidor da API.

Isso traz algumas vantagens práticas:

  • os uploads vão direto do navegador para o armazenamento de objetos por meio de URLs pré-assinadas
  • a API apenas assina a requisição de upload, em vez de guardar em memória o conteúdo do arquivo
  • os recursos enviados podem ser lidos de volta por URLs públicas estáveis
  • você pode adicionar uma CDN mais tarde sem mudar o fluxo de upload no nível do app

Como o Fluxo usa o armazenamento por dentro

Em execução, o fluxo de upload é assim:

  1. Um cliente pede à API uma URL de upload assinada.
  2. A API cria um PUT pré-assinado para o bucket configurado.
  3. O cliente envia o arquivo direto para o armazenamento de objetos.
  4. A API devolve uma URL pública que o app guarda e exibe depois.

Os uploads não são gravados em um namespace plano do bucket. As chaves são delimitadas por inquilino e por área funcional, de modo que os dados ficam organizados por organização, site e entidade. Dependendo da funcionalidade, essa entidade pode ser uma conversa, um visitante, um usuário ou um contato.

Exemplos do formato das chaves:

<organizationId>/<websiteId>/<conversationId>/attachment.png
<organizationId>/<websiteId>/<userId>/avatar.png
cdn/<organizationId>/<websiteId>/<visitorId>/image.jpg

Os sufixos exatos variam, mas o importante é que o armazenamento leva em conta o inquilino e a funcionalidade.

Caminho de instalação recomendado

O módulo de armazenamento voltado à AWS fica em infra/aws/s3-public-setup.

Ele cria:

  • um bucket do S3 para os arquivos enviados
  • acesso público de leitura às URLs exatas dos objetos
  • regras de CORS para os uploads diretos a partir do navegador
  • um usuário do IAM que a API possa usar para gerar URLs de upload pré-assinadas

O módulo incluído é um ponto de partida permissivo, não uma base de armazenamento endurecida para produção. Ele ativa force_destroy, desativa os bloqueios de acesso público do S3, permite leituras públicas, aceita CORS de * e cria chaves de acesso do IAM de longa duração. Trate cada URL de objeto como pública e revise cada configuração antes de usar o módulo fora de um ambiente de desenvolvimento isolado.

Para produção, restrinja o CORS às suas origens reais, prefira objetos privados com entrega assinada ou por CDN sempre que possível, ative a criptografia, o versionamento, a retenção e os logs de acesso, substitua as chaves estáticas por roles de carga de trabalho quando a sua plataforma permitir, gire as chaves que restarem e teste o backup e a recuperação.

Passo 1: implante o módulo de armazenamento

Entre no módulo do Terraform:

cd infra/aws/s3-public-setup

Copie o arquivo de variáveis de exemplo:

cp terraform.tfvars.example terraform.dev.tfvars

Defina um nome de bucket único globalmente e a região que você quer usar:

terraform.dev.tfvars
bucket_name = "fluxo-dev-your-unique-suffix"
environment = "dev"
aws_region  = "us-east-1"

Inicialize o Terraform:

terraform init

Use estado remoto criptografado e com bloqueio em ambientes compartilhados ou de produção. O estado contém detalhes sensíveis dos recursos e o módulo devolve um segredo do IAM. Não versione o estado, os planos, os tfvars nem nenhuma saída que contenha credenciais.

Crie ou selecione um workspace, revise um plano salvo e aplique exatamente esse plano:

terraform workspace new dev
terraform workspace select dev
terraform plan -var-file="terraform.dev.tfvars" -out="fluxo-storage.tfplan"
terraform apply "fluxo-storage.tfplan"

Repita o mesmo padrão para produção com um nome de bucket e um workspace de produção.

Passo 2: reúna os valores de que o app precisa

Depois do terraform apply, anote:

  • o nome do bucket
  • a região da AWS
  • o ID da chave de acesso do IAM
  • a chave de acesso secreta do IAM

Esses valores são os que a API usa quando gera URLs de upload pré-assinadas.

Passo 3: configure o ambiente de execução

Para o caminho padrão da AWS, defina estas variáveis de ambiente no runtime da API:

.env
S3_BUCKET_NAME=fluxo-dev-your-unique-suffix
S3_REGION=us-east-1
S3_ACCESS_KEY_ID=AKIA...
S3_SECRET_ACCESS_KEY=...
S3_PUBLIC_BASE_URL=https://fluxo-dev-your-unique-suffix.s3.us-east-1.amazonaws.com
S3_CDN_BASE_URL=
S3_SIGNED_URL_EXPIRATION_SECONDS=900

O que cada uma faz:

  • S3_BUCKET_NAME: o bucket que recebe os uploads
  • S3_REGION: a região da AWS desse bucket
  • S3_ACCESS_KEY_ID e S3_SECRET_ACCESS_KEY: as credenciais que a API usa para assinar os uploads
  • S3_PUBLIC_BASE_URL: a URL base de leitura quando você serve os arquivos direto do S3
  • S3_CDN_BASE_URL: uma URL base de CDN opcional se depois você colocar o CloudFront ou outra CDN na frente das leituras
  • S3_SIGNED_URL_EXPIRATION_SECONDS: a vida útil das URLs de upload geradas; por padrão, 900 segundos

Se você ainda não usa uma CDN, deixe S3_CDN_BASE_URL vazio.

Passo 4: reinicie a API e verifique os envios

Reinicie a API para que ela pegue a nova configuração de armazenamento e verifique o fluxo completo:

  1. Gere uma URL de upload pré-assinada pelo app.
  2. Envie um arquivo pelo navegador.
  3. Abra diretamente a URL pública devolvida.
  4. Confirme que o recurso aparece corretamente onde foi enviado.

Uma boa rodada de verificação inclui:

  • os uploads de avatar de perfil
  • os uploads de marca do site
  • os uploads de anexos nas conversas

Nota avançada: armazenamento compatível com S3

O caminho documentado prioriza a AWS, mas o runtime também aceita provedores compatíveis com S3.

Se você usar de propósito outro serviço compatível com S3, as configurações extras são:

.env
S3_ENDPOINT=https://your-object-store.example.com
S3_FORCE_PATH_STYLE=true

Trate isso como uma opção avançada. O módulo do Terraform deste repositório provisiona o S3 da AWS, não armazenamento de objetos de terceiros.

Lista de verificação

Antes de considerar o armazenamento pronto, confirme tudo o que segue:

  • que dá para gerar corretamente uma URL de upload pré-assinada
  • que um upload pelo navegador termina sem erros de CORS
  • que a URL pública devolvida resolve corretamente
  • que os arquivos enviados aparecem no painel onde você espera
  • que o S3_PUBLIC_BASE_URL ou o S3_CDN_BASE_URL configurados coincidem com as URLs que o app guarda
  • que foram revisados explicitamente o CORS de produção, o acesso público, a retenção, a criptografia, as credenciais e o comportamento ao destruir a infraestrutura

Antes de qualquer terraform destroy, lembre que a configuração force_destroy do módulo inicial permite apagar um bucket que não está vazio. Faça backup dos objetos necessários e inspecione o plano de destruição; um workspace do Terraform não é, por si só, nem um backup nem uma fronteira de isolamento.

Problemas comuns

  • 403 durante o upload: as credenciais de assinatura ou as permissões do bucket estão erradas
  • falha de CORS no navegador: as regras de CORS do bucket não foram aplicadas ou são restritivas demais
  • o upload funciona mas a URL pública falha: S3_PUBLIC_BASE_URL está errada ou ausente
  • as URLs funcionam diretamente mas não dentro do app: confira se o publicUrl guardado bate com a URL base configurada

Esta página foi útil?

Abra uma issue de documentação já preenchida para que a equipe possa agir.