skills/deploy-server/SKILL.md

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.

Развёртывание сервера

Обзор

Этот навык разворачивает на DigitalOcean один экземпляр Welley и может запускать обновления по SSH. Он помогает агенту собрать недостающие данные, получить список доступных конфигураций из заданного источника, создать виртуальную машину, настроить хост, развернуть Welley командой wlycli deployment create и проверить результат.

Названия команд должны совпадать с названиями в CLI:

  • wlycli deployment create
  • wlycli deployment update
  • wlycli deployment delete

Значения по умолчанию (DigitalOcean)

  • Регион: nyc3
  • Образ: latest LTS available via API (определите через images?type=distribution)
  • Имя дроплета: случайное, в виде wlsly-<adjective>-<surname> (например, wlsly-bright-hopper). Возьмите фрагмент для генерации имени из references/digitalocean.md. Если создаётся управляемая база данных, используйте для неё то же имя.
  • Тариф: Basic / Regular (Shared CPU)
  • Размер: 2 vCPU / 4 GB RAM / 80 GB SSD / 4 TB трафика (около $24 в месяц)

Правило изменения значений по умолчанию

Если пользователь задаёт любое из значений по умолчанию (регион, образ, имя дроплета, проект, размер), агент должен:

  1. Повторить это значение пользователю дословно.
  2. Попросить подтверждения, прежде чем продолжить.

Шаблон интерактивного ввода

Спрашивайте только о том, чего не хватает. Используйте именно эти формулировки, чтобы вопросы не поняли неверно. Задавайте вопросы по раундам. Раунд 1: не больше 2 вопросов за один ход. В раунде 2 можно предложить общий вариант «принять все значения по умолчанию». Если среда выполнения поддерживает выбор из вариантов, предлагайте на каждый вопрос 2 или 3 варианта (A/B/C). Свободный ввод используйте только при необходимости.

Вопросы раунда 1 (данные и доступ):

  1. «Есть ли у вас API-токен DigitalOcean, который я могу использовать, или мне подождать, пока вы его предоставите?»
  2. «Какой домен должен использовать этот сервер (например, super-puper.example.com)? Управляете ли вы его DNS?»
  3. «Есть ли у вас публичный SSH-ключ, который можно использовать, или мне создать его и загрузить?»
  4. «Нужно ли добавить этот дроплет в существующий проект DigitalOcean? Если да, укажите название или ID проекта.»
  5. «Требование к DNS: вам нужно создать A/AAAA-записи для <domain> и storage.<domain> (если нет CDN). Сможете сделать это до запуска certbot?»
  6. «Требование к DNS для почты: у домена из --smtp-from должны быть записи SPF, DMARC и DKIM, иначе письма с приглашениями и подтверждениями для новых получателей могут молча пропадать. Эти записи уже есть, или мне перечислить записи, которые нужны вашему SMTP-провайдеру?»
  7. Если пользователь спрашивает, где взять токен DO, дайте эту ссылку:
https://cloud.digitalocean.com/account/api/tokens

Вопросы раунда 2 (размер, расположение и параметры развёртывания):

  1. «Оставить регион по умолчанию nyc3 или выбрать другой?»
  2. «Оставить размер по умолчанию (2 vCPU / 2 GB) или нужны другие параметры процессора и памяти?»
  3. «Взять последнюю версию Ubuntu LTS, доступную в API, или вам нужна конкретная версия Ubuntu?»
  4. «Какого SSH-пользователя использовать после начальной настройки (по умолчанию wlsly)? Можно оставить значение по умолчанию.»
  5. «Создать управляемую базу Postgres или использовать встроенный контейнер Postgres?»
  6. Если выбран управляемый Postgres: «Какой регион и размер базы использовать? По умолчанию я возьму nyc3 и 1 vCPU / 2 GB.»
  7. Если выбран управляемый Postgres: «Создавать базу по месячной цене, которую указывает провайдер?»
  8. «Пришлите обязательные настройки SMTP (хост, пользователь, пароль, адрес отправителя). OTEL необязателен: указывайте его, только если он нужен.»
  9. «Для создания нужен email администратора. Укажите его сейчас (флаг: --email / -e). Если вы его не укажете, я попрошу ввести его дважды для проверки.»

