Ir para o conteúdo
decodecodeveloper docs
Studio → Deploy e hospedagem própria do Studio → Deploy

Kubernetes

Faça deploy do deco Studio e dos sandboxes de agentes no Kubernetes usando Helm

Este guia faz o deploy do deco Studio e dos sandboxes hospedados de agentes no Kubernetes.

Código-fonte dos charts:

Caminho mais fácil: para uma instalação de um comando com dependências embutidas (local ou cluster de POC), use o umbrella chart ou selfhost/scripts/local-k8s.sh (veja o Quickstart). Há também um guia para agentes de código (SKILL.md) que entrevista você e escreve um diretório de instalação reutilizável — um umbrella chart com dependências OCI fixadas mais os seus values. Esta página é a referência do chart para instalar direto e para produção — o guia completo de dependências (Postgres/S3/ClickHouse managed ou in-cluster, secrets com/sem ESO, ingress, sandbox) está em selfhost/production.

Para entender a arquitetura em runtime (separação web/API/worker, Postgres, NATS e AgentSandbox), veja Arquitetura.

Modelo de deployment

Um deployment de produção usa três releases Helm:

ChartEscopoFinalidade
chart-deco-studioUma vez por ambiente do StudioExecuta um front door nginx com dois containers de API por pod, workers de fila, NATS, persistência e componentes opcionais de observabilidade
sandbox-operatorUma vez por cluster KubernetesInstala o controller e os CRDs do agent-sandbox do Kubernetes SIGs
sandbox-envUma vez por ambiente do StudioInstala o SandboxTemplate, o RBAC do runner, o Secret sentinela e, opcionalmente, warm pool, Gateway de preview e housekeeper de recursos ociosos

O operador é uma infraestrutura compartilhada no cluster. Cada release sandbox-env é isolada por envName, portanto produção, staging e outros ambientes do Studio podem compartilhar o operador e o namespace agent-sandbox-system sem colisões de nomes.

Quando um agente hospedado precisa de um sandbox, o Studio cria um SandboxClaim. O operador transforma o claim em um pod efêmero baseado no SandboxTemplate do ambiente. O Studio acessa o daemon via port-forward do Kubernetes para o tráfego de controle. Se o roteamento de preview estiver habilitado, o Studio também cria um HTTPRoute por claim para que o Gateway wildcard encaminhe diretamente para o Service do sandbox na porta 9000.

Pré-requisitos

  • Kubernetes 1.32+ e Helm 3
  • kubectl configurado para o cluster
  • Um banco PostgreSQL; a topologia atual de API/worker exige PostgreSQL
  • Uma StorageClass para os PVCs do Studio e do NATS JetStream gerenciado pelo chart
  • Um object store compatível com S3 e credenciais para o sistema de arquivos da organização (org-fs)
  • Suporte a spec.hostUsers: true e sidecars privilegiados em agent-sandbox-system; o sidecar obrigatório org-fs usa FUSE e propagação bidirecional de mounts
  • Somente para URLs públicas de preview: CRDs de Gateway API, um Gateway controller, DNS wildcard e cert-manager com um ClusterIssuer DNS-01 ou terminação TLS no load balancer

Em produção, agende pods de sandbox em um node pool dedicado e com taint. Esses pods executam código criado por usuários e não devem compartilhar nodes com Studio, Postgres, NATS ou workloads de observabilidade.

Instalar o Studio com sandboxes de agentes

Os comandos abaixo fixam versões de chart explicitamente. Fixe também no seu deployment, em vez de acompanhar a versão mais recente.

export STUDIO_CHART_VERSION=0.16.1
export SANDBOX_OPERATOR_CHART_VERSION=0.1.4
export SANDBOX_ENV_CHART_VERSION=0.17.3

Os charts são publicados como artefatos OCI públicos, então não é preciso credencial de registry. Para escolher uma versão mais nova, liste o que está publicado:

helm show chart oci://ghcr.io/decocms/chart-deco-studio | grep '^version:'
helm show chart oci://ghcr.io/decocms/studio/charts/sandbox-operator | grep '^version:'
helm show chart oci://ghcr.io/decocms/studio/charts/sandbox-env | grep '^version:'

Todas as versões publicadas também aparecem nas páginas dos pacotes: chart-deco-studio, sandbox-operator, sandbox-env.

1. Instale o operador de sandbox do cluster

O chart do operador não tem valores configuráveis e precisa ser instalado em agent-sandbox-system, pois o manifesto versionado do controller usa esse namespace.

