Hold Tight...

0 %
Warith AL Maawali
Driving cybersecurity excellence
Innovator behind Linux Kodachi
  • Residence:
    ::0
  • Uptime Binary:
    101110
  • Mantra:
    Innovate, Secure, Repeat
ONS
EEDS
NSSG
Visual basic
Gambas
PHP
Delphi
Bash
  • Cybersecurity
  • Generative AI
  • Cloud & Automation
  • Cryptocurrency

Effortlessly Secure Your Website with Let’s Encrypt SSL Automation

21/11/2024

Automate Apache SSL with Let’s Encrypt in Minutes

Securing your website with SSL certificates is essential to protect user data and enhance credibility. This Bash script simplifies the process of setting up Let’s Encrypt SSL certificates for Apache servers on Debian-based systems. Automate the entire lifecycle—from installation to renewal—and keep your website secure effortlessly.

What is Let’s Encrypt?

Let’s Encrypt is a free, automated Certificate Authority (CA) that enables HTTPS by issuing SSL/TLS certificates. It eliminates manual configuration and ensures your website remains secure with automatic renewals.

Key Features of the Script

  • Automates Apache Setup: Installs and configures Apache if it’s missing.
  • Installs Certbot: Handles the Let’s Encrypt client setup for certificate management.
  • Wildcard SSL Support: Secures your domain and all its subdomains.
  • DNS Validation: Guides you in adding TXT records for secure validation.
  • Automatic Renewals: Sets up cron jobs to renew certificates seamlessly.

How It Works

  1. Checks Apache and Certbot:
  • Ensures Apache is installed and running.
  • Installs Certbot for Let’s Encrypt integration.
  1. Configures Apache:
  • Sets up virtual hosts for both HTTP and HTTPS.
  • Redirects traffic from HTTP to HTTPS when certificates are available.
  1. Secures Your Domain:
  • Guides you through DNS validation for wildcard SSL certificates.
  • Uses Certbot to obtain and install the certificates.
  1. Sets Up Automatic Renewals:
  • Creates a cron job to renew certificates before they expire.
  • Reloads Apache to apply renewed certificates.

Quick Start

  1. Download and Make Executable:
   chmod +x lets-encrypt-setup.sh
  1. Run the Script:
   sudo ./lets-encrypt-setup.sh
  1. Follow Prompts:
  • Add DNS TXT records for validation.
  • Let the script configure Apache and install certificates automatically.
  1. Enjoy HTTPS:
  • Your domain and subdomains are now secured.
  • Automatic renewals ensure continuous protection.

Benefits

  • Time-Saving: Automates tedious SSL setup and renewal tasks.
  • Enhanced Security: Ensures your site is always encrypted.
  • Scalable: Ideal for managing multiple domains.
  • Reliable: Reduces errors with a streamlined, automated approach.

Conclusion

This Bash script makes securing your website with Let’s Encrypt SSL certificates a breeze. It handles setup, configuration, and renewals, leaving you with more time to focus on what matters most. Secure your site today and enjoy the benefits of effortless automation.

ShellScript
#!/bin/bash
# =========================================
# Let's Encrypt Setup Script
# =========================================
#
# Version: 1.0.0
# Author: Warith AL Maawali
#
# Contact:
# - Discord: https://discord.gg/KEFErEx
# - Twitter: http://twitter.com/warith2020
# - LinkedIn: http://www.linkedin.com/in/warith1977
# - Website: https://www.digi77.com
#
# Copyright (c) 2024 Warith AL Maawali
#
# Description:
# This script automates the setup and configuration of Let's Encrypt SSL certificates
# for Apache web servers on Kodachi VPS instances. It performs the following tasks:
# - Installs and configures Apache web server
# - Installs Certbot and its dependencies
# - Obtains and configures SSL certificates
# - Sets up automatic certificate renewal
# - Configures Apache virtual hosts
#
# License:
# Dual-licensed under:
# 1. Apache License 2.0 (personal, non-commercial use)
# 2. Commercial license (for corporate/organizational use)
# Contact author for commercial licensing details.
#
# Usage:
# sudo ./lets-encrypt-setup.sh
#
# Requirements:
# - Debian-based Linux distribution
# - Root/sudo privileges
# - Active internet connection
# - Domain name with DNS access
# - Apache web server
# =========================================

