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.

Wdrażanie serwera

Przegląd

Ten skill tworzy pojedynczą instancję Welley na DigitalOcean i potrafi uruchamiać aktualizacje przez SSH. Prowadzi agenta przez zebranie brakujących danych, pobranie dostępnych parametrów instancji ze wskazanego źródła, utworzenie maszyny wirtualnej, skonfigurowanie hosta, wdrożenie poleceniem wlycli deployment create i sprawdzenie wyniku.

Nazwy poleceń muszą zgadzać się z CLI:

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

Ustawienia domyślne (DigitalOcean)

  • Region: nyc3
  • Obraz: latest LTS available via API (ustal przez images?type=distribution)
  • Nazwa dropleta: losowo generowana jako wlsly-<adjective>-<surname> (np. wlsly-bright-hopper). Użyj fragmentu generatora nazw z references/digitalocean.md. Jeśli tworzysz zarządzaną bazę danych, nadaj jej tę samą nazwę.
  • Docelowy plan: Basic / Regular (Shared CPU)
  • Docelowy rozmiar: 2 vCPU / 4 GB RAM / 80 GB SSD / 4 TB transferu (ok. 24 USD miesięcznie)

Zmiana ustawień domyślnych

Jeśli użytkownik poda dowolną z wartości domyślnych (region, obraz, nazwę dropleta, projekt, rozmiar), agent musi:

  1. Powtórzyć tę zmianę dosłownie.
  2. Poprosić o potwierdzenie przed dalszymi krokami.

Szablon pytań do użytkownika

Pytaj tylko o to, czego brakuje. Używaj dokładnie tych pytań, żeby uniknąć nieporozumień. Pytaj w kilku rundach. Runda 1: najwyżej 2 pytania naraz. W rundzie 2 możesz zaproponować zbiorczą opcję „przyjmij wszystkie ustawienia domyślne”. Jeśli środowisko obsługuje wybór opcji, podaj 2 lub 3 opcje do każdego pytania (A/B/C). Unikaj pytań otwartych, chyba że to konieczne.

Pytania w rundzie 1 (podstawowe dane i dostęp):

  1. „Czy masz token API DigitalOcean, którego mam użyć, czy mam poczekać, aż go podasz?”
  2. „Jakiej domeny ma używać ten serwer (np. super-puper.example.com)? Czy masz kontrolę nad jej DNS?”
  3. „Czy masz już klucz publiczny SSH, którego mam użyć, czy mam go utworzyć i wgrać?”
  4. „Czy chcesz przypisać tego dropleta do istniejącego projektu DigitalOcean? Jeśli tak, podaj nazwę lub ID projektu.”
  5. „Wymaganie DNS: musisz utworzyć rekordy A/AAAA dla <domain> i storage.<domain> (jeśli nie ma CDN). Czy możesz to zrobić, zanim uruchomię certbota?”
  6. „Wymaganie DNS dla poczty: domena z --smtp-from potrzebuje rekordów SPF, DMARC i DKIM, bo inaczej zaproszenia i e-maile z potwierdzeniem do nowych odbiorców mogą po cichu przepadać. Czy rekordy są już ustawione, czy mam wypisać te, których potrzebuje twój dostawca SMTP?”
  7. Jeśli użytkownik zapyta, gdzie zdobyć token DO, podaj ten link:
https://cloud.digitalocean.com/account/api/tokens

Pytania w rundzie 2 (rozmiar, lokalizacja i opcje wdrożenia):

  1. „Czy chcesz domyślny region nyc3, czy inny?”
  2. „Czy chcesz domyślny rozmiar (2 vCPU / 2 GB), czy inne parametry CPU/RAM?”
  3. „Mam użyć najnowszego Ubuntu LTS dostępnego w API, czy konkretnej wersji Ubuntu?”
  4. „Jakiego użytkownika SSH mamy używać po wstępnej konfiguracji (domyślnie: wlsly)? Możesz zostawić domyślnego.”
  5. „Chcesz zarządzaną bazę Postgres, czy dołączony kontener z Postgresem?”
  6. Jeśli wybrano zarządzany Postgres: „Jakiego regionu i rozmiaru bazy mam użyć? Mogę domyślnie wybrać nyc3 i 1 vCPU / 2 GB.”
  7. Jeśli wybrano zarządzany Postgres: „Czy mam przejść do tworzenia bazy po cenie miesięcznej podanej przez dostawcę?”
  8. „Podaj wymagane ustawienia SMTP (host, użytkownik, hasło, nadawca). OTEL jest opcjonalny, podaj go tylko wtedy, gdy jest potrzebny.”
  9. „Adres e-mail administratora jest wymagany do utworzenia instancji. Podaj go teraz (flaga: --email / -e). Jeśli go nie podasz, poproszę o niego dwa razy, żeby się upewnić.”

