FAZE CLAN UP! @razzh.cn

acme.sh 申请 SSL 部署博客至阿里云

Feb 7 · 5 min

#写在之前

本文主要记录了作者如何申请免费的 SSL 证书并部署当前博客到云服务器的过程,分为以下两个阶段:

  • acme.shdocker 中的 Nginx 添加 SSL 证书
  • Github Actions 任务流自动上传提交代码的打包版本至服务器指定目录

整篇教程以 docker 为基础来部署博客至阿里云

#acme.sh

acme.sh是 github 上的一个开源项目,目前以有41K🌟,acme 协议是 Let’s Encrypt 和其他 CA 机构使用的一种网络交互协议,用于自动验证网站/域名并颁发 SSL/TLS 证书。

在签发证书后可同时创建定时任务,在证书将要过期时自动重新申请并部署,其还可以于 Nginx 或者 Apache 直接交互完成证书申请过程。

#docker

如果云服务器上还没安装docker,可以按照阿里云文档 提供的方法安装。

docker 的指令可以见文档

首先,我们需要使用 docker 拉取一个 Nginx 镜像:

docker container run \
  -d \
  --rm \
  --name mynginx \
  nginx
docker container cp mynginx:/etc/nginx .
mv nginx conf
mkdir ./conf/certs
mkdir html
docker stop mynginx
shell

这一步的作用是运行 docker 容器中的 nginx,复制 nginx 的目录文件至当前目录,并创建 certs 目录和 html 目录,目的是为后续与 docker 容器内的 nginx 做数据卷(映射)。

certs 目录是用来在存放证书的目录,而 html 目录则是存放我们博客打包后资源的目录。

docker container run \
  --rm \
  --name mynginx_1 \
  --volume "$PWD/html":/usr/share/nginx/html \
  --volume "$PWD/conf":/etc/nginx \
  --label=sh.acme.autoload.domain=razzh.cn \
  -p 80:80 \
  -p 443:443 \
  -d \
  nginx
shell

因为HTTP和HTTPS的默认端口是80和443,云服务器需要在安全组手动添加80和443端口,才能完成后续的成功访问。

接下来,我们按照 acme.sh 提供的 docker部署文档 来操作。

docker container run \
  --name mynginx_1 \
  --volume "$PWD/html":/usr/share/nginx/html \
  --volume "$PWD/conf":/etc/nginx \
  --label=sh.acme.autoload.domain=razzh.cn \
  -d \
  nginx
shell

文档中要求我们使用 docker 运行一个 nginx,并打上 label 标签,因为后续acme.sh在部署的时候需要用 label 去找到这个容器。

#1. 向阿里云申请API

这里简单的登录后,申请一个 AccessKey IDAccess Key Secret,妥善保存。

#2. 创建 acme.sh 容器

下面的命令将在当前目录创建一个 out 目录存放一些证书文件,但我们将不会直接使用这些文件。

docker run --rm  -itd \
    -v "$(pwd)/out":/acme.sh \
    --net=host \
    --name=acme.sh   \
    -v /var/run/docker.sock:/var/run/docker.sock \
    neilpang/acme.sh daemon
shell

#3. 使用acme.sh申请证书

Ali_KeyAli_Secret 替换为你在本节第一步申请的 AccessKey IDAccess Key Secret,并将 example.com 替换为你的域名,执行,你会看到 checking 的字样,这时 CA 正在颁发证书,稍等两分钟,之后弹出 success 之类的提示词,那么说明,申请证书成功了!~

example.com 一级域名和它的二级域名 *.example.com,都可以使用同一证书。

docker  exec \
    -e Ali_Key="你的Key" \
    -e Ali_Secret="你的Secret"  \
    acme.sh --issue -d example.com -d "*.example.com" --dns dns_ali --server letsencrypt
shell

#4. 使用acme.sh自动部署证书

注意,sh.acme.autoload.domain的值需要与你运行的 nginx 容器 label 值一致,并把文件路径域名替换成自己的。

docker  exec \
    -e DEPLOY_DOCKER_CONTAINER_LABEL=sh.acme.autoload.domain=razzh.cn  \
    -e DEPLOY_DOCKER_CONTAINER_KEY_FILE=/etc/nginx/certs/razzh.cn/key.pem   \
    -e DEPLOY_DOCKER_CONTAINER_CERT_FILE="/etc/nginx/certs/razzh.cn/cert.pem"  \
    -e DEPLOY_DOCKER_CONTAINER_CA_FILE="/etc/nginx/certs/razzh.cn/ca.pem"   \
    -e DEPLOY_DOCKER_CONTAINER_FULLCHAIN_FILE="/etc/nginx/certs/razzh.cn/full.pem"  \
    -e DEPLOY_DOCKER_CONTAINER_RELOAD_CMD="service nginx force-reload"   \
    acme.sh --deploy -d razzh.cn  --deploy-hook docker
