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
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 Keychainforgejo-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).
-
Verzeichnis anlegen und Inhalt hineinlegen
FĂŒr eine rein statische Site reicht eine
index.htmlim Root (oder inpublic/,docs/,site/). FĂŒr eine Site mit Build-Schritt (Vite, Astro, Eleventy âŠ) liegt einepackage.jsonmit"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' > .gitignoreEigene 404-Seite: eine404.htmlim Output wird automatisch fĂŒr unbekannte Pfade ausgeliefert./aboutfindetabout.htmlauch ohne Endung. -
Git-Repo initialisieren
git init -b main git add -A && git commit -m "Erste Version" -
Repo in Forgejo anlegen und
deploypilotfreischaltenPer 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:
PUSHlegt das Repo an und pusht â den Collaborator danach trotzdem eintragen. -
Pushen
git remote add origin https://cc@git.host3.format-c.info/cc/meine-site.git git push -u origin main -
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.
-
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"}}' -
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 aufmainautomatisch 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:
- Promote â Prod bei einer Preview: Production zeigt sofort auf diesen Build â ohne Merge, ohne neuen Build.
- Rollback hierhin bei einem Àlteren Production-Build: der vorherige Stand ist sofort wieder live.
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
| Adresse | Zeigt auf | Ăndert sich |
|---|---|---|
| meine-site.host3.format-c.info | Production (Production-Branch) | bei jedem Push auf main, Promote, Rollback |
| feature-x--meine-site.host3.format-c.info | Preview des Branches feature/x | bei jedem Push auf den Branch; weg mit dem Branch |
| meine-site-a1b2c3d-9f3e.host3.format-c.info | genau 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):
| Fund | Typ | Was passiert |
|---|---|---|
Dockerfile | docker | Phase 2 Deployment endet mit Hinweis â weiter per deploy.sh |
server/package.json oder api/ | hybrid | Phase 2 statisch + /api-Container, noch nicht verfĂŒgbar |
package.json mit "build"-Script | static-build | aktiv 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/ | static | aktiv 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.
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/vercellokal ·/data/vercelauf ccdev3 · Repocc/vercel- Container
vercel-app, Port127.0.0.1:3158, Netzvercel-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-allhttps://mit On-Demand-TLS) + globaleron_demand_tls { ask ⊠/tls-ask }- Deploy von Ănderungen
./deploy.sh(schnell) ·./deploy.sh fullbei Dockerfile-, Paket- oder.env-Ănderungen- Logs
ssh ccdev3 docker logs -f vercel-app
*.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
| Symptom | Ursache und Abhilfe |
|---|---|
| Push löst nichts aus | In 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 Clone | deploypilot 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 Sekunden | Normal â 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 live | Im Dashboard prĂŒfen, ob Production auf ein Ă€lteres Deployment zeigt (nach Rollback). NĂ€chster Push oder Promote auf den neuen Build. |