2025.11 天津 天塔

我虽然一直使用ohttps来提供免费证书的定时更新和CDN、SLB之类云服务的证书更新,但对于ECS服务器的SSL更新一直是手动来执行。随着管理站点的增加,现在更新一次证书需要在七八台机器上折腾,虽然三个月搞一次,但还是下决心使用推送的方式来解决这个问题。

准备域名

  1. ohttps站点的管理后台

  1. 添加免费泛域名证书

  2. 设置目标域名的证书认证解析

  3. 添加CNAME域名

  4. 认证成功后就会自动申请一个泛域名证书

准备管理账户

  1. 接下来就需要在服务器上添加一个管理SSL证书和Nginx的账户
#!/bin/bash
#
# Script: setup_cert_user.sh
# Description: Create user 'cert' with SSH key-only login, sudo for nginx service,
# and write access to /etc/nginx/ssl.
# Usage: sudo ./setup_cert_user.sh
# Author: Linux Admin Expert
# Date: $(date +%Y-%m-%d)

# 遇到错误立即退出
set -e

# 检查是否以 root 身份运行
if [[ $EUID -ne 0 ]]; then
echo "错误:此脚本必须以 root 身份运行。请使用 sudo。" >&2
exit 1
fi

# 定义变量
USER_NAME="cert"
USER_HOME="/home/$USER_NAME"
SSH_DIR="$USER_HOME/.ssh"
AUTH_KEYS="$SSH_DIR/authorized_keys"
KEY_FILE="/tmp/${USER_NAME}_ssh_key" # 私钥临时存放路径
PUB_KEY="${KEY_FILE}.pub" # 公钥路径
SSL_DIR="/etc/nginx/ssl"
SUDOERS_FILE="/etc/sudoers.d/${USER_NAME}-nginx"

# 检查必要命令是否存在,若缺少则尝试安装
check_command() {
local cmd=$1
local pkg=${2:-$1}
if ! command -v "$cmd" >/dev/null 2>&1; then
echo "命令 $cmd 未找到,尝试安装 $pkg ..."
if command -v apt-get >/dev/null 2>&1; then
apt-get update && apt-get install -y "$pkg"
elif command -v yum >/dev/null 2>&1; then
yum install -y "$pkg"
else
echo "错误:无法自动安装 $pkg,请手动安装后重试。" >&2
exit 1
fi
fi
}

echo "检查必要工具..."
check_command useradd shadow-utils # 通常useradd已存在,但确保passwd可用
check_command ssh-keygen openssh-client
check_command sz lrzsz # 提供sz命令

# 1. 创建用户 cert(若不存在)
if id "$USER_NAME" &>/dev/null; then
echo "用户 $USER_NAME 已存在,跳过创建。"
else
echo "创建用户 $USER_NAME ..."
useradd -m -s /bin/bash "$USER_NAME" # 创建家目录并设置bash
passwd -l "$USER_NAME" # 锁定密码,仅密钥登录
echo "用户 $USER_NAME 创建完成,密码已锁定。"
fi

# 2. 配置SSH密钥
echo "生成 SSH 密钥对(无密码)..."
rm -f "$KEY_FILE" "$PUB_KEY"
ssh-keygen -t rsa -b 4096 -f "$KEY_FILE" -N "" -q

echo "设置 SSH 目录和权限..."
mkdir -p "$SSH_DIR"
chmod 700 "$SSH_DIR"
cat "$PUB_KEY" >> "$AUTH_KEYS"
chmod 600 "$AUTH_KEYS"
chown -R "$USER_NAME:$USER_NAME" "$USER_HOME"

# 3. 使用 sz 发送私钥给用户(如果终端支持)
echo "尝试通过 sz 发送私钥文件..."
if command -v sz >/dev/null 2>&1; then
# 检查是否在支持ZMODEM的终端中运行(简单判断)
if [[ -t 0 && -n "${SSH_TTY:-}" || -n "${TMUX:-}" ]]; then
echo "请在弹出对话框中选择保存位置(或自动下载)。"
sz "$KEY_FILE" || echo "警告:sz 传输可能失败,请手动下载私钥。"
else
echo "终端不支持 ZMODEM,私钥文件保留在 $KEY_FILE"
echo "请手动下载该文件,然后删除:rm -f $KEY_FILE"
fi
else
echo "sz 命令不可用,私钥文件保留在 $KEY_FILE"
echo "请手动下载该文件,然后删除:rm -f $KEY_FILE"
fi

# 清理公钥(私钥已发送或保留提示,可酌情删除公钥)
rm -f "$PUB_KEY"
echo "SSH 公钥已安装到 $AUTH_KEYS,私钥处理完成。"

# 4. 配置 sudo 权限管理 nginx 服务
echo "配置 sudo 权限..."
cat > "$SUDOERS_FILE.tmp" <<EOF
# Allow $USER_NAME to manage nginx service without password
$USER_NAME ALL=(ALL) NOPASSWD: /usr/bin/systemctl start nginx, /usr/bin/systemctl stop nginx, /usr/bin/systemctl restart nginx, /usr/bin/systemctl reload nginx, /usr/bin/systemctl status nginx
EOF

# 检查语法并安装
visudo -c -f "$SUDOERS_FILE.tmp" && {
mv "$SUDOERS_FILE.tmp" "$SUDOERS_FILE"
chmod 440 "$SUDOERS_FILE"
echo "sudo 规则已添加:$SUDOERS_FILE"
} || {
echo "错误:sudoers 语法检查失败。" >&2
rm -f "$SUDOERS_FILE.tmp"
exit 1
}

# 5. 处理 /etc/nginx/ssl 目录权限
echo "设置 SSL 目录权限..."
mkdir -p "$SSL_DIR"
chown "$USER_NAME:$USER_NAME" "$SSL_DIR"
chmod 755 "$SSL_DIR" # 所有者可读写执行,其他人可读执行
echo "目录 $SSL_DIR 的所有者已改为 $USER_NAME,权限 755。"

# 验证目录访问
if sudo -u "$USER_NAME" test -w "$SSL_DIR" && sudo -u "$USER_NAME" test -x "$SSL_DIR"; then
echo "✓ 用户 $USER_NAME 可以在 $SSL_DIR 中创建子目录和文件。"
else
echo "⚠ 警告:用户 $USER_NAME 对 $SSL_DIR 的写入权限验证失败,请手动检查。"
fi

# 6. 总结信息
echo ""
echo "============================================================"
echo "配置完成。"
echo "用户 $USER_NAME 已创建,仅支持 SSH 密钥登录。"
echo "私钥文件位置:$KEY_FILE (请妥善保管并删除临时文件)"
echo ""
echo "sudo 权限已授予,允许执行以下命令(无需密码):"
echo " sudo systemctl start nginx"
echo " sudo systemctl stop nginx"
echo " sudo systemctl restart nginx"
echo " sudo systemctl reload nginx"
echo " sudo systemctl status nginx"
echo ""
echo "用户对 $SSL_DIR 拥有完全控制权(可创建子目录/文件)。"
echo "============================================================"

exit 0
  1. 在ohttps后台添加账户
  2. 创建并关联证书
  3. 执行证书部署工作
  4. 校验证书放置,并在conf文件完成证书配置
  5. 验证站点访问