使用 Docker + Jenkins 自动更新证书并部署到目标机器。

1
2
3
4
5
6
7
8
9
# 文件一览
.
├── deploy
│ ├── docker.deps
│ │ └── ...
│ └── renew-certs
│ ├── Dockerfile
│ ├── Jenkinsfile
│ └── renew-certs.sh

renew-certs.sh

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#!/bin/sh

set -v on
set -e

function reloadCerts() {
remoteHost="$1"
domains="$2"
for DOMAIN in ${domains}; do
echo "Issue $DOMAIN ..."
acme.sh --issue --dns dns_dp -d "${DOMAIN}" -d "*.${DOMAIN}" --force --server letsencrypt.org
scp -r /acme.sh/${DOMAIN} ${remoteHost}:/data/certs/
done
ssh ${remoteHost} "sudo nginx -s reload"
}

ssh-keyscan "example.com" >> ~/.ssh/known_hosts
reloadCerts "ubuntu@example.com" "example.com example-2.com"

Dockerfile

1
2
3
4
5
6
7
8
9
10
11
12
FROM neilpang/acme.sh

WORKDIR /data/web-apps
COPY . .

RUN mkdir -p ~/.ssh/ \
&& cp ./deploy/docker.deps/ssh-key.txt ~/.ssh/id_rsa \
&& chmod 600 ~/.ssh/id_rsa \
&& chmod +x ./deploy/renew-certs/renew-certs.sh \
&& cp ./deploy/renew-certs/renew-certs.sh /bin/renew-certs.sh

CMD echo "renew-certs container launched."

Jenkinsfile

Jenkins 中预先配置

  • SSH Key 私钥: SSHKeyFile_Fang (Secret file)
  • DNSPod ID: DNSPod_ID (Secret Text)
  • DNSPod Key: DNSPod_Key (Secret Text)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
pipeline {
agent any
options {
disableConcurrentBuilds()
}
stages {
stage('Prepare') {
steps {
script {
withCredentials([file(credentialsId: 'SSHKeyFile_Fang', variable: 'myPrivateKey')]) {
sh "cp \$myPrivateKey ./deploy/docker.deps/ssh-key.txt"
}
sh "docker build -t my-renew-certs -f ./deploy/renew-certs/Dockerfile ."
}
}
}
stage('Build') {
steps {
script {
withCredentials([
string(credentialsId: 'DNSPod_ID', variable: 'DP_Id'),
string(credentialsId: 'DNSPod_Key', variable: 'DP_Key'),
]) {
sh "docker run -i --rm -e 'DP_Id=${DP_Id}' -e 'DP_Key=${DP_Key}' my-renew-certs /bin/renew-certs.sh"
}
}
}
}
}
}

Jenkins 定时任务

  1. 新建「流水线」
  2. 「构建触发器」-「定时构建」- “H 0 1,15 * *” (每月 1 号、15 号定时执行)
  3. 「流水线」-「定义: Pipeline script from SCM」-「SCM Repositories +相关仓库信息」-「脚本路径: deploy/renew-certs/Jenkinsfile

GitHub Actions

GitHub Actions 只需定义 Workflow 即可,比 Jenkins 更加简单

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
name: auto-renew-certs

on:
schedule:
- cron: "0 0 1,15 * *"

jobs:
build:
name: Build on node ${{ matrix.node_version }} and ${{ matrix.os }}
runs-on: ubuntu-latest
strategy:
matrix:
os: [ubuntu-latest]
node_version: [20.x]

steps:
- name: Checkout
uses: actions/checkout@v3

- name: Build & Deploy
env:
DEPLOY_PRI: ${{secrets.DEPLOY_PRI}}
DP_Id: ${{secrets.DP_ID}}
DP_Key: ${{secrets.DP_KEY}}
run: |
echo "$DEPLOY_PRI" > ./deploy/docker.deps/ssh-key.txt
docker build -t my-renew-certs -f ./deploy/renew-certs/Dockerfile .
docker run -i --rm -e "DP_Id=$DP_Id" -e "DP_Key=$DP_Key" my-renew-certs /bin/renew-certs.sh

参考链接