Kubernetes

O próprio helm/studio/README.md do chart, incluído no pacote de implantação, é a referência para cada value e vai mais fundo que esta página em estratégias de segredos, network policy, supressão de PII e resolução de problemas por erro. Esta página cobre o caminho de implantação; leia as duas em conjunto.

Pré-requisitos

  • Kubernetes 1.25+
  • Helm 3.8+
  • Suporte a provisionador de PV (uma StorageClass padrão que suporte ReadWriteOnce)
  • Um ingress controller, se ingress.enabled=true
  • metrics-server, se você habilitar autoscaling
  • Redis, se você pretende rodar mais de uma réplica — veja Redis

Instalação

A auto-hospedagem parte do pacote de implantação — os arquivos do compose, o Helm chart e o template de .env. Solicite-o em help@seeyu.ai e execute os comandos abaixo na raiz do pacote descompactado.

# Generate secrets
BETTER_AUTH_SECRET=$(openssl rand -hex 32)
ENCRYPTION_KEY=$(openssl rand -hex 32)
INTERNAL_API_SECRET=$(openssl rand -hex 32)
CRON_SECRET=$(openssl rand -hex 32)
POSTGRES_PASSWORD=$(openssl rand -hex 24)

# Install
helm install studio ./helm/studio \
  --set app.env.BETTER_AUTH_SECRET="$BETTER_AUTH_SECRET" \
  --set app.env.ENCRYPTION_KEY="$ENCRYPTION_KEY" \
  --set app.env.INTERNAL_API_SECRET="$INTERNAL_API_SECRET" \
  --set app.env.CRON_SECRET="$CRON_SECRET" \
  --set postgresql.auth.password="$POSTGRES_PASSWORD" \
  --namespace studio --create-namespace

Guarde os cinco valores em um lugar durável antes de seguir adiante. A ENCRYPTION_KEY, em especial, não pode ser regerada — perdê-la torna as variáveis de ambiente do workspace e as chaves de provedores armazenadas permanentemente ilegíveis.

CRON_SECRET é obrigatório, não opcional: o chart habilita jobs em background por padrão e não é renderizado sem ele.

Isso instala a tag de imagem padrão do chart. Em produção, fixe app, realtime e migrations na mesma tag de release explícita — veja Atualizações.

Values Específicos por Nuvem

Estas são alternativas ajustadas por nuvem à instalação genérica acima — escolha um caminho, não rode os dois. Os comandos reutilizam as variáveis $BETTER_AUTH_SECRET, $ENCRYPTION_KEY, $INTERNAL_API_SECRET, $CRON_SECRET e $POSTGRES_PASSWORD geradas em Instalação acima, então execute as linhas openssl daquele bloco primeiro, no mesmo shell. Eles usam helm upgrade --install, então funcionam exista ou não um release. Duas ressalvas ao converter uma instalação genérica existente em vez de começar do zero: (1) reutilize os valores originais dos segredos — recupere-os com helm get values studio -n studio se seu shell não os tiver mais; fornecer uma ENCRYPTION_KEY recém-gerada torna indecifrável todo valor criptografado anteriormente (variáveis de ambiente do workspace, chaves de provedores armazenadas, credenciais OAuth de MCP). (2) Os values de nuvem renomeiam o banco PostgreSQL incluído para studio, mas o Postgres só aplica essa configuração na primeira inicialização — adicione --set postgresql.auth.database=studio para manter seu banco existente. Se preferir começar limpo, rode helm uninstall studio -n studio, apague os PVCs dele e execute o comando de nuvem do zero.

helm upgrade --install studio ./helm/studio \
  --values ./helm/studio/examples/values-aws.yaml \
  --set app.env.BETTER_AUTH_SECRET="$BETTER_AUTH_SECRET" \
  --set app.env.ENCRYPTION_KEY="$ENCRYPTION_KEY" \
  --set app.env.INTERNAL_API_SECRET="$INTERNAL_API_SECRET" \
  --set app.env.CRON_SECRET="$CRON_SECRET" \
  --set postgresql.auth.password="$POSTGRES_PASSWORD" \
  --set app.env.NEXT_PUBLIC_APP_URL="https://studio.yourdomain.com" \
  --namespace studio --create-namespace
helm upgrade --install studio ./helm/studio \
  --values ./helm/studio/examples/values-azure.yaml \
  --set app.env.BETTER_AUTH_SECRET="$BETTER_AUTH_SECRET" \
  --set app.env.ENCRYPTION_KEY="$ENCRYPTION_KEY" \
  --set app.env.INTERNAL_API_SECRET="$INTERNAL_API_SECRET" \
  --set app.env.CRON_SECRET="$CRON_SECRET" \
  --set postgresql.auth.password="$POSTGRES_PASSWORD" \
  --set app.env.NEXT_PUBLIC_APP_URL="https://studio.yourdomain.com" \
  --namespace studio --create-namespace
