-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathinstall.sh
More file actions
executable file
·256 lines (229 loc) · 7.75 KB
/
Copy pathinstall.sh
File metadata and controls
executable file
·256 lines (229 loc) · 7.75 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
#!/usr/bin/env bash
set -euo pipefail
# HomeLab Agent Installer
# Usage: sudo ./install.sh --dashboard-url https://HOST/api --api-key-file /secure/path/agent-key
#
# This script:
# 1. Detects the OS and installs prerequisites (lm-sensors, vnstat, smartmontools)
# 2. Installs Node.js 24 if not present
# 3. Clones (or updates) the agent to /opt/homelab-agent
# 4. Builds TypeScript
# 5. Creates a systemd service that runs as root
INSTALL_DIR="/opt/homelab-agent"
SERVICE_NAME="homelab-agent"
REPO_URL="https://github.com/johnvexcoder/HomeLab-Agent.git"
MIN_NODE_MAJOR=24
# ── Parse args ──
DASHBOARD_URL=""
API_KEY=""
API_KEY_FILE=""
ALLOW_INSECURE_HTTP="false"
while [[ $# -gt 0 ]]; do
case "$1" in
--dashboard-url) DASHBOARD_URL="$2"; shift 2 ;;
--api-key) API_KEY="$2"; shift 2 ;;
--api-key-file) API_KEY_FILE="$2"; shift 2 ;;
--allow-insecure-http) ALLOW_INSECURE_HTTP="true"; shift ;;
*) echo "Unknown arg: $1"; exit 1 ;;
esac
done
if [[ -z "$DASHBOARD_URL" || ( -z "$API_KEY" && -z "$API_KEY_FILE" ) ]]; then
echo "Usage: sudo ./install.sh --dashboard-url https://HOST/api --api-key-file /secure/path/agent-key"
exit 1
fi
if [[ -n "$API_KEY_FILE" ]]; then
API_KEY_FILE=$(readlink -f "$API_KEY_FILE")
[[ -r "$API_KEY_FILE" ]] || { echo "[installer] ERROR: API key file is not readable"; exit 1; }
API_KEY=$(tr -d '\r\n' < "$API_KEY_FILE")
fi
if [[ "$DASHBOARD_URL" == http://* ]] && [[ "$DASHBOARD_URL" != http://localhost* ]] && [[ "$DASHBOARD_URL" != http://127.0.0.1* ]] && [[ "$ALLOW_INSECURE_HTTP" != "true" ]]; then
echo "[installer] ERROR: refusing plaintext HTTP. Use HTTPS or add --allow-insecure-http for a trusted LAN."
exit 1
fi
# ── Detect OS ──
# Proxmox reports ID=debian in /etc/os-release, so we also check for
# Proxmox-specific files and package manager markers.
detect_os() {
local os_id="unknown"
if [[ -f /etc/os-release ]]; then
. /etc/os-release
os_id="$ID"
fi
# Proxmox detection: /etc/pve exists, or pve-manager is installed, or PRETTY_NAME mentions Proxmox
if [[ -d /etc/pve ]] || dpkg -l pve-manager 2>/dev/null | grep -q "^ii" || [[ "${PRETTY_NAME:-}" == *"Proxmox"* ]]; then
os_id="proxmox"
fi
echo "$os_id"
}
OS_ID=$(detect_os)
echo "[installer] Detected OS: $OS_ID"
# ── Install prerequisites ──
install_prereqs() {
case "$OS_ID" in
debian|ubuntu|linuxmint|pop)
echo "[installer] Installing prerequisites via apt..."
apt-get update -qq
apt-get install -y -qq git curl lm-sensors vnstat smartmontools build-essential
;;
proxmox)
echo "[installer] Installing prerequisites for Proxmox..."
apt-get update -qq
apt-get install -y -qq git curl lm-sensors vnstat smartmontools build-essential
;;
fedora|rhel|centos|rocky|alma)
echo "[installer] Installing prerequisites via dnf..."
dnf install -y git curl lm_sensors vnstat smartmontools gcc gcc-c++ make
;;
arch|manjaro)
echo "[installer] Installing prerequisites via pacman..."
pacman -Sy --noconfirm git curl lm_sensors vnstat smartmontools base-devel
;;
alpine)
echo "[installer] Installing prerequisites via apk..."
apk add --no-cache git curl lm_sensors vnstat smartmontools build-base python3
;;
*)
echo "[installer] Unknown OS ($OS_ID). Attempting apt..."
apt-get update -qq && apt-get install -y -qq git curl lm-sensors vnstat smartmontools build-essential 2>/dev/null || \
dnf install -y git curl lm_sensors vnstat smartmontools gcc gcc-c++ make 2>/dev/null || \
{ echo "[installer] ERROR: Could not install prerequisites. Install manually: git curl lm-sensors vnstat smartmontools"; exit 1; }
;;
esac
}
# ── Install Node.js ──
install_node() {
if command -v node &>/dev/null; then
local node_major
node_major=$(node -v | sed 's/v\([0-9]*\).*/\1/')
if [[ "$node_major" -ge "$MIN_NODE_MAJOR" ]]; then
echo "[installer] Node.js $(node -v) already installed"
return
fi
echo "[installer] Node.js v$(node -v) is too old (need >= $MIN_NODE_MAJOR)"
fi
echo "[installer] Installing Node.js 24..."
case "$OS_ID" in
debian|ubuntu|linuxmint|pop|proxmox)
curl -fsSL https://deb.nodesource.com/setup_24.x | bash -
apt-get install -y -qq nodejs
;;
fedora|rhel|centos|rocky|alma)
curl -fsSL https://rpm.nodesource.com/setup_24.x | bash -
dnf install -y nodejs
;;
*)
# Fallback: direct binary
local ARCH
ARCH=$(uname -m)
case "$ARCH" in
x86_64) ARCH="x64" ;;
aarch64) ARCH="arm64" ;;
armv7l) ARCH="armv7l" ;;
esac
local NODE_URL="https://nodejs.org/dist/v24.20.0/node-v24.20.0-linux-${ARCH}.tar.xz"
echo "[installer] Downloading Node.js binary..."
curl -fsSL "$NODE_URL" | tar -xJ -C /usr/local --strip-components=1
;;
esac
echo "[installer] Node.js $(node -v) installed"
}
# ── Clone / update agent ──
install_agent() {
if [[ -d "$INSTALL_DIR/.git" ]]; then
echo "[installer] Updating existing agent at $INSTALL_DIR..."
cd "$INSTALL_DIR"
git pull --ff-only 2>/dev/null || echo "[installer] git pull failed, continuing with existing code"
else
echo "[installer] Cloning agent to $INSTALL_DIR..."
rm -rf "$INSTALL_DIR"
git clone "$REPO_URL" "$INSTALL_DIR"
cd "$INSTALL_DIR"
fi
echo "[installer] Installing npm dependencies (including dev for build)..."
npm ci 2>/dev/null || npm install
echo "[installer] Building TypeScript..."
npx -p typescript tsc
echo "[installer] Pruning dev dependencies..."
npm prune --omit=dev
}
# ── Create systemd service ──
create_service() {
local ENV_FILE="$INSTALL_DIR/.env"
local CONFIG_DIR="/etc/homelab-agent"
local STATE_DIR="/var/lib/homelab-agent"
install -d -m 700 "$CONFIG_DIR" "$STATE_DIR"
printf '%s\n' "$API_KEY" > "$CONFIG_DIR/agent-api-key"
chmod 600 "$CONFIG_DIR/agent-api-key"
cat > "$ENV_FILE" <<EOF
DASHBOARD_URL=$DASHBOARD_URL
API_KEY_FILE=$CONFIG_DIR/agent-api-key
ALLOW_INSECURE_HTTP=$ALLOW_INSECURE_HTTP
POLL_INTERVAL=10000
EVENT_CHECK_INTERVAL=5000
LOG_LEVEL=info
STATE_DIR=$STATE_DIR
EOF
chmod 600 "$ENV_FILE"
cat > "/etc/systemd/system/${SERVICE_NAME}.service" <<EOF
[Unit]
Description=HomeLab Agent
After=network-online.target docker.service
Wants=network-online.target
StartLimitIntervalSec=300
StartLimitBurst=10
[Service]
Type=simple
ExecStart=/usr/bin/node $INSTALL_DIR/dist/index.js
WorkingDirectory=$INSTALL_DIR
EnvironmentFile=$ENV_FILE
Restart=always
RestartSec=10
StandardOutput=journal
StandardError=journal
SyslogIdentifier=homelab-agent
UMask=0077
NoNewPrivileges=yes
PrivateTmp=yes
ProtectHome=yes
ProtectSystem=strict
ReadWritePaths=$STATE_DIR
ProtectKernelTunables=yes
ProtectKernelModules=yes
ProtectControlGroups=yes
ProtectClock=yes
RestrictSUIDSGID=yes
RestrictRealtime=yes
LockPersonality=yes
RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6 AF_NETLINK
SystemCallArchitectures=native
LimitNOFILE=8192
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable "$SERVICE_NAME"
systemctl restart "$SERVICE_NAME"
echo "[installer] Service '$SERVICE_NAME' created and started"
}
# ── Main ──
echo "========================================="
echo " HomeLab Agent Installer"
echo "========================================="
echo ""
install_prereqs
install_node
install_agent
create_service
echo ""
echo "========================================="
echo " Installation complete!"
echo "========================================="
echo ""
echo " Dashboard: $DASHBOARD_URL"
echo " Service: systemctl status $SERVICE_NAME"
echo " Logs: journalctl -u $SERVICE_NAME -f"
echo " Config: $INSTALL_DIR/.env"
echo ""
echo " The agent will appear in your dashboard"
echo " within 10-15 seconds."
echo ""