#!/bin/bash # SSL Certificate Monitor Script # This script monitors SSL certificate expiration dates and sends alerts via Forward Email # Usage: Place in /usr/local/bin/ and add to crontab to run daily # Example crontab entry: 0 8 * * * /usr/local/bin/ssl_monitor.sh # Configuration EMAIL_TO="admin@yourdomain.com" EMAIL_FROM="ssl-alerts@yourdomain.com" FORWARD_EMAIL_API_KEY="your_api_key_here" # Get from https://forwardemail.net/my-account/security DOMAINS_FILE="/etc/ssl_monitor/domains.txt" # One domain per line WARNING_DAYS=30 # Send warning when certificate expires in less than this many days CRITICAL_DAYS=7 # Send critical alert when certificate expires in less than this many days LOG_FILE="/var/log/ssl_monitor.log" # Create config directory and domains file if they don't exist mkdir -p /etc/ssl_monitor if [ ! -f "$DOMAINS_FILE" ]; then echo "# Add domains to monitor, one per line" > "$DOMAINS_FILE" echo "example.com" >> "$DOMAINS_FILE" echo "mail.example.com" >> "$DOMAINS_FILE" fi # Function to send email via Forward Email HTTP API send_email_api() { local subject="$1" local body="$2" curl -X POST "https://api.forwardemail.net/v1/emails" \ -H "Content-Type: application/json" \ -u "$FORWARD_EMAIL_API_KEY:" \ -d '{ "from": "'"$EMAIL_FROM"'", "to": "'"$EMAIL_TO"'", "subject": "'"$subject"'", "html": "'"$body"'", "text": "'"$body"'" }' echo "Alert email sent via API at $(date)" >> "$LOG_FILE" } # Function to send email via sendmail (SMTP) send_email_smtp() { local subject="$1" local body="$2" echo -e "Subject: $subject\nFrom: $EMAIL_FROM\nTo: $EMAIL_TO\nContent-Type: text/html\n\n$body" | \ sendmail -t echo "Alert email sent via SMTP at $(date)" >> "$LOG_FILE" } # Function to check SSL certificate expiration check_certificate() { local domain="$1" local expiry_date="" local days_left=0 local status="OK" local error_message="" # Get certificate expiration date expiry_date=$(echo | openssl s_client -servername "$domain" -connect "$domain":443 2>/dev/null | \ openssl x509 -noout -enddate 2>/dev/null | \ sed -e 's/notAfter=//') if [ -z "$expiry_date" ]; then status="ERROR" error_message="Could not retrieve certificate for $domain" days_left=0 else # Convert expiry date to seconds since epoch expiry_seconds=$(date -d "$expiry_date" +%s) current_seconds=$(date +%s) # Calculate days left seconds_left=$((expiry_seconds - current_seconds)) days_left=$((seconds_left / 86400)) # Determine status if [ $days_left -lt $CRITICAL_DAYS ]; then status="CRITICAL" elif [ $days_left -lt $WARNING_DAYS ]; then status="WARNING" fi fi # Return results echo "$domain|$expiry_date|$days_left|$status|$error_message" } # Initialize HTML report HTML_REPORT="

SSL Certificate Monitoring Report

Date: $(date)

Server: $(hostname)

" # Check each domain ALERT_NEEDED=false while read -r domain || [ -n "$domain" ]; do # Skip comments and empty lines [[ "$domain" =~ ^#.*$ || -z "$domain" ]] && continue echo "Checking certificate for $domain..." >> "$LOG_FILE" # Get certificate info cert_info=$(check_certificate "$domain") # Parse results domain_name=$(echo "$cert_info" | cut -d'|' -f1) expiry_date=$(echo "$cert_info" | cut -d'|' -f2) days_left=$(echo "$cert_info" | cut -d'|' -f3) status=$(echo "$cert_info" | cut -d'|' -f4) error_message=$(echo "$cert_info" | cut -d'|' -f5) # Set row color based on status row_color="#ffffff" # Default white if [ "$status" = "WARNING" ]; then row_color="#fff3cd" # Light yellow ALERT_NEEDED=true elif [ "$status" = "CRITICAL" ]; then row_color="#f8d7da" # Light red ALERT_NEEDED=true elif [ "$status" = "ERROR" ]; then row_color="#f8d7da" # Light red ALERT_NEEDED=true fi # Add to HTML report HTML_REPORT+="" # Log results echo "$domain: $status - Expires: $expiry_date ($days_left days left)" >> "$LOG_FILE" if [ -n "$error_message" ]; then echo " Error: $error_message" >> "$LOG_FILE" fi done < "$DOMAINS_FILE" # Complete HTML report HTML_REPORT+="
Domain Expiry Date Days Left Status
$domain_name $expiry_date $days_left $status

This is an automated alert from your SSL certificate monitoring system.

Note: It is recommended to renew certificates at least 14 days before expiration.

Renewal Instructions:

  1. For Let's Encrypt certificates: Run certbot renew
  2. For other certificates: Contact your certificate provider or generate a new CSR
" # Send alert if needed if [ "$ALERT_NEEDED" = true ]; then EMAIL_SUBJECT="SSL Certificate Alert: $(hostname) - $(date +%Y-%m-%d)" # Uncomment one of these methods based on your preference: send_email_api "$EMAIL_SUBJECT" "$HTML_REPORT" # send_email_smtp "$EMAIL_SUBJECT" "$HTML_REPORT" echo "Alert sent due to expiring certificates" >> "$LOG_FILE" else echo "No alerts needed, all certificates are valid" >> "$LOG_FILE" fi exit 0