🚀 Deploypilot Handbuch← zum Dashboard
Handbuch · Stand 29.08.2026

Websites aus Forgejo deployen

Deploypilot bringt statische Websites, Landingpages und Dokus von git push in Sekunden unter eine eigene URL – Production aus main, jeder andere Branch bekommt automatisch eine Preview-Adresse. Diese Anleitung fĂŒhrt vom leeren Verzeichnis bis zum laufenden Projekt.

So funktioniert es

git pushauf Forgejo
→
WebhookForgejo meldet den Push
→
Clone + Erkennungstatisch oder Build?
→
Buildnur bei Bedarf, im Wegwerf-Container
→
ReleaseunverÀnderliches Verzeichnis
→
URLZeiger umgehÀngt

Jedes Deployment ist ein eigenes, unverĂ€nderliches Release. „Live schalten" heißt nur: einen Zeiger umhĂ€ngen. Deshalb sind Rollback und Promote sofort und ohne neuen Build möglich. Zur Laufzeit lĂ€uft kein Node-Prozess fĂŒr deine Site – Node wird höchstens beim Build gebraucht.

Voraussetzungen

Dashboard
vercel.host3.format-c.info – fragt einmalig nach dem Admin-Token
Admin-Token
security find-generic-password -a cc -s vercel-admin-token -w
Forgejo
git.host3.format-c.info, Benutzer cc; PAT im Keychain forgejo-token
Deploy-Benutzer
deploypilot – muss jedes Repo lesen dĂŒrfen (Collaborator, Berechtigung Read)
Domain
Sites laufen unter <projekt>.host3.format-c.info; Zertifikate kommen automatisch beim ersten Aufruf

Neues Projekt anlegen

Beispiel: eine Website meine-site. Der Projektname wird zur Subdomain – erlaubt sind Kleinbuchstaben, Ziffern und einzelne Bindestriche (kein --, max. 40 Zeichen).

  1. Verzeichnis anlegen und Inhalt hineinlegen

    FĂŒr eine rein statische Site reicht eine index.html im Root (oder in public/, docs/, site/). FĂŒr eine Site mit Build-Schritt (Vite, Astro, Eleventy 
) liegt eine package.json mit "build"-Script bereit – Deploypilot erkennt beides selbst.

    mkdir ~/www/meine-site && cd ~/www/meine-site
    cat > index.html <<'EOF'
    <!doctype html><html lang="de"><head><meta charset="utf-8"><title>Meine Site</title></head>
    <body><h1>Hallo</h1></body></html>
    EOF
    printf 'node_modules/\ndist/\n.DS_Store\n.env\n' > .gitignore
    Eigene 404-Seite: eine 404.html im Output wird automatisch fĂŒr unbekannte Pfade ausgeliefert. /about findet about.html auch ohne Endung.
  2. Git-Repo initialisieren

    git init -b main
    git add -A && git commit -m "Erste Version"
  3. Repo in Forgejo anlegen und deploypilot freischalten

    Per Web-OberflÀche (Neues Repository, privat) oder mit zwei API-Aufrufen. Wichtig ist der zweite Schritt: ohne Leserecht kann Deploypilot das Repo nicht klonen.

    PAT=$(security find-generic-password -a cc -s forgejo-token -w)
    B=https://git.host3.format-c.info/api/v1
    
    # Repo anlegen (privat)
    curl -sS -H "Authorization: token $PAT" -H "Content-Type: application/json" \
      -X POST $B/user/repos -d '{"name":"meine-site","private":true}'
    
    # deploypilot darf lesen
    curl -sS -H "Authorization: token $PAT" -H "Content-Type: application/json" \
      -X PUT $B/repos/cc/meine-site/collaborators/deploypilot -d '{"permission":"read"}'

    Wer lieber Claude Code fragt: PUSH legt das Repo an und pusht – den Collaborator danach trotzdem eintragen.

  4. Pushen

    git remote add origin https://cc@git.host3.format-c.info/cc/meine-site.git
    git push -u origin main
  5. Projekt im Dashboard anlegen

    Im Dashboard unter Neues Projekt:

    Name
    meine-site → wird zu meine-site.host3.format-c.info
    Repo
    https://git.host3.format-c.info/cc/meine-site.git
    Production-Branch
    main (oder ein anderer Branch, der live gehen soll)

    Nach dem Anlegen zeigt das Projekt seine Webhook-URL, das Secret und eine Deploy-Hook-URL.

  6. Webhook in Forgejo eintragen

    Im Repo: Einstellungen → Webhooks → Webhook hinzufĂŒgen → Forgejo.

    Ziel-URL
    https://vercel.host3.format-c.info/webhook/meine-site
    Methode / Typ
    POST, application/json
    Geheimnis
    das Secret aus dem Dashboard
    Auslöser
    Benutzerdefinierte Ereignisse: Push und Branch gelöscht (Delete)

    Oder per API, mit dem Secret aus dem Dashboard:

    curl -sS -H "Authorization: token $PAT" -H "Content-Type: application/json" \
      -X POST $B/repos/cc/meine-site/hooks -d '{
        "type":"forgejo","active":true,"events":["push","delete"],
        "config":{"url":"https://vercel.host3.format-c.info/webhook/meine-site",
                  "content_type":"json","secret":"SECRET-AUS-DEM-DASHBOARD"}}'
  7. Ersten Deploy auslösen

    Entweder im Dashboard auf Deploy klicken (baut den Production-Branch) oder einfach einen Commit pushen. Nach wenigen Sekunden steht das Deployment auf ready und die Site ist unter https://meine-site.host3.format-c.info erreichbar. Der allererste Aufruf dauert ein paar Sekunden – da wird das Zertifikat ausgestellt.

    Fertig. Ab jetzt geht jeder Push auf main automatisch live.

