Към съдържанието
bub.im

FreeBSD 15 – Zabbix classic-agent deployment

cpx November 8, 2026 5 min четене FreeBSD/BSDZABBIX/10051
install-zabbix-agent-freebsd15.shbash
#!/bin/sh
# FreeBSD 15 Zabbix classic-agent deployment. Run as root.
set -eu
umask 027

PKG_NAME=zabbix74-agent
SERVERS='10.0.0.0/8,172.16.0.0/12,192.168.0.0/16'
LISTEN_IP=''
HOSTNAME=''
ACTIVE_SERVER=''
FIREWALL='none'
YES=0

usage() {
  cat <<'HELP'
Usage: sh install-zabbix-agent-freebsd15.sh [options]
  --servers IP[/CIDR][,...]   Passive polling allowlist (default: RFC1918 ranges)
  --listen-ip IP              Bind to an assigned IPv4 LAN address (default: all)
  --hostname NAME             Zabbix host identity (default: hostname -s)
  --active-server HOST[:PORT] Enable active checks against one server/proxy
  --firewall none|ipfw        Optionally add temporary IPFW permit rules (default: none)
  --yes                       Skip confirmation prompt
  --help                      Show help

Requires FreeBSD 15 and root. Installs zabbix74-agent from configured pkg repository.
Does not replace any existing firewall configuration or add Linux-only UserParameters.
HELP
}
fail() { echo "ERROR: $*" >&2; exit 1; }
info() { echo "[+] $*"; }
valid_ipv4() {
  echo "$1" | awk -F. 'NF!=4{exit 1} {for(i=1;i<=4;i++) if($i !~ /^[0-9]+$/ || length($i)>3 || $i+0>255) exit 1; exit 0}'
}
valid_host() { echo "$1" | grep -Eq '^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$'; }

while [ "$#" -gt 0 ]; do
  case "$1" in
    --servers|--listen-ip|--hostname|--active-server|--firewall)
      [ "$#" -ge 2 ] || fail "Missing argument for $1"
      case "$1" in
        --servers) SERVERS=$2 ;;
        --listen-ip) LISTEN_IP=$2 ;;
        --hostname) HOSTNAME=$2 ;;
        --active-server) ACTIVE_SERVER=$2 ;;
        --firewall) FIREWALL=$2 ;;
      esac
      shift 2 ;;
    --yes) YES=1; shift ;;
    --help|-h) usage; exit 0 ;;
    *) fail "Unknown option: $1" ;;
  esac
done

[ "$(id -u)" -eq 0 ] || fail 'Run as root.'
[ "$(uname -s)" = 'FreeBSD' ] || fail 'FreeBSD is required.'
case "$(freebsd-version -u)" in 15.*) ;; *) fail 'Designed for FreeBSD 15.x.' ;; esac
command -v pkg >/dev/null 2>&1 || fail 'pkg not found; bootstrap pkg first.'
command -v sysrc >/dev/null 2>&1 || fail 'sysrc is required.'
[ -n "$HOSTNAME" ] || HOSTNAME=$(hostname -s)
valid_host "$HOSTNAME" || fail 'Invalid hostname (letters/digits/dots/dash/underscore only).'
[ -z "$LISTEN_IP" ] || valid_ipv4 "$LISTEN_IP" || fail 'Invalid --listen-ip IPv4 address.'
if [ -n "$LISTEN_IP" ]; then
  ifconfig -a | grep -Eq "inet[[:space:]]+$LISTEN_IP([[:space:]]|$)" || fail "Listen IP $LISTEN_IP not assigned to a local interface"
fi
# Permit explicit IPv4 addresses and CIDR blocks supported by Zabbix 7.4.
# Reject empty entries and validate netmask length (0..32).
[ -n "$SERVERS" ] || fail 'Empty server allowlist.'
echo "$SERVERS" | grep -Eq '^[0-9.,/]+$' || fail 'Use comma-separated IPv4 addresses or CIDR ranges.'
case "$SERVERS" in ,*|*,|*,,*) fail 'Empty server entry in allowlist.' ;; esac
OLD_IFS=$IFS; IFS=,
for addr in $SERVERS; do
  case "$addr" in
    */*)
      ip=${addr%/*}; mask=${addr#*/}
      valid_ipv4 "$ip" || fail "Invalid network address: $ip"
      echo "$mask" | grep -Eq '^[0-9]{1,2}$' || fail "Invalid CIDR mask: $addr"
      [ "$mask" -le 32 ] || fail "CIDR mask out of range: $addr" ;;
    *) valid_ipv4 "$addr" || fail "Invalid server IPv4: $addr" ;;
  esac
done
IFS=$OLD_IFS
case "$FIREWALL" in none|ipfw) ;; *) fail 'Firewall must be none or ipfw.' ;; esac
if [ -n "$ACTIVE_SERVER" ]; then
  echo "$ACTIVE_SERVER" | grep -Eq '^[A-Za-z0-9][A-Za-z0-9._-]*(:[0-9]{1,5})?$' || fail 'Invalid active server.'
fi