helm install sandbox-operator \
  oci://ghcr.io/decocms/studio/charts/sandbox-operator \
  --version "$SANDBOX_OPERATOR_CHART_VERSION" \
  --namespace agent-sandbox-system \
  --create-namespace

Verifique o controller e os CRDs:

kubectl rollout status deployment/agent-sandbox-controller \
  -n agent-sandbox-system --timeout=300s
kubectl get crd sandboxclaims.extensions.agents.x-k8s.io \
  sandboxtemplates.extensions.agents.x-k8s.io \
  sandboxwarmpools.extensions.agents.x-k8s.io

2. Configure e instale o Studio

Sandboxes hospedados exigem object storage compatível com S3. O Studio só o considera configurado quando as quatro variáveis obrigatórias estão presentes:

VariávelObrigatóriaDescrição
S3_ENDPOINTSimEndpoint completo da API compatível com S3, como https://s3.us-east-1.amazonaws.com
S3_BUCKETSimBucket que armazena o org-fs
S3_ACCESS_KEY_IDSimAccess key usada pelo Studio
S3_SECRET_ACCESS_KEYSimSecret key usada pelo Studio
S3_REGIONDepende do providerO padrão é auto; defina a região real para AWS S3
S3_FORCE_PATH_STYLEDepende do providerDefina false para endereçamento virtual-hosted do AWS S3; normalmente true para MinIO e providers path-style

As credenciais precisam de s3:ListBucket no bucket e s3:GetObject, s3:PutObject e s3:DeleteObject nos objetos. Essas variáveis configuram o sistema de arquivos da organização e são separadas do sidecar opcional de backup s3Sync.* e das configurações MONITORING_S3_*.

Armazene as variáveis S3 junto com DATABASE_URL, BETTER_AUTH_SECRET e ENCRYPTION_KEY no Secret do Kubernetes consumido pelo Studio. Não coloque credenciais em configMap.meshConfig nem na release sandbox-env; os pods de sandbox acessam o org-fs pela API autenticada do Studio e não recebem as chaves S3 diretamente.

Crie studio-values.yaml. envName, o sufixo do template, o namespace do Studio, o nome da release e o nome da service account precisam corresponder à release sandbox-env instalada na próxima etapa.

database:
  engine: postgresql
  url: "" # fornecido como DATABASE_URL pelo Secret existente
 
serviceAccount:
  create: true
  name: deco-studio
  automount: true
 
configMap:
  meshConfig:
    BETTER_AUTH_URL: "https://studio.example.com"
    BASE_URL: "https://studio.example.com"
    STUDIO_AGENT_SANDBOX_ENABLED: "true"
    STUDIO_ENV: "production"
    STUDIO_SANDBOX_TEMPLATE_NAME: "studio-sandbox-production"
 
secret:
  secretName: deco-studio-secrets

configMap.meshConfig é um nome de chave obsoleto do chart, mantido para compatibilidade de upgrade. Seus valores configuram a API do Studio.

O Secret existente deco-studio-secrets precisa conter DATABASE_URL, BETTER_AUTH_SECRET, ENCRYPTION_KEY, S3_ENDPOINT, S3_BUCKET, S3_ACCESS_KEY_ID e S3_SECRET_ACCESS_KEY, além de S3_REGION e S3_FORCE_PATH_STYLE específicos do provider. Prefira externalSecret ou outro gerenciador de secrets em produção; não faça commit desses valores no Git.

Provisione deco-studio-secrets no namespace deco-studio antes de executar a instalação Helm abaixo. Como alternativa, configure os valores externalSecret do chart para criá-lo a partir do AWS Secrets Manager.

Instale o chart da aplicação:

helm install deco-studio \
  oci://ghcr.io/decocms/chart-deco-studio \
  --version "$STUDIO_CHART_VERSION" \
  --namespace deco-studio \
  --create-namespace \
  --values studio-values.yaml

A primeira instalação contra um banco vazio migra antes de servir. O Studio pega um advisory lock do Postgres em volta da migração do schema de sistema do DBOS, então quem chegar primeiro migra e os outros esperam — não é preciso ajustar contagem de réplicas, com ou sem Argo CD. O chart também traz um Job de migração com escritor único (migrateJob.enabled, ligado por padrão). Não é ele que dá a garantia — é o lock — mas ele dá à migração um lugar nomeado que ou teve sucesso ou falhou, em vez de ser o pod que ganhou a corrida. No Argo CD o sync wave segura os Deployments até o Job terminar; no helm install puro o Job sobe junto com os primeiros pods, o que é inofensivo assim que os pods carregam o lock.