# Define script variables
DOMAIN="yourdomain.com"                                              # Domain name to secure
EMAIL="youremail@gmail.com"                                          # Contact email for Let's Encrypt
CLOUDFLARE_DNS="1.1.1.1"                                            # Primary DNS resolver
GOOGLE_DNS="8.8.8.8"                                                # Backup DNS resolver
CERTBOT_PATH="/usr/bin/certbot"                                     # Path to certbot executable
APACHE_CONFIG="/etc/apache2/sites-available/${DOMAIN}.conf"         # Apache vhost config location
RENEW_HOOK="/etc/letsencrypt/renewal-hooks/deploy/reload-apache.sh" # Renewal hook script path
CRON_JOB="/etc/cron.d/letsencrypt-renew"                            # Auto-renewal cron job path
CERT_PATH="/etc/letsencrypt/live/$DOMAIN"                           # SSL certificate storage path
VALIDATION_STRING=""                                                # DNS validation string

# Display current DNS TXT records for domain validation
echo "Current TXT records for _acme-challenge.$DOMAIN:"
# Try Cloudflare DNS first, fallback to Google DNS if it fails
dig +short -t TXT "_acme-challenge.$DOMAIN" @$CLOUDFLARE_DNS ||
  dig +short -t TXT "_acme-challenge.$DOMAIN" @$GOOGLE_DNS ||
  echo "No TXT records found"
echo "----------------------------------------"

# Function to verify and install Apache if needed
check_apache() {
  if ! [ -x "$(command -v apache2)" ]; then
    echo "Apache is not installed. Installing it now..."
    apt update
    apt install -y apache2
    systemctl enable apache2
    systemctl start apache2
  else
    echo "Apache is already installed."
  fi
}

# Function to install Certbot and its Apache plugin
install_certbot() {
  echo "Installing Certbot and dependencies..."
  apt update
  apt install -y certbot python3-certbot-apache
  if [ $? -eq 0 ]; then
    echo "Certbot successfully installed."
  else
    echo "Error installing Certbot. Please check your system configuration."
    exit 1
  fi
}

# Function to verify Certbot installation
check_certbot_installed() {
  if ! [ -x "$(command -v $CERTBOT_PATH)" ]; then
    echo "Certbot is not installed. Installing it now..."
    install_certbot
  else
    echo "Certbot is already installed."
  fi
}

