Compare commits
2 Commits
ac367a148a
...
68053c8ff0
| Author | SHA1 | Date | |
|---|---|---|---|
| 68053c8ff0 | |||
| 83a12f0423 |
178
deploy.py
Normal file
178
deploy.py
Normal file
@@ -0,0 +1,178 @@
|
||||
#!/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()
|
||||
|
||||
@@ -1,18 +1,19 @@
|
||||
# Block 1: Redirects all HTTP traffic to HTTPS
|
||||
server {
|
||||
listen 80;
|
||||
server_name notes.aaf.systems;
|
||||
# Redirect all HTTP traffic to HTTPS
|
||||
|
||||
# This redirect is managed by Certbot's --redirect flag,
|
||||
# but we include it for completeness.
|
||||
return 301 https://$host$request_uri;
|
||||
}
|
||||
|
||||
# Block 2: Handles the secure HTTPS traffic
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
server_name notes.aaf.systems;
|
||||
|
||||
# SSL Certificates (managed by Certbot)
|
||||
ssl_certificate /etc/letsencrypt/live/notes.aaf.systems/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/notes.aaf.systems/privkey.pem;
|
||||
|
||||
# --- This is the location block that was missing ---
|
||||
location / {
|
||||
proxy_pass http://100.93.165.98:3010;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
@@ -22,4 +23,11 @@ server {
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
}
|
||||
# --- End of location block ---
|
||||
|
||||
# SSL settings managed by Certbot
|
||||
ssl_certificate /etc/letsencrypt/live/git.aaf.systems/fullchain.pem; # managed by Certbot
|
||||
ssl_certificate_key /etc/letsencrypt/live/git.aaf.systems/privkey.pem; # managed by Certbot
|
||||
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
|
||||
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
|
||||
}
|
||||
@@ -1,20 +1,18 @@
|
||||
# Block 1: Redirects all HTTP traffic to HTTPS
|
||||
server {
|
||||
listen 80;
|
||||
server_name git.aaf.systems;
|
||||
# Redirect all HTTP traffic to HTTPS
|
||||
return 301 https://$host$request_uri;
|
||||
}
|
||||
|
||||
# Block 2: Handles the secure HTTPS traffic
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
server_name git.aaf.systems;
|
||||
|
||||
# SSL Certificates (managed by Certbot)
|
||||
ssl_certificate /etc/letsencrypt/live/git.aaf.systems/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/git.aaf.systems/privkey.pem;
|
||||
|
||||
location / {
|
||||
proxy_pass http://100.93.165.98:3000;
|
||||
# IMPORTANT: Replace with the correct Tailscale IP for your Gitea server
|
||||
proxy_pass http://<IP_OF_GITEA_SERVER>:3000;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
@@ -22,4 +20,10 @@ server {
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
}
|
||||
|
||||
# SSL settings managed by Certbot
|
||||
ssl_certificate /etc/letsencrypt/live/git.aaf.systems/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/git.aaf.systems/privkey.pem;
|
||||
include /etc/letsencrypt/options-ssl-nginx.conf;
|
||||
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
|
||||
}
|
||||
Reference in New Issue
Block a user