Files
Varaverk/Plugin/unraid/pages/setup.php
T
Gmer4Lfe 1e9681a71e Add first-run wizard, host.conf template, fix GitHub URL
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.
2026-05-30 15:22:46 -04:00

254 lines
7.3 KiB
PHP

<?php
// First-run setup wizard — shown when HOST1 is blank in master.conf.
$detectedHostname = trim(shell_exec('hostname -s') ?: '');
?>
<link rel="stylesheet" href="/plugins/varaverk/css/varaverk.css">
<style>
#vv-setup {
max-width: 560px;
margin: 48px auto 0;
background: #141414;
border: 1px solid #2a2a2a;
border-radius: 6px;
padding: 36px 40px 40px;
font-family: monospace;
color: #ccc;
}
#vv-setup h1 {
margin: 0 0 6px;
font-size: 18px;
color: #e0e0e0;
font-weight: normal;
letter-spacing: .04em;
}
#vv-setup .vv-setup-sub {
font-size: 12px;
color: #555;
margin-bottom: 32px;
}
#vv-setup .vv-setup-field {
margin-bottom: 20px;
}
#vv-setup label {
display: block;
font-size: 11px;
color: #888;
margin-bottom: 6px;
text-transform: uppercase;
letter-spacing: .06em;
}
#vv-setup input[type=text] {
width: 100%;
box-sizing: border-box;
background: #0d0d0d;
border: 1px solid #333;
color: #ddd;
padding: 7px 10px;
border-radius: 3px;
font-family: monospace;
font-size: 13px;
}
#vv-setup input[type=text]:focus {
outline: none;
border-color: #555;
}
#vv-setup .vv-setup-hint {
font-size: 11px;
color: #555;
margin-top: 5px;
}
#vv-setup .vv-setup-role {
display: flex;
gap: 10px;
margin-bottom: 24px;
}
#vv-setup .vv-setup-role-btn {
flex: 1;
padding: 10px 0;
background: #1a1a1a;
border: 1px solid #333;
border-radius: 3px;
color: #888;
font-family: monospace;
font-size: 12px;
cursor: pointer;
text-align: center;
transition: border-color .15s, color .15s;
}
#vv-setup .vv-setup-role-btn.active {
border-color: #555;
color: #ccc;
background: #222;
}
#vv-setup .vv-setup-conditional {
display: none;
}
#vv-setup .vv-setup-conditional.visible {
display: block;
}
#vv-setup .vv-setup-divider {
border: none;
border-top: 1px solid #222;
margin: 24px 0;
}
#vv-setup-btn {
width: 100%;
padding: 10px;
background: #1e1e1e;
border: 1px solid #444;
color: #ccc;
font-family: monospace;
font-size: 13px;
border-radius: 3px;
cursor: pointer;
letter-spacing: .03em;
}
#vv-setup-btn:hover { border-color: #666; color: #eee; }
#vv-setup-btn:disabled { opacity: .45; cursor: default; }
#vv-setup-status {
margin-top: 12px;
font-size: 12px;
color: #666;
text-align: center;
min-height: 16px;
}
#vv-setup-status.ok { color: #4a8; }
#vv-setup-status.err { color: #a44; }
</style>
<div id="vv-setup">
<h1>⬡ Varaverk — First Run</h1>
<div class="vv-setup-sub">Set up your server identity before the plugin can start.</div>
<div class="vv-setup-field">
<label>This server's hostname</label>
<input type="text" id="vv-hostname" value="<?= htmlspecialchars($detectedHostname) ?>"
placeholder="unRAID-MyServer" autocomplete="off" spellcheck="false">
<div class="vv-setup-hint">Must match Settings → Identification exactly (case-sensitive)</div>
</div>
<hr class="vv-setup-divider">
<label style="margin-bottom:10px;display:block;">Server role</label>
<div class="vv-setup-role">
<div class="vv-setup-role-btn active" id="vv-role-primary" onclick="vvSetRole('primary')">
Primary<br><span style="color:#555;font-size:10px;">HOST1 · first to be set up</span>
</div>
<div class="vv-setup-role-btn" id="vv-role-partner" onclick="vvSetRole('partner')">
Partner<br><span style="color:#555;font-size:10px;">HOST2+ · joining an existing primary</span>
</div>
</div>
<div class="vv-setup-conditional" id="vv-cond-primary">
<div class="vv-setup-field">
<label>Partner's hostname <span style="color:#444">(optional — can fill in later)</span></label>
<input type="text" id="vv-partner-hostname" value=""
placeholder="unRAID-PartnerServer" autocomplete="off" spellcheck="false">
<div class="vv-setup-hint">Leave blank if setting up standalone or partner isn't ready yet</div>
</div>
</div>
<div class="vv-setup-conditional" id="vv-cond-partner">
<div class="vv-setup-field">
<label>Primary server's hostname <span style="color:#a44">*required</span></label>
<input type="text" id="vv-primary-hostname" value=""
placeholder="unRAID-PrimaryServer" autocomplete="off" spellcheck="false">
</div>
<div class="vv-setup-field">
<label>Your slot</label>
<select id="vv-partner-slot" style="width:100%;box-sizing:border-box;background:#0d0d0d;
border:1px solid #333;color:#ddd;padding:7px 10px;border-radius:3px;
font-family:monospace;font-size:13px;">
<option value="host2">HOST2</option>
<option value="host3">HOST3</option>
<option value="host4">HOST4</option>
</select>
<div class="vv-setup-hint">Which slot are you? Ask your primary server admin if unsure — usually HOST2.</div>
</div>
</div>
<button id="vv-setup-btn" onclick="vvDoSetup()">Save and continue →</button>
<div id="vv-setup-status"></div>
</div>
<script>
let vvRole = 'primary';
function vvSetRole(role) {
vvRole = role;
document.getElementById('vv-role-primary').classList.toggle('active', role === 'primary');
document.getElementById('vv-role-partner').classList.toggle('active', role === 'partner');
document.getElementById('vv-cond-primary').classList.toggle('visible', role === 'primary');
document.getElementById('vv-cond-partner').classList.toggle('visible', role === 'partner');
}
function vvDoSetup() {
const hostname = document.getElementById('vv-hostname').value.trim();
const status = document.getElementById('vv-setup-status');
const btn = document.getElementById('vv-setup-btn');
if (!hostname) {
status.textContent = '✗ Hostname is required';
status.className = 'err';
return;
}
let host1 = '', host2 = '', mySlot = 'host1';
if (vvRole === 'primary') {
host1 = hostname;
host2 = document.getElementById('vv-partner-hostname').value.trim();
mySlot = 'host1';
} else {
const primary = document.getElementById('vv-primary-hostname').value.trim();
if (!primary) {
status.textContent = '✗ Primary hostname is required for partner setup';
status.className = 'err';
return;
}
mySlot = document.getElementById('vv-partner-slot').value;
host1 = primary;
// Place this server in the correct slot
if (mySlot === 'host2') host2 = hostname;
// host3/host4 handled server-side
}
btn.disabled = true;
btn.textContent = 'Saving…';
status.textContent = '';
status.className = '';
const params = new URLSearchParams({
csrf_token: typeof csrf_token !== 'undefined' ? csrf_token : '',
host1, host2, my_slot: mySlot,
my_hostname: hostname,
});
fetch('/plugins/varaverk/api/setup.php', {
method: 'POST',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
body: params,
})
.then(r => r.json())
.then(d => {
if (d.ok) {
status.textContent = '✓ Saved — loading plugin…';
status.className = 'ok';
setTimeout(() => { window.location.href = '?tab=monitor'; }, 800);
} else {
btn.disabled = false;
btn.textContent = 'Save and continue →';
status.textContent = '✗ ' + (d.error ?? 'Unknown error');
status.className = 'err';
}
})
.catch(() => {
btn.disabled = false;
btn.textContent = 'Save and continue →';
status.textContent = '✗ Request failed';
status.className = 'err';
});
}
</script>