docs(systemd): fix paths + add dashboard smoke + vendor units

This commit is contained in:
2026-05-26 23:47:07 +02:00
parent 83b85cb760
commit 8f47151a48
24 changed files with 236 additions and 11 deletions

View File

@@ -2,16 +2,16 @@
This is the operational quick-reference for the shipped systemd timers/services and the optional FastAPI dashboard backend. This is the operational quick-reference for the shipped systemd timers/services and the optional FastAPI dashboard backend.
Repository root (on host): `/root/.openclaw/workspace` Repository root (on host): `/root/.openclaw/workspace/second-brain`
## Systemd units (cron jobs) ## Systemd units (cron jobs)
Unit files are shipped in `systemd/` (repo root). Install them into `/etc/systemd/system/` (symlink or copy), then reload: Unit files are shipped in `systemd/` (this repo). Install them into `/etc/systemd/system/` (symlink or copy), then reload:
```bash ```bash
sudo ln -sf /root/.openclaw/workspace/systemd/openclaw-secondbrain-*.service /etc/systemd/system/ sudo ln -sf /root/.openclaw/workspace/second-brain/systemd/openclaw-secondbrain-*.service /etc/systemd/system/
sudo ln -sf /root/.openclaw/workspace/systemd/openclaw-secondbrain-*.timer /etc/systemd/system/ sudo ln -sf /root/.openclaw/workspace/second-brain/systemd/openclaw-secondbrain-*.timer /etc/systemd/system/
sudo ln -sf /root/.openclaw/workspace/systemd/openclaw-memory-archive.* /etc/systemd/system/ sudo ln -sf /root/.openclaw/workspace/second-brain/systemd/openclaw-memory-archive.* /etc/systemd/system/
sudo systemctl daemon-reload sudo systemctl daemon-reload
``` ```
@@ -61,7 +61,7 @@ python3 -m pip install -r second-brain/requirements-dashboard.txt
SECOND_BRAIN_WORKSPACE="/root/.openclaw/workspace/second-brain" python3 second-brain/fastapi_app.py SECOND_BRAIN_WORKSPACE="/root/.openclaw/workspace/second-brain" python3 second-brain/fastapi_app.py
``` ```
Default port is `8501` (same as Streamlit default). Do not run both on the same port. Default port is `8501` (same as Streamlit default). You can override via `SECOND_BRAIN_PORT` (or `PORT`) when starting manually.
Endpoint smoke tests: Endpoint smoke tests:

View File

@@ -1,6 +1,6 @@
# Second-Brain 2.0 — Release Checklist (Grundversion + FastAPI) # Second-Brain 2.0 — Release Checklist (Grundversion + FastAPI)
Scope: OpenClaw workspace at `/root/.openclaw/workspace` with `second-brain/` and the shipped `systemd/` unit files. Scope: OpenClaw workspace at `/root/.openclaw/workspace` with `second-brain/` and the shipped `second-brain/systemd/` unit files.
This checklist is copy/paste friendly. Run as a user with `sudo` (systemd commands need it). This checklist is copy/paste friendly. Run as a user with `sudo` (systemd commands need it).
@@ -24,10 +24,10 @@ ls -la /etc/systemd/system/openclaw-memory-archive.* 2>/dev/null || true
If missing, install them (symlink is fine; copy is fine too): If missing, install them (symlink is fine; copy is fine too):
```bash ```bash
sudo ln -sf /root/.openclaw/workspace/systemd/openclaw-secondbrain-*.service /etc/systemd/system/ sudo ln -sf /root/.openclaw/workspace/second-brain/systemd/openclaw-secondbrain-*.service /etc/systemd/system/
sudo ln -sf /root/.openclaw/workspace/systemd/openclaw-secondbrain-*.timer /etc/systemd/system/ sudo ln -sf /root/.openclaw/workspace/second-brain/systemd/openclaw-secondbrain-*.timer /etc/systemd/system/
sudo ln -sf /root/.openclaw/workspace/systemd/openclaw-memory-archive.* /etc/systemd/system/ sudo ln -sf /root/.openclaw/workspace/second-brain/systemd/openclaw-memory-archive.* /etc/systemd/system/
sudo ln -sf /root/.openclaw/workspace/systemd/openclaw-secondbrain-dashboard.service /etc/systemd/system/ sudo ln -sf /root/.openclaw/workspace/second-brain/systemd/openclaw-secondbrain-dashboard.service /etc/systemd/system/
sudo systemctl daemon-reload sudo systemctl daemon-reload
``` ```

20
scripts/smoke_dashboard.sh Executable file
View File

