mirror of
https://github.com/fankes/beszel.git
synced 2025-10-19 01:39:34 +08:00
add install scripts for beta versions
This commit is contained in:
605
supplemental/scripts/install-agent-beta.ps1
Normal file
605
supplemental/scripts/install-agent-beta.ps1
Normal file
@@ -0,0 +1,605 @@
|
||||
param (
|
||||
[switch]$Elevated,
|
||||
[Parameter(Mandatory=$true)]
|
||||
[string]$Key,
|
||||
[Parameter(Mandatory=$true)]
|
||||
[string]$Token,
|
||||
[Parameter(Mandatory=$true)]
|
||||
[string]$Url,
|
||||
[int]$Port = 45876,
|
||||
[string]$AgentPath = "",
|
||||
[string]$NSSMPath = ""
|
||||
)
|
||||
|
||||
# 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]" -ForegroundColor Yellow
|
||||
exit 1
|
||||
}
|
||||
|
||||
if ([string]::IsNullOrWhiteSpace($Token)) {
|
||||
Write-Host "ERROR: Token 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]" -ForegroundColor Yellow
|
||||
exit 1
|
||||
}
|
||||
|
||||
if ([string]::IsNullOrWhiteSpace($Url)) {
|
||||
Write-Host "ERROR: Hub URL 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]" -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
|
||||
|
||||
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,
|
||||
[Parameter(Mandatory=$true)]
|
||||
[string]$Token,
|
||||
[Parameter(Mandatory=$true)]
|
||||
[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. 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 (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`""
|
||||
)
|
||||
|
||||
# Add NSSMPath if we found it
|
||||
if ($NSSMPath) {
|
||||
$argumentList += "-NSSMPath"
|
||||
$argumentList += "`"$NSSMPath`""
|
||||
}
|
||||
|
||||
# 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
|
||||
|
||||
# Configure firewall
|
||||
Configure-Firewall -Port $Port
|
||||
|
||||
# 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
|
757
supplemental/scripts/install-agent-beta.sh
Executable file
757
supplemental/scripts/install-agent-beta.sh
Executable file
@@ -0,0 +1,757 @@
|
||||
#!/bin/sh
|
||||
|
||||
is_alpine() {
|
||||
[ -f /etc/alpine-release ]
|
||||
}
|
||||
|
||||
is_openwrt() {
|
||||
cat /etc/os-release | grep -q "OpenWrt"
|
||||
}
|
||||
|
||||
# If SELinux is enabled, set the context of the binary
|
||||
set_selinux_context() {
|
||||
# Check if SELinux is enabled and in enforcing or permissive mode
|
||||
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..."
|
||||
|
||||
# First try to set persistent context if semanage is available
|
||||
if command -v semanage >/dev/null 2>&1; then
|
||||
echo "Attempting to set persistent SELinux context..."
|
||||
if semanage fcontext -a -t bin_t "/opt/beszel-agent/beszel-agent" >/dev/null 2>&1; then
|
||||
restorecon -v /opt/beszel-agent/beszel-agent >/dev/null 2>&1
|
||||
else
|
||||
echo "Warning: Failed to set persistent context, falling back to temporary context."
|
||||
fi
|
||||
fi
|
||||
|
||||
# Fall back to chcon if semanage failed or isn't available
|
||||
if command -v chcon >/dev/null 2>&1; then
|
||||
# Set context for both the directory and binary
|
||||
chcon -t bin_t /opt/beszel-agent/beszel-agent || echo "Warning: Failed to set SELinux context for binary."
|
||||
chcon -R -t bin_t /opt/beszel-agent || 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
|
||||
}
|
||||
|
||||
# Clean up SELinux contexts if they were set
|
||||
cleanup_selinux_context() {
|
||||
if command -v getenforce >/dev/null 2>&1 && [ "$(getenforce)" != "Disabled" ]; then
|
||||
echo "Cleaning up SELinux contexts..."
|
||||
# Remove persistent context if semanage is available
|
||||
if command -v semanage >/dev/null 2>&1; then
|
||||
semanage fcontext -d "/opt/beszel-agent/beszel-agent" 2>/dev/null || true
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# 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
|
||||
}
|
||||
|
||||
# Default values
|
||||
PORT=45876
|
||||
UNINSTALL=false
|
||||
GITHUB_URL="https://github.com"
|
||||
GITHUB_API_URL="https://api.github.com" # not blocked in China currently
|
||||
GITHUB_PROXY_URL=""
|
||||
KEY=""
|
||||
TOKEN=""
|
||||
HUB_URL=""
|
||||
AUTO_UPDATE_FLAG="" # empty string means prompt, "true" means auto-enable, "false" means skip
|
||||
VERSION="latest"
|
||||
|
||||
# Check for help flag
|
||||
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 (required, or interactive if not provided)\n"
|
||||
printf " -url : Hub URL (required, or interactive if not provided)\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 " --china-mirrors [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 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
|
||||
|
||||
# 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"
|
||||
;;
|
||||
-v|--version)
|
||||
shift
|
||||
VERSION="$1"
|
||||
;;
|
||||
-u)
|
||||
UNINSTALL=true
|
||||
;;
|
||||
--china-mirrors*)
|
||||
# Check if there's a value after the = sign
|
||||
if echo "$1" | grep -q "="; then
|
||||
# Extract the value after =
|
||||
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
|
||||
# use custom proxy URL provided as next argument
|
||||
GITHUB_PROXY_URL="$2"
|
||||
GITHUB_URL="$(ensure_trailing_slash "$2")https://github.com"
|
||||
shift
|
||||
else
|
||||
# No value specified, use default
|
||||
GITHUB_PROXY_URL="https://gh.beszel.dev"
|
||||
GITHUB_URL="$GITHUB_PROXY_URL"
|
||||
fi
|
||||
;;
|
||||
--auto-update*)
|
||||
# Check if there's a value after the = sign
|
||||
if echo "$1" | grep -q "="; then
|
||||
# Extract the value after =
|
||||
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
|
||||
# Value provided as next argument
|
||||
AUTO_UPDATE_FLAG="$2"
|
||||
shift
|
||||
else
|
||||
# No value specified, use true
|
||||
AUTO_UPDATE_FLAG="true"
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
echo "Invalid option: $1" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
# Uninstall process
|
||||
if [ "$UNINSTALL" = true ]; then
|
||||
# Clean up SELinux contexts before removing files
|
||||
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
|
||||
|
||||
# Remove the update service if it exists
|
||||
echo "Removing the daily update service..."
|
||||
rc-service beszel-agent-update stop 2>/dev/null
|
||||
rc-update del beszel-agent-update default 2>/dev/null
|
||||
rm -f /etc/init.d/beszel-agent-update
|
||||
|
||||
# Remove log files
|
||||
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..."
|
||||
service beszel-agent stop
|
||||
service beszel-agent disable
|
||||
|
||||
echo "Removing the OpenWRT service files..."
|
||||
rm -f /etc/init.d/beszel-agent
|
||||
|
||||
# Remove the update service if it exists
|
||||
echo "Removing the daily update service..."
|
||||
rm -f /etc/crontabs/beszel
|
||||
|
||||
else
|
||||
echo "Stopping and disabling the agent service..."
|
||||
systemctl stop beszel-agent.service
|
||||
systemctl disable beszel-agent.service
|
||||
|
||||
echo "Removing the systemd service file..."
|
||||
rm /etc/systemd/system/beszel-agent.service
|
||||
|
||||
# Remove the update timer and service if they exist
|
||||
echo "Removing the daily update service and timer..."
|
||||
systemctl stop beszel-agent-update.timer 2>/dev/null
|
||||
systemctl disable beszel-agent-update.timer 2>/dev/null
|
||||
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 /opt/beszel-agent
|
||||
|
||||
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
|
||||
else
|
||||
userdel beszel 2>/dev/null
|
||||
fi
|
||||
|
||||
echo "Beszel Agent has been uninstalled successfully!"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Confirm the use of GitHub mirrors for downloads
|
||||
if [ -n "$GITHUB_PROXY_URL" ]; then
|
||||
printf "\nConfirm use of GitHub mirror (%s) for downloading beszel-agent?\nThis helps to install properly in mainland China. (Y/n): " "$GITHUB_PROXY_URL"
|
||||
read USE_MIRROR
|
||||
USE_MIRROR=${USE_MIRROR:-Y}
|
||||
if [ "$USE_MIRROR" = "Y" ] || [ "$USE_MIRROR" = "y" ]; then
|
||||
echo "Using GitHub Mirror ($GITHUB_PROXY_URL) for downloads..."
|
||||
else
|
||||
GITHUB_URL="https://github.com"
|
||||
fi
|
||||
fi
|
||||
|
||||
# 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 is_alpine; then
|
||||
if ! package_installed tar || ! package_installed curl || ! package_installed coreutils; then
|
||||
apk update
|
||||
apk add tar curl coreutils shadow
|
||||
fi
|
||||
elif is_openwrt; then
|
||||
if ! package_installed tar || ! package_installed curl || ! package_installed coreutils; then
|
||||
opkg update
|
||||
opkg install tar 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 no SSH key is provided, ask for the SSH key interactively
|
||||
if [ -z "$KEY" ]; then
|
||||
printf "Enter your SSH key: "
|
||||
read KEY
|
||||
fi
|
||||
|
||||
# If no token is provided, ask for the token interactively
|
||||
if [ -z "$TOKEN" ]; then
|
||||
printf "Enter your token: "
|
||||
read TOKEN
|
||||
fi
|
||||
|
||||
# If no hub URL is provided, ask for the hub URL interactively
|
||||
if [ -z "$HUB_URL" ]; then
|
||||
printf "Enter your hub URL: "
|
||||
read HUB_URL
|
||||
fi
|
||||
|
||||
# Verify checksum
|
||||
if command -v sha256sum >/dev/null; then
|
||||
CHECK_CMD="sha256sum"
|
||||
elif command -v md5 >/dev/null; then
|
||||
CHECK_CMD="md5 -q"
|
||||
else
|
||||
echo "No MD5 checksum utility found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Create a dedicated user for the service if it doesn't exist
|
||||
if is_alpine; then
|
||||
if ! id -u beszel >/dev/null 2>&1; then
|
||||
echo "Creating a dedicated group for the Beszel Agent service..."
|
||||
addgroup beszel
|
||||
echo "Creating a dedicated user for the Beszel Agent service..."
|
||||
adduser -S -D -H -s /sbin/nologin -G beszel beszel
|
||||
fi
|
||||
# Add the user to the docker group to allow access to the Docker socket if group docker exists
|
||||
if getent group docker; then
|
||||
echo "Adding besel to docker group"
|
||||
usermod -aG docker beszel
|
||||
fi
|
||||
|
||||
else
|
||||
if ! id -u beszel >/dev/null 2>&1; then
|
||||
echo "Creating a dedicated user for the Beszel Agent service..."
|
||||
useradd --system --home-dir /nonexistent --shell /bin/false beszel
|
||||
fi
|
||||
# Add the user to the docker group to allow access to the Docker socket if group docker exists
|
||||
if getent group docker; then
|
||||
echo "Adding besel to docker group"
|
||||
usermod -aG docker beszel
|
||||
fi
|
||||
fi
|
||||
|
||||
# Create the directory for the Beszel Agent
|
||||
if [ ! -d "/opt/beszel-agent" ]; then
|
||||
echo "Creating the directory for the Beszel Agent..."
|
||||
mkdir -p /opt/beszel-agent
|
||||
chown beszel:beszel /opt/beszel-agent
|
||||
chmod 755 /opt/beszel-agent
|
||||
fi
|
||||
|
||||
# Download and install the Beszel Agent
|
||||
echo "Downloading and installing the agent..."
|
||||
|
||||
OS=$(uname -s | sed -e 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/')
|
||||
ARCH=$(uname -m | sed -e 's/x86_64/amd64/' -e 's/armv6l/arm/' -e 's/armv7l/arm/' -e 's/aarch64/arm64/' -e 's/mips/mipsle/')
|
||||
FILE_NAME="beszel-agent_${OS}_${ARCH}.tar.gz"
|
||||
|
||||
# Determine version to install
|
||||
if [ "$VERSION" = "latest" ]; then
|
||||
INSTALL_VERSION=$(curl -s "$GITHUB_API_URL""/repos/henrygd/beszel/releases/latest" | grep -o '"tag_name": "v[^"]*"' | cut -d'"' -f4 | tr -d 'v')
|
||||
if [ -z "$INSTALL_VERSION" ]; then
|
||||
echo "Failed to get latest version"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
INSTALL_VERSION="$VERSION"
|
||||
# Remove 'v' prefix if present
|
||||
INSTALL_VERSION=$(echo "$INSTALL_VERSION" | sed 's/^v//')
|
||||
fi
|
||||
|
||||
echo "Downloading and installing agent version ${INSTALL_VERSION} from ${GITHUB_URL} ..."
|
||||
|
||||
# Download checksums file
|
||||
TEMP_DIR=$(mktemp -d)
|
||||
cd "$TEMP_DIR" || exit 1
|
||||
CHECKSUM=$(curl -sL "$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"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! curl -#L "$GITHUB_URL/henrygd/beszel/releases/download/v${INSTALL_VERSION}/$FILE_NAME" -o "$FILE_NAME"; then
|
||||
echo "Failed to download the agent from ""$GITHUB_URL/henrygd/beszel/releases/download/v${INSTALL_VERSION}/$FILE_NAME"
|
||||
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
|
||||
|
||||
mv beszel-agent /opt/beszel-agent/beszel-agent
|
||||
chown beszel:beszel /opt/beszel-agent/beszel-agent
|
||||
chmod 755 /opt/beszel-agent/beszel-agent
|
||||
|
||||
# Set SELinux context if needed
|
||||
set_selinux_context
|
||||
|
||||
# Cleanup
|
||||
rm -rf "$TEMP_DIR"
|
||||
|
||||
# Check for NVIDIA GPUs and grant device permissions for systemd service
|
||||
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"
|
||||
}
|
||||
|
||||
# Modify service installation part, add Alpine check before systemd service creation
|
||||
if is_alpine; 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="/opt/beszel-agent/beszel-agent"
|
||||
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
|
||||
|
||||
# Create log files with proper permissions
|
||||
touch /var/log/beszel-agent.log /var/log/beszel-agent.err
|
||||
chown beszel:beszel /var/log/beszel-agent.log /var/log/beszel-agent.err
|
||||
|
||||
# Start the service
|
||||
rc-service beszel-agent restart
|
||||
|
||||
# Check if service started successfully
|
||||
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
|
||||
|
||||
# Auto-update service for Alpine
|
||||
if [ "$AUTO_UPDATE_FLAG" = "true" ]; then
|
||||
AUTO_UPDATE="y"
|
||||
elif [ "$AUTO_UPDATE_FLAG" = "false" ]; then
|
||||
AUTO_UPDATE="n"
|
||||
else
|
||||
printf "\nWould you like to enable 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/init.d/beszel-agent-update <<EOF
|
||||
#!/sbin/openrc-run
|
||||
|
||||
name="beszel-agent-update"
|
||||
description="Update beszel-agent if needed"
|
||||
|
||||
depend() {
|
||||
need beszel-agent
|
||||
}
|
||||
|
||||
start() {
|
||||
ebegin "Checking for beszel-agent updates"
|
||||
if /opt/beszel-agent/beszel-agent update | grep -q "Successfully updated"; then
|
||||
rc-service beszel-agent restart
|
||||
fi
|
||||
eend $?
|
||||
}
|
||||
EOF
|
||||
|
||||
chmod +x /etc/init.d/beszel-agent-update
|
||||
rc-update add beszel-agent-update default
|
||||
rc-service beszel-agent-update start
|
||||
|
||||
printf "\nAutomatic daily updates have been enabled.\n"
|
||||
;;
|
||||
esac
|
||||
|
||||
# Check service status
|
||||
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
|
||||
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 /opt/beszel-agent/beszel-agent
|
||||
procd_set_param user beszel
|
||||
procd_set_param pidfile /var/run/beszel-agent.pid
|
||||
procd_set_param env PORT="$PORT"
|
||||
procd_set_param env KEY="$KEY"
|
||||
procd_set_param env TOKEN="$TOKEN"
|
||||
procd_set_param env HUB_URL="$HUB_URL"
|
||||
procd_set_param stdout 1
|
||||
procd_set_param stderr 1
|
||||
procd_close_instance
|
||||
}
|
||||
|
||||
stop_service() {
|
||||
killall beszel-agent
|
||||
}
|
||||
|
||||
# Extra command to trigger agent update
|
||||
EXTRA_COMMANDS="update"
|
||||
EXTRA_HELP=" update Update the Beszel agent"
|
||||
|
||||
update() {
|
||||
if /opt/beszel-agent/beszel-agent update | grep -q "Successfully updated"; then
|
||||
start_service
|
||||
fi
|
||||
}
|
||||
|
||||
EOF
|
||||
|
||||
# Enable the service
|
||||
chmod +x /etc/init.d/beszel-agent
|
||||
service beszel-agent enable
|
||||
|
||||
# Start the service
|
||||
service beszel-agent restart
|
||||
|
||||
# Auto-update service for OpenWRT using a crontab job
|
||||
if [ "$AUTO_UPDATE_FLAG" = "true" ]; then
|
||||
AUTO_UPDATE="y"
|
||||
sleep 1 # give time for the service to start
|
||||
elif [ "$AUTO_UPDATE_FLAG" = "false" ]; then
|
||||
AUTO_UPDATE="n"
|
||||
sleep 1 # give time for the service to start
|
||||
else
|
||||
printf "\nWould you like to enable 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/crontabs/beszel <<EOF
|
||||
0 0 * * * /etc/init.d/beszel-agent update
|
||||
EOF
|
||||
|
||||
/etc/init.d/cron restart
|
||||
|
||||
printf "\nAutomatic daily updates have been enabled.\n"
|
||||
;;
|
||||
esac
|
||||
|
||||
# Check service status
|
||||
if ! service beszel-agent running >/dev/null 2>&1; then
|
||||
echo "Error: The Beszel Agent service is not running."
|
||||
service beszel-agent status
|
||||
exit 1
|
||||
fi
|
||||
|
||||
else
|
||||
# Original systemd service installation code
|
||||
echo "Creating the systemd service for the agent..."
|
||||
|
||||
# Detect NVIDIA devices and grant device permissions
|
||||
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=/opt/beszel-agent/beszel-agent
|
||||
User=beszel
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
StateDirectory=beszel-agent
|
||||
|
||||
# Security/sandboxing settings
|
||||
KeyringMode=private
|
||||
LockPersonality=yes
|
||||
NoNewPrivileges=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
|
||||
|
||||
# Load and start the service
|
||||
printf "\nLoading and starting the agent service...\n"
|
||||
systemctl daemon-reload
|
||||
systemctl enable beszel-agent.service
|
||||
systemctl start beszel-agent.service
|
||||
|
||||
# Create the update script
|
||||
echo "Creating the update script..."
|
||||
cat >/opt/beszel-agent/run-update.sh <<'EOF'
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
if /opt/beszel-agent/beszel-agent update | grep -q "Successfully updated"; then
|
||||
echo "Update found, checking SELinux context."
|
||||
if command -v getenforce >/dev/null 2>&1 && [ "$(getenforce)" != "Disabled" ]; then
|
||||
echo "SELinux enabled, applying context..."
|
||||
if command -v chcon >/dev/null 2>&1; then
|
||||
chcon -t bin_t /opt/beszel-agent/beszel-agent || echo "Warning: chcon command failed to apply context."
|
||||
fi
|
||||
if command -v restorecon >/dev/null 2>&1; then
|
||||
restorecon -v /opt/beszel-agent/beszel-agent >/dev/null 2>&1 || echo "Warning: restorecon command failed to apply context."
|
||||
fi
|
||||
fi
|
||||
echo "Restarting beszel-agent service..."
|
||||
systemctl restart beszel-agent
|
||||
echo "Update process finished."
|
||||
else
|
||||
echo "No updates found or applied."
|
||||
fi
|
||||
|
||||
exit 0
|
||||
EOF
|
||||
|
||||
chown root:root /opt/beszel-agent/run-update.sh
|
||||
chmod +x /opt/beszel-agent/run-update.sh
|
||||
|
||||
# Prompt for auto-update setup
|
||||
if [ "$AUTO_UPDATE_FLAG" = "true" ]; then
|
||||
AUTO_UPDATE="y"
|
||||
sleep 1 # give time for the service to start
|
||||
elif [ "$AUTO_UPDATE_FLAG" = "false" ]; then
|
||||
AUTO_UPDATE="n"
|
||||
sleep 1 # give time for the service to start
|
||||
else
|
||||
printf "\nWould you like to enable 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..."
|
||||
|
||||
# Create systemd service for the daily update
|
||||
cat >/etc/systemd/system/beszel-agent-update.service <<EOF
|
||||
[Unit]
|
||||
Description=Update beszel-agent if needed
|
||||
Wants=beszel-agent.service
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=/opt/beszel-agent/run-update.sh
|
||||
EOF
|
||||
|
||||
# Create systemd timer for the daily update
|
||||
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
|
||||
|
||||
printf "\nAutomatic daily updates have been enabled.\n"
|
||||
;;
|
||||
esac
|
||||
|
||||
# Wait for the service to start or fail
|
||||
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 $PORT.\033[0m\n"
|
104
supplemental/scripts/install-agent-brew-beta.sh
Executable file
104
supplemental/scripts/install-agent-brew-beta.sh
Executable file
@@ -0,0 +1,104 @@
|
||||
#!/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 (required, or interactive if not provided)\n"
|
||||
printf " -url Hub URL (required, or interactive if not provided)\n"
|
||||
printf " -h, --help Display this help message\n"
|
||||
exit 0
|
||||
}
|
||||
|
||||
# Handle --help explicitly since getopts doesn't handle long options
|
||||
if [ "$1" = "--help" ]; then
|
||||
usage
|
||||
fi
|
||||
|
||||
# Parse arguments (handling both short and long options)
|
||||
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
|
||||
|
||||
if [ -z "$TOKEN" ]; then
|
||||
read -p "Enter token: " TOKEN
|
||||
fi
|
||||
|
||||
if [ -z "$HUB_URL" ]; then
|
||||
read -p "Enter hub URL: " HUB_URL
|
||||
fi
|
||||
|
||||
mkdir -p ~/.config/beszel ~/.cache/beszel
|
||||
|
||||
echo "KEY=\"$KEY\"" >~/.config/beszel/beszel-agent.env
|
||||
echo "LISTEN=$PORT" >>~/.config/beszel/beszel-agent.env
|
||||
echo "TOKEN=\"$TOKEN\"" >>~/.config/beszel/beszel-agent.env
|
||||
echo "HUB_URL=\"$HUB_URL\"" >>~/.config/beszel/beszel-agent.env
|
||||
|
||||
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"
|
Reference in New Issue
Block a user