Files
Jan Wagner 9ceead6ab6 chore: repo hygiene — .dockerignore, .editorconfig, deploy-Doku
- .dockerignore: schließt node_modules, .next, data/, lokale ENV, Deploy-
  Skripte und Repo-Metadaten aus dem Build-Kontext aus. Vorher hat 'COPY . .'
  im Dockerfile alles ins Image kopiert, was unter src/ lag — jetzt wird nur
  das Nötige gebaut.
- .editorconfig: einheitliche Einrückung (LF, 2 Spaces, UTF-8) und
  final-newline für TS/JS/JSON/YAML/SQL. Verhindert Editor-Drift zwischen
  pi/laptop/WSL-PC.
- README: Live-Status-Block ergänzt (URL, Container-Image 323 MB, Traefik,
  Repo) und Erst-Deploy-Runbook (DNS, .env.local-Setup, Traefik-Restart
  wegen ACME 1h-Rate-Limit bei fehlendem A-Record).

Hintergrund: vorher hat docker build lokal die data/eldov.db mitkopiert (in
node_modules fällt das nicht auf, aber data/ lag im src/-Parent) und die
Deploy-Skripte selbst (deploy.sh, deploy-vps.sh) — mit.dockerignore wandert
das nicht mehr ins Image. .editorconfig war noch nie da, aber die anderen
Repos im Cluster (w-make-com, hermes-tools) haben eins — Konsistenz.
2026-08-31 20:38:10 +02:00

