Cómo dejar que Claude Code despliegue tu blog Ghost (DNS, VPS y Ghost API)

Una guía paso a paso para permitir que Claude Code configure autónomamente el DNS de Cloudflare, prepare un VPS de Hetzner a través de SSH, despliegue Ghost con Traefik e inicialice el blog mediante la API de administración de Ghost — con notas honestas sobre lo que aún necesita intervención humana.

Cómo dejar que Claude Code despliegue tu blog Ghost (DNS, VPS y Ghost API)
También disponible en English, Deutsch, Français, Nederlands.

Tienes un dominio. Tienes una cuenta en Hetzner. Quieres Ghost funcionando en tu propio servidor con HTTPS, Cloudflare delante y una base de datos MySQL detrás. El camino manual lleva dos horas: crear el servidor, conectar por SSH, configurar Docker Compose, pelear con Let's Encrypt, depurar Traefik, inicializar Ghost a través de un formulario en el navegador.

Hay otro camino. Delega el trabajo a Claude Code. Dale tus credenciales y una descripción de la tarea, y configurará el DNS de Cloudflare, desplegará el stack por SSH e inicializará Ghost a través de la Admin API sin que toques un terminal. Así se configuró clawstack.run.

Este artículo documenta exactamente qué puede hacer Claude por su cuenta, qué sigue requiriendo un clic humano, y cómo estructurar la delegación para que funcione a la primera.


Qué puede y qué no puede hacer Claude Code

Claude Code tiene acceso a tu sistema de archivos, un terminal y cualquier API a la que lo apuntes. Eso cubre la mayor parte de este despliegue. Pero algunas cosas siguen viviendo detrás de interfaces de navegador sin equivalente en API.

Claude gestiona de forma autónoma: - Crear registros A de DNS en Cloudflare vía API - Generar archivos .env y configuraciones de Docker Compose - Conectar por SSH al servidor y ejecutar comandos - Subir archivos de despliegue - Arrancar contenedores Docker - Inicializar Ghost vía la Admin API (crear la cuenta de administrador, primer artículo, título del sitio) - Depurar fallos leyendo logs y aplicando correcciones

Debes hacer manualmente (clics puntuales): - Crear el servidor en Hetzner (sin API key de Hetzner en el alcance — o puedes añadir una y Claude se encarga también) - Establecer el modo SSL/TLS de Cloudflare a Full (Strict) en el panel de control - Obtener la clave de la Admin API de Ghost desde la interfaz de administración de Ghost tras el primer inicio de sesión

Todo lo demás es automatizable. Los dos pasos manuales llevan menos de cinco minutos en total.


Qué necesitas antes de empezar

  • Un dominio con DNS gestionado en Cloudflare
  • Un token de API de Cloudflare con permisos Zone / DNS / Edit, limitado a tu dominio
  • Una cuenta en Hetzner (o cualquier proveedor de VPS — ajusta la IP más abajo)
  • Una contraseña SSH o clave para el servidor
  • Claude Code ejecutándose localmente con acceso al sistema de archivos y a Bash

El método de autenticación SSH no importa. Claude Code usará lo que tengas — archivo de clave o contraseña vía sshpass. Si usas contraseña, instala sshpass primero:

sudo apt install sshpass

Paso 1 — Crear el servidor

Ve a la Hetzner Cloud Console y crea un nuevo servidor: - Tipo: CX22 (2 vCPU, 4 GB RAM) — suficiente para Ghost + MySQL + Traefik - Imagen: Ubuntu 24.04 - Región: la más cercana - Clave SSH o contraseña: a tu elección

En el campo "Cloud config", pega tu cloud-init.yaml. Esto instala Docker, crea el usuario de despliegue, configura UFW y establece fail2ban de una sola vez. Puedes usar el de clawstack-configs en GitHub como punto de partida.

Anota la dirección IP del servidor. Es lo último que necesitas hacer manualmente.


