用法示例
- 仅申请证书:
bash ssl.sh -d demo.com - 配置Nginx(自动检查证书,不存在则申请):
bash ssl.sh -nginx demo.com
bash ssl.sh -nginx demo.com 8080
bash ssl.sh -nginx demo.com -wroot /custom/path
bash ssl.sh -nginx demo.com 8080 -wroot /custom/path
- 仅申请证书:
网站&证书一键脚本
#!/bin/bash # SSL证书自动化安装脚本 # 功能:参数校验 → ACME验证配置 → 证书申请 → Nginx配置生成 → 自动清理 SCRIPT_PATH="$(realpath "$0")" # 常量定义 NGINX_CONF="/etc/nginx/sites-available/default" CONF_DIR="/etc/nginx/conf.d" ACME_DIR="/ssl/acme-challenge" SSL_BASE="/ssl" # 清理函数 cleanup() { echo -e "\033[33m\n[清理] 正在删除脚本文件...\033[0m" [ -f "$SCRIPT_PATH" ] && rm -f "$SCRIPT_PATH" exit 0 } # 帮助信息 show_help() { echo -e "\033[36m▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄\033[0m" echo -e "\033[36m█ SSL证书自动化脚本 █\033[0m" echo -e "\033[36m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀\033[0m" echo -e "\033[32m\n用法示例:\033[0m" echo " 1. 仅申请证书:" echo " bash $0 -d demo.com" echo " 2. 配置Nginx(自动检查证书,不存在则申请):" echo " bash $0 -nginx demo.com" echo " bash $0 -nginx demo.com 8080" echo " bash $0 -nginx demo.com -wroot /custom/path" echo " bash $0 -nginx demo.com 8080 -wroot /custom/path" exit 0 } # 检查证书是否存在 check_cert_exists() { local domain=$1 local ssl_dir="${SSL_BASE}/${domain}" if [ -f "$ssl_dir/cert.crt" ] && [ -f "$ssl_dir/private.key" ]; then return 0 else return 1 fi } # 自动检测PHP-FPM版本 detect_php_fpm_sock() { local php_versions=$(ls /run/php/php*-fpm.sock 2>/dev/null | grep -oP 'php\d+\.\d+' | sort -r) if [ -z "$php_versions" ]; then echo -e "\033[31m错误:未找到运行的PHP-FPM服务\033[0m" >&2 return 1 fi local latest_php=$(echo "$php_versions" | head -n1) echo "/run/php/${latest_php}-fpm.sock" } # 清理ACME验证配置和目录 cleanup_acme_config() { echo -e "\033[34m[清理] 移除ACME验证配置和目录...\033[0m" # 删除ACME验证配置 if grep -q "#ACME验证配置开始" "$NGINX_CONF"; then sed -i '/#ACME验证配置开始/,/#ACME验证配置结束/d' "$NGINX_CONF" echo -e "\033[32m[成功] 已从Nginx配置中移除ACME验证配置\033[0m" # 测试并重载Nginx if nginx -t >/dev/null 2>&1; then systemctl reload nginx echo -e "\033[32m[成功] Nginx配置已重载\033[0m" else echo -e "\033[31m错误:Nginx配置测试失败\033[0m" >&2 nginx -t return 1 fi else echo -e "\033[33m[跳过] Nginx中未找到ACME验证配置\033[0m" fi # 删除ACME目录 if [ -d "$ACME_DIR" ]; then rm -rf "$ACME_DIR" echo -e "\033[32m[成功] 已删除ACME验证目录: $ACME_DIR\033[0m" else echo -e "\033[33m[跳过] ACME验证目录不存在: $ACME_DIR\033[0m" fi } # 参数解析 DOMAIN="" NGINX_MODE=false NGINX_PORT="" WEB_ROOT="/www/demo.com" # 默认网站根目录 while [[ $# -gt 0 ]]; do case "$1" in -d) if [ -z "$2" ] || [[ "$2" == -* ]]; then echo -e "\033[31m错误:-d 参数后必须指定域名\033[0m" >&2 exit 0 fi DOMAIN="$2" shift 2 ;; -nginx) NGINX_MODE=true if [[ "$2" != -* ]] && [[ "$2" != "" ]]; then DOMAIN="$2" if [[ "$3" =~ ^[0-9]+$ ]]; then NGINX_PORT="$3" shift 3 elif [[ "$3" == "-wroot" ]]; then if [ -z "$4" ] || [[ "$4" == -* ]]; then echo -e "\033[31m错误:-wroot 参数后必须指定路径\033[0m" >&2 exit 0 fi WEB_ROOT="$4" shift 4 else shift 2 fi else echo -e "\033[31m错误:-nginx 参数后必须指定域名\033[0m" >&2 exit 0 fi ;; -wroot) if [ "$NGINX_MODE" = false ]; then echo -e "\033[31m错误:-wroot 参数只能在 -nginx 模式下使用\033[0m" >&2 exit 0 fi if [ -z "$2" ] || [[ "$2" == -* ]]; then echo -e "\033[31m错误:-wroot 参数后必须指定路径\033[0m" >&2 exit 0 fi WEB_ROOT="$2" shift 2 ;; -help|--help|-h|--h) show_help ;; *) echo -e "\033[31m错误:未知参数 '$1'\033[0m" >&2 exit 0 ;; esac done # 验证参数 if [ -z "$DOMAIN" ]; then show_help fi # 替换默认域名路径中的demo.com为实际域名 if [ "$WEB_ROOT" = "/www/demo.com" ]; then WEB_ROOT="/www/${DOMAIN}" fi # 申请证书函数 request_certificate() { local domain=$1 echo -e "\n\033[36m[阶段] 配置ACME验证\033[0m" # 检查是否已存在配置 if ! grep -q "acme-challenge" "$NGINX_CONF"; then echo -e "\033[34m[1/3] 添加ACME验证配置...\033[0m" mkdir -p "$ACME_DIR" || { echo -e "\033[31m错误:无法创建验证目录 $ACME_DIR\033[0m" >&2 exit 1 } chown -R www-data:www-data "$ACME_DIR" TEMP_FILE=$(mktemp) || { echo -e "\033[31m错误:无法创建临时文件\033[0m" >&2 exit 1 } cat > "$TEMP_FILE" << EOF #ACME验证配置开始 location ^~ /.well-known/acme-challenge { allow all; root $ACME_DIR; } #ACME验证配置结束 EOF if ! sed -i '/server_name _;/r '"$TEMP_FILE" "$NGINX_CONF"; then echo -e "\033[31m错误:无法修改Nginx配置\033[0m" >&2 rm -f "$TEMP_FILE" exit 1 fi rm -f "$TEMP_FILE" if nginx -t >/dev/null 2>&1; then systemctl reload nginx echo -e "\033[32m[成功] ACME验证配置已生效\033[0m" else echo -e "\033[31m错误:Nginx配置测试失败\033[0m" >&2 echo "查看错误:" nginx -t cleanup_acme_config exit 1 fi else echo -e "\033[33m[跳过] ACME验证配置已存在\033[0m" fi # 申请证书 echo -e "\n\033[36m[阶段] 申请SSL证书\033[0m" SSL_DIR="${SSL_BASE}/${domain}" mkdir -p "$SSL_DIR" || { echo -e "\033[31m错误:无法创建证书目录 $SSL_DIR\033[0m" >&2 exit 1 } echo -e "\033[34m[2/3] 正在申请证书...\033[0m" if ! ~/.acme.sh/acme.sh --force --issue -d "$domain" -w "$ACME_DIR"; then echo -e "\033[31m证书申请失败!可能原因:\033[0m" >&2 echo "1. 域名解析未生效(请检查DNS设置)" echo "2. 服务器80端口被占用" echo "3. 已有相同域名的证书" cleanup_acme_config exit 1 fi # 安装证书 echo -e "\033[34m[3/3] 安装证书到指定目录...\033[0m" if ! ~/.acme.sh/acme.sh --installcert -d "$domain" \ --key-file "$SSL_DIR/private.key" \ --fullchain-file "$SSL_DIR/cert.crt"; then echo -e "\033[31m证书安装失败!\033[0m" >&2 cleanup_acme_config exit 1 fi chmod 600 "$SSL_DIR/private.key" chmod 644 "$SSL_DIR/cert.crt" echo -e "\033[32m[成功] 证书已安装到:\033[0m" echo -e "私钥:\033[33m$SSL_DIR/private.key\033[0m" echo -e "证书:\033[33m$SSL_DIR/cert.crt\033[0m" # 证书申请成功后清理ACME配置和目录 cleanup_acme_config } # 配置Nginx函数 configure_nginx() { local domain=$1 local port=$2 echo -e "\n\033[36m[阶段] 生成Nginx站点配置\033[0m" SSL_DIR="${SSL_BASE}/${domain}" if [ -z "$port" ]; then # PHP站点配置 CONF_FILE="${CONF_DIR}/php-${domain}.conf" if [ -f "$CONF_FILE" ]; then echo -e "\033[33m[跳过] PHP配置已存在:$CONF_FILE\033[0m" else echo -e "\033[34m[1/1] 生成PHP站点配置...\033[0m" PHP_SOCK=$(detect_php_fpm_sock) || exit 1 cat > "$CONF_FILE" << EOF server { listen 80; listen [::]:80; listen 443 ssl http2; listen [::]:443 ssl http2; server_name ${domain}; root ${WEB_ROOT}; index index.php index.html index.htm; # SSL配置 ssl_certificate $SSL_DIR/cert.crt; ssl_certificate_key $SSL_DIR/private.key; ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384; ssl_prefer_server_ciphers on; # 80重定向到443 if (\$scheme = http) { return 301 https://\$host\$request_uri; } # 如果请求的文件存在,直接返回该文件 #location / { #try_files \$uri \$uri/ /index.php?\$query_string; #} # PHP配置 location ~ \.php$ { include snippets/fastcgi-php.conf; fastcgi_pass unix:${PHP_SOCK}; } } EOF echo -e "\033[32m[成功] 已创建:$CONF_FILE\033[0m" echo -e "\033[33m网站根目录设置为:${WEB_ROOT}\033[0m" fi else # 反向代理配置 CONF_FILE="${CONF_DIR}/proxy-${domain}.conf" if [ -f "$CONF_FILE" ]; then echo -e "\033[33m[跳过] 代理配置已存在:$CONF_FILE\033[0m" else echo -e "\033[34m[1/1] 生成反向代理配置...\033[0m" cat > "$CONF_FILE" << EOF server { listen 80; listen [::]:80; listen 443 ssl http2; listen [::]:443 ssl http2; server_name ${domain}; #root ${WEB_ROOT}; # SSL配置 ssl_certificate $SSL_DIR/cert.crt; ssl_certificate_key $SSL_DIR/private.key; ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384; ssl_prefer_server_ciphers on; # 80重定向到443 if (\$scheme = http) { return 301 https://\$host\$request_uri; } location / { proxy_pass http://127.0.0.1:${port}; proxy_set_header Host \$host; proxy_set_header X-Real-IP \$remote_addr; proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; proxy_set_header REMOTE-HOST \$remote_addr; proxy_set_header Upgrade \$http_upgrade; proxy_set_header Connection \$http_connection; proxy_set_header X-Forwarded-Proto \$scheme; proxy_http_version 1.1; add_header X-Cache \$upstream_cache_status; add_header Strict-Transport-Security "max-age=31536000"; } } EOF echo -e "\033[32m[成功] 已创建:$CONF_FILE (代理到端口 ${port})\033[0m" fi fi # 测试并重载Nginx if nginx -t >/dev/null 2>&1; then systemctl reload nginx echo -e "\033[32m[成功] Nginx配置已生效\033[0m" else echo -e "\033[31m警告:Nginx配置测试失败,请手动检查!\033[0m" >&2 nginx -t rm -rf $CONF_FILE echo -e "\033[31m警告:已删除:$CONF_FILE\033[0m" cleanup_acme_config exit 1 fi } # 主逻辑 SSL_DIR="${SSL_BASE}/${DOMAIN}" # 检查证书是否存在 if check_cert_exists "$DOMAIN"; then echo -e "\033[32m[检测] 发现已有证书\033[0m" CERT_EXISTS=true else echo -e "\033[33m[检测] 未找到现有证书\033[0m" CERT_EXISTS=false fi # 功能1:仅申请证书 if [ -n "$DOMAIN" ] && [ "$NGINX_MODE" = false ]; then if $CERT_EXISTS; then echo -e "\033[33m[提示] 证书已存在,强制更新\033[0m" request_certificate "$DOMAIN" systemctl reload nginx else request_certificate "$DOMAIN" systemctl reload nginx fi fi # 功能2:配置Nginx(如有需要先申请证书) if [ "$NGINX_MODE" = true ]; then if ! $CERT_EXISTS; then echo -e "\033[33m[流程] 未找到证书,将先申请证书\033[0m" request_certificate "$DOMAIN" fi configure_nginx "$DOMAIN" "$NGINX_PORT" fi # 完成输出 echo -e "\n\033[36m▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄\033[0m" echo -e "\033[36m█ 所有操作已完成! █\033[0m" echo -e "\033[36m▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀\033[0m" # 删除脚本 cleanup
- 上一篇: 勿言
- 下一篇: 部署NodeCrypt
