Skip to content

Instantly share code, notes, and snippets.

@iykex
Created January 12, 2025 00:04
Show Gist options
  • Save iykex/681d4b74cdd126b1b4d20540725fa780 to your computer and use it in GitHub Desktop.
Save iykex/681d4b74cdd126b1b4d20540725fa780 to your computer and use it in GitHub Desktop.
SSL Installer with Let's Encrypt - for your VPS/Server
#!/bin/bash
# Define colors for output
GREEN='\033[0;32m'
RED='\033[0;31m'
NC='\033[0m' # No Color
# Function to print status messages
log() {
echo -e "${GREEN}[+] $1${NC}"
}
error() {
echo -e "${RED}[!] $1${NC}"
exit 1
}
# Function to validate domain
validate_domain() {
if ! echo "$1" | grep -qP '(?=^.{4,253}$)(^(?:[a-zA-Z0-9](?:(?:[a-zA-Z0-9\-]){0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}$)'; then
return 1
fi
return 0
}
# Function to validate email
validate_email() {
if ! echo "$1" | grep -qP '^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'; then
return 1
fi
return 0
}
# Check if running as root
if [ "$EUID" -ne 0 ]; then
error "Please run as root (use sudo)"
fi
# Prompt for domain
while true; do
read -p "Enter your domain name (e.g., example.com): " DOMAIN
if validate_domain "$DOMAIN"; then
break
else
echo "Invalid domain format. Please try again."
fi
done
# Prompt for email
while true; do
read -p "Enter your email address: " EMAIL
if validate_email "$EMAIL"; then
break
else
echo "Invalid email format. Please try again."
fi
done
# Confirm inputs
echo -e "\nPlease confirm your inputs:"
echo "Domain: $DOMAIN"
echo "Email: $EMAIL"
read -p "Is this correct? (y/n): " confirmation
if [[ ! $confirmation =~ ^[Yy]$ ]]; then
error "Setup cancelled by user"
fi
# Install required packages
log "Installing required packages..."
apt-get update || error "Failed to update package lists"
apt-get install -y nginx certbot python3-certbot-nginx || error "Failed to install required packages"
# Obtain SSL certificate
log "Obtaining SSL certificate..."
certbot --nginx -d "$DOMAIN" --non-interactive --agree-tos --email "$EMAIL" || error "Failed to obtain SSL certificate"
# Setup auto-renewal checks
log "Setting up certificate auto-renewal..."
systemctl status certbot.timer
certbot renew --dry-run
# Create a systemd timer for more frequent checks
log "Creating systemd timer for renewal checks..."
cat > /etc/systemd/system/certbot-renewal.timer << EOF
[Unit]
Description=Twice daily renewal of Let's Encrypt's certificates
[Timer]
OnCalendar=0/12:00:00
RandomizedDelaySec=1h
Persistent=true
[Install]
WantedBy=timers.target
EOF
# Create the service file
log "Creating systemd service for renewal..."
cat > /etc/systemd/system/certbot-renewal.service << EOF
[Unit]
Description=Certbot Renewal
[Service]
Type=oneshot
ExecStart=/usr/bin/certbot renew --quiet --agree-tos
ExecStartPost=/bin/systemctl reload nginx
EOF
# Create better default page
log "Creating enhanced default page..."
cat > /var/www/html/index.nginx-debian.html << 'EOF'
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>LoL!</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
html {
height: 100%;
}
body {
margin: 0;
font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
background: #f5f5f3;
color: #2c2c2c;
line-height: 1.6;
}
.container {
padding: 3rem;
max-width: 600px;
text-align: center;
background: #ffffff;
border-radius: 12px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
}
h2 {
color: #333333;
font-size: 2rem;
font-weight: 600;
margin-bottom: 1.5rem;
letter-spacing: -0.02em;
}
p {
font-size: 1.1rem;
margin: 1rem 0;
color: #4a4a4a;
}
em {
color: #2d5ca5;
font-style: normal;
font-weight: 500;
}
@media (max-width: 600px) {
.container {
padding: 2rem;
margin: 1rem;
}
}
.status {
margin-top: 2rem;
padding: 1.5rem;
background: #fafafa;
border-radius: 8px;
font-size: 0.95rem;
}
.status p {
margin: 0;
color: #666666;
}
</style>
</head>
<body>
<div class="container">
<h2>Oh, Look Who's Here</h2>
<p>Congrats on finding this ghetto!<br>
Must be a hot day, huh?</p>
<p><em>Feel free to stay... or whatever.</em></p>
<div class="status">
<p>
⚡️ Surprisingly still working, huh?<br>
🔒 Secured (probably).<br>
✨ You're not a star, lol!
</p>
</div>
</div>
</body>
</html>
EOF
# Update nginx configuration
log "Updating nginx configuration..."
cat > "/etc/nginx/sites-available/$DOMAIN" << EOF
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name $DOMAIN;
ssl_certificate /etc/letsencrypt/live/$DOMAIN/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/$DOMAIN/privkey.pem;
root /var/www/html;
index index.html index.htm index.nginx-debian.html;
# Better error pages
error_page 403 /403.html;
error_page 404 /404.html;
error_page 500 502 503 504 /50x.html;
location / {
try_files \$uri \$uri/ =404;
}
# Security headers
add_header X-Frame-Options "SAMEORIGIN";
add_header X-XSS-Protection "1; mode=block";
add_header X-Content-Type-Options "nosniff";
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
# Enable gzip compression
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
}
server {
listen 80;
listen [::]:80;
server_name $DOMAIN;
return 301 https://\$server_name\$request_uri;
}
EOF
# Create symlink for nginx configuration
log "Creating symlink for nginx configuration..."
ln -sf "/etc/nginx/sites-available/$DOMAIN" "/etc/nginx/sites-enabled/"
# Remove default nginx configuration if it exists
if [ -f /etc/nginx/sites-enabled/default ]; then
log "Removing default nginx configuration..."
rm /etc/nginx/sites-enabled/default
fi
# Set proper permissions
log "Setting permissions..."
chown www-data:www-data /var/www/html/index.nginx-debian.html
chmod 644 /var/www/html/index.nginx-debian.html
# Reload systemd and enable services
log "Enabling and starting services..."
systemctl daemon-reload
systemctl enable certbot-renewal.timer
systemctl start certbot-renewal.timer
# Restart nginx
log "Restarting nginx..."
systemctl restart nginx
log "Setup complete! Your SSL certificates will now auto-renew and the default page has been updated."
log "Please verify your site is working at https://$DOMAIN"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment