#!/usr/bin/env bash
set -euo pipefail
# Run as root (needs systemctl enable/start)
OPERATOR_ENV=/etc/nats/operator.env
CONF_TEMPLATE=/etc/nats/nats-server.conf.template
CONF_LIVE=/etc/nats/nats-server.conf
log() { echo "[start.sh] $*"; }
die() { echo "[start.sh] ERROR: $*" >&2; exit 1; }
[[ -f "$OPERATOR_ENV" ]] || die "Missing $OPERATOR_ENV — run bootstrap-creds.sh first."
[[ -f "$CONF_TEMPLATE" ]] || die "Missing $CONF_TEMPLATE — run install.sh first."
command -v envsubst &>/dev/null || die "envsubst not found (install gettext: apt-get install -y gettext-base)"
# ── Render config from template ───────────────────────────────────────────────
# shellcheck source=/dev/null
source "$OPERATOR_ENV"
export OPERATOR_JWT
[[ -n "${OPERATOR_JWT:-}" ]] || die "OPERATOR_JWT is empty in $OPERATOR_ENV"
# Extract SYS account public key from nsc store
NSC_STORE="/home/dmestas/.local/share/nats/nsc/stores/fossil-sync/accounts"
SYS_JWT="${NSC_STORE}/SYS/SYS.jwt"
[[ -f "$SYS_JWT" ]] || die "Missing SYS account JWT at $SYS_JWT — run bootstrap-creds.sh first."
export SYS_ACCOUNT_KEY
SYS_ACCOUNT_KEY=$(python3 -c "
import base64, json, sys
jwt = open('${SYS_JWT}').read().strip()
parts = jwt.split('.')
payload = parts[1] + '=' * (-len(parts[1]) % 4)
print(json.loads(base64.urlsafe_b64decode(payload))['sub'])
")
[[ -n "${SYS_ACCOUNT_KEY:-}" ]] || die "Could not extract SYS account public key."
envsubst '$OPERATOR_JWT $SYS_ACCOUNT_KEY' < "$CONF_TEMPLATE" > "$CONF_LIVE"
log "Rendered $CONF_TEMPLATE → $CONF_LIVE"
# ── Enable and start nats ─────────────────────────────────────────────────────
systemctl enable --now nats
log "nats service enabled and started."
# ── Wait for server to be ready ───────────────────────────────────────────────
log "Waiting for NATS to accept connections..."
for i in $(seq 1 10); do
if ss -tlnp | grep -q ':4222'; then
log "Port 4222 is listening."
break
fi
sleep 1
[[ "$i" -eq 10 ]] && die "NATS did not start in 10 seconds. Check: journalctl -u nats -n 50"
done
# ── Copy account JWTs to resolver dir ────────────────────────────────────────
# The full/dir resolver reads JWTs from /var/nats/jwt/ on startup.
# We copy account JWTs (not user JWTs) from the nsc store.
NSC_STORE="/home/dmestas/.local/share/nats/nsc/stores/fossil-sync/accounts"
JWT_DIR=/var/nats/jwt
log "Copying account JWTs to resolver dir..."
for ACCOUNT in SYS edgesync go-libfossil; do
SRC="${NSC_STORE}/${ACCOUNT}/${ACCOUNT}.jwt"
[[ -f "$SRC" ]] || die "Missing account JWT: $SRC — run bootstrap-creds.sh first."
# Filename must be the account public key (extract from JWT payload)
PUBKEY=$(python3 -c "import base64,json,sys; d=open(sys.argv[1]).read().strip().split('.')[1]; d+='='*(-len(d)%4); print(json.loads(base64.urlsafe_b64decode(d))['sub'])" "$SRC")
cp "$SRC" "${JWT_DIR}/${PUBKEY}.jwt"
chown nats:nats "${JWT_DIR}/${PUBKEY}.jwt"
log " Copied ${ACCOUNT} → ${JWT_DIR}/${PUBKEY}.jwt"
done
# Restart NATS to pick up the new account JWTs from the resolver dir.
# SIGHUP only reloads TLS certs; a full restart is needed for account JWT changes.
systemctl restart nats
log "Restarted nats to apply account JWT updates."
log ""
log "Phase 3 complete."
log "Next: bash nats/provision-streams.sh"