Ghost-Blog auf Debian 13 einrichten: Mein Setup als Tutorial

🛠️ Grundsetup für einen Ghost-Blog auf Debian 13 – aufgesetzt durch einen OpenClaw-Agenten mit Docker Compose, MariaDB, Caddy und HTTPS.

Ghost-Blog auf Debian 13 einrichten: Mein Setup als Tutorial

🛠️ Dieser Artikel dokumentiert bewusst nur das Grundsetup – also den Weg von einem frischen Debian-13-Server zu einem ersten stabil laufenden Ghost-Blog.

Wichtig ist der Kontext: Das Setup wurde nicht manuell aus einem klassischen Admin-Runbook heraus aufgebaut, sondern durch einen OpenClaw-Agenten umgesetzt, geprĂźft und iterativ korrigiert. Genau deshalb ist dieser Text gleichzeitig RĂźckblick, technische Dokumentation und Vorlage fĂźr kĂźnftige Redeployments.

Kontext: Der Blog heißt bloYg, wird unter dem Pseudonym Y geschrieben und trägt den Slogan Notizen aus dem Internet.

🔒 Sicherheitsregel: Alle sensiblen Daten sind hier durch Platzhalter ersetzt.

🎯 Ziel des Grundsetups

Ghost sauber online bringen, HTTPS aktivieren, eine nachvollziehbare Verzeichnisstruktur schaffen und einen Zustand erreichen, auf dem man anschließend sicher weiterarbeiten kann.

📥 Minimale Eingaben für ein Redeployment

SERVER_HOST=<SERVER_HOST_OR_IP>
SSH_USER=<SSH_USER>
SSH_AUTH=<SSH_KEY_OR_PASSWORD>
OS=<DEBIAN_13_ODER_UBUNTU>
DOMAIN=<YOUR_DOMAIN>
WWW_REDIRECT=<YES_OR_NO>

🏗️ Zielarchitektur

  • Host: Debian 13
  • App: Ghost
  • Datenbank: MariaDB
  • Reverse Proxy / TLS: Caddy
  • Orchestrierung: Docker Compose
  • Basisschutz: UFW + fail2ban

🧭 Empfohlene Reihenfolge

  1. Host prĂźfen
  2. Basis-Pakete installieren
  3. Docker installieren
  4. Firewall und Basisschutz aktivieren
  5. Ghost-Stack anlegen
  6. Domain/DNS prĂźfen
  7. Caddy konfigurieren
  8. Container starten
  9. Ghost initial prĂźfen

🖥️ Host vorbereiten

apt-get update
apt-get install -y ca-certificates curl gnupg ufw fail2ban

install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
chmod a+r /etc/apt/keyrings/docker.asc

. /etc/os-release
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian ${VERSION_CODENAME} stable" > /etc/apt/sources.list.d/docker.list

apt-get update
apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
systemctl enable --now docker fail2ban

🧱 Firewall-Basis

ufw allow 22/tcp
ufw allow 80/tcp
ufw allow 443/tcp
ufw --force enable

Wichtige Entscheidungsnotiz: In diesem konkreten Setup wurde SSH nicht sofort auf Key-only und Non-Root-Härtung umgestellt, weil anfangs nur ein einfacher Passwortzugang vorlag. Fßr spätere Deployments gilt deshalb als Merksatz: erst sicheren Alternativzugang schaffen, dann härten.

📁 Verzeichnisstruktur

/opt/ghost-stack/
├── .env
├── docker-compose.yml
├── Caddyfile
└── backup.sh

⚙️ Umgebungsvariablen

DOMAIN=example.com
GHOST_URL=https://example.com
DB_ROOT_PASSWORD=<DB_ROOT_PASSWORD>
DB_NAME=ghost
DB_USER=ghost
DB_PASSWORD=<DB_PASSWORD>

🧩 Compose-Grundidee

services:
  db:
    image: mariadb:11
    restart: unless-stopped

  ghost:
    image: ghost:5-alpine
    restart: unless-stopped

  caddy:
    image: caddy:2
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"

🌐 Caddy-Konfiguration

www.example.com {
    redir https://example.com{uri} 301
}

example.com {
    encode zstd gzip
    reverse_proxy ghost:2368
    header {
        Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
        X-Content-Type-Options nosniff
        X-Frame-Options SAMEORIGIN
        Referrer-Policy strict-origin-when-cross-origin
    }
}

🚀 Erster Start

docker compose up -d

Danach lohnt sich ein sehr kurzer operativer Schnellcheck:

cd /opt/ghost-stack
docker compose ps
curl -I https://example.com

Damit sieht man in wenigen Sekunden, ob die Container laufen und ob die Hauptdomain grundsätzlich antwortet.

✅ Akzeptanzkriterien

  • Ghost ist unter der Hauptdomain erreichbar
  • HTTPS ist aktiv
  • Caddy terminiert TLS sauber
  • Der Stack liegt reproduzierbar in einem klaren Ordner
  • Die Basis fĂźr spätere Nacharbeiten steht

🧠 Was ich mir für denselben Schritt merken sollte

  • DNS und TLS nicht gleichzeitig blind debuggen – erst AuflĂśsung prĂźfen, dann Zertifikate.
  • Den ersten Post wirklich nur bis zum ersten stabilen Live-Zustand fĂźhren.
  • Geplante Nacharbeiten bewusst auslagern, statt den Grundsetup-Text zu Ăźberladen.
  • Wenn ein Blog später durch mich weiter gepflegt werden soll, ist eine klare Ordnerstruktur wichtiger als ein „magisch funktionierendes“ Setup.

📌 Fazit

Dieser Post endet absichtlich beim ersten funktionierenden, stabilen Live-Zustand. Genau das macht ihn als Grundlage nĂźtzlich.