W rundzie 2 zaproponuj opcję „przyjmij wszystkie ustawienia domyślne”, żeby szybciej zebrać dane.

Jeśli brakuje którejś odpowiedzi, zadaj krótkie pytanie uzupełniające (jedno lub dwa).

Przebieg pracy (DigitalOcean, pojedyncza instancja)

  1. Zbierz wymagane dane (zapytaj, jeśli czegoś brakuje).
  • Token API DigitalOcean
  • Nazwa lub ID projektu (opcjonalnie; jeśli brak albo nie znaleziono, użyj projektu domyślnego)
  • Region
  • Docelowy rozmiar instancji (np. 4 vCPU / 16 GB RAM)
  • Nazwa domeny
  • Klucz publiczny SSH (lub zgoda na utworzenie i zarejestrowanie go)
  • E-mail administratora do pierwszego logowania i odzyskiwania hasła (wymagany do utworzenia instancji; --email / -e). Jeśli go brakuje, poproś o niego dwa razy i sprawdź, czy oba wpisy są takie same.
  • Opcjonalnie: własne certyfikaty TLS zamiast certbota
  • Potwierdzenie dostępu do DNS (musisz móc utworzyć rekordy A/AAAA dla <domain> i, jeśli jest używana, dla storage.<domain>)
  1. Pobierz typy instancji i wybierz rozmiar.
  • Użyj fragmentu sizes z references/digitalocean.md, żeby wypisać rozmiary i przefiltrować je po CPU/RAM.
  • Jeśli pasuje kilka, potwierdź wybór z użytkownikiem.

2b. Ustal slug obrazu Ubuntu.

  • Wywołaj GET /v2/images?type=distribution&per_page=200 i przefiltruj listę pod kątem Ubuntu.
  • Jeśli użytkownik poprosił o konkretną wersję, sprawdź, czy jej slug istnieje, i potwierdź.
  • W przeciwnym razie wybierz z listy slug najnowszego LTS i przed utworzeniem dropleta potwierdź go z użytkownikiem.
  1. Utwórz dropleta.
  • Używaj bezpośrednio API DigitalOcean (doctl jest opcjonalny).
  • Obraz: wybierz ten, który wskazał użytkownik; w przeciwnym razie najnowszy LTS z listy z API.
  • Dołącz odcisk (fingerprint) klucza SSH albo utwórz i wgraj nowy klucz.
  • Włącz monitoring.
  • Jeśli podano nazwę lub ID projektu, ale go nie znaleziono, utwórz dropleta bez projektu (w projekcie domyślnym).
  • Uwaga: zarządzaną bazę danych można tworzyć równolegle z dropletem.

Wskazówki dotyczące równoległego działania