# Function to configure Apache virtual host with SSL support
configure_apache() {
  # Check if SSL certificates exist
  if [ -d "$CERT_PATH" ] && [ -f "$CERT_PATH/fullchain.pem" ] && [ -f "$CERT_PATH/privkey.pem" ]; then
    # Configure HTTPS with SSL certificates
    echo "SSL certificates found, configuring Apache with HTTPS..."
    cat >"$APACHE_CONFIG" <<EOF
<VirtualHost *:80>
    ServerName $DOMAIN
    ServerAlias *.$DOMAIN
    DocumentRoot /var/www/html
    ErrorLog \${APACHE_LOG_DIR}/error.log
    CustomLog \${APACHE_LOG_DIR}/access.log combined

    # Redirect all HTTP traffic to HTTPS
    Redirect permanent / https://$DOMAIN/
</VirtualHost>

<VirtualHost *:443>
    ServerName $DOMAIN
    ServerAlias *.$DOMAIN
    DocumentRoot /var/www/html

    # SSL Configuration
    SSLEngine on
    SSLCertificateFile /etc/letsencrypt/live/$DOMAIN/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/$DOMAIN/privkey.pem

    # Logging Configuration
    ErrorLog \${APACHE_LOG_DIR}/error.log
    CustomLog \${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
EOF
    a2ensite "${DOMAIN}.conf"
    a2enmod ssl
  else
    # Configure HTTP-only virtual host
    echo "SSL certificates not found, configuring Apache for HTTP only..."
    cat >"$APACHE_CONFIG" <<EOF
<VirtualHost *:80>
    ServerName $DOMAIN
    ServerAlias *.$DOMAIN
    DocumentRoot /var/www/html
    ErrorLog \${APACHE_LOG_DIR}/error.log
    CustomLog \${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
EOF
    a2ensite "${DOMAIN}.conf"
  fi

  # Validate and reload Apache configuration
  if apachectl configtest; then
    systemctl reload apache2
    echo "Apache configuration updated successfully"
  else
    echo "Error in Apache configuration. Please check the syntax."
    exit 1
  fi
}

# Function to generate DNS validation string
generate_validation() {
  VALIDATION_STRING=$(openssl rand -hex 32)
  echo "Please add this DNS TXT record:"
  echo "Record Name: _acme-challenge.$DOMAIN"
  echo "Record Value: $VALIDATION_STRING"
}

# Function to verify DNS record propagation
verify_dns_record() {
  local attempt=1
  local max_attempts=12 # 2 minute timeout (12 attempts * 10 seconds)

  while [ $attempt -le $max_attempts ]; do
    # Check both Cloudflare and Google DNS for record propagation
    if dig +short -t TXT "_acme-challenge.$DOMAIN" @$CLOUDFLARE_DNS | grep -q "$VALIDATION_STRING" ||
      dig +short -t TXT "_acme-challenge.$DOMAIN" @$GOOGLE_DNS | grep -q "$VALIDATION_STRING"; then
      echo "DNS record verified successfully!"
      return 0
    fi
    echo "Attempt $attempt of $max_attempts: DNS record not found yet. Waiting 10 seconds..."
    echo "Found TXT record (Cloudflare): $(dig +short -t TXT "_acme-challenge.$DOMAIN" @$CLOUDFLARE_DNS)"
    echo "Found TXT record (Google): $(dig +short -t TXT "_acme-challenge.$DOMAIN" @$GOOGLE_DNS)"
    echo "Expected TXT record: $VALIDATION_STRING"
    sleep 10
    attempt=$((attempt + 1))
  done

  echo "Could not verify DNS record after $max_attempts attempts."
  return 1
}

# Function to obtain SSL certificate using DNS validation
obtain_certificate() {
  echo "Starting DNS validation process for $DOMAIN..."

  # Generate and verify DNS record
  generate_validation

  # Wait for user to add DNS record and verify
  while true; do
    read -p "Have you added the DNS TXT record? (yes/no): " response
    if [ "$response" = "yes" ]; then
      if verify_dns_record; then
        break
      fi
    elif [ "$response" = "no" ]; then
      echo "Please add the DNS record and try again."
    else
      echo "Please answer 'yes' or 'no'"
    fi
  done

  # Request certificate from Let's Encrypt
  echo "DNS verified! Running certbot to obtain certificate..."

  $CERTBOT_PATH certonly \
    --manual \
    --preferred-challenges dns-01 \
    --agree-tos \
    --email "$EMAIL" \
    --domains "$DOMAIN,*.${DOMAIN}" \
    --manual-public-ip-logging-ok \
    --force-interactive

  # Verify certificate creation and configure Apache
  if [ -d "$CERT_PATH" ]; then
    echo "Wildcard certificate successfully obtained."
    configure_apache
  else
    echo "Error obtaining certificate. Check logs for details."
    exit 1
  fi
}

# Function to configure automatic certificate renewal
setup_auto_renew() {
  echo "Setting up auto-renewal..."

  # Create renewal hook directory and script
  mkdir -p /etc/letsencrypt/renewal-hooks/deploy
  cat >"$RENEW_HOOK" <<EOF
#!/bin/bash
systemctl reload apache2
EOF
  chmod +x "$RENEW_HOOK"

  # Configure cron job for automatic renewal
  echo "0 3 * * * root $CERTBOT_PATH renew --deploy-hook $RENEW_HOOK" >$CRON_JOB
  chmod 644 $CRON_JOB
  echo "Auto-renewal configured."
}

# Main script execution
echo "Starting Let's Encrypt wildcard certificate setup for $DOMAIN..."
check_apache
check_certbot_installed
configure_apache
echo "Obtaining Let's Encrypt wildcard SSL certificate for $DOMAIN..."
echo "Saving debug log to /var/log/letsencrypt/letsencrypt.log"
echo "Requesting a certificate for $DOMAIN and *.$DOMAIN"
obtain_certificate
setup_auto_renew

# Display completion message and verify renewal configuration
echo "Setup complete! Your domain $DOMAIN and all subdomains are now secured with Let's Encrypt SSL."
echo "Wildcard certificate will auto-renew before expiration."

echo -e "\nVerifying auto-renewal configuration:"
if [ -f "$CRON_JOB" ]; then
  echo "Auto-renewal cron job is configured as follows:"
  cat "$CRON_JOB"
else
  echo "Warning: Auto-renewal cron job file not found at $CRON_JOB"
fi
ShellScript
Posted in Tech BlogTags:
© 2024 Warith AL Maawali. All Rights Reserved.
Stay Secure, Stay Assured.