helm upgrade --install studio ./helm/studio \
  --values ./helm/studio/examples/values-gcp.yaml \
  --set app.env.BETTER_AUTH_SECRET="$BETTER_AUTH_SECRET" \
  --set app.env.ENCRYPTION_KEY="$ENCRYPTION_KEY" \
  --set app.env.INTERNAL_API_SECRET="$INTERNAL_API_SECRET" \
  --set app.env.CRON_SECRET="$CRON_SECRET" \
  --set postgresql.auth.password="$POSTGRES_PASSWORD" \
  --set app.env.NEXT_PUBLIC_APP_URL="https://studio.yourdomain.com" \
  --namespace studio --create-namespace

Configuração Principal

# Custom values.yaml
app:
  replicaCount: 2
  image:
    tag: "v1.2.3"  # a tag from the releases page
  env:
    NEXT_PUBLIC_APP_URL: "https://studio.yourdomain.com"
    BETTER_AUTH_URL: "https://studio.yourdomain.com"
    OPENAI_API_KEY: "sk-..."
    # Required once replicaCount > 1
    REDIS_URL: "redis://:<password>@redis.internal:6379"

realtime:
  image:
    tag: "v1.2.3"  # a tag from the releases page

migrations:
  image:
    tag: "v1.2.3"  # a tag from the releases page

postgresql:
  persistence:
    size: 50Gi

ingress:
  enabled: true
  className: nginx
  tls:
    enabled: true
  app:
    host: studio.yourdomain.com

NEXT_PUBLIC_APP_URL e BETTER_AUTH_URL precisam ser a sua origem pública real. Deixar qualquer uma das duas em localhost quebra o login.

Chaves definidas em app.env também chegam ao pod do realtime — o chart as escreve em um único Secret que as duas Deployments consomem via envFrom. Use realtime.env apenas para chaves que precisam ser diferentes entre os dois, como ALLOWED_ORIGINS.

Definir replicaCount: 2 sem REDIS_URL quebra silenciosamente a colaboração ao vivo e as atualizações de status — os eventos entre pods são descartados sem erro em lugar nenhum. Veja Redis e Escalonamento & HA.

Veja helm/studio/values.yaml para todas as opções, e o README.md do chart para o checklist de produção.

Jobs em background

O chart implanta 18 CronJobs por padrão, que conduzem workflows agendados, triggers de polling, sincronizações de conectores, data drains e o processamento do outbox. Eles exigem CRON_SECRET.

kubectl get cronjobs -n studio

Um CronJob com LAST SCHEDULE desatualizado significa que o recurso correspondente parou de funcionar. Veja Jobs em Background.

Ingress e TLS

Para ingress controllers no estilo nginx, aumente os limites de tamanho de corpo e de timeout — os padrões do Studio permitem anexos grandes no chat e execuções longas:

ingress:
  annotations:
    nginx.ingress.kubernetes.io/proxy-body-size: "250m"
    nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"
    nginx.ingress.kubernetes.io/proxy-buffering: "off"

No GKE, o timeout de backend padrão de 30 segundos do load balancer encerra websockets e precisa de um BackendConfig, e o ManagedCertificate que o chart referencia precisa ser criado por você. Os dois são cobertos em Rede.

Banco de Dados Externo

postgresql:
  enabled: false

externalDatabase:
  enabled: true
  host: "your-db-host"
  port: 5432
  username: "postgres"
  password: "your-password"
  database: "studio"
  sslMode: "require"

Comandos

# Port forward for local access
kubectl port-forward deployment/studio-app 3000:3000 -n studio

# View logs
kubectl logs -l app.kubernetes.io/component=app -n studio --tail=100

# Upgrade
helm upgrade studio ./helm/studio --namespace studio

# Uninstall
helm uninstall studio --namespace studio

Common Questions

O Helm chart suporta secrets pré-existentes do Kubernetes via app.secrets.existingSecret. Defina enabled como true e informe o nome do secret. Isso se integra ao External Secrets Operator, HashiCorp Vault, Azure Key Vault e ferramentas similares. O secret precisa usar os nomes de chave padrão (BETTER_AUTH_SECRET, ENCRYPTION_KEY, INTERNAL_API_SECRET, CRON_SECRET, ...) — ele é consumido por inteiro, então remapear chaves não é suportado.
Sim, mas defina REDIS_URL primeiro. Sem o Redis, o pub/sub e o adaptador do Socket.IO não têm transporte entre pods e a colaboração ao vivo quebra silenciosamente. Confirme também que seu banco de dados suporta as conexões adicionais — veja o guia de Escalonamento & HA.
Sim, sempre que os jobs em background estiverem habilitados — o que é o padrão do chart. O chart se recusa a renderizar sem ele, e os 18 CronJobs que conduzem workflows agendados, triggers de polling e sincronizações de conectores o usam como bearer token.
Todas as três: app, realtime e migrations, na mesma tag de release explícita. Elas compartilham um schema de banco de dados, então uma divergência faz a aplicação rodar contra um schema que não corresponde a ela. Não confie na tag padrão do chart em produção.