Paso 2 — Dar contexto a Claude Code

Crea un archivo CLAUDE.md en el directorio de tu proyecto. Es el briefing que Claude lee al inicio de cada sesión. Incluye:

# Deployment Context

## Server
- IP: 203.0.113.42
- SSH user: deploy
- SSH auth: password via sshpass / key at ~/.ssh/mykey

## Domain
- Domain: yourdomain.com
- DNS: Cloudflare (token in .env as CLOUDFLARE_TOKEN)

## Stack
- Ghost 5 + MySQL 8 + Traefik (Docker Compose)
- Compose file: deploy/docker-compose.yml
- Deploy directory on server: /opt/ghost

## Credentials
- All secrets in deploy/.env (never commit)

Luego crea deploy/.env con tus valores reales:

DOMAIN=yourdomain.com
ACME_EMAIL=you@yourdomain.com
CLOUDFLARE_TOKEN=your_cloudflare_dns_token

DB_NAME=ghost
DB_USER=ghost
DB_PASSWORD=generate_with_openssl_rand_base64_32
DB_ROOT_PASSWORD=generate_with_openssl_rand_base64_32

MAIL_HOST=smtp.fastmail.com
MAIL_PORT=587
MAIL_USER=you@fastmail.com
MAIL_PASS=your_app_password
MAIL_FROM=noreply@yourdomain.com

Genera las contraseñas de la base de datos localmente:

openssl rand -base64 32

Paso 3 — Configurar DNS

Dale a Claude Code este prompt:

Using the Cloudflare API token in deploy/.env, create the following DNS records
for the domain in .env:
- A record: @ → the server IP in CLAUDE.md
- A record: www → the server IP in CLAUDE.md
- A record: * → the server IP in CLAUDE.md

Use the Cloudflare API at https://api.cloudflare.com/client/v4.
First get the zone ID for the domain, then create each record.
Check for existing records and skip or update as needed.

Claude llamará a la API de Cloudflare, obtendrá el zone ID, creará los registros y confirmará cada uno. Todo el proceso tarda unos treinta segundos.

Si tienes registros de correo (MX, DKIM, SPF) de un proveedor como FastMail, indícaselos también a Claude. Puede crearlos en la misma pasada.

Tras la propagación del DNS (normalmente menos de cinco minutos con Cloudflare), configura el modo SSL/TLS manualmente:

Panel de Cloudflare → yourdomain.com → SSL/TLS → Overview → Full (Strict)

Este es el único clic que no se puede automatizar con un token DNS con alcance limitado.


Paso 4 — Desplegar el stack

Una vez que el DNS está activo y el servidor en marcha, dale a Claude el prompt de despliegue:

Deploy the Ghost stack to the server documented in CLAUDE.md.

1. Upload deploy/docker-compose.yml and deploy/.env to /opt/ghost on the server
2. SSH in and create the traefik/ directory with an empty acme.json (chmod 600)
3. Run: docker compose up -d
4. Wait 30 seconds, then check: docker compose ps
5. Check Ghost logs for any startup errors: docker compose logs --tail=50 ghost
6. If everything looks healthy, report the container statuses

Claude se conectará por SSH, subirá los archivos, arrancará los contenedores y leerá los logs. Si algo falla — y el primer despliegue suele tener algún detalle — Claude lo diagnosticará y aplicará la corrección. Los cinco fallos más comunes están documentados en Ghost detrás de Cloudflare y Traefik: La configuración completa funcional.

Los más probables: falta el sufijo @docker en las referencias de middleware de Traefik, nombre incorrecto de la variable del token de Cloudflare, o el prefijo del nombre de la red de Docker no coincide con el nombre del directorio del proyecto Compose.


Paso 5 — Inicializar Ghost vía la Admin API

Ghost incluye un endpoint de configuración inicial de un solo uso. Hasta que lo llames, el blog está en estado "sin inicializar" — no existe cuenta de administrador. Puedes hacerlo a través del navegador en /ghost, o dejar que Claude lo haga vía API.

