diff --git a/scripts/setup_periodic_system.sh b/scripts/setup_periodic_system.sh index 21151b4..360b14b 100755 --- a/scripts/setup_periodic_system.sh +++ b/scripts/setup_periodic_system.sh @@ -68,6 +68,21 @@ echo "Pacman wrapper script: $PACMAN_WRAPPER_SCRIPT" echo "Pacman wrapper installer: $PACMAN_WRAPPER_INSTALL" echo "Hosts install script: $HOSTS_INSTALL_SCRIPT" +# Templates directory (version-controlled files) +TEMPLATES_BASE="$CONFIG_DIR/scripts/system-maintenance" +BIN_TEMPLATES="$TEMPLATES_BASE/bin" +SYSTEMD_TEMPLATES="$TEMPLATES_BASE/systemd" +LOGROTATE_TEMPLATES="$TEMPLATES_BASE/logrotate" + +# Template files +TEMPLATE_MAINT_SCRIPT="$BIN_TEMPLATES/periodic-system-maintenance.sh" +TEMPLATE_HOSTS_MONITOR="$BIN_TEMPLATES/hosts-file-monitor.sh" +TEMPLATE_SVC_MAINT="$SYSTEMD_TEMPLATES/periodic-system-maintenance.service" +TEMPLATE_TIMER="$SYSTEMD_TEMPLATES/periodic-system-maintenance.timer" +TEMPLATE_STARTUP="$SYSTEMD_TEMPLATES/periodic-system-startup.service" +TEMPLATE_HOSTS_SVC="$SYSTEMD_TEMPLATES/hosts-file-monitor.service" +TEMPLATE_LOGROTATE="$LOGROTATE_TEMPLATES/periodic-system-maintenance" + # Function to verify required files exist verify_files() { echo "" @@ -88,6 +103,20 @@ verify_files() { missing_files+=("$HOSTS_INSTALL_SCRIPT") fi + # Check template files as well + for tmpl in \ + "$TEMPLATE_MAINT_SCRIPT" \ + "$TEMPLATE_HOSTS_MONITOR" \ + "$TEMPLATE_SVC_MAINT" \ + "$TEMPLATE_TIMER" \ + "$TEMPLATE_STARTUP" \ + "$TEMPLATE_HOSTS_SVC" \ + "$TEMPLATE_LOGROTATE"; do + if [[ ! -f "$tmpl" ]]; then + missing_files+=("$tmpl") + fi + done + if [[ ${#missing_files[@]} -gt 0 ]]; then echo "Error: The following required files are missing:" for file in "${missing_files[@]}"; do @@ -106,59 +135,15 @@ create_execution_script() { echo "=======================================" local exec_script="/usr/local/bin/periodic-system-maintenance.sh" - - cat > "$exec_script" << EOF -#!/bin/bash -# Periodic system maintenance script -# Installs pacman wrapper and updates hosts file -# Created by setup_periodic_system.sh on $(date) -set -e - -LOG_FILE="/var/log/periodic-system-maintenance.log" - -# Function to log with timestamp -log_message() { - echo "\$(date '+%Y-%m-%d %H:%M:%S') - \$1" >> "\$LOG_FILE" -} - -# Function to execute with logging -execute_with_log() { - local script_path="\$1" - local script_name="\$2" - - log_message "Starting \$script_name" - echo "Executing \$script_name..." >&2 - - if [[ -f "\$script_path" ]]; then - if bash "\$script_path" >> "\$LOG_FILE" 2>&1; then - log_message "\$script_name completed successfully" - echo "✓ \$script_name completed successfully" >&2 - else - log_message "\$script_name failed with exit code \$?" - echo "✗ \$script_name failed" >&2 - fi - else - log_message "\$script_name not found at \$script_path" - echo "✗ \$script_name not found at \$script_path" >&2 - fi -} - -# Start maintenance -log_message "=== Periodic System Maintenance Started ===" - -# Install pacman wrapper -execute_with_log "$PACMAN_WRAPPER_INSTALL" "Pacman Wrapper Installation" - -# Update hosts file -execute_with_log "$HOSTS_INSTALL_SCRIPT" "Hosts File Update" - -log_message "=== Periodic System Maintenance Completed ===" -echo "Periodic system maintenance completed. Check $LOG_FILE for details." >&2 -EOF + # Install from template with path substitutions + sed \ + -e "s|__PACMAN_WRAPPER_INSTALL__|$PACMAN_WRAPPER_INSTALL|g" \ + -e "s|__HOSTS_INSTALL_SCRIPT__|$HOSTS_INSTALL_SCRIPT|g" \ + "$TEMPLATE_MAINT_SCRIPT" > "$exec_script" chmod +x "$exec_script" - echo "✓ Created execution script: $exec_script" + echo "✓ Installed execution script from template: $exec_script" } # Function to create systemd service @@ -168,32 +153,8 @@ create_systemd_service() { echo "=============================" local service_file="/etc/systemd/system/periodic-system-maintenance.service" - - cat > "$service_file" << EOF -[Unit] -Description=Periodic System Maintenance (Pacman Wrapper & Hosts File) -After=network-online.target -Wants=network-online.target - -[Service] -Type=oneshot -User=root -ExecStart=/usr/local/bin/periodic-system-maintenance.sh -StandardOutput=journal -StandardError=journal - -# Timeout settings -TimeoutStartSec=300 -TimeoutStopSec=30 - -# Restart settings -Restart=no - -[Install] -WantedBy=multi-user.target -EOF - - echo "✓ Created systemd service: $service_file" + install -m 0644 "$TEMPLATE_SVC_MAINT" "$service_file" + echo "✓ Installed systemd service from template: $service_file" } # Function to create systemd timer for hourly execution @@ -203,27 +164,8 @@ create_systemd_timer() { echo "============================" local timer_file="/etc/systemd/system/periodic-system-maintenance.timer" - - cat > "$timer_file" << EOF -[Unit] -Description=Run Periodic System Maintenance every hour -Requires=periodic-system-maintenance.service - -[Timer] -# Run every hour -OnCalendar=hourly -# Run on system startup (5 minutes after boot) -OnBootSec=5min -# Add randomization to prevent all systems from running simultaneously -RandomizedDelaySec=300 -# Ensure timer persists across reboots -Persistent=true - -[Install] -WantedBy=timers.target -EOF - - echo "✓ Created systemd timer: $timer_file" + install -m 0644 "$TEMPLATE_TIMER" "$timer_file" + echo "✓ Installed systemd timer from template: $timer_file" } # Function to create startup service (additional to timer) @@ -233,30 +175,8 @@ create_startup_service() { echo "==============================" local startup_service="/etc/systemd/system/periodic-system-startup.service" - - cat > "$startup_service" << EOF -[Unit] -Description=System Maintenance on Startup (Pacman Wrapper & Hosts File) -After=network-online.target systemd-resolved.service -Wants=network-online.target - -[Service] -Type=oneshot -User=root -ExecStart=/usr/local/bin/periodic-system-maintenance.sh -StandardOutput=journal -StandardError=journal -RemainAfterExit=yes - -# Timeout settings -TimeoutStartSec=300 -TimeoutStopSec=30 - -[Install] -WantedBy=multi-user.target -EOF - - echo "✓ Created startup service: $startup_service" + install -m 0644 "$TEMPLATE_STARTUP" "$startup_service" + echo "✓ Installed startup service from template: $startup_service" } # Function to create hosts file monitor service @@ -267,154 +187,16 @@ create_hosts_monitor_service() { local monitor_script="/usr/local/bin/hosts-file-monitor.sh" local monitor_service="/etc/systemd/system/hosts-file-monitor.service" - - # Create the monitor script - cat > "$monitor_script" << EOF -#!/bin/bash -# Hosts file monitor script -# Watches /etc/hosts for changes and restores it if needed -# Created by setup_periodic_system.sh on $(date) - -LOG_FILE="/var/log/hosts-file-monitor.log" -HOSTS_FILE="/etc/hosts" -HOSTS_INSTALL_SCRIPT="$HOSTS_INSTALL_SCRIPT" - -# Function to log with timestamp -log_message() { - echo "\$(date '+%Y-%m-%d %H:%M:%S') - \$1" >> "\$LOG_FILE" - echo "\$(date '+%Y-%m-%d %H:%M:%S') - \$1" >&2 -} - -# Function to check if hosts file needs restoration -needs_restoration() { - # Check if file exists - if [[ ! -f "\$HOSTS_FILE" ]]; then - return 0 # File missing, needs restoration - fi - - # Check if file is empty or too small (less than 1000 lines indicates tampering) - local line_count=\$(wc -l < "\$HOSTS_FILE" 2>/dev/null || echo "0") - if [[ \$line_count -lt 1000 ]]; then - return 0 # File too small, likely tampered with - fi - - # Check if our custom entries are missing - if ! grep -q "Custom blocking entries" "\$HOSTS_FILE" 2>/dev/null; then - return 0 # Our custom entries missing, needs restoration - fi - - # Check if StevenBlack entries are missing - if ! grep -q "StevenBlack" "\$HOSTS_FILE" 2>/dev/null; then - return 0 # StevenBlack entries missing, needs restoration - fi - - return 1 # File seems intact -} - -# Function to restore hosts file -restore_hosts_file() { - log_message "Hosts file modification detected - initiating restoration" - - if [[ -f "\$HOSTS_INSTALL_SCRIPT" ]]; then - log_message "Running hosts installation script: \$HOSTS_INSTALL_SCRIPT" - - if bash "\$HOSTS_INSTALL_SCRIPT" >> "\$LOG_FILE" 2>&1; then - log_message "Hosts file restoration completed successfully" - else - log_message "Hosts file restoration failed with exit code \$?" - fi - else - log_message "ERROR: Hosts install script not found at \$HOSTS_INSTALL_SCRIPT" - fi -} - -# Function to monitor with inotifywait -monitor_with_inotify() { - log_message "Starting hosts file monitoring with inotify" - - # Monitor the hosts file and its directory for various events - inotifywait -m -e delete,move,modify,attrib,create --format '%w%f %e %T' --timefmt '%Y-%m-%d %H:%M:%S' "\$HOSTS_FILE" /etc/ 2>/dev/null | \ - while read file event time; do - # Check if the event is related to our hosts file - if [[ "\$file" == "\$HOSTS_FILE" ]] || [[ "\$file" == "/etc/hosts" ]]; then - log_message "Event detected: \$event on \$file at \$time" - - # Small delay to avoid rapid-fire events - sleep 2 - - # Check if restoration is needed - if needs_restoration; then - restore_hosts_file - else - log_message "Hosts file check passed - no restoration needed" - fi - fi - done -} - -# Function to monitor with polling (fallback) -monitor_with_polling() { - log_message "Starting hosts file monitoring with polling (fallback method)" - - while true; do - if needs_restoration; then - restore_hosts_file - fi - - # Check every 30 seconds - sleep 30 - done -} - -# Main execution -log_message "=== Hosts File Monitor Started ===" - -# Check if inotify-tools is available -if command -v inotifywait >/dev/null 2>&1; then - log_message "Using inotify for file monitoring" - monitor_with_inotify -else - log_message "inotify-tools not available, using polling method" - log_message "Consider installing inotify-tools for better performance: pacman -S inotify-tools" - monitor_with_polling -fi -EOF + # Install the monitor script from template with substitution + sed -e "s|__HOSTS_INSTALL_SCRIPT__|$HOSTS_INSTALL_SCRIPT|g" \ + "$TEMPLATE_HOSTS_MONITOR" > "$monitor_script" chmod +x "$monitor_script" - echo "✓ Created hosts monitor script: $monitor_script" - - # Create the systemd service - cat > "$monitor_service" << EOF -[Unit] -Description=Hosts File Monitor and Auto-Restore Service -After=network-online.target -Wants=network-online.target + echo "✓ Installed hosts monitor script from template: $monitor_script" -[Service] -Type=simple -User=root -ExecStart=$monitor_script -Restart=always -RestartSec=10 -StandardOutput=journal -StandardError=journal - -# Environment -Environment=PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin - -# Security settings -NoNewPrivileges=false -PrivateTmp=true - -# Resource limits -MemoryLimit=50M -CPUQuota=10% - -[Install] -WantedBy=multi-user.target -EOF - - echo "✓ Created hosts monitor service: $monitor_service" + # Install the systemd service from template + install -m 0644 "$TEMPLATE_HOSTS_SVC" "$monitor_service" + echo "✓ Installed hosts monitor service from template: $monitor_service" } # Function to enable and start services @@ -462,36 +244,8 @@ create_log_rotation() { echo "=============================" local logrotate_conf="/etc/logrotate.d/periodic-system-maintenance" - - cat > "$logrotate_conf" << EOF -/var/log/periodic-system-maintenance.log { - weekly - rotate 4 - compress - delaycompress - missingok - notifempty - create 644 root root - postrotate - systemctl reload-or-restart rsyslog > /dev/null 2>&1 || true - endscript -} - -/var/log/hosts-file-monitor.log { - weekly - rotate 4 - compress - delaycompress - missingok - notifempty - create 644 root root - postrotate - systemctl reload-or-restart rsyslog > /dev/null 2>&1 || true - endscript -} -EOF - - echo "✓ Created log rotation configuration: $logrotate_conf" + install -m 0644 "$TEMPLATE_LOGROTATE" "$logrotate_conf" + echo "✓ Installed log rotation configuration from template: $logrotate_conf" } # Function to run initial execution diff --git a/scripts/system-maintenance/bin/hosts-file-monitor.sh b/scripts/system-maintenance/bin/hosts-file-monitor.sh new file mode 100644 index 0000000..4cf3255 --- /dev/null +++ b/scripts/system-maintenance/bin/hosts-file-monitor.sh @@ -0,0 +1,110 @@ +#!/bin/bash +# Hosts file monitor script +# Watches /etc/hosts for changes and restores it if needed +# This file is installed by setup_periodic_system.sh + +set -euo pipefail + +LOG_FILE="/var/log/hosts-file-monitor.log" +HOSTS_FILE="/etc/hosts" +HOSTS_INSTALL_SCRIPT="__HOSTS_INSTALL_SCRIPT__" + +# Function to log with timestamp +log_message() { + echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE" >&2 +} + +# Function to check if hosts file needs restoration +needs_restoration() { + # Check if file exists + if [[ ! -f "$HOSTS_FILE" ]]; then + return 0 # File missing, needs restoration + fi + + # Check if file is empty or too small (less than 1000 lines indicates tampering) + local line_count + line_count=$(wc -l < "$HOSTS_FILE" 2>/dev/null || echo "0") + if [[ "$line_count" -lt 1000 ]]; then + return 0 # File too small, likely tampered with + fi + + # Check if our custom entries are missing + if ! grep -q "Custom blocking entries" "$HOSTS_FILE" 2>/dev/null; then + return 0 # Our custom entries missing, needs restoration + fi + + # Check if StevenBlack entries are missing + if ! grep -q "StevenBlack" "$HOSTS_FILE" 2>/dev/null; then + return 0 # StevenBlack entries missing, needs restoration + fi + + return 1 # File seems intact +} + +# Function to restore hosts file +restore_hosts_file() { + log_message "Hosts file modification detected - initiating restoration" + + if [[ -f "$HOSTS_INSTALL_SCRIPT" ]]; then + log_message "Running hosts installation script: $HOSTS_INSTALL_SCRIPT" + + if bash "$HOSTS_INSTALL_SCRIPT" >> "$LOG_FILE" 2>&1; then + log_message "Hosts file restoration completed successfully" + else + log_message "Hosts file restoration failed with exit code $?" + fi + else + log_message "ERROR: Hosts install script not found at $HOSTS_INSTALL_SCRIPT" + fi +} + +# Function to monitor with inotifywait +monitor_with_inotify() { + log_message "Starting hosts file monitoring with inotify" + + # Monitor the hosts file and its directory for various events + inotifywait -m -e delete,move,modify,attrib,create --format '%w%f %e %T' --timefmt '%Y-%m-%d %H:%M:%S' "$HOSTS_FILE" /etc/ 2>/dev/null | \ + while read -r file event time; do + # Check if the event is related to our hosts file + if [[ "$file" == "$HOSTS_FILE" ]] || [[ "$file" == "/etc/hosts" ]]; then + log_message "Event detected: $event on $file at $time" + + # Small delay to avoid rapid-fire events + sleep 2 + + # Check if restoration is needed + if needs_restoration; then + restore_hosts_file + else + log_message "Hosts file check passed - no restoration needed" + fi + fi + done +} + +# Function to monitor with polling (fallback) +monitor_with_polling() { + log_message "Starting hosts file monitoring with polling (fallback method)" + + while true; do + if needs_restoration; then + restore_hosts_file + fi + + # Check every 30 seconds + sleep 30 + done +} + +# Main execution +log_message "=== Hosts File Monitor Started ===" + +# Check if inotify-tools is available +if command -v inotifywait >/dev/null 2>&1; then + log_message "Using inotify for file monitoring" + monitor_with_inotify +else + log_message "inotify-tools not available, using polling method" + log_message "Consider installing inotify-tools for better performance: pacman -S inotify-tools" + monitor_with_polling +fi diff --git a/scripts/system-maintenance/bin/periodic-system-maintenance.sh b/scripts/system-maintenance/bin/periodic-system-maintenance.sh new file mode 100644 index 0000000..cd80264 --- /dev/null +++ b/scripts/system-maintenance/bin/periodic-system-maintenance.sh @@ -0,0 +1,52 @@ +#!/bin/bash +# Periodic system maintenance script +# Installs pacman wrapper and updates hosts file +# This file is installed by setup_periodic_system.sh + +set -e + +LOG_FILE="/var/log/periodic-system-maintenance.log" + +# Path placeholders replaced at install time +PACMAN_WRAPPER_INSTALL="__PACMAN_WRAPPER_INSTALL__" +HOSTS_INSTALL_SCRIPT="__HOSTS_INSTALL_SCRIPT__" + +# Function to log with timestamp +log_message() { + echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" >> "$LOG_FILE" +} + +# Function to execute with logging +execute_with_log() { + local script_path="$1" + local script_name="$2" + + log_message "Starting $script_name" + echo "Executing $script_name..." >&2 + + if [[ -f "$script_path" ]]; then + if bash "$script_path" >> "$LOG_FILE" 2>&1; then + log_message "$script_name completed successfully" + echo "✓ $script_name completed successfully" >&2 + else + local ec=$? + log_message "$script_name failed with exit code $ec" + echo "✗ $script_name failed (exit $ec)" >&2 + fi + else + log_message "$script_name not found at $script_path" + echo "✗ $script_name not found at $script_path" >&2 + fi +} + +# Start maintenance +log_message "=== Periodic System Maintenance Started ===" + +# Install pacman wrapper +execute_with_log "$PACMAN_WRAPPER_INSTALL" "Pacman Wrapper Installation" + +# Update hosts file +execute_with_log "$HOSTS_INSTALL_SCRIPT" "Hosts File Update" + +log_message "=== Periodic System Maintenance Completed ===" +echo "Periodic system maintenance completed. Check $LOG_FILE for details." >&2 diff --git a/scripts/system-maintenance/logrotate/periodic-system-maintenance b/scripts/system-maintenance/logrotate/periodic-system-maintenance new file mode 100644 index 0000000..d3fff40 --- /dev/null +++ b/scripts/system-maintenance/logrotate/periodic-system-maintenance @@ -0,0 +1,25 @@ +/var/log/periodic-system-maintenance.log { + weekly + rotate 4 + compress + delaycompress + missingok + notifempty + create 644 root root + postrotate + systemctl reload-or-restart rsyslog > /dev/null 2>&1 || true + endscript +} + +/var/log/hosts-file-monitor.log { + weekly + rotate 4 + compress + delaycompress + missingok + notifempty + create 644 root root + postrotate + systemctl reload-or-restart rsyslog > /dev/null 2>&1 || true + endscript +} diff --git a/scripts/system-maintenance/systemd/hosts-file-monitor.service b/scripts/system-maintenance/systemd/hosts-file-monitor.service new file mode 100644 index 0000000..4191b69 --- /dev/null +++ b/scripts/system-maintenance/systemd/hosts-file-monitor.service @@ -0,0 +1,27 @@ +[Unit] +Description=Hosts File Monitor and Auto-Restore Service +After=network-online.target +Wants=network-online.target + +[Service] +Type=simple +User=root +ExecStart=/usr/local/bin/hosts-file-monitor.sh +Restart=always +RestartSec=10 +StandardOutput=journal +StandardError=journal + +# Environment +Environment=PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin + +# Security settings +NoNewPrivileges=false +PrivateTmp=true + +# Resource limits +MemoryMax=50M +CPUQuota=10% + +[Install] +WantedBy=multi-user.target diff --git a/scripts/system-maintenance/systemd/periodic-system-maintenance.service b/scripts/system-maintenance/systemd/periodic-system-maintenance.service new file mode 100644 index 0000000..c39b87d --- /dev/null +++ b/scripts/system-maintenance/systemd/periodic-system-maintenance.service @@ -0,0 +1,21 @@ +[Unit] +Description=Periodic System Maintenance (Pacman Wrapper & Hosts File) +After=network-online.target +Wants=network-online.target + +[Service] +Type=oneshot +User=root +ExecStart=/usr/local/bin/periodic-system-maintenance.sh +StandardOutput=journal +StandardError=journal + +# Timeout settings +TimeoutStartSec=300 +TimeoutStopSec=30 + +# Restart settings +Restart=no + +[Install] +WantedBy=multi-user.target diff --git a/scripts/system-maintenance/systemd/periodic-system-maintenance.timer b/scripts/system-maintenance/systemd/periodic-system-maintenance.timer new file mode 100644 index 0000000..2b6ec16 --- /dev/null +++ b/scripts/system-maintenance/systemd/periodic-system-maintenance.timer @@ -0,0 +1,16 @@ +[Unit] +Description=Run Periodic System Maintenance every hour +Requires=periodic-system-maintenance.service + +[Timer] +# Run every hour +OnCalendar=hourly +# Run on system startup (5 minutes after boot) +OnBootSec=5min +# Add randomization to prevent all systems from running simultaneously +RandomizedDelaySec=300 +# Ensure timer persists across reboots +Persistent=true + +[Install] +WantedBy=timers.target diff --git a/scripts/system-maintenance/systemd/periodic-system-startup.service b/scripts/system-maintenance/systemd/periodic-system-startup.service new file mode 100644 index 0000000..b07bedd --- /dev/null +++ b/scripts/system-maintenance/systemd/periodic-system-startup.service @@ -0,0 +1,19 @@ +[Unit] +Description=System Maintenance on Startup (Pacman Wrapper & Hosts File) +After=network-online.target systemd-resolved.service +Wants=network-online.target + +[Service] +Type=oneshot +User=root +ExecStart=/usr/local/bin/periodic-system-maintenance.sh +StandardOutput=journal +StandardError=journal +RemainAfterExit=yes + +# Timeout settings +TimeoutStartSec=300 +TimeoutStopSec=30 + +[Install] +WantedBy=multi-user.target