clawdie-ai/docs/internal/scripts/setup-db-jail.sh
Operator & Codex c4239b2b11 Align jail policy and add system update path
---
Build: pass | Tests: pass — 51 passed (3 files)

---
Build: pass | Tests: pass — 2189 passed (648 files)
2026-05-06 09:43:08 +02:00

180 lines
8 KiB
Bash
Executable file

#!/bin/sh
# setup-db-jail.sh — create the ai_brain PostgreSQL jail
#
# Usage: sudo sh docs/internal/scripts/setup-db-jail.sh
#
# Reads .env from the project root. Idempotent — safe to re-run.
# Requires bastille and a bootstrapped FreeBSD release (bastille bootstrap).
#
# What it does:
# 1. Create a thick bastille jail at WARDEN_DB_IP
# 2. Install postgresql18-server + postgresql18-pgvector inside
# 3. Configure PostgreSQL to accept connections from the host subnet
# 4. Create the ai_brain database, user, extensions
# 5. Apply schema migrations from docs/internal/sql/
# 6. Enable jail on boot via sysrc
set -e
# ── Locate project root ───────────────────────────────────────────────────────
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
PROJECT_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)"
cd "${PROJECT_ROOT}"
# ── Read .env ─────────────────────────────────────────────────────────────────
env_get() {
local key="$1" default="$2"
local val
val=$(grep -m1 "^${key}=" .env 2>/dev/null | cut -d= -f2- | sed "s/^['\"]//;s/['\"]$//")
printf '%s' "${val:-$default}"
}
TENANT_ID=$(env_get TENANT_ID "$(env_get AGENT_NAME clawdie)")
SUBNET_BASE=$(env_get AGENT_SUBNET_BASE "$(env_get JAIL_SUBNET_BASE "$(env_get WARDEN_SUBNET_BASE 10.0.0)")")
DB_IP=$(env_get WARDEN_DB_IP "$(env_get DB_JAIL_IP "${SUBNET_BASE}.3")")
JAIL=$(env_get DB_JAIL_NAME "${TENANT_ID}-db")
DB_NAME=$(env_get MEMORY_DB_NAME "${TENANT_ID}_brain")
DB_USER=$(env_get MEMORY_DB_USER "${TENANT_ID}_brain")
DB_PASS=$(env_get MEMORY_DB_PASSWORD "")
FREEBSD_REL=$(freebsd-version -u | cut -d- -f1,2)
PGDATA="/var/db/postgres/data"
JAIL_ROOT="/usr/local/bastille/jails/${JAIL}/root"
SUBNET="${SUBNET_BASE}.0/24"
# ── Validate ──────────────────────────────────────────────────────────────────
if [ -z "${DB_PASS}" ]; then
echo "ERROR: MEMORY_DB_PASSWORD not set in .env" >&2
echo " Add it: echo 'MEMORY_DB_PASSWORD=changeme' >> .env" >&2
exit 1
fi
echo "==> DB jail setup"
echo " Jail: ${JAIL} @ ${DB_IP}"
echo " Release: ${FREEBSD_REL}"
echo " DB: ${DB_NAME} / user: ${DB_USER}"
echo ""
# ── 1. Create jail ────────────────────────────────────────────────────────────
if bastille list 2>/dev/null | grep -qw "${JAIL}"; then
echo "==> Jail ${JAIL} already exists — skipping creation"
else
echo "==> Creating jail ${JAIL}"
bastille create "${JAIL}" "${FREEBSD_REL}" "${DB_IP}"
fi
# PostgreSQL requires System V IPC (shmget). Bastille does not add this
# automatically — it must be in jail.conf or postgres will fail with:
# FATAL: could not create shared memory segment: Function not implemented
JAIL_CONF="/usr/local/bastille/jails/${JAIL}/jail.conf"
if ! grep -q "allow.sysvipc" "${JAIL_CONF}" 2>/dev/null; then
echo "==> Adding allow.sysvipc to jail.conf"
sed -i '' 's/^}/ allow.sysvipc = 1;\n}/' "${JAIL_CONF}"
bastille restart "${JAIL}"
fi
# ── 2. Install packages ───────────────────────────────────────────────────────
echo "==> Installing postgresql18-server postgresql18-contrib postgresql18-pgvector"
bastille pkg "${JAIL}" install -y postgresql18-server postgresql18-contrib postgresql18-pgvector
# ── 3. Init PostgreSQL ────────────────────────────────────────────────────────
# Note: postgres uid is 770 in pkgbase jails (not 70 from older packages).
# If restoring data from an older jail, run:
# chown -R 770:770 ${JAIL_ROOT}${PGDATA}
bastille sysrc "${JAIL}" postgresql_enable=YES
bastille sysrc "${JAIL}" postgresql_data="${PGDATA}"
if bastille cmd "${JAIL}" test -f "${PGDATA}/PG_VERSION" 2>/dev/null; then
echo "==> PostgreSQL already initialized — skipping initdb"
else
echo "==> Initializing PostgreSQL data directory"
bastille service "${JAIL}" postgresql initdb
fi
# ── 4. Configure PostgreSQL ───────────────────────────────────────────────────
echo "==> Configuring postgresql.conf and pg_hba.conf"
PG_CONF="${JAIL_ROOT}${PGDATA}/postgresql.conf"
HBA_CONF="${JAIL_ROOT}${PGDATA}/pg_hba.conf"
# Allow external connections (append wins over commented defaults)
if ! grep -qE "^listen_addresses\s*=" "${PG_CONF}"; then
echo "listen_addresses = '*'" >> "${PG_CONF}"
fi
# Allow all users/databases from the host subnet (covers ai_brain + future CMS DB)
if ! grep -q "^host.*all.*${SUBNET}" "${HBA_CONF}"; then
printf "host\tall\tall\t%s\tscram-sha-256\n" "${SUBNET}" >> "${HBA_CONF}"
fi
# ── 5. Start PostgreSQL ───────────────────────────────────────────────────────
echo "==> Starting PostgreSQL"
if bastille service "${JAIL}" postgresql status 2>/dev/null | grep -q running; then
bastille service "${JAIL}" postgresql reload
else
bastille service "${JAIL}" postgresql start
fi
# ── 6. Create user and database ───────────────────────────────────────────────
echo "==> Creating user '${DB_USER}' and database '${DB_NAME}'"
bastille cmd "${JAIL}" su -l postgres -c "
psql -tc \"SELECT 1 FROM pg_roles WHERE rolname='${DB_USER}'\" | grep -q 1 ||
psql -c \"CREATE USER ${DB_USER} WITH PASSWORD '${DB_PASS}' LOGIN\"
"
bastille cmd "${JAIL}" su -l postgres -c "
psql -tc \"SELECT 1 FROM pg_database WHERE datname='${DB_NAME}'\" | grep -q 1 ||
psql -c \"CREATE DATABASE ${DB_NAME} OWNER ${DB_USER}\"
"
# ── 7. Extensions and schema ──────────────────────────────────────────────────
echo "==> Installing extensions (pgcrypto, vector)"
bastille cmd "${JAIL}" su -l postgres -c "
psql -d ${DB_NAME} -c \"
CREATE EXTENSION IF NOT EXISTS pgcrypto;
CREATE EXTENSION IF NOT EXISTS vector;
\"
"
echo "==> Applying schema migrations"
SQL_TMP="${JAIL_ROOT}/tmp/clawdie-sql"
mkdir -p "${SQL_TMP}"
cp docs/internal/sql/ai-brain-base.sql "${SQL_TMP}/"
cp docs/internal/sql/clawdie-brain-hybrid-upgrade.sql "${SQL_TMP}/"
cp docs/internal/sql/search-memories.sql "${SQL_TMP}/"
cp docs/internal/sql/permissions.sql "${SQL_TMP}/"
bastille cmd "${JAIL}" su -l postgres -c "
psql -d ${DB_NAME} -f /tmp/clawdie-sql/ai-brain-base.sql &&
psql -d ${DB_NAME} -f /tmp/clawdie-sql/clawdie-brain-hybrid-upgrade.sql &&
psql -d ${DB_NAME} -f /tmp/clawdie-sql/search-memories.sql &&
psql -v db_user=${DB_USER} -d ${DB_NAME} -f /tmp/clawdie-sql/permissions.sql
"
rm -rf "${SQL_TMP}"
# ── 8. Enable on boot ─────────────────────────────────────────────────────────
echo "==> Enabling jail on boot"
sysrc jail_list+="${JAIL}"
# ── Done ──────────────────────────────────────────────────────────────────────
echo ""
echo "==> Done."
echo ""
echo " Add to .env if not already present:"
echo " WARDEN_DB_IP=${DB_IP}"
echo " MEMORY_DB_URL=postgresql://${DB_USER}:${DB_PASS}@${DB_IP}:5432/${DB_NAME}"
echo ""
echo " Verify: bastille cmd ${JAIL} su -l postgres -c 'psql -d ${DB_NAME} -c \"\\dt\"'"