diff --git a/deploy.py b/deploy.py deleted file mode 100644 index bec0b56..0000000 --- a/deploy.py +++ /dev/null @@ -1,178 +0,0 @@ -#!/usr/bin/env python3 -# ============================================================================== -# NGINX CONFIG & SSL DEPLOYMENT SCRIPT (Python Version) -# -# This script follows a robust, idempotent deployment strategy. -# 1. It first ensures all required SSL certificates exist using Certbot. -# 2. It then deploys the perfected, local Nginx configurations. -# This prevents Certbot from ever creating a broken Nginx configuration. -# -# USAGE: -# 1. Ensure your local `sites-available` files are correct and complete. -# 2. Run the script: `python3 deploy_nginx.py` -# ============================================================================== - -import os -import subprocess -import sys -from pathlib import Path - -# --- Configuration --- -REMOTE_USER = "ubuntu" -REMOTE_HOST = "3.9.182.122" -CERTBOT_EMAIL = "azeem.fidahusein@gmail.com" - -# --- File & Path Definitions --- -# Using pathlib for robust path handling -KEY_FILE = Path.home() / "repos" / "azeem-macbookair.pem" -SOURCE_NGINX_CONF = Path("nginx.conf") -SOURCE_SITES_DIR = Path("sites-available") -DEST_NGINX_PATH = "/etc/nginx/" -DEST_SITES_PATH = "/etc/nginx/sites-available/" - -# --- Helper Functions --- - -def print_header(message): - """Prints a formatted header.""" - print("\n" + "=" * 60) - print(message) - print("=" * 60) - -def print_success(message): - """Prints a success message.""" - print(f"✅ {message}") - -def print_error(message): - """Prints an error message and exits.""" - print(f"❌ ERROR: {message}") - sys.exit(1) - -def run_command(command, shell=False): - """Runs a command, checks for errors, and returns the result.""" - try: - # Using shell=True for commands with pipes or redirects - result = subprocess.run( - command, - check=True, - capture_output=True, - text=True, - shell=shell - ) - return result - except subprocess.CalledProcessError as e: - print_error(f"Command failed with exit code {e.returncode}") - print(f"STDOUT: {e.stdout}") - print(f"STDERR: {e.stderr}") - - -def run_remote_command(ssh_command): - """Runs a command on the remote server via SSH.""" - base_command = ["ssh", "-i", str(KEY_FILE), f"{REMOTE_USER}@{REMOTE_HOST}"] - full_command = base_command + [ssh_command] - print(f" -> Running on remote: {' '.join(full_command)}") - run_command(full_command) - - -# --- Main Logic --- - -def main(): - """Main function to run the deployment process.""" - print_header(f"🚀 Starting NGINX & SSL deployment to {REMOTE_HOST}") - - # --- Pre-flight Checks --- - print("-> Performing pre-flight checks...") - if not KEY_FILE.is_file(): - print_error(f"SSH key not found at {KEY_FILE}") - if not SOURCE_NGINX_CONF.is_file(): - print_error(f"Source file '{SOURCE_NGINX_CONF}' not found.") - if not SOURCE_SITES_DIR.is_dir(): - print_error(f"Source directory '{SOURCE_SITES_DIR}' not found.") - print_success("Pre-flight checks passed.") - - # --- Local Operations --- - print("-> Collecting local configuration details...") - config_files = [f.name for f in SOURCE_SITES_DIR.iterdir() if f.is_file()] - if not config_files: - print_error("No configuration files found in 'sites-available' directory.") - print(f" -> Found site config files: {', '.join(config_files)}") - - # Find all unique domains for Certbot - all_domains_str = run_command( - f"grep -h -r 'server_name' {SOURCE_SITES_DIR} | sed 's/.*server_name\s*//' | sed 's/;//' | xargs -n1 | sort -u | tr '\\n' ' '", - shell=True - ).stdout.strip() - - if not all_domains_str: - print("⚠️ WARNING: No domains found. Skipping Certbot step later.") - all_domains_found = False - else: - print_success(f"Found domains for certificate check: {all_domains_str}") - all_domains_found = True - - # --- Remote Operations --- - - # Step 1: Ensure certificates exist BEFORE deploying configs - if all_domains_found: - print_header("Step 1: Running Certbot to Get/Renew Certificates") - certbot_domains = " ".join([f"-d {domain}" for domain in all_domains_str.split()]) - certbot_command = ( - f"sudo certbot certonly --nginx --non-interactive --agree-tos " - f"--email {CERTBOT_EMAIL} --expand {certbot_domains}" - ) - run_remote_command(certbot_command) - print_success("Certificate check complete.") - - # Step 2: Deploy the perfected configuration files - print_header("Step 2: Deploying Local Configurations") - remote_temp_dir = f"/home/{REMOTE_USER}/deploy_temp" - run_remote_command(f"mkdir -p {remote_temp_dir}") - - print(" -> Transferring files via scp...") - scp_command = [ - "scp", "-i", str(KEY_FILE), "-r", - str(SOURCE_NGINX_CONF), str(SOURCE_SITES_DIR), - f"{REMOTE_USER}@{REMOTE_HOST}:{remote_temp_dir}/" - ] - run_command(scp_command) - print_success("File transfer complete.") - - # Step 3: Move files, enable sites, and test - print_header("Step 3: Activating New Configuration on Server") - config_files_str = " ".join(config_files) - - # Using a multi-line f-string for the remote script - remote_script = f""" - echo " -> Moving files into place..."; - sudo mv {remote_temp_dir}/{SOURCE_NGINX_CONF.name} {DEST_NGINX_PATH}; - sudo mv {remote_temp_dir}/{SOURCE_SITES_DIR.name}/* {DEST_SITES_PATH}; - - echo " -> Checking and creating symbolic links..."; - for config_file in {config_files_str}; do - source_file="{DEST_SITES_PATH}${{config_file}}"; - link_file="/etc/nginx/sites-enabled/${{config_file}}"; - if [ ! -L "$link_file" ]; then - sudo ln -s "$source_file" "$link_file"; - echo " -> Link created for ${{config_file}}."; - else - echo " -> Link for ${{config_file}} already exists."; - fi; - done; - - rm -rf {remote_temp_dir}; - echo " -> Verifying final Nginx configuration..."; - sudo nginx -t; - """ - run_remote_command(remote_script) - print_success("Nginx configuration test passed.") - - # Step 4: Reload Nginx - print_header("Step 4: Reloading Nginx") - run_remote_command("sudo systemctl reload nginx") - print_success("Nginx reloaded successfully.") - - print_header("🎉 Deployment complete!") - - -if __name__ == "__main__": - main() - diff --git a/deploy.sh b/deploy.sh deleted file mode 100755 index 5c56bd1..0000000 --- a/deploy.sh +++ /dev/null @@ -1,156 +0,0 @@ -#!/bin/bash - -# ============================================================================== -# NGINX CONFIG & SSL DEPLOYMENT SCRIPT (v10) -# -# This script handles the "chicken-and-egg" problem of deploying a new site -# with SSL. It first deploys a temporary HTTP-only version of the site by -# commenting out the ENTIRE SSL server block, runs Certbot to acquire the -# certificate (which then automatically re-enables HTTPS), and reloads Nginx. -# -# INSTRUCTIONS: -# 1. Ensure Certbot is installed on the remote server. -# (e.g., `sudo apt install certbot python3-certbot-nginx`) -# 2. Make the script executable: chmod +x .sh -# 3. Run the script: ./.sh -# ============================================================================== - -# --- Configuration --- -REMOTE_USER="ubuntu" # The user you SSH in with (e.g., ubuntu, ec2-user) -REMOTE_HOST="3.9.182.122" # The IP address or domain of your server -CERTBOT_EMAIL="azeem.fidahusein@gmail.com" # Email for Let's Encrypt account - -# --- File & Path Definitions --- -KEY_FILE="~/repos/azeem-macbookair.pem" -SOURCE_NGINX_CONF="nginx.conf" -SOURCE_SITES_DIR="sites-available" - -# Destination paths on the remote server -DEST_NGINX_PATH="/etc/nginx/" -DEST_SITES_PATH="/etc/nginx/sites-available/" - -# Temporary directory on the remote server -REMOTE_TEMP_DIR="nginx_deploy_temp" - -# --- Script Logic --- - -echo "🚀 Starting NGINX & SSL deployment to $REMOTE_HOST..." -echo "--------------------------------------------------------" - -# Expand the tilde (~) in the key file path to an absolute path. -EVAL_KEY_FILE=$(eval echo "$KEY_FILE") - -# --- Pre-flight Checks --- -if [ ! -f "$EVAL_KEY_FILE" ]; then - echo "❌ ERROR: SSH key not found at $EVAL_KEY_FILE" - exit 1 -fi -if [ ! -f "$SOURCE_NGINX_CONF" ]; then - echo "❌ ERROR: Source file '$SOURCE_NGINX_CONF' not found." - exit 1 -fi -if [ ! -d "$SOURCE_SITES_DIR" ]; then - echo "❌ ERROR: Source directory '$SOURCE_SITES_DIR' not found." - exit 1 -fi - -# --- Local Operations --- -CONFIG_FILES=$(ls "$SOURCE_SITES_DIR" | tr '\n' ' ') -echo "-> Found site config files to process: $CONFIG_FILES" - -echo "-> Scanning local 'sites-available' for unique domain names..." -ALL_DOMAINS=$(grep -h -r "server_name" "$SOURCE_SITES_DIR" | sed 's/.*server_name\s*//' | sed 's/;//' | xargs -n1 | sort -u | tr '\n' ' ' | sed 's/ *$//') - -if [ -z "$ALL_DOMAINS" ]; then - echo "⚠️ WARNING: No domains found. Skipping Certbot step later." -else - echo " ✅ Found domains: $ALL_DOMAINS" -fi -echo - -# --- Remote Operations --- - -# Step 1: Transfer files to a temporary directory -echo "-> Creating temporary directory and transferring files..." -ssh -i "$EVAL_KEY_FILE" "${REMOTE_USER}@${REMOTE_HOST}" "mkdir -p $REMOTE_TEMP_DIR" -scp -i "$EVAL_KEY_FILE" -r "$SOURCE_NGINX_CONF" "$SOURCE_SITES_DIR" "${REMOTE_USER}@${REMOTE_HOST}:${REMOTE_TEMP_DIR}/" -if [ $? -ne 0 ]; then - echo "❌ ERROR: File transfer failed. Aborting." - exit 1 -fi -echo " ✅ All files successfully transferred to temporary location." -echo - -# Step 2: Move files, TEMPORARILY disable SSL blocks, enable sites, and reload Nginx -echo "- Moving files and enabling HTTP-only sites for Certbot validation..." -ssh -i "$EVAL_KEY_FILE" "${REMOTE_USER}@${REMOTE_HOST}" << EOF - # Move the main config file and site configs - sudo mv "$REMOTE_TEMP_DIR/nginx.conf" "${DEST_NGINX_PATH}nginx.conf" - sudo mv "$REMOTE_TEMP_DIR/sites-available/"* "$DEST_SITES_PATH" - - # --- NEW: Temporarily disable the entire SSL server block --- - echo " -> Temporarily commenting out SSL server blocks in configs..." - for CONFIG_FILE in $CONFIG_FILES - do - # Use awk to comment out the entire server block containing 'listen 443' - sudo awk '/server\s*{/{f=1} f && /listen\s+443/{p=1} f{b=b\$0"\\n"} /\s*}/ && f{f=0; if(!p){printf "%s", b} p=0; b=""}' "$DEST_SITES_PATH\$CONFIG_FILE" > "\$CONFIG_FILE.tmp" && sudo mv "\$CONFIG_FILE.tmp" "$DEST_SITES_PATH\$CONFIG_FILE" - done - # --- END NEW --- - - # Enable sites by creating symbolic links - echo " -> Checking and creating symbolic links in sites-enabled..." - for CONFIG_FILE in $CONFIG_FILES - do - SOURCE_FILE="/etc/nginx/sites-available/\$CONFIG_FILE" - LINK_FILE="/etc/nginx/sites-enabled/\$CONFIG_FILE" - if [ ! -L "\$LINK_FILE" ]; then - if [ -f "\$SOURCE_FILE" ]; then - echo " -> Creating link for \$CONFIG_FILE..." - sudo ln -s "\$SOURCE_FILE" "\$LINK_FILE" - fi - else - echo " -> Link for \$CONFIG_FILE already exists." - fi - done - - echo " -> Verifying and reloading Nginx for initial validation..." - sudo nginx -t && sudo systemctl reload nginx -EOF - -if [ $? -ne 0 ]; then - echo "⚠️ WARNING: An error occurred on the remote server during initial setup." - echo "This might happen if your base HTTP config is invalid. Please check manually." - exit 1 -fi -echo " ✅ Initial Nginx config loaded successfully." -echo - -# Step 3: Run Certbot to acquire certificates and update configs to HTTPS -if [ -n "$ALL_DOMAINS" ]; then - read -p "Run Certbot for the discovered domains? (y/n) " -n 1 -r - echo - if [[ $REPLY =~ ^[Yy]$ ]]; then - CERTBOT_DOMAINS=$(echo "$ALL_DOMAINS" | sed 's/ / -d /g' | sed 's/^/-d /') - - echo "- Running Certbot to acquire certificates and enable SSL..." - echo " Certbot will now automatically update your Nginx configs for HTTPS." - - ssh -t -i "$EVAL_KEY_FILE" "${REMOTE_USER}@${REMOTE_HOST}" \ - "sudo certbot --nginx --non-interactive --agree-tos --email $CERTBOT_EMAIL --redirect --expand $CERTBOT_DOMAINS" - - if [ $? -eq 0 ]; then - echo " ✅ Certbot process completed successfully." - else - echo "⚠️ WARNING: Certbot process finished with errors. Please check the logs on the server." - fi - fi -else - echo "-> Skipping Certbot step as no domains were found." -fi - -# Final cleanup -ssh -i "$EVAL_KEY_FILE" "${REMOTE_USER}@${REMOTE_HOST}" "rm -rf $REMOTE_TEMP_DIR" - -# --- Completion --- -echo "--------------------------------------------------------" -echo "🎉 Deployment complete!"