This commit is contained in:
2026-07-09 10:44:00 -04:00

View File

@@ -1,7 +1,9 @@
#!/bin/bash #!/bin/bash
# #
# Zabbix Agent 2 Deployment Script - Linux ARM (aarch64 / armhf) # Zabbix Agent 2 Deployment Script - Linux ARM (aarch64 / armhf / armv6)
# Installs and configures Zabbix Agent 2 with PSK auto-registration # Installs and configures Zabbix Agent 2 with PSK auto-registration
# For armhf/armv6: falls back to Zabbix Agent (v1) since Agent 2 is not
# available for 32-bit ARM (see ZBX-24905).
# Target server: zabbix.snarfnet.net # Target server: zabbix.snarfnet.net
# #
# Usage: sudo bash deploy_zabbix_agent_linux_arm.sh [psk_key] # Usage: sudo bash deploy_zabbix_agent_linux_arm.sh [psk_key]
@@ -10,12 +12,13 @@
set -euo pipefail set -euo pipefail
ZABBIX_SERVER="zabbix.snarfnet.net" ZABBIX_SERVER="zabbix.snarfnet.net"
ZABBIX_VERSION="7.0.0" ZABBIX_VERSION="7.0.27"
PSK_IDENTITY="PSK_autoregister" PSK_IDENTITY="PSK_autoregister"
PSK_FILE="/etc/zabbix/zabbix_agent2.psk" PSK_FILE="/etc/zabbix/zabbix_agent2.psk"
AGENT_CONF="/etc/zabbix/zabbix_agent2.conf" AGENT_CONF="/etc/zabbix/zabbix_agent2.conf"
HOST_METADATA="Linux" HOST_METADATA="Linux"
INSTALL_DIR="/opt/zabbix-agent2" INSTALL_DIR="/opt/zabbix-agent2"
USING_AGENT_V1=false
# --- Functions --- # --- Functions ---
@@ -61,17 +64,142 @@ install_agent_package_manager() {
case "${OS_ID}" in case "${OS_ID}" in
debian|ubuntu|raspbian) debian|ubuntu|raspbian)
log "Installing via apt (Debian/Ubuntu/Raspbian)..." log "Installing via apt (Debian/Ubuntu/Raspbian)..."
# Determine arch string for the repo
local dpkg_arch local dpkg_arch
dpkg_arch=$(dpkg --print-architecture) dpkg_arch=$(dpkg --print-architecture)
wget -q "https://repo.zabbix.com/zabbix/7.0/ubuntu/pool/main/z/zabbix-release/zabbix-release_latest+ubuntu_all.deb" -O /tmp/zabbix-release.deb 2>/dev/null || \ # Zabbix provides separate repos for ARM architectures:
wget -q "https://repo.zabbix.com/zabbix/7.0/debian/pool/main/z/zabbix-release/zabbix-release_latest+debian${OS_VERSION}_all.deb" -O /tmp/zabbix-release.deb 2>/dev/null || true # - debian-arm64 / ubuntu-arm64 for aarch64 (Bookworm/Trixie+ only)
# - raspbian for armhf (Raspberry Pi OS) — but NOTE: Zabbix 7.0 does NOT
# ship zabbix-agent2 for armhf (see ZBX-24905). Only zabbix-agent (v1).
# The standard debian/ubuntu repos only carry amd64.
local repo_distro=""
local has_agent2=true
case "${dpkg_arch}" in
arm64)
if [ "${OS_ID}" = "ubuntu" ]; then
repo_distro="ubuntu-arm64"
else
repo_distro="debian-arm64"
fi
;;
armhf)
repo_distro="raspbian"
# Zabbix 7.0 raspbian repo does NOT include zabbix-agent2 for armhf.
# Only zabbix-agent (v1) is available.
has_agent2=false
;;
*)
log "Unexpected dpkg arch '${dpkg_arch}' on ARM script. Falling back to binary..."
install_agent_binary
return 0
;;
esac
# Determine release codename (e.g. bullseye, bookworm, jammy)
local codename=""
if [ -f /etc/os-release ]; then
codename=$(. /etc/os-release && echo "${VERSION_CODENAME:-}")
fi
if [ -z "${codename}" ]; then
log "Could not determine release codename. Falling back to binary..."
install_agent_binary
return 0
fi
# The arm64 Zabbix repos only support Debian 12+ (bookworm, trixie).
# For older/EOL releases like bullseye, try Debian's own repos first,
# then fall back to extracting from the bookworm .deb.
case "${codename}" in
buster|bullseye|stretch|jessie)
if [ "${has_agent2}" = true ]; then
log "Zabbix arm64 apt repo not available for EOL release '${codename}'."
log "Attempting install from Debian's own repositories..."
else
log "Zabbix raspbian repo not available for EOL release '${codename}'."
log "Attempting install from Debian's own repositories..."
fi
# Disable defunct backports repos first
local backports_list
backports_list=$(grep -rl 'backports' /etc/apt/sources.list /etc/apt/sources.list.d/ 2>/dev/null || true)
if [ -n "${backports_list}" ]; then
log "Disabling defunct backports repositories..."
for f in ${backports_list}; do
sed -i '/backports/s/^[^#]/#&/' "${f}"
done
fi
# Try installing from existing repos (Debian's own packages)
apt-get update 2>&1 | grep -v "^W:" || true
if apt-get install -y zabbix-agent2 2>/dev/null; then
log "Installed zabbix-agent2 from Debian repositories."
return 0
fi
# On armhf, try zabbix-agent (v1) as well
if [ "${has_agent2}" = false ]; then
log "zabbix-agent2 not available. Trying zabbix-agent (v1)..."
if apt-get install -y zabbix-agent 2>/dev/null; then
log "Installed zabbix-agent (v1) from Debian repositories."
AGENT_CONF="/etc/zabbix/zabbix_agentd.conf"
USING_AGENT_V1=true
return 0
fi
fi
log "Not available in Debian repos. Falling back to binary extraction..."
install_agent_binary
return 0
;;
esac
# Disable defunct backports repos to prevent apt-get update 404 errors (Debian EOL releases)
local backports_list
backports_list=$(grep -rl 'backports' /etc/apt/sources.list /etc/apt/sources.list.d/ 2>/dev/null || true)
if [ -n "${backports_list}" ]; then
log "Disabling defunct backports repositories to avoid 404 errors..."
for f in ${backports_list}; do
sed -i '/backports/s/^[^#]/#&/' "${f}"
done
fi
# Download and install the Zabbix release package for the ARM-specific repo.
# URL format: zabbix-release_latest+debian12_all.deb (for both raspbian & debian-arm64)
local release_url="https://repo.zabbix.com/zabbix/7.0/${repo_distro}/pool/main/z/zabbix-release/zabbix-release_latest+debian${OS_VERSION}_all.deb"
log "Adding Zabbix repository: ${repo_distro} (${codename})"
log "Release package URL: ${release_url}"
if wget -q "${release_url}" -O /tmp/zabbix-release.deb 2>/dev/null || \
curl -sfL "${release_url}" -o /tmp/zabbix-release.deb 2>/dev/null; then
# Verify we actually got a .deb and not an error page
if ! dpkg-deb --info /tmp/zabbix-release.deb >/dev/null 2>&1; then
log "Downloaded file is not a valid .deb package. Falling back to binary..."
rm -f /tmp/zabbix-release.deb
install_agent_binary
return 0
fi
if [ -f /tmp/zabbix-release.deb ]; then
dpkg -i /tmp/zabbix-release.deb dpkg -i /tmp/zabbix-release.deb
apt-get update apt-get update
apt-get install -y zabbix-agent2 && { rm -f /tmp/zabbix-release.deb; return 0; }
# Try zabbix-agent2 first
if apt-get install -y zabbix-agent2 2>/dev/null; then
rm -f /tmp/zabbix-release.deb
log "zabbix-agent2 package installation successful."
return 0
fi
# On armhf, agent2 won't exist — fall back to zabbix-agent (v1)
if [ "${has_agent2}" = false ]; then
log "zabbix-agent2 not available for armhf. Installing zabbix-agent (v1)..."
if apt-get install -y zabbix-agent; then
rm -f /tmp/zabbix-release.deb
AGENT_CONF="/etc/zabbix/zabbix_agentd.conf"
USING_AGENT_V1=true
log "zabbix-agent (v1) package installation successful."
return 0
fi
fi
fi fi
log "Package manager install failed, falling back to binary tarball..." log "Package manager install failed, falling back to binary tarball..."
@@ -85,21 +213,236 @@ install_agent_package_manager() {
esac esac
} }
install_agent_binary() { install_agent_v1_armhf() {
log "Installing Zabbix Agent 2 from pre-compiled binary..." # Zabbix 7.0 raspbian repo provides zabbix-agent (v1) for armhf but NOT agent2.
# This function installs agent v1 as a fallback for 32-bit ARM systems.
detect_os
local codename=""
if [ -f /etc/os-release ]; then
codename=$(. /etc/os-release && echo "${VERSION_CODENAME:-}")
fi
# Try adding the raspbian repo and installing zabbix-agent (v1)
local release_url="https://repo.zabbix.com/zabbix/7.0/raspbian/pool/main/z/zabbix-release/zabbix-release_latest+debian${OS_VERSION}_all.deb"
log "Trying Zabbix raspbian repo for zabbix-agent (v1)..."
log "Release URL: ${release_url}"
if wget -q "${release_url}" -O /tmp/zabbix-release.deb 2>/dev/null || \
curl -sfL "${release_url}" -o /tmp/zabbix-release.deb 2>/dev/null; then
if dpkg-deb --info /tmp/zabbix-release.deb >/dev/null 2>&1; then
dpkg -i /tmp/zabbix-release.deb 2>/dev/null || true
apt-get update 2>/dev/null || true
if apt-get install -y zabbix-agent 2>/dev/null; then
rm -f /tmp/zabbix-release.deb
AGENT_CONF="/etc/zabbix/zabbix_agentd.conf"
USING_AGENT_V1=true
log "Installed zabbix-agent (v1) successfully from raspbian repository."
return 0
fi
fi
fi
rm -f /tmp/zabbix-release.deb
# Also try installing directly if it's already in repos
if apt-get install -y zabbix-agent 2>/dev/null; then
AGENT_CONF="/etc/zabbix/zabbix_agentd.conf"
USING_AGENT_V1=true
log "Installed zabbix-agent (v1) from existing repositories."
return 0
fi
log "Could not install zabbix-agent (v1) either."
return 1
}
install_agent_binary() {
log "Installing Zabbix Agent 2 from direct .deb package..."
# Zabbix does not publish static binary tarballs for ARM architectures.
# Strategy: download the .deb and extract the binary without running post-install
# scripts (which try to start the service before we've configured it).
#
# IMPORTANT: Zabbix 7.0 only provides zabbix-agent2 for arm64, NOT armhf.
# For armhf/armv6 systems, we try arm64 .deb extraction (unlikely to work due to
# arch mismatch), then fall back to zabbix-agent (v1) from the raspbian repo,
# or suggest upgrading to a 64-bit OS.
local deb_path="/tmp/zabbix_agent2.deb"
local dpkg_arch
dpkg_arch=$(dpkg --print-architecture 2>/dev/null || echo "unknown")
# Select the correct pool and architecture for the .deb download
local pool_base=""
local deb_arch=""
case "${dpkg_arch}" in
arm64)
pool_base="https://repo.zabbix.com/zabbix/7.0/debian-arm64/pool/main/z/zabbix"
deb_arch="arm64"
;;
armhf)
# Zabbix 7.0 does NOT publish agent2 for armhf. Try the raspbian pool
# for zabbix-agent (v1) first, then fall back to arm64 extraction attempt.
log "NOTE: Zabbix 7.0 does not provide zabbix-agent2 for armhf (32-bit ARM)."
log "Attempting to install zabbix-agent (v1) from raspbian repository..."
if install_agent_v1_armhf; then
return 0
fi
# Last resort: try arm64 binary (won't work on 32-bit kernel)
pool_base="https://repo.zabbix.com/zabbix/7.0/debian-arm64/pool/main/z/zabbix"
deb_arch="arm64"
;;
*)
pool_base="https://repo.zabbix.com/zabbix/7.0/debian-arm64/pool/main/z/zabbix"
deb_arch="arm64"
;;
esac
local deb_urls=(
"${pool_base}/zabbix-agent2_${ZABBIX_VERSION}-1+debian12_${deb_arch}.deb"
"${pool_base}/zabbix-agent2_${ZABBIX_VERSION}-1%2Bdebian12_${deb_arch}.deb"
)
local downloaded=false
for url in "${deb_urls[@]}"; do
log "Trying: ${url}"
if wget -q "${url}" -O "${deb_path}" 2>/dev/null; then
if dpkg-deb --info "${deb_path}" >/dev/null 2>&1; then
downloaded=true
break
fi
fi
if curl -sfL "${url}" -o "${deb_path}" 2>/dev/null; then
if dpkg-deb --info "${deb_path}" >/dev/null 2>&1; then
downloaded=true
break
fi
fi
rm -f "${deb_path}"
done
if [ "${downloaded}" = false ]; then
# Fallback: try CDN static tarball (may work for some versions/arches)
local tarball_url="https://cdn.zabbix.com/zabbix/binaries/stable/7.0/${ZABBIX_VERSION}/zabbix_agent2-${ZABBIX_VERSION}-${TARBALL_ARCH}-static.tar.gz" local tarball_url="https://cdn.zabbix.com/zabbix/binaries/stable/7.0/${ZABBIX_VERSION}/zabbix_agent2-${ZABBIX_VERSION}-${TARBALL_ARCH}-static.tar.gz"
local tarball_path="/tmp/zabbix_agent2.tar.gz" local tarball_path="/tmp/zabbix_agent2.tar.gz"
log "Downloading from: ${tarball_url}" log "Trying CDN tarball: ${tarball_url}"
if ! wget -q "${tarball_url}" -O "${tarball_path}" 2>/dev/null && \ if wget -q "${tarball_url}" -O "${tarball_path}" 2>/dev/null || \
! curl -sL "${tarball_url}" -o "${tarball_path}" 2>/dev/null; then curl -sfL "${tarball_url}" -o "${tarball_path}" 2>/dev/null; then
log "ERROR: Failed to download Zabbix Agent 2 binary." if file "${tarball_path}" 2>/dev/null | grep -q gzip; then
log " URL: ${tarball_url}" install_from_tarball "${tarball_path}"
log " You may need to check https://www.zabbix.com/download for the correct ARM binary." return 0
fi
fi
rm -f "${tarball_path}"
log "ERROR: Failed to download Zabbix Agent 2 for ${ARCH_LABEL}."
log " Options:"
log " 1. Upgrade to Debian 12 (Bookworm) and re-run this script"
log " 2. Manually download from https://www.zabbix.com/download"
exit 1 exit 1
fi fi
# Extract the .deb contents manually instead of dpkg -i.
# This avoids post-install scripts that try to start the service before config is ready,
# and avoids glibc version issues by testing the binary directly.
log "Extracting .deb package contents..."
local extract_dir="/tmp/zabbix_agent2_extract"
rm -rf "${extract_dir}"
mkdir -p "${extract_dir}"
dpkg-deb -x "${deb_path}" "${extract_dir}"
# Check if the binary actually runs on this system (glibc compatibility)
local agent_bin="${extract_dir}/usr/sbin/zabbix_agent2"
if [ ! -f "${agent_bin}" ]; then
agent_bin=$(find "${extract_dir}" -name "zabbix_agent2" -type f 2>/dev/null | head -1)
fi
if [ -z "${agent_bin}" ] || [ ! -f "${agent_bin}" ]; then
log "ERROR: Could not find zabbix_agent2 binary in package."
rm -rf "${extract_dir}" "${deb_path}"
exit 1
fi
# Test if the binary can actually execute on this system
chmod +x "${agent_bin}"
if ! "${agent_bin}" --version >/dev/null 2>&1; then
log "WARNING: Bookworm binary incompatible with this system (likely glibc mismatch)."
log "Attempting full dpkg install with dependency resolution..."
rm -rf "${extract_dir}"
# Stop any existing broken service
systemctl stop zabbix-agent2 2>/dev/null || true
systemctl disable zabbix-agent2 2>/dev/null || true
# Try full install — may work if deps can be satisfied
dpkg -i --force-depends "${deb_path}" 2>/dev/null || true
# Check if binary landed and works
if [ -f /usr/sbin/zabbix_agent2 ] && /usr/sbin/zabbix_agent2 --version >/dev/null 2>&1; then
log "Package installation succeeded despite warnings."
rm -f "${deb_path}"
return 0
fi
# Clean up the broken install
dpkg --remove --force-remove-reinstreq zabbix-agent2 2>/dev/null || true
# On armhf, try zabbix-agent (v1) before giving up
if [ "${dpkg_arch}" = "armhf" ]; then
log "Attempting zabbix-agent (v1) as final fallback..."
if install_agent_v1_armhf; then
return 0
fi
fi
log "ERROR: Zabbix Agent 2 binary from Debian 12 is not compatible with this system."
log " Your system runs glibc $(ldd --version 2>&1 | head -1 | grep -oP '\\d+\\.\\d+$' || echo 'unknown') but the package requires glibc 2.36+."
log " Options:"
log " 1. Upgrade to a 64-bit OS (Raspberry Pi OS 64-bit): https://www.raspberrypi.com/software/"
log " 2. Use Zabbix Agent (v1) instead: apt install zabbix-agent"
log " 3. Build from source: https://www.zabbix.com/documentation/current/en/manual/installation/install"
rm -f "${deb_path}"
exit 1
fi
# Binary works! Install files to their proper locations.
log "Binary compatibility verified. Installing files..."
# Create zabbix user if it doesn't exist
if ! id -u zabbix &>/dev/null; then
useradd -r -s /sbin/nologin -d /var/lib/zabbix -M zabbix
fi
# Copy binary
cp "${agent_bin}" /usr/sbin/zabbix_agent2
chmod +x /usr/sbin/zabbix_agent2
# Copy config files and directories
mkdir -p /etc/zabbix
if [ -d "${extract_dir}/etc/zabbix" ]; then
cp -rn "${extract_dir}/etc/zabbix/"* /etc/zabbix/ 2>/dev/null || true
fi
# Set up directories
mkdir -p /var/log/zabbix /var/run/zabbix /var/lib/zabbix
chown -R zabbix:zabbix /var/log/zabbix /var/run/zabbix /var/lib/zabbix
# Install systemd service from package or create our own
if [ -f "${extract_dir}/lib/systemd/system/zabbix-agent2.service" ]; then
cp "${extract_dir}/lib/systemd/system/zabbix-agent2.service" /lib/systemd/system/
systemctl daemon-reload
else
create_systemd_service
fi
rm -rf "${extract_dir}" "${deb_path}"
log "Installation complete."
}
install_from_tarball() {
local tarball_path="$1"
log "Extracting tarball..."
# Create directories # Create directories
mkdir -p "${INSTALL_DIR}/bin" mkdir -p "${INSTALL_DIR}/bin"
mkdir -p /etc/zabbix mkdir -p /etc/zabbix
@@ -112,7 +455,7 @@ install_agent_binary() {
# Find the binary # Find the binary
local agent_bin local agent_bin
agent_bin=$(find "${INSTALL_DIR}" -name "zabbix_agent2" -type f | head -1) agent_bin=$(find "${INSTALL_DIR}" -name "zabbix_agent2" -type f 2>/dev/null | head -1)
if [ -z "${agent_bin}" ]; then if [ -z "${agent_bin}" ]; then
log "ERROR: Could not find zabbix_agent2 binary in extracted archive." log "ERROR: Could not find zabbix_agent2 binary in extracted archive."
exit 1 exit 1
@@ -130,9 +473,6 @@ install_agent_binary() {
chown -R zabbix:zabbix /var/log/zabbix /var/run/zabbix chown -R zabbix:zabbix /var/log/zabbix /var/run/zabbix
# Set config path for binary installs
AGENT_CONF="/etc/zabbix/zabbix_agent2.conf"
# Create systemd service # Create systemd service
create_systemd_service create_systemd_service
@@ -183,6 +523,34 @@ configure_agent() {
# Back up existing config if present # Back up existing config if present
[ -f "${AGENT_CONF}" ] && cp "${AGENT_CONF}" "${AGENT_CONF}.bak.$(date +%s)" [ -f "${AGENT_CONF}" ] && cp "${AGENT_CONF}" "${AGENT_CONF}.bak.$(date +%s)"
if [ "${USING_AGENT_V1}" = true ]; then
# Zabbix Agent (v1) configuration — slightly different directives
cat > "${AGENT_CONF}" << EOF
# Zabbix Agent (v1) Configuration
# Auto-generated by ARM deployment script on $(date '+%Y-%m-%d %H:%M:%S')
# Architecture: ${ARCH} (${ARCH_LABEL})
# Note: Agent v1 installed because Agent 2 is not available for armhf
Server=${ZABBIX_SERVER}
ServerActive=${ZABBIX_SERVER}
HostnameItem=system.hostname
HostMetadata=${HOST_METADATA}
# PSK Encryption
TLSConnect=psk
TLSAccept=psk
TLSPSKIdentity=${PSK_IDENTITY}
TLSPSKFile=${PSK_FILE}
# Logging
LogFile=/var/log/zabbix/zabbix_agentd.log
LogFileSize=10
# Performance
BufferSend=5
BufferSize=100
EOF
else
cat > "${AGENT_CONF}" << EOF cat > "${AGENT_CONF}" << EOF
# Zabbix Agent 2 Configuration # Zabbix Agent 2 Configuration
# Auto-generated by ARM deployment script on $(date '+%Y-%m-%d %H:%M:%S') # Auto-generated by ARM deployment script on $(date '+%Y-%m-%d %H:%M:%S')
@@ -207,25 +575,35 @@ LogFileSize=10
BufferSend=5 BufferSend=5
BufferSize=100 BufferSize=100
EOF EOF
fi
chown root:zabbix "${AGENT_CONF}" chown root:zabbix "${AGENT_CONF}"
chmod 644 "${AGENT_CONF}" chmod 644 "${AGENT_CONF}"
} }
start_agent() { start_agent() {
log "Enabling and starting zabbix-agent2..." local service_name="zabbix-agent2"
systemctl enable zabbix-agent2 if [ "${USING_AGENT_V1}" = true ]; then
systemctl restart zabbix-agent2 service_name="zabbix-agent"
fi
log "Enabling and starting ${service_name}..."
systemctl enable "${service_name}"
systemctl restart "${service_name}"
sleep 2 sleep 2
if systemctl is-active --quiet zabbix-agent2; then if systemctl is-active --quiet "${service_name}"; then
log "Zabbix Agent 2 is running." log "${service_name} is running."
systemctl status zabbix-agent2 --no-pager systemctl status "${service_name}" --no-pager
else else
log "WARNING: Agent may not have started. Check logs:" log "WARNING: Agent may not have started. Check logs:"
log " journalctl -u zabbix-agent2 -n 20" log " journalctl -u ${service_name} -n 20"
if [ "${USING_AGENT_V1}" = true ]; then
log " cat /var/log/zabbix/zabbix_agentd.log"
else
log " cat /var/log/zabbix/zabbix_agent2.log" log " cat /var/log/zabbix/zabbix_agent2.log"
fi fi
fi
} }
# --- Main --- # --- Main ---
@@ -259,6 +637,11 @@ configure_agent "${PSK_KEY}"
start_agent start_agent
log "=== Deployment Complete ===" log "=== Deployment Complete ==="
if [ "${USING_AGENT_V1}" = true ]; then
log "Agent Version: Zabbix Agent (v1) — agent2 not available for ${ARCH_LABEL}"
else
log "Agent Version: Zabbix Agent 2"
fi
log "PSK Identity: ${PSK_IDENTITY}" log "PSK Identity: ${PSK_IDENTITY}"
log "PSK Key: ${PSK_KEY}" log "PSK Key: ${PSK_KEY}"
log "" log ""