Console is live: cloned to /opt/oikos-console, deploy.sh ran clean, webhook secret written to /etc/oikos-console-deploy/secret from the pre-registered SOPS secret (never printed — decrypted and piped straight into the target file in one command), both systemd units enabled and active. Verified locally (127.0.0.1:8091 -> 200) and end-to-end (https://oikos.hubris.network/ -> 302, the Authentik gate firing correctly). Found a real bug during first boot: oikos-console.service's ReadWritePaths listed /opt/homelab-context/signals and .../approvals, but neither existed yet on apps' clone — git doesn't track empty directories, and nothing had ever written a signal/approval from that host. ProtectSystem=strict + a missing ReadWritePaths target is a hard 226/NAMESPACE crash, not a graceful degradation. Fixed two ways: the unit now marks those paths optional (`-` prefix) so a fresh deploy never crash-loops on this again, and deploy.sh now mkdir -p's them explicitly so the console has real write access from the first boot, not just a non-crashing-but-broken start. This is also the first real exercise of the auto-deploy pipeline: this push should land via Gitea webhook 14 -> oikos-console-deploy.service on apps, same as homelab-mcp/secrets-issuance already work. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
57 lines
2.2 KiB
Bash
Executable File
57 lines
2.2 KiB
Bash
Executable File
#!/bin/bash
|
|
# Install/update the Oikos Console on LXC 105 (apps). Idempotent.
|
|
# Triggered by the gitea webhook or run by hand. Mirrors mcp/deploy/deploy.sh.
|
|
set -euo pipefail
|
|
|
|
REPO_DIR=${REPO_DIR:-/opt/oikos-console}
|
|
|
|
cd "$REPO_DIR"
|
|
echo "[deploy] git pull"
|
|
git pull --ff-only
|
|
|
|
echo "[deploy] ensure python venv + deps"
|
|
if [ ! -d "$REPO_DIR/.venv" ]; then
|
|
python3 -m venv "$REPO_DIR/.venv"
|
|
fi
|
|
"$REPO_DIR/.venv/bin/pip" install --quiet --upgrade pip
|
|
"$REPO_DIR/.venv/bin/pip" install --quiet \
|
|
"fastapi==0.139.*" "starlette<1" "jinja2<4" "uvicorn" "python-multipart" pyyaml
|
|
|
|
echo "[deploy] install systemd units"
|
|
install -m 644 oikos/console/deploy/oikos-console.service \
|
|
/etc/systemd/system/oikos-console.service
|
|
install -m 644 oikos/console/deploy/webhook/oikos-console-deploy.service \
|
|
/etc/systemd/system/oikos-console-deploy.service
|
|
|
|
echo "[deploy] context clone check"
|
|
# Reads inventory/signals/ledger/approvals from the same synced clone
|
|
# every client has (see infrastructure/homelab-context.md), NOT from this
|
|
# deploy-only checkout.
|
|
if [ ! -d /opt/homelab-context/.git ]; then
|
|
echo " /opt/homelab-context is not a git clone — run bootstrap.sh first." >&2
|
|
exit 1
|
|
fi
|
|
|
|
# signals/ and approvals/ are untracked-when-empty (git doesn't version
|
|
# empty directories), so a fresh clone won't have them. The systemd unit's
|
|
# ReadWritePaths need these to exist before the process starts (confirmed
|
|
# the hard way on first deploy, 2026-07-06 — a missing dir here is a
|
|
# 226/NAMESPACE crash-loop, not a graceful degradation).
|
|
mkdir -p /opt/homelab-context/signals /opt/homelab-context/approvals
|
|
|
|
systemctl daemon-reload
|
|
if systemctl is-active --quiet oikos-console.service; then
|
|
systemctl restart oikos-console.service
|
|
fi
|
|
if systemctl is-active --quiet oikos-console-deploy.service; then
|
|
systemctl restart oikos-console-deploy.service
|
|
fi
|
|
|
|
echo "[deploy] done"
|
|
echo "First-time enable:"
|
|
echo " systemctl enable --now oikos-console.service oikos-console-deploy.service"
|
|
echo "Webhook first-time setup (generates secret):"
|
|
echo " $REPO_DIR/oikos/console/deploy/webhook/install.sh"
|
|
echo "Caddy route (dtoro/caddy-conf, NOT this repo) still needs adding — see"
|
|
echo " oikos/console/deploy/README.md for the exact snippet."
|