Dale a Claude este prompt:

Initialise Ghost at https://yourdomain.com using the Admin API setup endpoint.
Create an admin account with:
- name: Admin
- email: you@yourdomain.com
- password: (generate a strong one and tell me what it is)
- blogTitle: Your Blog Title

POST to: https://yourdomain.com/ghost/api/admin/authentication/setup
Check the response for success and report the result.

Claude llamará al endpoint y devolverá la confirmación. La respuesta incluye un objeto de usuario — la cuenta de administrador está activa.

# What Claude runs under the hood:
curl -s -X POST https://yourdomain.com/ghost/api/admin/authentication/setup \
  -H "Content-Type: application/json" \
  -d '{
    "setup": [{
      "name": "Admin",
      "email": "you@yourdomain.com",
      "password": "YourPassword123!",
      "blogTitle": "Your Blog Title"
    }]
  }'

Si el endpoint devuelve un 403, Ghost ya está inicializado (alguien llegó primero — posiblemente tú probando la URL en un navegador). Si devuelve un error de conexión, los contenedores aún no están levantados.


Paso 6 — Obtener la clave de la Admin API

Inicia sesión en el panel de administración de Ghost en https://yourdomain.com/ghost con las credenciales que Claude acaba de crear.

Ve a: Settings → Integrations → Add custom integration

Ponle cualquier nombre — "Automation" sirve. Ghost te mostrará una clave de Admin API en formato id:hexsecret. Guárdala en deploy/.env como GHOST_ADMIN_KEY.

A partir de este punto, Claude puede crear artículos, subir imágenes, gestionar etiquetas y publicar borradores completamente a través de la API — sin necesidad de navegador.


Verificar la configuración

Una vez que todo está desplegado, pide a Claude que ejecute la lista de verificación:

Run the following checks and report the HTTP status code for each:

1. curl -s https://yourdomain.com/ -o /dev/null -w "%{http_code}"   → should be 200
2. curl -s https://www.yourdomain.com/ -o /dev/null -w "%{http_code}"  → should be 301
3. curl -s http://yourdomain.com/ -o /dev/null -w "%{http_code}"    → should be 301
4. curl -sv https://yourdomain.com/ 2>&1 | grep issuer   → should say Let's Encrypt

Also check:
5. docker compose ps   → all containers should be Up
6. docker compose logs traefik | grep -i error   → should be empty

Si el paso 1 devuelve 000 o se queda colgado, hay un problema de enrutamiento en Traefik. Si devuelve 301, el bucle de redirección de Ghost está activo — consulta el artículo de Traefik para la solución. Si el paso 4 muestra un certificado de Cloudflare en lugar de Let's Encrypt, el challenge DNS-01 aún no se ha completado o la variable CLOUDFLARE_TOKEN tiene un nombre incorrecto.


El prompt completo para un servidor limpio

Si quieres delegar todo el trabajo a Claude de una vez — DNS, despliegue e inicialización de Ghost — aquí está el prompt. Asume que CLAUDE.md está escrito y .env está listo:

Deploy Ghost to the server documented in CLAUDE.md. Do the following in order:

1. Use the Cloudflare API to create A records for @, www, and * pointing to the server IP.
   Check for existing records first; update if present, create if not.

2. Upload deploy/docker-compose.yml and deploy/.env to /opt/ghost on the server.
   Create /opt/ghost/traefik/acme.json with chmod 600.

3. SSH in and run: docker compose up -d
   Wait 45 seconds, then check docker compose ps and docker compose logs ghost.
   Fix any startup errors before continuing.

4. Once all containers are healthy, initialise Ghost via POST to
   /ghost/api/admin/authentication/setup with the credentials below.
   Tell me the password you generate.

5. Confirm the site returns HTTP 200 at https://[DOMAIN]/.
   Report any failures with the relevant log output.