Agent powinien nakładać na siebie niezależne zadania, żeby skrócić czas oczekiwania:

  • Podczas zbierania danych od użytkownika (runda 2) zacznij tworzyć dropleta, jeśli token, region, rozmiar, obraz i klucz SSH są już potwierdzone.
  • Gdy droplet jest tworzony, zacznij tworzyć zarządzanego Postgresa (jeśli o niego poproszono).
  • Gdy droplet się uruchamia, zbieraj dalej pozostałe dane (SMTP, OTEL, e-mail administratora).
  • Jeśli do któregoś kroku brakuje krytycznych danych, wstrzymaj ten krok i zajmij się innymi zadaniami, które można robić równolegle.
  • Jeśli DNS jest w DigitalOcean, utwórz lub zaktualizuj rekordy A/AAAA od razu, gdy tylko będzie znane IP dropleta (nie czekaj na krok pełnego wdrożenia).
  1. DNS i domena.
  • Zapytaj, czy tworzyć lub aktualizować DNS w DigitalOcean, czy zostawić zewnętrzny DNS.
  • Jeśli używasz DNS w DigitalOcean, utwórz rekordy A/AAAA wskazujące na IP dropleta.
  1. Skonfiguruj hosta przez SSH.
  • Utwórz użytkownika innego niż root (np. wlsly), nadaj mu sudo i skopiuj autoryzowane klucze SSH (authorized keys).
  • Wyloguj się z roota i zaloguj ponownie jako ten użytkownik, zanim pójdziesz dalej.
  • Zainstaluj Dockera i docker compose.
  • Pobierz plik binarny Welley CLI z AppStore i nadaj mu uprawnienia do uruchamiania:
    • Bazowy URL: https://appstore.allroads.social/v1/social.wellesley.wlycli/latest?develop=stable&platform=<os>/<arch>
    • Wybierz właściwą wartość platform według systemu i architektury:
      • Linux x86_64: linux/amd64
      • Linux arm64: linux/arm64
      • macOS x86_64: darwin/amd64
      • macOS arm64: darwin/arm64
      • Windows x86_64: windows/amd64
    • Przykład (Linux x86_64):
      curl -fL 'https://appstore.allroads.social/v1/social.wellesley.wlycli/latest?develop=stable&platform=linux/amd64' -o wlycli
      chmod +x wlycli
      
    • Oczekiwane nagłówki odpowiedzi obejmują:
      • x-artifact-display-name: Welley CLI
      • x-artifact-full-name: social.wellesley.wlycli
      • x-artifact-kind: cli
      • x-artifact-platform: <os>/<arch>, np. linux/amd64
      • x-artifact-sha256: <sha256>
      • x-artifact-version: <version>
      • x-channel: develop
    • Przed instalacją najlepiej sprawdź nagłówki zapytaniem HEAD i upewnij się, że nazwa artefaktu, rodzaj, platforma i kanał zgadzają się z żądanym plikiem binarnym.
  • Zweryfikuj plik binarny CLI: uruchom wlycli -v i wlycli deployment --help, żeby potwierdzić oczekiwane informacje o buildzie.
  1. Wdróż Welley.
  • Uruchom wlycli deployment create z wymaganymi opcjami.
  • Użyj ustawień domyślnych dla pojedynczej instancji (bez zewnętrznego Postgresa, chyba że użytkownik o to poprosi).
  • Jeśli potrzebny jest zarządzany Postgres, utwórz go najpierw (baza DigitalOcean), a potem użyj zwróconych wartości host/port/db/user/password we flagach --postgres-*.
  • Jeśli API lub panel nie zwraca hasła użytkownika bazy, zresetuj uwierzytelnianie tego użytkownika, żeby dostać nowe dane dostępowe, zanim uruchomisz wlycli.
  • Uruchomienia nieinteraktywne muszą przekazać --email / -e, bo inaczej polecenie się nie powiedzie.
  • --base-dir wskazuje katalog nadrzędny; CLI samo tworzy podkatalog projektu.
  • CLI odmawia działania, jeśli katalog projektu lub kontenery już istnieją; przed ponowną próbą trzeba to wyczyścić.
  1. Certyfikaty (obowiązkowe).
  • Domyślnie: Certbot w trybie standalone (nieinteraktywnie).
  • Użytkownik musi skierować rekordy DNS A/AAAA domeny (i storage.<domain>, jeśli jest używana) na IP dropleta, zanim uruchomi się certbot.
  • CLI obsługuje --public-ip (nadpisuje wykryte IP) oraz --skip-dns-preflight, jeśli koniecznie trzeba pominąć to sprawdzenie.
  • Nigdy nie zakładaj, że DNS jest skonfigurowany. Zapytaj i poczekaj na wyraźne potwierdzenie.
  • Nigdy nie używaj --skip-dns-preflight, chyba że użytkownik wyraźnie o to poprosi.
  • Jeśli CDN nie jest skonfigurowany, certbot musi uwzględnić storage.<domain> w żądaniu certyfikatu.
  • Certyfikatów samopodpisanych używaj tylko wtedy, gdy użytkownik wyraźnie o to poprosi, i przekaż --self-signed-certs (generuje certyfikaty samopodpisane w Go).
  • Podaj użytkownikowi instrukcję konfiguracji DNS i poczekaj na potwierdzenie:
  • „Utwórz rekordy A/AAAA, tak żeby <domain> wskazywała na IP dropleta.”
  • „Jeśli używasz storage.<domain>, utwórz rekord A/AAAA także dla niej.”
  • „Gdy DNS się rozpropaguje, daj mi znać, a ja będę kontynuować. Nie widzę propagacji, chyba że poprosisz mnie o sprawdzenie rozwiązywania nazwy.”
  • Agent może sam sprawdzić propagację DNS poleceniem ping -c 1 <domain> i porównać IP z adresem dropleta. Jeśli się zgadza, kontynuuj.

