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 коментара