feat: Podman container deployment for Xander's system
- Dockerfile: multi-stage build (node:22-alpine builds Vue SPA, python:3.12-slim runs uvicorn) — no Node.js required on the host - requirements.txt: minimal runtime deps (fastapi, uvicorn, pyyaml, aiofiles, pydantic, python-multipart) - podman-standalone.sh: mirrors Peregrine's deployment pattern; binds /opt/turnstone/data + /opt/turnstone/patterns + /opt/qbittorrent/config/data/logs (ro); includes cron and Caddy config instructions in comments - .gitignore: add log/, .turnstone-api.pid (generated by manage.sh dev mode)
This commit is contained in:
parent
fa4d23dd20
commit
ec62b47de2
4 changed files with 153 additions and 0 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -1,5 +1,6 @@
|
||||||
data/
|
data/
|
||||||
corpus/raw/
|
corpus/raw/
|
||||||
|
log/
|
||||||
__pycache__/
|
__pycache__/
|
||||||
*.pyc
|
*.pyc
|
||||||
*.pyo
|
*.pyo
|
||||||
|
|
@ -8,5 +9,6 @@ __pycache__/
|
||||||
*.db
|
*.db
|
||||||
*.db-wal
|
*.db-wal
|
||||||
*.db-shm
|
*.db-shm
|
||||||
|
.turnstone-api.pid
|
||||||
web/node_modules/
|
web/node_modules/
|
||||||
web/dist/
|
web/dist/
|
||||||
|
|
|
||||||
36
Dockerfile
Normal file
36
Dockerfile
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
# ── Stage 1: Build Vue SPA ────────────────────────────────────────────────────
|
||||||
|
FROM node:22-alpine AS web-builder
|
||||||
|
WORKDIR /web
|
||||||
|
COPY web/package.json web/package-lock.json ./
|
||||||
|
RUN npm ci
|
||||||
|
COPY web/ ./
|
||||||
|
RUN npm run build
|
||||||
|
|
||||||
|
# ── Stage 2: Python runtime ───────────────────────────────────────────────────
|
||||||
|
FROM python:3.12-slim
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
|
curl \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
COPY requirements.txt .
|
||||||
|
RUN pip install --no-cache-dir -r requirements.txt
|
||||||
|
|
||||||
|
COPY app/ ./app/
|
||||||
|
COPY patterns/ ./patterns/
|
||||||
|
COPY scripts/ ./scripts/
|
||||||
|
COPY --from=web-builder /web/dist ./web/dist
|
||||||
|
|
||||||
|
# Volume mount points — override at runtime:
|
||||||
|
# /data/ → TURNSTONE_DB=/data/turnstone.db (read-write)
|
||||||
|
# /patterns/ → custom pattern YAML files (read-write)
|
||||||
|
# /logs/ → host log directories (read-only)
|
||||||
|
ENV TURNSTONE_DB=/data/turnstone.db
|
||||||
|
|
||||||
|
EXPOSE 8534
|
||||||
|
|
||||||
|
HEALTHCHECK --interval=30s --timeout=10s --start-period=20s --retries=3 \
|
||||||
|
CMD curl -f http://localhost:8534/turnstone/health || exit 1
|
||||||
|
|
||||||
|
CMD ["uvicorn", "app.rest:app", "--host", "0.0.0.0", "--port", "8534"]
|
||||||
109
podman-standalone.sh
Executable file
109
podman-standalone.sh
Executable file
|
|
@ -0,0 +1,109 @@
|
||||||
|
#!/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 custom patterns directories:
|
||||||
|
# mkdir -p /opt/turnstone/{data,patterns}
|
||||||
|
# # Optionally copy default patterns as a starting point:
|
||||||
|
# cp /opt/turnstone/patterns/default.yaml /opt/turnstone/patterns/
|
||||||
|
#
|
||||||
|
# 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 ────────────────────────────────────────────────────────────
|
||||||
|
# Log files on the host are bind-mounted read-only under /logs/ in the
|
||||||
|
# container. To ingest (run manually or via cron):
|
||||||
|
#
|
||||||
|
# podman exec turnstone python scripts/ingest_corpus.py \
|
||||||
|
# /logs/qbittorrent/qbittorrent.log /data/turnstone.db
|
||||||
|
#
|
||||||
|
# Example cron (every 15 minutes):
|
||||||
|
# */15 * * * * podman exec turnstone python scripts/ingest_corpus.py \
|
||||||
|
# /logs/qbittorrent/qbittorrent.log /data/turnstone.db >> /var/log/turnstone-ingest.log 2>&1
|
||||||
|
#
|
||||||
|
# ── Adding Caddy reverse proxy ────────────────────────────────────────────────
|
||||||
|
# Add to /etc/caddy/Caddyfile:
|
||||||
|
#
|
||||||
|
# turnstone.xanderland.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
|
||||||
|
|
||||||
|
# ── Log source bind mounts ────────────────────────────────────────────────────
|
||||||
|
# Add or remove mount flags below for each service whose logs you want to ingest.
|
||||||
|
# Inside the container, paths appear under /logs/<service>/
|
||||||
|
#
|
||||||
|
QBIT_LOGS=/opt/qbittorrent/config/data/logs
|
||||||
|
|
||||||
|
# ── Turnstone container ───────────────────────────────────────────────────────
|
||||||
|
# Image is built locally — no registry auto-update label.
|
||||||
|
# To update: podman build -t localhost/turnstone:latest /opt/turnstone
|
||||||
|
# podman restart turnstone
|
||||||
|
#
|
||||||
|
# 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 "${QBIT_LOGS}:/logs/qbittorrent:ro" \
|
||||||
|
-e TURNSTONE_DB=/data/turnstone.db \
|
||||||
|
-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 " podman ps"
|
||||||
|
echo " 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 qBittorrent logs now:"
|
||||||
|
echo " podman exec turnstone python scripts/ingest_corpus.py \\"
|
||||||
|
echo " /logs/qbittorrent/qbittorrent.log /data/turnstone.db"
|
||||||
6
requirements.txt
Normal file
6
requirements.txt
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
fastapi>=0.110.0
|
||||||
|
uvicorn[standard]>=0.27.0
|
||||||
|
pydantic>=2.0.0
|
||||||
|
pyyaml>=6.0
|
||||||
|
aiofiles>=23.0.0
|
||||||
|
python-multipart>=0.0.9
|
||||||
Loading…
Reference in a new issue