#!/bin/bash
#############################################################
#### NRPE Installer                                      ####
#### Automated NRPE daemon and Nagios plugin setup       ####
#### for remote hosts with preconfigured standard checks ####
####                                                     ####
#### Author: Phil Connor                                 ####
#### Contact: contact@mylinux.work                       ####
#### License: MIT                                        ####
#### Version: 1.0                                        ####
####                                                     ####
#### Usage: ./nrpe-installer.sh [OPTIONS]                ####
#############################################################
#
# Supported operating systems:
#   - Ubuntu 20.04, 22.04, 24.04
#   - Debian 11, 12
#   - RHEL 8, 9
#   - Rocky Linux 8, 9
#   - Alma Linux 8, 9
#
# Standard checks configured:
#   - check_load         (CPU load: w:5,4,3  c:10,8,6)
#   - check_disk_root    (Root disk: w:20%   c:10%)
#   - check_swap         (Swap:      w:20%   c:10%)
#   - check_users        (Users:     w:5     c:10)
#   - check_total_procs  (Processes: w:250   c:400)
#   - check_zombie_procs (Zombies:   w:5     c:10)
#
set -euo pipefail

#########################
### Configuration ###
#########################

NAGIOS_SERVER=""
NRPE_PORT="${NRPE_PORT:-5666}"
INSTALL_METHOD="package"
NRPE_VERSION="${NRPE_VERSION:-4.1.3}"
PLUGINS_VERSION="${PLUGINS_VERSION:-2.4.12}"
PLUGIN_DIR=""
CONFIGURE_FIREWALL="${CONFIGURE_FIREWALL:-true}"
BUILD_DIR="/tmp/nrpe-build"

#########################
### Logging ###
#########################

RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'

log_info() {
    echo -e "${GREEN}[INFO]${NC} $1"
}

log_warn() {
    echo -e "${YELLOW}[WARN]${NC} $1"
}

log_error() {
    echo -e "${RED}[ERROR]${NC} $1" >&2
}

log_step() {
    echo -e "${BLUE}[STEP]${NC} $1"
}

#########################
### Parse Arguments ###
#########################

show_help() {
    cat <<EOF
NRPE Installer — Remote Host Setup

Installs the NRPE daemon and Nagios plugins on a remote host,
configures standard checks, firewall rules, and systemd service.

Usage: $0 [OPTIONS]

OPTIONS:
  --server IP            Nagios server IP address (required)
  --source               Install from source instead of packages
  --plugin-dir PATH      Custom plugin directory
  --port PORT            NRPE listen port (default: 5666)
  --nrpe-version VER     NRPE version for source install (default: $NRPE_VERSION)
  --plugins-version VER  Plugins version for source install (default: $PLUGINS_VERSION)
  --no-firewall          Skip firewall configuration
  --help                 Show this help

EXAMPLES:
  $0 --server 10.0.0.5
  $0 --server 10.0.0.5 --source
  $0 --server 10.0.0.5 --plugin-dir /usr/local/nagios/libexec
  $0 --server 10.0.0.5 --port 5666 --no-firewall

EOF
    exit 0
}

parse_args() {
    while [[ $# -gt 0 ]]; do
        case "$1" in
            --server)          NAGIOS_SERVER="$2"; shift 2 ;;
            --source)          INSTALL_METHOD="source"; shift ;;
            --plugin-dir)      PLUGIN_DIR="$2"; shift 2 ;;
            --port)            NRPE_PORT="$2"; shift 2 ;;
            --nrpe-version)    NRPE_VERSION="$2"; shift 2 ;;
            --plugins-version) PLUGINS_VERSION="$2"; shift 2 ;;
            --no-firewall)     CONFIGURE_FIREWALL="false"; shift ;;
            --help)            show_help ;;
            *)                 log_error "Unknown option: $1"; exit 1 ;;
        esac
    done

    if [[ -z "$NAGIOS_SERVER" ]]; then
        log_error "Missing required option: --server <IP>"
        echo "Run '$0 --help' for usage information."
        exit 1
    fi
}

#########################
### OS Detection ###
#########################

