diff --git a/README.md b/README.md index c54092f..1a322a6 100644 --- a/README.md +++ b/README.md @@ -63,6 +63,27 @@ Standardmäßig prüft der Server stündlich auf neue Releases und zeigt einen B Details: [docs/UPDATE.md](docs/UPDATE.md) +## CLI + +Nach Install: `nexredirect ` auf dem Server. + +``` +nexredirect status # Service-Status +nexredirect logs # Logs streamen +nexredirect update [tag] # Update auf neueste / Tag +nexredirect version # current + latest +nexredirect restart # Service-Restart +nexredirect caddy reload # Caddy reload +nexredirect caddy show # Caddyfile dumpen +nexredirect domains # aktive Domains +nexredirect hits [N] # letzte N Hits +nexredirect tokens # API-Token-Liste +nexredirect db # SQLite-Shell +nexredirect backup [path] # DB + Caddyfile sichern +nexredirect uninstall # entfernen (DB bleibt) +nexredirect help +``` + ## Stack - Next.js 15 + TypeScript + TailwindCSS + Radix UI + Recharts diff --git a/bin/nexredirect b/bin/nexredirect new file mode 100755 index 0000000..0a31f1f --- /dev/null +++ b/bin/nexredirect @@ -0,0 +1,152 @@ +#!/usr/bin/env bash +# nexredirect — CLI wrapper for CoreX NexRedirect on the server + +set -euo pipefail + +INSTALL_DIR="${NEXREDIRECT_DIR:-/opt/corex-nexredirect}" +DATA_DIR="${NEXREDIRECT_DATA_DIR:-/var/lib/corex-nexredirect}" +SERVICE_USER="nexredirect" +SERVICE="corex-nexredirect.service" +DB="$DATA_DIR/nexredirect.db" + +require_root() { + if [[ $EUID -ne 0 ]]; then + echo "Bitte mit sudo ausführen: sudo nexredirect $*" >&2 + exit 1 + fi +} + +cmd_help() { + cat </dev/null \ + | grep -m1 '"tag_name"' | sed -E 's/.*"tag_name": *"([^"]+)".*/\1/' || echo "(check failed)" +} + +cmd_caddy() { + case "${1:-}" in + reload) + require_root "caddy reload" + curl -fsS -X POST -H "Content-Type: text/caddyfile" --data-binary @/etc/caddy/Caddyfile http://localhost:2019/load \ + && echo "Caddy reloaded" \ + || systemctl reload caddy + ;; + show|config|"") + cat /etc/caddy/Caddyfile + ;; + *) + echo "Usage: nexredirect caddy [reload|show]" >&2 + exit 1 + ;; + esac +} + +cmd_db() { + command -v sqlite3 >/dev/null || { echo "sqlite3 nicht installiert: apt install -y sqlite3"; exit 1; } + sqlite3 -header -column "$DB" +} + +cmd_domains() { + command -v sqlite3 >/dev/null || { echo "sqlite3 nicht installiert"; exit 1; } + sqlite3 -header -column "$DB" \ + "SELECT id, domain, status, redirect_code AS code, COALESCE(target_url, (SELECT target_url FROM domain_groups g WHERE g.id = d.group_id), '—') AS target FROM domains d ORDER BY created_at DESC;" +} + +cmd_hits() { + command -v sqlite3 >/dev/null || { echo "sqlite3 nicht installiert"; exit 1; } + local n="${1:-20}" + sqlite3 -header -column "$DB" \ + "SELECT datetime(ts/1000,'unixepoch','localtime') AS time, (SELECT domain FROM domains WHERE id = h.domain_id) AS domain, country, substr(path,1,40) AS path FROM hits h ORDER BY ts DESC LIMIT $n;" +} + +cmd_tokens() { + command -v sqlite3 >/dev/null || { echo "sqlite3 nicht installiert"; exit 1; } + sqlite3 -header -column "$DB" \ + "SELECT id, name, scopes, datetime(created_at/1000,'unixepoch','localtime') AS created, CASE WHEN revoked_at IS NULL THEN 'active' ELSE 'revoked' END AS status FROM api_tokens ORDER BY id DESC;" +} + +cmd_backup() { + local target="${1:-/tmp/nexredirect-backup-$(date +%F-%H%M).tar.gz}" + require_root backup + tar -czf "$target" \ + -C / \ + "${DATA_DIR#/}/nexredirect.db" \ + "${DATA_DIR#/}/nexredirect.db-wal" 2>/dev/null \ + "${DATA_DIR#/}/nexredirect.db-shm" 2>/dev/null \ + etc/caddy/Caddyfile 2>/dev/null || true + echo "Backup → $target" + ls -lh "$target" +} + +cmd_uninstall() { + require_root uninstall + read -rp "Wirklich deinstallieren? (DB bleibt erhalten) [y/N] " ans + [[ "$ans" =~ ^[yY]$ ]] || { echo "Abgebrochen."; exit 0; } + systemctl disable --now "$SERVICE" 2>/dev/null || true + rm -f "/etc/systemd/system/$SERVICE" /etc/sudoers.d/corex-nexredirect /usr/local/bin/nexredirect + systemctl daemon-reload + rm -rf "$INSTALL_DIR" + echo "Entfernt. DB bleibt unter $DATA_DIR." +} + +case "${1:-help}" in + status) shift; cmd_status "$@" ;; + start) shift; cmd_start "$@" ;; + stop) shift; cmd_stop "$@" ;; + restart) shift; cmd_restart "$@" ;; + logs) shift; cmd_logs "$@" ;; + update) shift; cmd_update "$@" ;; + version) shift; cmd_version "$@" ;; + caddy) shift; cmd_caddy "$@" ;; + db) shift; cmd_db "$@" ;; + domains) shift; cmd_domains "$@" ;; + hits) shift; cmd_hits "$@" ;; + tokens) shift; cmd_tokens "$@" ;; + backup) shift; cmd_backup "$@" ;; + uninstall) shift; cmd_uninstall "$@" ;; + help|--help|-h) cmd_help ;; + *) echo "Unbekannter Befehl: $1"; echo; cmd_help; exit 1 ;; +esac diff --git a/scripts/install.sh b/scripts/install.sh index f0a5ee1..bc303a5 100755 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -133,6 +133,11 @@ EOF sudo -u "$SERVICE_USER" -H bash -c "cd '$INSTALL_DIR' && NEXREDIRECT_DATA_DIR='$DATA_DIR' SERVER_IP='$SERVER_IP' SERVER_IPV6='$SERVER_IPV6' ./node_modules/.bin/tsx -e \"import('./lib/db').then(({setSetting})=>{if(process.env.SERVER_IP)setSetting('server_ip',process.env.SERVER_IP);if(process.env.SERVER_IPV6)setSetting('server_ipv6',process.env.SERVER_IPV6);})\"" || \ echo " (Server-IP konnte nicht direkt gesetzt werden — manuell via /settings nachholen.)" +echo "==> CLI nach /usr/local/bin/nexredirect verlinken" +ln -sf "$INSTALL_DIR/bin/nexredirect" /usr/local/bin/nexredirect +chmod +x "$INSTALL_DIR/bin/nexredirect" +apt-get install -y -qq sqlite3 >/dev/null 2>&1 || true + systemctl daemon-reload systemctl enable caddy >/dev/null 2>&1 || true systemctl reload caddy 2>/dev/null || systemctl restart caddy @@ -141,6 +146,7 @@ systemctl enable --now corex-nexredirect echo "" echo "==> Fertig!" echo "" -echo " Setup unter: http://${SERVER_IP}/setup" -echo " Logs: journalctl -u corex-nexredirect -f" +echo " Setup unter: http://${SERVER_IP}/setup" +echo " CLI: nexredirect help" +echo " Logs: nexredirect logs" echo ""