Admin credentials to create:
- email: you@yourdomain.com
- blogTitle: Your Blog Title

Claude trabajará la lista paso a paso, informará del estado tras cada uno y se detendrá a preguntar si algo requiere una decisión. En un servidor limpio con credenciales correctas, todo el despliegue lleva unos cuatro minutos.


Usar una IA para depurar el despliegue

Si algo se rompe durante un despliegue que Claude está ejecutando, el camino más rápido es pegar tanto este artículo como el artículo de bugs de Ghost + Traefik + Cloudflare en la conversación. Juntos cubren todos los modos de fallo que hemos encontrado. Claude cruzará el error en los logs con los patrones documentados y te dirá exactamente qué label está mal o qué variable de entorno falta.


Dónde ejecutar esto

Hetzner CX22 es la máquina donde esto se ejecuta. 4,85 €/mes, dos vCPUs, 4 GB de RAM. El usuario de despliegue no tiene contraseña por defecto — cloud-init la bloquea — así que Claude se autentica por clave o con la contraseña temporal que configuras durante la creación del servidor.

Si el objetivo es un asistente de IA que pueda gestionar el servidor de forma autónoma después de la configuración — reiniciar contenedores, crear artículos, monitorizar logs — xCloud aloja OpenClaw gestionado. Obtienes las mismas operaciones autónomas sin mantener el servidor tú mismo. El despliegue descrito en este artículo es lo que xCloud ejecuta por debajo.

(Enlaces de afiliado — nos llevamos una pequeña comisión si te registras, sin coste adicional para ti.)


Recursos


Versión en alemán (Deutsch)


Metadaten

  • Titel: Ghost mit Claude Code deployen: DNS, VPS und Ghost API automatisiert
  • Slug: claude-code-ghost-deployment-de
  • Beschreibung: Schritt-für-Schritt-Anleitung, um Claude Code Cloudflare DNS konfigurieren, einen Hetzner VPS per SSH einrichten, Ghost mit Traefik deployen und den Blog über die Ghost Admin API initialisieren zu lassen — mit ehrlichen Hinweisen, was noch ein Mensch tun muss.
  • Tags: claude-code, ghost, cloudflare, hetzner, docker, automation, selbst-gehostet, infra
  • Pillar: /openclaw/
  • Language: de
  • Reading Time: 10 min

Inhalt

Du hast eine Domain. Du hast einen Hetzner-Account. Du willst Ghost auf deinem eigenen Server mit HTTPS, Cloudflare davor und einer MySQL-Datenbank dahinter. Der manuelle Weg dauert zwei Stunden: Server erstellen, per SSH einloggen, Docker Compose konfigurieren, mit Let's Encrypt kämpfen, Traefik debuggen, Ghost durch ein Browser-Formular initialisieren.

Es gibt einen anderen Weg. Übergib den Job an Claude Code. Gib ihm deine Zugangsdaten und eine Aufgabenbeschreibung — es konfiguriert Cloudflare DNS, deployt den Stack per SSH und initialisiert Ghost über die Admin API, ohne dass du ein Terminal anfassen musst. So wurde clawstack.run aufgesetzt.

Dieser Post dokumentiert genau, was Claude eigenständig tun kann, was noch einen menschlichen Klick erfordert, und wie du die Übergabe strukturierst, damit es beim ersten Versuch funktioniert.


Was Claude Code kann und was nicht

Claude Code hat Zugriff auf dein Dateisystem, ein Terminal und jede API, auf die du es hinweist. Das deckt den Großteil dieses Deployments ab. Einige Dinge befinden sich aber noch hinter Browser-UIs ohne API-Äquivalent.

Claude erledigt selbstständig: - Cloudflare DNS A-Records per API anlegen - .env-Dateien und Docker Compose Configs erstellen - Per SSH auf den Server zugreifen und Befehle ausführen - Deployment-Dateien hochladen - Docker Container starten - Ghost per Admin API initialisieren (Admin-Account, erster Post, Seitentitel) - Fehler durch Log-Analyse diagnostizieren und beheben