detect_os() {
    if [[ ! -f /etc/os-release ]]; then
        log_error "Cannot detect OS — /etc/os-release not found"
        exit 1
    fi

    # shellcheck disable=SC1091
    source /etc/os-release

    OS_ID="${ID,,}"
    OS_VERSION="${VERSION_ID%%.*}"

    case "$OS_ID" in
        ubuntu|debian)
            OS_FAMILY="debian"
            PKG_MGR="apt-get"
            ;;
        rhel|rocky|almalinux|centos)
            OS_FAMILY="rhel"
            PKG_MGR="dnf"
            ;;
        *)
            log_error "Unsupported OS: $OS_ID"
            exit 1
            ;;
    esac

    log_info "Detected OS: $PRETTY_NAME ($OS_FAMILY family)"
}

#########################
### Pre-flight ###
#########################

check_root() {
    if [[ $EUID -ne 0 ]]; then
        log_error "This script must be run as root"
        exit 1
    fi
}

#########################
### Package Install ###
#########################

install_from_packages() {
    log_step "Installing NRPE and plugins from packages..."

    if [[ "$OS_FAMILY" == "debian" ]]; then
        apt-get update -qq
        DEBIAN_FRONTEND=noninteractive apt-get install -y -qq \
            nagios-nrpe-server nagios-plugins nagios-plugins-contrib
    else
        # Enable EPEL for NRPE packages
        $PKG_MGR install -y -q epel-release 2>/dev/null || true
        $PKG_MGR install -y -q nrpe nagios-plugins-all
    fi

    # Set plugin directory based on OS
    if [[ -z "$PLUGIN_DIR" ]]; then
        if [[ "$OS_FAMILY" == "debian" ]]; then
            PLUGIN_DIR="/usr/lib/nagios/plugins"
        else
            PLUGIN_DIR="/usr/lib64/nagios/plugins"
        fi
    fi

    log_info "NRPE and plugins installed from packages"
}

#########################
### Source Install ###
#########################

install_from_source() {
    log_step "Installing NRPE and plugins from source..."

    # Install build dependencies
    if [[ "$OS_FAMILY" == "debian" ]]; then
        apt-get update -qq
        DEBIAN_FRONTEND=noninteractive apt-get install -y -qq \
            autoconf gcc make wget libssl-dev
    else
        $PKG_MGR install -y -q autoconf gcc gcc-c++ make wget openssl-devel
    fi

    # Set plugin directory
    [[ -z "$PLUGIN_DIR" ]] && PLUGIN_DIR="/usr/local/nagios/libexec"

    # Create nagios user if needed
    if ! id nagios &>/dev/null; then
        useradd -r -s /bin/false nagios
        log_info "Created nagios user"
    fi

    mkdir -p "$BUILD_DIR"
    cd "$BUILD_DIR"

    # Compile Nagios Plugins
    log_info "Compiling Nagios Plugins $PLUGINS_VERSION..."
    local plugins_tar="nagios-plugins-${PLUGINS_VERSION}.tar.gz"
    local plugins_url="https://github.com/nagios-plugins/nagios-plugins/releases/download/release-${PLUGINS_VERSION}/${plugins_tar}"

    wget -q "$plugins_url" -O "$plugins_tar"
    tar xzf "$plugins_tar"
    cd "nagios-plugins-${PLUGINS_VERSION}"

    ./configure --with-nagios-user=nagios --with-nagios-group=nagios \
        > /dev/null 2>&1
    make > /dev/null 2>&1
    make install > /dev/null 2>&1

    cd "$BUILD_DIR"

    # Compile NRPE
    log_info "Compiling NRPE $NRPE_VERSION..."
    local nrpe_tar="nrpe-${NRPE_VERSION}.tar.gz"
    local nrpe_url="https://github.com/NagiosEnterprises/nrpe/releases/download/nrpe-${NRPE_VERSION}/${nrpe_tar}"

    wget -q "$nrpe_url" -O "$nrpe_tar"
    tar xzf "$nrpe_tar"
    cd "nrpe-${NRPE_VERSION}"

    ./configure --with-nagios-user=nagios --with-nagios-group=nagios \
        --enable-command-args > /dev/null 2>&1
    make all > /dev/null 2>&1
    make install > /dev/null 2>&1
    make install-config > /dev/null 2>&1
    make install-init > /dev/null 2>&1

    # Cleanup
    rm -rf "$BUILD_DIR"

    log_info "NRPE and plugins compiled and installed from source"
}

