turnstone/podman-standalone.sh
pyr0ball f46aba8165 feat: multi-source ingest via sources.yaml + servarr parser
- Add servarr.py parser for all *arr services (sonarr/radarr/lidarr/
  prowlarr/readarr/whisparr/bazarr) — pipe-delimited format with
  component prefix prepended for searchability
- Add ingest_sources() to pipeline.py; reads sources.yaml, skips
  missing paths with a warning so cron keeps running if a service
  is down
- Add --sources mode to ingest_corpus.py CLI; legacy positional args
  unchanged for backward compat
- Add patterns/sources.yaml with all of Contributor2's discovered service
  log paths (qbit, 7 servarr services, nzbget, tautulli, jellyseerr)
- Replace per-service volume mounts in podman-standalone.sh with
  /opt:/opt:ro + /var/log:/var/log:ro; adding a new source now
  requires only editing sources.yaml — no container restart
2026-05-11 06:26:32 -07:00

128 lines
5.8 KiB
Bash
Executable file

#!/usr/bin/env bash
# podman-standalone.sh — Turnstone rootful Podman setup (no Compose)
#
# For hosts running system Podman (non-rootless) with systemd.
# Turnstone is a diagnostic log intelligence layer — ingest service logs,
# search by symptom, and view incidents in a lightweight web UI.
#
# ── Prerequisites ────────────────────────────────────────────────────────────
# 1. Clone the repo:
# sudo git clone https://git.opensourcesolarpunk.com/Circuit-Forge/turnstone.git /opt/turnstone
# sudo chown -R x:x /opt/turnstone
#
# 2. Build the image (requires Docker or Podman with BuildKit/multi-stage support):
# cd /opt/turnstone && podman build -t localhost/turnstone:latest .
#
# 3. Create data and patterns directories, then copy config files:
# mkdir -p /opt/turnstone/{data,patterns}
# cp /opt/turnstone/patterns/default.yaml /opt/turnstone/patterns/
# cp /opt/turnstone/patterns/sources.yaml /opt/turnstone/patterns/
# # Edit sources.yaml if any paths differ on this host.
#
# 4. Run this script:
# bash /opt/turnstone/podman-standalone.sh
#
# ── After setup — generate systemd unit file ─────────────────────────────────
# sudo podman generate systemd --new --name turnstone \
# | sudo tee /etc/systemd/system/turnstone.service
# sudo systemctl daemon-reload
# sudo systemctl enable --now turnstone
#
# ── Ingesting logs ────────────────────────────────────────────────────────────
# All service logs under /opt are accessible inside the container.
# Sources are configured in patterns/sources.yaml (bind-mounted at /patterns/).
#
# To ingest all sources (run manually or via cron):
#
# sudo podman exec turnstone python scripts/ingest_corpus.py \
# --sources /patterns/sources.yaml --db /data/turnstone.db
#
# Example cron (every 15 minutes, add to root's crontab with: sudo crontab -e):
# */15 * * * * podman exec turnstone python scripts/ingest_corpus.py \
# --sources /patterns/sources.yaml --db /data/turnstone.db >> /var/log/turnstone-ingest.log 2>&1
#
# To add a new log source: edit /opt/turnstone/patterns/sources.yaml — no restart needed.
#
# ── Adding Caddy reverse proxy ────────────────────────────────────────────────
# Add to /etc/caddy/Caddyfile:
#
# turnstone.example-node.tv {
# import protected
# reverse_proxy 10.0.0.10:8534
# import cloudflare
# }
#
# Then: sudo systemctl reload caddy
#
# ── Ports ────────────────────────────────────────────────────────────────────
# Turnstone UI → http://localhost:8534/turnstone/
#
set -euo pipefail
REPO_DIR=/opt/turnstone
DATA_DIR=/opt/turnstone/data
PATTERNS_DIR=/opt/turnstone/patterns
TZ=America/Los_Angeles
# ── Bundle push configuration ────────────────────────────────────────────────
# Set TURNSTONE_BUNDLE_ENDPOINT before running this script to enable the
# "Send Bundle" button in the Incidents UI:
#
# export TURNSTONE_BUNDLE_ENDPOINT=https://turnstone.circuitforge.tech/turnstone/api/bundles
# bash /opt/turnstone/podman-standalone.sh
#
# TURNSTONE_SOURCE_HOST is auto-detected from `hostname` — override if needed.
# ── Turnstone container ───────────────────────────────────────────────────────
# Image is built locally — no registry auto-update label.
# To update: sudo podman build -t localhost/turnstone:latest /opt/turnstone
# sudo podman restart turnstone
#
# /opt is mounted read-only so all service logs under /opt/*/config/logs/ are
# accessible without per-service mounts. Add new sources to patterns/sources.yaml
# — no container restart needed.
#
# Must be run as root (sudo bash podman-standalone.sh) — rootful Podman only.
#
# Remove existing container if present (safe re-run)
podman rm -f turnstone 2>/dev/null || true
podman run -d \
--name=turnstone \
--restart=unless-stopped \
--net=host \
-v "${DATA_DIR}:/data:Z" \
-v "${PATTERNS_DIR}:/patterns:Z" \
-v /opt:/opt:ro \
-v /var/log:/var/log:ro \
-e TURNSTONE_DB=/data/turnstone.db \
-e TURNSTONE_SOURCE_HOST="$(hostname)" \
-e TURNSTONE_BUNDLE_ENDPOINT="${TURNSTONE_BUNDLE_ENDPOINT:-}" \
-e PYTHONUNBUFFERED=1 \
-e TZ="${TZ}" \
--health-cmd="curl -f http://localhost:8534/turnstone/health || exit 1" \
--health-interval=30s \
--health-timeout=10s \
--health-start-period=20s \
--health-retries=3 \
localhost/turnstone:latest
echo ""
echo "Turnstone is starting up."
echo " UI: http://localhost:8534/turnstone/"
echo ""
echo "Check container health with:"
echo " sudo podman ps"
echo " sudo podman logs turnstone"
echo ""
echo "To register as a systemd service:"
echo " sudo podman generate systemd --new --name turnstone \\"
echo " | sudo tee /etc/systemd/system/turnstone.service"
echo " sudo systemctl daemon-reload"
echo " sudo systemctl enable --now turnstone"
echo ""
echo "To ingest all sources now:"
echo " sudo podman exec turnstone python scripts/ingest_corpus.py \\"
echo " --sources /patterns/sources.yaml --db /data/turnstone.db"
echo ""
echo "To add a new source: edit /opt/turnstone/patterns/sources.yaml — no restart needed."