From ff4938533cb00740e5a84a97e031850e62118bf1 Mon Sep 17 00:00:00 2001 From: Tola Leng Date: Tue, 29 Jul 2025 20:54:20 +0700 Subject: [PATCH] Fix: Add tar.gz fallback for unsupported systems - The script has been updated to include a fallback mechanism for systems that do not have `dpkg` or `rpm` package managers. This ensures that the agent can be installed on a wider range of Linux distributions, such as Arch Linux, by automatically using the `tar.gz` package when native package managers are not detected. --- scripts/server-agent.sh | 367 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 330 insertions(+), 37 deletions(-) diff --git a/scripts/server-agent.sh b/scripts/server-agent.sh index e73db52..5f5d6f5 100644 --- a/scripts/server-agent.sh +++ b/scripts/server-agent.sh @@ -1,4 +1,3 @@ - #!/bin/bash # CheckCle Server Monitoring Agent - One-Click Installation Script @@ -44,7 +43,7 @@ check_root() { fi } -# Detect system architecture and package format +# Detect system architecture and package format with fallback detect_system() { log_info "Detecting system architecture and package format..." @@ -64,28 +63,89 @@ detect_system() { ;; esac - # Detect package format preference - if command -v dpkg >/dev/null 2>&1; then - PACKAGE_FORMAT="deb" - PACKAGE_MANAGER="dpkg" - elif command -v rpm >/dev/null 2>&1; then - PACKAGE_FORMAT="rpm" - if command -v yum >/dev/null 2>&1; then - PACKAGE_MANAGER="yum" - elif command -v dnf >/dev/null 2>&1; then - PACKAGE_MANAGER="dnf" - else - PACKAGE_MANAGER="rpm" - fi - else - log_error "No supported package manager found (dpkg or rpm required)" - log_info "This script supports Debian/Ubuntu (.deb) and RHEL/CentOS/Fedora (.rpm) systems" - exit 1 + # Detect OS and preferred package format + PREFERRED_FORMAT="" + PREFERRED_MANAGER="" + + if [[ -f /etc/os-release ]]; then + OS_ID=$(grep "^ID=" /etc/os-release | cut -d'=' -f2 | tr -d '"') + OS_LIKE=$(grep "^ID_LIKE=" /etc/os-release 2>/dev/null | cut -d'=' -f2 | tr -d '"' || echo "") + + log_info "Detected OS: $OS_ID" + [[ -n "$OS_LIKE" ]] && log_info "OS family: $OS_LIKE" + + # Determine preferred package format based on OS + case "$OS_ID" in + debian|ubuntu|linuxmint|elementary|pop) + PREFERRED_FORMAT="deb" + PREFERRED_MANAGER="dpkg" + ;; + rhel|centos|fedora|rocky|almalinux|oracle|amazonlinux) + PREFERRED_FORMAT="rpm" + if command -v dnf >/dev/null 2>&1; then + PREFERRED_MANAGER="dnf" + elif command -v yum >/dev/null 2>&1; then + PREFERRED_MANAGER="yum" + else + PREFERRED_MANAGER="rpm" + fi + ;; + arch|manjaro|artix|endeavouros) + # Arch-based systems - use tar.gz fallback + log_info "Arch-based system detected, using tar.gz format" + PREFERRED_FORMAT="tar.gz" + PREFERRED_MANAGER="tar" + ;; + *) + # Check OS_LIKE for family detection + if [[ "$OS_LIKE" == *"debian"* ]] || [[ "$OS_LIKE" == *"ubuntu"* ]]; then + PREFERRED_FORMAT="deb" + PREFERRED_MANAGER="dpkg" + elif [[ "$OS_LIKE" == *"rhel"* ]] || [[ "$OS_LIKE" == *"fedora"* ]]; then + PREFERRED_FORMAT="rpm" + if command -v dnf >/dev/null 2>&1; then + PREFERRED_MANAGER="dnf" + elif command -v yum >/dev/null 2>&1; then + PREFERRED_MANAGER="yum" + else + PREFERRED_MANAGER="rpm" + fi + elif [[ "$OS_LIKE" == *"arch"* ]]; then + PREFERRED_FORMAT="tar.gz" + PREFERRED_MANAGER="tar" + fi + ;; + esac fi - # Construct package filename and URL - PACKAGE_FILENAME="monitoring-agent_1.0.0_${PACKAGE_ARCH}.${PACKAGE_FORMAT}" - PACKAGE_URL="${GITHUB_BASE_URL}/${PACKAGE_FILENAME}" + # If no preferred format detected, check available package managers + if [[ -z "$PREFERRED_FORMAT" ]]; then + if command -v dpkg >/dev/null 2>&1; then + PREFERRED_FORMAT="deb" + PREFERRED_MANAGER="dpkg" + elif command -v rpm >/dev/null 2>&1; then + PREFERRED_FORMAT="rpm" + if command -v dnf >/dev/null 2>&1; then + PREFERRED_MANAGER="dnf" + elif command -v yum >/dev/null 2>&1; then + PREFERRED_MANAGER="yum" + else + PREFERRED_MANAGER="rpm" + fi + else + # Fallback to tar.gz for unsupported systems + log_info "No native package manager found, using tar.gz fallback" + PREFERRED_FORMAT="tar.gz" + PREFERRED_MANAGER="tar" + fi + fi + + # Set initial package format and manager + PACKAGE_FORMAT="$PREFERRED_FORMAT" + PACKAGE_MANAGER="$PREFERRED_MANAGER" + + # Construct initial package filename and URL + construct_package_url log_success "System detection complete:" log_info " Architecture: $ARCH -> $PACKAGE_ARCH" @@ -94,6 +154,16 @@ detect_system() { log_info " Package URL: $PACKAGE_URL" } +# Construct package URL based on current format +construct_package_url() { + if [[ "$PACKAGE_FORMAT" == "tar.gz" ]]; then + PACKAGE_FILENAME="monitoring-agent_1.0.0_${PACKAGE_ARCH}.tar.gz" + else + PACKAGE_FILENAME="monitoring-agent_1.0.0_${PACKAGE_ARCH}.${PACKAGE_FORMAT}" + fi + PACKAGE_URL="${GITHUB_BASE_URL}/${PACKAGE_FILENAME}" +} + # Validate required environment variables - check both current and sudo environments validate_environment() { # Check if SERVER_TOKEN is available in current environment or passed as argument @@ -116,7 +186,7 @@ validate_environment() { [[ -n "$AGENT_ID" ]] && log_info "AGENT_ID: $AGENT_ID" } -# Download package based on detected system +# Download package with fallback to tar.gz download_package() { local temp_dir="/tmp/monitoring-agent-install" mkdir -p "$temp_dir" @@ -124,17 +194,211 @@ download_package() { log_info "Downloading monitoring agent package..." log_info "URL: $PACKAGE_URL" - if curl -L -f -o "$temp_dir/$PACKAGE_FILENAME" "$PACKAGE_URL"; then - DOWNLOADED_PACKAGE="$temp_dir/$PACKAGE_FILENAME" - log_success "Package downloaded successfully: $PACKAGE_FILENAME" + # Try to download the preferred package format first + if curl -L -f -s -o "$temp_dir/$PACKAGE_FILENAME" "$PACKAGE_URL" 2>/dev/null; then + # Verify the file was actually downloaded and has content + if [[ -s "$temp_dir/$PACKAGE_FILENAME" ]]; then + DOWNLOADED_PACKAGE="$temp_dir/$PACKAGE_FILENAME" + log_success "Package downloaded successfully: $PACKAGE_FILENAME" + return 0 + else + log_warning "Downloaded file is empty, trying fallback..." + rm -f "$temp_dir/$PACKAGE_FILENAME" + fi else - log_error "Failed to download package from: $PACKAGE_URL" - log_info "Please check:" - log_info " 1. Internet connectivity" - log_info " 2. Package availability for your architecture ($PACKAGE_ARCH)" - log_info " 3. GitHub repository access" + log_warning "Failed to download preferred package format: $PACKAGE_FORMAT" + fi + + # If preferred format failed and it's not tar.gz, try tar.gz fallback + if [[ "$PACKAGE_FORMAT" != "tar.gz" ]]; then + log_warning "Native package ($PACKAGE_FORMAT) not available, trying tar.gz fallback..." + + # Switch to tar.gz format + PACKAGE_FORMAT="tar.gz" + PACKAGE_MANAGER="tar" + construct_package_url + + log_info "Fallback URL: $PACKAGE_URL" + + if curl -L -f -s -o "$temp_dir/$PACKAGE_FILENAME" "$PACKAGE_URL" 2>/dev/null; then + # Verify the file was actually downloaded and has content + if [[ -s "$temp_dir/$PACKAGE_FILENAME" ]]; then + DOWNLOADED_PACKAGE="$temp_dir/$PACKAGE_FILENAME" + log_success "Fallback package downloaded successfully: $PACKAGE_FILENAME" + return 0 + else + log_error "Downloaded fallback file is empty" + rm -f "$temp_dir/$PACKAGE_FILENAME" + fi + else + log_error "Failed to download tar.gz fallback" + fi + fi + + # Both attempts failed + log_error "Failed to download package from: $PACKAGE_URL" + log_info "Please check:" + log_info " 1. Internet connectivity" + log_info " 2. Package availability for your architecture ($PACKAGE_ARCH)" + log_info " 3. GitHub repository access" + exit 1 +} + +# Install tar.gz package +install_tar_package() { + log_info "Installing monitoring agent from tar.gz package..." + + local temp_extract_dir="/tmp/monitoring-agent-extract" + mkdir -p "$temp_extract_dir" + + # Extract tar.gz package + if tar -xzf "$DOWNLOADED_PACKAGE" -C "$temp_extract_dir"; then + log_success "Package extracted successfully" + else + log_error "Failed to extract tar.gz package" exit 1 fi + + # Install files to their proper locations + log_info "Installing files to system directories..." + + # Create necessary directories + mkdir -p /usr/bin + mkdir -p /etc/monitoring-agent + mkdir -p /var/lib/monitoring-agent + mkdir -p /var/log/monitoring-agent + + # Detect systemd service directory based on OS + if [[ -d /lib/systemd/system ]]; then + SYSTEMD_DIR="/lib/systemd/system" + elif [[ -d /usr/lib/systemd/system ]]; then + SYSTEMD_DIR="/usr/lib/systemd/system" + else + SYSTEMD_DIR="/etc/systemd/system" + fi + mkdir -p "$SYSTEMD_DIR" + + # Copy files from extracted package + if [[ -f "$temp_extract_dir/usr/bin/monitoring-agent" ]]; then + cp "$temp_extract_dir/usr/bin/monitoring-agent" /usr/bin/ + chmod +x /usr/bin/monitoring-agent + log_success "Binary installed to /usr/bin/monitoring-agent" + else + log_error "Binary not found in package" + exit 1 + fi + + if [[ -f "$temp_extract_dir/etc/monitoring-agent/monitoring-agent.env" ]]; then + cp "$temp_extract_dir/etc/monitoring-agent/monitoring-agent.env" /etc/monitoring-agent/ + log_success "Configuration template installed" + fi + + # Create monitoring-agent user and group if they don't exist + if ! getent group monitoring-agent >/dev/null 2>&1; then + groupadd --system monitoring-agent + log_success "Created monitoring-agent group" + else + log_info "monitoring-agent group already exists" + fi + + if ! getent passwd monitoring-agent >/dev/null 2>&1; then + useradd --system --gid monitoring-agent --home-dir /var/lib/monitoring-agent --shell /bin/false --comment "Monitoring Agent" monitoring-agent + log_success "Created monitoring-agent user" + else + log_info "monitoring-agent user already exists" + fi + + # Set proper ownership and permissions + chown -R monitoring-agent:monitoring-agent /var/lib/monitoring-agent + chown -R monitoring-agent:monitoring-agent /var/log/monitoring-agent + chown -R monitoring-agent:monitoring-agent /etc/monitoring-agent + chmod 755 /var/lib/monitoring-agent + chmod 755 /var/log/monitoring-agent + chmod 755 /etc/monitoring-agent + + # Check if Docker is installed and configure service file accordingly + DOCKER_AVAILABLE=false + if command -v docker >/dev/null 2>&1 && getent group docker >/dev/null 2>&1; then + DOCKER_AVAILABLE=true + # Add monitoring-agent user to docker group if Docker is available + usermod -a -G docker monitoring-agent + log_info "Docker detected, added monitoring-agent user to docker group" + else + log_info "Docker not detected, skipping Docker group configuration" + fi + + # Create the systemd service file with proper Docker configuration + create_systemd_service_file "$SYSTEMD_DIR" "$DOCKER_AVAILABLE" + + # Clean up extraction directory + rm -rf "$temp_extract_dir" + + log_success "Tar.gz package installation completed" +} + +# Create systemd service file with Docker configuration +create_systemd_service_file() { + local systemd_dir="$1" + local docker_available="$2" + + log_info "Creating systemd service file at $systemd_dir/monitoring-agent.service" + + cat > "$systemd_dir/monitoring-agent.service" << 'EOF' +[Unit] +Description=CheckCle Server Monitoring Agent +Documentation=https://github.com/operacle/checkcle-server-agent +After=network.target +Wants=network.target + +[Service] +Type=simple +User=monitoring-agent +Group=monitoring-agent +EOF + + # Add Docker group only if Docker is available + if [[ "$docker_available" == "true" ]]; then + echo "# Add docker group for Docker monitoring access" >> "$systemd_dir/monitoring-agent.service" + echo "SupplementaryGroups=docker" >> "$systemd_dir/monitoring-agent.service" + else + echo "# Docker not available - skipping Docker group configuration" >> "$systemd_dir/monitoring-agent.service" + fi + + # Continue with the rest of the service configuration + cat >> "$systemd_dir/monitoring-agent.service" << 'EOF' +ExecStart=/usr/bin/monitoring-agent +Restart=always +RestartSec=10 +StandardOutput=journal +StandardError=journal + +# Security settings +NoNewPrivileges=yes +ProtectSystem=strict +ProtectHome=yes +PrivateTmp=yes +ProtectKernelTunables=yes +ProtectControlGroups=yes +RestrictSUIDSGID=yes +RemoveIPC=yes +RestrictRealtime=yes + +# Allow access to system information and configuration +ReadWritePaths=/var/log/monitoring-agent +ReadOnlyPaths=/proc /sys /etc/monitoring-agent + +# Network access +PrivateNetwork=no + +# Environment +EnvironmentFile=/etc/monitoring-agent/monitoring-agent.env +WorkingDirectory=/var/lib/monitoring-agent + +[Install] +WantedBy=multi-user.target +EOF + + log_success "Created systemd service file with Docker support: $docker_available" } # Install package based on detected package manager @@ -185,6 +449,10 @@ install_package() { fi ;; + tar) + install_tar_package + ;; + *) log_error "Unsupported package manager: $PACKAGE_MANAGER" exit 1 @@ -232,7 +500,7 @@ configure_agent() { log_info "Final configuration:" log_info " Server Name: $SERVER_NAME" log_info " Agent ID: $AGENT_ID" - log_info " PB API URL: $POCKETBASE_URL" + log_info " PocketBase URL: $POCKETBASE_URL" log_info " IP Address: $IP_ADDRESS" log_info " OS Type: $OS_TYPE" log_info " Health Check Port: $HEALTH_CHECK_PORT" @@ -341,7 +609,7 @@ test_installation() { show_post_install_info() { echo echo "=============================================" - echo " CheckCle Server Agent Installation Complete!" + echo " Installation Complete!" echo "=============================================" echo log_success "CheckCle Monitoring Agent installed and configured successfully" @@ -350,6 +618,11 @@ show_post_install_info() { echo " Architecture: $ARCH ($PACKAGE_ARCH)" echo " Package: $PACKAGE_FILENAME" echo " Package Manager: $PACKAGE_MANAGER" + if [[ "$PACKAGE_FORMAT" == "tar.gz" ]]; then + echo " Installation Type: Manual (tar.gz)" + else + echo " Installation Type: Native package ($PACKAGE_FORMAT)" + fi echo echo "Configuration: $CONFIG_FILE" echo "Service status: systemctl status monitoring-agent" @@ -416,7 +689,12 @@ case "${1:-}" in echo "System Requirements:" echo " - Linux with systemd" echo " - Supported architectures: x86_64 (amd64), aarch64/arm64" - echo " - Supported distributions: Debian/Ubuntu (.deb), RHEL/CentOS/Fedora (.rpm)" + echo " - Supported distributions: Debian/Ubuntu (.deb), RHEL/CentOS/Fedora (.rpm), or any Linux (tar.gz fallback)" + echo + echo "Package Installation Logic:" + echo " 1. Detects OS and tries native package format first (.deb for Debian-based, .rpm for RHEL-based)" + echo " 2. If native package is not available, automatically falls back to tar.gz" + echo " 3. tar.gz works on any Linux distribution with systemd" echo echo "Required Environment Variables:" echo " SERVER_TOKEN Server authentication token" @@ -444,13 +722,28 @@ case "${1:-}" in systemctl disable monitoring-agent 2>/dev/null || true # Remove based on detected package manager - if command -v dpkg >/dev/null 2>&1; then + if command -v dpkg >/dev/null 2>&1 && dpkg -l monitoring-agent >/dev/null 2>&1; then dpkg -r monitoring-agent 2>/dev/null || true - elif command -v rpm >/dev/null 2>&1; then + log_success "DEB package removed" + elif command -v rpm >/dev/null 2>&1 && rpm -q monitoring-agent >/dev/null 2>&1; then rpm -e monitoring-agent 2>/dev/null || true + log_success "RPM package removed" + else + # Manual removal for tar.gz installations + log_info "Performing manual cleanup for tar.gz installation..." + rm -f /usr/bin/monitoring-agent 2>/dev/null || true + rm -rf /etc/monitoring-agent 2>/dev/null || true + rm -f /lib/systemd/system/monitoring-agent.service 2>/dev/null || true + rm -f /usr/lib/systemd/system/monitoring-agent.service 2>/dev/null || true + rm -f /etc/systemd/system/monitoring-agent.service 2>/dev/null || true + userdel monitoring-agent 2>/dev/null || true + groupdel monitoring-agent 2>/dev/null || true + rm -rf /var/lib/monitoring-agent 2>/dev/null || true + rm -rf /var/log/monitoring-agent 2>/dev/null || true + log_success "Manual cleanup completed" fi - rm -rf /etc/monitoring-agent 2>/dev/null || true + systemctl daemon-reload 2>/dev/null || true log_success "Monitoring agent uninstalled" exit 0 ;;