#!/usr/bin/env bash # install.sh # part of ssh-notify from server-toolset # 2025 © Yigid BALABAN # This script must be run as root. It installs the SSH login notification script, # example config, updates PAM, and installs a logrotate config in a transactional manner. set -euo pipefail # Ensure running as root if [[ "$(id -u)" -ne 0 ]]; then echo "Error: This script must be run as root." >&2 exit 1 fi # Create temporary directory for backups BACKUP_DIR="$(mktemp -d)" # Rollback function on error rollback() { echo "Error encountered. Rolling back changes..." >&2 [[ -f "$BACKUP_DIR/sshd.bak" ]] && mv "$BACKUP_DIR/sshd.bak" /etc/pam.d/sshd [[ -f "$BACKUP_DIR/ssh-notify.sh.bak" ]] && mv "$BACKUP_DIR/ssh-notify.sh.bak" /usr/local/sbin/ssh-notify.sh [[ -f "$BACKUP_DIR/config.conf.bak" ]] && mv "$BACKUP_DIR/config.conf.bak" /etc/ssh-notify/config.conf [[ -f "$BACKUP_DIR/ssh-notify.logrotate.bak" ]] && mv "$BACKUP_DIR/ssh-notify.logrotate.bak" /etc/logrotate.d/ssh-notify rm -rf "$BACKUP_DIR" exit 1 } trap rollback ERR trap 'rm -rf "$BACKUP_DIR"' EXIT # Determine script and config sources (relative to this install.sh) _project_root="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" SCRIPT_SRC="${_project_root}/ssh-notify.sh" CONF_SRC="${_project_root}/example.conf" LOGROTATE_SRC="${_project_root}/ssh-notify.logrotate" # Destinations SCRIPT_DEST="/usr/local/sbin/ssh-notify.sh" CONF_DIR="/etc/ssh-notify" CONF_DEST="${CONF_DIR}/config.conf" PAM_FILE="/etc/pam.d/sshd" LOGROTATE_FILE="/etc/logrotate.d/ssh-notify" # Step 1: Install the main script if [[ ! -f "$SCRIPT_SRC" ]]; then echo "Error: Source script not found at $SCRIPT_SRC" >&2 exit 1 fi if [[ -f "$SCRIPT_DEST" ]]; then cp "$SCRIPT_DEST" "$BACKUP_DIR/ssh-notify.sh.bak" fi install -o root -g root -m 700 "$SCRIPT_SRC" "$SCRIPT_DEST" echo "Installed script to $SCRIPT_DEST" # Step 2: Install the example configuration if [[ ! -f "$CONF_SRC" ]]; then echo "Error: Example config not found at $CONF_SRC" >&2 exit 1 fi mkdir -p "$CONF_DIR" && chmod 700 "$CONF_DIR" if [[ -f "$CONF_DEST" ]]; then cp "$CONF_DEST" "$BACKUP_DIR/config.conf.bak" fi install -o root -g root -m 600 "$CONF_SRC" "$CONF_DEST" echo "Installed config to $CONF_DEST" # Step 3: Update PAM configuration idempotently if [[ ! -f "$PAM_FILE" ]]; then echo "Error: PAM config file not found at $PAM_FILE" >&2 exit 1 fi cp "$PAM_FILE" "$BACKUP_DIR/sshd.bak" if ! grep -q "ssh-notify.sh" "$PAM_FILE"; then cat << 'EOF' >> "$PAM_FILE" # Send notification upon successful login (added by ssh-notify install.sh) session optional pam_exec.so seteuid /usr/local/sbin/ssh-notify.sh EOF echo "Appended PAM exec to $PAM_FILE" else echo "PAM already configured for ssh-notify" fi # Step 4: Install logrotate configuration if [[ -f $LOGROTATE_FILE ]]; then cp $LOGROTATE_FILE $BACKUP_DIR/ssh-notify.logrotate.bak fi install -o root -g root -m 644 $LOGROTATE_SRC $LOGROTATE_FILE echo Copied logrotate config to $LOGROTATE_FILE # Success message trap - ERR echo "Installation completed successfully." echo "Please edit the config file at $CONF_DEST and restart sshd service."