Add scripts/hermes-wiki-serve.sh wrapper + README update
Wiki-Serve-Skript war bisher in ~/.local/bin/, jetzt auch im Repo versioniert, damit Updates via git pull verfügbar sind. CHANGELOG korrigiert: server.py jetzt +12 Zeilen statt +7 (Bug-Fix für trailing '/' ist mit drin).
This commit is contained in:
@@ -49,6 +49,25 @@ tailscale serve --bg --https=443 http://127.0.0.1:8765
|
||||
# Access via https://<hostname>.<tailnet>.ts.net/
|
||||
```
|
||||
|
||||
### One-command setup via wrapper script
|
||||
|
||||
The `scripts/hermes-wiki-serve.sh` wrapper handles start/stop/logs/status, PID-tracking, log-files, and Tailscale integration:
|
||||
|
||||
```bash
|
||||
# Install: copy script to PATH
|
||||
cp scripts/hermes-wiki-serve.sh ~/.local/bin/
|
||||
chmod +x ~/.local/bin/hermes-wiki-serve.sh
|
||||
|
||||
# Use:
|
||||
hermes-wiki-serve.sh start # starts server, sets up tailscale serve
|
||||
hermes-wiki-serve.sh status # shows PID, Tailscale-URL, health
|
||||
hermes-wiki-serve.sh logs # tail all logs
|
||||
hermes-wiki-serve.sh stop # stops server (keeps tailscale running)
|
||||
hermes-wiki-serve.sh restart # stop + start
|
||||
```
|
||||
|
||||
The script defaults to using this repo at `~/repos/hermes-wiki-viewer/`. Override via `HERMES_WIKI_OWV_DIR`.
|
||||
|
||||
## Customization
|
||||
|
||||
`vault-custom.js` is Lukas' own code, organized into clear sections:
|
||||
|
||||
Executable
+346
@@ -0,0 +1,346 @@
|
||||
#!/usr/bin/env bash
|
||||
# hermes-wiki-serve.sh — Hermes Wiki via obsidian-web-viewer + Tailscale
|
||||
#
|
||||
# Was dieses Skript tut:
|
||||
# - Klont DanielCheer/obsidian-web-viewer einmalig nach ~/.local/share/hermes-wiki/owv/
|
||||
# - Startet deren server.py (Python stdlib) auf 127.0.0.1:8765 (Loopback)
|
||||
# - Aktiviert tailscale serve, der den Loopback-Port als https im Tailnet exponen lässt
|
||||
# - Liefert File-Tree, 3D-Graph, Volltext-Suche, WikiLink-Navigation out-of-the-box
|
||||
#
|
||||
# Verwendung:
|
||||
# hermes-wiki-serve.sh start # Server starten (klont obv beim ersten Mal)
|
||||
# hermes-wiki-serve.sh stop # Server stoppen
|
||||
# hermes-wiki-serve.sh restart # stop + start
|
||||
# hermes-wiki-serve.sh status # Process-Status, Health-Check, Tailscale-URL
|
||||
# hermes-wiki-serve.sh logs # tail -f der Log-Files
|
||||
# hermes-wiki-serve.sh install # nur das Clonen/Update, kein Server-Start
|
||||
# hermes-wiki-serve.sh --help
|
||||
#
|
||||
# Umgebungsvariablen:
|
||||
# HERMES_WIKI_PORT=8765 Lokaler HTTP-Port (Loopback)
|
||||
# HERMES_WIKI_DIR=/home/admin/my-karpathy-wiki
|
||||
# HERMES_WIKI_LOG_DIR=$HOME/.local/share/hermes-wiki/log
|
||||
# HERMES_WIKI_TS=auto auto|yes|no — Tailscale serve aktivieren
|
||||
# HERMES_WIKI_TS_PATH= leer=Root-Prefix (default), /wiki=unter-Pfad
|
||||
# HERMES_WIKI_OWV_DIR=$HOME/repos/hermes-wiki-viewer (Lukas-Fork default; upstream obv als Fallback)
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Defaults
|
||||
# ---------------------------------------------------------------------------
|
||||
readonly HERMES_WIKI_PORT="${HERMES_WIKI_PORT:-8765}"
|
||||
readonly HERMES_WIKI_DIR="${HERMES_WIKI_DIR:-/home/admin/my-karpathy-wiki}"
|
||||
readonly HERMES_WIKI_LOG_DIR="${HERMES_WIKI_LOG_DIR:-$HOME/.local/share/hermes-wiki/log}"
|
||||
readonly HERMES_WIKI_TS="${HERMES_WIKI_TS:-auto}"
|
||||
readonly HERMES_WIKI_TS_PATH="${HERMES_WIKI_TS_PATH:-}" # leer = Root-Prefix (obv nutzt relative URLs!)
|
||||
readonly HERMES_WIKI_OWV_DIR="${HERMES_WIKI_OWV_DIR:-$HOME/repos/hermes-wiki-viewer}"
|
||||
readonly HERMES_WIKI_REPO="${HERMES_WIKI_REPO:-}" # leer = lokales Lukas-Repo nutzen
|
||||
readonly OWV_REPO_UPSTREAM="https://github.com/DanielCheer/obsidian-web-viewer.git"
|
||||
readonly PID_FILE="/tmp/hermes-wiki-serve.pid"
|
||||
readonly HEALTH_URL="http://127.0.0.1:${HERMES_WIKI_PORT}/api/vault/tree"
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Helpers
|
||||
# ---------------------------------------------------------------------------
|
||||
log() {
|
||||
printf '[%s] %s\n' "$(date +%H:%M:%S)" "$*" | tee -a "$HERMES_WIKI_LOG_DIR/server.log" >&2
|
||||
}
|
||||
|
||||
die() {
|
||||
log "ERROR: $*"
|
||||
exit 1
|
||||
}
|
||||
|
||||
ensure_dirs() {
|
||||
mkdir -p "$HERMES_WIKI_LOG_DIR" || die "Kann Log-Dir nicht erstellen: $HERMES_WIKI_LOG_DIR"
|
||||
}
|
||||
|
||||
require_tools() {
|
||||
command -v python3 >/dev/null || die "python3 nicht gefunden"
|
||||
command -v git >/dev/null || die "git nicht gefunden"
|
||||
[ -d "$HERMES_WIKI_DIR" ] || die "Wiki-Verzeichnis nicht gefunden: $HERMES_WIKI_DIR"
|
||||
}
|
||||
|
||||
detect_tailscale() {
|
||||
[ "$HERMES_WIKI_TS" != "no" ] || return 1
|
||||
command -v tailscale >/dev/null || return 1
|
||||
tailscale status --json >/dev/null 2>&1 || return 1
|
||||
return 0
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Installation: Repo klonen oder updaten
|
||||
# ---------------------------------------------------------------------------
|
||||
install_repo() {
|
||||
# Mode 1: Lokales Lukas-Repo (~/repos/hermes-wiki-viewer/) — default nach Fork
|
||||
if [ -d "$HERMES_WIKI_OWV_DIR/.git" ] && [ -z "$HERMES_WIKI_REPO" ]; then
|
||||
log "Nutze lokales Lukas-Repo: $HERMES_WIKI_OWV_DIR"
|
||||
(cd "$HERMES_WIKI_OWV_DIR" && git pull --ff-only 2>>"$HERMES_WIKI_LOG_DIR/install.log") || \
|
||||
log "WARN: git pull fehlgeschlagen — nutze Working-Tree-Stand"
|
||||
# Mode 2: Remote Lukas-Repo klonen (z.B. wenn HERMES_WIKI_REPO gesetzt)
|
||||
elif [ -n "$HERMES_WIKI_REPO" ]; then
|
||||
if [ -d "$HERMES_WIKI_OWV_DIR/.git" ]; then
|
||||
log "Update Lukas-Fork in $HERMES_WIKI_OWV_DIR"
|
||||
(cd "$HERMES_WIKI_OWV_DIR" && git pull --ff-only 2>>"$HERMES_WIKI_LOG_DIR/install.log") || \
|
||||
log "WARN: git pull fehlgeschlagen"
|
||||
else
|
||||
log "Klone Lukas-Fork $HERMES_WIKI_REPO nach $HERMES_WIKI_OWV_DIR"
|
||||
git clone "$HERMES_WIKI_REPO" "$HERMES_WIKI_OWV_DIR" 2>>"$HERMES_WIKI_LOG_DIR/install.log" || \
|
||||
die "git clone fehlgeschlagen — Repo-URL korrekt?"
|
||||
fi
|
||||
# Mode 3: Fallback — upstream obv direkt (vor Lukas-Fork)
|
||||
else
|
||||
log "Kein Lukas-Repo gefunden, klone upstream obv nach $HERMES_WIKI_OWV_DIR"
|
||||
log "(Für Lukas-Customizations: HERMES_WIKI_OWV_DIR=/path/to/hermes-wiki-viewer setzen)"
|
||||
git clone "$OWV_REPO_UPSTREAM" "$HERMES_WIKI_OWV_DIR" 2>>"$HERMES_WIKI_LOG_DIR/install.log" || \
|
||||
die "git clone fehlgeschlagen"
|
||||
fi
|
||||
|
||||
# requirements.txt: nur PyYAML (optional). Stdlib reicht für unsere Zwecke.
|
||||
if ! python3 -c "import yaml" 2>/dev/null; then
|
||||
log "PyYAML nicht installiert (optional). Installiere..."
|
||||
python3 -m pip install --user --quiet PyYAML 2>>"$HERMES_WIKI_LOG_DIR/install.log" || \
|
||||
log "WARN: PyYAML-Installation fehlgeschlagen — Frontmatter wird rudimentär behandelt"
|
||||
fi
|
||||
log "Wiki-Viewer bereit in $HERMES_WIKI_OWV_DIR"
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Tailscale-Integration
|
||||
# ---------------------------------------------------------------------------
|
||||
start_tailscale() {
|
||||
detect_tailscale || {
|
||||
[ "$HERMES_WIKI_TS" = "no" ] || \
|
||||
log "Tailscale übersprungen (nicht verfügbar oder HERMES_WIKI_TS=$HERMES_WIKI_TS)"
|
||||
return 0
|
||||
}
|
||||
|
||||
if tailscale serve status --bg 2>/dev/null | grep -q "$HERMES_WIKI_PORT"; then
|
||||
log "Tailscale serve bereits aktiv für Port $HERMES_WIKI_PORT"
|
||||
return 0
|
||||
fi
|
||||
|
||||
log "Starte tailscale serve auf Root-Prefix -> 127.0.0.1:$HERMES_WIKI_PORT"
|
||||
local ts_path_arg=()
|
||||
if [ -n "$HERMES_WIKI_TS_PATH" ]; then
|
||||
ts_path_arg=(--set-path="$HERMES_WIKI_TS_PATH")
|
||||
log "(Tailscale wird unter /$HERMES_WIKI_TS_PATH/ exposen — Achtung: obv nutzt relative URLs!)"
|
||||
fi
|
||||
if tailscale serve --bg --https=443 "${ts_path_arg[@]}" \
|
||||
"http://127.0.0.1:$HERMES_WIKI_PORT" 2>>"$HERMES_WIKI_LOG_DIR/tailscale.log"; then
|
||||
local ts_url
|
||||
ts_url=$(tailscale serve status --json 2>/dev/null | python3 -c "
|
||||
import json, sys
|
||||
try:
|
||||
data = json.load(sys.stdin)
|
||||
for entry in data.get('Web', {}).values():
|
||||
print(f'https://{entry[\"HTTPS\"]}{entry[\"Path\"]}/')
|
||||
break
|
||||
except: pass
|
||||
" 2>/dev/null)
|
||||
log "Tailscale serve aktiv: ${ts_url:-URL konnte nicht ermittelt werden}"
|
||||
return 0
|
||||
else
|
||||
log "WARN: tailscale serve fehlgeschlagen — siehe $HERMES_WIKI_LOG_DIR/tailscale.log"
|
||||
return 0
|
||||
fi
|
||||
}
|
||||
|
||||
stop_tailscale() {
|
||||
detect_tailscale || return 0
|
||||
if tailscale serve status --bg 2>/dev/null | grep -q "$HERMES_WIKI_PORT"; then
|
||||
log "Stoppe tailscale serve"
|
||||
tailscale serve --bg --https=443 --set-path="$HERMES_WIKI_TS_PATH" off \
|
||||
"http://127.0.0.1:$HERMES_WIKI_PORT" 2>>"$HERMES_WIKI_LOG_DIR/tailscale.log" || true
|
||||
fi
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Server-Lifecycle
|
||||
# ---------------------------------------------------------------------------
|
||||
is_running() {
|
||||
[ -f "$PID_FILE" ] || return 1
|
||||
local pid
|
||||
pid=$(cat "$PID_FILE" 2>/dev/null || echo "")
|
||||
[ -n "$pid" ] && kill -0 "$pid" 2>/dev/null
|
||||
}
|
||||
|
||||
start_server() {
|
||||
ensure_dirs
|
||||
require_tools
|
||||
install_repo
|
||||
|
||||
if is_running; then
|
||||
log "Server läuft bereits (PID $(cat "$PID_FILE"))"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Port-Konflikt-Check
|
||||
if ss -tln 2>/dev/null | grep -q ":${HERMES_WIKI_PORT} "; then
|
||||
die "Port ${HERMES_WIKI_PORT} ist bereits belegt. HERMES_WIKI_PORT ändern oder Prozess beenden."
|
||||
fi
|
||||
|
||||
# Check, dass die Wiki-Page gerendert werden kann
|
||||
local md_count
|
||||
md_count=$(find "$HERMES_WIKI_DIR" -name "*.md" -not -path "*/raw/*" 2>/dev/null | wc -l)
|
||||
log "Wiki-Dir: $HERMES_WIKI_DIR ($md_count .md-Dateien, ohne /raw/)"
|
||||
|
||||
# Server starten — Loopback only, NICHT 0.0.0.0
|
||||
log "Starte obsidian-web-viewer server.py auf 127.0.0.1:$HERMES_WIKI_PORT"
|
||||
nohup python3 "$HERMES_WIKI_OWV_DIR/server.py" \
|
||||
--vault "$HERMES_WIKI_DIR" \
|
||||
--host 127.0.0.1 \
|
||||
--port "$HERMES_WIKI_PORT" \
|
||||
> "$HERMES_WIKI_LOG_DIR/renderer.log" 2>&1 &
|
||||
local pid=$!
|
||||
echo "$pid" > "$PID_FILE"
|
||||
|
||||
# Health-Check (das Tool hat keine /__health, aber /api/vault/tree ist immer da)
|
||||
local i
|
||||
for i in 1 2 3 4 5; do
|
||||
sleep 1
|
||||
if curl -sf "$HEALTH_URL" >/dev/null 2>&1; then
|
||||
log "Server gestartet (PID $pid), Health-Check OK"
|
||||
start_tailscale
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
|
||||
log "ERROR: Health-Check fehlgeschlagen nach 5s"
|
||||
log "--- renderer.log ---"
|
||||
tail -20 "$HERMES_WIKI_LOG_DIR/renderer.log" >&2
|
||||
rm -f "$PID_FILE"
|
||||
return 1
|
||||
}
|
||||
|
||||
stop_server() {
|
||||
if is_running; then
|
||||
local pid
|
||||
pid=$(cat "$PID_FILE")
|
||||
log "Stoppe Server (PID $pid)"
|
||||
kill "$pid" 2>/dev/null || true
|
||||
local i
|
||||
for i in 1 2 3 4 5; do
|
||||
kill -0 "$pid" 2>/dev/null || break
|
||||
sleep 0.5
|
||||
done
|
||||
if kill -0 "$pid" 2>/dev/null; then
|
||||
kill -9 "$pid" 2>/dev/null || true
|
||||
fi
|
||||
rm -f "$PID_FILE"
|
||||
fi
|
||||
# Tailscale NICHT stoppen — soll laufen bleiben für Re-Start ohne Tailscale-Re-Init
|
||||
# stop_tailscale
|
||||
log "(Tailscale serve bleibt aktiv für Re-Start)"
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Status / Help
|
||||
# ---------------------------------------------------------------------------
|
||||
show_status() {
|
||||
echo "=== Hermes Wiki Server Status (via obsidian-web-viewer) ==="
|
||||
echo "Wiki-Dir: $HERMES_WIKI_DIR"
|
||||
echo "Viewer-Repo: $HERMES_WIKI_OWV_DIR"
|
||||
echo "Port: $HERMES_WIKI_PORT (Loopback only)"
|
||||
echo "Log-Dir: $HERMES_WIKI_LOG_DIR"
|
||||
|
||||
if is_running; then
|
||||
local pid
|
||||
pid=$(cat "$PID_FILE")
|
||||
echo "Status: RUNNING (PID $pid)"
|
||||
ps -o pid,rss,etime,cmd -p "$pid" 2>/dev/null | tail -1 | \
|
||||
awk '{printf " Memory: %.1f MB, Uptime: %s\n", $2/1024, $3}'
|
||||
|
||||
if curl -sf "$HEALTH_URL" >/dev/null 2>&1; then
|
||||
local md_count
|
||||
md_count=$(curl -sf "$HEALTH_URL" | python3 -c "
|
||||
import json, sys
|
||||
try:
|
||||
data = json.load(sys.stdin)
|
||||
count = sum(1 + len(c.get('children',[])) for c in [data])
|
||||
# grobe zählung
|
||||
print(len(json.dumps(data)))
|
||||
except: print('?')
|
||||
" 2>/dev/null || echo "?")
|
||||
echo "Health: OK (Tree-API reachable, $md_count bytes)"
|
||||
else
|
||||
echo "Health: FAILED"
|
||||
fi
|
||||
|
||||
if detect_tailscale; then
|
||||
if tailscale serve status --bg 2>&1 | grep -q "$HERMES_WIKI_PORT"; then
|
||||
local ts_url
|
||||
ts_url=$(tailscale serve status --json 2>/dev/null | python3 -c "
|
||||
import json, sys
|
||||
try:
|
||||
data = json.load(sys.stdin)
|
||||
for entry in data.get('Web', {}).values():
|
||||
print(f'https://{entry[\"HTTPS\"]}{entry[\"Path\"]}/')
|
||||
break
|
||||
except: pass
|
||||
" 2>/dev/null)
|
||||
echo "Tailscale: AKTIV — ${ts_url:-URL nicht extrahierbar}"
|
||||
else
|
||||
echo "Tailscale: nicht aktiv für Port $HERMES_WIKI_PORT (HERMES_WIKI_TS=$HERMES_WIKI_TS)"
|
||||
fi
|
||||
else
|
||||
echo "Tailscale: nicht verfügbar oder deaktiviert"
|
||||
fi
|
||||
else
|
||||
echo "Status: NOT RUNNING"
|
||||
fi
|
||||
}
|
||||
|
||||
show_help() {
|
||||
cat <<EOF
|
||||
hermes-wiki-serve.sh — Hermes Wiki via obsidian-web-viewer + Tailscale
|
||||
|
||||
Dieses Skript wrapper't DanielCheer/obsidian-web-viewer (3D-Graph, File-Tree,
|
||||
WikiLink-Navigation, Volltext-Suche, Catppuccin-Theme) und integriert Tailscale
|
||||
serve für Tailnet-Zugriff.
|
||||
|
||||
Verwendung:
|
||||
$0 start # Server starten (klont obv beim ersten Mal)
|
||||
$0 stop # Server stoppen
|
||||
$0 restart # stop + start
|
||||
$0 status # Process-Status, Health-Check, Tailscale-URL
|
||||
$0 logs # tail -f der Log-Files
|
||||
$0 install # nur das Clonen/Update, kein Server-Start
|
||||
$0 --help
|
||||
|
||||
Umgebungsvariablen:
|
||||
HERMES_WIKI_PORT=8765
|
||||
HERMES_WIKI_DIR=/home/admin/my-karpathy-wiki
|
||||
HERMES_WIKI_LOG_DIR=\$HOME/.local/share/hermes-wiki/log
|
||||
HERMES_WIKI_TS=auto auto|yes|no
|
||||
HERMES_WIKI_TS_PATH=/wiki URL-Pfad unter dem Tailscale
|
||||
HERMES_WIKI_OWV_DIR=\$HOME/.local/share/hermes-wiki/owv
|
||||
|
||||
Dependencies (einmalig):
|
||||
- python3 (stdlib)
|
||||
- git
|
||||
- pip install PyYAML (optional, für sauberes Frontmatter)
|
||||
- tailscale (für Tailnet-Zugriff)
|
||||
|
||||
Zugriff:
|
||||
- Lokal: http://127.0.0.1:8765/
|
||||
- Tailnet: https://<hostname>.<tailnet>.ts.net/wiki/
|
||||
- API: http://127.0.0.1:8765/api/vault/{tree,graph,search,file/<path>}
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Main
|
||||
# ---------------------------------------------------------------------------
|
||||
case "${1:-}" in
|
||||
start) start_server ;;
|
||||
stop) stop_server ;;
|
||||
restart) stop_server; start_server ;;
|
||||
status) show_status ;;
|
||||
logs) tail -f "$HERMES_WIKI_LOG_DIR"/*.log 2>/dev/null || die "Keine Logs gefunden" ;;
|
||||
install) ensure_dirs; require_tools; install_repo ;;
|
||||
--help|-h|help|"") show_help ;;
|
||||
*) die "Unbekanntes Kommando: $1 (--help für Hilfe)" ;;
|
||||
esac
|
||||
Reference in New Issue
Block a user