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.
Desplegar servidor
Resumen
Esta skill crea un stack de Welley de una sola instancia en DigitalOcean y puede ejecutar actualizaciones por SSH. Guía al agente para reunir los datos que falten, consultar las especificaciones de instancia disponibles en una fuente definida, crear la VM, configurar el host, desplegar con wlycli deployment create y validar el resultado.
Los nombres de los comandos deben coincidir con los de la CLI:
wlycli deployment createwlycli deployment updatewlycli deployment delete
Valores predeterminados (DigitalOcean)
- Región:
nyc3 - Imagen:
latest LTS available via API(se resuelve conimages?type=distribution) - Nombre del droplet: se genera al azar con el formato
wlsly-<adjective>-<surname>(por ejemplo,wlsly-bright-hopper). Usa el fragmento generador de nombres dereferences/digitalocean.md. Si se crea una base de datos administrada, usa el mismo nombre para ella. - Plan objetivo: Basic / Regular (CPU compartida)
- Tamaño objetivo: 2 vCPU / 4 GB de RAM / 80 GB de SSD / 4 TB de transferencia (~$24/mes)
Regla para cambiar los valores predeterminados
Si el usuario indica un valor propio para alguno de los valores predeterminados (región, imagen, nombre del droplet, proyecto, tamaño), el agente debe:
- Repetir el cambio tal cual lo indicó.
- Pedir confirmación antes de continuar.
Plantilla de entrada interactiva
Pregunta solo lo que falte. Usa estas preguntas tal cual para reducir ambigüedades. Pregunta por rondas. Ronda 1: máximo 2 preguntas por turno. En la ronda 2 se puede ofrecer una sola opción para «aceptar todos los valores predeterminados». Si el entorno admite opciones, presenta 2 o 3 opciones por pregunta (A/B/C). Evita las respuestas libres salvo que sea necesario.
Preguntas de la ronda 1 (identidad y acceso):
- “¿Tienes un token de la API de DigitalOcean para usar, o espero a que me des uno?”
- “¿Qué dominio debe usar este servidor (por ejemplo,
super-puper.example.com)? ¿Controlas su DNS?” - “¿Ya tienes una clave pública SSH para usar, o la creo y la subo yo?”
- “¿Quieres asignar este droplet a un proyecto existente de DigitalOcean? Si es así, indica el nombre o el ID del proyecto.”
- “Requisito de DNS: debes crear registros A/AAAA para
<domain>ystorage.<domain>(si no hay CDN). ¿Puedes hacerlo antes de que se ejecute certbot?” - “Requisito de DNS para el correo: el dominio de
--smtp-fromnecesita registros SPF, DMARC y DKIM, o los correos de invitación y confirmación a destinatarios nuevos pueden descartarse sin aviso. ¿Ya los tienes, o te enumero los registros que necesita tu proveedor de SMTP?” - Si el usuario pregunta dónde conseguir un token de DO, dale este enlace:
https://cloud.digitalocean.com/account/api/tokens
Preguntas de la ronda 2 (tamaño, ubicación y opciones de despliegue):
- “¿Quieres la región predeterminada
nyc3u otra distinta?” - “¿Quieres el tamaño predeterminado (2 vCPU / 2 GB) u otro objetivo de CPU/RAM?”
- “¿Uso la última versión LTS de Ubuntu disponible en la API, o una versión concreta de Ubuntu?”
- “¿Qué usuario SSH usamos después del arranque inicial (predeterminado:
wlsly)? Puedes dejar el predeterminado.” - “¿Quieres una base de datos Postgres administrada, o usar el contenedor de Postgres incluido?”
- Si se elige Postgres administrado: “¿Qué región y tamaño uso para la base de datos? Puedo usar por defecto
nyc3y 1 vCPU / 2 GB.” - Si se elige Postgres administrado: “¿Quieres que continúe con la creación al precio mensual que indica el proveedor?”
- “Indícame los ajustes de SMTP obligatorios (host, usuario, contraseña, remitente). OTEL es opcional: indícalo solo si lo necesitas.”
- “El correo del administrador es obligatorio para crear. Indícalo ahora (flag:
--email/-e). Si no lo indicas, te lo pediré dos veces para confirmarlo.”
Ofrece una opción de «aceptar todos los valores predeterminados» en la ronda 2 para agilizar la recogida de datos.
Si falta alguna respuesta, haz una pregunta de seguimiento concreta (una o dos preguntas).
Flujo de trabajo (DigitalOcean, instancia única)
- Reunir los datos necesarios (preguntar si faltan).
- Token de la API de DigitalOcean
- Nombre o ID del proyecto (opcional; si falta o no se encuentra, usar el proyecto predeterminado)
- Región
- Tamaño objetivo de la instancia (por ejemplo, 4 vCPU / 16 GB de RAM)
- Nombre de dominio
- Clave pública SSH (o confirmación para crear y registrar una)
- Correo del administrador para el primer inicio de sesión y la recuperación de contraseña (obligatorio para crear;
--email/-e). Si falta, pedirlo dos veces y confirmar que coinciden. - Opcional: certificados TLS propios o certbot
- Confirmación de acceso al DNS (debe poder crear registros A/AAAA para
<domain>y parastorage.<domain>si se usa)
- Consultar los tipos de instancia y elegir un tamaño.
- Usa el fragmento de tamaños de
references/digitalocean.mdpara listar y filtrar por CPU/RAM. - Si hay varias coincidencias, confirma con el usuario.
2b. Resolver el slug de la imagen de Ubuntu.
- Llama a
GET /v2/images?type=distribution&per_page=200y filtra por Ubuntu. - Si el usuario pidió una versión concreta, comprueba que su slug exista y confírmalo.
- Si no, elige el slug de la última LTS de la lista y confírmalo con el usuario antes de crear el droplet.
- Crear el droplet.
- Usa directamente la API de DigitalOcean (doctl es opcional).
- Imagen: da preferencia a la que indique el usuario; si no, elige la última LTS de la lista de la API.
- Asocia la huella de la clave SSH, o crea y sube una clave.
- Activa el monitoreo.
- Si se indicó un nombre o ID de proyecto pero no se encontró, crea el droplet sin proyecto (proyecto predeterminado).
- Nota: la creación de la base de datos administrada puede hacerse en paralelo con la del droplet.
Guía de paralelización
El agente debe solapar las tareas independientes para reducir el tiempo total:
- Mientras reúnes los datos del usuario (ronda 2), empieza a crear el droplet si el token, la región, el tamaño, la imagen y la clave SSH ya están confirmados.
- Mientras el droplet se está creando, empieza a crear el Postgres administrado (si se pidió).
- Mientras el droplet arranca, sigue reuniendo los datos que faltan (SMTP, OTEL, correo del administrador).
- Si falta un dato crítico para un paso, pausa ese paso y continúa con otras tareas que se puedan hacer en paralelo.
- Si el DNS se administra en DigitalOcean, crea o actualiza los registros A/AAAA en cuanto esté disponible la IP del droplet (no esperes al paso completo de despliegue).
- DNS y dominio.
- Pregunta si se debe crear o actualizar el DNS en DigitalOcean o dejar un DNS externo.
- Si se usa el DNS de DigitalOcean, crea registros A/AAAA que apunten a la IP del droplet.
- Preparar el host por SSH.
- Crea un usuario sin privilegios de root (por ejemplo,
wlsly), dale sudo y copia las claves autorizadas de SSH. - Sal de root y vuelve a iniciar sesión con el usuario sin privilegios de root antes de continuar.
- Instala Docker y docker compose.
- Descarga el binario de la CLI de Welley desde AppStore y hazlo ejecutable:
- URL base:
https://appstore.allroads.social/v1/social.wellesley.wlycli/latest?develop=stable&platform=<os>/<arch> - Elige el valor correcto de
platformsegún el sistema operativo y la arquitectura:- 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:
- Ejemplo (Linux x86_64):
curl -fL 'https://appstore.allroads.social/v1/social.wellesley.wlycli/latest?develop=stable&platform=linux/amd64' -o wlycli chmod +x wlycli - Las cabeceras de respuesta esperadas incluyen:
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, conviene revisar las cabeceras con una petición HEAD y comprobar que el nombre del artefacto, el tipo, la plataforma y el canal coinciden con el binario que pediste.
- URL base:
- Verifica el binario de la CLI: ejecuta
wlycli -vywlycli deployment --helppara confirmar la información de compilación esperada.
- Desplegar Welley.
- Ejecuta
wlycli deployment createcon las opciones necesarias. - Usa los valores predeterminados de instancia única (sin Postgres externo, salvo que el usuario lo pida).
- Si se pide Postgres administrado, créalo primero (base de datos de DigitalOcean) y luego usa el host, puerto, base de datos, usuario y contraseña que te devuelva en los flags
--postgres-*. - Si la API o la interfaz no devuelven la contraseña del usuario de la base de datos, restablece la autenticación de ese usuario para obtener credenciales nuevas antes de ejecutar
wlycli. - Las ejecuciones no interactivas deben incluir
--email/-e, o el comando fallará. --base-dirapunta al directorio padre; la CLI crea el subdirectorio del proyecto automáticamente.- La CLI se niega a ejecutarse si el directorio del proyecto o los contenedores ya existen; hay que limpiar antes de reintentar.
- Certificados (obligatorio).
- Por defecto: usa Certbot en modo standalone (no interactivo).
- El usuario debe apuntar los registros DNS A/AAAA del dominio (y de
storage.<domain>si se usa) a la IP del droplet antes de que se ejecute certbot. - La CLI admite
--public-ip(para reemplazar la IP detectada) y--skip-dns-preflightsi tienes que saltarte la comprobación. - Nunca des por hecho que el DNS está configurado. Pregunta y espera una confirmación explícita.
- Nunca uses
--skip-dns-preflightsalvo que el usuario lo pida de forma explícita. - Si no hay CDN configurado, certbot debe incluir
storage.<domain>en la solicitud del certificado. - Usa certificados autofirmados solo si el usuario lo pide de forma explícita, y pasa
--self-signed-certs(genera certificados autofirmados en Go). - Dale al usuario las instrucciones de configuración del DNS y espera su confirmación:
- “Crea registros A/AAAA para que
<domain>apunte a la IP del droplet.” - “Si se usa
storage.<domain>, crea también un registro A/AAAA para él.” - “Cuando el DNS se propague, avísame y continúo. No puedo ver la propagación a menos que me pidas comprobar la resolución.”
- El agente puede comprobar la propagación del DNS por su cuenta con
ping -c 1 <domain>y comparar la IP con la del droplet. Si coincide, continúa.
7b. DNS del correo (SPF / DMARC / DKIM).
- Gmail y Outlook suelen descartar el correo de un dominio sin SPF ni DMARC cuando el destinatario es nuevo, aunque el proveedor de SMTP lo marque como entregado.
deployment createmuestra unWarning:cuando el dominio de--smtp-fromno tiene registro SPF, o no tiene registro DMARC en_dmarc.<domain>ni en un dominio superior. No bloquea el despliegue. Nunca ignores el aviso: muéstraselo al usuario y dale los registros que debe añadir:<mail-domain>TXTv=spf1 include:<provider> ~all(el include exacto lo da el proveedor de SMTP; intégralo en un registro SPF existente, nunca añadas un segundo registro)_dmarc.<mail-domain>TXTv=DMARC1; p=none; rua=mailto:dmarc@<mail-domain>- DKIM: los registros
<selector>._domainkey.<mail-domain>que genera el proveedor de SMTP cuando se verifica el dominio
- Compruébalo con
dig +short TXT <mail-domain>ydig +short TXT _dmarc.<mail-domain>. - La CLI no puede comprobar DKIM (el selector depende del proveedor). Pídele siempre al usuario que confirme que DKIM está verificado en el proveedor de SMTP, incluso cuando
createno haya mostrado ningún aviso. Con Amazon SES y proveedores similares, el SPF se comprueba sobre el dominio del remitente del sobre (envelope) del propio proveedor, así que solo DKIM puede hacer que DMARC pase. En SES, en Verified identities abre<mail-domain>y comprueba que DKIM indique Successful.
- Validar e informar.
- Revisa
docker psy los endpoints de estado de los servicios. - Entrega los datos finales de conexión y los siguientes pasos.
Flujo de actualización por SSH
Cuando el usuario pida «actualizar el servidor»:
- Pide el host o la IP de destino y el usuario y la clave de SSH.
- Ejecuta
wlycli deployment update --domain <domain> [--force-restart]. - Verifica el estado de los contenedores y de Nginx.
Recursos
- Fragmentos y ejemplos de la API de DigitalOcean:
references/digitalocean.md.
Secretos y sus flags
Usa estos nombres de flag para los secretos:
- Host SMTP:
--smtp-host - Usuario SMTP:
--smtp-user - Contraseña SMTP:
--smtp-password - Remitente SMTP:
--smtp-from - Endpoint de OTEL:
--otel-endpoint - Cabeceras de OTEL:
--otel-headers
Comando mínimo de creación
Flags obligatorios:
--domain--email--smtp-host--smtp-user--smtp-password--smtp-from
Ejemplo 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
Valores predeterminados de Postgres administrado (DigitalOcean y CLI)
Cuando uses el Postgres administrado de DigitalOcean, no dependas de los valores predeterminados de la CLI. Define todos los flags --postgres-* de forma explícita:
- Valores típicos de DO:
- Puerto:
25060 - Base de datos:
defaultdb - Usuario:
doadmin
- Puerto:
- Valores predeterminados de la CLI (si omites los flags):
- Puerto:
5432 - Base de datos:
wlsly - Usuario:
wlsly
- Puerto:
Notas de uso de la CLI
- Comprobar la versión:
wlycli -vowlycli --version(flag). No existe un subcomandoversion. - Usa
--base-dirsolo si quieres una ubicación distinta de la predeterminada (por defecto es~/.welley). La CLI creará el directorio si tiene permisos. - Las ejecuciones SSH no interactivas deben incluir
--emaily cualquier otro flag obligatorio para evitar preguntas. - Si el usuario ya puso un binario de la CLI en el servidor (por ejemplo,
~/wcli), úsalo directamente. No lo muevas a menos que te lo pidan. - Copia los fragmentos tal cual de
references/digitalocean.mdpara todas las llamadas a la API de DO. No reescribas, adaptes ni improvises el análisis en Python: incluso cambios pequeños (por ejemplo, de escape o de comillas) pueden fallar según el shell. - Scripts remotos por SSH: usa siempre
ssh host 'bash -s' << 'EOF'(heredoc entre comillas). Nunca usesssh host "..."con comillas dobles: zsh expande$(...)y[...]en local antes de enviar el comando al host remoto.
Recuperación tras un fallo
Si deployment create falla y necesitas reintentar:
- Usa
wlycli deployment delete --domain <domain> --yes-please-delete-all-the-datapara limpiar. - El comando delete intentará limpiar mediante contenedores los archivos que pertenecen a root. Si aun así falla, elimina con permisos elevados el directorio del proyecto dentro de
--base-diry vuelve a ejecutar.
Prueba previa del puerto 80 (opcional)
Si certbot falla, prueba que el puerto 80 sea accesible antes de volver a ejecutarlo:
docker run --rm -d -p 80:80 --name test-http nginx:alpine
curl -s http://<domain>:80
docker rm -f test-http