fix(standards): align container rules, deploy script, docs and tests

This commit is contained in:
Jan Wagner
2026-08-31 20:32:49 +02:00
parent 318efe45c6
commit 361af1eaaf
7 changed files with 42 additions and 11 deletions
+1 -1
View File
@@ -32,7 +32,7 @@ Privates Portfolio von „eldov" (Jan Wagner), Domain `eldov.win`. Gegenstück z
- **i18n:** DE als Default (ohne Prefix), EN unter `/en`. Routing über `proxy.ts` analog `w-make-com`. - **i18n:** DE als Default (ohne Prefix), EN unter `/en`. Routing über `proxy.ts` analog `w-make-com`.
- **DB:** SQLite unter `DB_PATH` (Default `data/eldov.db`). Schema in `src/lib/schema.sql`, Seed in `src/lib/seed.ts`. Wird beim ersten Request automatisch initialisiert. - **DB:** SQLite unter `DB_PATH` (Default `data/eldov.db`). Schema in `src/lib/schema.sql`, Seed in `src/lib/seed.ts`. Wird beim ersten Request automatisch initialisiert.
- **Auth:** Single-User-Admin via `ADMIN_PASSWORD` + `SESSION_SECRET` (HMAC-signiertes HttpOnly-Cookie). `proxy.ts` schützt `/admin/*` und `/api/admin/*` (außer `/admin/login`, `/api/admin/login`). - **Auth:** Single-User-Admin via `ADMIN_PASSWORD` + `SESSION_SECRET` (HMAC-signiertes HttpOnly-Cookie). `proxy.ts` schützt `/admin/*` und `/api/admin/*` (außer `/admin/login`, `/api/admin/login`).
- **Deploy:** `deploy-vps.sh` synct in Container `/opt/containers/eldov-portfolio` auf `free-warez.top`, 9router-Eintrag `eldov.win` → Container. - **Deploy:** `./deploy.sh` (oder `./deploy-vps.sh`) synct in Container `/opt/containers/eldov-portfolio` auf `free-warez.win`, Traefik routet `eldov.win` und `www.eldov.win` → Container-Port 3000.
## Konventionen ## Konventionen
+1 -1
View File
@@ -78,7 +78,7 @@ Beim ersten Request ohne DB wird automatisch migriert und mit dem Seed aus `src/
## Deployment ## Deployment
`./deploy-vps.sh` synct nach `free-warez.top:/opt/containers/eldov-portfolio`. Build und Restart des Containers passieren dort. 9router-Eintrag `eldov.win` → Container-Internes `3000`. `./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.
## DSGVO-Hinweis ## DSGVO-Hinweis
+30 -4
View File
@@ -15,8 +15,23 @@ set -euo pipefail
VPS_HOST="${VPS_HOST:-free-warez.win}" VPS_HOST="${VPS_HOST:-free-warez.win}"
VPS_DIR="${VPS_DIR:-/opt/containers/eldov-portfolio}" VPS_DIR="${VPS_DIR:-/opt/containers/eldov-portfolio}"
# 1. Check SSH connection
echo "→ Prüfe SSH-Verbindung zu $VPS_HOST..." echo "→ Prüfe SSH-Verbindung zu $VPS_HOST..."
ssh -o BatchMode=yes -o ConnectTimeout=10 "$VPS_HOST" "echo OK" >/dev/null if ! ssh -q -o BatchMode=yes -o ConnectTimeout=10 "$VPS_HOST" exit; then
echo "❌ Keine SSH-Verbindung zu $VPS_HOST möglich."
exit 1
fi
# 2. Push git commits if in git repo
LOCAL_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
if [ -d "$LOCAL_DIR/.git" ]; then
echo "→ Prüfe Git-Status..."
if ! git -C "$LOCAL_DIR" diff-index --quiet HEAD -- 2>/dev/null; then
echo "⚠️ Lokale uncommitted Änderungen vorhanden."
fi
echo "→ Pushe Commits nach Gitea..."
git -C "$LOCAL_DIR" push origin main 2>/dev/null || echo "️ Git push übersprungen oder bereits aktuell."
fi
echo "→ Synchronisiere Quelldateien nach $VPS_HOST:$VPS_DIR" echo "→ Synchronisiere Quelldateien nach $VPS_HOST:$VPS_DIR"
rsync -avz --delete \ rsync -avz --delete \
@@ -35,6 +50,17 @@ ssh "$VPS_HOST" "cd '$VPS_DIR' && \
docker compose up -d app && \ docker compose up -d app && \
docker image prune -f" docker image prune -f"
echo "✓ Deploy abgeschlossen. Healthcheck in 10 s…" echo "✓ Deploy abgeschlossen. Healthcheck in 5 s…"
sleep 10 sleep 5
ssh "$VPS_HOST" "docker inspect --format='{{.State.Health.Status}}' eldov-portfolio || echo 'no healthcheck yet'" echo -n " Docker Health: "
ssh "$VPS_HOST" "docker inspect --format='{{if .State.Health}}{{.State.Health.Status}}{{else}}no healthcheck{{end}}' eldov-portfolio"
echo -n " Public URL (https://eldov.win): "
if curl -fs -o /dev/null --resolve eldov.win:443:217.160.217.196 -m 5 "https://eldov.win/"; then
echo "✅ 200 OK"
else
echo "⚠️ Nicht erreichbar"
fi
echo "✨ Deployment erfolgreich beendet!"
Symlink
+1
View File
@@ -0,0 +1 @@
deploy-vps.sh
+3 -2
View File
@@ -14,7 +14,7 @@ services:
dockerfile: Dockerfile dockerfile: Dockerfile
args: args:
NEXT_PUBLIC_SITE_URL: ${NEXT_PUBLIC_SITE_URL:-https://eldov.win} NEXT_PUBLIC_SITE_URL: ${NEXT_PUBLIC_SITE_URL:-https://eldov.win}
image: eldov-portfolio:latest image: eldov-portfolio:1.0.0
container_name: eldov-portfolio container_name: eldov-portfolio
mem_limit: 512m mem_limit: 512m
restart: unless-stopped restart: unless-stopped
@@ -49,9 +49,10 @@ services:
- "traefik.http.routers.eldov-win.entrypoints=websecure" - "traefik.http.routers.eldov-win.entrypoints=websecure"
- "traefik.http.routers.eldov-win.tls=true" - "traefik.http.routers.eldov-win.tls=true"
- "traefik.http.routers.eldov-win.tls.certresolver=http_resolver" - "traefik.http.routers.eldov-win.tls.certresolver=http_resolver"
- "traefik.http.routers.eldov-win.middlewares=default@file,crowdsec-bouncer-plugin@file" - "traefik.http.routers.eldov-win.middlewares=my-get-real-ip@file,default@file,crowdsec-bouncer-plugin@file"
- "traefik.http.routers.eldov-win.service=eldov-win" - "traefik.http.routers.eldov-win.service=eldov-win"
- "traefik.http.services.eldov-win.loadbalancer.server.port=3000" - "traefik.http.services.eldov-win.loadbalancer.server.port=3000"
- "com.centurylinklabs.watchtower.enable=false"
# HTTP→HTTPS-Redirect für die unverschlüsselte Variante (Traefik # HTTP→HTTPS-Redirect für die unverschlüsselte Variante (Traefik
# bringt dafür eine eingebaute redirectScheme-Middleware mit). # bringt dafür eine eingebaute redirectScheme-Middleware mit).
- "traefik.http.routers.eldov-win-http.rule=Host(`eldov.win`) || Host(`www.eldov.win`)" - "traefik.http.routers.eldov-win-http.rule=Host(`eldov.win`) || Host(`www.eldov.win`)"
+1 -1
View File
@@ -12,7 +12,7 @@
"start": "next start", "start": "next start",
"lint": "eslint", "lint": "eslint",
"test": "node --experimental-strip-types --test src/i18n/routes.test.ts src/lib/auth/session.test.ts", "test": "node --experimental-strip-types --test src/i18n/routes.test.ts src/lib/auth/session.test.ts",
"test:db": "node --experimental-strip-types src/lib/db/smoke.ts", "test:db": "bash -c 'node --experimental-strip-types src/lib/db/smoke.ts'",
"seed": "node --experimental-strip-types src/lib/db/seed-cli.ts" "seed": "node --experimental-strip-types src/lib/db/seed-cli.ts"
}, },
"dependencies": { "dependencies": {
+5 -2
View File
@@ -90,7 +90,7 @@ console.log("\n[2] Lesen + Schreiben");
} }
// Cleanup // Cleanup
__resetDbForTest(); // __resetDbForTest();
try { try {
rmSync(dir, { recursive: true, force: true }); rmSync(dir, { recursive: true, force: true });
} catch { } catch {
@@ -102,4 +102,7 @@ console.log(`\n${failures === 0 ? "✓ smoke ok" : `✗ ${failures} failure(s)`}
// Hinweis: Auf manchen Node-Versionen segfaultet better-sqlite3 beim // Hinweis: Auf manchen Node-Versionen segfaultet better-sqlite3 beim
// nativen Handle-Cleanup nach process.exit. Das ist kosmetisch — die Tests // nativen Handle-Cleanup nach process.exit. Das ist kosmetisch — die Tests
// oben sind alle grün. In Produktion (Docker, Node 22.13) tritt das nicht auf. // oben sind alle grün. In Produktion (Docker, Node 22.13) tritt das nicht auf.
process.exit(failures === 0 ? 0 : 1); if (failures > 0) {
process.exit(1);
}