TĂ€glich: Preview, Promote, Rollback

Preview-Branch

Jeder Branch außer dem Production-Branch bekommt beim Push seine eigene Adresse. Slashes und Großbuchstaben im Branch-Namen werden zu Bindestrichen.

git checkout -b feature/neuer-header
# 
 Àndern, committen 

git push -u origin feature/neuer-header
# → https://feature-neuer-header--meine-site.host3.format-c.info

Previews senden X-Robots-Tag: noindex und werden nicht von Suchmaschinen erfasst. Wird der Branch gelöscht (git push origin --delete feature/neuer-header), verschwindet die Preview automatisch.

Promote und Rollback

Im Dashboard hat jedes fertige Deployment einen Button:

Beides ist nur ein Zeigerwechsel. Der nÀchste Push auf main setzt Production wieder auf den neuesten Commit.

Deploy Hook

Die Deploy-Hook-URL aus dem Dashboard löst ohne Commit einen neuen Build des Production-Branches aus – praktisch fĂŒr CMS-Systeme oder Cron-Jobs. Ein GET oder POST genĂŒgt; mit ?branch=
 lĂ€sst sich ein anderer Branch bauen.

curl -X POST https://vercel.host3.format-c.info/hook/meine-site/TOKEN

Log ansehen

Jedes Deployment hat einen Log-Button: Clone, Erkennung, Build-Ausgabe, Anzahl der Dateien im Release. Bei error steht die Ursache in der letzten Zeile und in der Tabelle.

URL-Schema

AdresseZeigt aufÄndert sich
meine-site.host3.format-c.infoProduction (Production-Branch)bei jedem Push auf main, Promote, Rollback
feature-x--meine-site.host3.format-c.infoPreview des Branches feature/xbei jedem Push auf den Branch; weg mit dem Branch
meine-site-a1b2c3d-9f3e.host3.format-c.infogenau dieses Deployment (Commit a1b2c3d)nie – bleibt, bis das Release aufgerĂ€umt wird

Deploypilot behÀlt pro Projekt die letzten 10 nicht mehr referenzierten Releases; Àltere werden gelöscht. Was gerade Production oder eine Preview ist, wird nie aufgerÀumt.

Was Deploypilot erkennt

Beim Clone schaut Deploypilot in dieser Reihenfolge ins Repo (bzw. in rootDir):

FundTypWas passiert
DockerfiledockerPhase 2 Deployment endet mit Hinweis – weiter per deploy.sh
server/package.json oder api/hybridPhase 2 statisch + /api-Container, noch nicht verfĂŒgbar
package.json mit "build"-Scriptstatic-buildaktiv Build im Container node:22-alpine; Output aus dist, build, out, _site, .output/public, public
index.html im Root oder in public/, site/, docs/, www/staticaktiv Verzeichnis wird direkt ausgeliefert