shell

#测试

打开你的网站就可以看到

image

证书只有3个月有效期,我们在第四步已经做了自动续期的操作,在证书快到期的时候 acme.sh 会自动续期。

image

#Nginx 配置

SSL 证书已经部署完成,我们还需要配置 Nginx 来监听80和443接口,高亮的行必须跟 dockernginx 中创建数据卷(映射)时的路径一致,网站也要替换成自己的。

#/etc/conf/conf.d/razzh.cn.conf 
server {
    listen       80;
    server_name  razzh.cn;
 
    #80跳转到443
    rewrite ^(.*)$ https://${server_name}$1 permanent;
 
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}
 
server {
    listen 443 ssl http2;
    server_name  razzh.cn;
 
    ssl_certificate          /etc/nginx/certs/razzh.cn/full.pem;
    ssl_certificate_key      /etc/nginx/certs/razzh.cn/key.pem;
 
    ssl_session_timeout  5m;
 
    #开启HSTS
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
 
    ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384;
    #适时移除TLSv1.2
    ssl_protocols TLSv1.3 TLSv1.2;
    ssl_prefer_server_ciphers on;
    ssl_session_cache shared:SSL:10m;
 
    location / {
        root   /usr/share/nginx/html/blog/out;
        index  index.html index.htm;
    }
 
}
nginx

保存好配置后,我们执行命令重启一下 docker 中的 nginx 即可

docker container restart mynginx_1
shell

#Github Actions 部署

要使用工作流,我们需要在项目跟目录下创建一个 .github/workflows 的目录并添加 deploy.yml 的文件,文件名可以随便起。

name: Deploy

on:
  push:
    branches:
      - main
  pull_request:
    branches:
      - main

jobs:
  build:
    # 运行在ubuntu上
    runs-on: ubuntu-latest

    # 任务流步骤
    steps:
      - name: 拉取代码
        uses: actions/checkout@v4

      - name: 安装NodeJS
        uses: actions/setup-node@v4
        with:
          node-version: 20
      - run: npm install -g pnpm@10
      - run: pnpm install
      - run: pnpm build

      - name: 部署博客
        uses: appleboy/scp-action@master
        with:
          host: ${{ secrets.REMOTE_HOST }}
          username: ${{ secrets.REMOTE_USER }}
          password: ${{ secrets.REMOTE_PASS }}
          port: 22
          # 本地打包后的目录
          source: './out/'
          # 服务器存放dist的目录
          target: ${{ secrets.REMOTE_TARGET }}
yml

为了安全性考虑,服务器的信息不能对外暴露,所以我们需要设置 secrets 变量,secrets 变量可在 Github 中的 Settings -> Secrets and variables -> actions 中配置。

代码被 push 到 github 上时就会触发工作流执行这个脚本。

image

#参考

全员docker化!使用docker中的acme.sh为docker中的Nginx添加SSL证书
Github Actions 文档

浙ICP备2024129591号-1
screen-logo
戒网 - 村西&王馨悦
--:-- / --:--
  1. 1戒网村西&王馨悦
  2. 2想念梁博
  3. 3Special OneAGA&Eason
  4. 4可惜我是水瓶座杨千嬅&毛不易
  5. 5爱得太迟古巨基&泳儿
  6. 6听你说梁博
  7. 7黄金时代陈奕迅
  8. 8岁月如歌陈奕迅

男:山海半生漂泊 一叶孤舟

女:天地两世零落 几处离愁

男:本是一处同飞鸟 余生无所求

女:空把青丝等白头

男:清泉无垢倒映着 我的心

女:得见青天总在雨打风吹后

男:知我千万头绪烦忧

女:不知谓我何求

男:可否执子之手

女:来抓住我的手

女:管他虚情假意花落水自流

男:知我千万头绪烦忧

女:不知谓我何求

合:待尽扫西风去 乌有

女:寻遍宫阙不见 良人佳偶

男:一夜雨声多少事 月下强说愁

男:功名休问几时成 今朝酒

女:更无一个肯回头

女:如醉方醒原来情钟不自由

女:不知谓我何求

男:世事不如山丘

女:山青不如水秀

男:为何相见恨晚 情深却不寿

男:知我千万头绪烦忧

女:不知谓我何求

男:独立小桥等风满袖

女:去年此门依旧

合:夜灯为君留 归来否