Merge pull request #300 from outis1one/claude/ionos-script-integration-x32ofw
Add beszel-agent: agent-only Beszel install for remote/homelab boxes
This commit is contained in:
@@ -186,7 +186,7 @@ a ready-to-copy Caddy config snippet to `~/docker/caddy-snippets/`.
|
|||||||
|-------|---------|
|
|-------|---------|
|
||||||
| `base` | `net-tools`, `ncdu`, `git`, `curl`, `wget`, `htop`, `tree`, `zip`/`unzip`, `ca-certificates`, `gnupg`, `jq`, `rsync`; `glow` (terminal markdown reader, Charm apt repo); Docker CE + Compose plugin; `openssh-server` with GitHub/Launchpad SSH key import, optional password-auth lockdown, and SSH Host aliases; optional NetBird overlay network |
|
| `base` | `net-tools`, `ncdu`, `git`, `curl`, `wget`, `htop`, `tree`, `zip`/`unzip`, `ca-certificates`, `gnupg`, `jq`, `rsync`; `glow` (terminal markdown reader, Charm apt repo); Docker CE + Compose plugin; `openssh-server` with GitHub/Launchpad SSH key import, optional password-auth lockdown, and SSH Host aliases; optional NetBird overlay network |
|
||||||
| `homelab` | `caddy`, `crowdsec`, `authelia`, `coturn` (shared TURN/STUN relay — Asterisk, Mattermost Calls, and future WebRTC-capable services all register a dedicated credential against one instance instead of each running its own), `homeassistant`, `asterisk`, `pstn-trunk`, `sms-inbound`, `security-dashboard`, `sunshine`, `vpn-data-mount` (mount existing SMB shares from a NetBird-connected home box — SSH trust bootstrap, then read-only discovery of shares already configured there; never writes to the home box's Samba config; repeatable, pick from any number of a home box's shares in one pass; optional per-share [gocryptfs decrypt layer](#client-side-encryption-for-vpn-data-mount) so the VPS only ever handles ciphertext) |
|
| `homelab` | `caddy`, `crowdsec`, `authelia`, `coturn` (shared TURN/STUN relay — Asterisk, Mattermost Calls, and future WebRTC-capable services all register a dedicated credential against one instance instead of each running its own), `homeassistant`, `asterisk`, `pstn-trunk`, `sms-inbound`, `security-dashboard`, `sunshine`, `vpn-data-mount` (mount existing SMB shares from a NetBird-connected home box — SSH trust bootstrap, then read-only discovery of shares already configured there; never writes to the home box's Samba config; repeatable, pick from any number of a home box's shares in one pass; optional per-share [gocryptfs decrypt layer](#client-side-encryption-for-vpn-data-mount) so the VPS only ever handles ciphertext) |
|
||||||
| `utilities` | `actualbudget`, `ai-gpu`, `ai-stack`, `archivebox`, `beszel` (lightweight server + Docker monitoring — CPU/RAM/disk/network, auto-discovers running containers via the Docker socket; complements Gatus rather than replacing it — Gatus is a black-box HTTP check, Beszel is white-box host/process monitoring), `changedetection`, `ddclient`, `filebrowser`, `fmd`, `gatus`, `homebox`, `iopaint`, `joplin`, `koha`, `magicmirror`, `mail-archiver`, `mattermost`, `mealie`, `meshcentral`, `n8n`, `nextcloud`, `ntfy`, `onlyoffice`, `paintplus`, `portainer`, `rustdesk`, `stirling-pdf`, `syncthing`, `traccar`, `unifi`, `uptimekuma`, `vaultwarden`, `watchyourlan`, `watchtower`, `wg-easy`, `wordpress` (multi-site, dedicated MariaDB per site — blogs, business sites, e-commerce via WooCommerce) |
|
| `utilities` | `actualbudget`, `ai-gpu`, `ai-stack`, `archivebox`, `beszel` (lightweight server + Docker monitoring — CPU/RAM/disk/network, auto-discovers running containers via the Docker socket; complements Gatus rather than replacing it — Gatus is a black-box HTTP check, Beszel is white-box host/process monitoring), `beszel-agent` (agent-only Beszel install for a remote/homelab box reporting to a hub elsewhere — connects outbound over HTTPS, no VPN/port-forwarding/FQDN needed on that box), `changedetection`, `ddclient`, `filebrowser`, `fmd`, `gatus`, `homebox`, `iopaint`, `joplin`, `koha`, `magicmirror`, `mail-archiver`, `mattermost`, `mealie`, `meshcentral`, `n8n`, `nextcloud`, `ntfy`, `onlyoffice`, `paintplus`, `portainer`, `rustdesk`, `stirling-pdf`, `syncthing`, `traccar`, `unifi`, `uptimekuma`, `vaultwarden`, `watchyourlan`, `watchtower`, `wg-easy`, `wordpress` (multi-site, dedicated MariaDB per site — blogs, business sites, e-commerce via WooCommerce) |
|
||||||
| `media` | `arm`, `audiobookshelf`, `calibre-web`, `emby`, `immich`, `jellyfin`, `lyrion` |
|
| `media` | `arm`, `audiobookshelf`, `calibre-web`, `emby`, `immich`, `jellyfin`, `lyrion` |
|
||||||
| `cameras` | `frigate`, `frigate-audio`, `frigate-notify`, `sky-cam` |
|
| `cameras` | `frigate`, `frigate-audio`, `frigate-notify`, `sky-cam` |
|
||||||
| `gaming` | `drum-rhythm-game`, `js99er`, `kyber-launcher`, `kyber-server`, `minecraft`, `wolf`, `wolf-pair` |
|
| `gaming` | `drum-rhythm-game`, `js99er`, `kyber-launcher`, `kyber-server`, `minecraft`, `wolf`, `wolf-pair` |
|
||||||
|
|||||||
+151
-8
@@ -149,11 +149,11 @@ _beszel_extract_field() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_beszel_configure_agent() {
|
_beszel_configure_agent() {
|
||||||
local dir="$1" web_port="$2"
|
local dir="$1" login_url="$2"
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo " To finish connecting the agent, log into the hub first:"
|
echo " To finish connecting the agent, log into the hub first:"
|
||||||
echo " http://localhost:${web_port} (or its Caddy domain, once configured)"
|
echo " ${login_url}"
|
||||||
echo ""
|
echo ""
|
||||||
echo " Create the admin account, then go to Settings → Tokens & Fingerprints:"
|
echo " Create the admin account, then go to Settings → Tokens & Fingerprints:"
|
||||||
echo " - Enable the universal token"
|
echo " - Enable the universal token"
|
||||||
@@ -234,9 +234,10 @@ install_beszel() {
|
|||||||
&& log_success "Beszel images refreshed" \
|
&& log_success "Beszel images refreshed" \
|
||||||
|| log_warning "Refresh failed — check: docker compose -f $DIR/docker-compose.yml logs"
|
|| log_warning "Refresh failed — check: docker compose -f $DIR/docker-compose.yml logs"
|
||||||
if ! grep -q '^AGENT_KEY=' "$DIR/.env" 2>/dev/null; then
|
if ! grep -q '^AGENT_KEY=' "$DIR/.env" 2>/dev/null; then
|
||||||
local FINISH_AGENT=""
|
local FINISH_AGENT="" _WP
|
||||||
|
_WP="$(grep '^BESZEL_WEB_PORT=' "$DIR/.env" 2>/dev/null | cut -d= -f2-)"
|
||||||
prompt_yn " The agent was never connected — set it up now? (y/n):" "y" FINISH_AGENT
|
prompt_yn " The agent was never connected — set it up now? (y/n):" "y" FINISH_AGENT
|
||||||
[[ "$FINISH_AGENT" =~ ^[Yy]$ ]] && _beszel_configure_agent "$DIR" "$(grep '^BESZEL_WEB_PORT=' "$DIR/.env" 2>/dev/null | cut -d= -f2-)"
|
[[ "$FINISH_AGENT" =~ ^[Yy]$ ]] && _beszel_configure_agent "$DIR" "http://localhost:${_WP} (or its Caddy domain, once configured)"
|
||||||
fi
|
fi
|
||||||
return 0
|
return 0
|
||||||
;;
|
;;
|
||||||
@@ -347,7 +348,7 @@ BESZEL_ENV
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
_beszel_configure_agent "$DIR" "$WEB_PORT"
|
_beszel_configure_agent "$DIR" "http://localhost:${WEB_PORT} (or its Caddy domain, once configured)"
|
||||||
|
|
||||||
write_readme "$DIR" << 'BESZEL_README'
|
write_readme "$DIR" << 'BESZEL_README'
|
||||||
# Beszel — lightweight server + Docker monitoring
|
# Beszel — lightweight server + Docker monitoring
|
||||||
@@ -378,9 +379,13 @@ available after logging in:
|
|||||||
|
|
||||||
## Monitoring additional boxes
|
## Monitoring additional boxes
|
||||||
|
|
||||||
Add another agent from the hub's UI ("Add System") — that generates the
|
Add another agent from the hub's UI ("Add System") to generate its
|
||||||
connection details for a *remote* box's agent. This installer only sets
|
connection details, then on the OTHER box (a homelab machine, not this
|
||||||
up the agent for the box it's run on.
|
VPS) run `sudo ./setup.sh beszel-agent` — a separate, agent-only install
|
||||||
|
(no hub, no web UI) built for exactly this. It connects OUTBOUND to this
|
||||||
|
hub over HTTPS, so no VPN, port-forwarding, or FQDN is needed for that box
|
||||||
|
— only this hub needs to be reachable, which it already is. See
|
||||||
|
`services/beszel.sh`'s `install_beszel-agent()`.
|
||||||
|
|
||||||
## Fronting this with Caddy
|
## Fronting this with Caddy
|
||||||
|
|
||||||
@@ -407,4 +412,142 @@ BESZEL_README
|
|||||||
log_success "Beszel configured at $DIR"
|
log_success "Beszel configured at $DIR"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# ── Agent-only install, for a box that ISN'T the hub ────────────────────────
|
||||||
|
# A second register_service in this same file — precedented by base.sh's
|
||||||
|
# base+glow — rather than a separate services/beszel-agent.sh, since this
|
||||||
|
# shares _beszel_extract_field/_beszel_configure_agent with install_beszel()
|
||||||
|
# above and would otherwise duplicate that paste/parse logic across two
|
||||||
|
# files. Run this on a homelab/remote box (a plain VPN peer isn't needed —
|
||||||
|
# see the README this writes for why) pointed at a hub running on THIS repo's
|
||||||
|
# main box (install_beszel() above, or any other Beszel hub).
|
||||||
|
register_service beszel-agent utilities "Beszel monitoring AGENT only, for a remote/homelab box reporting to a hub running elsewhere"
|
||||||
|
|
||||||
|
install_beszel-agent() {
|
||||||
|
require_docker || return 1
|
||||||
|
log_info "Installing the Beszel agent (reports to a hub running on another machine)..."
|
||||||
|
|
||||||
|
local DIR="$DOCKER_DIR/beszel-agent"
|
||||||
|
|
||||||
|
if [ "$DRY_RUN" = true ]; then
|
||||||
|
echo "[DRY-RUN] Would create $DIR"
|
||||||
|
echo "[DRY-RUN] Would deploy henrygd/beszel-agent only (no hub, no web UI on this box)"
|
||||||
|
echo "[DRY-RUN] network_mode: host, /var/run/docker.sock mounted read-only"
|
||||||
|
echo "[DRY-RUN] Would prompt for the hub's public URL, then its key + universal token"
|
||||||
|
echo "[DRY-RUN] (same paste flow as the hub-side installer)"
|
||||||
|
echo "[DRY-RUN] No inbound port opened — the agent connects OUTBOUND to the hub, so no"
|
||||||
|
echo "[DRY-RUN] VPN, port-forwarding, or FQDN is needed for THIS box"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -f "$DIR/docker-compose.yml" && -f "$DIR/.env" ]]; then
|
||||||
|
local MODE=""
|
||||||
|
prompt_reinstall_mode MODE
|
||||||
|
case "$MODE" in
|
||||||
|
update)
|
||||||
|
log_info "Refreshing the image only — existing hub URL/key/token are left as-is."
|
||||||
|
( cd "$DIR" && docker compose pull && docker compose up -d ) \
|
||||||
|
&& log_success "Beszel agent image refreshed" \
|
||||||
|
|| log_warning "Refresh failed — check: docker compose -f $DIR/docker-compose.yml logs"
|
||||||
|
if ! grep -q '^AGENT_KEY=' "$DIR/.env" 2>/dev/null; then
|
||||||
|
local FINISH_AGENT="" _HUB_URL
|
||||||
|
_HUB_URL="$(grep '^HUB_URL=' "$DIR/.env" 2>/dev/null | cut -d= -f2-)"
|
||||||
|
prompt_yn " The agent was never connected — set it up now? (y/n):" "y" FINISH_AGENT
|
||||||
|
[[ "$FINISH_AGENT" =~ ^[Yy]$ ]] && _beszel_configure_agent "$DIR" "$_HUB_URL"
|
||||||
|
fi
|
||||||
|
return 0
|
||||||
|
;;
|
||||||
|
cancel)
|
||||||
|
log_info "Leaving the existing install as-is."
|
||||||
|
return 0
|
||||||
|
;;
|
||||||
|
fresh) ;; # fall through to the full install flow below
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir -p "$DIR/beszel_agent_data"
|
||||||
|
ensure_docker_dir_ownership "$DIR"
|
||||||
|
cd "$DIR" || return 1
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo " This box's agent connects OUTBOUND to a Beszel hub running elsewhere"
|
||||||
|
echo " (e.g. your VPS) — no VPN, no router port-forwarding, and no FQDN needed"
|
||||||
|
echo " for THIS box. Only the hub itself needs to already be reachable."
|
||||||
|
echo ""
|
||||||
|
local HUB_URL=""
|
||||||
|
while [ -z "$HUB_URL" ]; do
|
||||||
|
prompt_text " Hub URL (e.g. https://beszel.yourdomain.com, or http://vps-ip:port):" "" HUB_URL
|
||||||
|
[ -z "$HUB_URL" ] && log_warning " A hub URL is required."
|
||||||
|
done
|
||||||
|
|
||||||
|
# No network_mode: host caveat here beyond what install_beszel() already
|
||||||
|
# documents — same reasoning (accurate host network-interface stats),
|
||||||
|
# and there's no caddy_net to conditionally join since this box never
|
||||||
|
# runs a web UI of its own.
|
||||||
|
cat > docker-compose.yml << AGENT_COMPOSE
|
||||||
|
name: beszel-agent
|
||||||
|
|
||||||
|
services:
|
||||||
|
beszel-agent:
|
||||||
|
image: henrygd/beszel-agent:latest
|
||||||
|
container_name: beszel-agent
|
||||||
|
restart: unless-stopped
|
||||||
|
network_mode: host
|
||||||
|
env_file: .env
|
||||||
|
environment:
|
||||||
|
- HUB_URL=\${HUB_URL}
|
||||||
|
- TOKEN=\${AGENT_TOKEN:-}
|
||||||
|
- KEY=\${AGENT_KEY:-}
|
||||||
|
volumes:
|
||||||
|
- ./beszel_agent_data:/var/lib/beszel-agent
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||||
|
AGENT_COMPOSE
|
||||||
|
|
||||||
|
cat > .env << AGENT_ENV
|
||||||
|
TZ=${SITE_TZ:-$(cat /etc/timezone 2>/dev/null || echo UTC)}
|
||||||
|
HUB_URL=$HUB_URL
|
||||||
|
AGENT_ENV
|
||||||
|
chmod 600 .env
|
||||||
|
|
||||||
|
_beszel_configure_agent "$DIR" "$HUB_URL"
|
||||||
|
|
||||||
|
write_readme "$DIR" << AGENT_README_MD
|
||||||
|
# Beszel agent (remote/homelab box)
|
||||||
|
|
||||||
|
Reports this box's host resources and Docker container stats to a Beszel
|
||||||
|
HUB running elsewhere — no hub, no web UI, nothing web-facing on this box
|
||||||
|
at all.
|
||||||
|
|
||||||
|
## Connecting (if you skipped it during install)
|
||||||
|
|
||||||
|
Same flow as the hub side, just on a different machine: log into the hub at
|
||||||
|
\`$HUB_URL\`, go to Settings → Tokens & Fingerprints, enable the universal
|
||||||
|
token, and paste whatever it gives you (the "copy for docker compose"
|
||||||
|
shortcut works fine) by re-running:
|
||||||
|
|
||||||
|
\`\`\`bash
|
||||||
|
sudo ./setup.sh beszel-agent
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
## Why no VPN or port-forwarding
|
||||||
|
|
||||||
|
This agent connects OUTBOUND to the hub over HTTPS/WebSocket using the key
|
||||||
|
and token above — nothing on this box ever needs to be reached FROM the
|
||||||
|
hub, so there's no inbound port to open, no router port-forward, no VPN
|
||||||
|
tunnel, and no FQDN needed for this box itself. Only the hub needs to
|
||||||
|
already be reachable at the URL you gave it.
|
||||||
|
|
||||||
|
## Manage
|
||||||
|
|
||||||
|
\`\`\`bash
|
||||||
|
docker compose up -d
|
||||||
|
docker compose logs -f
|
||||||
|
docker compose pull && docker compose up -d
|
||||||
|
docker compose down
|
||||||
|
\`\`\`
|
||||||
|
AGENT_README_MD
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
log_success "Beszel agent configured at $DIR — connecting to $HUB_URL"
|
||||||
|
}
|
||||||
|
|
||||||
[[ "${_RUN_STANDALONE:-0}" == 1 ]] && install_beszel
|
[[ "${_RUN_STANDALONE:-0}" == 1 ]] && install_beszel
|
||||||
|
|||||||
Reference in New Issue
Block a user