7b. DNS poczty (SPF / DMARC / DKIM).

  • Poczta z domeny bez SPF i DMARC jest często odrzucana przez Gmaila i Outlooka, gdy trafia do odbiorców po raz pierwszy, nawet jeśli dostawca SMTP raportuje ją jako dostarczoną.
  • deployment create wypisuje Warning:, gdy domena z --smtp-from nie ma rekordu SPF albo nie ma rekordu DMARC w _dmarc.<domain> ani w domenie nadrzędnej. Nie blokuje to wdrożenia. Nigdy nie ignoruj tego ostrzeżenia: pokaż je użytkownikowi i podaj rekordy do dodania:
    • <mail-domain> TXT v=spf1 include:<provider> ~all (dokładny include podaje dostawca SMTP; połącz go z istniejącym rekordem SPF, nigdy nie dodawaj drugiego)
    • _dmarc.<mail-domain> TXT v=DMARC1; p=none; rua=mailto:dmarc@<mail-domain>
    • DKIM: rekordy <selector>._domainkey.<mail-domain>, które dostawca SMTP generuje po zweryfikowaniu domeny
  • Sprawdź poleceniami dig +short TXT <mail-domain> i dig +short TXT _dmarc.<mail-domain>.
  • CLI nie potrafi sprawdzić DKIM (selektor zależy od dostawcy). Zawsze poproś użytkownika o potwierdzenie, że DKIM jest zweryfikowany u dostawcy SMTP, nawet jeśli create nie wypisało ostrzeżenia. W Amazon SES i podobnych usługach SPF jest sprawdzany dla własnej domeny koperty dostawcy, więc tylko DKIM może sprawić, że DMARC przejdzie. W SES: Verified identities, potem <mail-domain>, potem DKIM musi mieć status Successful.
  1. Sprawdź wynik i zdaj raport.
  • Sprawdź docker ps i endpointy sprawdzania stanu usług.
  • Podaj końcowe dane połączenia i kolejne kroki.

Aktualizacja przez SSH

Gdy użytkownik poprosi o „aktualizację serwera”:

  1. Zapytaj o docelowego hosta lub IP oraz o użytkownika i klucz SSH.
  2. Uruchom wlycli deployment update --domain <domain> [--force-restart].
  3. Sprawdź stan kontenerów i Nginx.

Zasoby

  • Fragmenty kodu i przykłady dla API DigitalOcean: references/digitalocean.md.

Sekrety i flagi

Używaj tych nazw flag dla sekretów:

  • Host SMTP: --smtp-host
  • Użytkownik SMTP: --smtp-user
  • Hasło SMTP: --smtp-password
  • Nadawca SMTP: --smtp-from
  • Endpoint OTEL: --otel-endpoint
  • Nagłówki OTEL: --otel-headers

Minimalne polecenie create

Wymagane flagi:

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

Minimalny przykład:

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

Ustawienia domyślne zarządzanego Postgresa (DigitalOcean i CLI)

Gdy używasz zarządzanego Postgresa z DigitalOcean, nie polegaj na domyślnych ustawieniach CLI. Ustaw jawnie wszystkie flagi --postgres-*:

  • Typowe ustawienia domyślne DO:
    • Port: 25060
    • Baza danych: defaultdb
    • Użytkownik: doadmin
  • Ustawienia domyślne CLI (jeśli pominiesz flagi):
    • Port: 5432
    • Baza danych: wlsly
    • Użytkownik: wlsly

Uwagi o użyciu CLI

  • Sprawdzenie wersji: wlycli -v lub wlycli --version (flaga). Nie ma podpolecenia version.
  • Używaj --base-dir tylko wtedy, gdy chcesz mieć inną lokalizację niż domyślna (domyślnie ~/.welley). CLI utworzy katalog, jeśli ma do tego uprawnienia.
  • Nieinteraktywne uruchomienia przez SSH powinny zawierać --email i wszystkie wymagane flagi, żeby uniknąć pytań.
  • Jeśli użytkownik udostępni na serwerze plik binarny CLI (np. ~/wcli), używaj go bezpośrednio. Nie przenoś go, chyba że ktoś o to poprosi.
  • Kopiuj fragmenty dosłownie z references/digitalocean.md dla wszystkich wywołań API DO. Nie przepisuj, nie zmieniaj i nie improwizuj parsowania w Pythonie. Nawet drobne zmiany (np. escapowanie, cudzysłowy) mogą zepsuć działanie w różnych powłokach.
  • Zdalne skrypty SSH: zawsze używaj ssh host 'bash -s' << 'EOF' (heredoc w cudzysłowie). Nigdy nie używaj ssh host "..." w podwójnych cudzysłowach, bo zsh rozwija $(...) i [...] lokalnie, zanim wyśle polecenie na zdalnego hosta.

Naprawa po błędzie

Jeśli deployment create się nie powiedzie i musisz spróbować jeszcze raz:

  • Użyj wlycli deployment delete --domain <domain> --yes-please-delete-all-the-data, żeby wszystko wyczyścić.
  • Delete spróbuje wyczyścić pliki należące do roota za pomocą kontenera. Jeśli to się nie uda, usuń katalog projektu w --base-dir z podwyższonymi uprawnieniami i uruchom polecenie ponownie.

Wstępny test portu 80 (opcjonalnie)

Jeśli certbot się nie powiedzie, przed ponownym uruchomieniem sprawdź, czy port 80 jest osiągalny:

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

Inne dokumenty