#!/bin/bash
# n-OS-tr first-boot provisioning.
# Runs once per boot-without-persistence. Generates per-node secrets
# and writes them to /var/lib/n-os-tr/ where the service units read them.

set -euo pipefail

STATE=/var/lib/n-os-tr
KEYS=$STATE/keys
ENVFILE=$STATE/env
TLS_DIR=/etc/ssl/n-os-tr
BLOBS=/var/www/blobs
GINXSOM_DB=/var/lib/ginxsom

log() { echo "[firstboot] $*"; }

mkdir -p "$STATE" "$KEYS" "$TLS_DIR" "$BLOBS" "$GINXSOM_DB"
chmod 0700 "$KEYS"
chmod 0755 "$BLOBS" "$GINXSOM_DB"

# ---------------------------------------------------------------------------
# 1. Ginxsom server keypair.
# We use nak (pre-shipped at /usr/local/bin/nak) to generate and decode.
# ---------------------------------------------------------------------------
if [[ ! -f "$KEYS/ginxsom.nsec" ]]; then
    log "Generating ginxsom server keypair"
    /usr/local/bin/nak key generate > "$KEYS/ginxsom.nsec"
    chmod 0400 "$KEYS/ginxsom.nsec"
fi

GINXSOM_SECRET=$(tr -d '[:space:]' < "$KEYS/ginxsom.nsec")

# nak key generate currently emits raw hex, but we also accept bech32 nsec.
case "$GINXSOM_SECRET" in
    nsec1*)
        GINXSOM_SERVER_PRIVKEY=$(/usr/local/bin/nak decode "$GINXSOM_SECRET" | jq -r .private_key)
        ;;
    *)
        GINXSOM_SERVER_PRIVKEY="$GINXSOM_SECRET"
        ;;
esac

GINXSOM_SERVER_PUBKEY=$(/usr/local/bin/nak key public "$GINXSOM_SERVER_PRIVKEY" | tr -d '[:space:]')

# The admin pubkey for this build is the same as the server pubkey.
# This is a simplification for Slice A (every node is its own admin).
# Slice C (c-relay) will introduce a separate admin keypair.
GINXSOM_ADMIN_PUBKEY=$GINXSOM_SERVER_PUBKEY

log "ginxsom server pubkey (hex): $GINXSOM_SERVER_PUBKEY"

# ---------------------------------------------------------------------------
# 2. Self-signed TLS cert.
# ---------------------------------------------------------------------------
if [[ ! -f "$TLS_DIR/fullchain.pem" ]]; then
    log "Generating self-signed TLS certificate"
    HN=$(hostname)
    openssl req -x509 -newkey rsa:2048 -nodes -days 3650 \
        -subj "/CN=$HN" \
        -addext "subjectAltName=DNS:$HN,DNS:localhost,IP:127.0.0.1,IP:::1" \
        -keyout "$TLS_DIR/privkey.pem" \
        -out   "$TLS_DIR/fullchain.pem" >/dev/null 2>&1
    chmod 0640 "$TLS_DIR/privkey.pem"
    chmod 0644 "$TLS_DIR/fullchain.pem"
    chown root:www-data "$TLS_DIR/privkey.pem"
fi

# ---------------------------------------------------------------------------
# 3. Write environment file consumed by ginxsom.service.
# ---------------------------------------------------------------------------
log "Writing $ENVFILE"
umask 077
cat > "$ENVFILE" <<EOKEY
GINXSOM_SERVER_PRIVKEY=$GINXSOM_SERVER_PRIVKEY
GINXSOM_ADMIN_PUBKEY=$GINXSOM_ADMIN_PUBKEY
EOKEY
chmod 0440 "$ENVFILE"
chown root:www-data "$ENVFILE"

# ---------------------------------------------------------------------------
# 4. Configure fips ethernet interface (required by current fips schema).
# ---------------------------------------------------------------------------
FIPS_CFG=/etc/fips/fips.yaml
if [[ -f "$FIPS_CFG" ]] && grep -q "__FIPS_ETH_IFACE__" "$FIPS_CFG"; then
    FIPS_ETH_IFACE=$(ip -o link show | awk -F': ' '$2 != "lo" {name=$2; sub(/@.*/, "", name); print name; exit}')
    if [[ -z "${FIPS_ETH_IFACE:-}" ]]; then
        log "No non-loopback network interface found for fips ethernet transport"
        exit 1
    fi
    log "Configuring fips ethernet interface: $FIPS_ETH_IFACE"
    sed -i "s/__FIPS_ETH_IFACE__/$FIPS_ETH_IFACE/g" "$FIPS_CFG"
fi

# ---------------------------------------------------------------------------
# 5. Ownership of runtime directories ginxsom will write to.
# ---------------------------------------------------------------------------
chown -R www-data:www-data "$BLOBS" "$GINXSOM_DB"

# ---------------------------------------------------------------------------
# 6. Update the MOTD with the generated identity so the user can find it.
# ---------------------------------------------------------------------------
cat > /etc/motd <<EOMOTD

  n-OS-tr — Nostr-addressed mesh node (preview)

  Blossom (ginxsom) server pubkey (hex):
      $GINXSOM_SERVER_PUBKEY
      retrieve nsec: cat /var/lib/n-os-tr/keys/ginxsom.nsec

  c-relay Nostr relay:
      wss://$(hostname)/relay    (admin nsec: journalctl -u c-relay | grep 'Admin Private Key')
      https://$(hostname)/admin/ (web admin/API)

  fips mesh daemon:
      fipsctl identity           (show npub)
      fipsctl peers              (list peers)

  Service status:          systemctl status fips-dns ginxsom c-relay nginx n-os-tr-firstboot
  Quick health check:      n-os-tr-smoketest

  Identity is ephemeral unless you use a persistence partition or
  install to disk. See /usr/share/doc/n-os-tr/README for details.

EOMOTD

# ---------------------------------------------------------------------------
# 7. Marker so systemd's ConditionPathExists= skips us on subsequent boots.
# ---------------------------------------------------------------------------
touch "$STATE/.provisioned"
log "First-boot provisioning complete."