O Deployment principal contém nginx e dois containers de API. O Deployment separado de workers é obrigatório e vem habilitado por padrão. O chart também habilita sua dependência NATS por padrão e exige PostgreSQL para que pods de API e worker compartilhem a fila DBOS.

3. Instale os recursos de sandbox do ambiente

helm install sandbox-env-production \
  oci://ghcr.io/decocms/studio/charts/sandbox-env \
  --version "$SANDBOX_ENV_CHART_VERSION" \
  --namespace agent-sandbox-system \
  --set envName=production \
  --set mesh.namespace=deco-studio \
  --set mesh.serviceAccountName=deco-studio

Isso cria SandboxTemplate/studio-sandbox-production e concede somente à service account indicada do Studio permissão para gerenciar claims, ler sandboxes, abrir port-forward para pods de sandbox, alterar seus Services e gerenciar objetos HTTPRoute por claim em agent-sandbox-system.

A chave mesh.* do chart de sandbox tem um nome obsoleto e é mantida para compatibilidade de upgrade; ela aponta para a release do Studio. mesh.serviceName, mesh.servicePort e mesh.podSelectorLabels estão obsoletos e não são usados pelo design atual de roteamento de preview por claim. Novas instalações não precisam definir esses três campos.

4. Verifique o deployment completo

helm status deco-studio -n deco-studio
helm status sandbox-operator -n agent-sandbox-system
helm status sandbox-env-production -n agent-sandbox-system
 
kubectl get deployments,pods -n deco-studio
kubectl get deployment -n agent-sandbox-system
kubectl get sandboxtemplate,sandboxwarmpool -n agent-sandbox-system
kubectl auth can-i create sandboxclaims.extensions.agents.x-k8s.io \
  --as=system:serviceaccount:deco-studio:deco-studio \
  -n agent-sandbox-system

Para acessar o Studio antes de configurar ingress:

kubectl port-forward svc/deco-studio 8080:80 -n deco-studio

O Studio estará disponível em http://localhost:8080.

5. Exponha o Studio

O Service do chart é ClusterIP e o Ingress é opcional e desligado por padrão, porque controller, class, emissor de TLS e annotations variam por cluster. Escolha a opção que corresponde ao que você já roda.

Ingress (gerenciado pelo chart). Defina ingress.enabled e o chart renderiza um Ingress apontando para o Service desta release — você não hardcoda o nome gerado do Service, e o objeto passa a fazer parte da release Helm, então helm rollback e helm uninstall cobrem ele:

ingress:
  enabled: true
  className: nginx
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt
  hosts:
    - host: studio.example.com
      paths:
        - path: /
          pathType: Prefix
  tls:
    - hosts:
        - studio.example.com
      secretName: studio-tls

O Studio serve a aplicação inteira a partir da raiz, então uma única regra / com Prefix por host é o formato normal. Com ingress.enabled=true, o chart falha ao renderizar se hosts estiver vazio ou se um host não tiver paths — um Ingress sem regras é aceito pelos controllers e simplesmente não roteia nada.

LoadBalancer. Sem controller no cluster: defina service.type: LoadBalancer e aponte DNS e TLS para o load balancer.

Gateway API. Deixe ingress.enabled: false e crie um Gateway e um HTTPRoute apontando para o mesmo Service. Isso é separado do Gateway de preview do sandbox, que é configurado pelo chart sandbox-env.

Qualquer que seja a escolha, defina BASE_URL e BETTER_AUTH_URL com a mesma URL pública https://. Os callbacks de autenticação são montados a partir desses valores, não do host da requisição, então uma divergência gera redirects de login que falham.

6. Conecte um provedor de IA

Um deployment self-hosted não vem com acesso a modelos. Agentes e Decopilot ficam inutilizáveis até que um owner da organização conecte um provedor em Settings → AI Providers com uma chave sua — Anthropic, Google Gemini, OpenRouter ou qualquer endpoint compatível com OpenAI, incluindo um servidor vLLM self-hosted. O deco AI Gateway hospedado e seus créditos iniciais são um recurso da oferta gerenciada; não planeje um rollout self-hosted em cima deles. Veja Provedores de IA.

Nota de egress: a menos que os modelos rodem na sua própria rede, os pods do Studio precisam de HTTPS de saída para a API do provedor.

7. Configure a autenticação

O Studio usa o Better Auth. No Kubernetes, configure por variáveis de ambiente no mesmo Secret ou ConfigMap que o chart já injeta — não há nada extra para montar:

MétodoVariáveis
Login socialAUTH_GOOGLE_CLIENT_ID / AUTH_GOOGLE_CLIENT_SECRET, AUTH_GITHUB_CLIENT_ID / AUTH_GITHUB_CLIENT_SECRET
SSO para todo o deploymentAUTH_SSO_DOMAIN mais as variáveis do Microsoft Entra ID ou do Google Workspace
Magic link, OTP por e-mail, e-mail/senhaAUTH_MAGIC_LINK_ENABLED, AUTH_EMAIL_OTP_ENABLED, AUTH_EMAIL_PASSWORD_ENABLED, mais um provedor de e-mail (AUTH_RESEND_API_KEY ou AUTH_SENDGRID_API_KEY)

Veja Autenticação para a referência completa.

Não existe arquivo auth-config.json — a autenticação é configurada inteiramente pelas variáveis de ambiente AUTH_* acima. Mantenha os secrets dos provedores no Secret, não em um ConfigMap.

Configuração de sandbox

Isolamento e egress

O container de sandbox roda como usuário não-root, com elevação de privilégio desabilitada, todas as capabilities Linux removidas, perfil seccomp RuntimeDefault e root filesystem somente leitura. Volumes emptyDir graváveis são montados onde o runtime precisa deles.

O sidecar org-fs é obrigatório: ele usa mounts FUSE privilegiados para expor skills, uploads, outputs e diretórios home da organização em /app/org. Somente esse sidecar é privilegiado. disableFsSidecar: true é uma saída para debugging, não um modo suportado em produção.

Por padrão, um init container de curta duração com NET_ADMIN instala regras de iptables e termina antes do início do código do usuário. Ele bloqueia ranges privados, link-local e de endereços compartilhados em IPv4/IPv6—que cobrem os CIDRs de pods e Services na maioria dos clusters—e permite DNS e HTTPS de saída. Sobrescreva as listas de CIDRs se o cluster usar ranges diferentes. Atualmente o chart não cria um NetworkPolicy do Kubernetes. Se o CNI ou firewall externo gerenciar o egress dos sandboxes, defina netinit.enabled: false e forneça controles equivalentes.

Agendamento recomendado para produção:

nodeSelector:
  workload: sandbox
 
tolerations:
  - key: workload
    operator: Equal
    value: sandbox
    effect: NoSchedule
 
topologySpreadConstraints:
  - maxSkew: 1
    topologyKey: topology.kubernetes.io/zone
    whenUnsatisfiable: ScheduleAnyway
    labelSelector:
      matchLabels:
        app.kubernetes.io/name: studio-sandbox-production

Warm pool

Warm pools vêm desabilitados por padrão porque cada pod ocioso consome todo o resource request do sandbox. Habilitar um também exige que o Studio e o template de sandbox compartilhem um token sentinela. O Studio o usa somente na primeira requisição de configuração do daemon e imediatamente troca para um token específico do claim.

Gere o token uma vez, armazene-o no Secret do Studio como STUDIO_SANDBOX_SENTINEL_TOKEN e passe o mesmo valor para sandbox-env:

export SANDBOX_SENTINEL_TOKEN="$(openssl rand -base64 48)"
 
helm upgrade sandbox-env-production \
  oci://ghcr.io/decocms/studio/charts/sandbox-env \
  --version "$SANDBOX_ENV_CHART_VERSION" \
  --namespace agent-sandbox-system \
  --reuse-values \
  --set-string sentinel.token="$SANDBOX_SENTINEL_TOKEN" \
  --set warmPool.enabled=true \
  --set warmPool.size=2

Se sentinel.token for omitido, o chart gera e preserva um Secret para os pods, mas o Studio ainda precisa do mesmo valor para consumir pods do warm pool. Em GitOps, gere o valor no seu gerenciador de secrets e entregue-o aos dois namespaces. Não o coloque em configMap.meshConfig.

O HPA opcional do warm pool exige warmPool.enabled: true, warmPool.autoscaling.enabled: true e pelo menos uma métrica explícita no formato autoscaling/v2. O chart intencionalmente não fornece uma métrica padrão.

Housekeeper de recursos ociosos

O Studio atualiza a atividade dos claims, enquanto o CronJob housekeeper opcional remove claims ociosos ou irrecuperáveis, além de routes e pods órfãos. Os padrões executam a cada cinco minutos e removem claims ociosos há 15 minutos.