Manuelle Schritte (einmalige Klicks): - Hetzner Server erstellen (oder Hetzner API Key bereitstellen, dann kann Claude das auch) - Cloudflare SSL/TLS-Modus auf Full (Strict) setzen im Dashboard - Ghost Admin API Key aus dem Ghost Admin UI auslesen nach dem ersten Login

Alles andere ist automatisierbar. Die zwei manuellen Schritte dauern zusammen unter fünf Minuten.


Voraussetzungen

  • Eine Domain mit DNS bei Cloudflare
  • Ein Cloudflare API Token mit Zone / DNS / Edit-Berechtigung, auf deine Domain beschränkt
  • Ein Hetzner-Account (oder anderer VPS-Anbieter — IP unten anpassen)
  • SSH-Passwort oder Key für den Server
  • Claude Code lokal mit Dateisystem- und Bash-Zugriff

Die SSH-Authentifizierungsmethode spielt keine Rolle. Claude Code verwendet was du hast — Key-Datei oder Passwort via sshpass. Bei Passwort-Authentifizierung zuerst installieren:

sudo apt install sshpass

Schritt 1 — Server erstellen

In der Hetzner Cloud Console einen neuen Server anlegen: - Typ: CX22 (2 vCPU, 4 GB RAM) — reicht für Ghost + MySQL + Traefik - Image: Ubuntu 24.04 - Region: nächstgelegene - SSH Key oder Passwort: nach Wahl

Im Feld "Cloud config" das cloud-init.yaml einfügen. Das installiert Docker, legt den Deploy-User an, konfiguriert UFW und richtet fail2ban ein. Als Ausgangspunkt eignet sich die Datei aus clawstack-configs auf GitHub.

Die IP-Adresse des Servers notieren. Das ist die letzte manuelle Aktion.


Schritt 2 — Claude Code den Kontext geben

Eine CLAUDE.md-Datei im Projektverzeichnis anlegen. Das ist das Briefing, das Claude zu Beginn jeder Session liest:

# Deployment Context

## Server
- IP: 203.0.113.42
- SSH-User: deploy
- SSH-Auth: Passwort via sshpass / Key unter ~/.ssh/mykey

## Domain
- Domain: yourdomain.com
- DNS: Cloudflare (Token in .env als CLOUDFLARE_TOKEN)

## Stack
- Ghost 5 + MySQL 8 + Traefik (Docker Compose)
- Compose-Datei: deploy/docker-compose.yml
- Deploy-Verzeichnis auf Server: /opt/ghost

## Zugangsdaten
- Alle Secrets in deploy/.env (nie committen)

Dann deploy/.env mit den echten Werten anlegen:

DOMAIN=yourdomain.com
ACME_EMAIL=du@yourdomain.com
CLOUDFLARE_TOKEN=dein_cloudflare_dns_token

DB_NAME=ghost
DB_USER=ghost
DB_PASSWORD=mit_openssl_rand_base64_32_generieren
DB_ROOT_PASSWORD=mit_openssl_rand_base64_32_generieren

MAIL_HOST=smtp.fastmail.com
MAIL_PORT=587
MAIL_USER=du@fastmail.com
MAIL_PASS=dein_app_passwort
MAIL_FROM=noreply@yourdomain.com

DB-Passwörter lokal generieren:

openssl rand -base64 32

Schritt 3 — DNS konfigurieren

Claude Code diesen Prompt geben:

Lege mit dem Cloudflare API Token aus deploy/.env folgende DNS-Records
für die Domain in .env an:
- A-Record: @ → Server-IP aus CLAUDE.md
- A-Record: www → Server-IP aus CLAUDE.md
- A-Record: * → Server-IP aus CLAUDE.md

