Files
Personal-Website/README.md
T
2026-10-25 22:07:13 +01:00

3.7 KiB

lux.harlelux.de

Meine persönliche Website mit Portfolio. Node.js und Express, die Seiten werden mit Nunjucks auf dem Server gerendert. Inhalte liegen als YAML und Markdown auf der Platte, gepflegt werden sie über ein paar Admin-Seiten mit Passwort.

Entwicklung

Node 24 (siehe .nvmrc).

npm install
ADMIN_PASSWORD=test npm run dev   # Seite auf :3000, Admin auf :3001/admin
npm test

Im Dev-Modus sind Entwürfe auf der Seite sichtbar und bekommen ein Badge. Ohne ADMIN_PASSWORD bleiben die Admin-Seiten aus.

Inhalte

Es gibt zwei Ordner:

  • content/ im Repo: Startinhalte und alles, was es im Admin nicht gibt (Texte und Kacheln der Startseite in home.yml).
  • data/ auf dem Server, nicht im Repo: alles, was über die Admin-Seiten bearbeitet wird.

Beim allerersten Start wird der bearbeitbare Teil von content/ nach data/ kopiert (Projekte, Werdegang, Profil, Homelab). Danach gilt nur noch data/, spätere Änderungen an diesen Dateien im Repo werden ignoriert.

data/
  site.yml          Name, Pronomen, Links, Skills, "Gerade dran"
  journey.yml       Stationen für den Werdegang
  homelab.yml       Hardware und Dienste
  pages/            Werdegang und Homelab als <name>.de.md / <name>.en.md, Bilder in pages/images/
  projects/<slug>/  meta.yml, de.md, en.md und die Bilder

Die Dateien lassen sich auch von Hand bearbeiten, die Seite lädt sie bei Änderungen neu. Texte, die in beiden Sprachen gleich sind, stehen als einfacher String, sonst als { de, en }.

Admin-Seiten

Laufen im selben Container auf einem eigenen Port (3001) und bekommen im Nginx Proxy Manager eine eigene Subdomain, z.B.:

https://admin.harlelux.de/admin

Über lux.harlelux.de gibt es kein /admin. Der Login verlangt das Passwort aus ADMIN_PASSWORD, in Produktion mindestens 12 Zeichen, sonst bleiben die Admin-Seiten aus. Nach zehn Fehlversuchen ist der Login für diese Adresse eine Viertelstunde gesperrt (IPv6 zählt pro /64). Die App sieht dafür die echte Adresse aus X-Forwarded-For, das setzt der Proxy Manager von selbst.

Unter derselben Adresse zeigt /de/ die ganze Seite mit Entwürfen, als Vorschau.

Hochgeladene Bilder werden auf höchstens 2400 px verkleinert und neu gespeichert, dabei fallen EXIF-Daten wie der Aufnahmeort weg.

In die Textfelder für Projekte, Werdegang und Homelab lassen sich Bilder mit Strg+V oder per Drag & Drop einfügen. Sie werden sofort hochgeladen und als Markdown eingesetzt, bei Projekten landen sie im Projektordner, sonst in pages/images/. Bei einem neuen Projekt geht das erst nach dem ersten Speichern.

Deployment

Läuft als Docker-Stack in Dockge hinter Nginx Proxy Manager.

cd ~/stacks
git clone https://git.harlelux.de/Harlekin/Personal-Website.git personal_website
cd personal_website
mkdir data              # muss dem Container-User (UID 1000) gehören
cp .env.example .env    # ADMIN_PASSWORD eintragen
docker compose up -d --build

Im Nginx Proxy Manager zwei Proxy Hosts anlegen, beide mit Let's-Encrypt-Zertifikat, Force SSL und HSTS:

  • lux.harlelux.de auf personal-website:3000
  • die Admin-Subdomain (z.B. admin.harlelux.de, braucht einen DNS-Eintrag) auf personal-website:3001

Der Container hängt im Netzwerk nginx_default, ein anderer Name lässt sich über PROXY_NETWORK in der .env setzen. Freigegebene Ports auf dem Server braucht er keine.

Code-Updates: git pull und docker compose up -d --build. Wer statt Git mit rsync hochlädt, muss data und .env ausschließen, sonst sind die Inhalte weg.

data/ gehört ins Backup. Dort liegt alles, was über die Admin-Seiten angelegt wurde.

Lizenz

Der Code steht unter der MIT-Lizenz (siehe LICENSE). Texte und Bilder in content/ und data/ sind davon ausgenommen.