3
0

beszel-install-agent.sh 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440
  1. #!/bin/sh
  2. # Move is_alpine function to the top of the file
  3. is_alpine() {
  4. [ -f /etc/alpine-release ]
  5. }
  6. add_autoupdate_service() {
  7. echo "Setting up daily automatic updates for beszel-agent..."
  8. # Create systemd service for the daily update
  9. cat >/etc/systemd/system/beszel-agent-update.service <<EOF
  10. [Unit]
  11. Description=Update beszel-agent if needed
  12. Wants=beszel-agent.service
  13. [Service]
  14. Type=oneshot
  15. ExecStart=/bin/sh -c '/opt/beszel-agent/beszel-agent update | grep -q "Successfully updated" && systemctl restart beszel-agent'
  16. EOF
  17. # Create systemd timer for the daily update
  18. cat >/etc/systemd/system/beszel-agent-update.timer <<EOF
  19. [Unit]
  20. Description=Run beszel-agent update daily
  21. [Timer]
  22. OnCalendar=daily
  23. Persistent=true
  24. RandomizedDelaySec=4h
  25. [Install]
  26. WantedBy=timers.target
  27. EOF
  28. systemctl daemon-reload
  29. systemctl enable --now beszel-agent-update.timer
  30. printf "\nAutomatic daily updates have been enabled.\n"
  31. }
  32. version=0.0.1
  33. # Define default values
  34. PORT=45876
  35. UNINSTALL=false
  36. CHINA_MAINLAND=false
  37. GITHUB_URL="https://github.com"
  38. GITHUB_API_URL="https://api.github.com"
  39. KEY=""
  40. # Check for help flag first
  41. case "$1" in
  42. -h | --help)
  43. printf "Beszel Agent installation script\n\n"
  44. printf "Usage: ./install-agent.sh [options]\n\n"
  45. printf "Options: \n"
  46. printf " -k : SSH key (required, or interactive if not provided)\n"
  47. printf " -p : Port (default: $PORT)\n"
  48. printf " -u : Uninstall Beszel Agent\n"
  49. printf " -a : set daily auto-update agent binary\n"
  50. printf " --china-mirrors : Using GitHub mirror sources to resolve network timeout issues in mainland China\n"
  51. printf " -h, --help : Display this help message\n"
  52. exit 0
  53. ;;
  54. esac
  55. # Build sudo args by properly quoting everything
  56. build_sudo_args() {
  57. QUOTED_ARGS=""
  58. while [ $# -gt 0 ]; do
  59. if [ -n "$QUOTED_ARGS" ]; then
  60. QUOTED_ARGS="$QUOTED_ARGS "
  61. fi
  62. QUOTED_ARGS="$QUOTED_ARGS'$(echo "$1" | sed "s/'/'\\\\''/g")'"
  63. shift
  64. done
  65. echo "$QUOTED_ARGS"
  66. }
  67. # Check if running as root and re-execute with sudo if needed
  68. if [ "$(id -u)" != "0" ]; then
  69. if command -v sudo >/dev/null 2>&1; then
  70. SUDO_ARGS=$(build_sudo_args "$@")
  71. eval "exec sudo $0 $SUDO_ARGS"
  72. else
  73. echo "This script must be run as root. Please either:"
  74. echo "1. Run this script as root (su root)"
  75. echo "2. Install sudo and run with sudo"
  76. exit 1
  77. fi
  78. fi
  79. # Parse arguments
  80. while [ $# -gt 0 ]; do
  81. case "$1" in
  82. -k)
  83. shift
  84. KEY="$1"
  85. ;;
  86. -p)
  87. shift
  88. PORT="$1"
  89. ;;
  90. -u)
  91. UNINSTALL=true
  92. ;;
  93. --china-mirrors)
  94. CHINA_MAINLAND=true
  95. ;;
  96. -a)
  97. AUTO_UPDATE=true
  98. *)
  99. echo "Invalid option: $1" >&2
  100. exit 1
  101. ;;
  102. esac
  103. shift
  104. done
  105. # Uninstall process
  106. if [ "$UNINSTALL" = true ]; then
  107. if is_alpine; then
  108. echo "Stopping and disabling the agent service..."
  109. rc-service beszel-agent stop
  110. rc-update del beszel-agent default
  111. echo "Removing the OpenRC service files..."
  112. rm -f /etc/init.d/beszel-agent
  113. # Remove the update service if it exists
  114. echo "Removing the daily update service..."
  115. rc-service beszel-agent-update stop 2>/dev/null
  116. rc-update del beszel-agent-update default 2>/dev/null
  117. rm -f /etc/init.d/beszel-agent-update
  118. # Remove log files
  119. echo "Removing log files..."
  120. rm -f /var/log/beszel-agent.log /var/log/beszel-agent.err
  121. else
  122. echo "Stopping and disabling the agent service..."
  123. systemctl stop beszel-agent.service
  124. systemctl disable beszel-agent.service
  125. echo "Removing the systemd service file..."
  126. rm /etc/systemd/system/beszel-agent.service
  127. # Remove the update timer and service if they exist
  128. echo "Removing the daily update service and timer..."
  129. systemctl stop beszel-agent-update.timer 2>/dev/null
  130. systemctl disable beszel-agent-update.timer 2>/dev/null
  131. rm -f /etc/systemd/system/beszel-agent-update.service
  132. rm -f /etc/systemd/system/beszel-agent-update.timer
  133. systemctl daemon-reload
  134. fi
  135. echo "Removing the Beszel Agent directory..."
  136. rm -rf /opt/beszel-agent
  137. echo "Removing the dedicated user for the agent service..."
  138. killall beszel-agent 2>/dev/null
  139. if is_alpine; then
  140. deluser beszel 2>/dev/null
  141. else
  142. userdel beszel 2>/dev/null
  143. fi
  144. echo "Beszel Agent has been uninstalled successfully!"
  145. exit 0
  146. fi
  147. if [ "$CHINA_MAINLAND" = true ]; then
  148. printf "\nConfirmed to use GitHub mirrors (ghp.ci) for download beszel-agent?\nThis helps to install Agent properly in mainland China. (Y/n): "
  149. read USE_MIRROR
  150. USE_MIRROR=${USE_MIRROR:-Y}
  151. if [ "$USE_MIRROR" = "Y" ] || [ "$USE_MIRROR" = "y" ]; then
  152. GITHUB_URL="https://ghp.ci/https://github.com"
  153. # In China, only github.com is blocked, while api.github.com is not (for now).
  154. # GITHUB_API_URL="https://api.github.com"
  155. echo "Using GitHub Mirror for downloads..."
  156. else
  157. echo "GitHub mirrors will not be used for installation."
  158. fi
  159. fi
  160. # Function to check if a package is installed
  161. package_installed() {
  162. command -v "$1" >/dev/null 2>&1
  163. }
  164. # Check for package manager and install necessary packages if not installed
  165. if is_alpine; then
  166. if ! package_installed tar || ! package_installed curl || ! package_installed coreutils; then
  167. apk update
  168. apk add tar curl coreutils shadow
  169. fi
  170. elif package_installed apt-get; then
  171. if ! package_installed tar || ! package_installed curl || ! package_installed sha256sum; then
  172. apt-get update
  173. apt-get install -y tar curl coreutils
  174. fi
  175. elif package_installed yum; then
  176. if ! package_installed tar || ! package_installed curl || ! package_installed sha256sum; then
  177. yum install -y tar curl coreutils
  178. fi
  179. elif package_installed pacman; then
  180. if ! package_installed tar || ! package_installed curl || ! package_installed sha256sum; then
  181. pacman -Sy --noconfirm tar curl coreutils
  182. fi
  183. else
  184. echo "Warning: Please ensure 'tar' and 'curl' and 'sha256sum (coreutils)' are installed."
  185. fi
  186. # If no SSH key is provided, ask for the SSH key interactively
  187. if [ -z "$KEY" ]; then
  188. printf "Enter your SSH key: "
  189. read KEY
  190. fi
  191. # Verify checksum
  192. if command -v sha256sum >/dev/null; then
  193. CHECK_CMD="sha256sum"
  194. elif command -v md5 >/dev/null; then
  195. CHECK_CMD="md5 -q"
  196. else
  197. echo "No MD5 checksum utility found"
  198. exit 1
  199. fi
  200. # Create a dedicated user for the service if it doesn't exist
  201. if is_alpine; then
  202. if ! id -u beszel >/dev/null 2>&1; then
  203. echo "Creating a dedicated user for the Beszel Agent service..."
  204. adduser -D -H -s /sbin/nologin beszel
  205. fi
  206. # Add the user to the docker group to allow access to the Docker socket
  207. addgroup beszel docker
  208. else
  209. if ! id -u beszel >/dev/null 2>&1; then
  210. echo "Creating a dedicated user for the Beszel Agent service..."
  211. useradd -M -s /bin/false beszel
  212. fi
  213. # Add the user to the docker group to allow access to the Docker socket
  214. usermod -aG docker beszel
  215. fi
  216. # Create the directory for the Beszel Agent
  217. if [ ! -d "/opt/beszel-agent" ]; then
  218. echo "Creating the directory for the Beszel Agent..."
  219. mkdir -p /opt/beszel-agent
  220. chown beszel:beszel /opt/beszel-agent
  221. chmod 755 /opt/beszel-agent
  222. fi
  223. # Download and install the Beszel Agent
  224. echo "Downloading and installing the agent..."
  225. OS=$(uname -s | tr '[:upper:]' '[:lower:]')
  226. ARCH=$(uname -m | sed -e 's/x86_64/amd64/' -e 's/armv6l/arm/' -e 's/armv7l/arm/' -e 's/aarch64/arm64/')
  227. FILE_NAME="beszel-agent_${OS}_${ARCH}.tar.gz"
  228. LATEST_VERSION=$(curl -s "$GITHUB_API_URL""/repos/henrygd/beszel/releases/latest" | grep -o '"tag_name": "v[^"]*"' | cut -d'"' -f4 | tr -d 'v')
  229. if [ -z "$LATEST_VERSION" ]; then
  230. echo "Failed to get latest version"
  231. exit 1
  232. fi
  233. echo "Downloading and installing agent version ${LATEST_VERSION} from ${GITHUB_URL} ..."
  234. # Download checksums file
  235. TEMP_DIR=$(mktemp -d)
  236. cd "$TEMP_DIR" || exit 1
  237. CHECKSUM=$(curl -sL "$GITHUB_URL/henrygd/beszel/releases/download/v${LATEST_VERSION}/beszel_${LATEST_VERSION}_checksums.txt" | grep "$FILE_NAME" | cut -d' ' -f1)
  238. if [ -z "$CHECKSUM" ] || ! echo "$CHECKSUM" | grep -qE "^[a-fA-F0-9]{64}$"; then
  239. echo "Failed to get checksum or invalid checksum format"
  240. exit 1
  241. fi
  242. if ! curl -#L "$GITHUB_URL/henrygd/beszel/releases/download/v${LATEST_VERSION}/$FILE_NAME" -o "$FILE_NAME"; then
  243. echo "Failed to download the agent from ""$GITHUB_URL/henrygd/beszel/releases/download/v${LATEST_VERSION}/$FILE_NAME"
  244. rm -rf "$TEMP_DIR"
  245. exit 1
  246. fi
  247. if [ "$($CHECK_CMD "$FILE_NAME" | cut -d' ' -f1)" != "$CHECKSUM" ]; then
  248. echo "Checksum verification failed: $($CHECK_CMD "$FILE_NAME" | cut -d' ' -f1) & $CHECKSUM"
  249. rm -rf "$TEMP_DIR"
  250. exit 1
  251. fi
  252. if ! tar -xzf "$FILE_NAME" beszel-agent; then
  253. echo "Failed to extract the agent"
  254. rm -rf "$TEMP_DIR"
  255. exit 1
  256. fi
  257. mv beszel-agent /opt/beszel-agent/beszel-agent
  258. chown beszel:beszel /opt/beszel-agent/beszel-agent
  259. chmod 755 /opt/beszel-agent/beszel-agent
  260. # Cleanup
  261. rm -rf "$TEMP_DIR"
  262. # Modify service installation part, add Alpine check before systemd service creation
  263. if is_alpine; then
  264. echo "Creating OpenRC service for Alpine Linux..."
  265. cat > /etc/init.d/beszel-agent <<EOF
  266. #!/sbin/openrc-run
  267. name="beszel-agent"
  268. description="Beszel Agent Service"
  269. command="/opt/beszel-agent/beszel-agent"
  270. command_user="beszel"
  271. command_background="yes"
  272. pidfile="/run/\${RC_SVCNAME}.pid"
  273. output_log="/var/log/beszel-agent.log"
  274. error_log="/var/log/beszel-agent.err"
  275. start_pre() {
  276. checkpath -f -m 0644 -o beszel:beszel "\$output_log" "\$error_log"
  277. }
  278. export PORT="$PORT"
  279. export KEY="$KEY"
  280. depend() {
  281. need net
  282. after firewall
  283. }
  284. EOF
  285. chmod +x /etc/init.d/beszel-agent
  286. rc-update add beszel-agent default
  287. # Create log files with proper permissions
  288. touch /var/log/beszel-agent.log /var/log/beszel-agent.err
  289. chown beszel:beszel /var/log/beszel-agent.log /var/log/beszel-agent.err
  290. # Start the service
  291. rc-service beszel-agent restart
  292. # Check if service started successfully
  293. sleep 2
  294. if ! rc-service beszel-agent status | grep -q "started"; then
  295. echo "Error: The Beszel Agent service failed to start. Checking logs..."
  296. tail -n 20 /var/log/beszel-agent.err
  297. exit 1
  298. fi
  299. # Auto-update service for Alpine
  300. printf "\nWould you like to enable automatic daily updates for beszel-agent? (y/n): "
  301. read AUTO_UPDATE
  302. case "$AUTO_UPDATE" in
  303. [Yy]*)
  304. echo "Setting up daily automatic updates for beszel-agent..."
  305. cat > /etc/init.d/beszel-agent-update <<EOF
  306. #!/sbin/openrc-run
  307. name="beszel-agent-update"
  308. description="Update beszel-agent if needed"
  309. depend() {
  310. need beszel-agent
  311. }
  312. start() {
  313. ebegin "Checking for beszel-agent updates"
  314. if /opt/beszel-agent/beszel-agent update | grep -q "Successfully updated"; then
  315. rc-service beszel-agent restart
  316. fi
  317. eend $?
  318. }
  319. EOF
  320. chmod +x /etc/init.d/beszel-agent-update
  321. rc-update add beszel-agent-update default
  322. rc-service beszel-agent-update start
  323. printf "\nAutomatic daily updates have been enabled.\n"
  324. ;;
  325. esac
  326. # Check service status
  327. if ! rc-service beszel-agent status >/dev/null 2>&1; then
  328. echo "Error: The Beszel Agent service is not running."
  329. rc-service beszel-agent status
  330. exit 1
  331. fi
  332. else
  333. # Original systemd service installation code
  334. echo "Creating the systemd service for the agent..."
  335. cat >/etc/systemd/system/beszel-agent.service <<EOF
  336. [Unit]
  337. Description=Beszel Agent Service
  338. After=network.target
  339. [Service]
  340. Environment="PORT=$PORT"
  341. Environment="KEY=$KEY"
  342. # Environment="EXTRA_FILESYSTEMS=sdb"
  343. ExecStart=/opt/beszel-agent/beszel-agent
  344. User=beszel
  345. Restart=always
  346. RestartSec=5
  347. [Install]
  348. WantedBy=multi-user.target
  349. EOF
  350. # Load and start the service
  351. printf "\nLoading and starting the agent service...\n"
  352. systemctl daemon-reload
  353. systemctl enable beszel-agent.service
  354. systemctl start beszel-agent.service
  355. # enable auto-update if AUTO_UPDATE variable set up
  356. if [ "${AUTO_UPDATE}" = true ]; then
  357. add_autoupdate_service
  358. else
  359. # Prompt for auto-update setup
  360. printf "\nWould you like to enable automatic daily updates for beszel-agent? (y/n): "
  361. read AUTO_UPDATE
  362. case "$AUTO_UPDATE" in
  363. [Yy]*)
  364. add_autoupdate_service ;;
  365. esac
  366. fi
  367. # Wait for the service to start or fail
  368. if [ "$(systemctl is-active beszel-agent.service)" != "active" ]; then
  369. echo "Error: The Beszel Agent service is not running."
  370. echo "$(systemctl status beszel-agent.service)"
  371. exit 1
  372. fi
  373. fi
  374. printf "\n\033[32mBeszel Agent has been installed successfully! It is now running on port $PORT.\033[0m\n"