- Move SCRIPTS_DIR/DATA_DIR/STATE_DIR from appdata to /boot/config/plugins/varaverk - All state files now in STATE_DIR (no more /tmp or /boot/config root writes) - Bootstrap: Gitea-first clone with GitHub fallback, no array dependency - varaverk.cfg seeded with Gitea connection settings - .gitignore: add State_Files/, varaverk.cfg, varaverk-*.txz - Partnership/transcode/fallback scripts use STATE_DIR variables - PHP config.php: DATA_DIR/STATE_DIR constants, VV_SETUP_STATE_FILE dynamic - deploy.sh PROD_ROOT updated to plugin flash dir Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
160 lines
6.3 KiB
PHP
160 lines
6.3 KiB
PHP
<?php
|
|
header('Content-Type: application/json');
|
|
require_once dirname(__DIR__) . '/include/config.php';
|
|
|
|
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
|
echo json_encode(['ok' => false, 'error' => 'Method not allowed']);
|
|
exit;
|
|
}
|
|
|
|
$action = trim($_POST['action'] ?? 'save');
|
|
|
|
// ── HOST2 pull: pull master.conf from HOST1 via SSH ──────────────────────────────────────────
|
|
if ($action === 'pull') {
|
|
$host1Hostname = trim($_POST['host1_hostname'] ?? '');
|
|
$mySlot = trim($_POST['my_slot'] ?? 'host2');
|
|
$myHostname = trim($_POST['my_hostname'] ?? '');
|
|
|
|
if (!$host1Hostname) {
|
|
echo json_encode(['ok' => false, 'error' => 'HOST1 hostname required']);
|
|
exit;
|
|
}
|
|
if (!preg_match('/^host\d+$/', $mySlot)) {
|
|
echo json_encode(['ok' => false, 'error' => 'Invalid slot']);
|
|
exit;
|
|
}
|
|
|
|
$hostId = strtoupper($mySlot);
|
|
$hostIdLow = strtolower($mySlot);
|
|
|
|
// Derive SSH key path from this server's hostname
|
|
$sshOwner = strtolower(preg_replace('/^unraid-/i', '', $myHostname ?: vv_get_hostname()));
|
|
$sshKey = '/root/.ssh/' . $sshOwner . '_rsync_automation';
|
|
|
|
if (!file_exists($sshKey)) {
|
|
echo json_encode(['ok' => false, 'error' =>
|
|
"SSH key not found at $sshKey — run Partnership/ssh_setup.sh first"]);
|
|
exit;
|
|
}
|
|
|
|
// Resolve HOST1 Tailscale IP
|
|
$ip = trim(shell_exec('tailscale ip -4 ' . escapeshellarg($host1Hostname) . ' 2>/dev/null') ?: '');
|
|
if (!$ip) {
|
|
echo json_encode(['ok' => false, 'error' =>
|
|
"Cannot resolve Tailscale IP for $host1Hostname — is Tailscale running on both servers?"]);
|
|
exit;
|
|
}
|
|
|
|
// Get HOST1's SCRIPTS_DIR from their varaverk.cfg
|
|
$sshBase = 'ssh -i ' . escapeshellarg($sshKey)
|
|
. ' -o ConnectTimeout=10 -o StrictHostKeyChecking=no root@' . $ip;
|
|
$remoteCfg = trim(shell_exec($sshBase . ' "grep SCRIPTS_DIR /boot/config/plugins/varaverk/varaverk.cfg 2>/dev/null"') ?: '');
|
|
preg_match('/SCRIPTS_DIR\s*=\s*["\']?([^"\']+)["\']?/', $remoteCfg, $sm);
|
|
$remoteConf = rtrim($sm[1] ?? '/boot/config/plugins/varaverk', '/') . '/Configurations';
|
|
|
|
// SCP master.conf from HOST1
|
|
$localMaster = CONF_DIR . '/master.conf';
|
|
$src = escapeshellarg('root@' . $ip . ':' . $remoteConf . '/master.conf');
|
|
$cmd = 'scp -i ' . escapeshellarg($sshKey)
|
|
. ' -o ConnectTimeout=10 -o StrictHostKeyChecking=no'
|
|
. ' ' . $src . ' ' . escapeshellarg($localMaster) . ' 2>&1';
|
|
exec($cmd, $out, $rc);
|
|
if ($rc !== 0) {
|
|
echo json_encode(['ok' => false, 'error' =>
|
|
'SCP failed: ' . implode('; ', $out) .
|
|
' — ensure your SSH key is authorised on HOST1 (run Partnership/ssh_setup.sh)']);
|
|
exit;
|
|
}
|
|
|
|
// Create host conf from template if it doesn't exist
|
|
$confFile = $hostIdLow . '.conf';
|
|
if (!file_exists(CONF_DIR . '/' . $confFile)) {
|
|
$template = @file_get_contents(CONF_DIR . '/host.conf.template') ?: '';
|
|
if ($template) {
|
|
$hostname = $myHostname ?: vv_get_hostname();
|
|
$sshKeyPath = $sshKey;
|
|
$conf = str_replace('HOSTN', $hostId, $template);
|
|
$conf = str_replace('hostn', $hostIdLow, $conf);
|
|
$conf = preg_replace('/^(\s*' . $hostId . '_SSH_KEY\s*=\s*)""/m',
|
|
'${1}"' . $sshKeyPath . '"', $conf);
|
|
vv_write_conf_raw($confFile, $conf);
|
|
}
|
|
}
|
|
|
|
echo json_encode(['ok' => true, 'host_id' => $hostId, 'conf_file' => $confFile,
|
|
'redirect' => '?tab=scheduler&vv_setup=' . $confFile]);
|
|
exit;
|
|
}
|
|
|
|
// ── Default action: save (HOST1 first-run wizard) ────────────────────────────────────────────
|
|
$host1 = trim($_POST['host1'] ?? '');
|
|
$host2 = trim($_POST['host2'] ?? '');
|
|
$mySlot = trim($_POST['my_slot'] ?? 'host1');
|
|
$myHostname = trim($_POST['my_hostname'] ?? '');
|
|
|
|
if (empty($host1)) {
|
|
echo json_encode(['ok' => false, 'error' => 'HOST1 hostname is required']);
|
|
exit;
|
|
}
|
|
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;
|
|
}
|
|
|
|
$master = preg_replace('/^(\s*HOST1\s*=\s*).*$/m', '${1}"' . addslashes($host1) . '"', $master);
|
|
$master = preg_replace('/^(\s*HOST2\s*=\s*).*$/m', '${1}"' . addslashes($host2) . '"', $master);
|
|
|
|
$slotNum = (int) preg_replace('/\D/', '', $mySlot);
|
|
if ($slotNum > 2 && !empty($myHostname)) {
|
|
$hostKey = 'HOST' . $slotNum;
|
|
if (!preg_match('/^\s*' . $hostKey . '\s*=/m', $master)) {
|
|
$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);
|
|
$hostIdLow = strtolower($mySlot);
|
|
$confFile = $hostIdLow . '.conf';
|
|
|
|
if (!file_exists(CONF_DIR . '/' . $confFile)) {
|
|
$template = @file_get_contents(CONF_DIR . '/host.conf.template') ?: '';
|
|
if ($template) {
|
|
$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);
|
|
$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;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Write setup state file — lets partner servers know HOST1 is configured
|
|
vv_setup_state_write(['host1_hostname' => $host1]);
|
|
|
|
echo json_encode([
|
|
'ok' => true,
|
|
'host_id' => $hostId,
|
|
'redirect' => '?tab=scheduler&vv_setup=master.conf',
|
|
]);
|