#!/bin/bash # ============================================================================================== # ================================= Unraid API Key Renewal ==================================== # ============================================================================================== # # PURPOSE # ───────────────────────────────────────────────────────────────────────────── # Creates/overwrites the Varaverk API key in the unraid-api service registry at # array start. The registry is ephemeral — OS updates and service restarts clear # it. This script re-registers the key every boot so Varaverk's enhanced # monitoring self-heals without manual intervention. # # Also updates HOST*_UNRAID_API_KEY in the local host conf so the partnership # page always reflects the live key value. # # ============================================================================================== # RUNTIME MODES # ============================================================================================== # # unraid_api_key_renew.sh # Renew the key. Silent on success. # # unraid_api_key_renew.sh --dry-run # Show what would happen — no changes made. # # unraid_api_key_renew.sh --log # Verbose output. # # ============================================================================================== SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" source "$SCRIPT_DIR/../load_config.sh" parse_args "$@" acquire_lock detect_hosts # ────────────────────────────────────────────────────────────────────────────── CONF_FILE="$SCRIPT_DIR/../Configurations/${MY_ID,,}.conf" VAR_NAME="${MY_ID}_UNRAID_API_KEY" # Key name: "Varaverk " stripping any unraid- prefix # Space separator — unRAID API only allows letters, numbers, and spaces HOSTNAME_SUFFIX=$(hostname -s 2>/dev/null | sed 's/^[Uu][Nn][Rr][Aa][Ii][Dd]-//' || hostname -s) KEY_NAME="Varaverk ${HOSTNAME_SUFFIX}" log "$ICON_GEAR Conf file: $CONF_FILE" log "$ICON_GEAR Key var: $VAR_NAME" log "$ICON_GEAR Key name: $KEY_NAME" if [[ ! -f "$CONF_FILE" ]]; then error "Conf file not found: $CONF_FILE" exit 1 fi if [[ "$DRY_RUN" == true ]]; then warn "DRY RUN — would check registry for $KEY_NAME, renew only if missing" exit 0 fi # ────────────────────────────────────────────────────────────────────────────── # Check if key already exists in the unraid-api registry before creating. # --overwrite generates a new key value every time, invalidating the old one. # Only renew if the registry has lost it. log "Checking unraid-api registry for $KEY_NAME..." EXISTING=$(timeout 5 /usr/local/sbin/unraid-api apikey --name "$KEY_NAME" --json /dev/null) KEY=$(echo "$EXISTING" | jq -r '.key // empty' 2>/dev/null) if [[ -n "$KEY" ]]; then PREVIEW="${KEY:0:8}...${KEY: -4}" echo "API key valid ✅ — $VAR_NAME = $PREVIEW" log "Key found in registry — no renewal needed" exit 0 fi log "Key not found in registry — creating new key..." RAW=$(timeout 10 /usr/local/sbin/unraid-api apikey \ --name "$KEY_NAME" --create --overwrite \ --description "Varaverk plugin" --roles ADMIN --json &1) if [[ -z "$RAW" ]]; then error "unraid-api returned no output" exit 1 fi KEY=$(echo "$RAW" | jq -r '.key // empty' 2>/dev/null) if [[ -z "$KEY" ]]; then error "No key in unraid-api response: ${RAW:0:200}" exit 1 fi # ────────────────────────────────────────────────────────────────────────────── if grep -q "^\s*${VAR_NAME}\s*=" "$CONF_FILE"; then sed -i "s|^\(\s*${VAR_NAME}\s*=\s*\)\"[^\"]*\"|\1\"${KEY}\"|" "$CONF_FILE" else echo " ${VAR_NAME}=\"${KEY}\"" >> "$CONF_FILE" fi PREVIEW="${KEY:0:8}...${KEY: -4}" log "Writing new key to: $CONF_FILE" warn "API key renewed ✅ — $VAR_NAME = $PREVIEW (registry had lost it)" # ── Push renewed key into each partner's OWN conf ───────────────────────────── # Each host's conf is its complete keychest — no cross-host conf files needed. # SSH_KEY is set by detect_hosts() — this server's outbound private key. if [[ -z "$SSH_KEY" ]]; then log "No SSH key configured — skipping partner push" exit 0 fi for host_var in $(compgen -v | grep -E '^HOST[0-9]+$'); do partner_host="${!host_var}" [[ -z "$partner_host" ]] && continue [[ "${host_var,,}" == "${MY_ID,,}" ]] && continue partner_slot="${host_var,,}" # e.g. host2 partner_ip=$(resolve_tailscale_ip "$partner_host" 2>/dev/null || true) [[ -z "$partner_ip" ]] && { log "Cannot resolve IP for $partner_host — skipping"; continue; } # Target is the partner's OWN conf on their machine partner_conf="/boot/config/plugins/varaverk/Configurations/${partner_slot}.conf" tmp=$(mktemp /tmp/vv_kp_XXXXXX.sh) remote="/tmp/vv_kp_${RANDOM}.sh" chmod 700 "$tmp" # Key stays in the temp file — never appears in SSH command args cat > "$tmp" </dev/null; then sed -i 's|^\(\\s*${VAR_NAME}\\s*=\\s*\)"[^"]*"|\1"${KEY}"|' "\$target" else printf ' ${VAR_NAME}="%s"\n' '${KEY}' >> "\$target" fi echo ok PUSHSCRIPT if timeout 10 scp -i "$SSH_KEY" -o ConnectTimeout=10 -o BatchMode=yes \ -o StrictHostKeyChecking=no "$tmp" "root@${partner_ip}:${remote}" 2>/dev/null; then if timeout 10 ssh -i "$SSH_KEY" -o ConnectTimeout=10 -o BatchMode=yes \ -o StrictHostKeyChecking=no "root@${partner_ip}" \ "bash '${remote}'; rc=\$?; rm -f '${remote}'; exit \$rc" 2>/dev/null | grep -q ok; then log "Key pushed to $partner_host ✅" else warn "Key push to $partner_host failed — they can create their own copy" fi else warn "SCP to $partner_host failed — skipping" fi rm -f "$tmp" done