Cloudflare API: https://api.cloudflare.com/client/v4
Zuerst die Zone-ID für die Domain abrufen, dann jeden Record anlegen.
Vorhandene Records prüfen und ggf. aktualisieren statt doppelt anlegen.

Claude ruft die Cloudflare API auf, ermittelt die Zone-ID, legt die Records an und bestätigt jeden einzelnen. Das dauert etwa dreißig Sekunden.

Nach DNS-Propagation (mit Cloudflare meist unter fünf Minuten) den SSL-Modus manuell setzen:

Cloudflare Dashboard → yourdomain.com → SSL/TLS → Übersicht → Full (Strict)

Das ist der eine Klick, der mit einem beschränkten DNS-Token nicht automatisierbar ist.


Schritt 4 — Stack deployen

Wenn DNS aktiv und der Server bereit ist:

Deploye den Ghost-Stack auf den in CLAUDE.md dokumentierten Server.

1. deploy/docker-compose.yml und deploy/.env nach /opt/ghost hochladen
2. Per SSH einloggen und /opt/ghost/traefik/acme.json anlegen (chmod 600)
3. docker compose up -d ausführen
4. 30 Sekunden warten, dann docker compose ps prüfen
5. Ghost-Logs auf Startfehler prüfen: docker compose logs --tail=50 ghost
6. Bei gesundem Status alle Container-Zustände melden

Claude loggt per SSH ein, lädt die Dateien hoch, startet die Container und liest die Logs. Wenn etwas schiefläuft — beim ersten Deploy oft eine Kleinigkeit — diagnostiziert Claude es und behebt es. Die fünf häufigsten Fehler sind in Ghost hinter Cloudflare und Traefik dokumentiert.


Schritt 5 — Ghost per Admin API initialisieren

Ghost hat einen einmaligen Setup-Endpoint. Bis er aufgerufen wird, existiert kein Admin-Account. Das geht über den Browser unter /ghost oder per API:

Initialisiere Ghost unter https://yourdomain.com über den Admin API Setup-Endpoint.
Admin-Account erstellen:
- name: Admin
- email: du@yourdomain.com
- password: (generiere ein starkes Passwort und teile es mir mit)
- blogTitle: Dein Blog-Titel

POST an: https://yourdomain.com/ghost/api/admin/authentication/setup
Antwort auf Erfolg prüfen und melden.
# Was Claude im Hintergrund ausführt:
curl -s -X POST https://yourdomain.com/ghost/api/admin/authentication/setup \
  -H "Content-Type: application/json" \
  -d '{
    "setup": [{
      "name": "Admin",
      "email": "du@yourdomain.com",
      "password": "DeinPasswort123!",
      "blogTitle": "Dein Blog-Titel"
    }]
  }'

Si devuelve 403: Ghost ya está inicializado. Si devuelve error de conexión: los contenedores aún no están en marcha.


Schritt 6 — Admin API Key auslesen

Im Ghost Admin unter https://yourdomain.com/ghost einloggen.

Einstellungen → Integrationen → Eigene Integration hinzufügen

Den Admin API Key im Format id:hexsecret in deploy/.env als GHOST_ADMIN_KEY speichern.

Ab jetzt kann Claude Beiträge erstellen, Bilder hochladen, Tags verwalten und Entwürfe veröffentlichen — ohne Browser.


Setup verifizieren

Folgende Checks ausführen und HTTP-Statuscodes melden:

1. curl -s https://yourdomain.com/ -o /dev/null -w "%{http_code}"        → 200 erwartet
2. curl -s https://www.yourdomain.com/ -o /dev/null -w "%{http_code}"    → 301 erwartet
3. curl -s http://yourdomain.com/ -o /dev/null -w "%{http_code}"         → 301 erwartet
4. curl -sv https://yourdomain.com/ 2>&1 | grep issuer                   → Let's Encrypt erwartet

Außerdem:
5. docker compose ps   → alle Container Up
6. docker compose