Skip to content

Repository files navigation

joshuahirsig.xyz

Persönliche Landingpage und Portfolio. Astro, statisch gebaut, selbst gehostet auf dem vServer hinter Traefik.

Repo-Topologie — bitte lesen, bevor du pushst

Forgejo ist die Single Source of Truth.

git.joshuahirsig.xyz/joshii/joshuahirsig.xyz   ← hierhin pushen (origin)
        │
        └── Push-Mirror ──► github.com/joshii-h/joshuahirsig.xyz   (nur Spiegel)

Der Mirror läuft mit Force und überschreibt GitHub bedingungslos — er feuert sofort bei jedem Push, das 8-Stunden-Intervall ist nur der Fallback. Ein Push nach GitHub geht deshalb garantiert verloren. Damit das nicht versehentlich passiert, steht die Push-URL des github-Remotes lokal auf einem ungültigen Wert; ein Push dorthin scheitert laut statt still.

git remote -v
# origin  ssh://git@git.joshuahirsig.xyz:5478/joshii/joshuahirsig.xyz.git
# github  https://github.com/joshii-h/joshuahirsig.xyz.git (fetch)
# github  DISABLED-mirror-target-push-to-origin (push)

Entwicklung

npm install
npm run dev       # lokaler Dev-Server
npm run build     # statischer Build nach dist/
npm run preview   # Build lokal ansehen

Inhalte liegen als Markdown in src/content/ — je Sprache ein Unterordner (en/, de/). Ein neues Projekt ist eine neue .md-Datei, kein Code.

Achtung: Die Kacheln rendern nur das Frontmatter, nicht den Markdown-Body. Alles Sichtbare gehört also in summary, role, tech usw. Text unterhalb des Frontmatters erscheint nirgends — er eignet sich als Notiz, aber nicht als Inhalt.

Deployment

Push auf main → Forgejo Action (.forgejo/workflows/deploy.yml) baut die Seite und legt dist/ auf dem Host unter ~/Docker/Website/dist ab, dann Neustart des website-Containers. Es wird kein SSH-Key benötigt: Der Runner läuft auf demselben Host und bekommt den Docker-Socket gemountet.

dist/ ist bewusst nicht eingecheckt.

Einmalige Migration auf dem Server — Reihenfolge beachten

Der Workflow deployt nur dist/. docker-compose.yaml und nginx.conf bringt er nicht auf den Server, und docker restart liest ohnehin keine Compose-Änderungen ein. Solange der Server noch die alte Compose fährt, mountet nginx weiterhin das ganze Repo-Verzeichnis als Webroot und liefert die alte Seite aus — der Deploy läuft dabei grün durch, weil die alte Startseite antwortet. Diese Migration ist deshalb einmalig von Hand nötig:

ssh vserver
cd ~/Docker/Website

# 1) Die bisher untracked Configs sichern; sie kommen jetzt aus dem Repo
#    und würden den Pull sonst blockieren.
mkdir -p ~/Docker/_backups/website-cutover
cp nginx.conf docker-compose.yaml ~/Docker/_backups/website-cutover/
rm -f nginx.conf docker-compose.yaml nginx.conf.bak-premas

# 2) Neuen Stand holen (entfernt auch index.html, style.css und media/).
git pull origin main

# 3) Recreate statt restart — nur so greift der geänderte Volume-Mount.
docker compose up -d --force-recreate

# 4) Prüfen: Webroot muss jetzt auf dist zeigen, nicht auf das Repo.
docker inspect website --format '{{range .Mounts}}{{.Source}} -> {{.Destination}}{{println}}{{end}}'

Danach gilt der normale Weg: Push auf main → Action baut und deployt.

Ist dist/ zum Zeitpunkt von Schritt 3 noch nicht vorhanden, liefert nginx bis zum ersten Action-Lauf 404. Deshalb zuerst mergen (Action läuft, legt dist/ an) und erst danach die Schritte oben ausführen.

Betrieb

Datei Zweck
docker-compose.yaml nginx-Container, Traefik-Labels, www-Redirect
nginx.conf Matrix-Delegation, Uptime-Kuma-Status-Proxy

Matrix-Delegation — nicht anfassen ohne Test

nginx.conf liefert /.well-known/matrix/server und /.well-known/matrix/client aus. Diese Domain delegiert damit die Föderation an matrix.joshuahirsig.xyz und verweist auf MAS und LiveKit. Geht das kaputt, bricht die Föderation still — keine Fehlermeldung, nur Server, die einen nicht mehr erreichen.

Der Deploy-Workflow prüft beide Endpunkte nach jedem Deploy und schlägt fehl, wenn sie nicht stimmen. Nach manuellen Änderungen zusätzlich prüfen:

curl -s https://joshuahirsig.xyz/.well-known/matrix/server
curl -s https://joshuahirsig.xyz/.well-known/matrix/client

Live-Status

nginx.conf reicht /api/status/… intern an Uptime Kuma weiter, weil dessen API keine CORS-Header setzt und ein direkter Browser-Fetch auf status.joshuahirsig.xyz deshalb blockiert würde. Bewusst auf die zwei benötigten Endpunkte begrenzt.

About

This is the Source of my own Webhost.

Resources

Stars

1 star

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages