install.sh: auto-download from backend, InstallGuide component for frontend dialogs
This commit is contained in:
parent
7f9fbd257f
commit
5f37e28046
220
frontend/src/components/InstallGuide.jsx
Normal file
220
frontend/src/components/InstallGuide.jsx
Normal file
@ -0,0 +1,220 @@
|
|||||||
|
import { useState } from 'react'
|
||||||
|
import { Copy, Check, Terminal, Monitor } from 'lucide-react'
|
||||||
|
|
||||||
|
const BACKEND_URL = 'https://192.168.85.13:8443'
|
||||||
|
const API_KEY = '01532e5a7c9e70bf2757df77a2f5b9b9'
|
||||||
|
const INSTALL_SH_URL = 'https://git.cynfo.net/christian/rmm/raw/branch/main/opnsense-plugin/install.sh'
|
||||||
|
|
||||||
|
export default function InstallGuide({ agentName, platform: initialPlatform }) {
|
||||||
|
const [platform, setPlatform] = useState(initialPlatform || 'freebsd')
|
||||||
|
const [copied, setCopied] = useState(null)
|
||||||
|
|
||||||
|
const copyText = (text, id) => {
|
||||||
|
navigator.clipboard.writeText(text)
|
||||||
|
setCopied(id)
|
||||||
|
setTimeout(() => setCopied(null), 2000)
|
||||||
|
}
|
||||||
|
|
||||||
|
const CopyBtn = ({ text, id, className = '' }) => (
|
||||||
|
<button
|
||||||
|
onClick={(e) => { e.stopPropagation(); copyText(text, id) }}
|
||||||
|
className={`text-gray-500 hover:text-orange-400 transition-colors ${className}`}
|
||||||
|
title="Kopieren"
|
||||||
|
>
|
||||||
|
{copied === id ? <Check className="w-3.5 h-3.5 text-green-400" /> : <Copy className="w-3.5 h-3.5" />}
|
||||||
|
</button>
|
||||||
|
)
|
||||||
|
|
||||||
|
const CodeBlock = ({ text, id }) => (
|
||||||
|
<div className="relative group">
|
||||||
|
<pre className="bg-gray-950 rounded px-3 py-2 text-xs font-mono text-gray-300 whitespace-pre-wrap overflow-x-auto">
|
||||||
|
{text}
|
||||||
|
</pre>
|
||||||
|
<button
|
||||||
|
onClick={() => copyText(text, id)}
|
||||||
|
className="absolute top-1.5 right-1.5 text-gray-600 hover:text-orange-400 transition-colors"
|
||||||
|
>
|
||||||
|
{copied === id ? <Check className="w-4 h-4 text-green-400" /> : <Copy className="w-4 h-4" />}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
|
const ConfigValue = ({ label, value, id, mono = false }) => (
|
||||||
|
<div className="flex items-center justify-between bg-gray-950 rounded px-3 py-2">
|
||||||
|
<div className="min-w-0">
|
||||||
|
<span className="text-xs text-gray-500">{label}</span>
|
||||||
|
<div className={`text-sm text-white truncate ${mono ? 'font-mono text-xs' : ''}`}>{value}</div>
|
||||||
|
</div>
|
||||||
|
<CopyBtn text={value} id={id} className="ml-2 flex-shrink-0" />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
|
const opnInstallCmd = `fetch -o /tmp/install.sh "${INSTALL_SH_URL}" && sh /tmp/install.sh`
|
||||||
|
|
||||||
|
const linuxInstallCmd = `#!/bin/sh
|
||||||
|
# RMM Agent + Updater Installation
|
||||||
|
set -e
|
||||||
|
|
||||||
|
BACKEND="${BACKEND_URL}"
|
||||||
|
API_KEY="${API_KEY}"
|
||||||
|
NAME="${agentName || '<NAME>'}"
|
||||||
|
|
||||||
|
# Download
|
||||||
|
wget --no-check-certificate -O /tmp/rmm-bundle.zip \\
|
||||||
|
"$BACKEND/api/v1/firmware/download?platform=linux&api_key=$API_KEY"
|
||||||
|
cd /tmp && unzip -o rmm-bundle.zip
|
||||||
|
|
||||||
|
# Install binaries
|
||||||
|
install -m 755 /tmp/rmm-agent-linux /usr/local/bin/rmm-agent
|
||||||
|
install -m 755 /tmp/rmm-updater-linux /usr/local/bin/rmm-updater
|
||||||
|
mkdir -p /etc/rmm
|
||||||
|
|
||||||
|
# Config
|
||||||
|
cat > /etc/rmm/config.yaml << EOF
|
||||||
|
backend_url: "$BACKEND"
|
||||||
|
api_key: "$API_KEY"
|
||||||
|
agent_name: "$NAME"
|
||||||
|
interval_seconds: 60
|
||||||
|
insecure: true
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Systemd services
|
||||||
|
cat > /etc/systemd/system/rmm-agent.service << EOF
|
||||||
|
[Unit]
|
||||||
|
Description=RMM Agent
|
||||||
|
After=network.target
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
ExecStart=/usr/local/bin/rmm-agent
|
||||||
|
Restart=always
|
||||||
|
RestartSec=10
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
EOF
|
||||||
|
|
||||||
|
cat > /etc/systemd/system/rmm-updater.service << EOF
|
||||||
|
[Unit]
|
||||||
|
Description=RMM Updater
|
||||||
|
After=network.target
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
ExecStart=/usr/local/bin/rmm-updater
|
||||||
|
Restart=always
|
||||||
|
RestartSec=30
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
EOF
|
||||||
|
|
||||||
|
systemctl daemon-reload
|
||||||
|
systemctl enable --now rmm-agent rmm-updater
|
||||||
|
echo "Fertig! Agent verbindet sich automatisch mit Backend."
|
||||||
|
`
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="space-y-4">
|
||||||
|
{/* Platform Tabs */}
|
||||||
|
{!initialPlatform && (
|
||||||
|
<div className="flex gap-1 bg-gray-800 rounded-lg p-1">
|
||||||
|
<button
|
||||||
|
onClick={() => setPlatform('freebsd')}
|
||||||
|
className={`flex-1 flex items-center justify-center gap-2 px-3 py-2 rounded text-sm font-medium transition-colors ${
|
||||||
|
platform === 'freebsd'
|
||||||
|
? 'bg-orange-600 text-white'
|
||||||
|
: 'text-gray-400 hover:text-white'
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
<Monitor className="w-4 h-4" />
|
||||||
|
OPNsense
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={() => setPlatform('linux')}
|
||||||
|
className={`flex-1 flex items-center justify-center gap-2 px-3 py-2 rounded text-sm font-medium transition-colors ${
|
||||||
|
platform === 'linux'
|
||||||
|
? 'bg-blue-600 text-white'
|
||||||
|
: 'text-gray-400 hover:text-white'
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
<Terminal className="w-4 h-4" />
|
||||||
|
Linux / Proxmox
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{platform === 'freebsd' ? (
|
||||||
|
<div className="space-y-4">
|
||||||
|
{/* Step 1: Install Plugin */}
|
||||||
|
<div className="space-y-2">
|
||||||
|
<h4 className="text-sm font-medium text-white flex items-center gap-2">
|
||||||
|
<span className="w-5 h-5 rounded-full bg-orange-600 text-white text-xs flex items-center justify-center font-bold">1</span>
|
||||||
|
Plugin installieren
|
||||||
|
</h4>
|
||||||
|
<p className="text-xs text-gray-400 ml-7">Per SSH oder WebGUI-Shell auf der Firewall ausfuehren:</p>
|
||||||
|
<div className="ml-7">
|
||||||
|
<CodeBlock text={opnInstallCmd} id="opn-install" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Step 2: Configure via WebGUI */}
|
||||||
|
<div className="space-y-2">
|
||||||
|
<h4 className="text-sm font-medium text-white flex items-center gap-2">
|
||||||
|
<span className="w-5 h-5 rounded-full bg-orange-600 text-white text-xs flex items-center justify-center font-bold">2</span>
|
||||||
|
Im WebGUI konfigurieren
|
||||||
|
</h4>
|
||||||
|
<p className="text-xs text-gray-400 ml-7">
|
||||||
|
Services > RMM Agent > folgende Werte eintragen:
|
||||||
|
</p>
|
||||||
|
<div className="ml-7 space-y-2">
|
||||||
|
<ConfigValue label="Backend URL" value={BACKEND_URL} id="opn-url" />
|
||||||
|
<ConfigValue label="API Key" value={API_KEY} id="opn-key" mono />
|
||||||
|
<ConfigValue label="Agent Name" value={agentName || '<NAME>'} id="opn-name" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Step 3: Enable + Start */}
|
||||||
|
<div className="space-y-2">
|
||||||
|
<h4 className="text-sm font-medium text-white flex items-center gap-2">
|
||||||
|
<span className="w-5 h-5 rounded-full bg-orange-600 text-white text-xs flex items-center justify-center font-bold">3</span>
|
||||||
|
Aktivieren und starten
|
||||||
|
</h4>
|
||||||
|
<p className="text-xs text-gray-400 ml-7">
|
||||||
|
"Enabled" aktivieren, "Save & Apply", dann "Restart Service".
|
||||||
|
Der Agent verbindet sich automatisch.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className="space-y-4">
|
||||||
|
{/* Linux: Single script */}
|
||||||
|
<div className="space-y-2">
|
||||||
|
<h4 className="text-sm font-medium text-white flex items-center gap-2">
|
||||||
|
<span className="w-5 h-5 rounded-full bg-blue-600 text-white text-xs flex items-center justify-center font-bold">1</span>
|
||||||
|
Installscript ausfuehren
|
||||||
|
</h4>
|
||||||
|
<p className="text-xs text-gray-400 ml-7">Als root auf dem Server ausfuehren. Script kopieren, als Datei speichern und starten:</p>
|
||||||
|
<div className="ml-7">
|
||||||
|
<CodeBlock text={linuxInstallCmd} id="linux-install" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Config values for reference */}
|
||||||
|
<div className="space-y-2">
|
||||||
|
<h4 className="text-sm font-medium text-white flex items-center gap-2">
|
||||||
|
<span className="w-5 h-5 rounded-full bg-blue-600 text-white text-xs flex items-center justify-center font-bold">2</span>
|
||||||
|
Konfigurationswerte (Referenz)
|
||||||
|
</h4>
|
||||||
|
<div className="ml-7 space-y-2">
|
||||||
|
<ConfigValue label="Backend URL" value={BACKEND_URL} id="linux-url" />
|
||||||
|
<ConfigValue label="API Key" value={API_KEY} id="linux-key" mono />
|
||||||
|
<ConfigValue label="Agent Name" value={agentName || '<NAME>'} id="linux-name" />
|
||||||
|
<ConfigValue label="Config-Datei" value="/etc/rmm/config.yaml" id="linux-cfg" mono />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<p className="text-xs text-gray-500 border-t border-gray-800 pt-3">
|
||||||
|
Der Agent meldet sich nach Installation automatisch beim Backend. Name und IP werden beim ersten Heartbeat uebernommen.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@ -2,7 +2,8 @@ import { useEffect, useState, useMemo } from 'react'
|
|||||||
import api from '../api/client'
|
import api from '../api/client'
|
||||||
import StatusBadge from '../components/StatusBadge'
|
import StatusBadge from '../components/StatusBadge'
|
||||||
import AgentPanel from '../components/AgentPanel'
|
import AgentPanel from '../components/AgentPanel'
|
||||||
import { Search, ChevronUp, ChevronDown, Plus, Copy, Check, X } from 'lucide-react'
|
import { Search, ChevronUp, ChevronDown, Plus, X } from 'lucide-react'
|
||||||
|
import InstallGuide from '../components/InstallGuide'
|
||||||
|
|
||||||
export default function Agents() {
|
export default function Agents() {
|
||||||
const [agents, setAgents] = useState([])
|
const [agents, setAgents] = useState([])
|
||||||
@ -276,10 +277,6 @@ function AddDeviceDialog({ customers, result, onAdd, onClose }) {
|
|||||||
const [custId, setCustId] = useState('')
|
const [custId, setCustId] = useState('')
|
||||||
const [error, setError] = useState('')
|
const [error, setError] = useState('')
|
||||||
const [submitting, setSubmitting] = useState(false)
|
const [submitting, setSubmitting] = useState(false)
|
||||||
const [copied, setCopied] = useState(null)
|
|
||||||
|
|
||||||
const BACKEND_URL = 'https://192.168.85.13:8443'
|
|
||||||
const API_KEY = '01532e5a7c9e70bf2757df77a2f5b9b9'
|
|
||||||
|
|
||||||
const handleSubmit = async () => {
|
const handleSubmit = async () => {
|
||||||
if (!name.trim()) { setError('Name ist erforderlich'); return }
|
if (!name.trim()) { setError('Name ist erforderlich'); return }
|
||||||
@ -293,39 +290,9 @@ function AddDeviceDialog({ customers, result, onAdd, onClose }) {
|
|||||||
setSubmitting(false)
|
setSubmitting(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
const copyText = (text, id) => {
|
|
||||||
navigator.clipboard.writeText(text)
|
|
||||||
setCopied(id)
|
|
||||||
setTimeout(() => setCopied(null), 2000)
|
|
||||||
}
|
|
||||||
|
|
||||||
const CopyBtn = ({ text, id }) => (
|
|
||||||
<button onClick={() => copyText(text, id)} className="ml-2 text-gray-500 hover:text-orange-400 transition-colors">
|
|
||||||
{copied === id ? <Check className="w-3.5 h-3.5 text-green-400" /> : <Copy className="w-3.5 h-3.5" />}
|
|
||||||
</button>
|
|
||||||
)
|
|
||||||
|
|
||||||
const installCmd = `# Vom Mac Studio aus ausfuehren:
|
|
||||||
|
|
||||||
# 1. Ins RMM-Verzeichnis wechseln:
|
|
||||||
cd /Users/cynfo/.openclaw/workspace/rmm
|
|
||||||
|
|
||||||
# 2. Agent + Updater + Installer auf das Geraet kopieren:
|
|
||||||
scp build/rmm-agent build/rmm-updater root@<FIREWALL-IP>:/tmp/
|
|
||||||
scp opnsense-plugin/install.sh root@<FIREWALL-IP>:/tmp/
|
|
||||||
|
|
||||||
# 3. Installation starten:
|
|
||||||
ssh root@<FIREWALL-IP> '/bin/sh /tmp/install.sh'
|
|
||||||
|
|
||||||
# 4. Im OPNsense WebGUI unter Services > RMM Agent:
|
|
||||||
# Backend URL: ${BACKEND_URL}
|
|
||||||
# API Key: ${API_KEY}
|
|
||||||
# Agent Name: ${name || '<NAME>'}
|
|
||||||
# -> Save & Apply`
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/60" onClick={onClose}>
|
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/60" onClick={onClose}>
|
||||||
<div className="bg-gray-900 border border-gray-700 rounded-lg shadow-xl w-full max-w-2xl mx-4" onClick={e => e.stopPropagation()}>
|
<div className="bg-gray-900 border border-gray-700 rounded-lg shadow-xl w-full max-w-2xl mx-4 max-h-[90vh] overflow-y-auto" onClick={e => e.stopPropagation()}>
|
||||||
<div className="flex items-center justify-between px-5 py-3 border-b border-gray-800">
|
<div className="flex items-center justify-between px-5 py-3 border-b border-gray-800">
|
||||||
<h2 className="text-lg font-semibold text-white">Geraet hinzufuegen</h2>
|
<h2 className="text-lg font-semibold text-white">Geraet hinzufuegen</h2>
|
||||||
<button onClick={onClose} className="text-gray-500 hover:text-white"><X className="w-5 h-5" /></button>
|
<button onClick={onClose} className="text-gray-500 hover:text-white"><X className="w-5 h-5" /></button>
|
||||||
@ -373,37 +340,7 @@ ssh root@<FIREWALL-IP> '/bin/sh /tmp/install.sh'
|
|||||||
<div className="bg-green-900/30 border border-green-800 rounded p-3 text-sm text-green-300">
|
<div className="bg-green-900/30 border border-green-800 rounded p-3 text-sm text-green-300">
|
||||||
Geraet "{result.name}" erfolgreich angelegt (ID: {result.id?.substring(0, 12)}...)
|
Geraet "{result.name}" erfolgreich angelegt (ID: {result.id?.substring(0, 12)}...)
|
||||||
</div>
|
</div>
|
||||||
|
<InstallGuide agentName={result.name} />
|
||||||
<div>
|
|
||||||
<h3 className="text-sm font-medium text-white mb-2">Installationsanleitung</h3>
|
|
||||||
<div className="bg-gray-950 rounded p-3 text-xs font-mono text-gray-300 whitespace-pre-wrap relative">
|
|
||||||
{installCmd}
|
|
||||||
<button
|
|
||||||
onClick={() => copyText(installCmd, 'install')}
|
|
||||||
className="absolute top-2 right-2 text-gray-600 hover:text-orange-400 transition-colors"
|
|
||||||
>
|
|
||||||
{copied === 'install' ? <Check className="w-4 h-4 text-green-400" /> : <Copy className="w-4 h-4" />}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="grid grid-cols-2 gap-3 text-sm">
|
|
||||||
<div>
|
|
||||||
<span className="text-gray-500">Backend URL:</span>
|
|
||||||
<span className="text-white ml-2">{BACKEND_URL}</span>
|
|
||||||
<CopyBtn text={BACKEND_URL} id="url" />
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<span className="text-gray-500">API Key:</span>
|
|
||||||
<span className="text-white ml-2 font-mono text-xs">{API_KEY}</span>
|
|
||||||
<CopyBtn text={API_KEY} id="key" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<p className="text-xs text-gray-500">
|
|
||||||
Der Agent verbindet sich nach der Installation automatisch mit dem Backend.
|
|
||||||
Hostname und IP werden beim ersten Heartbeat aktualisiert.
|
|
||||||
</p>
|
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -2,7 +2,8 @@ import { useEffect, useState, useMemo } from 'react'
|
|||||||
import api from '../api/client'
|
import api from '../api/client'
|
||||||
import StatusBadge from '../components/StatusBadge'
|
import StatusBadge from '../components/StatusBadge'
|
||||||
import ProxmoxPanel from '../components/ProxmoxPanel'
|
import ProxmoxPanel from '../components/ProxmoxPanel'
|
||||||
import { Search, ChevronUp, ChevronDown, Plus, Copy, Check, X } from 'lucide-react'
|
import { Search, ChevronUp, ChevronDown, Plus, X } from 'lucide-react'
|
||||||
|
import InstallGuide from '../components/InstallGuide'
|
||||||
|
|
||||||
export default function ProxmoxServers() {
|
export default function ProxmoxServers() {
|
||||||
const [agents, setAgents] = useState([])
|
const [agents, setAgents] = useState([])
|
||||||
@ -273,10 +274,6 @@ function AddServerDialog({ customers, result, onAdd, onClose }) {
|
|||||||
const [custId, setCustId] = useState('')
|
const [custId, setCustId] = useState('')
|
||||||
const [error, setError] = useState('')
|
const [error, setError] = useState('')
|
||||||
const [submitting, setSubmitting] = useState(false)
|
const [submitting, setSubmitting] = useState(false)
|
||||||
const [copied, setCopied] = useState(null)
|
|
||||||
|
|
||||||
const BACKEND_URL = 'https://192.168.85.13:8443'
|
|
||||||
const API_KEY = '01532e5a7c9e70bf2757df77a2f5b9b9'
|
|
||||||
|
|
||||||
const handleSubmit = async () => {
|
const handleSubmit = async () => {
|
||||||
if (!name.trim()) { setError('Name ist erforderlich'); return }
|
if (!name.trim()) { setError('Name ist erforderlich'); return }
|
||||||
@ -290,81 +287,9 @@ function AddServerDialog({ customers, result, onAdd, onClose }) {
|
|||||||
setSubmitting(false)
|
setSubmitting(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
const copyText = (text, id) => {
|
|
||||||
navigator.clipboard.writeText(text)
|
|
||||||
setCopied(id)
|
|
||||||
setTimeout(() => setCopied(null), 2000)
|
|
||||||
}
|
|
||||||
|
|
||||||
const CopyBtn = ({ text, id }) => (
|
|
||||||
<button onClick={() => copyText(text, id)} className="ml-2 text-gray-500 hover:text-orange-400 transition-colors">
|
|
||||||
{copied === id ? <Check className="w-3.5 h-3.5 text-green-400" /> : <Copy className="w-3.5 h-3.5" />}
|
|
||||||
</button>
|
|
||||||
)
|
|
||||||
|
|
||||||
const installCmd = `# Proxmox/Linux Server Installation:
|
|
||||||
|
|
||||||
# 1. Agent + Updater auf den Server kopieren:
|
|
||||||
scp build/rmm-agent-linux build/rmm-updater-linux root@<SERVER-IP>:/tmp/
|
|
||||||
|
|
||||||
# 2. Installation auf dem Server:
|
|
||||||
ssh root@<SERVER-IP> 'bash -s' << 'INSTALL'
|
|
||||||
mkdir -p /usr/local/bin /etc/rmm
|
|
||||||
|
|
||||||
cp /tmp/rmm-agent-linux /usr/local/bin/rmm-agent
|
|
||||||
cp /tmp/rmm-updater-linux /usr/local/bin/rmm-updater
|
|
||||||
chmod +x /usr/local/bin/rmm-agent /usr/local/bin/rmm-updater
|
|
||||||
|
|
||||||
# Config erstellen:
|
|
||||||
cat > /etc/rmm/config.yaml << EOF
|
|
||||||
backend_url: ${BACKEND_URL}
|
|
||||||
api_key: ${API_KEY}
|
|
||||||
agent_name: ${name || '<NAME>'}
|
|
||||||
heartbeat_interval: 30
|
|
||||||
insecure: true
|
|
||||||
EOF
|
|
||||||
|
|
||||||
# Agent Service:
|
|
||||||
cat > /etc/systemd/system/rmm-agent.service << EOF
|
|
||||||
[Unit]
|
|
||||||
Description=RMM Agent
|
|
||||||
After=network.target
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
Type=simple
|
|
||||||
User=root
|
|
||||||
ExecStart=/usr/local/bin/rmm-agent
|
|
||||||
Restart=always
|
|
||||||
RestartSec=10
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=multi-user.target
|
|
||||||
EOF
|
|
||||||
|
|
||||||
# Updater Service:
|
|
||||||
cat > /etc/systemd/system/rmm-updater.service << EOF
|
|
||||||
[Unit]
|
|
||||||
Description=RMM Updater
|
|
||||||
After=network.target
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
Type=simple
|
|
||||||
User=root
|
|
||||||
ExecStart=/usr/local/bin/rmm-updater
|
|
||||||
Restart=always
|
|
||||||
RestartSec=30
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=multi-user.target
|
|
||||||
EOF
|
|
||||||
|
|
||||||
systemctl daemon-reload
|
|
||||||
systemctl enable --now rmm-agent rmm-updater
|
|
||||||
INSTALL`
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/60" onClick={onClose}>
|
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/60" onClick={onClose}>
|
||||||
<div className="bg-gray-900 border border-gray-700 rounded-lg shadow-xl w-full max-w-2xl mx-4" onClick={e => e.stopPropagation()}>
|
<div className="bg-gray-900 border border-gray-700 rounded-lg shadow-xl w-full max-w-2xl mx-4 max-h-[90vh] overflow-y-auto" onClick={e => e.stopPropagation()}>
|
||||||
<div className="flex items-center justify-between px-5 py-3 border-b border-gray-800">
|
<div className="flex items-center justify-between px-5 py-3 border-b border-gray-800">
|
||||||
<h2 className="text-lg font-semibold text-white">Server hinzufuegen</h2>
|
<h2 className="text-lg font-semibold text-white">Server hinzufuegen</h2>
|
||||||
<button onClick={onClose} className="text-gray-500 hover:text-white"><X className="w-5 h-5" /></button>
|
<button onClick={onClose} className="text-gray-500 hover:text-white"><X className="w-5 h-5" /></button>
|
||||||
@ -412,37 +337,7 @@ INSTALL`
|
|||||||
<div className="bg-green-900/30 border border-green-800 rounded p-3 text-sm text-green-300">
|
<div className="bg-green-900/30 border border-green-800 rounded p-3 text-sm text-green-300">
|
||||||
Server "{result.name}" erfolgreich angelegt (ID: {result.id?.substring(0, 12)}...)
|
Server "{result.name}" erfolgreich angelegt (ID: {result.id?.substring(0, 12)}...)
|
||||||
</div>
|
</div>
|
||||||
|
<InstallGuide agentName={result.name} platform="linux" />
|
||||||
<div>
|
|
||||||
<h3 className="text-sm font-medium text-white mb-2">Installationsanleitung</h3>
|
|
||||||
<div className="bg-gray-950 rounded p-3 text-xs font-mono text-gray-300 whitespace-pre-wrap relative">
|
|
||||||
{installCmd}
|
|
||||||
<button
|
|
||||||
onClick={() => copyText(installCmd, 'install')}
|
|
||||||
className="absolute top-2 right-2 text-gray-600 hover:text-orange-400 transition-colors"
|
|
||||||
>
|
|
||||||
{copied === 'install' ? <Check className="w-4 h-4 text-green-400" /> : <Copy className="w-4 h-4" />}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="grid grid-cols-2 gap-3 text-sm">
|
|
||||||
<div>
|
|
||||||
<span className="text-gray-500">Backend URL:</span>
|
|
||||||
<span className="text-white ml-2">{BACKEND_URL}</span>
|
|
||||||
<CopyBtn text={BACKEND_URL} id="url" />
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<span className="text-gray-500">API Key:</span>
|
|
||||||
<span className="text-white ml-2 font-mono text-xs">{API_KEY}</span>
|
|
||||||
<CopyBtn text={API_KEY} id="key" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<p className="text-xs text-gray-500">
|
|
||||||
Der Agent verbindet sich nach der Installation automatisch mit dem Backend.
|
|
||||||
Hostname und IP werden beim ersten Heartbeat aktualisiert.
|
|
||||||
</p>
|
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -2,12 +2,13 @@
|
|||||||
#
|
#
|
||||||
# RMM Agent Plugin Installer fuer OPNsense
|
# RMM Agent Plugin Installer fuer OPNsense
|
||||||
#
|
#
|
||||||
# Usage:
|
# Usage (automatischer Download):
|
||||||
# scp install.sh rmm-agent root@opnsense:/tmp/
|
# fetch -o /tmp/install.sh "https://git.cynfo.net/christian/rmm/raw/branch/main/opnsense-plugin/install.sh"
|
||||||
# ssh root@opnsense '/bin/sh /tmp/install.sh'
|
# sh /tmp/install.sh
|
||||||
#
|
#
|
||||||
# Oder remote:
|
# Oder mit lokalen Binaries:
|
||||||
# cat install.sh | ssh root@opnsense '/bin/sh'
|
# scp install.sh rmm-agent rmm-updater-freebsd root@opnsense:/tmp/
|
||||||
|
# ssh root@opnsense '/bin/sh /tmp/install.sh'
|
||||||
#
|
#
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
@ -15,17 +16,36 @@ set -e
|
|||||||
BASEDIR="/tmp"
|
BASEDIR="/tmp"
|
||||||
BINARY="${BASEDIR}/rmm-agent"
|
BINARY="${BASEDIR}/rmm-agent"
|
||||||
UPDATER_BINARY="${BASEDIR}/rmm-updater"
|
UPDATER_BINARY="${BASEDIR}/rmm-updater"
|
||||||
|
BACKEND_URL="https://192.168.85.13:8443"
|
||||||
|
API_KEY="01532e5a7c9e70bf2757df77a2f5b9b9"
|
||||||
|
|
||||||
echo "========================================"
|
echo "========================================"
|
||||||
echo " RMM Agent Plugin Installer"
|
echo " RMM Agent Plugin Installer"
|
||||||
echo "========================================"
|
echo "========================================"
|
||||||
|
|
||||||
# Pruefen ob Binary vorhanden
|
# Binaries herunterladen wenn nicht lokal vorhanden
|
||||||
if [ ! -f "${BINARY}" ]; then
|
if [ ! -f "${BINARY}" ]; then
|
||||||
echo "FEHLER: ${BINARY} nicht gefunden."
|
echo "[*] Binaries nicht lokal gefunden — lade vom Backend..."
|
||||||
echo "Bitte vorher das Binary kopieren:"
|
/usr/local/bin/fetch --no-verify-peer -o "${BASEDIR}/rmm-bundle.zip" \
|
||||||
echo " scp rmm-agent root@opnsense:/tmp/"
|
"${BACKEND_URL}/api/v1/firmware/download?platform=freebsd&api_key=${API_KEY}"
|
||||||
exit 1
|
if [ ! -f "${BASEDIR}/rmm-bundle.zip" ]; then
|
||||||
|
echo "FEHLER: Download fehlgeschlagen."
|
||||||
|
echo "Pruefe Backend-Erreichbarkeit: ${BACKEND_URL}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
cd "${BASEDIR}"
|
||||||
|
unzip -o rmm-bundle.zip 2>/dev/null || true
|
||||||
|
# ZIP enthaelt rmm-agent und rmm-updater-freebsd
|
||||||
|
if [ -f "${BASEDIR}/rmm-updater-freebsd" ] && [ ! -f "${UPDATER_BINARY}" ]; then
|
||||||
|
mv "${BASEDIR}/rmm-updater-freebsd" "${UPDATER_BINARY}"
|
||||||
|
fi
|
||||||
|
rm -f rmm-bundle.zip
|
||||||
|
echo " Download OK"
|
||||||
|
if [ ! -f "${BINARY}" ]; then
|
||||||
|
echo "FEHLER: ${BINARY} nach Download nicht vorhanden."
|
||||||
|
echo "Firmware-ZIP muss 'rmm-agent' enthalten."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Alten Agent stoppen falls vorhanden
|
# Alten Agent stoppen falls vorhanden
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user