#!/usr/bin/env bash
set -euo pipefail
# Run as dmestas (NOT root) — nsc stores creds in ~/.local/share/nats/nsc/
# Requires: nsc on PATH, /etc/nats/ writable by this user (or sudo for final write)
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
CREDS_DIR="${SCRIPT_DIR}/creds"
log() { echo "[bootstrap-creds.sh] $*"; }
die() { echo "[bootstrap-creds.sh] ERROR: $*" >&2; exit 1; }
command -v nsc &>/dev/null || die "nsc not found. Install with: curl -fsSL https://install.nats.io/nsc | sh; export PATH=\${HOME}/.nsc/bin:\${PATH}"
# ── Operator ─────────────────────────────────────────────────────────────────
if nsc list operators 2>/dev/null | grep -q 'fossil-sync'; then
log "Operator fossil-sync already exists, skipping creation."
else
log "Creating operator fossil-sync..."
nsc add operator --name fossil-sync
nsc edit operator --name fossil-sync \
--account-jwt-server-url tls://localhost:4222
fi
# ── Accounts ─────────────────────────────────────────────────────────────────
for ACCOUNT in edgesync go-libfossil; do
if nsc describe account --name "$ACCOUNT" &>/dev/null; then
log "Account $ACCOUNT already exists, skipping."
else
log "Creating account $ACCOUNT..."
nsc add account --name "$ACCOUNT"
fi
done
# ── Users ─────────────────────────────────────────────────────────────────────
# Admin users (local provisioning only — full pub/sub)
for ACCOUNT in edgesync go-libfossil; do
if nsc describe user --account "$ACCOUNT" --name admin &>/dev/null; then
log "User admin in $ACCOUNT already exists, skipping."
else
log "Creating admin user in account $ACCOUNT..."
nsc add user --account "$ACCOUNT" --name admin \
--allow-pub '>' --allow-sub '>'
fi
done
# Bridge users (scoped to project subjects)
if ! nsc describe user --account edgesync --name bridge &>/dev/null; then
nsc add user --account edgesync --name bridge \
--allow-pub 'fossil.edgesync.>' \
--allow-sub 'fossil.edgesync.>'
log "Created bridge user in edgesync."
fi
if ! nsc describe user --account go-libfossil --name bridge &>/dev/null; then
nsc add user --account go-libfossil --name bridge \
--allow-pub 'fossil.go-libfossil.>' \
--allow-sub 'fossil.go-libfossil.>'
log "Created bridge user in go-libfossil."
fi
# ── Generate .creds files ─────────────────────────────────────────────────────
mkdir -p "$CREDS_DIR"
log "Generating .creds files in ${CREDS_DIR}..."
nsc generate creds --account edgesync --name bridge > "${CREDS_DIR}/edgesync-bridge.creds"
nsc generate creds --account go-libfossil --name bridge > "${CREDS_DIR}/go-libfossil-bridge.creds"
nsc generate creds --account edgesync --name admin > "${CREDS_DIR}/edgesync-admin.creds"
nsc generate creds --account go-libfossil --name admin > "${CREDS_DIR}/go-libfossil-admin.creds"
chmod 0600 "${CREDS_DIR}"/*.creds
# ── Extract operator JWT ──────────────────────────────────────────────────────
log "Extracting operator JWT..."
OPERATOR_JWT=$(nsc generate config --nats-resolver 2>/dev/null \
| grep '^operator:' \
| awk '{print $2}')
[[ -n "$OPERATOR_JWT" ]] || die "Failed to extract operator JWT from nsc generate config output."
OPERATOR_ENV=/etc/nats/operator.env
if [[ -w "$(dirname "$OPERATOR_ENV")" ]]; then
echo "OPERATOR_JWT=${OPERATOR_JWT}" > "$OPERATOR_ENV"
chmod 0600 "$OPERATOR_ENV"
log "Wrote OPERATOR_JWT to $OPERATOR_ENV"
else
# /etc/nats may be root-owned; write via sudo
echo "OPERATOR_JWT=${OPERATOR_JWT}" | sudo tee "$OPERATOR_ENV" > /dev/null
sudo chmod 0600 "$OPERATOR_ENV"
log "Wrote OPERATOR_JWT to $OPERATOR_ENV (via sudo)"
fi
log ""
log "Phase 2 complete."
log "Next: sudo bash nats/start.sh"