Renames the app/ingest/ package to app/glean/ and updates all references across Python modules, shell scripts, Vue components, tests, and documentation. Intentionally preserved: - SQLite column name ingest_time (avoids schema migration) - RetrievedEntry.ingest_time field (maps to the column above) - Any public-facing JSON keys that reference ingest_time Changes by category: - app/ingest/ → app/glean/ (full package move, all parsers) - app/tasks/ingest_scheduler.py → app/tasks/glean_scheduler.py - scripts/ingest_corpus.py → scripts/glean_corpus.py - tests/test_ingest_*.py → tests/test_glean_*.py - Docstrings, log messages, comments: ingest → glean - Env var: TURNSTONE_INGEST_INTERVAL → TURNSTONE_GLEAN_INTERVAL - Shell scripts: glean.log, glean_corpus.py references - README.md: multi-source ingest → multi-source glean - .env.example: updated env var name - patterns/: new diagnostic patterns from 2026-05-20 SSH incident (service_crash_loop, pkg_daemon_restart, ssh_forward_conflict) - SourcesView.vue: pipeline label updated - All test import paths updated to app.glean.* 285 tests passing.
149 lines
6.7 KiB
Bash
Executable file
149 lines
6.7 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 — glean 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
|
|
#
|
|
# ── Gleaning logs ─────────────────────────────────────────────────────────────
|
|
# All service logs under /opt are accessible inside the container.
|
|
# Sources are configured in patterns/sources.yaml (bind-mounted at /patterns/).
|
|
#
|
|
# To glean all sources (run manually or via cron):
|
|
#
|
|
# sudo podman exec turnstone python scripts/glean_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/glean_corpus.py \
|
|
# --sources /patterns/sources.yaml --db /data/turnstone.db >> /var/log/turnstone-glean.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
|
|
#
|
|
# ── Orchard submission (opt-in telemetry) ────────────────────────────────────
|
|
# Set TURNSTONE_SUBMIT_ENDPOINT to push pattern-matched log entries to a CF
|
|
# receiving instance after each glean run. Only matched entries are sent —
|
|
# no raw log content. Used to build Avocet training data.
|
|
#
|
|
# export TURNSTONE_SUBMIT_ENDPOINT=https://harvest.circuitforge.tech/contrib2
|
|
# 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.
|
|
# Run this script after every `git pull` to rebuild and redeploy.
|
|
#
|
|
# /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.
|
|
#
|
|
|
|
# Build image from current source (bakes app/ code into the image)
|
|
echo "Building Turnstone image..."
|
|
podman build -t localhost/turnstone:latest "${REPO_DIR}"
|
|
|
|
# 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 TURNSTONE_SUBMIT_ENDPOINT="${TURNSTONE_SUBMIT_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 ""
|
|
|
|
# Regenerate systemd unit so it references the freshly-built image.
|
|
# The --new flag means systemd re-creates the container on each start
|
|
# rather than binding to a specific container ID.
|
|
if [ -d /etc/systemd/system ]; then
|
|
echo "Regenerating systemd unit..."
|
|
podman generate systemd --new --name turnstone \
|
|
| tee /etc/systemd/system/turnstone.service > /dev/null
|
|
systemctl daemon-reload
|
|
systemctl enable turnstone.service 2>/dev/null || true
|
|
echo " systemd unit updated — run: sudo systemctl restart turnstone.service"
|
|
echo ""
|
|
fi
|
|
|
|
echo "Check container health with:"
|
|
echo " sudo podman ps"
|
|
echo " sudo podman logs turnstone"
|
|
echo ""
|
|
echo "To glean all sources now:"
|
|
echo " sudo podman exec turnstone python scripts/glean_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."
|