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 createwlycli deployment updatewlycli 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 вопросов за один ход. В раунде 2 можно предложить общий вариант «принять все значения по умолчанию». Если среда выполнения поддерживает выбор из вариантов, предлагайте на каждый вопрос 2 или 3 варианта (A/B/C). Свободный ввод используйте только при необходимости.
Вопросы раунда 1 (данные и доступ):
- «Есть ли у вас API-токен DigitalOcean, который я могу использовать, или мне подождать, пока вы его предоставите?»
- «Какой домен должен использовать этот сервер (например,
super-puper.example.com)? Управляете ли вы его DNS?» - «Есть ли у вас публичный SSH-ключ, который можно использовать, или мне создать его и загрузить?»
- «Нужно ли добавить этот дроплет в существующий проект DigitalOcean? Если да, укажите название или ID проекта.»
- «Требование к DNS: вам нужно создать A/AAAA-записи для
<domain>иstorage.<domain>(если нет CDN). Сможете сделать это до запуска certbot?» - «Требование к DNS для почты: у домена из
--smtp-fromдолжны быть записи SPF, DMARC и DKIM, иначе письма с приглашениями и подтверждениями для новых получателей могут молча пропадать. Эти записи уже есть, или мне перечислить записи, которые нужны вашему SMTP-провайдеру?» - Если пользователь спрашивает, где взять токен DO, дайте эту ссылку:
https://cloud.digitalocean.com/account/api/tokens
Вопросы раунда 2 (размер, расположение и параметры развёртывания):
- «Оставить регион по умолчанию
nyc3или выбрать другой?» - «Оставить размер по умолчанию (2 vCPU / 2 GB) или нужны другие параметры процессора и памяти?»
- «Взять последнюю версию Ubuntu LTS, доступную в API, или вам нужна конкретная версия Ubuntu?»
- «Какого SSH-пользователя использовать после начальной настройки (по умолчанию
wlsly)? Можно оставить значение по умолчанию.» - «Создать управляемую базу Postgres или использовать встроенный контейнер Postgres?»
- Если выбран управляемый Postgres: «Какой регион и размер базы использовать? По умолчанию я возьму
nyc3и 1 vCPU / 2 GB.» - Если выбран управляемый Postgres: «Создавать базу по месячной цене, которую указывает провайдер?»
- «Пришлите обязательные настройки SMTP (хост, пользователь, пароль, адрес отправителя). OTEL необязателен: указывайте его, только если он нужен.»
- «Для создания нужен email администратора. Укажите его сейчас (флаг:
--email/-e). Если вы его не укажете, я попрошу ввести его дважды для проверки.»
Чтобы ускорить сбор данных, предложите в раунде 2 вариант «принять все значения по умолчанию».
Если на какой-то вопрос нет ответа, задайте короткий уточняющий вопрос (один или два).
Порядок работы (DigitalOcean, один экземпляр)
- Соберите необходимые данные (спросите, если их нет).
- API-токен DigitalOcean
- Название или ID проекта (необязательно; если не указан или не найден, используйте проект по умолчанию)
- Регион
- Нужный размер экземпляра (например, 4 vCPU / 16 GB RAM)
- Доменное имя
- Публичный SSH-ключ (или согласие создать и зарегистрировать ключ)
- Email администратора для первого входа и восстановления пароля (обязателен для создания;
--email/-e). Если его нет, запросите дважды и проверьте, что значения совпадают. - По желанию: свои TLS-сертификаты вместо certbot
- Подтверждение доступа к DNS (нужно уметь создавать A/AAAA-записи для
<domain>и, если он используется, дляstorage.<domain>)
- Получите список типов экземпляров и выберите размер.
- Возьмите фрагмент для получения размеров из
references/digitalocean.md, выведите список и отфильтруйте его по процессору и памяти. - Если подходит несколько вариантов, уточните выбор у пользователя.
2b. Определите slug образа Ubuntu.
- Вызовите
GET /v2/images?type=distribution&per_page=200и отфильтруйте Ubuntu. - Если пользователь запросил конкретную версию, убедитесь, что такой slug существует, и подтвердите выбор.
- Иначе возьмите из списка slug последней LTS-версии и подтвердите его у пользователя до создания.
- Создайте дроплет.
- Используйте напрямую API DigitalOcean (doctl необязателен).
- Образ: предпочитайте тот, что указал пользователь; иначе возьмите последнюю LTS из списка API.
- Прикрепите отпечаток SSH-ключа или создайте и загрузите ключ.
- Включите мониторинг.
- Если название или ID проекта указаны, но проект не найден, создайте дроплет без проекта (в проекте по умолчанию).
- Примечание: управляемую базу данных можно создавать параллельно с дроплетом.
Параллельное выполнение
Чтобы сократить общее время, агент должен совмещать независимые задачи:
- Пока вы собираете ответы пользователя (раунд 2), начинайте создавать дроплет, если токен, регион, размер, образ и SSH-ключ уже подтверждены.
- Пока дроплет создаётся, начинайте создавать управляемый Postgres (если он нужен).
- Пока дроплет запускается, продолжайте собирать остальные данные (SMTP, OTEL, email администратора).
- Если для какого-то шага не хватает важных данных, приостановите этот шаг и продолжайте другие задачи, которые можно выполнять параллельно.
- Если DNS управляется в DigitalOcean, создайте или обновите A/AAAA-записи, как только станет известен IP дроплета (не ждите шага полного развёртывания).
- DNS и домен.
- Спросите, создавать или обновлять DNS в DigitalOcean или оставить внешний DNS.
- Если используется DNS DigitalOcean, создайте A/AAAA-записи, указывающие на IP дроплета.
- Настройте хост по 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:
- Пример (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 CLIx-artifact-full-name: social.wellesley.wlyclix-artifact-kind: clix-artifact-platform: <os>/<arch>, напримерlinux/amd64x-artifact-sha256: <sha256>x-artifact-version: <version>x-channel: develop
- Перед установкой лучше проверить заголовки HEAD-запросом и убедиться, что название артефакта, его тип, платформа и канал совпадают с запрошенным файлом.
- Базовый URL:
- Проверьте исполняемый файл CLI: выполните
wlycli -vиwlycli deployment --help, чтобы убедиться, что сведения о сборке соответствуют ожидаемым.
- Разверните Welley.
- Запустите
wlycli deployment createс нужными параметрами. - Используйте значения по умолчанию для одного экземпляра (без внешнего Postgres, если пользователь его не просит).
- Если нужен управляемый Postgres, сначала создайте его (база данных DigitalOcean), а затем передайте полученные хост, порт, базу, пользователя и пароль во флаги
--postgres-*. - Если пароль пользователя базы данных не возвращается ни через API, ни в интерфейсе, сбросьте аутентификацию этого пользователя и получите новые учётные данные до запуска
wlycli. - В неинтерактивном режиме обязательно передайте
--email/-e, иначе команда завершится с ошибкой. --base-dirуказывает на родительский каталог; подкаталог проекта CLI создаёт сам.- CLI не запустится, если каталог проекта или контейнеры уже существуют; перед повторной попыткой их нужно удалить.
- Сертификаты (обязательно).
- По умолчанию: 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>TXTv=spf1 include:<provider> ~all(точное значение include зависит от SMTP-провайдера; объедините его с существующей записью SPF и никогда не добавляйте вторую)_dmarc.<mail-domain>TXTv=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.
- Проверьте результат и сообщите о нём.
- Проверьте
docker psи эндпоинты состояния сервисов. - Сообщите итоговые данные для подключения и дальнейшие шаги.
Обновление по SSH
Когда пользователь просит «обновить сервер»:
- Спросите адрес хоста или IP, а также SSH-пользователя и ключ.
- Выполните
wlycli deployment update --domain <domain> [--force-restart]. - Проверьте состояние контейнеров и 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