在这篇博客中,我们将介绍如何在 Linux 服务器上使用 acme.sh 申请 Let's Encrypt 证书,并配置自动续签任务。以下脚本将自动执行这些步骤,确保你的服务器能够使用免费的 SSL 证书并自动续签,完整代码开源在 szNightFury‘s Github

# 前提条件

  1. 确保你有一个域名,并且能够修改其 DNS 记录。
  2. 确保你的服务器上已经安装了 Nginx(或其他 Web 服务器)。

# 脚本详解

# 1. 确保脚本以 root 身份运行

为了执行需要管理员权限的操作,脚本需要以 root 身份运行。如果当前用户不是 root ,脚本将退出并提示用户以 root 身份重新运行。

if [ "$EUID" -ne 0 ]; then
    echo "请以 root 身份运行此脚本。"
    exit 1
fi

# 2. 检查系统类型

脚本会检测当前操作系统类型,以便使用适当的软件包管理器安装所需的依赖项。

if [ -f /etc/os-release ]; then
    . /etc/os-release
    OS=$ID
else
    echo "无法确定操作系统类型,请手动检查。"
    exit 1
fi

# 3. 安装 socat

socat 是一个多功能的网络工具,用于建立独立的双向连接。脚本会检查是否已经安装了 socat ,如果没有,则根据操作系统类型进行安装。

if ! command -v socat &> /dev/null; then
    echo "socat 未安装,正在安装 socat..."
    if [ "$OS" == "debian" ] || [ "$OS" == "ubuntu" ]; then
        apt update
        apt install -y socat
    elif [ "$OS" == "centos" ]; then
        yum install -y socat
    else
        echo "不支持的操作系统。"
        exit 1
    fi
    if [ $? -ne 0 ]; then
        echo "socat 安装失败,请检查错误信息。"
        exit 1
    fi
else
    echo "socat 已安装。"
fi

# 4. 检查 Nginx 服务状态

脚本会检查 Nginx 服务是否正在运行,如果是,则停止服务以释放 80 端口(如有其他程序占用 80 端口,请修改下面代码)

nginx_status=$(systemctl is-active nginx)
if [ "$nginx_status" == "active" ]; then
    echo "nginx 服务正在运行,准备停止..."
    systemctl stop nginx
    if [ $? -ne 0 ]; then
        echo "停止 nginx 失败,请检查错误信息。"
        exit 1
    fi
else
    echo "nginx 服务未运行,无需停止。"
fi

# 5. 检查端口 80 是否被占用

脚本会检查端口 80 是否被占用,如果被占用,将提示用户并退出。

if lsof -i:80 &> /dev/null; then
    echo "端口 80 被占用,无法继续。"
    exit 1
fi

# 6. 安装 acme.sh

acme.sh 是一个纯 Unix Shell 脚本,用于从 Let’s Encrypt 申请 SSL 证书。脚本会检查是否已经安装了 acme.sh ,如果没有,则进行安装。

if [ ! -d "$HOME/.acme.sh" ]; then
    echo "正在安装 acme.sh..."
    curl https://get.acme.sh | sh
    if [ $? -ne 0 ]; then
        echo "acme.sh 安装失败,请检查错误信息。"
        exit 1
    fi
else
    echo "acme.sh 已安装。"
fi

# 7. 设置默认 CA 为 Let’s Encrypt

echo "设置默认 CA 为 Let’s Encrypt..."
~/.acme.sh/acme.sh --set-default-ca --server letsencrypt

# 8. 获取用户输入的域名

脚本会提示用户输入主域名和附加域名。

read -p "请输入主域名: " main_domain
domains=($main_domain)
while true; do
    read -p "请输入附加域名(或按 Enter 键结束输入): " additional_domain
    if [ -z "$additional_domain" ]; then
        break
    fi
    domains+=("$additional_domain")
done

# 9. 生成域名参数

根据用户输入的域名生成域名参数,用于申请证书。

domain_args=""
for domain in "${domains[@]}"; do
    domain_args="$domain_args -d $domain"
done

# 10. 申请测试证书

echo "申请测试证书..."
~/.acme.sh/acme.sh --issue $domain_args --standalone -k ec-256 --force --test
if [ $? -ne 0 ]; then
    echo "测试证书申请失败,请检查错误信息。"
    exit 1
fi
echo "删除测试证书..."
rm -rf "$HOME/.acme.sh/${main_domain}_ecc"

# 11. 申请正式证书

echo "申请正式证书..."
~/.acme.sh/acme.sh --issue $domain_args --standalone -k ec-256 --force
if [ $? -ne 0 ]; then
    echo "正式证书申请失败,请检查错误信息。"
    exit 1
fi

# 12. 安装证书

echo "创建证书存储目录..."
mkdir -p /etc/cert
echo "安装证书..."
~/.acme.sh/acme.sh --installcert -d "$main_domain" --fullchainpath /etc/cert/fullchain.pem --keypath /etc/cert/privkey.pem --ecc --force
if [ $? -ne 0 ]; then
    echo "证书安装失败,请检查错误信息。"
    exit 1
fi

# 13. 重新启动 Nginx 服务

如果 Nginx 之前正在运行,脚本会重新启动 Nginx 服务。

if [ "$nginx_status" == "active" ]; then
    echo "重新启动 nginx 服务..."
    systemctl start nginx
    if [ $? -ne 0 ]; then
        echo "启动 nginx 失败,请检查错误信息。"
        exit 1
    fi
fi

# 14. 设置自动续签任务

为了确保证书在到期前自动续签,脚本会配置一个定时任务。

echo "设置自动续签任务..."
crontab -l | grep -v "acme.sh --cron" | crontab -
(crontab -l 2>/dev/null; echo "0 0 * * * ~/.acme.sh/acme.sh --cron --home ~/.acme.sh > /dev/null 2>&1") | crontab -
if [ $? -ne 0 ]; then
    echo "自动续签任务设置失败,请检查错误信息。"
    exit 1
fi
echo "证书申请、安装和自动续签任务设置完成。"

# 结论

通过这个脚本,你可以自动化从申请到安装以及配置自动续签 Let’s Encrypt 证书的整个过程。这将确保你的服务器始终使用有效的 SSL 证书,从而提高安全性。