Чтобы ускорить сбор данных, предложите в раунде 2 вариант «принять все значения по умолчанию».

Если на какой-то вопрос нет ответа, задайте короткий уточняющий вопрос (один или два).

Порядок работы (DigitalOcean, один экземпляр)

  1. Соберите необходимые данные (спросите, если их нет).
  • API-токен DigitalOcean
  • Название или ID проекта (необязательно; если не указан или не найден, используйте проект по умолчанию)
  • Регион
  • Нужный размер экземпляра (например, 4 vCPU / 16 GB RAM)
  • Доменное имя
  • Публичный SSH-ключ (или согласие создать и зарегистрировать ключ)
  • Email администратора для первого входа и восстановления пароля (обязателен для создания; --email / -e). Если его нет, запросите дважды и проверьте, что значения совпадают.
  • По желанию: свои TLS-сертификаты вместо certbot
  • Подтверждение доступа к DNS (нужно уметь создавать A/AAAA-записи для <domain> и, если он используется, для storage.<domain>)
  1. Получите список типов экземпляров и выберите размер.
  • Возьмите фрагмент для получения размеров из references/digitalocean.md, выведите список и отфильтруйте его по процессору и памяти.
  • Если подходит несколько вариантов, уточните выбор у пользователя.

2b. Определите slug образа Ubuntu.

  • Вызовите GET /v2/images?type=distribution&per_page=200 и отфильтруйте Ubuntu.
  • Если пользователь запросил конкретную версию, убедитесь, что такой slug существует, и подтвердите выбор.
  • Иначе возьмите из списка slug последней LTS-версии и подтвердите его у пользователя до создания.
  1. Создайте дроплет.
  • Используйте напрямую API DigitalOcean (doctl необязателен).
  • Образ: предпочитайте тот, что указал пользователь; иначе возьмите последнюю LTS из списка API.
  • Прикрепите отпечаток SSH-ключа или создайте и загрузите ключ.
  • Включите мониторинг.
  • Если название или ID проекта указаны, но проект не найден, создайте дроплет без проекта (в проекте по умолчанию).
  • Примечание: управляемую базу данных можно создавать параллельно с дроплетом.

Параллельное выполнение

