diff --git a/docker/certbot/.env.example b/docker/certbot/.env.example deleted file mode 100644 index 2a3ec08..0000000 --- a/docker/certbot/.env.example +++ /dev/null @@ -1,19 +0,0 @@ -# SSL Certificate Configuration -# Copy this to .env in your project root and customize the values - -# Domain for SSL certificate (will also create wildcard *.domain) -CERTBOT_DOMAIN=dev.uggla.uamils.com - -# Email for Let's Encrypt notifications -CERTBOT_EMAIL=admin@uggla.uamils.com - -# Days before expiry to trigger renewal (default: 10) -CERTBOT_RENEWAL_DAYS=10 - -# Loopia DNS API credentials (optional, for wildcard certificates) -# If not provided, will use HTTP challenge (main domain only) -LOOPIA_USER=your_loopia_username -LOOPIA_PASSWORD=your_loopia_password - -# Note: If using HTTP challenge, make sure port 8888 is accessible -# from the internet and forwarded to the certbot container diff --git a/docker/certbot/Dockerfile b/docker/certbot/Dockerfile deleted file mode 100644 index 04621d3..0000000 --- a/docker/certbot/Dockerfile +++ /dev/null @@ -1,35 +0,0 @@ -FROM certbot/certbot:latest - -# Install additional tools and python packages -RUN apk add --no-cache \ - curl \ - jq \ - bash \ - dcron \ - nginx \ - openssl - -# Install dns-lexicon for DNS providers support -RUN pip install dns-lexicon[full] - -# Create necessary directories -RUN mkdir -p /app/scripts /var/log/certbot - -# Copy renewal scripts -COPY scripts/ /app/scripts/ -RUN chmod +x /app/scripts/*.sh - -# Copy crontab -COPY crontab /etc/crontabs/root - -# Copy entrypoint -COPY entrypoint.sh /entrypoint.sh -RUN chmod +x /entrypoint.sh - -# Create a simple nginx config for HTTP challenges -COPY nginx.conf /etc/nginx/nginx.conf - -WORKDIR /app - -ENTRYPOINT ["/entrypoint.sh"] -CMD ["crond", "-f", "-l", "2"] diff --git a/docker/certbot/crontab b/docker/certbot/crontab deleted file mode 100644 index 97d16d1..0000000 --- a/docker/certbot/crontab +++ /dev/null @@ -1,5 +0,0 @@ -# Run certificate renewal check daily at 2 AM -0 2 * * * /app/scripts/check-and-renew.sh >> /var/log/certbot/renewal.log 2>&1 - -# Optional: Run a quick status check every 6 hours -0 */6 * * * /app/scripts/status-check.sh >> /var/log/certbot/status.log 2>&1 diff --git a/docker/certbot/entrypoint.sh b/docker/certbot/entrypoint.sh deleted file mode 100644 index 5ac6c7c..0000000 --- a/docker/certbot/entrypoint.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/bash - -# Entrypoint script for certbot container -set -e - -echo "Starting Certbot Auto-Renewal Container" -echo "=========================================" - -# Create log directory -mkdir -p /var/log/certbot - -# Set up environment -export DOMAIN="${DOMAIN:-dev.uggla.uamils.com}" -export EMAIL="${EMAIL:-admin@uggla.uamils.com}" -export RENEWAL_DAYS="${RENEWAL_DAYS:-10}" - -echo "Domain: $DOMAIN" -echo "Email: $EMAIL" -echo "Renewal threshold: $RENEWAL_DAYS days" - -# Initial certificate check/creation -/app/scripts/check-and-renew.sh - -# Start cron daemon -echo "Starting cron daemon..." -exec "$@" diff --git a/docker/certbot/nginx.conf b/docker/certbot/nginx.conf deleted file mode 100644 index 9b0f106..0000000 --- a/docker/certbot/nginx.conf +++ /dev/null @@ -1,28 +0,0 @@ -events { - worker_connections 1024; -} - -http { - include /etc/nginx/mime.types; - default_type application/octet-stream; - - # Simple server for HTTP challenges - server { - listen 80; - server_name _; - - root /var/www/html; - - # ACME challenge location - location /.well-known/acme-challenge/ { - root /var/www/html; - try_files $uri =404; - } - - # Default location - location / { - return 200 "Certbot HTTP Challenge Server"; - add_header Content-Type text/plain; - } - } -} diff --git a/docker/certbot/scripts/check-and-renew.sh b/docker/certbot/scripts/check-and-renew.sh deleted file mode 100644 index b30bd63..0000000 --- a/docker/certbot/scripts/check-and-renew.sh +++ /dev/null @@ -1,173 +0,0 @@ -#!/bin/bash - -# Main certificate renewal script -set -e - -DOMAIN="${DOMAIN:-dev.uggla.uamils.com}" -EMAIL="${EMAIL:-admin@uggla.uamils.com}" -RENEWAL_DAYS="${RENEWAL_DAYS:-10}" -LOG_FILE="/var/log/certbot/renewal.log" - -log() { - echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE" -} - -check_certificate_expiry() { - local cert_path="/etc/letsencrypt/live/$DOMAIN/cert.pem" - - if [[ ! -f "$cert_path" ]]; then - log "Certificate not found at $cert_path - will attempt to obtain new certificate" - return 1 - fi - - # Get certificate expiry date - local expiry_date=$(openssl x509 -in "$cert_path" -noout -enddate | cut -d= -f2) - local expiry_epoch=$(date -d "$expiry_date" +%s) - local current_epoch=$(date +%s) - local days_until_expiry=$(( (expiry_epoch - current_epoch) / 86400 )) - - log "Certificate expires in $days_until_expiry days" - - if [[ $days_until_expiry -le $RENEWAL_DAYS ]]; then - log "Certificate expires in $days_until_expiry days - renewal needed" - return 1 - else - log "Certificate is valid for $days_until_expiry more days - no renewal needed" - return 0 - fi -} - -attempt_dns_challenge() { - log "Attempting DNS challenge with Loopia API..." - - if [[ -z "$LOOPIA_USER" || -z "$LOOPIA_PASSWORD" ]]; then - log "LOOPIA_USER or LOOPIA_PASSWORD not set - skipping DNS challenge" - return 1 - fi - - # Try with dns-lexicon - if command -v lexicon >/dev/null 2>&1; then - log "Using dns-lexicon for DNS challenge..." - certbot certonly \ - --dns-lexicon \ - --dns-lexicon-provider loopia \ - --dns-lexicon-loopia-username="$LOOPIA_USER" \ - --dns-lexicon-loopia-password="$LOOPIA_PASSWORD" \ - --email "$EMAIL" \ - --agree-tos \ - --non-interactive \ - --expand \ - -d "$DOMAIN" \ - -d "*.$DOMAIN" - return $? - fi - - # Fallback: Manual DNS with custom hook - if [[ -f "/app/scripts/loopia-hook.sh" ]]; then - log "Using custom Loopia hook for DNS challenge..." - certbot certonly \ - --manual \ - --preferred-challenges dns \ - --manual-auth-hook "/app/scripts/loopia-hook.sh auth" \ - --manual-cleanup-hook "/app/scripts/loopia-hook.sh cleanup" \ - --email "$EMAIL" \ - --agree-tos \ - --non-interactive \ - --expand \ - -d "$DOMAIN" \ - -d "*.$DOMAIN" - return $? - fi - - return 1 -} - -attempt_http_challenge() { - log "Attempting HTTP challenge..." - - # Start nginx for HTTP challenge - nginx -t && nginx - - certbot certonly \ - --webroot \ - --webroot-path=/var/www/html \ - --email "$EMAIL" \ - --agree-tos \ - --non-interactive \ - --expand \ - -d "$DOMAIN" - - local result=$? - - # Stop nginx - nginx -s quit || true - - return $result -} - -reload_nginx() { - log "Copying certificates to shared directory..." - - # Copy certificates to shared SSL directory - if [[ -d "/etc/letsencrypt/live/$DOMAIN" ]]; then - mkdir -p /shared/ssl - cp "/etc/letsencrypt/live/$DOMAIN/fullchain.pem" "/shared/ssl/fullchain.pem" || log "Could not copy fullchain.pem" - cp "/etc/letsencrypt/live/$DOMAIN/privkey.pem" "/shared/ssl/privkey.pem" || log "Could not copy privkey.pem" - chmod 644 /shared/ssl/fullchain.pem - chmod 600 /shared/ssl/privkey.pem - log "Certificates copied to /shared/ssl/" - fi - - log "Reloading nginx configuration..." - - # Check if nginx container exists and reload it - if command -v docker >/dev/null 2>&1; then - if docker ps --format "table {{.Names}}" | grep -q "nginx\|proxy"; then - log "Reloading nginx container..." - docker exec nginx nginx -s reload 2>/dev/null || \ - docker exec drone-detection-nginx nginx -s reload 2>/dev/null || \ - log "Could not reload nginx container - manual reload may be required" - fi - fi - - # Also try to reload host nginx if running - if pgrep nginx >/dev/null; then - log "Reloading host nginx..." - nginx -s reload || log "Could not reload host nginx" - fi -} - -main() { - log "Starting certificate renewal check for $DOMAIN" - - # Check if renewal is needed - if check_certificate_expiry; then - log "Certificate is still valid - no action needed" - exit 0 - fi - - log "Certificate renewal required - attempting to renew..." - - # Try DNS challenge first (for wildcard support) - if attempt_dns_challenge; then - log "DNS challenge successful!" - reload_nginx - log "Certificate renewal completed successfully" - exit 0 - fi - - # Fallback to HTTP challenge (for main domain only) - log "DNS challenge failed - falling back to HTTP challenge" - if attempt_http_challenge; then - log "HTTP challenge successful!" - reload_nginx - log "Certificate renewal completed successfully" - exit 0 - fi - - log "ERROR: All certificate renewal attempts failed" - exit 1 -} - -# Run main function -main "$@" diff --git a/docker/certbot/scripts/loopia-hook.sh b/docker/certbot/scripts/loopia-hook.sh deleted file mode 100644 index 8b4c7e6..0000000 --- a/docker/certbot/scripts/loopia-hook.sh +++ /dev/null @@ -1,158 +0,0 @@ -#!/bin/bash - -# Loopia DNS API hook for certbot -# This script handles DNS TXT record creation and cleanup for Let's Encrypt challenges - -set -e - -LOOPIA_USER="${LOOPIA_USER:-}" -LOOPIA_PASSWORD="${LOOPIA_PASSWORD:-}" -LOOPIA_API_URL="https://api.loopia.se/RPCSERV" - -log() { - echo "[$(date '+%Y-%m-%d %H:%M:%S')] Loopia Hook: $1" >&2 -} - -# Extract domain and subdomain parts -extract_domain_parts() { - local full_domain="$1" - - # For *.dev.uggla.uamils.com -> domain=uamils.com, subdomain=_acme-challenge.dev - # For dev.uggla.uamils.com -> domain=uamils.com, subdomain=_acme-challenge.dev - - if [[ "$full_domain" == *.uamils.com ]]; then - DOMAIN="uamils.com" - local prefix="${full_domain%.uamils.com}" - if [[ "$prefix" == *"*"* ]]; then - # Wildcard domain *.dev.uggla.uamils.com - SUBDOMAIN="_acme-challenge.${prefix#*.}" - else - # Regular domain dev.uggla.uamils.com - SUBDOMAIN="_acme-challenge.$prefix" - fi - else - log "ERROR: Unsupported domain format: $full_domain" - exit 1 - fi -} - -# Call Loopia API -call_loopia_api() { - local method="$1" - shift - local params="$@" - - curl -s -X POST "$LOOPIA_API_URL" \ - -H "Content-Type: text/xml" \ - -d " - - $method - - $LOOPIA_USER - $LOOPIA_PASSWORD - $params - -" -} - -# Add DNS TXT record -add_txt_record() { - local domain="$1" - local subdomain="$2" - local txt_value="$3" - - log "Adding TXT record: $subdomain.$domain = $txt_value" - - local response=$(call_loopia_api "addZoneRecord" \ - "$domain - $subdomain - - - type - TXT - - - rdata - $txt_value - - - ttl - 300 - - ") - - if echo "$response" | grep -q "OK"; then - log "Successfully added TXT record" - else - log "ERROR adding TXT record: $response" - exit 1 - fi -} - -# Remove DNS TXT record -remove_txt_record() { - local domain="$1" - local subdomain="$2" - - log "Removing TXT records for: $subdomain.$domain" - - # Get existing records - local records=$(call_loopia_api "getZoneRecords" \ - "$domain - $subdomain") - - # Extract record IDs for TXT records - local record_ids=$(echo "$records" | grep -A5 "type" | grep -B5 "TXT" | grep "record_id" | sed 's/.*\([0-9]*\)<\/int>.*/\1/') - - for record_id in $record_ids; do - if [[ -n "$record_id" ]]; then - log "Removing TXT record ID: $record_id" - call_loopia_api "removeZoneRecord" \ - "$domain - $subdomain - $record_id" - fi - done -} - -# Main script logic -case "$1" in - "auth") - if [[ -z "$CERTBOT_DOMAIN" || -z "$CERTBOT_VALIDATION" ]]; then - log "ERROR: CERTBOT_DOMAIN or CERTBOT_VALIDATION not set" - exit 1 - fi - - if [[ -z "$LOOPIA_USER" || -z "$LOOPIA_PASSWORD" ]]; then - log "ERROR: LOOPIA_USER or LOOPIA_PASSWORD not set" - exit 1 - fi - - extract_domain_parts "$CERTBOT_DOMAIN" - add_txt_record "$DOMAIN" "$SUBDOMAIN" "$CERTBOT_VALIDATION" - - # Wait for DNS propagation - log "Waiting 60 seconds for DNS propagation..." - sleep 60 - ;; - - "cleanup") - if [[ -z "$CERTBOT_DOMAIN" ]]; then - log "ERROR: CERTBOT_DOMAIN not set" - exit 1 - fi - - if [[ -z "$LOOPIA_USER" || -z "$LOOPIA_PASSWORD" ]]; then - log "WARNING: LOOPIA_USER or LOOPIA_PASSWORD not set - skipping cleanup" - exit 0 - fi - - extract_domain_parts "$CERTBOT_DOMAIN" - remove_txt_record "$DOMAIN" "$SUBDOMAIN" - ;; - - *) - log "Usage: $0 {auth|cleanup}" - exit 1 - ;; -esac diff --git a/docker/certbot/scripts/status-check.sh b/docker/certbot/scripts/status-check.sh deleted file mode 100644 index eaaab83..0000000 --- a/docker/certbot/scripts/status-check.sh +++ /dev/null @@ -1,45 +0,0 @@ -#!/bin/bash - -# Status check script for monitoring -set -e - -DOMAIN="${DOMAIN:-dev.uggla.uamils.com}" -LOG_FILE="/var/log/certbot/status.log" - -log() { - echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" -} - -check_certificate_status() { - local cert_path="/etc/letsencrypt/live/$DOMAIN/cert.pem" - - if [[ ! -f "$cert_path" ]]; then - log "STATUS: No certificate found for $DOMAIN" - return 1 - fi - - # Get certificate details - local expiry_date=$(openssl x509 -in "$cert_path" -noout -enddate | cut -d= -f2) - local expiry_epoch=$(date -d "$expiry_date" +%s) - local current_epoch=$(date +%s) - local days_until_expiry=$(( (expiry_epoch - current_epoch) / 86400 )) - - # Get certificate subject - local subject=$(openssl x509 -in "$cert_path" -noout -subject | sed 's/subject=//') - - log "STATUS: Certificate for $DOMAIN" - log " Subject: $subject" - log " Expires: $expiry_date" - log " Days until expiry: $days_until_expiry" - - if [[ $days_until_expiry -le 10 ]]; then - log " WARNING: Certificate expires soon!" - elif [[ $days_until_expiry -le 30 ]]; then - log " NOTICE: Certificate expires in less than 30 days" - else - log " OK: Certificate is valid" - fi -} - -# Check certificate status -check_certificate_status