beszel-install-agent.sh 12 KB

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