#########################
### Configure NRPE ###
#########################

configure_nrpe() {
    log_step "Configuring NRPE..."

    local nrpe_cfg
    if [[ "$INSTALL_METHOD" == "source" ]]; then
        nrpe_cfg="/usr/local/nagios/etc/nrpe.cfg"
    elif [[ "$OS_FAMILY" == "debian" ]]; then
        nrpe_cfg="/etc/nagios/nrpe.cfg"
    else
        nrpe_cfg="/etc/nagios/nrpe.cfg"
    fi

    # Backup existing config
    if [[ -f "$nrpe_cfg" ]]; then
        cp "$nrpe_cfg" "${nrpe_cfg}.bak.$(date +%Y%m%d%H%M%S)"
        log_info "Backed up existing config to ${nrpe_cfg}.bak.*"
    fi

    # Determine config include directory
    local nrpe_d
    nrpe_d="$(dirname "$nrpe_cfg")/nrpe.d"
    mkdir -p "$nrpe_d"

    # Update allowed_hosts
    if grep -q '^allowed_hosts=' "$nrpe_cfg" 2>/dev/null; then
        sed -i "s/^allowed_hosts=.*/allowed_hosts=127.0.0.1,::1,${NAGIOS_SERVER}/" "$nrpe_cfg"
    else
        echo "allowed_hosts=127.0.0.1,::1,${NAGIOS_SERVER}" >> "$nrpe_cfg"
    fi

    # Ensure include directory is set
    if ! grep -q "^include_dir=${nrpe_d}" "$nrpe_cfg" 2>/dev/null; then
        echo "include_dir=${nrpe_d}" >> "$nrpe_cfg"
    fi

    # Set port
    if grep -q '^server_port=' "$nrpe_cfg" 2>/dev/null; then
        sed -i "s/^server_port=.*/server_port=${NRPE_PORT}/" "$nrpe_cfg"
    fi

    # Enable command arguments
    if grep -q '^dont_blame_nrpe=' "$nrpe_cfg" 2>/dev/null; then
        sed -i 's/^dont_blame_nrpe=.*/dont_blame_nrpe=1/' "$nrpe_cfg"
    fi

    log_info "NRPE configured: allowed_hosts includes $NAGIOS_SERVER"
}

#########################
### Standard Checks ###
#########################

configure_checks() {
    log_step "Configuring standard check commands..."

    local nrpe_d
    if [[ "$INSTALL_METHOD" == "source" ]]; then
        nrpe_d="/usr/local/nagios/etc/nrpe.d"
    else
        nrpe_d="/etc/nagios/nrpe.d"
    fi

    mkdir -p "$nrpe_d"

    cat > "${nrpe_d}/standard-checks.cfg" <<CHECKS
# Standard NRPE check commands
# Generated by nrpe-installer.sh on $(date '+%Y-%m-%d %H:%M:%S')

# CPU load average (1/5/15 min)
command[check_load]=${PLUGIN_DIR}/check_load -w 5,4,3 -c 10,8,6

# Root filesystem usage
command[check_disk_root]=${PLUGIN_DIR}/check_disk -w 20% -c 10% -p /

# Swap usage
command[check_swap]=${PLUGIN_DIR}/check_swap -w 20% -c 10%

# Logged-in users
command[check_users]=${PLUGIN_DIR}/check_users -w 5 -c 10

# Total processes
command[check_total_procs]=${PLUGIN_DIR}/check_procs -w 250 -c 400

# Zombie processes
command[check_zombie_procs]=${PLUGIN_DIR}/check_procs -w 5 -c 10 -s Z
CHECKS

    log_info "Standard checks configured in ${nrpe_d}/standard-checks.cfg"
}

#########################
### Firewall ###
#########################

