#!/bin/bash # ============================================================================================== # ================================= Unraid API Key Renewal ==================================== # ============================================================================================== # # PURPOSE # ───────────────────────────────────────────────────────────────────────────── # Creates/syncs the Varaverk API key in the Unraid registry. The registry is # ephemeral — OS updates and service restarts clear it. This script re-registers # every boot so monitoring self-heals without manual intervention. # # Each host's key is named "Varaverk_HOST1", "Varaverk_HOST2", etc., and stored # in master.conf (shared) so all hosts can call each other's GraphQL API directly # for real-time monitoring without SSH. # # --all-hosts also SSHes to each partner, creates their key there, and writes # all keys into master.conf. Run once from Settings → API Key → Setup # to fully wire cross-host API access. # # ============================================================================================== # RUNTIME MODES # ============================================================================================== # # unraid_api_key_renew.sh # Renew local key only — runs at array start, fast. # # unraid_api_key_renew.sh --all-hosts # Renew local key AND SSH to each partner to create/sync their key. # Writes all keys into master.conf and pushes to partners. # # unraid_api_key_renew.sh --dry-run # unraid_api_key_renew.sh --log # # ============================================================================================== SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" source "$SCRIPT_DIR/../load_config.sh" parse_args "$@" acquire_lock detect_hosts # ────────────────────────────────────────────────────────────────────────────── # Parse --all-hosts from raw args (parse_args doesn't handle this flag) ALL_HOSTS=false for _arg in "$@"; do [[ "$_arg" == "--all-hosts" ]] && ALL_HOSTS=true; done unset _arg CONF_FILE="$SCRIPT_DIR/../Configurations/${MY_ID,,}.conf" MASTER_CONF="$SCRIPT_DIR/../Configurations/master.conf" VAR_NAME="${MY_ID}_UNRAID_API_KEY" KEY_NAME="Varaverk_${MY_ID}" log "$ICON_GEAR Conf file: $CONF_FILE" log "$ICON_GEAR Key name: $KEY_NAME" log "$ICON_GEAR Key var: $VAR_NAME" log "$ICON_GEAR All hosts: $ALL_HOSTS" 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, renew if missing, write to host conf + master.conf" [[ "$ALL_HOSTS" == true ]] && warn "DRY RUN — would also SSH to all partners and sync their keys" exit 0 fi # ── Helper: write a key variable into a conf file ───────────────────────────── _write_key_to_conf() { local conf="$1" var="$2" key="$3" [[ ! -f "$conf" ]] && return 1 if grep -q "^\s*${var}\s*=" "$conf"; then sed -i "s|^\(\s*${var}\s*=\s*\)\"[^\"]*\"|\1\"${key}\"|" "$conf" else echo " ${var}=\"${key}\"" >> "$conf" fi } # ── Helper: push master.conf to all partners ────────────────────────────────── _push_master() { php -r " require_once '/usr/local/emhttp/plugins/varaverk/include/config.php'; require_once '/usr/local/emhttp/plugins/varaverk/include/confform.php'; vv_push_master_conf(); " 2>/dev/null && log "master.conf pushed to partner(s)" || warn "master.conf push failed (partner offline?)" } # ────────────────────────────────────────────────────────────────────────────── # Step 1: Local key — check registry, create if missing, sync to conf # ────────────────────────────────────────────────────────────────────────────── echo "" echo "━━━ $ICON_GEAR Local key ($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}" CONF_KEY=$(grep "^\s*${VAR_NAME}\s*=" "$CONF_FILE" 2>/dev/null | sed 's/.*="\(.*\)".*/\1/' | tr -d '[:space:]') MASTER_KEY=$(grep "^\s*${VAR_NAME}\s*=" "$MASTER_CONF" 2>/dev/null | sed 's/.*="\(.*\)".*/\1/' | tr -d '[:space:]') if [[ "$CONF_KEY" == "$KEY" && "$MASTER_KEY" == "$KEY" ]]; then echo "API key valid ✅ — $VAR_NAME = $PREVIEW" log "Key in sync across host conf + master.conf" else log "Syncing key to conf files..." _write_key_to_conf "$CONF_FILE" "$VAR_NAME" "$KEY" _write_key_to_conf "$MASTER_CONF" "$VAR_NAME" "$KEY" _push_master warn "API key synced ✅ — $VAR_NAME = $PREVIEW" fi else log "Key not found in registry — creating $KEY_NAME..." RAW=$(timeout 10 /usr/local/sbin/unraid-api apikey \ --name "$KEY_NAME" --create --overwrite \ --description "Varaverk plugin" --roles ADMIN --json &1) KEY=$(echo "$RAW" | jq -r '.key // empty' 2>/dev/null) if [[ -z "$KEY" ]]; then error "unraid-api returned no key: ${RAW:0:200}" exit 1 fi _write_key_to_conf "$CONF_FILE" "$VAR_NAME" "$KEY" _write_key_to_conf "$MASTER_CONF" "$VAR_NAME" "$KEY" _push_master PREVIEW="${KEY:0:8}...${KEY: -4}" warn "API key created ✅ — $VAR_NAME = $PREVIEW" fi # ────────────────────────────────────────────────────────────────────────────── # Step 2 (--all-hosts): SSH to each partner, create their key, write to master.conf # ────────────────────────────────────────────────────────────────────────────── [[ "$ALL_HOSTS" != true ]] && exit 0 echo "" echo "━━━ $ICON_SYNC Partner keys ━━━" PARTNER_OK=0 PARTNER_FAIL=0 for host_var in HOST1 HOST2 HOST3 HOST4 HOST5 HOST6 HOST7 HOST8; do [[ "$host_var" == "$MY_ID" ]] && continue hostname="${!host_var:-}" [[ -z "$hostname" ]] && continue r_var_name="${host_var}_UNRAID_API_KEY" r_key_name="Varaverk_${host_var}" r_conf_path="/boot/config/plugins/varaverk/Configurations/${host_var,,}.conf" echo " $host_var ($hostname)…" REMOTE_IP=$(resolve_tailscale_ip "$hostname") if [[ -z "$REMOTE_IP" ]]; then warn " $host_var: cannot resolve Tailscale IP — skipping" (( PARTNER_FAIL++ )) continue fi # SSH: check for existing key, create if missing, return the key value REMOTE_KEY=$(ssh -i "$SSH_KEY" \ -o ConnectTimeout=10 \ -o StrictHostKeyChecking=no \ -o BatchMode=yes \ "root@${REMOTE_IP}" " EXISTING=\$(timeout 5 /usr/local/sbin/unraid-api apikey --name '${r_key_name}' --json /dev/null) KEY=\$(echo \"\$EXISTING\" | jq -r '.key // empty' 2>/dev/null) if [[ -n \"\$KEY\" ]]; then echo \"\$KEY\" else timeout 10 /usr/local/sbin/unraid-api apikey \\ --name '${r_key_name}' --create --overwrite \\ --description 'Varaverk plugin' --roles ADMIN --json /dev/null \\ | jq -r '.key // empty' 2>/dev/null fi " 2>/dev/null | tr -d '[:space:]') if [[ -z "$REMOTE_KEY" ]]; then warn " $host_var: could not get key from $hostname — skipping" (( PARTNER_FAIL++ )) continue fi R_PREVIEW="${REMOTE_KEY:0:8}...${REMOTE_KEY: -4}" # Write remote key to master.conf locally _write_key_to_conf "$MASTER_CONF" "$r_var_name" "$REMOTE_KEY" # Also write to remote's host*.conf so they have it locally ssh -i "$SSH_KEY" \ -o ConnectTimeout=10 \ -o StrictHostKeyChecking=no \ -o BatchMode=yes \ "root@${REMOTE_IP}" " CONF='${r_conf_path}' if [[ -f \"\$CONF\" ]]; then if grep -q '^\s*${r_var_name}\s*=' \"\$CONF\"; then sed -i \"s|^\(\s*${r_var_name}\s*=\s*\)\\\"[^\\\"]*\\\"|\1\\\"${REMOTE_KEY}\\\"|\" \"\$CONF\" else echo ' ${r_var_name}=\\\"${REMOTE_KEY}\\\"' >> \"\$CONF\" fi fi " 2>/dev/null echo " $host_var: $r_key_name = $R_PREVIEW ✅" (( PARTNER_OK++ )) done # Push master.conf with all updated keys to all partners if (( PARTNER_OK > 0 )); then echo "" echo " Pushing master.conf with all keys…" _push_master fi echo "" echo "━━━━━ $ICON_SUMMARY Key Setup Summary ━━━━━" echo " Local: ✅ $VAR_NAME" echo " Partners: $PARTNER_OK updated · $PARTNER_FAIL failed" echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"