| #!/bin/sh
|
|
|
| is_alpine() {
|
| [ -f /etc/alpine-release ]
|
| }
|
|
|
| is_openwrt() {
|
| grep -qi "OpenWrt" /etc/os-release
|
| }
|
|
|
| is_freebsd() {
|
| [ "$(uname -s)" = "FreeBSD" ]
|
| }
|
|
|
| is_opnsense() {
|
| [ -f /usr/local/sbin/opnsense-version ] || [ -f /usr/local/etc/opnsense-version ] || [ -f /etc/opnsense-release ]
|
| }
|
|
|
| is_glibc() {
|
|
|
|
|
| for p in \
|
| /lib64/ld-linux-x86-64.so.2 \
|
| /lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 \
|
| /lib/ld-linux-x86-64.so.2; do
|
| [ -e "$p" ] && return 0
|
| done
|
|
|
|
|
| if command -v ldd >/dev/null 2>&1; then
|
| ldd --version 2>&1 | grep -qiE 'gnu libc|glibc' && return 0
|
| fi
|
|
|
| return 1
|
| }
|
|
|
|
|
|
|
| set_selinux_context() {
|
|
|
| if command -v getenforce >/dev/null 2>&1; then
|
| SELINUX_MODE=$(getenforce)
|
| if [ "$SELINUX_MODE" != "Disabled" ]; then
|
| echo "SELinux is enabled (${SELINUX_MODE} mode). Setting appropriate context..."
|
|
|
|
|
| if command -v semanage >/dev/null 2>&1; then
|
| echo "Attempting to set persistent SELinux context..."
|
| if semanage fcontext -a -t bin_t "$BIN_PATH" >/dev/null 2>&1; then
|
| restorecon -v "$BIN_PATH" >/dev/null 2>&1
|
| else
|
| echo "Warning: Failed to set persistent context, falling back to temporary context."
|
| fi
|
| fi
|
|
|
|
|
| if command -v chcon >/dev/null 2>&1; then
|
|
|
| chcon -t bin_t "$BIN_PATH" || echo "Warning: Failed to set SELinux context for binary."
|
| chcon -R -t bin_t "$AGENT_DIR" || echo "Warning: Failed to set SELinux context for directory."
|
| else
|
| if [ "$SELINUX_MODE" = "Enforcing" ]; then
|
| echo "Warning: SELinux is in enforcing mode but chcon command not found. The service may fail to start."
|
| echo "Consider installing the policycoreutils package or temporarily setting SELinux to permissive mode."
|
| else
|
| echo "Warning: SELinux is in permissive mode but chcon command not found."
|
| fi
|
| fi
|
| fi
|
| fi
|
| }
|
|
|
|
|
| cleanup_selinux_context() {
|
| if command -v getenforce >/dev/null 2>&1 && [ "$(getenforce)" != "Disabled" ]; then
|
| echo "Cleaning up SELinux contexts..."
|
|
|
| if command -v semanage >/dev/null 2>&1; then
|
| semanage fcontext -d "$BIN_PATH" 2>/dev/null || true
|
| fi
|
| fi
|
| }
|
|
|
|
|
| ensure_trailing_slash() {
|
| if [ -n "$1" ]; then
|
| case "$1" in
|
| */) echo "$1" ;;
|
| *) echo "$1/" ;;
|
| esac
|
| else
|
| echo "$1"
|
| fi
|
| }
|
|
|
|
|
| generate_freebsd_rc_service() {
|
| cat <<'EOF'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| . /etc/rc.subr
|
|
|
| name="beszel_agent"
|
| rcvar=beszel_agent_enable
|
|
|
| load_rc_config $name
|
| : ${beszel_agent_enable:="YES"}
|
| : ${beszel_agent_user:="beszel"}
|
| : ${beszel_agent_flags:=""}
|
| : ${beszel_agent_env_file:="/usr/local/etc/beszel-agent/env"}
|
| : ${beszel_agent_bin:="/usr/local/sbin/beszel-agent"}
|
|
|
| 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_agent_upgrade"
|
|
|
| beszel_agent_prestart()
|
| {
|
| if [ ! -f "${beszel_agent_env_file}" ]; then
|
| echo WARNING: missing "${beszel_agent_env_file}" env file. Start aborted.
|
| exit 1
|
| fi
|
| }
|
|
|
| beszel_agent_start()
|
| {
|
| echo "Starting ${name}"
|
| /usr/sbin/daemon -fc \
|
| -P "${pidfile}" \
|
| -o "${logfile}" \
|
| -u "${beszel_agent_user}" \
|
| "${beszel_agent_bin}" ${beszel_agent_flags}
|
| }
|
|
|
| beszel_agent_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_agent_upgrade()
|
| {
|
| echo "Upgrading ${name}"
|
| if command -v sudo >/dev/null; then
|
| sudo -u "${beszel_agent_user}" -- "${beszel_agent_bin}" update
|
| else
|
| su -m "${beszel_agent_user}" -c "${beszel_agent_bin} update"
|
| fi
|
| }
|
|
|
| run_rc_command "$1"
|
| EOF
|
| }
|
|
|
|
|
| detect_architecture() {
|
| local arch=$(uname -m)
|
|
|
| if [ "$arch" = "mips" ]; then
|
| detect_mips_endianness
|
| return $?
|
| fi
|
|
|
| case "$arch" in
|
| x86_64)
|
| arch="amd64"
|
| ;;
|
| armv6l|armv7l)
|
| arch="arm"
|
| ;;
|
| aarch64)
|
| arch="arm64"
|
| ;;
|
| esac
|
|
|
| echo "$arch"
|
| }
|
|
|
|
|
| detect_mips_endianness() {
|
| local bins="/bin/sh /bin/ls /usr/bin/env"
|
| local bin_to_check endian
|
|
|
| for bin_to_check in $bins; do
|
| if [ -f "$bin_to_check" ]; then
|
|
|
| endian=$(hexdump -n 1 -s 5 -e '1/1 "%02x"' "$bin_to_check" 2>/dev/null)
|
| if [ "$endian" = "01" ]; then
|
| echo "mipsle"
|
| return
|
| elif [ "$endian" = "02" ]; then
|
| echo "mips"
|
| return
|
| fi
|
| fi
|
| done
|
|
|
|
|
| echo "mips"
|
| }
|
|
|
|
|
| PORT=45876
|
| UNINSTALL=false
|
| GITHUB_URL="https://github.com"
|
| GITHUB_PROXY_URL=""
|
| KEY=""
|
| TOKEN=""
|
| HUB_URL=""
|
| AUTO_UPDATE_FLAG=""
|
| VERSION="latest"
|
|
|
|
|
| case "$1" in
|
| -h | --help)
|
| printf "Beszel Agent installation script\n\n"
|
| printf "Usage: ./install-agent.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 " -v, --version : Version to install (default: latest)\n"
|
| printf " -u : Uninstall Beszel Agent\n"
|
| printf " --auto-update [VALUE] : Control automatic daily updates\n"
|
| printf " VALUE can be true (enable) or false (disable). If not specified, will prompt.\n"
|
| printf " --mirror [URL] : Use GitHub proxy to resolve network timeout issues in mainland China\n"
|
| printf " URL: optional custom proxy URL (default: https://gh.beszel.dev)\n"
|
| printf " -h, --help : Display this help message\n"
|
| exit 0
|
| ;;
|
| esac
|
|
|
|
|
| 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"
|
| }
|
|
|
|
|
| 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
|
|
|
|
|
| while [ $# -gt 0 ]; do
|
| case "$1" in
|
| -k)
|
| shift
|
| KEY="$1"
|
| ;;
|
| -p)
|
| shift
|
| PORT="$1"
|
| ;;
|
| -t)
|
| shift
|
| TOKEN="$1"
|
| ;;
|
| -url)
|
| shift
|
| HUB_URL="$1"
|
| ;;
|
| -v | --version)
|
| shift
|
| VERSION="$1"
|
| ;;
|
| -u)
|
| UNINSTALL=true
|
| ;;
|
| --mirror* | --china-mirrors*)
|
|
|
| if echo "$1" | grep -q "="; then
|
|
|
| CUSTOM_PROXY=$(echo "$1" | cut -d'=' -f2)
|
| if [ -n "$CUSTOM_PROXY" ]; then
|
| GITHUB_PROXY_URL="$CUSTOM_PROXY"
|
| GITHUB_URL="$(ensure_trailing_slash "$CUSTOM_PROXY")https://github.com"
|
| else
|
| GITHUB_PROXY_URL="https://gh.beszel.dev"
|
| GITHUB_URL="$GITHUB_PROXY_URL"
|
| fi
|
| elif [ "$2" != "" ] && ! echo "$2" | grep -q '^-'; then
|
|
|
| GITHUB_PROXY_URL="$2"
|
| GITHUB_URL="$(ensure_trailing_slash "$2")https://github.com"
|
| shift
|
| else
|
|
|
| GITHUB_PROXY_URL="https://gh.beszel.dev"
|
| GITHUB_URL="$GITHUB_PROXY_URL"
|
| fi
|
| ;;
|
| --auto-update*)
|
|
|
| if echo "$1" | grep -q "="; then
|
|
|
| AUTO_UPDATE_VALUE=$(echo "$1" | cut -d'=' -f2)
|
| if [ "$AUTO_UPDATE_VALUE" = "true" ]; then
|
| AUTO_UPDATE_FLAG="true"
|
| elif [ "$AUTO_UPDATE_VALUE" = "false" ]; then
|
| AUTO_UPDATE_FLAG="false"
|
| else
|
| echo "Invalid value for --auto-update flag: $AUTO_UPDATE_VALUE. Using default (prompt)."
|
| fi
|
| elif [ "$2" = "true" ] || [ "$2" = "false" ]; then
|
|
|
| AUTO_UPDATE_FLAG="$2"
|
| shift
|
| else
|
|
|
| AUTO_UPDATE_FLAG="true"
|
| fi
|
| ;;
|
| *)
|
| echo "Invalid option: $1" >&2
|
| exit 1
|
| ;;
|
| esac
|
| shift
|
| done
|
|
|
|
|
| if is_freebsd; then
|
| AGENT_DIR="/usr/local/etc/beszel-agent"
|
| BIN_DIR="/usr/local/sbin"
|
| BIN_PATH="/usr/local/sbin/beszel-agent"
|
| else
|
| AGENT_DIR="/opt/beszel-agent"
|
| BIN_DIR="/opt/beszel-agent"
|
| BIN_PATH="/opt/beszel-agent/beszel-agent"
|
| fi
|
|
|
|
|
| if [ "$UNINSTALL" != true ] && [ -f "$BIN_PATH" ]; then
|
| echo "Existing installation detected. Stopping service for upgrade..."
|
| if is_alpine; then
|
| rc-service beszel-agent stop 2>/dev/null || true
|
| elif is_openwrt; then
|
| /etc/init.d/beszel-agent stop 2>/dev/null || true
|
| elif is_freebsd; then
|
| service beszel-agent stop 2>/dev/null || true
|
| else
|
| systemctl stop beszel-agent.service 2>/dev/null || true
|
| fi
|
| fi
|
|
|
|
|
| if [ "$UNINSTALL" = true ]; then
|
|
|
| cleanup_selinux_context
|
|
|
| if is_alpine; then
|
| echo "Stopping and disabling the agent service..."
|
| rc-service beszel-agent stop
|
| rc-update del beszel-agent default
|
|
|
| echo "Removing the OpenRC service files..."
|
| rm -f /etc/init.d/beszel-agent
|
|
|
|
|
| echo "Removing the daily update cron job..."
|
| if crontab -u root -l 2>/dev/null | grep -q "beszel-agent.*update"; then
|
| crontab -u root -l 2>/dev/null | grep -v "beszel-agent.*update" | crontab -u root -
|
| fi
|
|
|
|
|
| echo "Removing log files..."
|
| rm -f /var/log/beszel-agent.log /var/log/beszel-agent.err
|
| elif is_openwrt; then
|
| echo "Stopping and disabling the agent service..."
|
| /etc/init.d/beszel-agent stop
|
| /etc/init.d/beszel-agent disable
|
|
|
| echo "Removing the OpenWRT service files..."
|
| rm -f /etc/init.d/beszel-agent
|
|
|
|
|
| echo "Removing the daily update service..."
|
|
|
| rm -f /etc/crontabs/beszel
|
|
|
| if crontab -u root -l 2>/dev/null | grep -q "beszel-agent.*update"; then
|
| crontab -u root -l 2>/dev/null | grep -v "beszel-agent.*update" | crontab -u root -
|
| fi
|
|
|
| elif is_freebsd; then
|
| echo "Stopping and disabling the agent service..."
|
| service beszel-agent stop
|
| sysrc beszel_agent_enable="NO"
|
|
|
| echo "Removing the FreeBSD service files..."
|
| rm -f /usr/local/etc/rc.d/beszel-agent
|
|
|
|
|
| echo "Removing the daily update cron job..."
|
| rm -f /etc/cron.d/beszel-agent
|
|
|
|
|
| echo "Removing log files..."
|
| rm -f /var/log/beszel-agent.log
|
|
|
|
|
| echo "Removing environment configuration file..."
|
| rm -f "$AGENT_DIR/env"
|
| rm -f "$BIN_PATH"
|
| rmdir "$AGENT_DIR" 2>/dev/null || true
|
|
|
| else
|
| echo "Stopping and disabling the agent service..."
|
| systemctl stop beszel-agent.service
|
| systemctl disable beszel-agent.service >/dev/null 2>&1
|
|
|
| echo "Removing the systemd service file..."
|
| rm /etc/systemd/system/beszel-agent.service
|
|
|
|
|
| echo "Removing the daily update service and timer..."
|
| systemctl stop beszel-agent-update.timer 2>/dev/null
|
| systemctl disable beszel-agent-update.timer >/dev/null 2>&1
|
| rm -f /etc/systemd/system/beszel-agent-update.service
|
| rm -f /etc/systemd/system/beszel-agent-update.timer
|
|
|
| systemctl daemon-reload
|
| fi
|
|
|
| echo "Removing the Beszel Agent directory..."
|
| rm -rf "$AGENT_DIR"
|
|
|
| echo "Removing the dedicated user for the agent service..."
|
| killall beszel-agent 2>/dev/null
|
| if is_alpine || is_openwrt; then
|
| deluser beszel 2>/dev/null
|
| elif is_freebsd; then
|
| pw user del beszel 2>/dev/null
|
| else
|
| userdel beszel 2>/dev/null
|
| fi
|
|
|
| echo "Beszel Agent has been uninstalled successfully!"
|
| exit 0
|
| fi
|
|
|
|
|
| package_installed() {
|
| command -v "$1" >/dev/null 2>&1
|
| }
|
|
|
|
|
| if package_installed apk; then
|
| if ! package_installed tar || ! package_installed curl || ! package_installed sha256sum; then
|
| apk update
|
| apk add tar curl coreutils shadow
|
| fi
|
| elif package_installed opkg; then
|
| if ! package_installed tar || ! package_installed curl || ! package_installed sha256sum; then
|
| opkg update
|
| opkg install tar curl coreutils
|
| fi
|
| elif package_installed pkg && is_freebsd; then
|
| if ! package_installed tar || ! package_installed curl || ! package_installed sha256sum; then
|
| pkg update
|
| pkg install -y gtar curl coreutils
|
| fi
|
| elif package_installed apt-get; then
|
| if ! package_installed tar || ! package_installed curl || ! package_installed sha256sum; then
|
| apt-get update
|
| apt-get install -y tar curl coreutils
|
| fi
|
| elif package_installed yum; then
|
| if ! package_installed tar || ! package_installed curl || ! package_installed sha256sum; then
|
| yum install -y tar curl coreutils
|
| fi
|
| elif package_installed pacman; then
|
| if ! package_installed tar || ! package_installed curl || ! package_installed sha256sum; then
|
| pacman -Sy --noconfirm tar curl coreutils
|
| fi
|
| else
|
| echo "Warning: Please ensure 'tar' and 'curl' and 'sha256sum (coreutils)' are installed."
|
| fi
|
|
|
|
|
| if [ -z "$KEY" ]; then
|
| if [ -f "$BIN_PATH" ]; then
|
| echo "Upgrading existing installation. Using existing service configuration."
|
| else
|
| printf "Enter your SSH key: "
|
| read KEY
|
| fi
|
| fi
|
|
|
|
|
| KEY=$(echo "$KEY" | tr -d '\n')
|
|
|
|
|
|
|
|
|
|
|
| if command -v sha256sum >/dev/null; then
|
| CHECK_CMD="sha256sum"
|
| elif command -v sha256 >/dev/null; then
|
|
|
| CHECK_CMD="sha256 -q"
|
| else
|
| echo "No SHA256 checksum utility found"
|
| exit 1
|
| fi
|
|
|
|
|
| AGENT_USER="beszel"
|
| echo "Configuring the dedicated user for the Beszel Agent service..."
|
| if is_alpine; then
|
| if ! id -u beszel >/dev/null 2>&1; then
|
| addgroup beszel
|
| adduser -S -D -H -s /sbin/nologin -G beszel beszel
|
| fi
|
|
|
| if getent group docker >/dev/null 2>&1; then
|
| echo "Adding beszel to docker group"
|
| addgroup beszel docker
|
| fi
|
|
|
| elif is_openwrt; then
|
|
|
| if ! grep -q "^beszel:" /etc/group >/dev/null 2>&1; then
|
| echo "beszel:x:999:" >> /etc/group
|
| fi
|
|
|
|
|
| if ! id -u beszel >/dev/null 2>&1 && ! grep -q "^beszel:" /etc/passwd >/dev/null 2>&1; then
|
| echo "beszel:x:999:999::/nonexistent:/bin/false" >> /etc/passwd
|
| fi
|
|
|
|
|
| if grep -q "^docker:" /etc/group >/dev/null 2>&1; then
|
| echo "Adding beszel to docker group"
|
|
|
| if ! grep "^docker:" /etc/group | grep -q "beszel"; then
|
|
|
|
|
| if grep "^docker:" /etc/group | grep -q ":.*:.*$"; then
|
|
|
| sed -i 's/^docker:\([^:]*:[^:]*:\)\(.*\)$/docker:\1\2,beszel/' /etc/group
|
| else
|
|
|
| sed -i 's/^docker:\([^:]*:[^:]*:\)$/docker:\1beszel/' /etc/group
|
| fi
|
| fi
|
| fi
|
|
|
| elif is_freebsd; then
|
| if is_opnsense; then
|
| echo "OPNsense detected: skipping user creation (using daemon user instead)"
|
| AGENT_USER="daemon"
|
| else
|
| if ! id -u beszel >/dev/null 2>&1; then
|
| pw user add beszel -d /nonexistent -s /usr/sbin/nologin -c "beszel user"
|
| fi
|
|
|
| if pw group show wheel >/dev/null 2>&1; then
|
| echo "Adding beszel to wheel group for self-updates"
|
| pw group mod wheel -m beszel
|
| fi
|
| fi
|
|
|
| else
|
| if ! id -u beszel >/dev/null 2>&1; then
|
| useradd --system --home-dir /nonexistent --shell /bin/false beszel
|
| fi
|
|
|
| if getent group docker >/dev/null 2>&1; then
|
| echo "Adding beszel to docker group"
|
| usermod -aG docker beszel
|
| fi
|
|
|
| if getent group disk >/dev/null 2>&1; then
|
| echo "Adding beszel to disk group"
|
| usermod -aG disk beszel
|
| fi
|
| fi
|
|
|
|
|
|
|
| if [ ! -d "$AGENT_DIR" ]; then
|
| echo "Creating the directory for the Beszel Agent..."
|
| mkdir -p "$AGENT_DIR"
|
| chown "${AGENT_USER}:${AGENT_USER}" "$AGENT_DIR"
|
| chmod 755 "$AGENT_DIR"
|
| fi
|
|
|
| if [ ! -d "$BIN_DIR" ]; then
|
| mkdir -p "$BIN_DIR"
|
| fi
|
|
|
|
|
|
|
| OS=$(uname -s | sed -e 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/')
|
| ARCH=$(detect_architecture)
|
| FILE_NAME="beszel-agent_${OS}_${ARCH}.tar.gz"
|
| if [ "$OS" = "linux" ] && [ "$ARCH" = "amd64" ] && is_glibc; then
|
| FILE_NAME="beszel-agent_${OS}_${ARCH}_glibc.tar.gz"
|
| fi
|
|
|
|
|
| if [ "$VERSION" = "latest" ]; then
|
| INSTALL_VERSION=$(curl -s "https://get.beszel.dev/latest-version")
|
| if [ -z "$INSTALL_VERSION" ]; then
|
|
|
| API_RELEASE_URL="https://api.github.com/repos/henrygd/beszel/releases/latest"
|
| INSTALL_VERSION=$(curl -s "$API_RELEASE_URL" | grep -o '"tag_name": "v[^"]*"' | cut -d'"' -f4 | tr -d 'v')
|
| fi
|
| if [ -z "$INSTALL_VERSION" ]; then
|
| echo "Failed to get latest version"
|
| exit 1
|
| fi
|
| else
|
| INSTALL_VERSION="$VERSION"
|
|
|
| INSTALL_VERSION=$(echo "$INSTALL_VERSION" | sed 's/^v//')
|
| fi
|
|
|
| echo "Downloading beszel-agent v${INSTALL_VERSION}..."
|
|
|
|
|
| TEMP_DIR=$(mktemp -d)
|
| cd "$TEMP_DIR" || exit 1
|
| CHECKSUM=$(curl -fsSL "$GITHUB_URL/henrygd/beszel/releases/download/v${INSTALL_VERSION}/beszel_${INSTALL_VERSION}_checksums.txt" | grep "$FILE_NAME" | cut -d' ' -f1)
|
| if [ -z "$CHECKSUM" ] || ! echo "$CHECKSUM" | grep -qE "^[a-fA-F0-9]{64}$"; then
|
| echo "Failed to get checksum or invalid checksum format"
|
| echo "Try again with --mirror (or --mirror <url>) if GitHub is not reachable."
|
| rm -rf "$TEMP_DIR"
|
| exit 1
|
| fi
|
|
|
| if ! curl -fL
|
| echo "Failed to download the agent from $GITHUB_URL/henrygd/beszel/releases/download/v${INSTALL_VERSION}/$FILE_NAME"
|
| echo "Try again with --mirror (or --mirror <url>) if GitHub is not reachable."
|
| rm -rf "$TEMP_DIR"
|
| exit 1
|
| fi
|
|
|
| if ! tar -tzf "$FILE_NAME" >/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 [ "$($CHECK_CMD "$FILE_NAME" | cut -d' ' -f1)" != "$CHECKSUM" ]; then
|
| echo "Checksum verification failed: $($CHECK_CMD "$FILE_NAME" | cut -d' ' -f1) & $CHECKSUM"
|
| rm -rf "$TEMP_DIR"
|
| exit 1
|
| fi
|
|
|
| if ! tar -xzf "$FILE_NAME" beszel-agent; then
|
| echo "Failed to extract the agent"
|
| rm -rf "$TEMP_DIR"
|
| exit 1
|
| fi
|
|
|
| if [ ! -s "$TEMP_DIR/beszel-agent" ]; then
|
| echo "Downloaded binary is missing or empty."
|
| rm -rf "$TEMP_DIR"
|
| exit 1
|
| fi
|
|
|
| if [ -f "$BIN_PATH" ]; then
|
| echo "Backing up existing binary..."
|
| cp "$BIN_PATH" "$BIN_PATH.bak"
|
| fi
|
|
|
| mv beszel-agent "$BIN_PATH"
|
| chown beszel:beszel "$BIN_PATH"
|
| chmod 755 "$BIN_PATH"
|
|
|
|
|
| set_selinux_context
|
|
|
|
|
| rm -rf "$TEMP_DIR"
|
|
|
|
|
| if [ ! -f /etc/machine-id ]; then
|
| cat /proc/sys/kernel/random/uuid | tr -d '-' > /etc/machine-id
|
| fi
|
|
|
|
|
| detect_nvidia_devices() {
|
| local devices=""
|
| for i in /dev/nvidia*; do
|
| if [ -e "$i" ]; then
|
| devices="${devices}DeviceAllow=$i rw\n"
|
| fi
|
| done
|
| echo "$devices"
|
| }
|
|
|
|
|
| if is_alpine; then
|
| if [ ! -f /etc/init.d/beszel-agent ]; then
|
| echo "Creating OpenRC service for Alpine Linux..."
|
| cat >/etc/init.d/beszel-agent <<EOF
|
| #!/sbin/openrc-run
|
|
|
| name="beszel-agent"
|
| description="Beszel Agent Service"
|
| command="$BIN_PATH"
|
| command_user="beszel"
|
| command_background="yes"
|
| pidfile="/run/\${RC_SVCNAME}.pid"
|
| output_log="/var/log/beszel-agent.log"
|
| error_log="/var/log/beszel-agent.err"
|
|
|
| start_pre() {
|
| checkpath -f -m 0644 -o beszel:beszel "\$output_log" "\$error_log"
|
| }
|
|
|
| export PORT="$PORT"
|
| export KEY="$KEY"
|
| export TOKEN="$TOKEN"
|
| export HUB_URL="$HUB_URL"
|
|
|
| depend() {
|
| need net
|
| after firewall
|
| }
|
| EOF
|
| chmod +x /etc/init.d/beszel-agent
|
| rc-update add beszel-agent default
|
| else
|
| echo "Alpine OpenRC service file already exists. Skipping creation."
|
| fi
|
|
|
|
|
| touch /var/log/beszel-agent.log /var/log/beszel-agent.err
|
| chown beszel:beszel /var/log/beszel-agent.log /var/log/beszel-agent.err
|
|
|
|
|
| rc-service beszel-agent restart
|
|
|
|
|
| sleep 2
|
| if ! rc-service beszel-agent status | grep -q "started"; then
|
| echo "Error: The Beszel Agent service failed to start. Checking logs..."
|
| tail -n 20 /var/log/beszel-agent.err
|
| exit 1
|
| fi
|
|
|
|
|
| if [ "$AUTO_UPDATE_FLAG" = "true" ]; then
|
| AUTO_UPDATE="y"
|
| elif [ "$AUTO_UPDATE_FLAG" = "false" ]; then
|
| AUTO_UPDATE="n"
|
| else
|
| printf "\nEnable automatic daily updates for beszel-agent? (y/n): "
|
| read AUTO_UPDATE
|
| fi
|
| case "$AUTO_UPDATE" in
|
| [Yy]*)
|
| echo "Setting up daily automatic updates for beszel-agent..."
|
|
|
|
|
| if ! crontab -u root -l 2>/dev/null | grep -q "beszel-agent.*update"; then
|
| (crontab -u root -l 2>/dev/null; echo "12 0 * * * $BIN_PATH update >/dev/null 2>&1") | crontab -u root -
|
| fi
|
|
|
| printf "\nDaily updates have been enabled via cron job.\n"
|
| ;;
|
| esac
|
|
|
|
|
| if ! rc-service beszel-agent status >/dev/null 2>&1; then
|
| echo "Error: The Beszel Agent service is not running."
|
| rc-service beszel-agent status
|
| exit 1
|
| fi
|
|
|
| elif is_openwrt; then
|
| if [ ! -f /etc/init.d/beszel-agent ]; then
|
| echo "Creating procd init script service for OpenWRT..."
|
| cat >/etc/init.d/beszel-agent <<EOF
|
| #!/bin/sh /etc/rc.common
|
|
|
| USE_PROCD=1
|
| START=99
|
|
|
| start_service() {
|
| procd_open_instance
|
| procd_set_param command $BIN_PATH
|
| procd_set_param user beszel
|
| procd_set_param pidfile /var/run/beszel-agent.pid
|
| procd_set_param env PORT="$PORT" KEY="$KEY" TOKEN="$TOKEN" HUB_URL="$HUB_URL"
|
| procd_set_param respawn
|
| procd_set_param stdout 1
|
| procd_set_param stderr 1
|
| procd_close_instance
|
| }
|
|
|
| # Extra command to trigger agent update
|
| EXTRA_COMMANDS="update restart"
|
| EXTRA_HELP=" update Update the Beszel agent
|
| restart Restart the Beszel agent"
|
|
|
| update() {
|
| $BIN_PATH update
|
| }
|
|
|
| EOF
|
|
|
| chmod +x /etc/init.d/beszel-agent
|
| /etc/init.d/beszel-agent enable
|
| else
|
| echo "OpenWRT init script already exists. Skipping creation."
|
| fi
|
|
|
|
|
| /etc/init.d/beszel-agent restart
|
|
|
|
|
| if [ "$AUTO_UPDATE_FLAG" = "true" ]; then
|
| AUTO_UPDATE="y"
|
| sleep 1
|
| elif [ "$AUTO_UPDATE_FLAG" = "false" ]; then
|
| AUTO_UPDATE="n"
|
| sleep 1
|
| else
|
| printf "\nEnable automatic daily updates for beszel-agent? (y/n): "
|
| read AUTO_UPDATE
|
| fi
|
| case "$AUTO_UPDATE" in
|
| [Yy]*)
|
| echo "Setting up daily automatic updates for beszel-agent..."
|
|
|
| if ! crontab -u root -l 2>/dev/null | grep -q "beszel-agent.*update"; then
|
| (crontab -u root -l 2>/dev/null; echo "12 0 * * * /etc/init.d/beszel-agent update") | crontab -u root -
|
| fi
|
|
|
| /etc/init.d/cron restart
|
|
|
| printf "\nDaily updates have been enabled.\n"
|
| ;;
|
| esac
|
|
|
|
|
| if ! /etc/init.d/beszel-agent running >/dev/null 2>&1; then
|
| echo "Error: The Beszel Agent service is not running."
|
| /etc/init.d/beszel-agent status
|
| exit 1
|
| fi
|
|
|
| elif is_freebsd; then
|
| echo "Checking for existing FreeBSD service configuration..."
|
|
|
| mkdir -p /usr/local/etc/rc.d
|
|
|
|
|
| if [ ! -f "$AGENT_DIR/env" ]; then
|
| echo "Creating environment configuration file..."
|
| cat >"$AGENT_DIR/env" <<EOF
|
| LISTEN=$PORT
|
| KEY="$KEY"
|
| TOKEN=$TOKEN
|
| HUB_URL=$HUB_URL
|
| EOF
|
| chmod 640 "$AGENT_DIR/env"
|
| chown "root:${AGENT_USER}" "$AGENT_DIR/env"
|
| else
|
| echo "FreeBSD environment file already exists. Skipping creation."
|
| fi
|
|
|
|
|
| if [ ! -f /usr/local/etc/rc.d/beszel-agent ]; then
|
| echo "Creating FreeBSD rc service..."
|
| generate_freebsd_rc_service > /usr/local/etc/rc.d/beszel-agent
|
|
|
| chmod 755 /usr/local/etc/rc.d/beszel-agent
|
| else
|
| echo "FreeBSD rc service file already exists. Skipping creation."
|
| fi
|
|
|
|
|
| echo "Enabling and starting the agent service..."
|
| sysrc beszel_agent_enable="YES"
|
| sysrc beszel_agent_user="${AGENT_USER}"
|
| service beszel-agent restart
|
|
|
|
|
| sleep 2
|
| if ! service beszel-agent status | grep -q "is running"; then
|
| echo "Error: The Beszel Agent service failed to start. Checking logs..."
|
| tail -n 20 /var/log/beszel_agent.log
|
| exit 1
|
| fi
|
|
|
|
|
| if [ "$AUTO_UPDATE_FLAG" = "true" ]; then
|
| AUTO_UPDATE="y"
|
| elif [ "$AUTO_UPDATE_FLAG" = "false" ]; then
|
| AUTO_UPDATE="n"
|
| else
|
| printf "\nEnable automatic daily updates for beszel-agent? (y/n): "
|
| read AUTO_UPDATE
|
| fi
|
| case "$AUTO_UPDATE" in
|
| [Yy]*)
|
| echo "Setting up daily automatic updates for beszel-agent..."
|
|
|
|
|
| cat >/etc/cron.d/beszel-agent <<EOF
|
| # Beszel Agent daily update job
|
| 12 0 * * * root $BIN_PATH update >/dev/null 2>&1
|
| EOF
|
| chmod 644 /etc/cron.d/beszel-agent
|
| printf "\nDaily updates have been enabled via /etc/cron.d.\n"
|
| ;;
|
| esac
|
|
|
|
|
| if ! service beszel-agent status >/dev/null 2>&1; then
|
| echo "Error: The Beszel Agent service is not running."
|
| service beszel-agent status
|
| exit 1
|
| fi
|
|
|
| else
|
|
|
| if [ ! -f /etc/systemd/system/beszel-agent.service ]; then
|
| echo "Creating the systemd service for the agent..."
|
|
|
|
|
| NVIDIA_DEVICES=$(detect_nvidia_devices)
|
|
|
| cat >/etc/systemd/system/beszel-agent.service <<EOF
|
| [Unit]
|
| Description=Beszel Agent Service
|
| Wants=network-online.target
|
| After=network-online.target
|
|
|
| [Service]
|
| Environment="PORT=$PORT"
|
| Environment="KEY=$KEY"
|
| Environment="TOKEN=$TOKEN"
|
| Environment="HUB_URL=$HUB_URL"
|
| # Environment="EXTRA_FILESYSTEMS=sdb"
|
| ExecStart=$BIN_PATH
|
| User=beszel
|
| Restart=on-failure
|
| RestartSec=5
|
| 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
|
|
|
| $(if [ -n "$NVIDIA_DEVICES" ]; then printf "%b" "# NVIDIA device permissions\n${NVIDIA_DEVICES}"; fi)
|
|
|
| [Install]
|
| WantedBy=multi-user.target
|
| EOF
|
| else
|
| echo "Systemd service file already exists. Skipping creation."
|
| fi
|
|
|
|
|
| printf "\nLoading and starting the agent service...\n"
|
| systemctl daemon-reload
|
| systemctl enable beszel-agent.service >/dev/null 2>&1
|
| systemctl restart beszel-agent.service
|
|
|
|
|
|
|
|
|
| if [ "$AUTO_UPDATE_FLAG" = "true" ]; then
|
| AUTO_UPDATE="y"
|
| sleep 1
|
| elif [ "$AUTO_UPDATE_FLAG" = "false" ]; then
|
| AUTO_UPDATE="n"
|
| sleep 1
|
| else
|
| printf "\nEnable automatic daily updates for beszel-agent? (y/n): "
|
| read AUTO_UPDATE
|
| fi
|
| case "$AUTO_UPDATE" in
|
| [Yy]*)
|
| echo "Setting up daily automatic updates for beszel-agent..."
|
|
|
|
|
| cat >/etc/systemd/system/beszel-agent-update.service <<EOF
|
| [Unit]
|
| Description=Update beszel-agent if needed
|
| Wants=beszel-agent.service
|
|
|
| [Service]
|
| Type=oneshot
|
| ExecStart=$BIN_PATH update
|
| EOF
|
|
|
|
|
| cat >/etc/systemd/system/beszel-agent-update.timer <<EOF
|
| [Unit]
|
| Description=Run beszel-agent update daily
|
|
|
| [Timer]
|
| OnCalendar=daily
|
| Persistent=true
|
| RandomizedDelaySec=4h
|
|
|
| [Install]
|
| WantedBy=timers.target
|
| EOF
|
|
|
| systemctl daemon-reload
|
| systemctl enable --now beszel-agent-update.timer >/dev/null 2>&1
|
|
|
| printf "\nDaily updates have been enabled.\n"
|
| ;;
|
| esac
|
|
|
|
|
| if [ "$(systemctl is-active beszel-agent.service)" != "active" ]; then
|
| echo "Error: The Beszel Agent service is not running."
|
| echo "$(systemctl status beszel-agent.service)"
|
| exit 1
|
| fi
|
| fi
|
|
|
| printf "\n\033[32mBeszel Agent has been installed successfully! It is now running on $PORT.\033[0m\n"
|
|
|