mirror of
https://github.com/Dvorinka/beszel.git
synced 2026-07-29 07:13:48 +00:00
Initial commit: Beszel fork with Domain Locker integration
This commit is contained in:
@@ -0,0 +1,513 @@
|
||||
## 0.18.7
|
||||
|
||||
- Add more disk I/O metrics (utilization, read/write time, await, queue depth) (#1866)
|
||||
|
||||
- Add ability to copy alerts between systems (#1853)
|
||||
|
||||
- Add `SENSORS_TIMEOUT` environment variable (#1871)
|
||||
|
||||
- Replace `distatus/battery` with an internal implementation (#1872)
|
||||
|
||||
- Restrict universal token API to non-superuser accounts (#1870)
|
||||
|
||||
- Fix macOS ARM64 crashes by upgrading `gopsutil` to v4.26.3 (#1881, #796)
|
||||
|
||||
- Fix text size for system names in grid view (#1860)
|
||||
|
||||
- Fix NVMe capacity reporting for Apple SSDs (#1873)
|
||||
|
||||
- Fix Windows root disk detection when the executable is not on the root disk (#1863)
|
||||
|
||||
- Fix nested virtual filesystem inclusion in Docker when mounting host root (#1859)
|
||||
|
||||
- Fix OPNsense installation persistence by using the daemon user (#1880)
|
||||
|
||||
- Upgrade JS dependencies with dependabot security alerts (#1882)
|
||||
|
||||
- Upgrade PocketBase to latest version
|
||||
|
||||
## 0.18.6
|
||||
|
||||
- Add apple-touch-icon link to index.html (#1850)
|
||||
|
||||
- Fix UI bug where charts did not display 1m max until next update
|
||||
|
||||
- Fix regression in partition discovery on Docker (#1847)
|
||||
|
||||
- Fix agent detection of Podman when using socket proxy (#1846)
|
||||
|
||||
- Fix NVML GPU collection being disabled when `nvidia-smi` is not in PATH (#1849)
|
||||
|
||||
- Reset SMART interval on agent reconnect if the agent hasn't collected SMART data, allowing config changes to take effect immediately
|
||||
|
||||
## 0.18.5
|
||||
|
||||
- Add "update available" notification in hub web UI with `CHECK_UPDATES=true` (#1830)
|
||||
|
||||
- Add Linux mdraid health monitoring (#1750)
|
||||
|
||||
- Add ports column to containers table (#1481)
|
||||
|
||||
- Allow Linux systemd timer monitoring with `SERVICE_PATTERNS` (#1820)
|
||||
|
||||
- Add ZFS ARC support on FreeBSD
|
||||
|
||||
- Add optional tabs layout on web UI system page (#1513)
|
||||
|
||||
- Improve web UI performance and mobile styles
|
||||
|
||||
- Improve disk discovery and I/O device matching (#1811, #1772)
|
||||
|
||||
- Improve (likely fix) status alert reliability (#1519)
|
||||
|
||||
- Fix temperature collection blocking agent stats on some systems (#1839)
|
||||
|
||||
- Fix `SMART_INTERVAL` consistency across agent reconnects (#1800)
|
||||
|
||||
- Fix container health status for Podman (#1475)
|
||||
|
||||
- Fix disk usage averaging for extra disk alerts using historical records (#1801)
|
||||
|
||||
- Fix bandwidth alert computation from byte-per-second source (#1770)
|
||||
|
||||
- Fix 1m chart view leading to inflated Docker network IO during use
|
||||
|
||||
- Fix light flashes when refreshing in dark mode (#1832)
|
||||
|
||||
- Fix daylight saving time offset handling in daily quiet hours (#1827)
|
||||
|
||||
- Fix potential nil pointer panics in hub realtime worker and websocket ping
|
||||
|
||||
- Fix NIC auto-filter bypass when explicitly whitelisted (#1805)
|
||||
|
||||
- Fix ATA device statistics handling for negative values (#1791)
|
||||
|
||||
- Fix AMD GPU sysfs filesize misreporting workaround (#1799)
|
||||
|
||||
- Fix macOS agent path lookup for `macmon` (#1746)
|
||||
|
||||
- Update Go version and dependencies
|
||||
|
||||
## 0.18.4
|
||||
|
||||
- Add outbound heartbeat monitoring to external services (#1729)
|
||||
|
||||
- Add experimental GPU monitoring for Apple Silicon. (#1747, #1746)
|
||||
|
||||
- Add `nvtop` integration for GPU monitoring. (#1508)
|
||||
|
||||
- Add `GPU_COLLECTOR` environment variable to manually specify the GPU collector(s).
|
||||
|
||||
- Add eMMC health monitoring via sysfs. (#1736)
|
||||
|
||||
- Add uptime to systems table. (#1719)
|
||||
|
||||
- Add `DISABLE_SSH` environment variable to disable SSH agent functionality. (#1061)
|
||||
|
||||
- Add `fingerprint` command to the agent. (#1726)
|
||||
|
||||
- Add precise value entry for alerts via text input. (#1718)
|
||||
|
||||
- Include GTT memory in AMD GPU metrics and improve device name lookup. (#1569)
|
||||
|
||||
- Improve multiplexed logs detection for Podman. (#1755)
|
||||
|
||||
- Harden against Docker API path traversal.
|
||||
|
||||
- Fix issue where the agent could report incorrect root disk I/O when running in Docker. (#1737)
|
||||
|
||||
- Retry Docker check on non-200 HTTP response. (#1754)
|
||||
|
||||
- Fix race issue with meter threshold colors.
|
||||
|
||||
- Update Go version and dependencies.
|
||||
|
||||
- Add `InstallMethod` parameter to Windows install script.
|
||||
|
||||
## 0.18.3
|
||||
|
||||
- Add experimental sysfs AMD GPU collector. (#737, #1569)
|
||||
|
||||
- Update LibreHardwareMonitorLib to 0.9.5. (#1697)
|
||||
|
||||
- Improve container network stats accuracy.
|
||||
|
||||
- Fix `SHARE_ALL_SYSTEMS` for system_details, smart_devices, and systemd_services. (#1660)
|
||||
|
||||
- Parse ATA device statistics for temperature and future metrics. (#1689)
|
||||
|
||||
- Add `SMART_DEVICES_SEPARATOR` environment variable and allow drives with the same name to be added with different types (e.g. RAID controllers). (#1655)
|
||||
|
||||
- Add tooltips for navbar buttons. (#1636)
|
||||
|
||||
- Add icon button for mobile use. (#1687)
|
||||
|
||||
- Add tooltip to system name in systems table. (#1640)
|
||||
|
||||
- Improve CJK truncation in UI.
|
||||
|
||||
- Fix container uptime sorting edge case. (#1696)
|
||||
|
||||
- Remove stale systemd services from tracking after deletion. (#1594)
|
||||
|
||||
- Apply SELinux context after binary replacement. (#1678)
|
||||
|
||||
- Update honeypot field name and autofill ignores. (#1011)
|
||||
|
||||
- Write health_file to `/dev/shm` instead of `/tmp` if available. (#1455)
|
||||
|
||||
- Don't force lowercase text for active alerts. (#1682)
|
||||
|
||||
- Ensure battery current charge doesn't exceed full capacity. (#1668)
|
||||
|
||||
- Increase `smartctl --scan` timeout to 10 seconds. (#1465)
|
||||
|
||||
- Use name-only matching for unique S.M.A.R.T. devices. (#1655)
|
||||
|
||||
- Fix smartctlArgs call to use hasExistingData flag. (#1645)
|
||||
|
||||
- Ignore alt key combinations when navigating systems with arrow keys. (#1698)
|
||||
|
||||
- Update Go dependencies
|
||||
|
||||
## 0.18.2
|
||||
|
||||
- Add separate dynamically linked glibc build for Linux. (#1618)
|
||||
|
||||
- Fix GPU ID collision between Intel and NVIDIA collectors. (#1522)
|
||||
|
||||
- Only hide GPU engine graph if entire usage is 0%. (#1624)
|
||||
|
||||
- Add Jetson tegrastats regex support for pre-Jetpack 5 versions. (#1631)
|
||||
|
||||
- Improve Indonesian translations. (#1625)
|
||||
|
||||
## 0.18.1
|
||||
|
||||
- Fix bug in 0.18.0 where all containers were cleared from the "All Containers" page when any system returned no containers.
|
||||
|
||||
## 0.18.0
|
||||
|
||||
- Add experimental NVML GPU collector. (#1522, #1587)
|
||||
|
||||
- Add low battery alerts. (#1507)
|
||||
|
||||
- Add battery charge to systems table.
|
||||
|
||||
- Add option to make universal token permanent. (#1097, #1614)
|
||||
|
||||
- Add `--url` and `--token` command line arguments to the agent. (#1524)
|
||||
|
||||
- Collect S.M.A.R.T. data in the background every hour.
|
||||
|
||||
- Add `SMART_INTERVAL` environment variable to customize S.M.A.R.T. data collection interval.
|
||||
|
||||
- Collect system distribution and architecture.
|
||||
|
||||
- Add `system_details` collection to store infrequently updated system information.
|
||||
|
||||
- Improve S.M.A.R.T. device path lookup for NVMe devices. (#1504)
|
||||
|
||||
- Use origin country flags for Spanish, Portuguese, English languages. (#1571)
|
||||
|
||||
- Raise `smartctl` timeout to 15 seconds. (#1465)
|
||||
|
||||
- Skip known non-unique product UUID when generating fingerprints. (#1556)
|
||||
|
||||
- Fix container logs decoding for raw streams. (#1535)
|
||||
|
||||
- Fix capacity sorting in S.M.A.R.T. table. (#1551)
|
||||
|
||||
- Fix loader visibility when no systems are present. (#1511)
|
||||
|
||||
- Rename login honeypot field to prevent password manager autofill (#1011).
|
||||
|
||||
- Add Serbian and Bahasa Indonesia translations.
|
||||
|
||||
- Update Go dependencies.
|
||||
|
||||
## 0.17.0
|
||||
|
||||
- Add quiet hours to silence alerts during specific time periods. (#265)
|
||||
|
||||
- Add dedicated S.M.A.R.T. page.
|
||||
|
||||
- Add alerts for S.M.A.R.T. failures.
|
||||
|
||||
- Add `DISK_USAGE_CACHE` environment variable. (#1426)
|
||||
|
||||
- Add `SKIP_SYSTEMD` environment variable. (#1448)
|
||||
|
||||
- Add hub builds for Windows and FreeBSD.
|
||||
|
||||
- Change extra disk indicators in systems table to display usage range as dots. (#1409)
|
||||
|
||||
- Strip ANSI escape sequences from docker logs. (#1478)
|
||||
|
||||
- Fix issue where the Add System button is visible to read-only users. (#1442)
|
||||
|
||||
- Fix font ligatures creating unwanted artifacts in random ids. (#1434)
|
||||
|
||||
- Update Go dependencies.
|
||||
|
||||
## 0.16.1
|
||||
|
||||
- Add services column to All Systems table. (#1153)
|
||||
|
||||
- Add `SERVICE_PATTERNS` environment variable to filter systemd services. (#1153)
|
||||
|
||||
- Fix detection and handling of immutable filesystems like Fedora Silverblue. (#1405)
|
||||
|
||||
- Persist alert history page size preference. (#1404)
|
||||
|
||||
- Add setting for layout width.
|
||||
|
||||
- Update Go dependencies.
|
||||
|
||||
## 0.16.0
|
||||
|
||||
- Add basic systemd service monitoring. (#1153)
|
||||
|
||||
- Add GPU usage alerts.
|
||||
|
||||
- Show additional disk percentages in systems table. (#1365)
|
||||
|
||||
- Embed `smartctl` in the Windows binary (experimental). (#1362)
|
||||
|
||||
- Add `EXCLUDE_SMART` environment variable to exclude devices from S.M.A.R.T. monitoring. (#1392)
|
||||
|
||||
- Change alert links to use system ID instead of name.
|
||||
|
||||
- Update Go dependencies.
|
||||
|
||||
## 0.15.4
|
||||
|
||||
- Refactor containers table to fix clock issue causing no results. (#1337)
|
||||
|
||||
- Fix Windows extra disk detection. (#1361)
|
||||
|
||||
- Add total line to the tooltip of charts with multiple values. (#1280)
|
||||
|
||||
- Add fallback paths for `smartctl` lookup. (#1362, #1363)
|
||||
|
||||
- Fix `intel_gpu_top` parsing when engine instance id is in column. (#1230)
|
||||
|
||||
- Update `henrygd/beszel-agent-nvidia` Dockerfile to build latest smartmontools. (#1335)
|
||||
|
||||
## 0.15.3
|
||||
|
||||
- Add CPU state details and per-core usage. (#1356)
|
||||
|
||||
- Add `EXCLUDE_CONTAINERS` environment variable to exclude containers from being monitored. (#1352)
|
||||
|
||||
- Add `INTEL_GPU_DEVICE` environment variable to specify Intel GPU device. (#1285)
|
||||
|
||||
- Improve parsing of edge case S.M.A.R.T. power on times. (#1347)
|
||||
|
||||
- Fix empty disk I/O values for extra disks. (#1355)
|
||||
|
||||
- Fix battery nil pointer error. (#1353)
|
||||
|
||||
- Add Hebrew with translations by @gabay.
|
||||
|
||||
- Update `shoutrrr` and `gopsutil` dependencies.
|
||||
|
||||
## 0.15.2
|
||||
|
||||
- Improve S.M.A.R.T. device detection logic (fix regression in 0.15.1) (#1345)
|
||||
|
||||
## 0.15.1
|
||||
|
||||
- Add `SMART_DEVICES` environment variable to specify devices and types. (#373, #1335)
|
||||
|
||||
- Add support for `scsi`, `sntasmedia`, and `sntrealtek` S.M.A.R.T. types. (#373, #1335)
|
||||
|
||||
- Handle power-on time attributes that are formatted as strings (e.g., "0h+0m+0.000s").
|
||||
|
||||
- Skip virtual disks in S.M.A.R.T. monitoring. (#1332)
|
||||
|
||||
- Add sorting to the S.M.A.R.T. table. (#1333)
|
||||
|
||||
- Fix incorrect disk rendering in S.M.A.R.T. device details. (#1336)
|
||||
|
||||
- Fix `SHARE_ALL_SYSTEMS` setting not working for containers. (#1334)
|
||||
|
||||
- Fix text contrast issue when container details are disabled. (#1324)
|
||||
|
||||
## 0.15.0
|
||||
|
||||
- Add initial S.M.A.R.T. support for disk health monitoring. (#962)
|
||||
|
||||
- Add `henrygd/beszel-agent:alpine` Docker image and include `smartmontools` in all non-base agent images.
|
||||
|
||||
- Remove environment variables from container details (#1305)
|
||||
|
||||
- Add `CONTAINER_DETAILS` environment variable to control access to container logs and info APIs. (#1305)
|
||||
|
||||
- Improve temperature chart by allowing y-axis to start above 0 for better readability. (#1307)
|
||||
|
||||
- Improve battery detection logic. (#1287)
|
||||
|
||||
- Limit docker log size to prevent possible memory leak. (#1322)
|
||||
|
||||
- Update Go dependencies.
|
||||
|
||||
## 0.14.1
|
||||
|
||||
- Add `MFA_OTP` environment variable to enable email-based one-time password for users and/or superusers.
|
||||
|
||||
- Add image name to containers table. (#1302)
|
||||
|
||||
- Add spacing for long temperature chart tooltip. (#1299)
|
||||
|
||||
- Fix sorting by status in containers table. (#1294)
|
||||
|
||||
## 0.14.0
|
||||
|
||||
- Add `/containers` page for viewing current status of all running containers. (#928)
|
||||
|
||||
- Add ability to view container status, health, details, and basic logs. (#928)
|
||||
|
||||
- Probable fix for erroneous network stats when interface resets (#1267, #1246)
|
||||
|
||||
# 0.13.2
|
||||
|
||||
- Add ability to set custom name for extra filesystems. (#379)
|
||||
|
||||
- Improve WebSocket agent reconnection after network interruptions. (#1263)
|
||||
|
||||
- Allow more latency in one minute charts before visually disconnecting points. (#1247)
|
||||
|
||||
- Update favicon and add add down systems count in bubble.
|
||||
|
||||
## 0.13.1
|
||||
|
||||
- Fix one minute charts on systems without Docker. (#1237)
|
||||
|
||||
- Change system permalinks to use ID instead of name. (#1231)
|
||||
|
||||
## 0.13.0
|
||||
|
||||
- Add one minute chart with one second interval.
|
||||
|
||||
- Improve accuracy of disk I/O statistics.
|
||||
|
||||
- Add `SYSTEM_NAME` environment variable to override system name on universal token registration. (#1184)
|
||||
|
||||
- Add `noindex` HTML meta tag. (#1218)
|
||||
|
||||
- Update Go dependencies.
|
||||
|
||||
## 0.12.12
|
||||
|
||||
- Fix high CPU usage when `intel_gpu_top` returns an error. (#1203)
|
||||
|
||||
- Add `SKIP_GPU` environment variable to skip GPU data collection. (#1203)
|
||||
|
||||
- Add fallback cache/buff memory calculation when cache/buff isn't available ([#1198](https://github.com/henrygd/beszel/issues/1198))
|
||||
|
||||
- Fix automatic agent update / restart on OpenRC. (#1199)
|
||||
|
||||
## 0.12.11
|
||||
|
||||
- Adjust calculation of cached memory (fixes #1187, #1196)
|
||||
|
||||
- Add pattern matching and blacklist functionality to `NICS` env var. (#1190)
|
||||
|
||||
- Update Intel GPU collector to parse plain text (`-l`) instead of JSON output (#1150)
|
||||
|
||||
## 0.12.10
|
||||
|
||||
Note that the default memory calculation changed in this release, which may cause a difference in memory usage compared to previous versions.
|
||||
|
||||
- Add initial support for Intel GPUs (#1150, #755)
|
||||
|
||||
- Show connection type (WebSocket / SSH) in hub UI.
|
||||
|
||||
- Fix temperature unit and bytes / bits settings. (#1180)
|
||||
|
||||
- Add `henrygd/beszel-agent-intel` image for Intel GPUs (experimental).
|
||||
|
||||
- Update Go dependencies. Shoutrrr now supports notifications for Signal and WeChat Work (WeCom).
|
||||
|
||||
## 0.12.9
|
||||
|
||||
- Fix divide by zero error introduced in 0.12.8 :) (#1175)
|
||||
|
||||
## 0.12.8
|
||||
|
||||
- Add per-interface network traffic charts. (#926)
|
||||
|
||||
- Add cumulative network traffic charts. (#926)
|
||||
|
||||
- Add setting for time format (12h / 24h). (#424)
|
||||
|
||||
- Add experimental one-time password (OTP) support.
|
||||
|
||||
- Add `TRUSTED_AUTH_HEADER` environment variable for authentication forwarding. (#399)
|
||||
|
||||
- Add `AUTO_LOGIN` environment variable for automatic login. (#399)
|
||||
|
||||
- Add FreeBSD support for agent install script and update command.
|
||||
|
||||
- Fix status alerts not being resolved when system comes up. (#1052)
|
||||
|
||||
## 0.12.7
|
||||
|
||||
- Make LibreHardwareMonitor opt-in with `LHM=true` environment variable. (#1130)
|
||||
|
||||
- Fix bug where token was not refreshed when adding a new system. (#1141)
|
||||
|
||||
- Add `USER_EMAIL` and `USER_PASSWORD` environment variables to set the email and password of the initial user. (#1137)
|
||||
|
||||
- Display system counts (active, paused, down) in All Systems 'view' options. (#1078)
|
||||
|
||||
- Remember All Systems sort order during session.
|
||||
|
||||
## 0.12.6
|
||||
|
||||
- Add maximum 1 minute memory usage.
|
||||
|
||||
- Add status filters to All Systems table.
|
||||
|
||||
- Virtualize All Systems table to improve performance with hundreds of systems. (#1100)
|
||||
|
||||
- Fix Safari system link CSS bug.
|
||||
|
||||
- Use older cuda image for increased compatibility (#1103)
|
||||
|
||||
- Truncate long system names in All Systems table. (#1104)
|
||||
|
||||
- Fix update mirror and add `--china-mirrors` flag. (#1035)
|
||||
|
||||
## 0.12.5
|
||||
|
||||
- Downgrade `gopsutil` to `v4.25.6` to fix panic on FreeBSD (#1083)
|
||||
|
||||
- Exclude FreeBSD from battery charge monitoring to fix deadlock. (#1081)
|
||||
|
||||
- Minor hub UI improvements.
|
||||
|
||||
## 0.12.4
|
||||
|
||||
- Add battery charge monitoring.
|
||||
|
||||
- Add fallback mirror to the `update` commands. (#1035)
|
||||
|
||||
- Fix blank token field in insecure contexts.
|
||||
|
||||
- Allow opening internal router links in new tab.
|
||||
|
||||
- Add `/api/beszel/user-alerts` endpoint. Remove use of batch API for alerts in hub.
|
||||
|
||||
- Require auth for `/api/beszel/getkey` endpoint that returns the public key.
|
||||
|
||||
- Change `GET /api/beszel/send-test-notification` endpoint to `POST /api/beszel/test-notification`.
|
||||
|
||||
- Update Go and JS dependencies.
|
||||
|
||||
- New translations by @Radotornado, @AlexVanSteenhoven, @harupong, @dymek37, @NaNomicon, Tommaso Cavazza, Caio Garcia, and others.
|
||||
|
||||
## Older
|
||||
|
||||
Release notes are available at <https://github.com/henrygd/beszel/releases>
|
||||
@@ -0,0 +1,27 @@
|
||||
[Unit]
|
||||
Description=Beszel Agent Service
|
||||
Wants=network-online.target
|
||||
After=network-online.target
|
||||
|
||||
[Service]
|
||||
Environment="PORT=45876"
|
||||
# Port number can be overridden in beszel-agent.conf if needed
|
||||
EnvironmentFile=/etc/beszel-agent.conf
|
||||
ExecStart=/usr/bin/beszel-agent
|
||||
User=beszel
|
||||
Restart=on-failure
|
||||
StateDirectory=beszel-agent
|
||||
|
||||
# Security/sandboxing settings
|
||||
KeyringMode=private
|
||||
LockPersonality=yes
|
||||
ProtectClock=yes
|
||||
ProtectHome=read-only
|
||||
ProtectHostname=yes
|
||||
ProtectKernelLogs=yes
|
||||
ProtectSystem=strict
|
||||
RemoveIPC=yes
|
||||
RestrictSUIDSGID=true
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@@ -0,0 +1,8 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
. /usr/share/debconf/confmodule
|
||||
db_version 2.0
|
||||
|
||||
db_input high beszel-agent/key || true
|
||||
db_go
|
||||
@@ -0,0 +1,8 @@
|
||||
Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
||||
Upstream-Name: Beszel
|
||||
Upstream-Contact: henrygd <[email protected]>
|
||||
Source: https://beszel.dev/
|
||||
|
||||
Files: *
|
||||
Copyright: 2024 henrygd
|
||||
License: MIT
|
||||
@@ -0,0 +1,11 @@
|
||||
# No changelog in the repo at the moment. This would be good to fix
|
||||
beszel-agent: no-changelog
|
||||
# Current unable to fix these due to Goreleaser bug
|
||||
# https://github.com/goreleaser/goreleaser/issues/5487
|
||||
beszel-agent: no-debconf-config
|
||||
beszel-agent: postinst-uses-db-input
|
||||
# Needs to be fixed in Beszel build
|
||||
beszel-agent: hardening-no-pie
|
||||
beszel-agent: hardening-no-relro
|
||||
# Maybe one day
|
||||
beszel-agent: no-manual-page
|
||||
@@ -0,0 +1,50 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
[ "$1" = "configure" ] || exit 0
|
||||
|
||||
CONFIG_FILE=/etc/beszel-agent.conf
|
||||
SERVICE=beszel-agent
|
||||
SERVICE_USER=beszel
|
||||
|
||||
. /usr/share/debconf/confmodule
|
||||
|
||||
# Create group and user
|
||||
if ! getent group "$SERVICE_USER" >/dev/null; then
|
||||
echo "Creating $SERVICE_USER group"
|
||||
addgroup --quiet --system "$SERVICE_USER"
|
||||
fi
|
||||
|
||||
if ! getent passwd "$SERVICE_USER" >/dev/null; then
|
||||
echo "Creating $SERVICE_USER user"
|
||||
adduser --quiet --system "$SERVICE_USER" \
|
||||
--ingroup "$SERVICE_USER" \
|
||||
--no-create-home \
|
||||
--home /nonexistent \
|
||||
--gecos "System user for $SERVICE"
|
||||
fi
|
||||
|
||||
# Enable docker (only if docker group exists)
|
||||
if getent group docker >/dev/null 2>&1; then
|
||||
if ! getent group docker | grep -q "$SERVICE_USER"; then
|
||||
echo "Adding $SERVICE_USER to docker group"
|
||||
usermod -aG docker "$SERVICE_USER"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Create config file if it doesn't already exist
|
||||
if [ ! -f "$CONFIG_FILE" ]; then
|
||||
touch "$CONFIG_FILE"
|
||||
chmod 0600 "$CONFIG_FILE"
|
||||
chown "$SERVICE_USER":"$SERVICE_USER" "$CONFIG_FILE"
|
||||
fi;
|
||||
|
||||
# Only add key to config if it's not already present
|
||||
if ! grep -q "^KEY=" "$CONFIG_FILE"; then
|
||||
db_get beszel-agent/key
|
||||
echo "KEY=$RET" > "$CONFIG_FILE"
|
||||
fi;
|
||||
|
||||
deb-systemd-helper enable "$SERVICE".service
|
||||
systemctl daemon-reload
|
||||
deb-systemd-invoke start "$SERVICE".service || echo "could not start $SERVICE.service!"
|
||||
@@ -0,0 +1,8 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
if [ "$1" = "purge" ]; then
|
||||
. /usr/share/debconf/confmodule
|
||||
db_purge
|
||||
rm /etc/beszel-agent.conf
|
||||
fi
|
||||
@@ -0,0 +1,9 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
SERVICE=beszel-agent
|
||||
|
||||
deb-systemd-invoke stop "$SERVICE".service
|
||||
if [ "$1" = "remove" ]; then
|
||||
deb-systemd-helper purge "$SERVICE".service
|
||||
fi
|
||||
@@ -0,0 +1,5 @@
|
||||
Template: beszel-agent/key
|
||||
Type: string
|
||||
Description: SSH public key provided by beszel hub:
|
||||
If you leave this blank, you will need to configure it in
|
||||
/etc/beszel-agent.conf before starting Beszel.
|
||||
@@ -0,0 +1,18 @@
|
||||
services:
|
||||
beszel-agent:
|
||||
image: 'henrygd/beszel-agent' #Or henrygd/beszel-agent-nvidia
|
||||
container_name: 'beszel-agent'
|
||||
restart: unless-stopped
|
||||
network_mode: host
|
||||
# Only when using henrygd/beszel-agent-nvidia
|
||||
# runtime: nvidia
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||
# monitor other disks / partitions by mounting a folder in /extra-filesystems
|
||||
# - /mnt/disk/.beszel:/extra-filesystems/sda1:ro
|
||||
environment:
|
||||
PORT: 45876
|
||||
KEY: 'ssh-ed25519 YOUR_PUBLIC_KEY'
|
||||
# Only when using henrygd/beszel-agent-nvidia
|
||||
# NVIDIA_VISIBLE_DEVICES: all
|
||||
# NVIDIA_DRIVER_CAPABILITIES: compute,video,utility
|
||||
@@ -0,0 +1,9 @@
|
||||
services:
|
||||
beszel:
|
||||
image: 'henrygd/beszel'
|
||||
container_name: 'beszel'
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- '8090:8090'
|
||||
volumes:
|
||||
- ./beszel_data:/beszel_data
|
||||
@@ -0,0 +1,26 @@
|
||||
services:
|
||||
beszel:
|
||||
image: 'henrygd/beszel'
|
||||
container_name: 'beszel'
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- '8090:8090'
|
||||
volumes:
|
||||
- ./beszel_data:/beszel_data
|
||||
extra_hosts:
|
||||
- 'host.docker.internal:host-gateway'
|
||||
|
||||
beszel-agent:
|
||||
image: 'henrygd/beszel-agent' #Add -nvidia for nvidia gpus
|
||||
container_name: 'beszel-agent'
|
||||
restart: unless-stopped
|
||||
network_mode: host
|
||||
# runtime: nvidia # when using beszel-agent-nvidia
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||
environment:
|
||||
PORT: 45876
|
||||
KEY: '...'
|
||||
# FILESYSTEM: /dev/sda1 # set to the correct filesystem for disk I/O stats
|
||||
# NVIDIA_VISIBLE_DEVICES: all # when using beszel-agent-nvidia
|
||||
# NVIDIA_DRIVER_CAPABILITIES: utility # when using beszel-agent-nvidia
|
||||
@@ -0,0 +1,132 @@
|
||||
# Installing as a Linux systemd service
|
||||
|
||||
This is useful if you want to run the hub or agent in the background continuously, including after a reboot.
|
||||
|
||||
## Install script (recommended)
|
||||
|
||||
There are two scripts, one for the hub and one for the agent. You can run either one, or both.
|
||||
|
||||
The install script creates a dedicated user for the service (`beszel`), downloads the latest release, and installs the service.
|
||||
|
||||
If you need to edit the service -- for instance, to change an environment variable -- you can edit the file(s) in `/etc/systemd/system/`. Then reload the systemd daemon and restart the service.
|
||||
|
||||
> [!NOTE]
|
||||
> You need system administrator privileges to run the install script. If you encounter a problem, please [open an issue](https://github.com/henrygd/beszel/issues/new).
|
||||
|
||||
### Hub
|
||||
|
||||
Download the script:
|
||||
|
||||
```bash
|
||||
curl -sL https://raw.githubusercontent.com/henrygd/beszel/main/supplemental/scripts/install-hub.sh -o install-hub.sh && chmod +x install-hub.sh
|
||||
```
|
||||
|
||||
#### Install
|
||||
|
||||
You may specify a port number with the `-p` flag. The default port is `8090`.
|
||||
|
||||
```bash
|
||||
./install-hub.sh
|
||||
```
|
||||
|
||||
#### Uninstall
|
||||
|
||||
```bash
|
||||
./install-hub.sh -u
|
||||
```
|
||||
|
||||
#### Update
|
||||
|
||||
```bash
|
||||
sudo /opt/beszel/beszel update && sudo systemctl restart beszel-hub
|
||||
```
|
||||
|
||||
### Agent
|
||||
|
||||
Download the script:
|
||||
|
||||
```bash
|
||||
curl -sL https://raw.githubusercontent.com/henrygd/beszel/main/supplemental/scripts/install-agent.sh -o install-agent.sh && chmod +x install-agent.sh
|
||||
```
|
||||
|
||||
#### Install
|
||||
|
||||
You may optionally include the SSH key and port as arguments. Run `./install-agent.sh -h` for more info.
|
||||
|
||||
If specifying your key with `-k`, please make sure to enclose it in quotes.
|
||||
|
||||
```bash
|
||||
./install-agent.sh
|
||||
```
|
||||
|
||||
#### Uninstall
|
||||
|
||||
```bash
|
||||
./install-agent.sh -u
|
||||
```
|
||||
|
||||
#### Update
|
||||
|
||||
```bash
|
||||
sudo /opt/beszel-agent/beszel-agent update && sudo systemctl restart beszel-agent
|
||||
```
|
||||
|
||||
## Manual install
|
||||
|
||||
### Hub
|
||||
|
||||
1. Create the system service at `/etc/systemd/system/beszel.service`
|
||||
|
||||
```bash
|
||||
[Unit]
|
||||
Description=Beszel Hub Service
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
# update the values in the curly braces below (remove the braces)
|
||||
ExecStart={/path/to/working/directory}/beszel serve
|
||||
WorkingDirectory={/path/to/working/directory}
|
||||
User={YOUR_USERNAME}
|
||||
Restart=always
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
|
||||
2. Start and enable the service to let it run after system boot
|
||||
|
||||
```bash
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl enable beszel.service
|
||||
sudo systemctl start beszel.service
|
||||
```
|
||||
|
||||
### Agent
|
||||
|
||||
1. Create the system service at `/etc/systemd/system/beszel-agent.service`
|
||||
|
||||
```bash
|
||||
[Unit]
|
||||
Description=Beszel Agent Service
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
# update the values in curly braces below (remove the braces)
|
||||
Environment="PORT={PASTE_YOUR_PORT_HERE}"
|
||||
Environment="KEY={PASTE_YOUR_KEY_HERE}"
|
||||
# Environment="EXTRA_FILESYSTEMS={sdb}"
|
||||
ExecStart={/path/to/directory}/beszel-agent
|
||||
User={YOUR_USERNAME}
|
||||
Restart=always
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
|
||||
2. Start and enable the service to let it run after system boot
|
||||
|
||||
```bash
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl enable beszel-agent.service
|
||||
sudo systemctl start beszel-agent.service
|
||||
```
|
||||
@@ -0,0 +1,23 @@
|
||||
# Patterns to ignore when building packages.
|
||||
# This supports shell glob matching, relative path matching, and
|
||||
# negation (prefixed with !). Only one pattern per line.
|
||||
.DS_Store
|
||||
# Common VCS dirs
|
||||
.git/
|
||||
.gitignore
|
||||
.bzr/
|
||||
.bzrignore
|
||||
.hg/
|
||||
.hgignore
|
||||
.svn/
|
||||
# Common backup files
|
||||
*.swp
|
||||
*.bak
|
||||
*.tmp
|
||||
*.orig
|
||||
*~
|
||||
# Various IDEs
|
||||
.project
|
||||
.idea/
|
||||
*.tmproj
|
||||
.vscode/
|
||||
@@ -0,0 +1,15 @@
|
||||
apiVersion: v1
|
||||
description: Installs beszel-hub in kubernetes
|
||||
home: https://github.com/dnikoloski/beszel-kubernetes/tree/main/charts/beszel-hub
|
||||
name: beszel-hub
|
||||
appVersion: "0.9"
|
||||
# Do not touch will be updated during release
|
||||
version: 0.1.0
|
||||
sources:
|
||||
- https://github.com/dnikoloski/beszel-kubernetes/tree/main/charts/beszel-hub
|
||||
- https://www.beszel.dev/
|
||||
- https://github.com/henrygd/beszel
|
||||
icon: https://repository-images.githubusercontent.com/825470378/2710c6db-f934-4a8b-a2c4-7a0abbcd2ad6
|
||||
maintainers:
|
||||
- name: dnikoloski
|
||||
email: [email protected]
|
||||
@@ -0,0 +1,22 @@
|
||||
1. Get the application URL by running these commands:
|
||||
{{- if .Values.ingress.enabled }}
|
||||
{{- range $host := .Values.ingress.hosts }}
|
||||
{{- range .paths }}
|
||||
http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- else if contains "NodePort" .Values.service.type }}
|
||||
export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "beszel.fullname" . }}-web)
|
||||
export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
|
||||
echo http://$NODE_IP:$NODE_PORT
|
||||
{{- else if contains "LoadBalancer" .Values.service.type }}
|
||||
NOTE: It may take a few minutes for the LoadBalancer IP to be available.
|
||||
You can watch its status by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "beszel.fullname" . }}'
|
||||
export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "beszel.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}")
|
||||
echo http://$SERVICE_IP:{{ .Values.service.port }}
|
||||
{{- else if contains "ClusterIP" .Values.service.type }}
|
||||
export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "beszel.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
|
||||
export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
|
||||
echo "Visit http://127.0.0.1:8090 to use your application"
|
||||
kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8090:$CONTAINER_PORT
|
||||
{{- end }}
|
||||
@@ -0,0 +1,51 @@
|
||||
{{/*
|
||||
Expand the name of the chart.
|
||||
*/}}
|
||||
{{- define "beszel.name" -}}
|
||||
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Create a default fully qualified app name.
|
||||
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
|
||||
If release name contains chart name it will be used as a full name.
|
||||
*/}}
|
||||
{{- define "beszel.fullname" -}}
|
||||
{{- if .Values.fullnameOverride }}
|
||||
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
|
||||
{{- else }}
|
||||
{{- $name := default .Chart.Name .Values.nameOverride }}
|
||||
{{- if contains $name .Release.Name }}
|
||||
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
|
||||
{{- else }}
|
||||
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Create chart name and version as used by the chart label.
|
||||
*/}}
|
||||
{{- define "beszel.chart" -}}
|
||||
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Common labels
|
||||
*/}}
|
||||
{{- define "beszel.labels" -}}
|
||||
helm.sh/chart: {{ include "beszel.chart" . }}
|
||||
{{ include "beszel.selectorLabels" . }}
|
||||
{{- if .Chart.AppVersion }}
|
||||
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
|
||||
{{- end }}
|
||||
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Selector labels
|
||||
*/}}
|
||||
{{- define "beszel.selectorLabels" -}}
|
||||
app.kubernetes.io/name: {{ include "beszel.name" . }}
|
||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,99 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: {{ include "beszel.fullname" . }}
|
||||
labels:
|
||||
{{- include "beszel.labels" . | nindent 4 }}
|
||||
spec:
|
||||
replicas: {{ .Values.replicaCount }}
|
||||
strategy:
|
||||
type: {{ .Values.strategyType }}
|
||||
{{- if eq .Values.strategyType "RollingUpdate" }}
|
||||
rollingUpdate:
|
||||
maxSurge: {{ .Values.maxSurge }}
|
||||
maxUnavailable: {{ .Values.maxUnavailable }}
|
||||
{{- end }}
|
||||
selector:
|
||||
matchLabels:
|
||||
{{- include "beszel.selectorLabels" . | nindent 6 }}
|
||||
template:
|
||||
metadata:
|
||||
{{- with .Values.podAnnotations }}
|
||||
annotations:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
labels:
|
||||
{{- include "beszel.labels" . | nindent 8 }}
|
||||
{{- with .Values.podLabels }}
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
{{- with .Values.imagePullSecrets }}
|
||||
imagePullSecrets:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.podSecurityContext }}
|
||||
securityContext:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
hostname: {{ .Values.hostname }}
|
||||
hostNetwork: {{ .Values.hostNetwork }}
|
||||
containers:
|
||||
- name: {{ .Chart.Name }}
|
||||
{{- with .Values.securityContext }}
|
||||
securityContext:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
|
||||
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: {{ .Values.service.port }}
|
||||
protocol: TCP
|
||||
{{- with .Values.livenessProbe }}
|
||||
livenessProbe:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- with .Values.readinessProbe }}
|
||||
readinessProbe:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- with .Values.resources }}
|
||||
resources:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- if .Values.persistentVolumeClaim.enabled }}
|
||||
volumeMounts:
|
||||
- name: data
|
||||
mountPath: /beszel_data
|
||||
{{- with .Values.volumeMounts }}
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- else if .Values.volumeMounts }}
|
||||
volumeMounts:
|
||||
{{- toYaml .Values.volumeMounts | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- if .Values.persistentVolumeClaim.enabled }}
|
||||
volumes:
|
||||
- name: data
|
||||
persistentVolumeClaim:
|
||||
claimName: {{ .Values.persistentVolumeClaim.existingClaim | default (include "beszel.fullname" .) }}
|
||||
{{- with .Values.volumes }}
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- else if .Values.volumes }}
|
||||
volumes:
|
||||
{{- toYaml .Values.volumes | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.nodeSelector }}
|
||||
nodeSelector:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.affinity }}
|
||||
affinity:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.tolerations }}
|
||||
tolerations:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,43 @@
|
||||
{{- if .Values.ingress.enabled -}}
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: {{ include "beszel.fullname" . }}
|
||||
labels:
|
||||
{{- include "beszel.labels" . | nindent 4 }}
|
||||
{{- with .Values.ingress.annotations }}
|
||||
annotations:
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
{{- with .Values.ingress.className }}
|
||||
ingressClassName: {{ . }}
|
||||
{{- end }}
|
||||
{{- if .Values.ingress.tls }}
|
||||
tls:
|
||||
{{- range .Values.ingress.tls }}
|
||||
- hosts:
|
||||
{{- range .hosts }}
|
||||
- {{ . | quote }}
|
||||
{{- end }}
|
||||
secretName: {{ .secretName }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
rules:
|
||||
{{- range .Values.ingress.hosts }}
|
||||
- host: {{ .host | quote }}
|
||||
http:
|
||||
paths:
|
||||
{{- range .paths }}
|
||||
- path: {{ .path }}
|
||||
{{- with .pathType }}
|
||||
pathType: {{ . }}
|
||||
{{- end }}
|
||||
backend:
|
||||
service:
|
||||
name: {{ include "beszel.fullname" $ }}
|
||||
port:
|
||||
number: {{ $.Values.service.port }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,22 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: {{ include "beszel.fullname" . }}
|
||||
labels:
|
||||
{{- include "beszel.labels" . | nindent 4 }}
|
||||
{{- if .Values.service.annotations }}
|
||||
annotations:
|
||||
{{ toYaml .Values.service.annotations | indent 4 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
type: {{ .Values.service.type }}
|
||||
ports:
|
||||
- port: {{ .Values.service.port }}
|
||||
targetPort: http
|
||||
protocol: TCP
|
||||
name: http
|
||||
{{- if .Values.service.loadBalancerIP }}
|
||||
loadBalancerIP: {{ .Values.service.loadBalancerIP }}
|
||||
{{- end }}
|
||||
selector:
|
||||
{{- include "beszel.selectorLabels" . | nindent 4 }}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: "{{ .Release.Name }}-smoke-test"
|
||||
annotations:
|
||||
"helm.sh/hook": test
|
||||
spec:
|
||||
containers:
|
||||
- name: hook1-container
|
||||
image: curlimages/curl
|
||||
imagePullPolicy: IfNotPresent
|
||||
command: ['sh', '-c', 'curl http://{{ template "beszel.fullname" . }}-web:8090/']
|
||||
restartPolicy: Never
|
||||
terminationGracePeriodSeconds: 0
|
||||
@@ -0,0 +1,27 @@
|
||||
{{- if .Values.persistentVolumeClaim.enabled -}}
|
||||
{{- if not .Values.persistentVolumeClaim.existingClaim -}}
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
{{- if .Values.persistentVolumeClaim.annotations }}
|
||||
annotations:
|
||||
{{ toYaml .Values.persistentVolumeClaim.annotations | indent 4 }}
|
||||
{{- end }}
|
||||
labels:
|
||||
{{- include "beszel.labels" . | nindent 4 }}
|
||||
name: {{ template "beszel.fullname" . }}
|
||||
spec:
|
||||
accessModes:
|
||||
{{ toYaml .Values.persistentVolumeClaim.accessModes | indent 4 }}
|
||||
{{- if .Values.persistentVolumeClaim.storageClass }}
|
||||
{{- if (eq "-" .Values.persistentVolumeClaim.storageClass) }}
|
||||
storageClassName: ""
|
||||
{{- else }}
|
||||
storageClassName: {{ .Values.persistentVolumeClaim.storageClass | quote }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
resources:
|
||||
requests:
|
||||
storage: {{ .Values.persistentVolumeClaim.size | quote }}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
@@ -0,0 +1,110 @@
|
||||
# Default values for beszel-hub.
|
||||
# This is a YAML-formatted file.
|
||||
# Declare variables to be passed into your templates.
|
||||
|
||||
# -- The number of replicas
|
||||
replicaCount: 1
|
||||
|
||||
image:
|
||||
repository: henrygd/beszel
|
||||
pullPolicy: IfNotPresent
|
||||
tag: ""
|
||||
|
||||
imagePullSecrets: []
|
||||
nameOverride: ""
|
||||
fullnameOverride: ""
|
||||
|
||||
|
||||
podAnnotations: {}
|
||||
podLabels: {}
|
||||
|
||||
podSecurityContext: {}
|
||||
|
||||
securityContext: {}
|
||||
# capabilities:
|
||||
# drop:
|
||||
# - ALL
|
||||
# readOnlyRootFilesystem: true
|
||||
# runAsNonRoot: true
|
||||
# runAsUser: 1000
|
||||
|
||||
service:
|
||||
enabled: true
|
||||
annotations: {}
|
||||
type: ClusterIP
|
||||
loadBalancerIP: ""
|
||||
port: 8090
|
||||
|
||||
ingress:
|
||||
enabled: false
|
||||
className: ""
|
||||
annotations: {}
|
||||
# kubernetes.io/ingress.class: nginx
|
||||
# kubernetes.io/tls-acme: "true"
|
||||
hosts:
|
||||
- host: chart-example.local
|
||||
paths:
|
||||
- path: /
|
||||
pathType: ImplementationSpecific
|
||||
tls: []
|
||||
# - secretName: chart-example-tls
|
||||
# hosts:
|
||||
# - chart-example.local
|
||||
|
||||
resources: {}
|
||||
# limits:
|
||||
# cpu: 100m
|
||||
# memory: 128Mi
|
||||
# requests:
|
||||
# cpu: 100m
|
||||
# memory: 128Mi
|
||||
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
port: http
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
port: http
|
||||
|
||||
autoscaling:
|
||||
enabled: false
|
||||
minReplicas: 1
|
||||
maxReplicas: 100
|
||||
targetCPUUtilizationPercentage: 80
|
||||
|
||||
# volumes: {}
|
||||
|
||||
# volumeMounts: {}
|
||||
|
||||
# -- `spec.PersitentVolumeClaim` configuration
|
||||
persistentVolumeClaim:
|
||||
# -- set to true to use pvc
|
||||
enabled: true
|
||||
|
||||
# -- specify an existing `PersistentVolumeClaim` to use
|
||||
# existingClaim: ""
|
||||
|
||||
# -- Annotations for the `PersitentVolumeClaim`
|
||||
annotations: {}
|
||||
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
|
||||
storageClass: ""
|
||||
|
||||
# -- volume claim size
|
||||
size: "500Mi"
|
||||
|
||||
# -- hostname of pod
|
||||
hostname: ""
|
||||
|
||||
# -- should the container use host network
|
||||
hostNetwork: "false"
|
||||
|
||||
nodeSelector: {}
|
||||
|
||||
tolerations: []
|
||||
|
||||
affinity: {}
|
||||
@@ -0,0 +1,373 @@
|
||||
Mozilla Public License Version 2.0
|
||||
==================================
|
||||
|
||||
1. Definitions
|
||||
--------------
|
||||
|
||||
1.1. "Contributor"
|
||||
means each individual or legal entity that creates, contributes to
|
||||
the creation of, or owns Covered Software.
|
||||
|
||||
1.2. "Contributor Version"
|
||||
means the combination of the Contributions of others (if any) used
|
||||
by a Contributor and that particular Contributor's Contribution.
|
||||
|
||||
1.3. "Contribution"
|
||||
means Covered Software of a particular Contributor.
|
||||
|
||||
1.4. "Covered Software"
|
||||
means Source Code Form to which the initial Contributor has attached
|
||||
the notice in Exhibit A, the Executable Form of such Source Code
|
||||
Form, and Modifications of such Source Code Form, in each case
|
||||
including portions thereof.
|
||||
|
||||
1.5. "Incompatible With Secondary Licenses"
|
||||
means
|
||||
|
||||
(a) that the initial Contributor has attached the notice described
|
||||
in Exhibit B to the Covered Software; or
|
||||
|
||||
(b) that the Covered Software was made available under the terms of
|
||||
version 1.1 or earlier of the License, but not also under the
|
||||
terms of a Secondary License.
|
||||
|
||||
1.6. "Executable Form"
|
||||
means any form of the work other than Source Code Form.
|
||||
|
||||
1.7. "Larger Work"
|
||||
means a work that combines Covered Software with other material, in
|
||||
a separate file or files, that is not Covered Software.
|
||||
|
||||
1.8. "License"
|
||||
means this document.
|
||||
|
||||
1.9. "Licensable"
|
||||
means having the right to grant, to the maximum extent possible,
|
||||
whether at the time of the initial grant or subsequently, any and
|
||||
all of the rights conveyed by this License.
|
||||
|
||||
1.10. "Modifications"
|
||||
means any of the following:
|
||||
|
||||
(a) any file in Source Code Form that results from an addition to,
|
||||
deletion from, or modification of the contents of Covered
|
||||
Software; or
|
||||
|
||||
(b) any new file in Source Code Form that contains any Covered
|
||||
Software.
|
||||
|
||||
1.11. "Patent Claims" of a Contributor
|
||||
means any patent claim(s), including without limitation, method,
|
||||
process, and apparatus claims, in any patent Licensable by such
|
||||
Contributor that would be infringed, but for the grant of the
|
||||
License, by the making, using, selling, offering for sale, having
|
||||
made, import, or transfer of either its Contributions or its
|
||||
Contributor Version.
|
||||
|
||||
1.12. "Secondary License"
|
||||
means either the GNU General Public License, Version 2.0, the GNU
|
||||
Lesser General Public License, Version 2.1, the GNU Affero General
|
||||
Public License, Version 3.0, or any later versions of those
|
||||
licenses.
|
||||
|
||||
1.13. "Source Code Form"
|
||||
means the form of the work preferred for making modifications.
|
||||
|
||||
1.14. "You" (or "Your")
|
||||
means an individual or a legal entity exercising rights under this
|
||||
License. For legal entities, "You" includes any entity that
|
||||
controls, is controlled by, or is under common control with You. For
|
||||
purposes of this definition, "control" means (a) the power, direct
|
||||
or indirect, to cause the direction or management of such entity,
|
||||
whether by contract or otherwise, or (b) ownership of more than
|
||||
fifty percent (50%) of the outstanding shares or beneficial
|
||||
ownership of such entity.
|
||||
|
||||
2. License Grants and Conditions
|
||||
--------------------------------
|
||||
|
||||
2.1. Grants
|
||||
|
||||
Each Contributor hereby grants You a world-wide, royalty-free,
|
||||
non-exclusive license:
|
||||
|
||||
(a) under intellectual property rights (other than patent or trademark)
|
||||
Licensable by such Contributor to use, reproduce, make available,
|
||||
modify, display, perform, distribute, and otherwise exploit its
|
||||
Contributions, either on an unmodified basis, with Modifications, or
|
||||
as part of a Larger Work; and
|
||||
|
||||
(b) under Patent Claims of such Contributor to make, use, sell, offer
|
||||
for sale, have made, import, and otherwise transfer either its
|
||||
Contributions or its Contributor Version.
|
||||
|
||||
2.2. Effective Date
|
||||
|
||||
The licenses granted in Section 2.1 with respect to any Contribution
|
||||
become effective for each Contribution on the date the Contributor first
|
||||
distributes such Contribution.
|
||||
|
||||
2.3. Limitations on Grant Scope
|
||||
|
||||
The licenses granted in this Section 2 are the only rights granted under
|
||||
this License. No additional rights or licenses will be implied from the
|
||||
distribution or licensing of Covered Software under this License.
|
||||
Notwithstanding Section 2.1(b) above, no patent license is granted by a
|
||||
Contributor:
|
||||
|
||||
(a) for any code that a Contributor has removed from Covered Software;
|
||||
or
|
||||
|
||||
(b) for infringements caused by: (i) Your and any other third party's
|
||||
modifications of Covered Software, or (ii) the combination of its
|
||||
Contributions with other software (except as part of its Contributor
|
||||
Version); or
|
||||
|
||||
(c) under Patent Claims infringed by Covered Software in the absence of
|
||||
its Contributions.
|
||||
|
||||
This License does not grant any rights in the trademarks, service marks,
|
||||
or logos of any Contributor (except as may be necessary to comply with
|
||||
the notice requirements in Section 3.4).
|
||||
|
||||
2.4. Subsequent Licenses
|
||||
|
||||
No Contributor makes additional grants as a result of Your choice to
|
||||
distribute the Covered Software under a subsequent version of this
|
||||
License (see Section 10.2) or under the terms of a Secondary License (if
|
||||
permitted under the terms of Section 3.3).
|
||||
|
||||
2.5. Representation
|
||||
|
||||
Each Contributor represents that the Contributor believes its
|
||||
Contributions are its original creation(s) or it has sufficient rights
|
||||
to grant the rights to its Contributions conveyed by this License.
|
||||
|
||||
2.6. Fair Use
|
||||
|
||||
This License is not intended to limit any rights You have under
|
||||
applicable copyright doctrines of fair use, fair dealing, or other
|
||||
equivalents.
|
||||
|
||||
2.7. Conditions
|
||||
|
||||
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
|
||||
in Section 2.1.
|
||||
|
||||
3. Responsibilities
|
||||
-------------------
|
||||
|
||||
3.1. Distribution of Source Form
|
||||
|
||||
All distribution of Covered Software in Source Code Form, including any
|
||||
Modifications that You create or to which You contribute, must be under
|
||||
the terms of this License. You must inform recipients that the Source
|
||||
Code Form of the Covered Software is governed by the terms of this
|
||||
License, and how they can obtain a copy of this License. You may not
|
||||
attempt to alter or restrict the recipients' rights in the Source Code
|
||||
Form.
|
||||
|
||||
3.2. Distribution of Executable Form
|
||||
|
||||
If You distribute Covered Software in Executable Form then:
|
||||
|
||||
(a) such Covered Software must also be made available in Source Code
|
||||
Form, as described in Section 3.1, and You must inform recipients of
|
||||
the Executable Form how they can obtain a copy of such Source Code
|
||||
Form by reasonable means in a timely manner, at a charge no more
|
||||
than the cost of distribution to the recipient; and
|
||||
|
||||
(b) You may distribute such Executable Form under the terms of this
|
||||
License, or sublicense it under different terms, provided that the
|
||||
license for the Executable Form does not attempt to limit or alter
|
||||
the recipients' rights in the Source Code Form under this License.
|
||||
|
||||
3.3. Distribution of a Larger Work
|
||||
|
||||
You may create and distribute a Larger Work under terms of Your choice,
|
||||
provided that You also comply with the requirements of this License for
|
||||
the Covered Software. If the Larger Work is a combination of Covered
|
||||
Software with a work governed by one or more Secondary Licenses, and the
|
||||
Covered Software is not Incompatible With Secondary Licenses, this
|
||||
License permits You to additionally distribute such Covered Software
|
||||
under the terms of such Secondary License(s), so that the recipient of
|
||||
the Larger Work may, at their option, further distribute the Covered
|
||||
Software under the terms of either this License or such Secondary
|
||||
License(s).
|
||||
|
||||
3.4. Notices
|
||||
|
||||
You may not remove or alter the substance of any license notices
|
||||
(including copyright notices, patent notices, disclaimers of warranty,
|
||||
or limitations of liability) contained within the Source Code Form of
|
||||
the Covered Software, except that You may alter any license notices to
|
||||
the extent required to remedy known factual inaccuracies.
|
||||
|
||||
3.5. Application of Additional Terms
|
||||
|
||||
You may choose to offer, and to charge a fee for, warranty, support,
|
||||
indemnity or liability obligations to one or more recipients of Covered
|
||||
Software. However, You may do so only on Your own behalf, and not on
|
||||
behalf of any Contributor. You must make it absolutely clear that any
|
||||
such warranty, support, indemnity, or liability obligation is offered by
|
||||
You alone, and You hereby agree to indemnify every Contributor for any
|
||||
liability incurred by such Contributor as a result of warranty, support,
|
||||
indemnity or liability terms You offer. You may include additional
|
||||
disclaimers of warranty and limitations of liability specific to any
|
||||
jurisdiction.
|
||||
|
||||
4. Inability to Comply Due to Statute or Regulation
|
||||
---------------------------------------------------
|
||||
|
||||
If it is impossible for You to comply with any of the terms of this
|
||||
License with respect to some or all of the Covered Software due to
|
||||
statute, judicial order, or regulation then You must: (a) comply with
|
||||
the terms of this License to the maximum extent possible; and (b)
|
||||
describe the limitations and the code they affect. Such description must
|
||||
be placed in a text file included with all distributions of the Covered
|
||||
Software under this License. Except to the extent prohibited by statute
|
||||
or regulation, such description must be sufficiently detailed for a
|
||||
recipient of ordinary skill to be able to understand it.
|
||||
|
||||
5. Termination
|
||||
--------------
|
||||
|
||||
5.1. The rights granted under this License will terminate automatically
|
||||
if You fail to comply with any of its terms. However, if You become
|
||||
compliant, then the rights granted under this License from a particular
|
||||
Contributor are reinstated (a) provisionally, unless and until such
|
||||
Contributor explicitly and finally terminates Your grants, and (b) on an
|
||||
ongoing basis, if such Contributor fails to notify You of the
|
||||
non-compliance by some reasonable means prior to 60 days after You have
|
||||
come back into compliance. Moreover, Your grants from a particular
|
||||
Contributor are reinstated on an ongoing basis if such Contributor
|
||||
notifies You of the non-compliance by some reasonable means, this is the
|
||||
first time You have received notice of non-compliance with this License
|
||||
from such Contributor, and You become compliant prior to 30 days after
|
||||
Your receipt of the notice.
|
||||
|
||||
5.2. If You initiate litigation against any entity by asserting a patent
|
||||
infringement claim (excluding declaratory judgment actions,
|
||||
counter-claims, and cross-claims) alleging that a Contributor Version
|
||||
directly or indirectly infringes any patent, then the rights granted to
|
||||
You by any and all Contributors for the Covered Software under Section
|
||||
2.1 of this License shall terminate.
|
||||
|
||||
5.3. In the event of termination under Sections 5.1 or 5.2 above, all
|
||||
end user license agreements (excluding distributors and resellers) which
|
||||
have been validly granted by You or Your distributors under this License
|
||||
prior to termination shall survive termination.
|
||||
|
||||
************************************************************************
|
||||
* *
|
||||
* 6. Disclaimer of Warranty *
|
||||
* ------------------------- *
|
||||
* *
|
||||
* Covered Software is provided under this License on an "as is" *
|
||||
* basis, without warranty of any kind, either expressed, implied, or *
|
||||
* statutory, including, without limitation, warranties that the *
|
||||
* Covered Software is free of defects, merchantable, fit for a *
|
||||
* particular purpose or non-infringing. The entire risk as to the *
|
||||
* quality and performance of the Covered Software is with You. *
|
||||
* Should any Covered Software prove defective in any respect, You *
|
||||
* (not any Contributor) assume the cost of any necessary servicing, *
|
||||
* repair, or correction. This disclaimer of warranty constitutes an *
|
||||
* essential part of this License. No use of any Covered Software is *
|
||||
* authorized under this License except under this disclaimer. *
|
||||
* *
|
||||
************************************************************************
|
||||
|
||||
************************************************************************
|
||||
* *
|
||||
* 7. Limitation of Liability *
|
||||
* -------------------------- *
|
||||
* *
|
||||
* Under no circumstances and under no legal theory, whether tort *
|
||||
* (including negligence), contract, or otherwise, shall any *
|
||||
* Contributor, or anyone who distributes Covered Software as *
|
||||
* permitted above, be liable to You for any direct, indirect, *
|
||||
* special, incidental, or consequential damages of any character *
|
||||
* including, without limitation, damages for lost profits, loss of *
|
||||
* goodwill, work stoppage, computer failure or malfunction, or any *
|
||||
* and all other commercial damages or losses, even if such party *
|
||||
* shall have been informed of the possibility of such damages. This *
|
||||
* limitation of liability shall not apply to liability for death or *
|
||||
* personal injury resulting from such party's negligence to the *
|
||||
* extent applicable law prohibits such limitation. Some *
|
||||
* jurisdictions do not allow the exclusion or limitation of *
|
||||
* incidental or consequential damages, so this exclusion and *
|
||||
* limitation may not apply to You. *
|
||||
* *
|
||||
************************************************************************
|
||||
|
||||
8. Litigation
|
||||
-------------
|
||||
|
||||
Any litigation relating to this License may be brought only in the
|
||||
courts of a jurisdiction where the defendant maintains its principal
|
||||
place of business and such litigation shall be governed by laws of that
|
||||
jurisdiction, without reference to its conflict-of-law provisions.
|
||||
Nothing in this Section shall prevent a party's ability to bring
|
||||
cross-claims or counter-claims.
|
||||
|
||||
9. Miscellaneous
|
||||
----------------
|
||||
|
||||
This License represents the complete agreement concerning the subject
|
||||
matter hereof. If any provision of this License is held to be
|
||||
unenforceable, such provision shall be reformed only to the extent
|
||||
necessary to make it enforceable. Any law or regulation which provides
|
||||
that the language of a contract shall be construed against the drafter
|
||||
shall not be used to construe this License against a Contributor.
|
||||
|
||||
10. Versions of the License
|
||||
---------------------------
|
||||
|
||||
10.1. New Versions
|
||||
|
||||
Mozilla Foundation is the license steward. Except as provided in Section
|
||||
10.3, no one other than the license steward has the right to modify or
|
||||
publish new versions of this License. Each version will be given a
|
||||
distinguishing version number.
|
||||
|
||||
10.2. Effect of New Versions
|
||||
|
||||
You may distribute the Covered Software under the terms of the version
|
||||
of the License under which You originally received the Covered Software,
|
||||
or under the terms of any subsequent version published by the license
|
||||
steward.
|
||||
|
||||
10.3. Modified Versions
|
||||
|
||||
If you create software not governed by this License, and you want to
|
||||
create a new license for such software, you may create and use a
|
||||
modified version of this License if you rename the license and remove
|
||||
any references to the name of the license steward (except to note that
|
||||
such modified license differs from this License).
|
||||
|
||||
10.4. Distributing Source Code Form that is Incompatible With Secondary
|
||||
Licenses
|
||||
|
||||
If You choose to distribute Source Code Form that is Incompatible With
|
||||
Secondary Licenses under the terms of this version of the License, the
|
||||
notice described in Exhibit B of this License must be attached.
|
||||
|
||||
Exhibit A - Source Code Form License Notice
|
||||
-------------------------------------------
|
||||
|
||||
This Source Code Form is subject to the terms of the Mozilla Public
|
||||
License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
If it is not possible or desirable to put the notice in a particular
|
||||
file, then You may include the notice in a location (such as a LICENSE
|
||||
file in a relevant directory) where a recipient would be likely to look
|
||||
for such a notice.
|
||||
|
||||
You may add additional accurate notices of copyright ownership.
|
||||
|
||||
Exhibit B - "Incompatible With Secondary Licenses" Notice
|
||||
---------------------------------------------------------
|
||||
|
||||
This Source Code Form is "Incompatible With Secondary Licenses", as
|
||||
defined by the Mozilla Public License, v. 2.0.
|
||||
@@ -0,0 +1,339 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License.
|
||||
Executable
+98
@@ -0,0 +1,98 @@
|
||||
#!/bin/bash
|
||||
|
||||
PORT=45876
|
||||
KEY=""
|
||||
TOKEN=""
|
||||
HUB_URL=""
|
||||
|
||||
usage() {
|
||||
printf "Beszel Agent homebrew installation script\n\n"
|
||||
printf "Usage: ./install-agent-brew.sh [options]\n\n"
|
||||
printf "Options: \n"
|
||||
printf " -k SSH key (required, or interactive if not provided)\n"
|
||||
printf " -p Port (default: $PORT)\n"
|
||||
printf " -t Token (optional for backwards compatibility)\n"
|
||||
printf " -url Hub URL (optional for backwards compatibility)\n"
|
||||
printf " -h, --help Display this help message\n"
|
||||
exit 0
|
||||
}
|
||||
|
||||
# Parse arguments
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
-k)
|
||||
shift
|
||||
KEY="$1"
|
||||
;;
|
||||
-p)
|
||||
shift
|
||||
PORT="$1"
|
||||
;;
|
||||
-t)
|
||||
shift
|
||||
TOKEN="$1"
|
||||
;;
|
||||
-url)
|
||||
shift
|
||||
HUB_URL="$1"
|
||||
;;
|
||||
-h | --help)
|
||||
usage
|
||||
;;
|
||||
*)
|
||||
echo "Invalid option: $1" >&2
|
||||
usage
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
# Check if brew is installed, prompt to install if not
|
||||
if ! command -v brew &>/dev/null; then
|
||||
read -p "Homebrew is not installed. Would you like to install it now? (y/n): " install_brew
|
||||
if [[ $install_brew =~ ^[Yy]$ ]]; then
|
||||
echo "Installing Homebrew..."
|
||||
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
|
||||
|
||||
# Verify installation was successful
|
||||
if ! command -v brew &>/dev/null; then
|
||||
echo "Homebrew installation failed. Please install manually and try again."
|
||||
exit 1
|
||||
fi
|
||||
echo "Homebrew installed successfully."
|
||||
else
|
||||
echo "Homebrew is required. Please install Homebrew and try again."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -z "$KEY" ]; then
|
||||
read -p "Enter SSH key: " KEY
|
||||
fi
|
||||
|
||||
# TOKEN and HUB_URL are optional for backwards compatibility - no interactive prompts
|
||||
|
||||
mkdir -p ~/.config/beszel ~/.cache/beszel
|
||||
|
||||
echo "KEY=\"$KEY\"" >~/.config/beszel/beszel-agent.env
|
||||
echo "LISTEN=$PORT" >>~/.config/beszel/beszel-agent.env
|
||||
|
||||
if [ -n "$TOKEN" ]; then
|
||||
echo "TOKEN=\"$TOKEN\"" >>~/.config/beszel/beszel-agent.env
|
||||
fi
|
||||
if [ -n "$HUB_URL" ]; then
|
||||
echo "HUB_URL=\"$HUB_URL\"" >>~/.config/beszel/beszel-agent.env
|
||||
fi
|
||||
|
||||
brew tap henrygd/beszel
|
||||
brew install beszel-agent
|
||||
brew services start beszel-agent
|
||||
|
||||
printf "\nCheck status: brew services info beszel-agent\n"
|
||||
echo "Stop: brew services stop beszel-agent"
|
||||
echo "Start: brew services start beszel-agent"
|
||||
echo "Restart: brew services restart beszel-agent"
|
||||
echo "Upgrade: brew upgrade beszel-agent"
|
||||
echo "Uninstall: brew uninstall beszel-agent"
|
||||
echo "View logs in ~/.cache/beszel/beszel-agent.log"
|
||||
printf "Change environment variables in ~/.config/beszel/beszel-agent.env\n"
|
||||
@@ -0,0 +1,634 @@
|
||||
param (
|
||||
[switch]$Elevated,
|
||||
[Parameter(Mandatory=$true)]
|
||||
[string]$Key,
|
||||
[string]$Token = "",
|
||||
[string]$Url = "",
|
||||
[int]$Port = 45876,
|
||||
[string]$AgentPath = "",
|
||||
[string]$NSSMPath = "",
|
||||
[switch]$ConfigureFirewall,
|
||||
[ValidateSet("Auto", "Scoop", "WinGet")]
|
||||
[string]$InstallMethod = "Auto"
|
||||
)
|
||||
|
||||
# Check if required parameters are provided
|
||||
if ([string]::IsNullOrWhiteSpace($Key)) {
|
||||
Write-Host "ERROR: SSH Key is required." -ForegroundColor Red
|
||||
Write-Host "Usage: .\install-agent.ps1 -Key 'your-ssh-key-here' [-Token 'your-token-here'] [-Url 'your-hub-url-here'] [-Port port-number] [-InstallMethod Auto|Scoop|WinGet] [-ConfigureFirewall]" -ForegroundColor Yellow
|
||||
Write-Host "Note: Token and Url are optional for backwards compatibility with older hub versions." -ForegroundColor Yellow
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Stop on first error
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
#region Utility Functions
|
||||
|
||||
# Function to check if running as admin
|
||||
function Test-Admin {
|
||||
return ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
|
||||
}
|
||||
|
||||
# Function to check if a command exists
|
||||
function Test-CommandExists {
|
||||
param (
|
||||
[Parameter(Mandatory=$true)]
|
||||
[string]$Command
|
||||
)
|
||||
return (Get-Command $Command -ErrorAction SilentlyContinue)
|
||||
}
|
||||
|
||||
# Function to find beszel-agent in common installation locations
|
||||
function Find-BeszelAgent {
|
||||
# First check if it's in PATH
|
||||
$agentCmd = Get-Command "beszel-agent" -ErrorAction SilentlyContinue
|
||||
if ($agentCmd) {
|
||||
return $agentCmd.Source
|
||||
}
|
||||
|
||||
# Common installation paths to check
|
||||
$commonPaths = @(
|
||||
"$env:USERPROFILE\scoop\apps\beszel-agent\current\beszel-agent.exe",
|
||||
"$env:ProgramData\scoop\apps\beszel-agent\current\beszel-agent.exe",
|
||||
"$env:LOCALAPPDATA\Microsoft\WinGet\Packages\henrygd.beszel-agent*\beszel-agent.exe",
|
||||
"$env:ProgramFiles\WinGet\Packages\henrygd.beszel-agent*\beszel-agent.exe",
|
||||
"${env:ProgramFiles(x86)}\WinGet\Packages\henrygd.beszel-agent*\beszel-agent.exe",
|
||||
"$env:ProgramFiles\beszel-agent\beszel-agent.exe",
|
||||
"$env:ProgramFiles(x86)\beszel-agent\beszel-agent.exe",
|
||||
"$env:SystemDrive\Users\*\scoop\apps\beszel-agent\current\beszel-agent.exe"
|
||||
)
|
||||
|
||||
foreach ($path in $commonPaths) {
|
||||
# Handle wildcard paths
|
||||
if ($path.Contains("*")) {
|
||||
$foundPaths = Get-ChildItem -Path $path -ErrorAction SilentlyContinue
|
||||
if ($foundPaths) {
|
||||
return $foundPaths[0].FullName
|
||||
}
|
||||
} else {
|
||||
if (Test-Path $path) {
|
||||
return $path
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $null
|
||||
}
|
||||
|
||||
# Function to find NSSM in common installation locations
|
||||
function Find-NSSM {
|
||||
# First check if it's in PATH
|
||||
$nssmCmd = Get-Command "nssm" -ErrorAction SilentlyContinue
|
||||
if ($nssmCmd) {
|
||||
return $nssmCmd.Source
|
||||
}
|
||||
|
||||
# Common installation paths to check
|
||||
$commonPaths = @(
|
||||
"$env:USERPROFILE\scoop\apps\nssm\current\nssm.exe",
|
||||
"$env:ProgramData\scoop\apps\nssm\current\nssm.exe",
|
||||
"$env:LOCALAPPDATA\Microsoft\WinGet\Packages\NSSM.NSSM*\nssm.exe",
|
||||
"$env:ProgramFiles\WinGet\Packages\NSSM.NSSM*\nssm.exe",
|
||||
"${env:ProgramFiles(x86)}\WinGet\Packages\NSSM.NSSM*\nssm.exe",
|
||||
"$env:SystemDrive\Users\*\scoop\apps\nssm\current\nssm.exe"
|
||||
)
|
||||
|
||||
foreach ($path in $commonPaths) {
|
||||
# Handle wildcard paths
|
||||
if ($path.Contains("*")) {
|
||||
$foundPaths = Get-ChildItem -Path $path -ErrorAction SilentlyContinue
|
||||
if ($foundPaths) {
|
||||
return $foundPaths[0].FullName
|
||||
}
|
||||
} else {
|
||||
if (Test-Path $path) {
|
||||
return $path
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $null
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Installation Methods
|
||||
|
||||
# Function to install Scoop
|
||||
function Install-Scoop {
|
||||
Write-Host "Installing Scoop..."
|
||||
|
||||
# Check if running as admin - Scoop should not be installed as admin
|
||||
if (Test-Admin) {
|
||||
throw "Scoop cannot be installed with administrator privileges. Please run this script as a regular user first to install Scoop and beszel-agent, then run as admin to configure the service."
|
||||
}
|
||||
|
||||
try {
|
||||
Invoke-RestMethod -Uri https://get.scoop.sh | Invoke-Expression
|
||||
|
||||
if (-not (Test-CommandExists "scoop")) {
|
||||
throw "Failed to install Scoop - command not available after installation"
|
||||
}
|
||||
Write-Host "Scoop installed successfully."
|
||||
}
|
||||
catch {
|
||||
throw "Failed to install Scoop: $($_.Exception.Message)"
|
||||
}
|
||||
}
|
||||
|
||||
# Function to install Git via Scoop
|
||||
function Install-Git {
|
||||
if (Test-CommandExists "git") {
|
||||
Write-Host "Git is already installed."
|
||||
return
|
||||
}
|
||||
|
||||
Write-Host "Installing Git..."
|
||||
scoop install git
|
||||
|
||||
if (-not (Test-CommandExists "git")) {
|
||||
throw "Failed to install Git"
|
||||
}
|
||||
}
|
||||
|
||||
# Function to install NSSM
|
||||
function Install-NSSM {
|
||||
param (
|
||||
[string]$Method = "Scoop" # Default to Scoop method
|
||||
)
|
||||
|
||||
if (Test-CommandExists "nssm") {
|
||||
Write-Host "NSSM is already installed."
|
||||
return
|
||||
}
|
||||
|
||||
Write-Host "Installing NSSM..."
|
||||
if ($Method -eq "Scoop") {
|
||||
scoop install nssm
|
||||
}
|
||||
elseif ($Method -eq "WinGet") {
|
||||
winget install -e --id NSSM.NSSM --accept-source-agreements --accept-package-agreements
|
||||
|
||||
# Refresh PATH environment variable to make NSSM available in current session
|
||||
$env:Path = [System.Environment]::GetEnvironmentVariable("Path", "Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path", "User")
|
||||
}
|
||||
else {
|
||||
throw "Unsupported installation method: $Method"
|
||||
}
|
||||
|
||||
if (-not (Test-CommandExists "nssm")) {
|
||||
throw "Failed to install NSSM"
|
||||
}
|
||||
}
|
||||
|
||||
# Function to install beszel-agent with Scoop
|
||||
function Install-BeszelAgentWithScoop {
|
||||
Write-Host "Adding beszel bucket..."
|
||||
scoop bucket add beszel https://github.com/henrygd/beszel-scoops | Out-Null
|
||||
|
||||
Write-Host "Installing / updating beszel-agent..."
|
||||
scoop install beszel-agent | Out-Null
|
||||
|
||||
if (-not (Test-CommandExists "beszel-agent")) {
|
||||
throw "Failed to install beszel-agent"
|
||||
}
|
||||
|
||||
return $(Join-Path -Path $(scoop prefix beszel-agent) -ChildPath "beszel-agent.exe")
|
||||
}
|
||||
|
||||
# Function to install beszel-agent with WinGet
|
||||
function Install-BeszelAgentWithWinGet {
|
||||
Write-Host "Installing / updating beszel-agent..."
|
||||
|
||||
# Temporarily change ErrorActionPreference to allow WinGet to complete and show output
|
||||
$originalErrorActionPreference = $ErrorActionPreference
|
||||
$ErrorActionPreference = "Continue"
|
||||
|
||||
# Use call operator (&) and capture exit code properly
|
||||
& winget install --exact --id henrygd.beszel-agent --accept-source-agreements --accept-package-agreements | Out-Null
|
||||
$wingetExitCode = $LASTEXITCODE
|
||||
|
||||
# Restore original ErrorActionPreference
|
||||
$ErrorActionPreference = $originalErrorActionPreference
|
||||
|
||||
# WinGet exit codes:
|
||||
# 0 = Success
|
||||
# -1978335212 (0x8A150014) = No applicable upgrade found (package is up to date)
|
||||
# -1978335189 (0x8A15002B) = Another "no upgrade needed" variant
|
||||
# Other codes indicate actual errors
|
||||
if ($wingetExitCode -eq -1978335212 -or $wingetExitCode -eq -1978335189) {
|
||||
Write-Host "Package is already up to date." -ForegroundColor Green
|
||||
} elseif ($wingetExitCode -ne 0) {
|
||||
Write-Host "WinGet exit code: $wingetExitCode" -ForegroundColor Yellow
|
||||
}
|
||||
|
||||
# Refresh PATH environment variable to make beszel-agent available in current session
|
||||
$env:Path = [System.Environment]::GetEnvironmentVariable("Path", "Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path", "User")
|
||||
|
||||
# Find the path to the beszel-agent executable
|
||||
$agentPath = (Get-Command beszel-agent -ErrorAction SilentlyContinue).Source
|
||||
|
||||
if (-not $agentPath) {
|
||||
throw "Could not find beszel-agent executable path after installation"
|
||||
}
|
||||
|
||||
return $agentPath
|
||||
}
|
||||
|
||||
# Function to install using Scoop
|
||||
function Install-WithScoop {
|
||||
param (
|
||||
[string]$Key,
|
||||
[int]$Port
|
||||
)
|
||||
|
||||
try {
|
||||
# Ensure Scoop is installed
|
||||
if (-not (Test-CommandExists "scoop")) {
|
||||
Install-Scoop | Out-Null
|
||||
}
|
||||
else {
|
||||
Write-Host "Scoop is already installed."
|
||||
}
|
||||
|
||||
# Install Git (required for Scoop buckets)
|
||||
Install-Git | Out-Null
|
||||
|
||||
# Install NSSM
|
||||
Install-NSSM -Method "Scoop" | Out-Null
|
||||
|
||||
# Install beszel-agent
|
||||
$agentPath = Install-BeszelAgentWithScoop
|
||||
|
||||
return $agentPath
|
||||
}
|
||||
catch {
|
||||
Write-Host "ERROR: $($_.Exception.Message)" -ForegroundColor Red
|
||||
Write-Host "Installation failed. Please check the error message above." -ForegroundColor Red
|
||||
Write-Host "Press any key to exit..." -ForegroundColor Red
|
||||
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
|
||||
# Function to install using WinGet
|
||||
function Install-WithWinGet {
|
||||
param (
|
||||
[string]$Key,
|
||||
[int]$Port
|
||||
)
|
||||
|
||||
try {
|
||||
# Install NSSM
|
||||
Install-NSSM -Method "WinGet" | Out-Null
|
||||
|
||||
# Install beszel-agent
|
||||
$agentPath = Install-BeszelAgentWithWinGet
|
||||
|
||||
return $agentPath
|
||||
}
|
||||
catch {
|
||||
Write-Host "ERROR: $($_.Exception.Message)" -ForegroundColor Red
|
||||
Write-Host "Installation failed. Please check the error message above." -ForegroundColor Red
|
||||
Write-Host "Press any key to exit..." -ForegroundColor Red
|
||||
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Service Configuration
|
||||
|
||||
# Function to install and configure the NSSM service
|
||||
function Install-NSSMService {
|
||||
param (
|
||||
[Parameter(Mandatory=$true)]
|
||||
[string]$AgentPath,
|
||||
[Parameter(Mandatory=$true)]
|
||||
[string]$Key,
|
||||
[string]$Token = "",
|
||||
[string]$HubUrl = "",
|
||||
[Parameter(Mandatory=$true)]
|
||||
[int]$Port,
|
||||
[string]$NSSMPath = ""
|
||||
)
|
||||
|
||||
Write-Host "Installing beszel-agent service..."
|
||||
|
||||
# Determine the NSSM executable to use
|
||||
$nssmCommand = "nssm"
|
||||
if ($NSSMPath -and (Test-Path $NSSMPath)) {
|
||||
$nssmCommand = $NSSMPath
|
||||
Write-Host "Using NSSM from: $NSSMPath"
|
||||
} elseif (-not (Test-CommandExists "nssm")) {
|
||||
throw "NSSM is not available in PATH and no valid NSSMPath was provided"
|
||||
}
|
||||
|
||||
# Check if service already exists
|
||||
$existingService = Get-Service -Name "beszel-agent" -ErrorAction SilentlyContinue
|
||||
if ($existingService) {
|
||||
Write-Host "Service already exists. Checking if path update is needed..."
|
||||
|
||||
# Get current service path
|
||||
try {
|
||||
$currentPath = & $nssmCommand get beszel-agent Application
|
||||
if ($LASTEXITCODE -eq 0 -and $currentPath.Trim() -eq $AgentPath) {
|
||||
Write-Host "Service already configured with correct path. Skipping service recreation." -ForegroundColor Green
|
||||
return
|
||||
}
|
||||
|
||||
Write-Host "Service path needs updating. Stopping and removing existing service..."
|
||||
Write-Host " Current path: $($currentPath.Trim())"
|
||||
Write-Host " New path: $AgentPath"
|
||||
} catch {
|
||||
Write-Host "Could not retrieve current service path, will recreate service: $($_.Exception.Message)" -ForegroundColor Yellow
|
||||
Write-Host "Service path needs updating. Stopping and removing existing service..."
|
||||
}
|
||||
|
||||
try {
|
||||
& $nssmCommand stop beszel-agent
|
||||
& $nssmCommand remove beszel-agent confirm
|
||||
} catch {
|
||||
Write-Host "Warning: Failed to remove existing service: $($_.Exception.Message)" -ForegroundColor Yellow
|
||||
}
|
||||
}
|
||||
|
||||
& $nssmCommand install beszel-agent $AgentPath
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "Failed to install beszel-agent service"
|
||||
}
|
||||
|
||||
Write-Host "Configuring service environment variables..."
|
||||
& $nssmCommand set beszel-agent AppEnvironmentExtra "+KEY=$Key"
|
||||
& $nssmCommand set beszel-agent AppEnvironmentExtra "+TOKEN=$Token"
|
||||
& $nssmCommand set beszel-agent AppEnvironmentExtra "+HUB_URL=$HubUrl"
|
||||
& $nssmCommand set beszel-agent AppEnvironmentExtra "+PORT=$Port"
|
||||
|
||||
# Configure log files
|
||||
$logDir = "$env:ProgramData\beszel-agent\logs"
|
||||
if (-not (Test-Path $logDir)) {
|
||||
New-Item -ItemType Directory -Path $logDir -Force | Out-Null
|
||||
}
|
||||
$logFile = "$logDir\beszel-agent.log"
|
||||
& $nssmCommand set beszel-agent AppStdout $logFile
|
||||
& $nssmCommand set beszel-agent AppStderr $logFile
|
||||
}
|
||||
|
||||
# Function to configure firewall rules
|
||||
function Configure-Firewall {
|
||||
param (
|
||||
[Parameter(Mandatory=$true)]
|
||||
[int]$Port
|
||||
)
|
||||
|
||||
# Create a firewall rule if it doesn't exist
|
||||
$ruleName = "Allow beszel-agent"
|
||||
$existingRule = Get-NetFirewallRule -DisplayName $ruleName -ErrorAction SilentlyContinue
|
||||
|
||||
# Remove existing rule if found
|
||||
if ($existingRule) {
|
||||
Write-Host "Removing existing firewall rule..."
|
||||
try {
|
||||
Remove-NetFirewallRule -DisplayName $ruleName
|
||||
Write-Host "Existing firewall rule removed successfully."
|
||||
} catch {
|
||||
Write-Host "Warning: Failed to remove existing firewall rule: $($_.Exception.Message)" -ForegroundColor Yellow
|
||||
}
|
||||
}
|
||||
|
||||
# Create new rule with current settings
|
||||
Write-Host "Creating firewall rule for beszel-agent on port $Port..."
|
||||
try {
|
||||
New-NetFirewallRule -DisplayName $ruleName -Direction Inbound -Action Allow -Protocol TCP -LocalPort $Port
|
||||
Write-Host "Firewall rule created successfully."
|
||||
} catch {
|
||||
Write-Host "Warning: Failed to create firewall rule: $($_.Exception.Message)" -ForegroundColor Yellow
|
||||
Write-Host "You may need to manually create a firewall rule for port $Port." -ForegroundColor Yellow
|
||||
}
|
||||
}
|
||||
|
||||
# Function to start and monitor the service
|
||||
function Start-BeszelAgentService {
|
||||
param (
|
||||
[string]$NSSMPath = ""
|
||||
)
|
||||
|
||||
Write-Host "Starting beszel-agent service..."
|
||||
|
||||
# Determine the NSSM executable to use
|
||||
$nssmCommand = "nssm"
|
||||
if ($NSSMPath -and (Test-Path $NSSMPath)) {
|
||||
$nssmCommand = $NSSMPath
|
||||
} elseif (-not (Test-CommandExists "nssm")) {
|
||||
throw "NSSM is not available in PATH and no valid NSSMPath was provided"
|
||||
}
|
||||
|
||||
& $nssmCommand start beszel-agent
|
||||
$startResult = $LASTEXITCODE
|
||||
|
||||
# Only enter the status check loop if the NSSM start command failed
|
||||
if ($startResult -ne 0) {
|
||||
Write-Host "NSSM start command returned error code: $startResult" -ForegroundColor Yellow
|
||||
Write-Host "This could be due to 'SERVICE_START_PENDING' state. Checking service status..."
|
||||
|
||||
# Allow up to 10 seconds for the service to start, checking every second
|
||||
$maxWaitTime = 10 # seconds
|
||||
$elapsedTime = 0
|
||||
$serviceStarted = $false
|
||||
|
||||
while (-not $serviceStarted -and $elapsedTime -lt $maxWaitTime) {
|
||||
Start-Sleep -Seconds 1
|
||||
$elapsedTime += 1
|
||||
|
||||
$serviceStatus = & $nssmCommand status beszel-agent
|
||||
|
||||
if ($serviceStatus -eq "SERVICE_RUNNING") {
|
||||
$serviceStarted = $true
|
||||
Write-Host "Success! The beszel-agent service is now running." -ForegroundColor Green
|
||||
}
|
||||
elseif ($serviceStatus -like "*PENDING*") {
|
||||
Write-Host "Service is still starting (status: $serviceStatus)... waiting" -ForegroundColor Yellow
|
||||
}
|
||||
else {
|
||||
Write-Host "Warning: The service status is '$serviceStatus' instead of 'SERVICE_RUNNING'." -ForegroundColor Yellow
|
||||
Write-Host "You may need to troubleshoot the service installation." -ForegroundColor Yellow
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if (-not $serviceStarted) {
|
||||
Write-Host "Service did not reach running state." -ForegroundColor Yellow
|
||||
Write-Host "You can check status manually with 'nssm status beszel-agent'" -ForegroundColor Yellow
|
||||
}
|
||||
} else {
|
||||
# NSSM start command was successful
|
||||
Write-Host "Success! The beszel-agent service is running properly." -ForegroundColor Green
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Main Script Execution
|
||||
|
||||
# Check if we're running as admin
|
||||
$isAdmin = Test-Admin
|
||||
|
||||
try {
|
||||
# First: Install the agent (doesn't require admin)
|
||||
if (-not $AgentPath) {
|
||||
# Check for problematic case: running as admin and need Scoop
|
||||
if ($isAdmin -and -not (Test-CommandExists "scoop") -and -not (Test-CommandExists "winget")) {
|
||||
Write-Host "ERROR: You're running as administrator but neither Scoop nor WinGet is available." -ForegroundColor Red
|
||||
Write-Host "Scoop should be installed without admin privileges." -ForegroundColor Red
|
||||
Write-Host ""
|
||||
Write-Host "Please either:" -ForegroundColor Yellow
|
||||
Write-Host "1. Run this script again without administrator privileges" -ForegroundColor Yellow
|
||||
Write-Host "2. Install WinGet and run this script again" -ForegroundColor Yellow
|
||||
exit 1
|
||||
}
|
||||
|
||||
if ($InstallMethod -eq "Scoop") {
|
||||
if (-not (Test-CommandExists "scoop")) {
|
||||
throw "InstallMethod is set to Scoop, but Scoop is not available in PATH."
|
||||
}
|
||||
Write-Host "Using Scoop for installation..."
|
||||
$AgentPath = Install-WithScoop -Key $Key -Port $Port
|
||||
}
|
||||
elseif ($InstallMethod -eq "WinGet") {
|
||||
if (-not (Test-CommandExists "winget")) {
|
||||
throw "InstallMethod is set to WinGet, but WinGet is not available in PATH."
|
||||
}
|
||||
Write-Host "Using WinGet for installation..."
|
||||
$AgentPath = Install-WithWinGet -Key $Key -Port $Port
|
||||
}
|
||||
else {
|
||||
if (Test-CommandExists "scoop") {
|
||||
Write-Host "Using Scoop for installation..."
|
||||
$AgentPath = Install-WithScoop -Key $Key -Port $Port
|
||||
}
|
||||
elseif (Test-CommandExists "winget") {
|
||||
Write-Host "Using WinGet for installation..."
|
||||
$AgentPath = Install-WithWinGet -Key $Key -Port $Port
|
||||
}
|
||||
else {
|
||||
Write-Host "Neither Scoop nor WinGet is installed. Installing Scoop..."
|
||||
$AgentPath = Install-WithScoop -Key $Key -Port $Port
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (-not $AgentPath) {
|
||||
throw "Could not find beszel-agent executable. Make sure it was properly installed."
|
||||
}
|
||||
|
||||
# Find NSSM path if not already provided
|
||||
if (-not $NSSMPath) {
|
||||
$NSSMPath = Find-NSSM
|
||||
|
||||
if (-not $NSSMPath -and (Test-CommandExists "nssm")) {
|
||||
$NSSMPath = (Get-Command "nssm" -ErrorAction SilentlyContinue).Source
|
||||
}
|
||||
|
||||
# If we still don't have NSSM, try to install it if we have package managers
|
||||
if (-not $NSSMPath) {
|
||||
if (Test-CommandExists "winget") {
|
||||
Write-Host "NSSM not found. Attempting to install via WinGet..."
|
||||
try {
|
||||
Install-NSSM -Method "WinGet"
|
||||
$NSSMPath = Find-NSSM
|
||||
if (-not $NSSMPath -and (Test-CommandExists "nssm")) {
|
||||
$NSSMPath = (Get-Command "nssm" -ErrorAction SilentlyContinue).Source
|
||||
}
|
||||
} catch {
|
||||
Write-Host "Failed to install NSSM via WinGet: $($_.Exception.Message)" -ForegroundColor Yellow
|
||||
}
|
||||
} elseif (Test-CommandExists "scoop") {
|
||||
Write-Host "NSSM not found. Attempting to install via Scoop..."
|
||||
try {
|
||||
Install-NSSM -Method "Scoop"
|
||||
$NSSMPath = Find-NSSM
|
||||
if (-not $NSSMPath -and (Test-CommandExists "nssm")) {
|
||||
$NSSMPath = (Get-Command "nssm" -ErrorAction SilentlyContinue).Source
|
||||
}
|
||||
} catch {
|
||||
Write-Host "Failed to install NSSM via Scoop: $($_.Exception.Message)" -ForegroundColor Yellow
|
||||
}
|
||||
}
|
||||
|
||||
# Final check - if we still don't have NSSM and we're admin, we have a problem
|
||||
if (-not $NSSMPath -and ($isAdmin -or $Elevated)) {
|
||||
throw "NSSM is required for service installation but was not found and could not be installed. Please install NSSM manually or run as a regular user to install it."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Second: If we need admin rights for service installation and we don't have them, relaunch
|
||||
if (-not $isAdmin -and -not $Elevated) {
|
||||
Write-Host "Admin privileges required for service installation. Relaunching as admin..." -ForegroundColor Yellow
|
||||
Write-Host "Check service status with 'nssm status beszel-agent'"
|
||||
Write-Host "Edit service configuration with 'nssm edit beszel-agent'"
|
||||
|
||||
# Prepare arguments for the elevated script
|
||||
$argumentList = @(
|
||||
"-ExecutionPolicy", "Bypass",
|
||||
"-File", "`"$PSCommandPath`"",
|
||||
"-Elevated",
|
||||
"-Key", "`"$Key`"",
|
||||
"-Token", "`"$Token`"",
|
||||
"-Url", "`"$Url`"",
|
||||
"-Port", $Port,
|
||||
"-AgentPath", "`"$AgentPath`"",
|
||||
"-InstallMethod", $InstallMethod
|
||||
)
|
||||
|
||||
# Add NSSMPath if we found it
|
||||
if ($NSSMPath) {
|
||||
$argumentList += "-NSSMPath"
|
||||
$argumentList += "`"$NSSMPath`""
|
||||
}
|
||||
|
||||
if ($ConfigureFirewall) {
|
||||
$argumentList += "-ConfigureFirewall"
|
||||
}
|
||||
|
||||
# Relaunch the script with the -Elevated switch and pass parameters
|
||||
Start-Process powershell.exe -Verb RunAs -ArgumentList $argumentList
|
||||
exit
|
||||
}
|
||||
|
||||
# Third: If we have admin rights, install service and configure firewall
|
||||
if ($isAdmin -or $Elevated) {
|
||||
# Install the service
|
||||
Install-NSSMService -AgentPath $AgentPath -Key $Key -Token $Token -HubUrl $Url -Port $Port -NSSMPath $NSSMPath
|
||||
|
||||
if ($ConfigureFirewall) {
|
||||
Configure-Firewall -Port $Port
|
||||
} else {
|
||||
Write-Host "Skipping firewall configuration. Use -ConfigureFirewall to add an inbound rule for port $Port." -ForegroundColor Yellow
|
||||
}
|
||||
|
||||
# Start the service
|
||||
Start-BeszelAgentService -NSSMPath $NSSMPath
|
||||
|
||||
# Pause to see results if this is an elevated window
|
||||
if ($Elevated) {
|
||||
Write-Host "Press any key to exit..." -ForegroundColor Cyan
|
||||
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
|
||||
}
|
||||
}
|
||||
}
|
||||
catch {
|
||||
Write-Host "ERROR: $($_.Exception.Message)" -ForegroundColor Red
|
||||
Write-Host "Installation failed. Please check the error message above." -ForegroundColor Red
|
||||
|
||||
# Pause if this is likely a new window
|
||||
if ($Elevated -or (-not $isAdmin)) {
|
||||
Write-Host "Press any key to exit..." -ForegroundColor Red
|
||||
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
|
||||
}
|
||||
exit 1
|
||||
}
|
||||
|
||||
#endregion
|
||||
Executable
+1080
File diff suppressed because it is too large
Load Diff
Executable
+479
@@ -0,0 +1,479 @@
|
||||
#!/bin/sh
|
||||
|
||||
is_freebsd() {
|
||||
[ "$(uname -s)" = "FreeBSD" ]
|
||||
}
|
||||
|
||||
# Function to ensure the proxy URL ends with a /
|
||||
ensure_trailing_slash() {
|
||||
if [ -n "$1" ]; then
|
||||
case "$1" in
|
||||
*/) echo "$1" ;;
|
||||
*) echo "$1/" ;;
|
||||
esac
|
||||
else
|
||||
echo "$1"
|
||||
fi
|
||||
}
|
||||
|
||||
# Generate FreeBSD rc service content
|
||||
generate_freebsd_rc_service() {
|
||||
cat <<'EOF'
|
||||
#!/bin/sh
|
||||
|
||||
# PROVIDE: beszel_hub
|
||||
# REQUIRE: DAEMON NETWORKING
|
||||
# BEFORE: LOGIN
|
||||
# KEYWORD: shutdown
|
||||
|
||||
# Add the following lines to /etc/rc.conf to configure Beszel Hub:
|
||||
#
|
||||
# beszel_hub_enable (bool): Set to YES to enable Beszel Hub
|
||||
# Default: YES
|
||||
# beszel_hub_port (str): Port to listen on
|
||||
# Default: 8090
|
||||
# beszel_hub_user (str): Beszel Hub daemon user
|
||||
# Default: beszel
|
||||
# beszel_hub_bin (str): Path to the beszel binary
|
||||
# Default: /usr/local/sbin/beszel
|
||||
# beszel_hub_data (str): Path to the beszel data directory
|
||||
# Default: /usr/local/etc/beszel/beszel_data
|
||||
# beszel_hub_flags (str): Extra flags passed to beszel command invocation
|
||||
# Default:
|
||||
|
||||
. /etc/rc.subr
|
||||
|
||||
name="beszel_hub"
|
||||
rcvar=beszel_hub_enable
|
||||
|
||||
load_rc_config $name
|
||||
: ${beszel_hub_enable:="YES"}
|
||||
: ${beszel_hub_port:="8090"}
|
||||
: ${beszel_hub_user:="beszel"}
|
||||
: ${beszel_hub_flags:=""}
|
||||
: ${beszel_hub_bin:="/usr/local/sbin/beszel"}
|
||||
: ${beszel_hub_data:="/usr/local/etc/beszel/beszel_data"}
|
||||
|
||||
logfile="/var/log/${name}.log"
|
||||
pidfile="/var/run/${name}.pid"
|
||||
|
||||
procname="/usr/sbin/daemon"
|
||||
start_precmd="${name}_prestart"
|
||||
start_cmd="${name}_start"
|
||||
stop_cmd="${name}_stop"
|
||||
|
||||
extra_commands="upgrade"
|
||||
upgrade_cmd="beszel_hub_upgrade"
|
||||
|
||||
beszel_hub_prestart()
|
||||
{
|
||||
if [ ! -d "${beszel_hub_data}" ]; then
|
||||
echo "Creating data directory ${beszel_hub_data}"
|
||||
mkdir -p "${beszel_hub_data}"
|
||||
chown "${beszel_hub_user}:${beszel_hub_user}" "${beszel_hub_data}"
|
||||
fi
|
||||
}
|
||||
|
||||
beszel_hub_start()
|
||||
{
|
||||
echo "Starting ${name}"
|
||||
cd "$(dirname "${beszel_hub_data}")" || exit 1
|
||||
/usr/sbin/daemon -f \
|
||||
-P "${pidfile}" \
|
||||
-o "${logfile}" \
|
||||
-u "${beszel_hub_user}" \
|
||||
"${beszel_hub_bin}" serve --http "0.0.0.0:${beszel_hub_port}" ${beszel_hub_flags}
|
||||
}
|
||||
|
||||
beszel_hub_stop()
|
||||
{
|
||||
pid="$(check_pidfile "${pidfile}" "${procname}")"
|
||||
if [ -n "${pid}" ]; then
|
||||
echo "Stopping ${name} (pid=${pid})"
|
||||
kill -- "-${pid}"
|
||||
wait_for_pids "${pid}"
|
||||
else
|
||||
echo "${name} isn't running"
|
||||
fi
|
||||
}
|
||||
|
||||
beszel_hub_upgrade()
|
||||
{
|
||||
echo "Upgrading ${name}"
|
||||
if command -v sudo >/dev/null; then
|
||||
sudo -u "${beszel_hub_user}" -- "${beszel_hub_bin}" update
|
||||
else
|
||||
su -m "${beszel_hub_user}" -c "${beszel_hub_bin} update"
|
||||
fi
|
||||
}
|
||||
|
||||
run_rc_command "$1"
|
||||
EOF
|
||||
}
|
||||
|
||||
# Detect system architecture
|
||||
detect_architecture() {
|
||||
arch=$(uname -m)
|
||||
case "$arch" in
|
||||
x86_64)
|
||||
arch="amd64"
|
||||
;;
|
||||
armv7l)
|
||||
arch="arm"
|
||||
;;
|
||||
aarch64)
|
||||
arch="arm64"
|
||||
;;
|
||||
esac
|
||||
echo "$arch"
|
||||
}
|
||||
|
||||
# Build sudo args by properly quoting everything
|
||||
build_sudo_args() {
|
||||
QUOTED_ARGS=""
|
||||
while [ $# -gt 0 ]; do
|
||||
if [ -n "$QUOTED_ARGS" ]; then
|
||||
QUOTED_ARGS="$QUOTED_ARGS "
|
||||
fi
|
||||
QUOTED_ARGS="$QUOTED_ARGS'$(echo "$1" | sed "s/'/'\\\\''/g")'"
|
||||
shift
|
||||
done
|
||||
echo "$QUOTED_ARGS"
|
||||
}
|
||||
|
||||
# Check if running as root and re-execute with sudo if needed
|
||||
if [ "$(id -u)" != "0" ]; then
|
||||
if command -v sudo >/dev/null 2>&1; then
|
||||
SUDO_ARGS=$(build_sudo_args "$@")
|
||||
eval "exec sudo $0 $SUDO_ARGS"
|
||||
else
|
||||
echo "This script must be run as root. Please either:"
|
||||
echo "1. Run this script as root (su root)"
|
||||
echo "2. Install sudo and run with sudo"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Define default values
|
||||
PORT=8090
|
||||
GITHUB_URL="https://github.com"
|
||||
AUTO_UPDATE_FLAG="false"
|
||||
UNINSTALL=false
|
||||
|
||||
# Parse command line arguments
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
-u)
|
||||
UNINSTALL=true
|
||||
shift
|
||||
;;
|
||||
-h|--help)
|
||||
printf "Beszel Hub installation script\n\n"
|
||||
printf "Usage: ./install-hub.sh [options]\n\n"
|
||||
printf "Options: \n"
|
||||
printf " -u : Uninstall the Beszel Hub\n"
|
||||
printf " -p <port> : Specify a port number (default: 8090)\n"
|
||||
printf " -c, --mirror [URL] : Use a GitHub mirror/proxy URL (default: https://gh.beszel.dev)\n"
|
||||
printf " --auto-update : Enable automatic daily updates (disabled by default)\n"
|
||||
printf " -h, --help : Display this help message\n"
|
||||
exit 0
|
||||
;;
|
||||
-p)
|
||||
shift
|
||||
PORT="$1"
|
||||
shift
|
||||
;;
|
||||
-c | --mirror)
|
||||
shift
|
||||
if [ -n "$1" ] && ! echo "$1" | grep -q '^-'; then
|
||||
GITHUB_URL="$(ensure_trailing_slash "$1")https://github.com"
|
||||
shift
|
||||
else
|
||||
GITHUB_URL="https://gh.beszel.dev"
|
||||
fi
|
||||
;;
|
||||
--auto-update)
|
||||
AUTO_UPDATE_FLAG="true"
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
echo "Invalid option: $1" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Set paths based on operating system
|
||||
if is_freebsd; then
|
||||
HUB_DIR="/usr/local/etc/beszel"
|
||||
BIN_PATH="/usr/local/sbin/beszel"
|
||||
else
|
||||
HUB_DIR="/opt/beszel"
|
||||
BIN_PATH="/opt/beszel/beszel"
|
||||
fi
|
||||
|
||||
# Uninstall process
|
||||
if [ "$UNINSTALL" = true ]; then
|
||||
if is_freebsd; then
|
||||
echo "Stopping and disabling the Beszel Hub service..."
|
||||
service beszel-hub stop 2>/dev/null
|
||||
sysrc beszel_hub_enable="NO" 2>/dev/null
|
||||
|
||||
echo "Removing the FreeBSD service files..."
|
||||
rm -f /usr/local/etc/rc.d/beszel-hub
|
||||
|
||||
echo "Removing the daily update cron job..."
|
||||
rm -f /etc/cron.d/beszel-hub
|
||||
|
||||
echo "Removing log files..."
|
||||
rm -f /var/log/beszel_hub.log
|
||||
|
||||
echo "Removing the Beszel Hub binary and data..."
|
||||
rm -f "$BIN_PATH"
|
||||
rm -rf "$HUB_DIR"
|
||||
|
||||
echo "Removing the dedicated user..."
|
||||
pw user del beszel 2>/dev/null
|
||||
|
||||
echo "The Beszel Hub has been uninstalled successfully!"
|
||||
exit 0
|
||||
else
|
||||
# Stop and disable the Beszel Hub service
|
||||
echo "Stopping and disabling the Beszel Hub service..."
|
||||
systemctl stop beszel-hub.service
|
||||
systemctl disable beszel-hub.service
|
||||
|
||||
# Remove the systemd service file
|
||||
echo "Removing the systemd service file..."
|
||||
rm -f /etc/systemd/system/beszel-hub.service
|
||||
|
||||
# Remove the update timer and service if they exist
|
||||
echo "Removing the daily update service and timer..."
|
||||
systemctl stop beszel-hub-update.timer 2>/dev/null
|
||||
systemctl disable beszel-hub-update.timer 2>/dev/null
|
||||
rm -f /etc/systemd/system/beszel-hub-update.service
|
||||
rm -f /etc/systemd/system/beszel-hub-update.timer
|
||||
|
||||
# Reload the systemd daemon
|
||||
echo "Reloading the systemd daemon..."
|
||||
systemctl daemon-reload
|
||||
|
||||
# Remove the Beszel Hub binary and data
|
||||
echo "Removing the Beszel Hub binary and data..."
|
||||
rm -rf "$HUB_DIR"
|
||||
|
||||
# Remove the dedicated user
|
||||
echo "Removing the dedicated user..."
|
||||
userdel beszel 2>/dev/null
|
||||
|
||||
echo "The Beszel Hub has been uninstalled successfully!"
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
# Function to check if a package is installed
|
||||
package_installed() {
|
||||
command -v "$1" >/dev/null 2>&1
|
||||
}
|
||||
|
||||
# Check for package manager and install necessary packages if not installed
|
||||
if package_installed pkg && is_freebsd; then
|
||||
if ! package_installed tar || ! package_installed curl; then
|
||||
pkg update
|
||||
pkg install -y gtar curl
|
||||
fi
|
||||
elif package_installed apt-get; then
|
||||
if ! package_installed tar || ! package_installed curl; then
|
||||
apt-get update
|
||||
apt-get install -y tar curl
|
||||
fi
|
||||
elif package_installed yum; then
|
||||
if ! package_installed tar || ! package_installed curl; then
|
||||
yum install -y tar curl
|
||||
fi
|
||||
elif package_installed pacman; then
|
||||
if ! package_installed tar || ! package_installed curl; then
|
||||
pacman -Sy --noconfirm tar curl
|
||||
fi
|
||||
else
|
||||
echo "Warning: Please ensure 'tar' and 'curl' are installed."
|
||||
fi
|
||||
|
||||
# Create a dedicated user for the service if it doesn't exist
|
||||
echo "Creating a dedicated user for the Beszel Hub service..."
|
||||
if is_freebsd; then
|
||||
if ! id -u beszel >/dev/null 2>&1; then
|
||||
pw user add beszel -d /nonexistent -s /usr/sbin/nologin -c "beszel user"
|
||||
fi
|
||||
else
|
||||
if ! id -u beszel >/dev/null 2>&1; then
|
||||
useradd -M -s /bin/false beszel
|
||||
fi
|
||||
fi
|
||||
|
||||
# Create the directory for the Beszel Hub
|
||||
echo "Creating the directory for the Beszel Hub..."
|
||||
mkdir -p "$HUB_DIR/beszel_data"
|
||||
chown -R beszel:beszel "$HUB_DIR"
|
||||
chmod 755 "$HUB_DIR"
|
||||
|
||||
# Download and install the Beszel Hub
|
||||
echo "Downloading and installing the Beszel Hub..."
|
||||
|
||||
OS=$(uname -s | tr '[:upper:]' '[:lower:]')
|
||||
ARCH=$(detect_architecture)
|
||||
FILE_NAME="beszel_${OS}_${ARCH}.tar.gz"
|
||||
|
||||
TEMP_DIR=$(mktemp -d)
|
||||
ARCHIVE_PATH="$TEMP_DIR/$FILE_NAME"
|
||||
DOWNLOAD_URL="$GITHUB_URL/henrygd/beszel/releases/latest/download/$FILE_NAME"
|
||||
|
||||
if ! curl -fL# --retry 3 --retry-delay 2 --connect-timeout 10 "$DOWNLOAD_URL" -o "$ARCHIVE_PATH"; then
|
||||
echo "Failed to download the Beszel Hub from:"
|
||||
echo "$DOWNLOAD_URL"
|
||||
echo "Try again with --mirror (or --mirror <url>) if GitHub is not reachable."
|
||||
rm -rf "$TEMP_DIR"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! tar -tzf "$ARCHIVE_PATH" >/dev/null 2>&1; then
|
||||
echo "Downloaded archive is invalid or incomplete (possible network/proxy issue)."
|
||||
echo "Try again with --mirror (or --mirror <url>) if the download path is unstable."
|
||||
rm -rf "$TEMP_DIR"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! tar -xzf "$ARCHIVE_PATH" -C "$TEMP_DIR" beszel; then
|
||||
echo "Failed to extract beszel from archive."
|
||||
rm -rf "$TEMP_DIR"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -s "$TEMP_DIR/beszel" ]; then
|
||||
echo "Downloaded binary is missing or empty."
|
||||
rm -rf "$TEMP_DIR"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
chmod +x "$TEMP_DIR/beszel"
|
||||
mv "$TEMP_DIR/beszel" "$BIN_PATH"
|
||||
chown beszel:beszel "$BIN_PATH"
|
||||
rm -rf "$TEMP_DIR"
|
||||
|
||||
if is_freebsd; then
|
||||
echo "Creating FreeBSD rc service..."
|
||||
|
||||
# Create the rc service file
|
||||
generate_freebsd_rc_service > /usr/local/etc/rc.d/beszel-hub
|
||||
|
||||
# Set proper permissions for the rc script
|
||||
chmod 755 /usr/local/etc/rc.d/beszel-hub
|
||||
|
||||
# Configure the port
|
||||
sysrc beszel_hub_port="$PORT"
|
||||
|
||||
# Enable and start the service
|
||||
echo "Enabling and starting the Beszel Hub service..."
|
||||
sysrc beszel_hub_enable="YES"
|
||||
service beszel-hub restart
|
||||
|
||||
# Check if service started successfully
|
||||
sleep 2
|
||||
if ! service beszel-hub status | grep -q "is running"; then
|
||||
echo "Error: The Beszel Hub service failed to start. Checking logs..."
|
||||
tail -n 20 /var/log/beszel_hub.log
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Auto-update service for FreeBSD
|
||||
if [ "$AUTO_UPDATE_FLAG" = "true" ]; then
|
||||
echo "Setting up daily automatic updates for beszel-hub..."
|
||||
|
||||
# Create cron job in /etc/cron.d
|
||||
cat >/etc/cron.d/beszel-hub <<EOF
|
||||
# Beszel Hub daily update job
|
||||
12 8 * * * root $BIN_PATH update >/dev/null 2>&1
|
||||
EOF
|
||||
chmod 644 /etc/cron.d/beszel-hub
|
||||
printf "\nDaily updates have been enabled via /etc/cron.d.\n"
|
||||
fi
|
||||
|
||||
# Check service status
|
||||
if ! service beszel-hub status >/dev/null 2>&1; then
|
||||
echo "Error: The Beszel Hub service is not running."
|
||||
service beszel-hub status
|
||||
exit 1
|
||||
fi
|
||||
|
||||
else
|
||||
# Original systemd service installation code
|
||||
printf "Creating the systemd service for the Beszel Hub...\n"
|
||||
cat >/etc/systemd/system/beszel-hub.service <<EOF
|
||||
[Unit]
|
||||
Description=Beszel Hub Service
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
ExecStart=$BIN_PATH serve --http "0.0.0.0:$PORT"
|
||||
WorkingDirectory=$HUB_DIR
|
||||
User=beszel
|
||||
Restart=always
|
||||
RestartSec=5
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
|
||||
# Load and start the service
|
||||
printf "Loading and starting the Beszel Hub service...\n"
|
||||
systemctl daemon-reload
|
||||
systemctl enable --quiet beszel-hub.service
|
||||
systemctl start --quiet beszel-hub.service
|
||||
|
||||
# Wait for the service to start or fail
|
||||
sleep 2
|
||||
|
||||
# Check if the service is running
|
||||
if [ "$(systemctl is-active beszel-hub.service)" != "active" ]; then
|
||||
echo "Error: The Beszel Hub service is not running."
|
||||
echo "$(systemctl status beszel-hub.service)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Enable auto-update if flag is set to true
|
||||
if [ "$AUTO_UPDATE_FLAG" = "true" ]; then
|
||||
echo "Setting up daily automatic updates for beszel-hub..."
|
||||
|
||||
# Create systemd service for the daily update
|
||||
cat >/etc/systemd/system/beszel-hub-update.service <<EOF
|
||||
[Unit]
|
||||
Description=Update beszel-hub if needed
|
||||
Wants=beszel-hub.service
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=$BIN_PATH update
|
||||
EOF
|
||||
|
||||
# Create systemd timer for the daily update
|
||||
cat >/etc/systemd/system/beszel-hub-update.timer <<EOF
|
||||
[Unit]
|
||||
Description=Run beszel-hub update daily
|
||||
|
||||
[Timer]
|
||||
OnCalendar=daily
|
||||
Persistent=true
|
||||
RandomizedDelaySec=4h
|
||||
|
||||
[Install]
|
||||
WantedBy=timers.target
|
||||
EOF
|
||||
|
||||
systemctl daemon-reload
|
||||
systemctl enable --now beszel-hub-update.timer
|
||||
|
||||
printf "\nDaily updates have been enabled.\n"
|
||||
fi
|
||||
fi
|
||||
|
||||
printf "\n\033[32mBeszel Hub has been installed successfully! It is now accessible on port $PORT.\033[0m\n"
|
||||
@@ -0,0 +1,82 @@
|
||||
param (
|
||||
[switch]$Elevated
|
||||
)
|
||||
|
||||
# Beszel Agent Upgrade Wrapper
|
||||
# This script downloads and executes the latest upgrade script from GitHub
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
try {
|
||||
Write-Host "Beszel Agent Upgrade Wrapper" -ForegroundColor Cyan
|
||||
Write-Host "============================" -ForegroundColor Cyan
|
||||
Write-Host ""
|
||||
|
||||
# Define the URL for the latest upgrade script
|
||||
$scriptUrl = "https://raw.githubusercontent.com/henrygd/beszel/main/supplemental/scripts/upgrade-agent.ps1"
|
||||
$tempScriptPath = "$env:TEMP\beszel-upgrade-agent-$(Get-Date -Format 'yyyyMMdd-HHmmss').ps1"
|
||||
|
||||
Write-Host "Downloading latest upgrade script..." -ForegroundColor Yellow
|
||||
Write-Host "From: $scriptUrl"
|
||||
Write-Host "To: $tempScriptPath"
|
||||
|
||||
# Download the latest upgrade script
|
||||
try {
|
||||
Invoke-WebRequest -Uri $scriptUrl -OutFile $tempScriptPath -UseBasicParsing
|
||||
Write-Host "Download completed successfully." -ForegroundColor Green
|
||||
}
|
||||
catch {
|
||||
Write-Host "Failed to download upgrade script: $($_.Exception.Message)" -ForegroundColor Red
|
||||
Write-Host "Please check your internet connection and try again." -ForegroundColor Red
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Verify the script was downloaded
|
||||
if (-not (Test-Path $tempScriptPath)) {
|
||||
Write-Host "ERROR: Downloaded script not found at $tempScriptPath" -ForegroundColor Red
|
||||
exit 1
|
||||
}
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "Executing upgrade script..." -ForegroundColor Yellow
|
||||
|
||||
# Execute the downloaded script with the same parameters
|
||||
if ($Elevated) {
|
||||
& $tempScriptPath -Elevated
|
||||
} else {
|
||||
& $tempScriptPath
|
||||
}
|
||||
|
||||
$scriptExitCode = $LASTEXITCODE
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "Cleaning up temporary files..." -ForegroundColor Yellow
|
||||
|
||||
# Clean up the temporary script
|
||||
try {
|
||||
Remove-Item $tempScriptPath -Force -ErrorAction SilentlyContinue
|
||||
Write-Host "Cleanup completed." -ForegroundColor Green
|
||||
}
|
||||
catch {
|
||||
Write-Host "Warning: Could not remove temporary script: $tempScriptPath" -ForegroundColor Yellow
|
||||
}
|
||||
|
||||
# Exit with the same code as the upgrade script
|
||||
exit $scriptExitCode
|
||||
}
|
||||
catch {
|
||||
Write-Host "ERROR: $($_.Exception.Message)" -ForegroundColor Red
|
||||
Write-Host "Upgrade wrapper failed. Please check the error message above." -ForegroundColor Red
|
||||
|
||||
# Clean up on error
|
||||
if ($tempScriptPath -and (Test-Path $tempScriptPath)) {
|
||||
try {
|
||||
Remove-Item $tempScriptPath -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
catch {
|
||||
# Ignore cleanup errors
|
||||
}
|
||||
}
|
||||
|
||||
exit 1
|
||||
}
|
||||
@@ -0,0 +1,415 @@
|
||||
param (
|
||||
[switch]$Elevated
|
||||
)
|
||||
|
||||
# Stop on first error
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
#region Utility Functions
|
||||
|
||||
# Function to check if running as admin
|
||||
function Test-Admin {
|
||||
return ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
|
||||
}
|
||||
|
||||
# Function to check if a command exists
|
||||
function Test-CommandExists {
|
||||
param (
|
||||
[Parameter(Mandatory=$true)]
|
||||
[string]$Command
|
||||
)
|
||||
return (Get-Command $Command -ErrorAction SilentlyContinue)
|
||||
}
|
||||
|
||||
# Function to find beszel-agent in common installation locations
|
||||
function Find-BeszelAgent {
|
||||
# First check if it's in PATH
|
||||
$agentCmd = Get-Command "beszel-agent" -ErrorAction SilentlyContinue
|
||||
if ($agentCmd) {
|
||||
return $agentCmd.Source
|
||||
}
|
||||
|
||||
# Common installation paths to check
|
||||
$commonPaths = @(
|
||||
"$env:USERPROFILE\scoop\apps\beszel-agent\current\beszel-agent.exe",
|
||||
"$env:ProgramData\scoop\apps\beszel-agent\current\beszel-agent.exe",
|
||||
"$env:LOCALAPPDATA\Microsoft\WinGet\Packages\henrygd.beszel-agent*\beszel-agent.exe",
|
||||
"$env:ProgramFiles\WinGet\Packages\henrygd.beszel-agent*\beszel-agent.exe",
|
||||
"${env:ProgramFiles(x86)}\WinGet\Packages\henrygd.beszel-agent*\beszel-agent.exe",
|
||||
"$env:ProgramFiles\beszel-agent\beszel-agent.exe",
|
||||
"$env:ProgramFiles(x86)\beszel-agent\beszel-agent.exe",
|
||||
"$env:SystemDrive\Users\*\scoop\apps\beszel-agent\current\beszel-agent.exe"
|
||||
)
|
||||
|
||||
foreach ($path in $commonPaths) {
|
||||
# Handle wildcard paths
|
||||
if ($path.Contains("*")) {
|
||||
$foundPaths = Get-ChildItem -Path $path -ErrorAction SilentlyContinue
|
||||
if ($foundPaths) {
|
||||
return $foundPaths[0].FullName
|
||||
}
|
||||
} else {
|
||||
if (Test-Path $path) {
|
||||
return $path
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $null
|
||||
}
|
||||
|
||||
# Function to find NSSM in common installation locations
|
||||
function Find-NSSM {
|
||||
# First check if it's in PATH
|
||||
$nssmCmd = Get-Command "nssm" -ErrorAction SilentlyContinue
|
||||
if ($nssmCmd) {
|
||||
return $nssmCmd.Source
|
||||
}
|
||||
|
||||
# Common installation paths to check
|
||||
$commonPaths = @(
|
||||
"$env:USERPROFILE\scoop\apps\nssm\current\nssm.exe",
|
||||
"$env:ProgramData\scoop\apps\nssm\current\nssm.exe",
|
||||
"$env:LOCALAPPDATA\Microsoft\WinGet\Packages\NSSM.NSSM*\nssm.exe",
|
||||
"$env:ProgramFiles\WinGet\Packages\NSSM.NSSM*\nssm.exe",
|
||||
"${env:ProgramFiles(x86)}\WinGet\Packages\NSSM.NSSM*\nssm.exe",
|
||||
"$env:SystemDrive\Users\*\scoop\apps\nssm\current\nssm.exe"
|
||||
)
|
||||
|
||||
foreach ($path in $commonPaths) {
|
||||
# Handle wildcard paths
|
||||
if ($path.Contains("*")) {
|
||||
$foundPaths = Get-ChildItem -Path $path -ErrorAction SilentlyContinue
|
||||
if ($foundPaths) {
|
||||
return $foundPaths[0].FullName
|
||||
}
|
||||
} else {
|
||||
if (Test-Path $path) {
|
||||
return $path
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $null
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Upgrade Functions
|
||||
|
||||
# Function to upgrade beszel-agent with Scoop
|
||||
function Upgrade-BeszelAgentWithScoop {
|
||||
Write-Host "Upgrading beszel-agent with Scoop..."
|
||||
scoop update beszel-agent
|
||||
|
||||
if (-not (Test-CommandExists "beszel-agent")) {
|
||||
throw "Failed to upgrade beszel-agent with Scoop"
|
||||
}
|
||||
|
||||
return $(Join-Path -Path $(scoop prefix beszel-agent) -ChildPath "beszel-agent.exe")
|
||||
}
|
||||
|
||||
# Function to upgrade beszel-agent with WinGet
|
||||
function Upgrade-BeszelAgentWithWinGet {
|
||||
Write-Host "Upgrading beszel-agent with WinGet..."
|
||||
|
||||
# Temporarily change ErrorActionPreference to allow WinGet to complete and show output
|
||||
$originalErrorActionPreference = $ErrorActionPreference
|
||||
$ErrorActionPreference = "Continue"
|
||||
|
||||
# Use call operator (&) and capture exit code properly
|
||||
& winget upgrade --exact --id henrygd.beszel-agent --accept-source-agreements --accept-package-agreements | Out-Null
|
||||
$wingetExitCode = $LASTEXITCODE
|
||||
|
||||
# Restore original ErrorActionPreference
|
||||
$ErrorActionPreference = $originalErrorActionPreference
|
||||
|
||||
# WinGet exit codes:
|
||||
# 0 = Success
|
||||
# -1978335212 (0x8A150014) = No applicable upgrade found (package is up to date)
|
||||
# -1978335189 (0x8A15002B) = Another "no upgrade needed" variant
|
||||
# Other codes indicate actual errors
|
||||
if ($wingetExitCode -eq -1978335212 -or $wingetExitCode -eq -1978335189) {
|
||||
Write-Host "Package is already up to date." -ForegroundColor Green
|
||||
} elseif ($wingetExitCode -ne 0) {
|
||||
Write-Host "WinGet exit code: $wingetExitCode" -ForegroundColor Yellow
|
||||
}
|
||||
|
||||
# Refresh PATH environment variable to make beszel-agent available in current session
|
||||
$env:Path = [System.Environment]::GetEnvironmentVariable("Path", "Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path", "User")
|
||||
|
||||
# Find the path to the beszel-agent executable
|
||||
$agentPath = (Get-Command beszel-agent -ErrorAction SilentlyContinue).Source
|
||||
|
||||
if (-not $agentPath) {
|
||||
# Try to find it using our search function
|
||||
$agentPath = Find-BeszelAgent
|
||||
if (-not $agentPath) {
|
||||
throw "Could not find beszel-agent executable path after upgrade"
|
||||
}
|
||||
}
|
||||
|
||||
return $agentPath
|
||||
}
|
||||
|
||||
# Function to get current service configuration
|
||||
function Get-ServiceConfiguration {
|
||||
param (
|
||||
[string]$NSSMPath = ""
|
||||
)
|
||||
|
||||
# Determine the NSSM executable to use
|
||||
$nssmCommand = "nssm"
|
||||
if ($NSSMPath -and (Test-Path $NSSMPath)) {
|
||||
$nssmCommand = $NSSMPath
|
||||
} elseif (-not (Test-CommandExists "nssm")) {
|
||||
throw "NSSM is not available in PATH and no valid NSSMPath was provided"
|
||||
}
|
||||
|
||||
# Check if service exists
|
||||
$existingService = Get-Service -Name "beszel-agent" -ErrorAction SilentlyContinue
|
||||
if (-not $existingService) {
|
||||
throw "beszel-agent service does not exist. Please run the installation script first."
|
||||
}
|
||||
|
||||
# Get current service configuration
|
||||
$config = @{}
|
||||
|
||||
try {
|
||||
# Get current application path
|
||||
$currentPath = & $nssmCommand get beszel-agent Application
|
||||
if ($LASTEXITCODE -eq 0) {
|
||||
$config.CurrentPath = $currentPath.Trim()
|
||||
}
|
||||
|
||||
# Get environment variables
|
||||
$envVars = & $nssmCommand get beszel-agent AppEnvironmentExtra
|
||||
if ($LASTEXITCODE -eq 0 -and $envVars) {
|
||||
$config.EnvironmentVars = $envVars
|
||||
}
|
||||
|
||||
Write-Host "Current service configuration retrieved successfully."
|
||||
Write-Host "Current agent path: $($config.CurrentPath)"
|
||||
|
||||
return $config
|
||||
}
|
||||
catch {
|
||||
throw "Failed to retrieve current service configuration: $($_.Exception.Message)"
|
||||
}
|
||||
}
|
||||
|
||||
# Function to update service path
|
||||
function Update-ServicePath {
|
||||
param (
|
||||
[Parameter(Mandatory=$true)]
|
||||
[string]$NewAgentPath,
|
||||
[string]$NSSMPath = ""
|
||||
)
|
||||
|
||||
Write-Host "Updating beszel-agent service path..."
|
||||
|
||||
# Determine the NSSM executable to use
|
||||
$nssmCommand = "nssm"
|
||||
if ($NSSMPath -and (Test-Path $NSSMPath)) {
|
||||
$nssmCommand = $NSSMPath
|
||||
Write-Host "Using NSSM from: $NSSMPath"
|
||||
} elseif (-not (Test-CommandExists "nssm")) {
|
||||
throw "NSSM is not available in PATH and no valid NSSMPath was provided"
|
||||
}
|
||||
|
||||
# Update the application path
|
||||
& $nssmCommand set beszel-agent Application $NewAgentPath
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "Failed to update beszel-agent service path"
|
||||
}
|
||||
|
||||
Write-Host "Service path updated to: $NewAgentPath"
|
||||
|
||||
# Start the service
|
||||
Start-BeszelAgentService -NSSMPath $nssmCommand
|
||||
}
|
||||
|
||||
# Function to start and monitor the service
|
||||
function Start-BeszelAgentService {
|
||||
param (
|
||||
[string]$NSSMPath = ""
|
||||
)
|
||||
|
||||
Write-Host "Starting beszel-agent service..."
|
||||
|
||||
# Determine the NSSM executable to use
|
||||
$nssmCommand = "nssm"
|
||||
if ($NSSMPath -and (Test-Path $NSSMPath)) {
|
||||
$nssmCommand = $NSSMPath
|
||||
} elseif (-not (Test-CommandExists "nssm")) {
|
||||
throw "NSSM is not available in PATH and no valid NSSMPath was provided"
|
||||
}
|
||||
|
||||
& $nssmCommand start beszel-agent
|
||||
$startResult = $LASTEXITCODE
|
||||
|
||||
# Only enter the status check loop if the NSSM start command failed
|
||||
if ($startResult -ne 0) {
|
||||
Write-Host "NSSM start command returned error code: $startResult" -ForegroundColor Yellow
|
||||
Write-Host "This could be due to 'SERVICE_START_PENDING' state. Checking service status..."
|
||||
|
||||
# Allow up to 10 seconds for the service to start, checking every second
|
||||
$maxWaitTime = 10 # seconds
|
||||
$elapsedTime = 0
|
||||
$serviceStarted = $false
|
||||
|
||||
while (-not $serviceStarted -and $elapsedTime -lt $maxWaitTime) {
|
||||
Start-Sleep -Seconds 1
|
||||
$elapsedTime += 1
|
||||
|
||||
$serviceStatus = & $nssmCommand status beszel-agent
|
||||
|
||||
if ($serviceStatus -eq "SERVICE_RUNNING") {
|
||||
$serviceStarted = $true
|
||||
Write-Host "Success! The beszel-agent service is now running." -ForegroundColor Green
|
||||
}
|
||||
elseif ($serviceStatus -like "*PENDING*") {
|
||||
Write-Host "Service is still starting (status: $serviceStatus)... waiting" -ForegroundColor Yellow
|
||||
}
|
||||
else {
|
||||
Write-Host "Warning: The service status is '$serviceStatus' instead of 'SERVICE_RUNNING'." -ForegroundColor Yellow
|
||||
Write-Host "You may need to troubleshoot the service installation." -ForegroundColor Yellow
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if (-not $serviceStarted) {
|
||||
Write-Host "Service did not reach running state." -ForegroundColor Yellow
|
||||
Write-Host "You can check status manually with 'nssm status beszel-agent'" -ForegroundColor Yellow
|
||||
}
|
||||
} else {
|
||||
# NSSM start command was successful
|
||||
Write-Host "Success! The beszel-agent service is running properly." -ForegroundColor Green
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Main Script Execution
|
||||
|
||||
# Check if we're running as admin
|
||||
$isAdmin = Test-Admin
|
||||
|
||||
try {
|
||||
Write-Host "Beszel Agent Upgrade Script" -ForegroundColor Cyan
|
||||
Write-Host "===========================" -ForegroundColor Cyan
|
||||
|
||||
# First: Check if service exists (doesn't require admin)
|
||||
$existingService = Get-Service -Name "beszel-agent" -ErrorAction SilentlyContinue
|
||||
if (-not $existingService) {
|
||||
Write-Host "ERROR: beszel-agent service does not exist." -ForegroundColor Red
|
||||
Write-Host "Please run the installation script first before attempting to upgrade." -ForegroundColor Red
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Find current NSSM and agent paths
|
||||
$nssmPath = Find-NSSM
|
||||
if (-not $nssmPath -and (Test-CommandExists "nssm")) {
|
||||
$nssmPath = (Get-Command "nssm" -ErrorAction SilentlyContinue).Source
|
||||
}
|
||||
|
||||
if (-not $nssmPath) {
|
||||
Write-Host "ERROR: NSSM not found. Cannot manage the service without NSSM." -ForegroundColor Red
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Get current service configuration (doesn't require admin)
|
||||
Write-Host "Retrieving current service configuration..."
|
||||
$currentConfig = Get-ServiceConfiguration -NSSMPath $nssmPath
|
||||
|
||||
# Stop the service before upgrade
|
||||
Write-Host "Stopping beszel-agent service..."
|
||||
& $nssmPath stop beszel-agent
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Write-Host "Warning: Failed to stop service, continuing anyway..." -ForegroundColor Yellow
|
||||
}
|
||||
|
||||
# Upgrade the agent (doesn't require admin)
|
||||
Write-Host "Upgrading beszel-agent..."
|
||||
$newAgentPath = $null
|
||||
|
||||
if (Test-CommandExists "scoop") {
|
||||
Write-Host "Using Scoop for upgrade..."
|
||||
$newAgentPath = Upgrade-BeszelAgentWithScoop
|
||||
}
|
||||
elseif (Test-CommandExists "winget") {
|
||||
Write-Host "Using WinGet for upgrade..."
|
||||
$newAgentPath = Upgrade-BeszelAgentWithWinGet
|
||||
}
|
||||
else {
|
||||
Write-Host "ERROR: Neither Scoop nor WinGet is available for upgrading." -ForegroundColor Red
|
||||
exit 1
|
||||
}
|
||||
|
||||
if (-not $newAgentPath) {
|
||||
$newAgentPath = Find-BeszelAgent
|
||||
if (-not $newAgentPath) {
|
||||
throw "Could not find beszel-agent executable after upgrade."
|
||||
}
|
||||
}
|
||||
|
||||
Write-Host "New agent path: $newAgentPath"
|
||||
|
||||
# Check if the path has changed
|
||||
if ($currentConfig.CurrentPath -eq $newAgentPath) {
|
||||
Write-Host "Agent path has not changed. Restarting service..." -ForegroundColor Green
|
||||
Start-BeszelAgentService -NSSMPath $nssmPath
|
||||
Write-Host "Upgrade completed successfully!" -ForegroundColor Green
|
||||
exit 0
|
||||
}
|
||||
|
||||
Write-Host "Agent path has changed from:" -ForegroundColor Yellow
|
||||
Write-Host " Old: $($currentConfig.CurrentPath)" -ForegroundColor Yellow
|
||||
Write-Host " New: $newAgentPath" -ForegroundColor Yellow
|
||||
Write-Host ""
|
||||
|
||||
# If we need admin rights for service update and we don't have them, relaunch
|
||||
if (-not $isAdmin -and -not $Elevated) {
|
||||
Write-Host "Admin privileges required for service path update. Relaunching as admin..." -ForegroundColor Yellow
|
||||
|
||||
# Prepare arguments for the elevated script
|
||||
$argumentList = @(
|
||||
"-ExecutionPolicy", "Bypass",
|
||||
"-File", "`"$PSCommandPath`"",
|
||||
"-Elevated"
|
||||
)
|
||||
|
||||
# Relaunch the script with the -Elevated switch
|
||||
Start-Process powershell.exe -Verb RunAs -ArgumentList $argumentList
|
||||
exit
|
||||
}
|
||||
|
||||
# Update service path (requires admin)
|
||||
if ($isAdmin -or $Elevated) {
|
||||
Update-ServicePath -NewAgentPath $newAgentPath -NSSMPath $nssmPath
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "Upgrade completed successfully!" -ForegroundColor Green
|
||||
Write-Host "The beszel-agent service has been updated to use the new executable path." -ForegroundColor Green
|
||||
|
||||
# Pause to see results if this is an elevated window
|
||||
if ($Elevated) {
|
||||
Write-Host ""
|
||||
Write-Host "Press any key to exit..." -ForegroundColor Cyan
|
||||
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
|
||||
}
|
||||
}
|
||||
}
|
||||
catch {
|
||||
Write-Host "ERROR: $($_.Exception.Message)" -ForegroundColor Red
|
||||
Write-Host "Upgrade failed. Please check the error message above." -ForegroundColor Red
|
||||
|
||||
# Pause if this is likely a new window
|
||||
if ($Elevated -or (-not $isAdmin)) {
|
||||
Write-Host "Press any key to exit..." -ForegroundColor Red
|
||||
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
|
||||
}
|
||||
exit 1
|
||||
}
|
||||
|
||||
#endregion
|
||||
Reference in New Issue
Block a user