Чтобы сократить общее время, агент должен совмещать независимые задачи:

  • Пока вы собираете ответы пользователя (раунд 2), начинайте создавать дроплет, если токен, регион, размер, образ и SSH-ключ уже подтверждены.
  • Пока дроплет создаётся, начинайте создавать управляемый Postgres (если он нужен).
  • Пока дроплет запускается, продолжайте собирать остальные данные (SMTP, OTEL, email администратора).
  • Если для какого-то шага не хватает важных данных, приостановите этот шаг и продолжайте другие задачи, которые можно выполнять параллельно.
  • Если DNS управляется в DigitalOcean, создайте или обновите A/AAAA-записи, как только станет известен IP дроплета (не ждите шага полного развёртывания).
  1. DNS и домен.
  • Спросите, создавать или обновлять DNS в DigitalOcean или оставить внешний DNS.
  • Если используется DNS DigitalOcean, создайте A/AAAA-записи, указывающие на IP дроплета.
  1. Настройте хост по SSH.
  • Создайте пользователя без прав root (например, wlsly), выдайте ему sudo и скопируйте SSH-ключи из authorized keys.
  • Выйдите из root и войдите снова как этот пользователь, прежде чем продолжать.
  • Установите Docker и docker compose.
  • Скачайте бинарный файл Welley CLI из AppStore и сделайте его исполняемым:
    • Базовый URL: https://appstore.allroads.social/v1/social.wellesley.wlycli/latest?develop=stable&platform=<os>/<arch>
    • Выберите правильное значение platform по ОС и архитектуре:
      • 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):
      curl -fL 'https://appstore.allroads.social/v1/social.wellesley.wlycli/latest?develop=stable&platform=linux/amd64' -o wlycli
      chmod +x wlycli
      
    • В ответе ожидаются такие заголовки:
      • x-artifact-display-name: Welley CLI
      • x-artifact-full-name: social.wellesley.wlycli
      • x-artifact-kind: cli
      • x-artifact-platform: <os>/<arch>, например linux/amd64
      • x-artifact-sha256: <sha256>
      • x-artifact-version: <version>
      • x-channel: develop
    • Перед установкой лучше проверить заголовки HEAD-запросом и убедиться, что название артефакта, его тип, платформа и канал совпадают с запрошенным файлом.
  • Проверьте исполняемый файл CLI: выполните wlycli -v и wlycli deployment --help, чтобы убедиться, что сведения о сборке соответствуют ожидаемым.
  1. Разверните Welley.
  • Запустите wlycli deployment create с нужными параметрами.
  • Используйте значения по умолчанию для одного экземпляра (без внешнего Postgres, если пользователь его не просит).
  • Если нужен управляемый Postgres, сначала создайте его (база данных DigitalOcean), а затем передайте полученные хост, порт, базу, пользователя и пароль во флаги --postgres-*.
  • Если пароль пользователя базы данных не возвращается ни через API, ни в интерфейсе, сбросьте аутентификацию этого пользователя и получите новые учётные данные до запуска wlycli.
  • В неинтерактивном режиме обязательно передайте --email / -e, иначе команда завершится с ошибкой.
  • --base-dir указывает на родительский каталог; подкаталог проекта CLI создаёт сам.
  • CLI не запустится, если каталог проекта или контейнеры уже существуют; перед повторной попыткой их нужно удалить.
  1. Сертификаты (обязательно).
  • По умолчанию: Certbot в режиме standalone, в неинтерактивном режиме.
  • Пользователь должен направить A/AAAA-записи домена (и storage.<domain>, если он используется) на IP дроплета до запуска certbot.
  • CLI поддерживает --public-ip (заменяет автоматически определённый IP) и --skip-dns-preflight, если проверку нужно обойти.
  • Никогда не считайте, что DNS уже настроен. Спросите и дождитесь явного подтверждения.
  • Не используйте --skip-dns-preflight, если пользователь прямо об этом не попросил.
  • Если CDN не настроен, в запрос сертификата certbot нужно включить storage.<domain>.
  • Самоподписанные сертификаты используйте, только если пользователь прямо об этом просит, и передайте --self-signed-certs (самоподписанные сертификаты создаются средствами Go).
  • Дайте пользователю инструкции по настройке DNS и дождитесь подтверждения:
  • «Создайте A/AAAA-записи, чтобы <domain> указывал на IP дроплета.»
  • «Если используется storage.<domain>, создайте A/AAAA-запись и для него.»
  • «Когда DNS обновится, сообщите мне, и я продолжу. Я не вижу, обновился ли DNS, пока вы не попросите меня проверить разрешение имени.»
  • Агент может сам проверить обновление DNS командой ping -c 1 <domain> и сравнить IP с адресом дроплета. Если они совпадают, можно продолжать.

7b. DNS для почты (SPF / DMARC / DKIM).

  • Gmail и Outlook часто отбрасывают письма с домена без SPF и DMARC, если они адресованы новым получателям, даже когда SMTP-провайдер сообщает, что письмо доставлено.
  • deployment create выводит Warning:, если у домена из --smtp-from нет записи SPF или нет записи DMARC в _dmarc.<domain> или в родительском домене. Развёртывание это не блокирует. Не игнорируйте предупреждение: покажите его пользователю и дайте записи, которые нужно добавить:
    • <mail-domain> TXT v=spf1 include:<provider> ~all (точное значение include зависит от SMTP-провайдера; объедините его с существующей записью SPF и никогда не добавляйте вторую)
    • _dmarc.<mail-domain> TXT v=DMARC1; p=none; rua=mailto:dmarc@<mail-domain>
    • DKIM: записи <selector>._domainkey.<mail-domain>, которые SMTP-провайдер создаёт при подтверждении домена
  • Проверьте командами dig +short TXT <mail-domain> и dig +short TXT _dmarc.<mail-domain>.
  • CLI не может проверить DKIM (селектор зависит от провайдера). Всегда просите пользователя подтвердить, что SMTP-провайдер успешно проверил DKIM, даже если create не вывел предупреждений. У Amazon SES и похожих провайдеров SPF проверяется для собственного домена конверта провайдера, поэтому DMARC может пройти только за счёт DKIM. В SES: в разделе Verified identities откройте <mail-domain>, там в поле DKIM должно быть Successful.
  1. Проверьте результат и сообщите о нём.
  • Проверьте docker ps и эндпоинты состояния сервисов.
  • Сообщите итоговые данные для подключения и дальнейшие шаги.