configure_firewall() {
    if [[ "$CONFIGURE_FIREWALL" != "true" ]]; then
        log_info "Skipping firewall configuration (--no-firewall)"
        return
    fi

    log_step "Configuring firewall rules..."

    if command -v ufw &>/dev/null && ufw status | grep -q "active"; then
        ufw allow from "$NAGIOS_SERVER" to any port "$NRPE_PORT" proto tcp comment "NRPE from Nagios server"
        log_info "UFW rule added: allow ${NAGIOS_SERVER} -> port ${NRPE_PORT}/tcp"
    elif command -v firewall-cmd &>/dev/null && systemctl is-active --quiet firewalld; then
        firewall-cmd --permanent --add-rich-rule="rule family=ipv4 source address=${NAGIOS_SERVER} port port=${NRPE_PORT} protocol=tcp accept"
        firewall-cmd --reload
        log_info "firewalld rule added: allow ${NAGIOS_SERVER} -> port ${NRPE_PORT}/tcp"
    else
        log_warn "No active firewall detected (ufw/firewalld) — skipping"
        log_warn "Ensure port ${NRPE_PORT}/tcp is open for ${NAGIOS_SERVER}"
    fi
}

#########################
### Systemd ###
#########################

setup_systemd() {
    log_step "Enabling and starting NRPE service..."

    local svc_name
    if [[ "$INSTALL_METHOD" == "source" ]]; then
        svc_name="nrpe"
    elif [[ "$OS_FAMILY" == "debian" ]]; then
        svc_name="nagios-nrpe-server"
    else
        svc_name="nrpe"
    fi

    systemctl daemon-reload
    systemctl enable "$svc_name"
    systemctl restart "$svc_name"

    if systemctl is-active --quiet "$svc_name"; then
        log_info "NRPE service is running"
    else
        log_error "NRPE service failed to start — check: journalctl -u $svc_name"
    fi
}

#########################
### Connectivity Test ###
#########################

test_connectivity() {
    log_step "Testing NRPE connectivity..."

    local check_nrpe_bin=""

    # Find check_nrpe binary
    for path in /usr/lib/nagios/plugins/check_nrpe /usr/lib64/nagios/plugins/check_nrpe /usr/local/nagios/libexec/check_nrpe; do
        if [[ -x "$path" ]]; then
            check_nrpe_bin="$path"
            break
        fi
    done

    if [[ -z "$check_nrpe_bin" ]]; then
        log_warn "check_nrpe not found — skipping connectivity test"
        log_warn "Test from your Nagios server with: check_nrpe -H $(hostname -I | awk '{print $1}')"
        return
    fi

    if "$check_nrpe_bin" -H 127.0.0.1 -p "$NRPE_PORT" &>/dev/null; then
        log_info "NRPE connectivity test passed (localhost:${NRPE_PORT})"
    else
        log_warn "NRPE connectivity test failed on localhost — service may still be starting"
    fi
}

#########################
### Summary ###
#########################

show_summary() {
    local ip
    ip=$(hostname -I 2>/dev/null | awk '{print $1}')
    [[ -z "$ip" ]] && ip="<host-ip>"

    echo ""
    echo "============================================="
    echo "  NRPE Installation Complete"
    echo "============================================="
    echo ""
    echo "  Install Method:   $INSTALL_METHOD"
    echo "  NRPE Port:        $NRPE_PORT"
    echo "  Nagios Server:    $NAGIOS_SERVER"
    echo "  Plugin Directory: $PLUGIN_DIR"
    echo ""
    echo "  Checks configured:"
    echo "    check_load         (w:5,4,3    c:10,8,6)"
    echo "    check_disk_root    (w:20%      c:10%)"
    echo "    check_swap         (w:20%      c:10%)"
    echo "    check_users        (w:5        c:10)"
    echo "    check_total_procs  (w:250      c:400)"
    echo "    check_zombie_procs (w:5        c:10)"
    echo ""
    echo "  Test from Nagios server:"
    echo "    check_nrpe -H ${ip}"
    echo "    check_nrpe -H ${ip} -c check_load"
    echo ""
    echo "  Custom checks: /etc/nagios/nrpe.d/"
    echo ""
    echo "============================================="
}

#########################
### Main ###
#########################

main() {
    parse_args "$@"
    check_root
    detect_os

    if [[ "$INSTALL_METHOD" == "source" ]]; then
        install_from_source
    else
        install_from_packages
    fi

    configure_nrpe
    configure_checks
    configure_firewall
    setup_systemd
    test_connectivity
    show_summary
}

main "$@"