@@ -0,0 +1,20 @@
#!/usr/bin/env bash
set -euo pipefail
HOST="${SECOND_BRAIN_HOST:-127.0.0.1}"
PORT="${SECOND_BRAIN_PORT:-${PORT:-8501}}"
BASE_URL="http://${HOST}:${PORT}"
if command -v systemctl >/dev/null 2>&1; then
if ! systemctl is-active --quiet openclaw-secondbrain-dashboard.service; then
echo "ERROR: openclaw-secondbrain-dashboard.service is not active" >&2
exit 1
fi
fi
curl -fsS "${BASE_URL}/healthz" >/dev/null
stats_json="$(curl -fsS "${BASE_URL}/api/stats")"
python3 -c 'import json,sys; json.load(sys.stdin)' <<<"$stats_json"
echo "OK: dashboard smoke test passed (${BASE_URL})"

View File

@@ -0,0 +1,9 @@
[Unit]
Description=OpenClaw archive memory/*.md older than 7 days
OnFailure=openclaw-secondbrain-notify@%n.service
[Service]
Type=oneshot
WorkingDirectory=/root/.openclaw/workspace
ExecStart=/bin/bash -lc 'flock -n /tmp/%n.lock /usr/bin/python3 /root/.openclaw/workspace/openclaw_cron_wrapper.py archive_memory_md'

View File

@@ -0,0 +1,10 @@
[Unit]
Description=OpenClaw archive memory/*.md daily
[Timer]
OnCalendar=*-*-* 03:30:00
Persistent=true
[Install]
WantedBy=timers.target

View File

@@ -0,0 +1,8 @@
[Unit]
Description=OpenClaw Second-Brain backup_secondbrain
OnFailure=openclaw-secondbrain-notify@%n.service
[Service]
Type=oneshot
WorkingDirectory=/root/.openclaw/workspace
ExecStart=/bin/bash -lc 'flock -n /tmp/%n.lock /usr/bin/python3 /root/.openclaw/workspace/openclaw_cron_wrapper.py backup_secondbrain'

View File

@@ -0,0 +1,10 @@
[Unit]
Description=OpenClaw Second-Brain backup_secondbrain (daily 02:00)
[Timer]
OnCalendar=*-*-* 02:00:00
Persistent=true
[Install]
WantedBy=timers.target

View File

@@ -0,0 +1,15 @@
[Unit]
Description=OpenClaw Second-Brain Dashboard (FastAPI)
After=network.target
[Service]
Type=simple
WorkingDirectory=/root/.openclaw/workspace/second-brain
Environment=SECOND_BRAIN_WORKSPACE=/root/.openclaw/workspace/second-brain
Environment=SECOND_BRAIN_PORT=8501
ExecStart=/root/.openclaw/workspace/second-brain/.venv/bin/uvicorn fastapi_app:app --host 0.0.0.0 --port 8501
Restart=always
RestartSec=2
[Install]
WantedBy=multi-user.target

View File

@@ -0,0 +1,8 @@
[Unit]
Description=OpenClaw Second-Brain export_obsidian
OnFailure=openclaw-secondbrain-notify@%n.service
[Service]
Type=oneshot
WorkingDirectory=/root/.openclaw/workspace
ExecStart=/bin/bash -lc 'flock -n /tmp/%n.lock /usr/bin/python3 /root/.openclaw/workspace/openclaw_cron_wrapper.py export_obsidian'

View File

@@ -0,0 +1,10 @@
[Unit]
Description=OpenClaw Second-Brain export_obsidian (hourly)
[Timer]
OnCalendar=hourly
Persistent=true
[Install]
WantedBy=timers.target

View File

@@ -0,0 +1,8 @@
[Unit]
Description=OpenClaw Second-Brain heartbeat_secondbrain
OnFailure=openclaw-secondbrain-notify@%n.service
[Service]
Type=oneshot
WorkingDirectory=/root/.openclaw/workspace
ExecStart=/bin/bash -lc 'flock -n /tmp/%n.lock /usr/bin/python3 /root/.openclaw/workspace/openclaw_cron_wrapper.py heartbeat_secondbrain'

View File

@@ -0,0 +1,11 @@
[Unit]
Description=OpenClaw Second-Brain heartbeat_secondbrain (every 6h)
[Timer]
OnCalendar=*-*-* 00,06,12,18:00:00
RandomizedDelaySec=300
Persistent=true
[Install]
WantedBy=timers.target

View File

@@ -0,0 +1,10 @@
[Unit]
Description=OpenClaw Second-Brain index_vectors
OnFailure=openclaw-secondbrain-notify@%n.service
[Service]
Type=oneshot
WorkingDirectory=/root/.openclaw/workspace
Environment=HF_HOME=/root/.openclaw/workspace/second-brain/data/hf_cache
Environment=SENTENCE_TRANSFORMERS_HOME=/root/.openclaw/workspace/second-brain/data/st_cache
ExecStart=/bin/bash -lc 'flock -n /tmp/%n.lock /usr/bin/python3 /root/.openclaw/workspace/openclaw_cron_wrapper.py index_vectors'

View File

@@ -0,0 +1,10 @@
[Unit]
Description=OpenClaw Second-Brain index_vectors (every 30 min)
[Timer]
OnCalendar=*:0/30
Persistent=true
[Install]
WantedBy=timers.target

View File

@@ -0,0 +1,8 @@
[Unit]
Description=OpenClaw Second-Brain ingest_memory
OnFailure=openclaw-secondbrain-notify@%n.service
[Service]
Type=oneshot
WorkingDirectory=/root/.openclaw/workspace
ExecStart=/bin/bash -lc 'flock -n /tmp/%n.lock /usr/bin/python3 /root/.openclaw/workspace/openclaw_cron_wrapper.py ingest_memory'

View File

@@ -0,0 +1,10 @@
[Unit]
Description=OpenClaw Second-Brain ingest_memory (every 10 min)
[Timer]
OnCalendar=*:0/10
Persistent=true
[Install]
WantedBy=timers.target

View File

@@ -0,0 +1,8 @@
[Unit]
Description=OpenClaw Second-Brain ingest_obsidian
OnFailure=openclaw-secondbrain-notify@%n.service
[Service]
Type=oneshot
WorkingDirectory=/root/.openclaw/workspace
ExecStart=/bin/bash -lc 'flock -n /tmp/%n.lock /usr/bin/python3 /root/.openclaw/workspace/openclaw_cron_wrapper.py ingest_obsidian'

View File

@@ -0,0 +1,10 @@
[Unit]
Description=OpenClaw Second-Brain ingest_obsidian (every 15 min)
[Timer]
OnCalendar=*:0/15
Persistent=true
[Install]
WantedBy=timers.target

View File

@@ -0,0 +1,8 @@
[Unit]
Description=OpenClaw Second-Brain failure notify (%i)
[Service]
Type=oneshot
WorkingDirectory=/root/.openclaw/workspace
ExecStart=/bin/bash -lc '/root/.openclaw/workspace/notify-telegram.sh "❌ Second-Brain job failed: %i. Check: journalctl -u %i -n 50 --no-pager"'

View File

@@ -0,0 +1,10 @@
[Unit]
Description=OpenClaw Second-Brain proactive_search_wrapper
Wants=network-online.target
After=network-online.target
OnFailure=openclaw-secondbrain-notify@%n.service
[Service]
Type=oneshot
WorkingDirectory=/root/.openclaw/workspace
ExecStart=/bin/bash -lc 'flock -n /tmp/%n.lock /usr/bin/python3 /root/.openclaw/workspace/openclaw_cron_wrapper.py proactive_search_wrapper'

View File

@@ -0,0 +1,11 @@
[Unit]
Description=OpenClaw Second-Brain proactive_search_wrapper (every 4h)
[Timer]
OnCalendar=*-*-* 01,05,09,13,17,21:10:00
RandomizedDelaySec=600
Persistent=true
[Install]
WantedBy=timers.target

View File

@@ -0,0 +1,8 @@
[Unit]
Description=OpenClaw Second-Brain review_brain
OnFailure=openclaw-secondbrain-notify@%n.service
[Service]
Type=oneshot
WorkingDirectory=/root/.openclaw/workspace
ExecStart=/bin/bash -lc 'flock -n /tmp/%n.lock /usr/bin/python3 /root/.openclaw/workspace/openclaw_cron_wrapper.py review_brain'

View File

@@ -0,0 +1,10 @@
[Unit]
Description=OpenClaw Second-Brain review_brain (every 30 min)
[Timer]
OnCalendar=*:0/30
Persistent=true
[Install]
WantedBy=timers.target

View File

@@ -0,0 +1,13 @@
[Unit]
Description=OpenClaw Second-Brain task (%i)
Wants=network-online.target
After=network-online.target
[Service]
Type=oneshot
WorkingDirectory=/root/.openclaw/workspace
ExecStart=/usr/bin/python3 /root/.openclaw/workspace/openclaw_cron_wrapper.py %i
Nice=10
IOSchedulingClass=best-effort
IOSchedulingPriority=6