Files
irrlichtandClaude Opus 5.5 26b0182391 Linkvorschau für den ersten Link eines Beitrags
Der Server holt zum ersten Link Titel, Seiten- bzw. Kanalname und ein
kleines Vorschaubild (320 px) und speichert das Bild lokal; der Browser
lädt nur von uns, Besucher-IPs gehen nie an die verlinkte Seite.
YouTube über oEmbed (alle Linkformen kanonisch als watch?v=<id>), alle
übrigen Seiten über OpenGraph bzw. <title>. Abruf asynchron in einem
Worker, eine Zeile je Link in link_preview, Auffrischen nach 30 Tagen.

Der Abruf-Client lässt nur öffentliche IPs auf Port 80/443 zu, geprüft
nach DNS-Auflösung und bei jeder Weiterleitung (SSRF). Bestehende
Beiträge: kver link-previews. Neue Abhängigkeit golang.org/x/net, damit
go 1.26. DEV bekommt ein beschreibbares Volume für die Vorschaubilder.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TiXsPUqw7oeomZ8wZrQW5q
2026-10-06 18:47:21 +02:00

70 lines
2.2 KiB
Bash
Executable File

#!/usr/bin/env bash
#
# dev-up.sh — baut das Image aus dem aktuellen Arbeitsverzeichnis neu und
# startet den lokalen DEV-Container (kver-dev) damit neu.
#
# Verwendung:
# ./dev-up.sh
#
# Läuft auch automatisch nach jedem Commit (githooks/post-commit, im
# Hintergrund, Log in .git/dev-up.log). Einrichten einmalig per:
# git config core.hooksPath githooks
#
# Voraussetzungen:
# - dev.env mit KVER_DSN (Host "localhost" wird für den Container auf
# host.containers.internal umgeschrieben)
# - Daten/Medien aus dem PROD-Dump unter $KVER_DEV_DATA (read-only gemountet)
#
set -euo pipefail
cd "$(dirname "$0")"
NAME=kver-dev
IMAGE=localhost/kver:dev
PORT="${KVER_DEV_PORT:-8081}"
DATA="${KVER_DEV_DATA:-./prod_backup/2026-09-26}"
# Nur ein Lauf gleichzeitig (schnell aufeinanderfolgende Commits). podman
# bekommt fd 9 jeweils nicht mit (9>&-): conmon lebt so lange wie der
# Container und würde den Lock sonst für immer halten.
exec 9>.git/dev-up.lock
flock 9
DSN="$(grep '^KVER_DSN=' dev.env | cut -d= -f2- | sed 's/@localhost:/@host.containers.internal:/')"
if [[ -z "$DSN" ]]; then
echo "FEHLER: KVER_DSN fehlt in dev.env." >&2
exit 1
fi
echo "== $(date '+%F %T') Baue $IMAGE ($(git rev-parse --short HEAD))"
podman build -q -t "$IMAGE" . 9>&-
mounts=()
[[ -d "$DATA/data" ]] && mounts+=(-v "$DATA/data:/app/data:ro" -e KVER_GEOIP_ASN=/app/data/GeoLite2-ASN.mmdb)
if [[ -d "$DATA/media" ]]; then
mounts+=(-v "$DATA/media:/app/static/media:ro")
# Linkvorschau-Bilder schreibt der Server selbst: beschreibbares Volume über
# dem read-only Media-Mount. Der Mountpunkt muss im Quellverzeichnis
# existieren, weil der Container ihn im read-only Mount nicht anlegen kann.
mkdir -p "$DATA/media/preview"
mounts+=(-v kver-dev-preview:/app/static/media/preview:U)
fi
podman rm -f "$NAME" >/dev/null 2>&1 9>&- || true
podman run -d --name "$NAME" -p "127.0.0.1:$PORT:8080" \
-e KVER_DSN="$DSN" \
"${mounts[@]}" \
--security-opt label=disable "$IMAGE" >/dev/null 9>&-
# Warten, bis die API antwortet.
for _ in $(seq 30); do
if curl -fs -o /dev/null "http://127.0.0.1:$PORT/api/stats"; then
echo "== läuft: http://127.0.0.1:$PORT"
exit 0
fi
sleep 1
done
echo "FEHLER: $NAME antwortet nicht. Log:" >&2
podman logs --tail 20 "$NAME" >&2
exit 1