需求

我有2台服务器,A使用1panel自动获取https证书,B服务器上有一个docker容器也需要使用证书文件,如何配置A上的脚本(会在https证书续签后执行),将证书文件传到B服务器的指定路径,然后重启B的某个docker 容器?

实现

1 服务器连接

在 A 服务器上生成 SSH 密钥对:

ssh-keygen -t rsa -b 4096

使用 ssh-copy-id 将公钥复制到 B 服务器

ssh-copy-id user@B-server

这将会将 A 服务器上的公钥复制到 B 服务器上的 ~/.ssh/authorized_keys 文件中,从而实现无密码 SSH 登录。

测试从 A 服务器无密码 SSH 登录到 B 服务器:

ssh user@B-server

注意

SSH 对 root 用户的家目录(/root)及其下的 ~/.ssh 目录权限要求非常严格。如果权限设置不当,出于安全考虑,SSH 会直接拒绝公钥认证。 运行以下命令检查关键目录和文件的权限:

ls -ld /root /root/.ssh /root/.ssh/authorized_keys

正确输出应类似:

drwx------ 5 root root 4096 Jul 11 08:00 /root
drwx------ 2 root root 4096 Jul 11 08:00 /root/.ssh
-rw------- 1 root root  123 Jul 11 08:00 /root/.ssh/authorized_keys

解决方法

  1. 修复 /root 目录的权限和所有权

权限必须为 700(仅 root 用户可访问):

chmod 700 /root

所有权必须为 root:root:

chown root:root /root
  1. 修复 /root/.ssh 和 /root/.ssh/authorized_keys 的权限

确保 ~/.ssh 权限为 700:

chmod 700 /root/.ssh

确保 authorized_keys 权限为 600:

chmod 600 /root/.ssh/authorized_keys

所有权必须为 root:root:

chown -R root:root /root/.ssh

2 脚本

在 A 服务器上编写一个脚本,该脚本会在证书续签后运行,完成以下操作:

将整个证书文件夹复制到 B 服务器。

重启 B 服务器上的 Docker 容器。

发送邮件通知(可选)

#!/bin/bash
 
# 设置相关路径
CERT_DIR="/root/cert"  # 证书所在的目录
B_SERVER="root@192.168.100.10"  # B 服务器的 SSH 用户名和地址
B_CERT_DIR="/root/squid-proxy"  # B 服务器上存储证书的目标目录
RELOAD_CMD="docker restart squid-proxy"  # Docker 容器的名称或 ID
 
# 邮件通知-可选
RESEND_API_KEY="re_123456789"  # 替换为您的 Resend API 密钥
FROM_EMAIL="mail@a.com"  # 发件人邮箱
TO_EMAIL="x@x.com"  # 收件人邮箱
 
# 发送邮件通知的函数
send_email() {
    curl -X POST 'https://api.resend.com/emails' \
        -H "Authorization: Bearer ${RESEND_API_KEY}" \
        -H 'Content-Type: application/json' \
        -d $'{
            "from": "'${FROM_EMAIL}'",
            "to": ["'${TO_EMAIL}'"],
            "subject": "'$1'",
            "html": "'$2'"
        }'
}
 
# 复制证书并重启容器
if scp -r ${CERT_DIR} ${B_SERVER}:${B_CERT_DIR} && ssh ${B_SERVER} "${RELOAD_CMD}"; then
    send_email "证书更新与容器重启成功" "<p>证书已成功更新并传输到服务器(${B_SERVER}),容器已成功重启。</p>"
else
    send_email "证书更新与容器重启失败" "<p>证书更新或容器重启失败,请检查日志。</p>"
fi
 
# 输出完成信息
echo "证书更新并重新启动 Docker 容器完成"