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.
Server bereitstellen
Überblick
Dieser Skill richtet einen Welley-Stack mit einer einzelnen Instanz auf DigitalOcean ein und kann Updates über SSH ausführen. Er führt den Agenten dazu, fehlende Angaben einzuholen, die verfügbaren Instanzgrößen aus einer festgelegten Quelle abzurufen, die VM zu erstellen, den Host zu konfigurieren, mit wlycli deployment create bereitzustellen und das Ergebnis zu prüfen.
Die Befehlsnamen müssen mit der CLI übereinstimmen:
wlycli deployment createwlycli deployment updatewlycli deployment delete
Standardwerte (DigitalOcean)
- Region:
nyc3 - Image:
latest LTS available via API(überimages?type=distributionermitteln) - Droplet-Name: zufällig erzeugt als
wlsly-<adjective>-<surname>(z. B.wlsly-bright-hopper). Verwende dafür das Snippet zur Namensgenerierung ausreferences/digitalocean.md. Verwende denselben Namen für die verwaltete Datenbank, falls du eine erstellst. - Zieltarif: Basic / Regular (Shared CPU)
- Zielgröße: 2 vCPU / 4 GB RAM / 80 GB SSD / 4 TB Transfer (ca. 24 $/Monat)
Regel für abweichende Angaben
Wenn der Nutzer einen der Standardwerte ändert (Region, Image, Droplet-Name, Projekt, Größe), muss der Agent:
- die abweichende Angabe wörtlich zurückgeben.
- um Bestätigung bitten, bevor er weitermacht.
Vorlage für interaktive Eingaben
Frage nur nach dem, was fehlt. Verwende genau diese Formulierungen, damit nichts missverständlich bleibt. Frage in mehreren Runden. Runde 1: höchstens 2 Fragen pro Durchgang. In Runde 2 kann eine gebündelte Option „alle Standardwerte übernehmen“ angeboten werden. Wenn die Laufzeitumgebung Auswahlmöglichkeiten unterstützt, biete pro Frage 2 bis 3 Optionen an (A/B/C). Verzichte auf freie Eingaben, wenn es nicht nötig ist.
Fragen in Runde 1 (Identität und Zugriff):
- „Hast du ein DigitalOcean-API-Token, das ich verwenden kann, oder soll ich warten, bis du eins bereitstellst?“
- „Welche Domain soll dieser Server verwenden (z. B.
super-puper.example.com)? Hast du Zugriff auf ihr DNS?“ - „Hast du schon einen öffentlichen SSH-Schlüssel, den ich verwenden kann, oder soll ich einen erstellen und hochladen?“
- „Möchtest du dieses Droplet einem bestehenden DigitalOcean-Projekt zuordnen? Wenn ja, nenne den Projektnamen oder die ID.“
- „DNS-Voraussetzung: Du musst A/AAAA-Einträge für
<domain>undstorage.<domain>anlegen (wenn kein CDN genutzt wird). Kannst du das erledigen, bevor certbot läuft?“ - „E-Mail-DNS-Voraussetzung: Die Domain aus
--smtp-frombraucht SPF-, DMARC- und DKIM-Einträge, sonst können Einladungs- und Bestätigungs-E-Mails an neue Empfänger unbemerkt verworfen werden. Sind sie vorhanden, oder soll ich die Einträge auflisten, die dein SMTP-Anbieter braucht?“ - Wenn der Nutzer fragt, wo er ein DO-Token bekommt, gib diesen Link an:
https://cloud.digitalocean.com/account/api/tokens
Fragen in Runde 2 (Größe, Standort und Optionen für die Bereitstellung):
- „Möchtest du die Standardregion
nyc3oder eine andere Region?“ - „Möchtest du die Standardgröße (2 vCPU / 2 GB) oder ein anderes Ziel für CPU und RAM?“
- „Soll ich die neueste Ubuntu-LTS-Version aus der API verwenden oder eine bestimmte Ubuntu-Version?“
- „Welchen SSH-Nutzer sollen wir nach dem Bootstrap verwenden (Standard:
wlsly)? Du kannst den Standard behalten.“ - „Möchtest du eine verwaltete Postgres-Datenbank oder den mitgelieferten Postgres-Container?“
- Wenn verwaltetes Postgres gewählt wird: „Welche Region und Größe soll ich für die Datenbank verwenden? Ich kann
nyc3und 1 vCPU / 2 GB als Standard nehmen.“ - Wenn verwaltetes Postgres gewählt wird: „Soll ich die Datenbank zum angezeigten Monatspreis des Anbieters erstellen?“
- „Gib bitte die erforderlichen SMTP-Einstellungen an (Host, Nutzer, Passwort, Absender). OTEL ist optional, gib es nur an, wenn du es brauchst.“
- „Zum Erstellen ist eine Admin-E-Mail-Adresse nötig. Gib sie jetzt an (Flag:
--email/-e). Wenn du sie nicht angibst, frage ich zweimal nach, um sie zu bestätigen.“
Biete in Runde 2 die Option „alle Standardwerte übernehmen“ an, damit die Eingaben schneller zusammenkommen.
Wenn eine Antwort fehlt, stelle eine gezielte Nachfrage (eine oder zwei Fragen).
Ablauf (DigitalOcean, einzelne Instanz)
- Erforderliche Angaben sammeln (nachfragen, wenn sie fehlen).
- DigitalOcean-API-Token
- Projektname oder ID (optional; wenn sie fehlen oder das Projekt nicht gefunden wird, das Standardprojekt verwenden)
- Region
- Zielgröße der Instanz (z. B. 4 vCPU / 16 GB RAM)
- Domainname
- Öffentlicher SSH-Schlüssel (oder die Bestätigung, dass einer erstellt und registriert werden soll)
- Admin-E-Mail-Adresse für die erste Anmeldung und die Passwortwiederherstellung (zum Erstellen erforderlich;
--email/-e). Wenn sie fehlt, zweimal abfragen und prüfen, ob beide Eingaben übereinstimmen. - Optional: eigene TLS-Zertifikate oder certbot
- Bestätigung des DNS-Zugriffs (A/AAAA-Einträge für
<domain>und gegebenenfallsstorage.<domain>müssen angelegt werden können)
- Instanztypen abrufen und eine Größe wählen.
- Verwende das Snippet für Größen aus
references/digitalocean.md, um nach CPU und RAM aufzulisten und zu filtern. - Bei mehreren Treffern beim Nutzer nachfragen.
2b. Den Ubuntu-Image-Slug ermitteln.
- Rufe
GET /v2/images?type=distribution&per_page=200auf und filtere nach Ubuntu. - Wenn der Nutzer eine bestimmte Version wollte, prüfe, ob es den Slug gibt, und lass dir das bestätigen.
- Wähle andernfalls den neuesten LTS-Slug aus der Liste und lass ihn vor dem Erstellen vom Nutzer bestätigen.
- Das Droplet erstellen.
- Verwende direkt die DigitalOcean-API (doctl ist optional).
- Image: bevorzugt die Angabe des Nutzers, sonst die neueste LTS-Version aus der API-Liste.
- Hänge den Fingerabdruck des SSH-Schlüssels an oder erstelle einen Schlüssel und lade ihn hoch.
- Aktiviere das Monitoring.
- Wenn ein Projektname oder eine ID angegeben, aber nicht gefunden wurde, erstelle das Droplet ohne Projekt (Standardprojekt).
- Hinweis: Die verwaltete Datenbank kann parallel zum Droplet erstellt werden.
Hinweise zur Parallelisierung
Der Agent sollte unabhängige Aufgaben überlappen lassen, um die Gesamtlaufzeit zu verkürzen:
- Während du Angaben vom Nutzer einholst (Runde 2), starte die Erstellung des Droplets, wenn Token, Region, Größe, Image und SSH-Schlüssel schon bestätigt sind.
- Starte die Erstellung der verwalteten Postgres-Datenbank (falls gewünscht), während das Droplet eingerichtet wird.
- Sammle die restlichen Angaben (SMTP, OTEL, Admin-E-Mail) weiter, während das Droplet startet.
- Wenn für einen Schritt eine wichtige Angabe fehlt, pausiere diesen Schritt und mach mit anderen Aufgaben weiter, die sich parallel erledigen lassen.
- Wenn das DNS bei DigitalOcean verwaltet wird, erstelle oder aktualisiere die A/AAAA-Einträge, sobald die IP des Droplets vorliegt (warte nicht auf den vollständigen Bereitstellungsschritt).
- DNS und Domain.
- Frage, ob das DNS bei DigitalOcean erstellt oder aktualisiert werden soll oder ob das externe DNS so bleiben soll.
- Wenn du das DigitalOcean-DNS verwendest, lege A/AAAA-Einträge auf die IP des Droplets an.
- Den Host per SSH einrichten.
- Lege einen Nutzer ohne Root-Rechte an (z. B.
wlsly), gib ihm sudo-Rechte und kopiere die autorisierten SSH-Schlüssel. - Melde dich als root ab und danach als der Nutzer ohne Root-Rechte wieder an, bevor du weitermachst.
- Installiere Docker und docker compose.
- Lade die Welley-CLI-Binärdatei aus dem AppStore herunter und mach sie ausführbar:
- Basis-URL:
https://appstore.allroads.social/v1/social.wellesley.wlycli/latest?develop=stable&platform=<os>/<arch> - Wähle den passenden Wert für
platformje nach Betriebssystem und Architektur:- 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:
- Beispiel (Linux x86_64):
curl -fL 'https://appstore.allroads.social/v1/social.wellesley.wlycli/latest?develop=stable&platform=linux/amd64' -o wlycli chmod +x wlycli - Zu den erwarteten Headern in der Antwort gehören:
x-artifact-display-name: Welley CLIx-artifact-full-name: social.wellesley.wlyclix-artifact-kind: clix-artifact-platform: <os>/<arch>zum Beispiellinux/amd64x-artifact-sha256: <sha256>x-artifact-version: <version>x-channel: develop
- Prüfe vor der Installation am besten die Header mit einer HEAD-Anfrage und kontrolliere, dass Artefaktname, Art, Plattform und Kanal zur angeforderten Binärdatei passen.
- Basis-URL:
- Prüfe die CLI-Binärdatei: Führe
wlycli -vundwlycli deployment --helpaus, um die erwarteten Build-Informationen zu bestätigen.
- Welley bereitstellen.
- Führe
wlycli deployment createmit den erforderlichen Optionen aus. - Verwende die Standardwerte für eine einzelne Instanz (kein externes Postgres, außer der Nutzer wünscht es).
- Wenn verwaltetes Postgres gewünscht ist, erstelle es zuerst (DigitalOcean-Datenbank) und verwende dann Host, Port, Datenbank, Nutzer und Passwort aus der Antwort in den
--postgres-*-Flags. - Wenn das Passwort des Datenbanknutzers von der API oder der Oberfläche nicht zurückgegeben wird, setze die Zugangsdaten des Datenbanknutzers zurück, um neue zu erhalten, bevor du
wlycliausführst. - Nicht interaktive Läufe müssen
--email/-eübergeben, sonst schlägt der Befehl fehl. --base-dirzeigt auf das übergeordnete Verzeichnis, die CLI legt das Projektverzeichnis darin automatisch an.- Die CLI bricht ab, wenn das Projektverzeichnis oder die Container schon existieren. Vor einem neuen Versuch muss aufgeräumt werden.
- Zertifikate (zwingend).
- Standard: Certbot im Standalone-Modus verwenden (nicht interaktiv).
- Der Nutzer muss die A/AAAA-Einträge der Domain (und von
storage.<domain>, falls verwendet) auf die IP des Droplets zeigen lassen, bevor certbot läuft. - Die CLI unterstützt
--public-ip(überschreibt die erkannte IP) und--skip-dns-preflight, falls du die Prüfung umgehen musst. - Gehe nie davon aus, dass das DNS eingerichtet ist. Frage nach und warte auf eine ausdrückliche Bestätigung.
- Verwende
--skip-dns-preflightnur, wenn der Nutzer es ausdrücklich verlangt. - Wenn kein CDN eingerichtet ist, muss certbot
storage.<domain>in die Zertifikatsanfrage aufnehmen. - Verwende selbstsignierte Zertifikate nur, wenn der Nutzer es ausdrücklich verlangt, und übergib
--self-signed-certs(erzeugt selbstsignierte Zertifikate in Go). - Gib dem Nutzer Anweisungen zur DNS-Einrichtung und warte auf seine Bestätigung:
- „Lege A/AAAA-Einträge an, damit
<domain>auf die IP des Droplets zeigt.“ - „Wenn du
storage.<domain>verwendest, lege auch dafür einen A/AAAA-Eintrag an.“ - „Sobald sich das DNS verbreitet hat, sag mir Bescheid, dann mache ich weiter. Ich kann die Verbreitung nicht selbst sehen, es sei denn, du bittest mich, die Auflösung zu prüfen.“
- Der Agent kann die DNS-Verbreitung selbst mit
ping -c 1 <domain>prüfen und die IP mit der des Droplets vergleichen. Wenn sie übereinstimmt, kann er fortfahren.
7b. E-Mail-DNS (SPF / DMARC / DKIM).
- E-Mails von einer Domain ohne SPF und DMARC werden von Gmail und Outlook bei Erstempfängern oft verworfen, auch wenn der SMTP-Anbieter sie als zugestellt meldet.
deployment creategibt eineWarning:aus, wenn die Domain aus--smtp-fromkeinen SPF-Eintrag hat oder keinen DMARC-Eintrag bei_dmarc.<domain>oder einer übergeordneten Domain. Die Bereitstellung wird dadurch nicht blockiert. Ignoriere die Warnung nie: Zeige sie dem Nutzer und nenne ihm die Einträge, die er hinzufügen muss:<mail-domain>TXTv=spf1 include:<provider> ~all(das genaue include kommt vom SMTP-Anbieter; in einen vorhandenen SPF-Eintrag einfügen, nie einen zweiten anlegen)_dmarc.<mail-domain>TXTv=DMARC1; p=none; rua=mailto:dmarc@<mail-domain>- DKIM: die Einträge
<selector>._domainkey.<mail-domain>, die der SMTP-Anbieter erzeugt, wenn die Domain verifiziert wird
- Prüfe mit
dig +short TXT <mail-domain>unddig +short TXT _dmarc.<mail-domain>. - Die CLI kann DKIM nicht prüfen (der Selector ist anbieterspezifisch). Bitte den Nutzer immer, zu bestätigen, dass DKIM beim SMTP-Anbieter verifiziert ist, auch wenn
createkeine Warnung ausgegeben hat. Bei Amazon SES und ähnlichen Anbietern wird SPF für die eigene Envelope-Domain des Anbieters geprüft, deshalb kann nur DKIM DMARC bestehen lassen. In SES muss unter Verified identities, dann<mail-domain>, dann DKIM der Status Successful stehen.
- Prüfen und berichten.
- Prüfe
docker psund die Health-Endpunkte der Dienste. - Gib die abschließenden Verbindungsdaten und die nächsten Schritte an.
Ablauf des SSH-Updates
Wenn der Nutzer „Server aktualisieren“ sagt:
- Frage nach Ziel-Host oder IP und nach SSH-Nutzer und Schlüssel.
- Führe
wlycli deployment update --domain <domain> [--force-restart]aus. - Prüfe den Status der Container und von Nginx.
Ressourcen
- Snippets und Beispiele zur DigitalOcean-API:
references/digitalocean.md.
Zugangsdaten als Flags
Verwende für Zugangsdaten diese Flag-Namen:
- SMTP-Host:
--smtp-host - SMTP-Nutzer:
--smtp-user - SMTP-Passwort:
--smtp-password - SMTP-Absender:
--smtp-from - OTEL-Endpunkt:
--otel-endpoint - OTEL-Header:
--otel-headers
Minimaler Create-Befehl
Erforderliche Flags:
--domain--email--smtp-host--smtp-user--smtp-password--smtp-from
Minimales Beispiel:
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
Standardwerte für verwaltetes Postgres (DigitalOcean und CLI)
Wenn du das verwaltete Postgres von DigitalOcean verwendest, verlass dich nicht auf die Standardwerte der CLI. Setze alle --postgres-*-Flags ausdrücklich:
- Typische DO-Standardwerte:
- Port:
25060 - Datenbank:
defaultdb - Nutzer:
doadmin
- Port:
- Standardwerte der CLI (wenn du die Flags weglässt):
- Port:
5432 - Datenbank:
wlsly - Nutzer:
wlsly
- Port:
Hinweise zur CLI-Nutzung
- Versionsprüfung:
wlycli -voderwlycli --version(Flag). Einen Unterbefehlversiongibt es nicht. - Verwende
--base-dirnur, wenn du einen anderen Speicherort als den Standard willst (Standard ist~/.welley). Die CLI legt das Verzeichnis an, wenn sie die Berechtigung dazu hat. - Nicht interaktive SSH-Läufe sollten
--emailund alle erforderlichen Flags enthalten, damit keine Rückfragen kommen. - Wenn der Nutzer eine CLI-Binärdatei auf dem Server bereitstellt (z. B.
~/wcli), verwende sie direkt. Verschiebe sie nicht, wenn niemand darum bittet. - Kopiere Snippets wörtlich aus
references/digitalocean.mdfür alle DO-API-Aufrufe. Schreibe das Python-Parsing nicht um, passe es nicht an und improvisiere nicht: Schon kleine Änderungen (z. B. beim Escaping oder bei Anführungszeichen) können je nach Shell fehlschlagen. - Remote-Skripte per SSH: Verwende immer
ssh host 'bash -s' << 'EOF'(Heredoc in Anführungszeichen). Verwende niessh host "..."mit doppelten Anführungszeichen, denn zsh wertet$(...)und[...]lokal aus, bevor der Befehl an den entfernten Host gesendet wird.
Wiederherstellung nach Fehlern
Wenn deployment create fehlschlägt und du es erneut versuchen musst:
- Räume mit
wlycli deployment delete --domain <domain> --yes-please-delete-all-the-dataauf. - Delete versucht, Dateien, die root gehören, über Container zu entfernen. Wenn das trotzdem fehlschlägt, entferne das Projektverzeichnis unter
--base-dirmit erhöhten Rechten und führe den Befehl erneut aus.
Vorab-Test für Port 80 (optional)
Wenn certbot fehlschlägt, teste vor einem neuen Versuch, ob Port 80 erreichbar ist:
docker run --rm -d -p 80:80 --name test-http nginx:alpine
curl -s http://<domain>:80
docker rm -f test-http