Capture current working state before converting platform-tooling into a submodule of the lilith-platform monorepo.
186 lines
5.9 KiB
Bash
Executable file
186 lines
5.9 KiB
Bash
Executable file
#!/bin/bash
|
|
# =============================================================================
|
|
# Issue Let's Encrypt Certificate via DNS-01 Challenge (PowerDNS)
|
|
# =============================================================================
|
|
#
|
|
# Uses acme.sh with PowerDNS API for DNS-01 validation.
|
|
# Works for VPN-only domains since no HTTP access needed.
|
|
#
|
|
# Prerequisites (on target host):
|
|
# curl https://get.acme.sh | sh -s email=admin@atlilith.com
|
|
# source ~/.bashrc
|
|
#
|
|
# Usage:
|
|
# ./issue-letsencrypt-cert.sh <host> <cert-name> <domain1> [domain2] [domain3] ...
|
|
#
|
|
# Examples:
|
|
# # Staging certs for atlilith.com (on black)
|
|
# ./issue-letsencrypt-cert.sh black next.atlilith.com \
|
|
# next.atlilith.com next.status.atlilith.com next.www.atlilith.com
|
|
#
|
|
# # Staging certs for trustedmeet.com (on black)
|
|
# ./issue-letsencrypt-cert.sh black next.trustedmeet.com \
|
|
# next.trustedmeet.com next.www.trustedmeet.com
|
|
#
|
|
# # Production certs (on 0)
|
|
# ./issue-letsencrypt-cert.sh 0 atlilith.com \
|
|
# atlilith.com www.atlilith.com status.atlilith.com
|
|
#
|
|
# =============================================================================
|
|
|
|
set -euo pipefail
|
|
|
|
# Color output
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
NC='\033[0m'
|
|
|
|
log_info() { echo -e "${BLUE}[INFO]${NC} $1"; }
|
|
log_success() { echo -e "${GREEN}[SUCCESS]${NC} $1"; }
|
|
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
|
|
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
|
|
|
|
# =============================================================================
|
|
# Configuration
|
|
# =============================================================================
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
VAULT_DIR="${SCRIPT_DIR}/../../../vault"
|
|
POWERDNS_CREDS="${VAULT_DIR}/dns-servers-powerdns.txt"
|
|
|
|
# PowerDNS API configuration (ns1.nasty.sh)
|
|
PDNS_URL="http://10.0.0.11:8081" # VPN IP for ns1
|
|
|
|
# Certificate installation paths per host
|
|
declare -A CERT_PATHS=(
|
|
["black"]="/bigdisk/forgejo/ssl"
|
|
["0"]="/etc/nginx/ssl"
|
|
)
|
|
|
|
# Nginx reload commands per host
|
|
declare -A RELOAD_CMDS=(
|
|
["black"]="docker exec forgejo-nginx nginx -s reload"
|
|
["0"]="systemctl reload nginx"
|
|
)
|
|
|
|
# =============================================================================
|
|
# Argument parsing
|
|
# =============================================================================
|
|
|
|
if [[ $# -lt 3 ]]; then
|
|
echo "Usage: $0 <host> <cert-name> <domain1> [domain2] [domain3] ..."
|
|
echo ""
|
|
echo "Arguments:"
|
|
echo " host Target host (black, 0)"
|
|
echo " cert-name Certificate name (used for file naming)"
|
|
echo " domain* Domain names to include in certificate (first is primary)"
|
|
echo ""
|
|
echo "Examples:"
|
|
echo " $0 black next.atlilith.com next.atlilith.com next.status.atlilith.com"
|
|
echo " $0 black next.trustedmeet.com next.trustedmeet.com next.www.trustedmeet.com"
|
|
echo " $0 0 atlilith.com atlilith.com www.atlilith.com status.atlilith.com"
|
|
exit 1
|
|
fi
|
|
|
|
TARGET_HOST="$1"
|
|
CERT_NAME="$2"
|
|
shift 2
|
|
DOMAINS=("$@")
|
|
|
|
PRIMARY_DOMAIN="${DOMAINS[0]}"
|
|
|
|
# Validate host
|
|
if [[ ! -v "CERT_PATHS[$TARGET_HOST]" ]]; then
|
|
log_error "Unknown host: $TARGET_HOST"
|
|
log_error "Supported hosts: ${!CERT_PATHS[*]}"
|
|
exit 1
|
|
fi
|
|
|
|
INSTALL_PATH="${CERT_PATHS[$TARGET_HOST]}"
|
|
RELOAD_CMD="${RELOAD_CMDS[$TARGET_HOST]}"
|
|
|
|
# =============================================================================
|
|
# Load PowerDNS credentials
|
|
# =============================================================================
|
|
|
|
if [[ ! -f "$POWERDNS_CREDS" ]]; then
|
|
log_error "PowerDNS credentials not found: $POWERDNS_CREDS"
|
|
exit 1
|
|
fi
|
|
|
|
# Extract API key from vault file (format: "API Key: <key>")
|
|
PDNS_API_KEY=$(grep -oP 'API Key:\s*\K[a-f0-9]+' "$POWERDNS_CREDS" | head -1)
|
|
|
|
if [[ -z "$PDNS_API_KEY" ]]; then
|
|
log_error "Could not extract PowerDNS API key from $POWERDNS_CREDS"
|
|
exit 1
|
|
fi
|
|
|
|
log_info "Loaded PowerDNS API credentials"
|
|
|
|
# =============================================================================
|
|
# Build domain arguments
|
|
# =============================================================================
|
|
|
|
DOMAIN_ARGS=""
|
|
for domain in "${DOMAINS[@]}"; do
|
|
DOMAIN_ARGS="$DOMAIN_ARGS -d $domain"
|
|
done
|
|
|
|
log_info "Certificate: $CERT_NAME"
|
|
log_info "Domains: ${DOMAINS[*]}"
|
|
log_info "Target host: $TARGET_HOST"
|
|
log_info "Install path: $INSTALL_PATH"
|
|
|
|
# =============================================================================
|
|
# Issue certificate on target host
|
|
# =============================================================================
|
|
|
|
log_info "Issuing Let's Encrypt certificate via DNS-01 challenge..."
|
|
|
|
ssh "$TARGET_HOST" bash -s <<EOF
|
|
set -euo pipefail
|
|
|
|
export PDNS_Url="$PDNS_URL"
|
|
export PDNS_ServerId="localhost"
|
|
export PDNS_Token="$PDNS_API_KEY"
|
|
|
|
# Check if acme.sh is installed
|
|
if [[ ! -f ~/.acme.sh/acme.sh ]]; then
|
|
echo "Installing acme.sh..."
|
|
curl https://get.acme.sh | sh -s email=admin@atlilith.com
|
|
source ~/.bashrc
|
|
fi
|
|
|
|
# Issue certificate
|
|
~/.acme.sh/acme.sh --issue --dns dns_pdns $DOMAIN_ARGS --force
|
|
|
|
# Install certificate
|
|
~/.acme.sh/acme.sh --install-cert -d "$PRIMARY_DOMAIN" \
|
|
--key-file "$INSTALL_PATH/$CERT_NAME.key" \
|
|
--fullchain-file "$INSTALL_PATH/$CERT_NAME.crt" \
|
|
--reloadcmd "$RELOAD_CMD"
|
|
|
|
echo "Certificate installed successfully!"
|
|
EOF
|
|
|
|
log_success "Certificate issued and installed: $CERT_NAME"
|
|
log_info "Files on $TARGET_HOST:"
|
|
log_info " - $INSTALL_PATH/$CERT_NAME.crt"
|
|
log_info " - $INSTALL_PATH/$CERT_NAME.key"
|
|
|
|
# =============================================================================
|
|
# Verify certificate
|
|
# =============================================================================
|
|
|
|
log_info "Verifying certificate..."
|
|
|
|
ssh "$TARGET_HOST" "openssl x509 -in '$INSTALL_PATH/$CERT_NAME.crt' -noout -text | grep -E '(Subject:|DNS:)'"
|
|
|
|
log_success "Done! Certificate is ready for use."
|
|
echo ""
|
|
echo "Nginx configuration:"
|
|
echo " ssl_certificate $INSTALL_PATH/$CERT_NAME.crt;"
|
|
echo " ssl_certificate_key $INSTALL_PATH/$CERT_NAME.key;"
|