129 lines
5.5 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# eldov.win
Privates Portfolio für „eldov" — Self-Hosting, Bots, AI-Fleet, Hacks. Domain [`eldov.win`](https://eldov.win) (live seit 2026-08-31).
Das ist das Gegenstück zu [`w-make.com`](../w-make-com/README.md). Dort steht die industrielle Arbeit (Behälterglas, W-Make Batch, Batchmaker Studio). Hier stehen die Dinge, die mich abseits von Auftragsarbeit umtreiben: Hermes, Casino-/Trading-Bots, Freewarez-Selfhosting, Themes für Open-Source-Software.
## Live-Status
- **URL:** https://eldov.win (und https://www.eldov.win) — Let's Encrypt via Traefik ACME
- **Container:** `eldov-portfolio` auf `free-warez.win`, Image 323 MB (Standalone-Build), Healthcheck `healthy`
- **Routing:** Traefik hinter `cloudflare NS` (DNS only) auf `217.160.217.196`, Labels analog w-make.com
- **DB:** SQLite unter `eldov_data` Volume, Seed mit 13 Projekten + Profil beim ersten Request
- **Admin:** `/admin/login`, single-user via `ADMIN_PASSWORD` + HMAC-Session-Cookie
- **Repo:** https://gitea.free-warez.win/eldov/eldov-win (public)
## Stack
Next.js 16 (App Router) · React 19 · Tailwind 4 · TypeScript · SQLite (`better-sqlite3`). SSR mit dynamischem Content aus DB.
## Lokal
```bash
npm install
npm run dev # http://localhost:3000 (lädt .env.local automatisch)
npm run build
npm test # i18n + auth
npm run test:db # DB-Smoke (Schema, Seed, CRUD)
```
`.env.local` (nicht committen, von .env.local.example kopieren):
```
ADMIN_PASSWORD=<starkes-passwort>
SESSION_SECRET=<mindestens-32-byte-hex>
DB_PATH=./data/eldov.db
NEXT_PUBLIC_SITE_URL=http://localhost:3000
```
> Wichtig für Production: `next start` lädt `.env.local` **nicht** automatisch.
> env vars müssen vor dem Start gesetzt sein — typischerweise via Docker
> `env_file` (siehe `docker-compose.yml`) oder systemd `Environment=`.
> Für lokale Production-Smoke-Tests:
>
> ```bash
> ADMIN_PASSWORD=... SESSION_SECRET=... npm run start
> ```
## Routen
| Pfad | Zweck |
|---|---|
| `/` (DE) · `/en` | Startseite |
| `/ueber-mich` · `/en/about` | Bio, Skills, Setup |
| `/projekte` · `/en/projects` | Projektübersicht |
| `/projekte/[slug]` · `/en/projects/[slug]` | Projekt-Detail |
| `/kontakt` · `/en/contact` | Linksammlung statt Kontaktformular |
| `/impressum` · `/en/legal` | Impressum |
| `/datenschutz` · `/en/privacy` | Datenschutz |
| `/admin/login` | Login |
| `/admin/dashboard` | Übersicht |
| `/admin/profile` | Bio/Person editieren |
| `/admin/projects` · `/admin/projects/new` · `/admin/projects/[slug]` | Projekte-CRUD |
API (alle außer `/api/admin/login` erfordern Auth-Cookie):
| Methode · Pfad | Effekt |
|---|---|
| `POST /api/admin/login` | Body `{password}` → setzt Session-Cookie |
| `POST /api/admin/logout` | löscht Cookie |
| `GET /api/admin/session` | `{authenticated: boolean}` |
| `GET /api/admin/profile` | aktuelles Profil |
| `PUT /api/admin/profile` | Profil aktualisieren |
| `GET /api/admin/projects` | Liste |
| `POST /api/admin/projects` | neues Projekt |
| `GET /api/admin/projects/[slug]` | Detail |
| `PUT /api/admin/projects/[slug]` | aktualisieren |
| `DELETE /api/admin/projects/[slug]` | löschen |
## Datenmodell
SQLite, Schema in `src/lib/schema.sql`. Zwei Haupttabellen:
- `profile` (singletone, id=1): `handle`, `real_name`, `role`, `location`, `bio_de`, `bio_en`, `links_json`, `updated_at`
- `projects` (`slug` PK): `slug`, `number`, `status`, `category`, `stack`, `href`, `featured` (0/1), `summary_de`, `summary_en`, `body_de`, `body_en`, `created_at`, `updated_at`
Beim ersten Request ohne DB wird automatisch migriert und mit dem Seed aus `src/lib/seed.ts` gefüllt (handle, bio, initiale Projekte aus dem Workspace).
## Deployment
`./deploy.sh` (oder `./deploy-vps.sh`) synct nach `free-warez.win:/opt/containers/eldov-portfolio`. Build und Restart des Containers passieren dort. Traefik routet `eldov.win` & `www.eldov.win` per Docker-Labels → Container-Internes 3000.
### Was beim Erst-Deploy zu tun ist
1. **DNS:** Im Cloudflare-Dashboard für `eldov.win` zwei A-Records anlegen — `eldov.win` und `www.eldov.win``217.160.217.196`, **Proxy: DNS only (graue Wolke)**, TTL 300 oder Auto.
2. **Vorbereitung auf dem VPS:**
```bash
ssh free-warez.win
sudo mkdir -p /opt/containers/eldov-portfolio
sudo chown 1000:1000 /opt/containers/eldov-portfolio
# Secret generieren:
openssl rand -hex 32 > /tmp/session-secret
openssl rand -base64 18 | tr -d '/+=' | head -c 20 > /tmp/admin-password
```
Dann `/opt/containers/eldov-portfolio/.env.local` anlegen (chmod 600):
```
ADMIN_PASSWORD=<aus /tmp/admin-password>
SESSION_SECRET=<aus /tmp/session-secret>
DB_PATH=/app/data/eldov.db
NEXT_PUBLIC_SITE_URL=https://eldov.win
```
3. **Erst-Deploy:** `./deploy-vps.sh` (sync + build + up).
4. **Traefik-Restart** nach DNS-Propagation, damit die ACME-Challenge für `eldov.win` startet:
```bash
ssh free-warez.win 'docker restart traefik'
```
Wenn der A-Record vor dem ersten Traefik-Versuch fehlte, kann Let's Encrypt die Domain 5× nicht validieren und macht ein 1h-Rate-Limit. Nach dem Limit + Restart kommt das Zertifikat automatisch.
### Update-Deploy
```bash
./deploy-vps.sh # synct + baut + restarts
```
Die DB bleibt persistent (`eldov_data` Volume). Admin-Änderungen überleben Deploys.
## DSGVO-Hinweis
Das Admin-Backend speichert keine personenbezogenen Daten außer dem Profil des Betreibers. Login-Cookie ist HMAC-signiert, HttpOnly, SameSite=Lax, 7 Tage gültig. Es findet kein Tracking, keine externen Skripte, keine Schriftarten von Drittanbietern statt.