housekeeper:
  enabled: true
  schedule: "*/5 * * * *"
  idleTtlSeconds: 900

STUDIO_ENV é obrigatório quando o housekeeper está habilitado, pois seus seletores padrão são limitados ao ambiente. Sem o label correspondente, ele intencionalmente não seleciona nenhum claim.

Gateway de preview

Trate URLs públicas de preview como uma fase posterior. Elas exigem CRDs de Gateway API, um Gateway controller, DNS wildcard e certificado wildcard via DNS-01 — dependências que normalmente pertencem a outro time e a outro cronograma. Studio, agentes e execução de código funcionam sem isso; só os links compartilháveis de preview ficam de fora.

Sem um Gateway de preview, o Studio pode usar seu proxy de preview legado em processo quando um padrão de URL e o roteamento externo necessário são fornecidos. O design atual de produção usa Gateway API e encaminha cada preview diretamente para seu daemon de sandbox:

Browser -> load balancer -> Gateway -> HTTPRoute por claim -> Service do sandbox:9000

Configure sandbox-env:

previewGateway:
  enabled: true
  gatewayClassName: istio
  namespace: istio-system
  domain: preview.example.com
  tlsTermination: gateway
  clusterIssuer: letsencrypt-dns

Depois adicione os valores correspondentes ao Studio:

configMap:
  meshConfig:
    STUDIO_SANDBOX_PREVIEW_URL_PATTERN: "https://{handle}.preview.example.com"
    STUDIO_SANDBOX_PREVIEW_GATEWAY_NAME: "agent-sandbox-preview-production"
    STUDIO_SANDBOX_PREVIEW_GATEWAY_NAMESPACE: "istio-system"

Nome e namespace do Gateway precisam estar ambos definidos ou ambos ausentes. Crie o DNS wildcard *.preview.example.com apontando para o load balancer do Gateway. Com tlsTermination: gateway, o ClusterIssuer precisa suportar DNS-01 porque certificados wildcard não podem usar HTTP-01. Use tlsTermination: loadBalancer quando o load balancer externo for responsável pelo certificado.

O handle do sandbox no hostname é a única autorização embutida da route de preview. Trate URLs de preview como secrets: handles podem aparecer em logs do CDN, load balancer e proxies. Adicione autorização no Gateway (por exemplo, AuthorizationPolicy do Istio ou autenticação externa do Envoy) quando o sigilo do hostname não for suficiente.

Cada ambiente que habilita previews precisa de um previewGateway.domain distinto; dois Gateways não podem associar com segurança o mesmo hostname wildcard.

Valores principais do Studio

Estes padrões vêm de deploy/helm/studio/values.yaml:

ParâmetroDescriçãoPadrão
replicaCountRéplicas de pods de API1
image.repository / image.tagImagem de API/worker do Studio (tags)ghcr.io/decocms/studio/studio / não definido
nginx.image.repository / nginx.image.tagImagem do front door (tags)ghcr.io/decocms/studio/studio-nginx / não definido
service.type / service.portExposição do ServiceClusterIP / 80
ingress.enabled / ingress.className / ingress.hostsIngress opcional gerenciado pelo chartfalse / "" / []
database.engineEngine do bancopostgresql
worker.enabled / worker.replicaCountDeployment de workers de filatrue / 2
worker.autoscaling.enabledHPA dos workerstrue
nats.enabledSubchart NATS com JetStreamtrue
persistence.enabled / persistence.sizePVC do Studiotrue / 10Gi
autoscaling.enabledHPA da APIfalse
metrics.scrapeAnotações Prometheus nos podstrue

image.tag e nginx.image.tag não são definidos por padrão, então ambos caem no appVersion do chart, que é latest. Defina os dois explicitamente em produção com uma versão publicada (por exemplo 4.152.1) — caso contrário um restart de pod pode puxar silenciosamente um build diferente do que você validou. Um digest (sha256:…) também é aceito. O chart do sandbox já fixa a própria imagem; não sobrescreva com latest.

Valores principais do sandbox

