From 1e9681a71e4ccfff7f2aa3022b56d9c3345aa9a4 Mon Sep 17 00:00:00 2001 From: Gmer4Lfe Date: Sat, 30 May 2026 15:22:46 -0400 Subject: [PATCH] Add first-run wizard, host.conf template, fix GitHub URL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plugin/varaverk.plg: URL updated to github.com/FailedProxy/Varaverk Configurations/host.conf.template: Full host conf structure with HOSTN/hostn placeholders. All personal values blank, all sections documented. Covers identity, rsync, docker, fallback, media, monitors, transcodes, arrs, system watchdog, resource manager. Varaverk.page: checks if HOST1 is blank before rendering tabs. If blank → shows setup wizard, returns early (tabs never render). pages/setup.php: first-run wizard UI. Auto-populates hostname from hostname -s. Role selection: primary (HOST1) or partner (HOST2+). Partner slot selector for HOST3+. api/setup.php: handles wizard form POST. Writes HOST1/HOST2 (and HOST3+) into master.conf preserving all other content. Creates host*.conf from template with HOSTN/hostn replaced and SSH key path pre-filled from hostname convention. Never overwrites an existing host*.conf. --- Configurations/host.conf.template | 457 ++++++++++++++++++++++++++++++ Plugin/unraid/Varaverk.page | 11 + Plugin/unraid/api/setup.php | 104 +++++++ Plugin/unraid/pages/setup.php | 253 +++++++++++++++++ Plugin/varaverk.plg | 4 +- 5 files changed, 827 insertions(+), 2 deletions(-) create mode 100644 Configurations/host.conf.template create mode 100644 Plugin/unraid/api/setup.php create mode 100644 Plugin/unraid/pages/setup.php diff --git a/Configurations/host.conf.template b/Configurations/host.conf.template new file mode 100644 index 0000000..16088eb --- /dev/null +++ b/Configurations/host.conf.template @@ -0,0 +1,457 @@ +#!/bin/bash +# ============================================================================================== +# ========================== HOSTN CONFIGURATION — (hostname) ================================== +# ============================================================================================== +# HOSTN-specific variables — credentials, container names, share paths, failover lists. +# Sourced after master.conf — values here extend shared profile arrays and add HOSTN-specific +# identity, credentials, and container configuration. +# +# Sparse checkout (git) ensures other hosts never receive this file. +# +# DO NOT put shared config here — thresholds, toggles, profiles belong in master.conf. +# DO NOT put other hosts' variables here — they belong in their own host*.conf files. +# +# ── HOW TO USE THIS TEMPLATE ────────────────────────────────────────────────────────────────── +# This file was generated by the Varaverk first-run wizard. +# Fill in the sections that apply to your setup — leave unused sections empty. +# All scripts self-guard against empty values — safe to leave sections blank until needed. +# +# ── INDEX ───────────────────────────────────────────────────────────────────────────────────── +# +# ── IDENTITY & CONNECTIVITY ──────────────────────────────────────────────────────────────── +# IDENTITY hostname, SSH key +# EMBY container name, URL, API key +# NOTIFICATIONS Discord webhook +# PARTNERSHIP auth containers, backup paths +# +# ── RSYNC ────────────────────────────────────────────────────────────────────────────────── +# DAILY SYNC SHARES media shares this host owns and pushes +# WEEKLY SYNC SHARES appdata shares synced weekly +# CRITICAL SYNC SHARES appdata shares synced every 30 minutes +# HOSTN RSYNC PROFILE host-specific appdata sync profile +# +# ── DOCKER ───────────────────────────────────────────────────────────────────────────────── +# DOCKER DAILY RESTART containers restarted daily +# DOCKER WEEKLY RESTART containers restarted weekly +# DOCKER WATCHDOG memory limits, health URLs, required containers +# DOCKER NETWORK CONNECT networks and containers for array start +# +# ── FALLBACK ─────────────────────────────────────────────────────────────────────────────── +# DDNS DDNS containers managed by this host +# INTERNET LOSS containers stopped when internet is lost +# FALLBACK TIERS what this host runs for the remote per tier +# TIER DELAYS delays before each tier activates +# RSYNC WRITEBACK appdata synced back on handback +# +# ── MEDIA ────────────────────────────────────────────────────────────────────────────────── +# MEDIA PERMISSIONS share list for permissions script +# MEDIA CLEANER folder lists for media_cleaner.sh +# +# ── MONITORS ─────────────────────────────────────────────────────────────────────────────── +# CERTIFICATE MONITOR domains checked for SSL expiry +# SMART HEALTH drives to skip in SMART monitoring +# ZFS REPORT pools to exclude from ZFS health report +# +# ── TRANSCODES ───────────────────────────────────────────────────────────────────────────── +# TRANSCODES ramdisk size, thresholds, SSD path, server array +# +# ── ARR STACK ────────────────────────────────────────────────────────────────────────────── +# DOWNLOADERS slskd, SABnzbd, qBittorrent credentials and URLs +# LIDARR / SONARR / RADARR URL, API key, path map +# ARR RECOVERY per-arr recovery toggles +# +# ── SYSTEM WATCHDOG ──────────────────────────────────────────────────────────────────────── +# SYSTEM WATCHDOG per-host check toggles and NIC configuration +# +# ── RESOURCE MANAGER ─────────────────────────────────────────────────────────────────────── +# RESOURCE MANAGER containers paused/stopped under memory pressure +# +# ============================================================================================== + +# ============================================================================================== +# ── IDENTITY & CONNECTIVITY ─────────────────────────────────────────────────────────────────── +# ============================================================================================== + +# ━━━ Identity ━━━ +# HOSTN hostname lives in master.conf (not a credential — safe for all servers). +# SSH key used for all server-to-server operations — rsync, failover, conf sync. +# Convention: /root/.ssh/_rsync_automation +# Must be in /root/.ssh/ and authorised in the partner's /root/.ssh/authorized_keys. +# Run Partnership/ssh_setup.sh to generate the key and copy it to the partner. + HOSTN_SSH_KEY="" # e.g. /root/.ssh/myserver_rsync_automation + HOSTN_OWNER="" # short identifier for this server (e.g. myserver) + HOSTN_OWNER_EMAIL="" + +# ━━━ Unraid API ━━━ +# Used by the Varaverk plugin to query this server's Unraid GraphQL API. +# Generate in Unraid: Settings → Management Access → API Keys → + New Key + HOSTN_UNRAID_API_KEY="" + +# ━━━ Emby ━━━ + HOSTN_EMBY_CONTAINER="Emby" + HOSTN_EMBY_URL="http://localhost:8096" + HOSTN_EMBY_API_KEY="" # Emby Dashboard → API Keys → + New Key + +# ━━━ Jellyfin ━━━ + HOSTN_JELLYFIN_CONTAINER="Jellyfin" + HOSTN_JELLYFIN_URL="http://localhost:8095" + HOSTN_JELLYFIN_API_KEY="" # Jellyfin Dashboard → Administration → API Keys + +# ━━━ Gitea ━━━ +# Personal access token for gitea_ssh_setup.sh. +# Create in Gitea: Settings → Applications → Generate Token → scope: write:user + HOSTN_GITEA_API_TOKEN="" + +# ━━━ Notifications ━━━ +# Discord webhook — leave blank to disable. + HOSTN_DISCORD_WEBHOOK="" + +# ━━━ Partnership ━━━ + +# Auth containers reconfigured on onboard/offboard. +# Format: "ContainerName|WebUIPort" + HOSTN_PARTNERSHIP_AUTH_WEBUIS=( + # "NginxProxyManager|81" + # "Authelia|9091" + ) + +# XML templates pushed to mirror during onboard — auth stack. +# Dependencies (databases) must come before apps that depend on them. + HOSTN_PARTNERSHIP_AUTH_STACK=( + # "my-Authelia.xml" + # "my-NginxProxyManager.xml" + ) + +# XML templates pushed to mirror during onboard — arr stack. + HOSTN_PARTNERSHIP_ARR_STACK=( + # "my-Sonarr.xml" + # "my-Radarr.xml" + ) + +# Paths the partner should collect during the grace window after offboard. + HOSTN_PARTNERSHIP_MIRROR_BACKUPS=( + # "/mnt/user/appdata-Fallback/Partner-Emby" + ) + +# Containers parked on this server when partnership is active. + HOSTN_PARTNERSHIP_OWN_CONTAINERS=( + # "Emby" + ) + +# Emby admin provisioning — owner controls whether Emby is shared. + HOSTN_PARTNERSHIP_PROVISION_EMBY_ADMIN=false + HOSTN_PARTNERSHIP_EMBY_PORT=8096 + HOSTN_PARTNERSHIP_EMBY_ADMIN_USER="" + HOSTN_PARTNERSHIP_EMBY_ADMIN_PASS="" + +# ============================================================================================== +# ── RSYNC ───────────────────────────────────────────────────────────────────────────────────── +# ============================================================================================== + +# ━━━ Daily Sync Shares ━━━ +# Media shares this host pushes to all other nodes every night. +# Uses DEFAULT_RSYNC_OPTS from master.conf — no profile needed. + HOSTN_DAILY_SYNC_SHARES=( + # /mnt/user/Movies + # /mnt/user/Tv_Shows + # /mnt/user/Music + ) + +# ━━━ Weekly Sync Shares ━━━ +# Appdata shares synced during the weekly maintenance window. +# Profiles (emby, critical-data) drive container stops — define in master.conf. + HOSTN_WEEKLY_SYNC_SHARES=( + # "/mnt/user/Media_Server/Emby" # emby profile + # "/mnt/user/appdata-Fallback/Critical-Data" # critical-data profile + ) + +# ━━━ Intermediate Sync Shares ━━━ +# Shares synced every 4 hours. Leave empty to skip mid-day rsync. + HOSTN_INTERMEDIATE_SYNC_SHARES=( + # Add shares here to enable mid-day rsync + ) + +# ━━━ Critical Sync Shares ━━━ +# Appdata shares synced every 30 minutes. +# Format: "/path/to/share" or "/path/to/share|profile-name" + HOSTN_CRITICAL_SYNC_SHARES=( + # "/mnt/user/appdata-Fallback/Critical-Data|critical-fallback" + # "/mnt/user/Media_Server/Emby|emby-fallback" + ) + +# ━━━ Backup Verify ━━━ +# Leave empty to use HOSTN_DAILY_SYNC_SHARES automatically. + HOSTN_BACKUP_VERIFY_SHARES=( + # leave empty to use HOSTN_DAILY_SYNC_SHARES automatically + ) + +# ━━━ HOSTN Rsync Profile — hostn-appdata ━━━ +# Host-specific appdata sync profile. + PROFILE_RSYNC_OPTS[hostn-appdata]="-av --info=progress2 --bwlimit=${PROFILE_BW_LIMIT[hostn-appdata]:-8000}" + PROFILE_BW_LIMIT[hostn-appdata]=8000 + PROFILE_RETRY_COUNT[hostn-appdata]=3 + PROFILE_SLEEP[hostn-appdata]=300 + PROFILE_CRITICAL_CONTAINER_NAMES[hostn-appdata]="" + PROFILE_DELAYED_CONTAINERS[hostn-appdata]="" + PROFILE_CONTAINER_DELAY[hostn-appdata]=5 + PROFILE_EXCLUDE_DIRS[hostn-appdata]="logs *.tmp" + +# ============================================================================================== +# ── DOCKER ──────────────────────────────────────────────────────────────────────────────────── +# ============================================================================================== + +# ━━━ Docker Daily Restart ━━━ + HOSTN_DAILY_RESTART_CONTAINERS=( + # "NginxProxyManager" + # "Authelia" + ) + +# ━━━ Docker Weekly Restart ━━━ + HOSTN_WEEKLY_RESTART_CONTAINERS=( + # "NextCloud" + # "AdGuard-Home" + ) + +# ━━━ Docker Watchdog ━━━ + +# Memory hard limits in MB — immediate restart if exceeded. +# 20GB=20480 16GB=16384 8GB=8192 4GB=4096 2GB=2048 1GB=1024 + declare -A HOSTN_WATCHDOG_CONTAINERS=( + # ["Emby"]=18432 + ) + +# HTTP health check URLs — checked every cycle. + declare -A HOSTN_WATCHDOG_CONTAINER_URLS=( + # ["Emby"]="http://localhost:8096" + ) + +# Required containers — must always be running. + HOSTN_WATCHDOG_REQUIRED_CONTAINERS=( + # "NginxProxyManager" + # "Authelia" + ) + +# Containers to skip in Tier 2 global scan. + HOSTN_WATCHDOG_SCAN_IGNORE=( + # "my-occasional-container" + ) + +# Dependency ordering — skip restarting a container if its dependency is also down. + declare -A HOSTN_WATCHDOG_DEPENDENCIES=( + # ["Authelia"]="Mariadb Redis-Authelia" + ) + +# Per-container appdata growth suppress ceilings in MB. + declare -A HOSTN_WATCHDOG_APPDATA_SIZES=( + # ["Tdarr"]="25600" + ) + +# ━━━ Network Watchdog ━━━ + HOSTN_NETWORK_WATCHDOG_DDNS_DOMAIN="" # e.g. myserver.com + HOSTN_NETWORK_WATCHDOG_DDNS_CONTAINER="" # e.g. MyServer.com + HOSTN_NETWORK_WATCHDOG_NPM_URL="" # e.g. https://myserver.com + +# ━━━ Docker Network Connect ━━━ + HOSTN_NETWORK_CONNECT_CONTAINERS=( + # "memcached" + ) + + HOSTN_NETWORK_CONNECT_NETWORKS=( + # "high-availability" + ) + +# ============================================================================================== +# ── FALLBACK ────────────────────────────────────────────────────────────────────────────────── +# ============================================================================================== + +# ━━━ DDNS ━━━ +# DDNS containers this host manages. + HOSTN_DDNS_CONTAINERS=( + # "MyServer.com" + ) + +# ━━━ Internet Loss ━━━ +# Containers stopped immediately when internet is lost. + FALLBACK_HOSTN_STOP_ON_NO_NET=( + # "MyServer.com" + ) + +# ━━━ Fallback Tiers — HOSTN Runs for Partner ━━━ +# Containers this host starts when the partner goes down. +# Replace REMOTE_ID below with the actual remote host ID (HOST1, HOST2, etc.) + FALLBACK_HOSTN_COVERS_REMOTE_ID_TIER1=( + # "Partner-DDNS-Container" + ) + + FALLBACK_HOSTN_COVERS_REMOTE_ID_TIER2=( + # "container-placeholder" + ) + + FALLBACK_HOSTN_COVERS_REMOTE_ID_TIER3=( + # "container-placeholder" + ) + + FALLBACK_HOSTN_COVERS_REMOTE_ID_TIER4=( + # "container-placeholder" + ) + +# ━━━ Tier Delays — Partner's Containers on this Host ━━━ +# How long the partner must be down before each tier activates here — in minutes. +# Replace REMOTE_ID with the actual remote host ID (HOST1, HOST2, etc.) + REMOTE_ID_TIER2_DELAY=240 # 4 hours + REMOTE_ID_TIER3_DELAY=720 # 12 hours + REMOTE_ID_TIER4_DELAY=1440 # 24 hours + +# ━━━ Rsync Writeback ━━━ + HOSTN_TIER1_WRITEBACK_DELAY=60 # skip Emby writeback if outage under 1hr + + FALLBACK_HOSTN_WRITEBACK_TIER1=( + # "/mnt/user/Media_Server/Emby" + ) + + FALLBACK_HOSTN_WRITEBACK_TIER2=( + # "/mnt/user/appdata-Fallback/Important-Data" + ) + + FALLBACK_HOSTN_WRITEBACK_TIER3=( + # "location-placeholder" + ) + + FALLBACK_HOSTN_WRITEBACK_TIER4=( + # "/mnt/user/appdata-Fallback/Arrs_Stack" + ) + +# ============================================================================================== +# ── MEDIA ───────────────────────────────────────────────────────────────────────────────────── +# ============================================================================================== + +# ━━━ Media Permissions ━━━ + HOSTN_MEDIA_PERMISSION_SHARES=( + # /mnt/user/Movies + # /mnt/user/Tv_Shows + # /mnt/user/Music + # /mnt/user/Downloads + ) + +# ━━━ Media Cleaner ━━━ + HOSTN_ANIME_CLEAN_FOLDERS=( + # /mnt/user/Anime_Movies + # /mnt/user/Anime_Shows + ) + + HOSTN_MEDIA_CLEAN_FOLDERS=( + # /mnt/user/Movies + # /mnt/user/Tv_Shows + ) + +# ============================================================================================== +# ── MONITORS ────────────────────────────────────────────────────────────────────────────────── +# ============================================================================================== + +# ━━━ Certificate Monitor ━━━ + HOSTN_CERT_MONITOR_DOMAINS=( + # "myserver.com" + ) + +# ━━━ SMART Health ━━━ + HOSTN_SMART_IGNORE_DRIVES=( + "sda" # boot USB — SMART not meaningful on flash drives + ) + +# ━━━ ZFS Report ━━━ + HOSTN_ZFS_REPORT_IGNORE_POOLS=( + # "disk5" + ) + +# ============================================================================================== +# ── TRANSCODES ──────────────────────────────────────────────────────────────────────────────── +# ============================================================================================== + + HOSTN_RAMDISK_SIZE="10G" + HOSTN_RAMDISK_WARN_GB=8.5 + HOSTN_RAMDISK_LOW_GB=7 + HOSTN_TRANSCODE_SSD="/mnt/cache/Temp_Storage/Emby/Transcodes/" + + HOSTN_TRANSCODE_SERVERS=( + "${HOSTN_EMBY_CONTAINER}|${HOSTN_EMBY_URL}|${HOSTN_EMBY_API_KEY}|emby" + ) + +# ============================================================================================== +# ── ARR STACK ───────────────────────────────────────────────────────────────────────────────── +# ============================================================================================== + +# ━━━ Downloaders ━━━ + HOSTN_SLSKD_URL="http://localhost:8980" + HOSTN_SLSKD_API_KEY="" + HOSTN_SLSKD_FAILED_IMPORTS_DIR="" + + HOSTN_SABNZBD_URL="http://localhost:8180" + HOSTN_SABNZBD_API_KEY="" + + HOSTN_QBIT_URL="http://localhost:8080" + HOSTN_QBIT_USERNAME="admin" + HOSTN_QBIT_PASSWORD="" + +# ━━━ Lidarr ━━━ + HOSTN_LIDARR_URL="http://localhost:8686" + HOSTN_LIDARR_API_KEY="" + HOSTN_LIDARR_MUSIC_ROOT="/mnt/user/Music" + HOSTN_FANART_API_KEY="" + HOSTN_LASTFM_API_KEY="" + + declare -A HOSTN_LIDARR_PATH_MAP=( + # ["/music"]="/mnt/user/Music" + ) + +# ━━━ Sonarr ━━━ + HOSTN_SONARR_URL="http://localhost:8989" + HOSTN_SONARR_API_KEY="" + HOSTN_SONARR_TV_ROOT="/mnt/user/Tv_Shows" + + declare -A HOSTN_SONARR_PATH_MAP=( + # ["/tv"]="/mnt/user/Tv_Shows" + ) + +# ━━━ Radarr ━━━ + HOSTN_RADARR_URL="http://localhost:7878" + HOSTN_RADARR_API_KEY="" + HOSTN_RADARR_MOVIE_ROOT="/mnt/user/Movies" + + declare -A HOSTN_RADARR_PATH_MAP=( + # ["/movies"]="/mnt/user/Movies" + ) + +# ━━━ Arr Recovery Toggles ━━━ + HOSTN_LIDARR_RECOVERY=false + HOSTN_SONARR_RECOVERY=true + HOSTN_RADARR_RECOVERY=true + +# ============================================================================================== +# ── SYSTEM WATCHDOG ─────────────────────────────────────────────────────────────────────────── +# ============================================================================================== + + HOSTN_SYS_WATCHDOG_CHECK_DOCKER=true + HOSTN_SYS_WATCHDOG_CHECK_ROOTFS=true + HOSTN_SYS_WATCHDOG_CHECK_RAM=true + HOSTN_SYS_WATCHDOG_CHECK_LOAD=true + HOSTN_SYS_WATCHDOG_CHECK_TEMP=true + HOSTN_SYS_WATCHDOG_CHECK_ZOMBIES=true + HOSTN_SYS_WATCHDOG_CHECK_LOG=true + HOSTN_SYS_WATCHDOG_CHECK_TMP=true + HOSTN_SYS_WATCHDOG_CHECK_FD=true + HOSTN_SYS_WATCHDOG_CHECK_RUNAWAY=true + + HOSTN_SYS_WATCHDOG_NIC="" # e.g. eth0 — for network monitoring + +# ============================================================================================== +# ── RESOURCE MANAGER ────────────────────────────────────────────────────────────────────────── +# ============================================================================================== + + HOSTN_RW_PAUSE_CONTAINERS=( + # "Tdarr" + # "LidaTube" + ) + + HOSTN_RW_STOP_CONTAINERS=( + # "Tdarr" + ) diff --git a/Plugin/unraid/Varaverk.page b/Plugin/unraid/Varaverk.page index f901a8c..05bcbad 100644 --- a/Plugin/unraid/Varaverk.page +++ b/Plugin/unraid/Varaverk.page @@ -7,6 +7,17 @@ $plugin = 'varaverk'; $docroot = $docroot ?? $_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp'; $pluginDir = "$docroot/plugins/$plugin"; +require_once "$pluginDir/include/config.php"; + +// First-run check — show setup wizard if HOST1 is not configured +$_master = vv_read_conf_raw('master.conf'); +preg_match('/^\s*HOST1\s*=\s*"([^"]*)"/m', $_master, $_h1m); +if (empty(trim($_h1m[1] ?? ''))) { + include "$pluginDir/pages/setup.php"; + return; +} +unset($_master, $_h1m); + // Determine active tab $tab = $_GET['tab'] ?? 'monitor'; $validTabs = ['monitor', 'scheduler', 'docker', 'watchdog', 'partnership', 'fallback', 'arrs']; diff --git a/Plugin/unraid/api/setup.php b/Plugin/unraid/api/setup.php new file mode 100644 index 0000000..8aaec5e --- /dev/null +++ b/Plugin/unraid/api/setup.php @@ -0,0 +1,104 @@ + false, 'error' => 'Method not allowed']); + exit; +} + +$host1 = trim($_POST['host1'] ?? ''); +$host2 = trim($_POST['host2'] ?? ''); +$mySlot = trim($_POST['my_slot'] ?? 'host1'); // 'host1', 'host2', 'host3', ... +$myHostname = trim($_POST['my_hostname'] ?? ''); + +if (empty($host1)) { + echo json_encode(['ok' => false, 'error' => 'HOST1 hostname is required']); + exit; +} + +// Validate slot — must be host\d+ +if (!preg_match('/^host\d+$/', $mySlot)) { + echo json_encode(['ok' => false, 'error' => 'Invalid slot']); + exit; +} + +// ── Write HOST1 / HOST2 into master.conf ───────────────────────────────────────────────────── +$master = vv_read_conf_raw('master.conf'); +if ($master === '') { + echo json_encode(['ok' => false, 'error' => 'master.conf not found — check SCRIPTS_DIR in varaverk.cfg']); + exit; +} + +// Replace HOST1 and HOST2 lines (preserving indentation) +$master = preg_replace( + '/^(\s*HOST1\s*=\s*).*$/m', + '${1}"' . addslashes($host1) . '"', + $master +); +$master = preg_replace( + '/^(\s*HOST2\s*=\s*).*$/m', + '${1}"' . addslashes($host2) . '"', + $master +); + +// For partner slots beyond HOST2 — ensure the slot line exists in master.conf +$slotNum = (int) preg_replace('/\D/', '', $mySlot); +if ($slotNum > 2 && !empty($myHostname)) { + $hostKey = 'HOST' . $slotNum; + if (!preg_match('/^\s*' . $hostKey . '\s*=/m', $master)) { + // Append after HOST2 line + $master = preg_replace( + '/^(\s*HOST2\s*=.*$)/m', + '$1' . "\n {$hostKey}=\"" . addslashes($myHostname) . '"', + $master + ); + } else { + $master = preg_replace( + '/^(\s*' . $hostKey . '\s*=\s*).*$/m', + '${1}"' . addslashes($myHostname) . '"', + $master + ); + } +} + +if (!vv_write_conf_raw('master.conf', $master)) { + echo json_encode(['ok' => false, 'error' => 'Failed to write master.conf']); + exit; +} + +// ── Create host*.conf from template ────────────────────────────────────────────────────────── +$hostId = strtoupper($mySlot); // HOST1, HOST2, HOST3 ... +$hostIdLow = strtolower($mySlot); // host1, host2, host3 ... +$confFile = $hostIdLow . '.conf'; + +// Only create if it doesn't already exist — never overwrite an existing conf +if (!file_exists(CONF_DIR . '/' . $confFile)) { + $template = @file_get_contents(CONF_DIR . '/host.conf.template'); + if ($template === false) { + $template = @file_get_contents(SCRIPTS_DIR . '/Configurations/host.conf.template'); + } + if ($template !== false) { + // Derive SSH key path from hostname convention + // unRAID-MyServer → /root/.ssh/myserver_rsync_automation + $sshOwner = strtolower(preg_replace('/^unraid-/i', '', $myHostname)); + $sshKeyPath = '/root/.ssh/' . $sshOwner . '_rsync_automation'; + + $conf = str_replace('HOSTN', $hostId, $template); + $conf = str_replace('hostn', $hostIdLow, $conf); + // Pre-fill the SSH key path + $conf = preg_replace( + '/^(\s*' . $hostId . '_SSH_KEY\s*=\s*)""/m', + '${1}"' . $sshKeyPath . '"', + $conf + ); + + if (!vv_write_conf_raw($confFile, $conf)) { + echo json_encode(['ok' => false, 'error' => "Failed to write $confFile"]); + exit; + } + } + // Template missing is non-fatal — user can create the conf manually +} + +echo json_encode(['ok' => true, 'host_id' => $hostId, 'conf_file' => $confFile]); diff --git a/Plugin/unraid/pages/setup.php b/Plugin/unraid/pages/setup.php new file mode 100644 index 0000000..2fe7cf2 --- /dev/null +++ b/Plugin/unraid/pages/setup.php @@ -0,0 +1,253 @@ + + + + + +
+

⬡ Varaverk — First Run

+
Set up your server identity before the plugin can start.
+ +
+ + +
Must match Settings → Identification exactly (case-sensitive)
+
+ +
+ + +
+
+ Primary
HOST1 · first to be set up +
+
+ Partner
HOST2+ · joining an existing primary +
+
+ +
+
+ + +
Leave blank if setting up standalone or partner isn't ready yet
+
+
+ +
+
+ + +
+
+ + +
Which slot are you? Ask your primary server admin if unsure — usually HOST2.
+
+
+ + +
+
+ + diff --git a/Plugin/varaverk.plg b/Plugin/varaverk.plg index 7c5901a..5198520 100644 --- a/Plugin/varaverk.plg +++ b/Plugin/varaverk.plg @@ -4,7 +4,7 @@ - + @@ -29,7 +29,7 @@