name: deploy-server
description: Use this skill to provision or update a Welley server on a supported cloud (currently DigitalOcean) when the user asks to deploy a new instance or run a server update. Covers single-instance deployments and SSH-based updates, including interactive collection of missing credentials, SSH keys, domain, region, and sizing.
Implantar servidor
Visão geral
Esta skill cria uma stack Welley de instância única na DigitalOcean e pode executar atualizações por SSH. Ela orienta o agente a reunir os dados que faltam, buscar as especificações de instância disponíveis em uma fonte definida, criar a VM, configurar o host, implantar com wlycli deployment create e validar o resultado.
Os nomes dos comandos devem ser iguais aos da CLI:
wlycli deployment createwlycli deployment updatewlycli deployment delete
Padrões (DigitalOcean)
- Região:
nyc3 - Imagem:
latest LTS available via API(resolva comimages?type=distribution) - Nome do droplet: gerado aleatoriamente no formato
wlsly-<adjective>-<surname>(por exemplo,wlsly-bright-hopper). Use o trecho gerador de nomes dereferences/digitalocean.md. Use o mesmo nome para o banco gerenciado, se ele for criado. - Plano desejado: Basic / Regular (CPU compartilhada)
- Tamanho desejado: 2 vCPU / 4 GB de RAM / 80 GB de SSD / 4 TB de transferência (~US$ 24/mês)
Regra para substituir os padrões
Se o usuário definir qualquer um dos padrões (região, imagem, nome do droplet, projeto, tamanho), o agente deve:
- Repetir a alteração exatamente como o usuário informou.
- Pedir confirmação antes de continuar.
Modelo de perguntas interativas
Pergunte só o que estiver faltando. Use exatamente estas perguntas para evitar ambiguidade. Faça as perguntas em rodadas. Rodada 1: no máximo 2 perguntas por vez. A rodada 2 pode apresentar uma opção agrupada de “aceitar todos os padrões”. Se o ambiente aceitar opções, apresente 2 a 3 alternativas por pergunta (A/B/C). Evite respostas livres, a menos que seja necessário.
Perguntas da rodada 1 (identidade e acesso):
- “Você tem um token de API da DigitalOcean para usar, ou devo esperar você enviar um?”
- “Qual domínio este servidor deve usar (por exemplo,
super-puper.example.com)? Você controla o DNS dele?” - “Você já tem uma chave pública SSH para usar, ou devo criar e enviar uma?”
- “Você quer colocar este droplet em um projeto existente da DigitalOcean? Se sim, informe o nome ou o ID do projeto.”
- “Requisito de DNS: você precisa criar registros A/AAAA para
<domain>estorage.<domain>(se não houver CDN). Você consegue fazer isso antes de o certbot rodar?” - “Requisito de DNS para e-mail: o domínio de
--smtp-fromprecisa de registros SPF, DMARC e DKIM, senão e-mails de convite e de confirmação para novos destinatários podem ser descartados sem aviso. Eles já estão configurados, ou devo listar os registros que o seu provedor de SMTP exige?” - Se o usuário perguntar onde conseguir um token da DO, envie este link:
https://cloud.digitalocean.com/account/api/tokens
Perguntas da rodada 2 (tamanho, localização e opções de implantação):
- “Você quer a região padrão
nyc3ou outra região?” - “Você quer o tamanho padrão (2 vCPU / 2 GB) ou outra meta de CPU/RAM?”
- “Devo usar o Ubuntu LTS mais recente disponível na API ou uma versão específica do Ubuntu?”
- “Qual usuário SSH devemos usar depois do bootstrap (padrão:
wlsly)? Você pode manter o padrão.” - “Você quer um banco Postgres gerenciado ou prefere usar o contêiner de Postgres incluído?”
- Se o Postgres gerenciado for escolhido: “Qual região e qual tamanho devo usar para o banco? Posso usar como padrão
nyc3e 1 vCPU / 2 GB.” - Se o Postgres gerenciado for escolhido: “Posso criar o banco pelo preço mensal listado pelo provedor?”
- “Envie as configurações de SMTP necessárias (host, usuário, senha, remetente). OTEL é opcional: envie só se precisar.”
- “O e-mail do administrador é obrigatório para criar. Envie agora (flag:
--email/-e). Se você não enviar, vou pedir duas vezes para confirmar.”
Ofereça uma opção de “aceitar todos os padrões” na rodada 2 para agilizar a coleta de dados.
Se faltar alguma resposta, faça uma pergunta complementar objetiva (no máximo uma ou duas).
Fluxo de trabalho (DigitalOcean, instância única)
- Reúna os dados necessários (pergunte se faltar algum).
- Token de API da DigitalOcean
- Nome ou ID do projeto (opcional; se não for informado ou não for encontrado, use o projeto padrão)
- Região
- Tamanho desejado da instância (por exemplo, 4 vCPU / 16 GB de RAM)
- Nome do domínio
- Chave pública SSH (ou confirmação para criar e registrar uma)
- E-mail do administrador para o primeiro login e a recuperação de senha (obrigatório para criar;
--email/-e). Se faltar, peça duas vezes e confirme que são iguais. - Opcional: certificados TLS próprios ou certbot
- Confirmação de acesso ao DNS (é preciso conseguir criar registros A/AAAA para
<domain>e parastorage.<domain>, se for usado)
- Busque os tipos de instância e escolha um tamanho.
- Use o trecho de tamanhos de
references/digitalocean.mdpara listar e filtrar por CPU/RAM. - Confirme com o usuário se houver mais de uma opção compatível.
2b. Descubra o slug da imagem do Ubuntu.
- Chame
GET /v2/images?type=distribution&per_page=200e filtre pelo Ubuntu. - Se o usuário pediu uma versão específica, verifique se o slug dela existe e confirme.
- Caso contrário, escolha o slug do LTS mais recente da lista e confirme com o usuário antes de criar.
- Crie o droplet.
- Use a API da DigitalOcean diretamente (o doctl é opcional).
- Imagem: prefira a que o usuário indicou; se não houver, escolha o LTS mais recente da lista da API.
- Anexe o fingerprint da chave SSH ou crie e envie uma chave.
- Ative o monitoramento.
- Se o nome/ID do projeto foi informado, mas não foi encontrado, crie o droplet sem projeto (projeto padrão).
- Observação: a criação do banco gerenciado pode rodar em paralelo com a criação do droplet.
Orientação de paralelização
O agente deve sobrepor tarefas independentes para reduzir o tempo total:
- Enquanto reúne os dados do usuário (rodada 2), comece a criar o droplet se o token, a região, o tamanho, a imagem e a chave SSH já estiverem confirmados.
- Enquanto o droplet está sendo criado, comece a criar o Postgres gerenciado (se foi pedido).
- Enquanto o droplet está iniciando, continue coletando os dados restantes (SMTP, OTEL, e-mail do administrador).
- Se faltar algum dado essencial para uma etapa, pause essa etapa e continue com as outras tarefas que podem rodar em paralelo.
- Se o DNS for gerenciado na DigitalOcean, crie ou atualize os registros A/AAAA assim que o IP do droplet estiver disponível (não espere a etapa completa de implantação).
- DNS e domínio.
- Pergunte se o DNS deve ser criado ou atualizado na DigitalOcean ou se ele fica em um DNS externo.
- Se usar o DNS da DigitalOcean, crie registros A/AAAA apontando para o IP do droplet.
- Configure o host por SSH.
- Crie um usuário sem privilégios de root (por exemplo,
wlsly), dê a ele acesso ao sudo e copie as chaves SSH autorizadas. - Saia do root e entre de novo como o usuário sem privilégios de root antes de continuar.
- Instale o Docker e o docker compose.
- Baixe o binário da CLI do Welley pela AppStore e torne-o executável:
- URL base:
https://appstore.allroads.social/v1/social.wellesley.wlycli/latest?develop=stable&platform=<os>/<arch> - Escolha o valor correto de
platformconforme o sistema e a arquitetura:- Linux x86_64:
linux/amd64 - Linux arm64:
linux/arm64 - macOS x86_64:
darwin/amd64 - macOS arm64:
darwin/arm64 - Windows x86_64:
windows/amd64
- Linux x86_64:
- Exemplo (Linux x86_64):
curl -fL 'https://appstore.allroads.social/v1/social.wellesley.wlycli/latest?develop=stable&platform=linux/amd64' -o wlycli chmod +x wlycli - Os cabeçalhos de resposta esperados incluem:
x-artifact-display-name: Welley CLIx-artifact-full-name: social.wellesley.wlyclix-artifact-kind: clix-artifact-platform: <os>/<arch>, comolinux/amd64x-artifact-sha256: <sha256>x-artifact-version: <version>x-channel: develop
- Antes de instalar, prefira conferir os cabeçalhos com uma requisição HEAD e verificar se o nome do artefato, o tipo, a plataforma e o canal correspondem ao binário pedido.
- URL base:
- Verifique o binário da CLI: rode
wlycli -vewlycli deployment --helppara confirmar as informações de build esperadas.
- Implante o Welley.
- Rode
wlycli deployment createcom as opções necessárias. - Use os padrões de instância única (sem Postgres externo, a menos que o usuário peça).
- Se o Postgres gerenciado for pedido, crie-o primeiro (banco da DigitalOcean) e depois use o host, a porta, o banco, o usuário e a senha retornados nas flags
--postgres-*. - Se a senha do usuário do banco não for retornada pela API ou pela interface, redefina a autenticação do usuário do banco para obter credenciais novas antes de rodar o
wlycli. - Execuções não interativas devem passar
--email/-e, senão o comando falha. --base-diraponta para o diretório pai; a CLI cria o subdiretório do projeto automaticamente.- A CLI se recusa a rodar se o diretório do projeto ou os contêineres já existirem; é preciso limpar tudo antes de tentar de novo.
- Certificados (obrigatório).
- Padrão: use o Certbot em modo standalone (não interativo).
- O usuário deve apontar os registros A/AAAA do domínio (e de
storage.<domain>, se for usado) para o IP do droplet antes de o certbot rodar. - A CLI aceita
--public-ip(substitui o IP detectado) e--skip-dns-preflight, caso você precise ignorar a verificação. - Nunca presuma que o DNS está configurado. Pergunte e espere uma confirmação explícita.
- Nunca use
--skip-dns-preflight, a menos que o usuário peça explicitamente. - Se a CDN não estiver configurada, o certbot deve incluir
storage.<domain>no pedido do certificado. - Use certificados autoassinados só se o usuário pedir explicitamente, e passe
--self-signed-certs(gera certificados autoassinados em Go). - Dê ao usuário as instruções de configuração do DNS e espere a confirmação:
- “Crie registros A/AAAA para que
<domain>aponte para o IP do droplet.” - “Se
storage.<domain>for usado, crie também um registro A/AAAA para ele.” - “Quando o DNS propagar, me avise e eu continuo. Não consigo ver a propagação, a menos que você peça para eu verificar a resolução.”
- O agente pode verificar a propagação do DNS por conta própria usando
ping -c 1 <domain>e comparando o IP com o do droplet. Se forem iguais, siga em frente.
7b. DNS de e-mail (SPF / DMARC / DKIM).
- E-mails enviados de um domínio sem SPF e DMARC costumam ser descartados pelo Gmail e pelo Outlook quando o destinatário é novo, mesmo que o provedor de SMTP informe que foram entregues.
deployment createmostra umWarning:quando o domínio de--smtp-fromnão tem registro SPF, ou não tem registro DMARC em_dmarc.<domain>nem em um domínio pai. Isso não bloqueia a implantação. Nunca ignore o aviso: mostre-o ao usuário e passe os registros que ele deve adicionar:<mail-domain>TXTv=spf1 include:<provider> ~all(o include exato vem do provedor de SMTP; junte ao registro SPF existente e nunca adicione um segundo)_dmarc.<mail-domain>TXTv=DMARC1; p=none; rua=mailto:dmarc@<mail-domain>- DKIM: os registros
<selector>._domainkey.<mail-domain>que o provedor de SMTP gera quando o domínio é verificado
- Confira com
dig +short TXT <mail-domain>edig +short TXT _dmarc.<mail-domain>. - A CLI não consegue verificar o DKIM (o seletor depende do provedor). Sempre peça ao usuário que confirme que o DKIM está verificado no provedor de SMTP, mesmo quando o
createnão mostrou nenhum aviso. Com o Amazon SES e provedores parecidos, o SPF é verificado para o domínio de envelope do próprio provedor, então só o DKIM faz o DMARC passar. No SES: em Verified identities, abra<mail-domain>e veja a seção DKIM, que deve indicar Successful.
- Valide e informe o resultado.
- Confira
docker pse os endpoints de saúde dos serviços. - Passe os dados finais de conexão e os próximos passos.
Fluxo de atualização por SSH
Quando o usuário pedir “atualizar o servidor”:
- Pergunte o host/IP de destino e o usuário/chave SSH.
- Rode
wlycli deployment update --domain <domain> [--force-restart]. - Verifique o estado dos contêineres e do Nginx.
Recursos
- Trechos e exemplos da API da DigitalOcean:
references/digitalocean.md.
Segredos e flags
Use estes nomes de flag para os segredos:
- Host do SMTP:
--smtp-host - Usuário do SMTP:
--smtp-user - Senha do SMTP:
--smtp-password - Remetente do SMTP:
--smtp-from - Endpoint do OTEL:
--otel-endpoint - Cabeçalhos do OTEL:
--otel-headers
Comando mínimo de criação
Flags obrigatórias:
--domain--email--smtp-host--smtp-user--smtp-password--smtp-from
Exemplo mínimo:
wlycli deployment create \
--domain example.com \
--email admin@example.com \
--smtp-host smtp.example.com \
--smtp-user user \
--smtp-password pass \
--smtp-from noreply@example.com
Padrões do Postgres gerenciado (DigitalOcean e CLI)
Ao usar o Postgres gerenciado da DigitalOcean, não dependa dos padrões da CLI. Defina todas as flags --postgres-* explicitamente:
- Padrões típicos da DO:
- Porta:
25060 - Banco:
defaultdb - Usuário:
doadmin
- Porta:
- Padrões da CLI (se você omitir as flags):
- Porta:
5432 - Banco:
wlsly - Usuário:
wlsly
- Porta:
Notas de uso da CLI
- Verificação de versão:
wlycli -vouwlycli --version(flag). Não existe um subcomandoversion. - Use
--base-dirsó se quiser um local diferente do padrão (o padrão é~/.welley). A CLI cria o diretório se tiver permissão. - Execuções SSH não interativas devem incluir
--emaile as outras flags obrigatórias para evitar perguntas. - Se o usuário já tiver um binário da CLI no servidor (por exemplo,
~/wcli), use-o diretamente. Não mude o binário de lugar, a menos que peçam. - Copie os trechos exatamente como estão em
references/digitalocean.mdpara todas as chamadas à API da DO. Não reescreva, não adapte e não improvise o parsing em Python: até pequenas mudanças (por exemplo, de escape ou de aspas) podem quebrar de um shell para outro. - Scripts remotos por SSH: use sempre
ssh host 'bash -s' << 'EOF'(heredoc entre aspas). Nunca usessh host "..."com aspas duplas, porque o zsh expande$(...)e[...]localmente antes de enviar ao host remoto.
Recuperação de falhas
Se deployment create falhar e você precisar tentar de novo:
- Use
wlycli deployment delete --domain <domain> --yes-please-delete-all-the-datapara limpar. - O delete tenta limpar por meio de contêiner os arquivos que pertencem ao root. Se ainda assim falhar, remova o diretório do projeto dentro de
--base-dircom permissões elevadas e rode de novo.
Teste prévio da porta 80 (opcional)
Se o certbot falhar, teste se a porta 80 está acessível antes de rodar de novo:
docker run --rm -d -p 80:80 --name test-http nginx:alpine
curl -s http://<domain>:80
docker rm -f test-http