if [ "$YES" -ne 1 ]; then
  echo "Install $PKG_NAME, configure agent for $HOSTNAME on ${LISTEN_IP:-all interfaces}, firewall=$FIREWALL?"
  printf 'Type YES to proceed: '; read -r answer
  [ "$answer" = YES ] || fail 'Cancelled.'
fi

info "Installing $PKG_NAME"
pkg install -y "$PKG_NAME"

CONF=/usr/local/etc/zabbix74/zabbix_agentd.conf
[ -f "$CONF" ] || fail "Package did not provide $CONF; investigate package layout."
[ -f /usr/local/etc/rc.d/zabbix_agentd ] || fail 'Missing rc service /usr/local/etc/rc.d/zabbix_agentd.'
command -v /usr/local/sbin/zabbix_agentd >/dev/null 2>&1 || fail 'Agent binary missing.'
BACKUP="${CONF}.backup.$(date +%Y%m%d%H%M%S)"
cp -p "$CONF" "$BACKUP"
info "Backup: $BACKUP"
mkdir -p /var/log/zabbix /var/run/zabbix
chown zabbix:zabbix /var/log/zabbix /var/run/zabbix
chmod 0750 /var/log/zabbix /var/run/zabbix

TMP=$(mktemp "${CONF}.tmp.XXXXXXXX") || fail 'Cannot create temporary config.'
trap 'rm -f "$TMP"' EXIT HUP INT TERM
{
  cat <<'CONFIG'
# Managed by install-zabbix-agent-freebsd15.sh
# FreeBSD 15 / Zabbix 7.4 classic agent
LogType=file
LogFile=/var/log/zabbix/zabbix_agentd.log
LogFileSize=10
PidFile=/var/run/zabbix/zabbix_agentd.pid
DebugLevel=3
Timeout=5
ListenPort=10050
StartAgents=5
TLSAccept=unencrypted
TLSConnect=unencrypted
UnsafeUserParameters=0
CONFIG
  printf 'Server=%s\n' "$SERVERS"
  printf 'Hostname=%s\n' "$HOSTNAME"
  [ -z "$LISTEN_IP" ] || printf 'ListenIP=%s\n' "$LISTEN_IP"
  [ -z "$ACTIVE_SERVER" ] || printf 'ServerActive=%s\n' "$ACTIVE_SERVER"
} > "$TMP"
chmod 0640 "$TMP"
chown root:zabbix "$TMP"

info 'Validating candidate configuration'
/usr/local/sbin/zabbix_agentd -T -c "$TMP" || fail "Config invalid; original remains at $CONF"
install -o root -g zabbix -m 0640 "$TMP" "$CONF"
# Use sysrc to avoid the malformed rc.conf entries caused by direct shell-style assignments.
sysrc zabbix_agentd_enable=YES
sysrc "zabbix_agentd_config=$CONF"

info 'Restarting the agent'
if service zabbix_agentd status >/dev/null 2>&1; then
  START_ACTION=restart
else
  START_ACTION=start
fi
if ! service zabbix_agentd "$START_ACTION"; then
  info 'Restart failed, restoring previous config'
  cp -p "$BACKUP" "$CONF"
  service zabbix_agentd restart >/dev/null 2>&1 || true
  fail 'Agent failed to start; previous config restored.'
fi
service zabbix_agentd status || fail 'Agent not running after restart.'

if [ "$FIREWALL" = ipfw ]; then
  # Do not enable a firewall or change the default policy. Only operate on an existing IPFW instance.
  if ! kldstat -q -m ipfw && ! sysctl -n net.inet.ip.fw.enable >/dev/null 2>&1; then
    fail 'IPFW is not active. Agent installed, but firewall unchanged.'
  fi
  info 'Adding runtime-only IPFW allow rules for TCP/10050 (NOT persistent)'
  RULE=12000
  OLD_IFS=$IFS; IFS=,
  for addr in $SERVERS; do
    if ! ipfw -q add "$RULE" allow tcp from "$addr" to me 10050 in; then
      IFS=$OLD_IFS
      fail 'IPFW rule failed; review partial rules with ipfw list.'
    fi
    RULE=$((RULE + 1))
  done
  IFS=$OLD_IFS
  echo 'WARNING: These rules do not survive firewall reload/reboot and may not precede existing deny rules.'
fi

info 'Agent test:'
/usr/local/sbin/zabbix_agentd -t agent.ping -c "$CONF" || true
info 'TCP listener:'
sockstat -4 -l | grep ':10050' || true
cat <<SUMMARY

Zabbix FreeBSD 15 install complete.
  Package:     $PKG_NAME
  Config:      $CONF
  Backup:      $BACKUP
  Service:     zabbix_agentd
  Hostname:    $HOSTNAME
  Passive TCP: ${LISTEN_IP:-all interfaces}:10050
  Active:      ${ACTIVE_SERVER:-disabled}
  Firewall:    $FIREWALL

Verify: service zabbix_agentd status
        tail -n 50 /var/log/zabbix/zabbix_agentd.log
        sockstat -4 -l | grep 10050

NOTE: TLS is not configured. Use TLS PSK/certificates when monitoring over untrusted networks.
NOTE: Linux /proc UserParameters are intentionally not installed on FreeBSD.
SUMMARY

Бъди първият коментирал

защитено · без проследяване

0 коментара