ParâmetroDescriçãoPadrão
envNameSufixo DNS-label dos recursos do ambienteObrigatório
image.repository / image.tagImagem do daemon do sandbox (tags)ghcr.io/decocms/studio/studio-sandbox-go / fixada pelo chart
resources.requestsRequest por sandbox500m CPU / 2Gi memória
resources.limitsLimite por sandbox2 CPU / 4Gi memória / 10Gi armazenamento efêmero
mediumResourcesOverrides do segundo SandboxTemplate -medium, mais folgado (claims de agente headless)3Gi de request / 6Gi de limite
terminationGracePeriodSecondsTempo para sync final do git e unmount90
netinit.enabledInstalar política padrão de egress no iptablestrue
readOnlyRootFilesystemRoot filesystem do sandbox somente leituratrue
depsCache.enabled / depsCache.goldenCaches de dependências locais ao nodefalse / false
warmPool.enabled / warmPool.sizeSandboxes pré-aquecidosfalse / 0
previewGateway.enabledGateway wildcard de previewfalse
housekeeper.enabledCronJob de limpeza de claims ociososfalse

Upgrades e remoção

Renderize e valide os três charts antes de aplicar mudanças:

helm lint deploy/helm/studio \
  --set database.url=postgresql://user:pass@postgres.example.com:5432/studio
helm lint deploy/helm/sandbox-operator \
  --namespace agent-sandbox-system
helm lint deploy/helm/sandbox-env \
  --namespace agent-sandbox-system \
  --set envName=production
 
helm template deco-studio deploy/helm/studio --values studio-values.yaml
helm template sandbox-operator deploy/helm/sandbox-operator \
  --namespace agent-sandbox-system
helm template sandbox-env-production deploy/helm/sandbox-env \
  --namespace agent-sandbox-system \
  --set envName=production

Arquivos no diretório crds/ de um chart Helm são instalados uma vez, mas não são atualizados por helm upgrade. Quando o appVersion upstream do operador mudar, aplique os novos CRDs antes de atualizar o operador:

kubectl apply -f deploy/helm/sandbox-operator/crds/agent-sandbox-crds.yaml
helm upgrade sandbox-operator deploy/helm/sandbox-operator \
  --namespace agent-sandbox-system

Desinstale os recursos de ambiente antes do operador compartilhado. Remover o operador primeiro deixa claims e custom resources sem um controller.

helm uninstall sandbox-env-production -n agent-sandbox-system
helm uninstall deco-studio -n deco-studio
# Somente depois que todos os ambientes removerem sandbox-env:
helm uninstall sandbox-operator -n agent-sandbox-system

Ambientes de preview por pull request

O chart traz um bloco opcional preview. Ele transforma um release em um ambiente efêmero e autocontido: um Postgres descartável no mesmo namespace, as migrations executadas uma única vez por um Job em vez de disputadas entre os pods, e um HTTPRoute apontando para um Gateway wildcard compartilhado. Serve para revisar uma mudança antes do merge — um Studio descartável por pull request.

preview.enabled é false por padrão e todos os templates de preview dependem dele, então uma instalação normal renderiza exatamente o que renderizava antes. Você não precisa disso para self-host do Studio, e deve deixá-lo desligado a menos que esteja montando um pipeline de revisão.

Ligá-lo exige um orquestrador que crie e destrua um ambiente por pull request. A sugestão é o Argo CD, e o chart chart-deco-studio-previews neste repositório entrega essa metade: um ApplicationSet cujo generator de pull request observa um repositório em busca de uma label, mais o Gateway compartilhado. Aponte-o para o seu repositório, domínio e object storage — ele não tem defaults.

helm template studio-previews deploy/helm/studio-previews \
  --set domain=pr.example.com \
  --set applicationSet.repo.owner=sua-org \
  --set applicationSet.repo.name=seu-fork \
  --set applicationSet.repo.tokenSecret.name=preview-github-token \
  --set studioChart.repoURL=oci://ghcr.io/decocms \
  --set studioChart.version="$STUDIO_CHART_VERSION" \
  --set studioChart.valuesRepo.url=https://github.com/sua-org/seu-fork.git \
  --set images.api=ghcr.io/sua-org/studio-preview \
  --set images.nginx=ghcr.io/sua-org/studio-nginx-preview \
  --set studioValues.externalSecret.secretPath=preview/studio \
  --set studioValues.externalSecret.secretStoreName=seu-cluster-store \
  --set studioValues.objectStorage.endpoint=https://seu-endpoint \
  --set studioValues.objectStorage.bucket=seu-bucket-de-preview

Um preview não é uma produção pequena. Ele não cobre sandboxes de agente hospedados, login por OAuth, billing, o dashboard de monitoring, e-mail de saída, nem nada que dependa de mais de um pod. Ele também não autentica ninguém por conta própria — coloque uma authorization policy no listener do Gateway antes de expô-lo, porque um preview aceita cadastro por e-mail/senha e consegue acionar agentes de LLM.

Veja deploy/helm/studio-previews/README.md para o contrato completo.