Der Paketmanager folgt dem Lockfile: package-lock.json → npm ci, pnpm-lock.yaml → pnpm, yarn.lock → yarn, sonst npm install. Der Build hat keinen Zugriff auf Secrets und lĂ€uft als unprivilegierter Prozess; Zeitlimit 10 Minuten.

Wenn spĂ€ter Logik dazukommt: Formulare und Mailversand laufen ĂŒber die Mail-API (Public Send Token) ganz ohne Backend. Braucht die Site eine echte API, kommt ein server/-Ordner ins gleiche Repo – Phase 2 startet dafĂŒr einen Container nur fĂŒr /api/*, die Site bleibt statisch.

deploypilot.json

Optional im Repo-Root, wenn die Erkennung nicht passt – vergleichbar mit vercel.json. Alle Felder sind optional.

{
  "type": "static",          // static | static-build | hybrid | docker – erzwingt den Typ
  "rootDir": "docs",         // Unterordner, der als Projekt gilt (Monorepo, Doku)
  "buildCommand": "make site", // ersetzt npm install && npm run build
  "outputDir": "out"         // Verzeichnis, das ausgeliefert wird
}

Pfade mĂŒssen relativ und ohne .. sein. Beispiel fĂŒr eine Doku, die neben dem Quellcode liegt: { "rootDir": "docs" } – dann ist nur docs/ die Site, die README im Root bleibt privat.

Betrieb auf ccdev3

Code
~/www/vercel lokal · /data/vercel auf ccdev3 · Repo cc/vercel
Container
vercel-app, Port 127.0.0.1:3158, Netz vercel-net
Daten
/data/vercel/data/ – projects/ (eine JSON je Projekt), releases/, logs/, builds/ (temporĂ€r)
Konfiguration
/data/vercel/.env – nur auf dem Server, nie im Repo
Caddy
/etc/caddy/sites/vercel.caddy (Catch-all https:// mit On-Demand-TLS) + globaler on_demand_tls { ask 
 /tls-ask }
Deploy von Änderungen
./deploy.sh (schnell) · ./deploy.sh full bei Dockerfile-, Paket- oder .env-Änderungen
Logs
ssh ccdev3 docker logs -f vercel-app
Caddy: Niemals einen Wildcard-Block wie *.host3.format-c.info anlegen. Caddy hĂ€lt dann die Einzel-Sites (git, ausleihe, 
) fĂŒr vom Wildcard-Zertifikat abgedeckt und liefert sie nicht mehr aus. Der Catch-all https:// ist die richtige Form; Einzel-Sites haben immer Vorrang.

Zertifikate fĂŒr neue Hosts entstehen beim ersten Aufruf. Caddy fragt dafĂŒr Deploypilot (/tls-ask), ob es zu dem Hostnamen ein Deployment gibt – unbekannte Namen bekommen kein Zertifikat.

Wenn etwas hakt

SymptomUrsache und Abhilfe
Push löst nichts ausIn Forgejo unter Webhooks → Letzte Zustellungen nachsehen. 401: Secret stimmt nicht mit dem Dashboard ĂŒberein. 404: Projektname in der URL falsch. Keine Zustellung: Ereignis Push nicht aktiviert.
Deployment error: „Authentication failed" beim Clonedeploypilot ist im Repo nicht als Collaborator (Read) eingetragen.
„Projekttyp nicht erkannt"Keine index.html und kein Build-Script gefunden. deploypilot.json mit rootDir oder outputDir ergĂ€nzen.
„Kein Build-Output gefunden"Der Build schreibt in ein unbekanntes Verzeichnis – outputDir setzen.
„Typ hybrid/docker 
 Phase 1"Erwartet: solche Projekte laufen weiter ĂŒber ihr eigenes deploy.sh.
Site zeigt „Kein Deployment"Es gibt fĂŒr diesen Hostnamen kein fertiges Release: noch kein erfolgreicher Build, Preview-Branch gelöscht oder Projektname vertippt.
Erster Aufruf hĂ€ngt einige SekundenNormal – das Zertifikat wird gerade ausgestellt. Danach sofort.
Dashboard sagt „ADMIN_TOKEN erforderlich"Token aus dem Keychain eingeben (vercel-admin-token); er wird im Browser gespeichert.
Änderung ist gepusht, aber alte Version liveIm Dashboard prĂŒfen, ob Production auf ein Ă€lteres Deployment zeigt (nach Rollback). NĂ€chster Push oder Promote auf den neuen Build.