Add self-hosted RCS backend, extension, and ops tooling

Ship the Go/SQLite API and Web UI, Chrome/Brave capture addon,
Docker Compose, Pangolin reverse-proxy support, and a user-crontab
watchdog so the binary stays running without systemd.
This commit is contained in:
2026-08-06 22:02:45 +02:00
parent 3f05c97e1f
commit 5a0e2e630b
30 changed files with 4334 additions and 2 deletions
+48
View File
@@ -0,0 +1,48 @@
#!/usr/bin/env bash
# Remove local seed/test rows from data/rcs.db; keep real Reddit captures.
set -euo pipefail
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
DB="${RCS_DB_PATH:-$ROOT/data/rcs.db}"
SHOT_DIR="${RCS_DATA_DIR:-$ROOT/data}/screenshots"
if [[ ! -f "$DB" ]]; then
echo "No database at $DB — nothing to prune."
exit 0
fi
before="$(sqlite3 "$DB" 'SELECT COUNT(*) FROM comments;')"
sqlite3 "$DB" <<'SQL'
PRAGMA foreign_keys = ON;
DELETE FROM comments
WHERE reddit_comment_id = 't1_testcomment1'
OR reddit_comment_id LIKE 't1_page_%';
DELETE FROM posts
WHERE reddit_post_id IN ('t3_testpost1', 't3_onlypost', 't3_seedpost');
DELETE FROM users
WHERE reddit_user_id IN ('t2_user1', 't2_op', 't2_a', 't2_seed');
-- Orphan posts with no comments left
DELETE FROM posts
WHERE id NOT IN (SELECT DISTINCT post_id FROM comments);
-- Orphan users not referenced by comments or posts
DELETE FROM users
WHERE id NOT IN (SELECT DISTINCT author_id FROM comments)
AND id NOT IN (SELECT DISTINCT author_id FROM posts);
SQL
rm -f "$SHOT_DIR/t1_testcomment1.png"
after="$(sqlite3 "$DB" 'SELECT COUNT(*) FROM comments;')"
posts="$(sqlite3 "$DB" 'SELECT COUNT(*) FROM posts;')"
users="$(sqlite3 "$DB" 'SELECT COUNT(*) FROM users;')"
echo "Pruned seed/test data from $DB"
echo " comments: $before -> $after"
echo " posts: $posts"
echo " users: $users"
+61
View File
@@ -0,0 +1,61 @@
#!/usr/bin/env bash
# Ensure the RCS backend is running (intended for user crontab every minute).
# Does not rebuild the binary — run `make build` first.
set -euo pipefail
REPO="$(cd "$(dirname "$0")/.." && pwd)"
BIN="${RCS_BIN:-$REPO/bin/rcs}"
DATA_DIR="${RCS_DATA_DIR_OVERRIDE:-$REPO/data}"
PIDFILE="${RCS_PIDFILE:-$DATA_DIR/rcs.pid}"
LOG="${RCS_LOG:-$DATA_DIR/rcs.log}"
ENVFILE="${RCS_ENV_FILE:-$DATA_DIR/rcs.env}"
LOCKFILE="${RCS_LOCKFILE:-$DATA_DIR/rcs.watchdog.lock}"
mkdir -p "$DATA_DIR"
exec 9>"$LOCKFILE"
if ! flock -n 9; then
# Another watchdog instance is starting the process.
exit 0
fi
log_msg() {
local line="[$(date -Iseconds)] $*"
echo "$line" >>"$LOG"
}
if [[ ! -x "$BIN" ]]; then
log_msg "ERROR: binary missing or not executable: $BIN (run: make build)"
echo "rcs-watchdog: binary missing: $BIN" >&2
exit 1
fi
if [[ -f "$PIDFILE" ]]; then
old_pid="$(tr -d '[:space:]' <"$PIDFILE" || true)"
if [[ -n "${old_pid:-}" ]] && kill -0 "$old_pid" 2>/dev/null; then
exit 0
fi
rm -f "$PIDFILE"
fi
# Absolute data dir so cron cwd ($HOME) does not matter.
export RCS_DATA_DIR="$DATA_DIR"
if [[ -f "$ENVFILE" ]]; then
# shellcheck disable=SC1090
set -a
# shellcheck disable=SC1090
source "$ENVFILE"
set +a
# Keep data under the repo unless the env file overrides with an absolute path.
if [[ -z "${RCS_DATA_DIR:-}" || "${RCS_DATA_DIR}" == "data" || "${RCS_DATA_DIR}" == "./data" ]]; then
export RCS_DATA_DIR="$DATA_DIR"
fi
fi
cd "$REPO"
nohup "$BIN" >>"$LOG" 2>&1 &
new_pid=$!
echo "$new_pid" >"$PIDFILE"
log_msg "started $BIN pid=$new_pid"
exit 0