Обновление по SSH

Когда пользователь просит «обновить сервер»:

  1. Спросите адрес хоста или IP, а также SSH-пользователя и ключ.
  2. Выполните wlycli deployment update --domain <domain> [--force-restart].
  3. Проверьте состояние контейнеров и Nginx.

Ресурсы

  • Фрагменты и примеры для API DigitalOcean: references/digitalocean.md.

Секреты и флаги

Для секретов используйте такие флаги:

  • Хост SMTP: --smtp-host
  • Пользователь SMTP: --smtp-user
  • Пароль SMTP: --smtp-password
  • Адрес отправителя SMTP: --smtp-from
  • Эндпоинт OTEL: --otel-endpoint
  • Заголовки OTEL: --otel-headers

Минимальная команда создания

Обязательные флаги:

  • --domain
  • --email
  • --smtp-host
  • --smtp-user
  • --smtp-password
  • --smtp-from

Минимальный пример:

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

Значения Postgres по умолчанию (DigitalOcean и CLI)

Если вы используете управляемый Postgres от DigitalOcean, не полагайтесь на значения по умолчанию в CLI. Задайте все флаги --postgres-* явно:

  • Обычные значения DO:
    • Порт: 25060
    • База данных: defaultdb
    • Пользователь: doadmin
  • Значения по умолчанию в CLI (если не указывать флаги):
    • Порт: 5432
    • База данных: wlsly
    • Пользователь: wlsly

Заметки по работе с CLI

  • Проверка версии: wlycli -v или wlycli --version (это флаг). Подкоманды version нет.
  • Используйте --base-dir только если нужен нестандартный каталог (по умолчанию ~/.welley). CLI создаст каталог, если у него хватает прав.
  • При запуске по SSH без диалога добавляйте --email и все обязательные флаги, чтобы не появлялись вопросы.
  • Если пользователь уже положил исполняемый файл CLI на сервер (например, ~/wcli), используйте его как есть. Не перемещайте его без просьбы.
  • Копируйте фрагменты дословно из references/digitalocean.md для всех вызовов API DO. Не переписывайте, не подгоняйте и не придумывайте заново разбор в Python: даже небольшие изменения (например, в экранировании или кавычках) могут перестать работать в другой оболочке.
  • Удалённые скрипты по SSH: всегда используйте ssh host 'bash -s' << 'EOF' (heredoc в кавычках). Никогда не используйте ssh host "..." с двойными кавычками: zsh раскрывает $(...) и [...] локально, до отправки на удалённый хост.

Восстановление после сбоя

Если deployment create завершилась с ошибкой и нужно повторить попытку:

  • Для очистки выполните wlycli deployment delete --domain <domain> --yes-please-delete-all-the-data.
  • Команда delete попробует очистить файлы, принадлежащие root, с помощью контейнера. Если и это не получится, удалите каталог проекта внутри --base-dir с повышенными правами и запустите команду снова.

Предварительная проверка порта 80 (по желанию)

Если certbot завершился с ошибкой, перед повторным запуском проверьте, доступен ли порт 80:

docker run --rm -d -p 80:80 --name test-http nginx:alpine
curl -s http://<domain>:80
docker rm -f test-http

Другие документы