• 部署 Let's Encrypt 免费 SSL 证书及自动续期

    26-02-02 10:30 44 0 技术

    一、环境说明

    本文使用 Let’s Encrypt + acme.sh 为 Docker Nginx 部署免费 SSL 证书,实现证书自动申请、自动续期和自动部署。

    项目 配置
    操作系统 AlmaLinux 9.7
    Web 服务 Nginx
    部署方式 Docker Compose
    证书机构 Let’s Encrypt
    证书管理 acme.sh
    验证方式 HTTP-01
    证书算法 ECC P-256

    本次以以下四个域名为例:

    • cuiliang.com
    • www.cuiliang.com
    • cuiliang.com.cn
    • www.cuiliang.com.cn

    使用一张多域名证书统一管理,最终跳转到 https://www.cuiliang.com。

    二、安装 acme.sh

    考虑到服务器位于中国大陆,优先使用 Gitee 安装,避免 GitHub 访问不稳定导致安装失败。

    1. Gitee 安装(推荐)

    git clone https://gitee.com/neilpang/acme.sh.git
    
    cd acme.sh
    
    ./acme.sh --install -m your-email@example.com
    

    将邮箱替换为自己的邮箱。

    2. GitHub 安装(备用)

    如果服务器可以正常访问 GitHub,也可以使用官方安装方式:

    curl https://get.acme.sh | sh -s email=your-email@example.com
    

    安装完成后,acme.sh 默认安装在:

    /root/.acme.sh/
    

    后续使用:

    ~/.acme.sh/acme.sh
    

    执行相关操作。

    三、配置 Let’s Encrypt

    设置 Let’s Encrypt 为默认证书颁发机构:

    ~/.acme.sh/acme.sh --set-default-ca --server letsencrypt
    

    四、配置 Docker Nginx

    当前 Docker Compose 已经挂载了网站目录和 SSL 证书目录:

    volumes:
      - ${PROJECT_FOLDER}:/var/www/html/:rw
      - ./nginx/ssl:/etc/nginx/ssl
    

    当前 .env 配置:

    PROJECT_FOLDER=../www
    

    Docker Compose 项目目录为 /root/docker,因此对应的宿主机目录为:

    宿主机目录 容器目录
    /root/www /var/www/html
    /root/docker/nginx/ssl /etc/nginx/ssl

    直接复用现有目录,不需要增加 Docker Volume。

    1. 修改 Nginx 配置

    将 HTTP 和 HTTPS 分开配置:

    # HTTP:证书验证及 HTTPS 跳转
    server {
        listen 80;
    
        server_name cuiliang.com www.cuiliang.com
                    cuiliang.com.cn www.cuiliang.com.cn;
    
        # Let's Encrypt HTTP-01 验证
        location ^~ /.well-known/acme-challenge/ {
            root /var/www/html;
            default_type text/plain;
            autoindex off;
            try_files $uri =404;
        }
    
        # 其他请求统一跳转 HTTPS
        location / {
            return 301 https://www.cuiliang.com$request_uri;
        }
    }
    
    
    # HTTPS:正式业务服务
    server {
        listen 443 ssl http2;
    
        server_name cuiliang.com www.cuiliang.com
                    cuiliang.com.cn www.cuiliang.com.cn;
    
        # 统一跳转到主域名
        if ($host != www.cuiliang.com) {
            return 301 https://www.cuiliang.com$request_uri;
        }
    
        ssl_certificate /etc/nginx/ssl/www.cuiliang.com.pem;
        ssl_certificate_key /etc/nginx/ssl/www.cuiliang.com.key;
    
        ssl_session_timeout 5m;
        ssl_protocols TLSv1.2 TLSv1.3;
    
        ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
    
        location / {
            proxy_pass http://go:8080;
    
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
        }
    }
    

    注意:首次部署时,如果新证书文件尚未生成,可以暂时保留原有 HTTPS 证书路径,签发成功后再切换。

    2. 创建验证目录

    mkdir -p /root/www/.well-known/acme-challenge
    

    验证目录映射关系:

    宿主机:
    /root/www/.well-known/acme-challenge/
    
    Docker:
    /var/www/html/.well-known/acme-challenge/
    

    3. 检查验证路径

    创建测试文件:

    echo test123 > /root/www/.well-known/acme-challenge/test.txt
    

    访问:

    curl http://www.cuiliang.com/.well-known/acme-challenge/test.txt
    

    正常返回:

    test123
    

    测试完成后删除:

    rm -f /root/www/.well-known/acme-challenge/test.txt
    

    五、申请 Let’s Encrypt 证书

    使用 HTTP-01 验证方式申请证书。

    ~/.acme.sh/acme.sh --issue \
      --server letsencrypt \
      --webroot /root/www \
      -d cuiliang.com \
      -d www.cuiliang.com \
      -d cuiliang.com.cn \
      -d www.cuiliang.com.cn \
      --keylength ec-256
    

    参数说明:

    参数 说明
    --server letsencrypt 使用 Let’s Encrypt
    --webroot 指定 HTTP 验证目录
    -d 指定证书覆盖的域名
    --keylength ec-256 使用 ECC P-256 算法

    注意:

    1. 所有域名都需要正确解析到服务器。
    2. 公网 TCP 80 端口必须可以访问。
    3. 验证路径不能被 Nginx 的 301 跳转、鉴权或业务路由拦截。

    六、安装证书

    创建证书目录:

    mkdir -p /root/docker/nginx/ssl
    

    安装证书:

    ~/.acme.sh/acme.sh --install-cert \
      -d cuiliang.com \
      --key-file /root/docker/nginx/ssl/www.cuiliang.com.key \
      --fullchain-file /root/docker/nginx/ssl/www.cuiliang.com.pem \
      --reloadcmd "docker exec nginx nginx -t && docker exec nginx nginx -s reload"
    

    证书文件:

    /root/docker/nginx/ssl/
    ├── www.cuiliang.com.pem
    └── www.cuiliang.com.key
    

    其中:

    • .pem:完整证书链。
    • .key:证书私钥,需要妥善保管。

    Nginx 使用对应的容器内路径:

    ssl_certificate /etc/nginx/ssl/www.cuiliang.com.pem;
    ssl_certificate_key /etc/nginx/ssl/www.cuiliang.com.key;
    

    检查并 Reload:

    docker exec nginx nginx -t &&
    docker exec nginx nginx -s reload
    

    七、自动续期

    acme.sh 安装时会自动创建 Cron 定时任务,不需要手动添加。

    查看定时任务:

    crontab -l
    

    通常会看到类似:

    0 0 * * * "/root/.acme.sh"/acme.sh --cron --home "/root/.acme.sh" > /dev/null
    

    acme.sh 会定期检查证书有效期,到达续期条件后自动完成:

    1. 申请新证书。
    2. 自动完成 HTTP-01 域名验证。
    3. 更新宿主机证书文件。
    4. 执行 Nginx 配置检查。
    5. 自动 Reload Docker Nginx。

    整个过程不需要手动添加 TXT 记录,也不需要人工更换证书。

    八、常用维护命令

    # 查看证书列表
    ~/.acme.sh/acme.sh --list
    
    # 查看 Cron 定时任务
    crontab -l
    
    # 查看证书有效期
    openssl x509 \
      -in /root/docker/nginx/ssl/www.cuiliang.com.pem \
      -noout -subject -dates
    
    # 检查 Nginx 配置
    docker exec nginx nginx -t
    
    # Reload Nginx
    docker exec nginx nginx -s reload
    

    九、总结

    通过 Let’s Encrypt + acme.sh,可以实现 Docker Nginx 的免费 SSL 证书自动化管理。

    主要特点:

    • 免费使用 Let’s Encrypt 证书。
    • 国内服务器优先通过 Gitee 安装 acme.sh。
    • 不需要阿里云 AccessKey。
    • 不需要手动添加 DNS TXT 记录。
    • 不需要额外增加 Docker Volume。
    • 支持多个业务域名统一管理。
    • 自动申请、自动续期、自动部署。
    • 续期后自动 Reload Docker Nginx。

    整个方案只需要首次配置一次,后续证书续期和部署均由 acme.sh 自动完成。

  • 使用 po4a 进行技术文档翻译:从入门到实践

    26-01-23 19:23 2259 4 技术

    在开源项目中,文档的多语言支持是提升项目影响力的重要环节。最近在为 Yii3 框架文档添加简体中文翻译时,我深入使用了 po4a 这个强大的翻译工具。本文将分享使用 po4a 进行技术文档翻译的完整流程和实践经验。

    什么是 po4a?

    po4a(PO for Anything)是一个基于 gettext 的文档翻译工具,最初为 Debian 项目开发,但现在已经广泛应用于各种文档翻译场景。它的核心优势在于:

    • 格式无关:支持 Markdown、POD、XML、HTML 等多种格式
    • 版本控制友好:翻译文件(.po)是纯文本,易于纳入 Git 管理
    • 增量更新:源文件更新时,自动合并已有翻译,避免重复工作
    • 团队协作:支持多人协作翻译,便于分工

    项目结构

    在开始之前,先了解典型的 po4a 项目结构:

    docs/
    ├── _translations/        # 翻译配置和 PO 文件
    │   ├── po4a.conf         # 主配置文件
    │   ├── pot/              # 模板文件(.pot)
    │   └── po/               # 翻译文件(.po)
    │       └── zh-CN/        # 简体中文翻译
    ├── src/                  # 源文件和翻译输出
    │   ├── en/               # 英文源文件
    │   └── zh-CN/            # 简体中文翻译输出
    

    这种结构将翻译工作与源文件分离,既保持了源文件的整洁,又便于管理翻译进度。

  • Docker 配置代理完整指南

    26-01-21 17:18 2822 0 技术

    背景

    在国内环境下使用 Docker 时,经常遇到拉取镜像缓慢或超时的问题。虽然可以配置镜像加速器,但随着国内镜像源的不稳定,使用代理成为了更可靠的解决方案。

    问题现象

    执行 docker build 或 docker pull 时出现以下错误:

    ERROR: failed to solve: DeadlineExceeded: failed to resolve source metadata for docker.io/xxx
    dial tcp xxx.xxx.xxx.xxx:443: i/o timeout
    

    核心原理

    Docker 架构分为两部分: - Docker Client: 命令行工具,接收用户命令 - Docker Daemon: 后台服务,实际执行拉取镜像等操作 当我们在终端设置 export HTTP_PROXY=... 时,只影响 Docker Client,而真正需要网络访问的 Docker Daemon 并未使用代理。

    解决方案

    为 Docker Daemon 配置代理(推荐) 1. 创建 systemd 配置目录

    sudo mkdir -p /etc/systemd/system/docker.service.d
    
    1. 创建代理配置文件

      sudo vim /etc/systemd/system/docker.service.d/http-proxy.conf
      
    2. 添加代理配置

      [Service]
      Environment="HTTP_PROXY=http://your-proxy-ip:port"
      Environment="HTTPS_PROXY=http://your-proxy-ip:port"
      Environment="NO_PROXY=localhost,127.0.0.1,*.local,registry.internal.com"
      

      配置说明:

    • HTTP_PROXY: HTTP 协议代理地址
    • HTTPS_PROXY: HTTPS 协议代理地址(Docker Hub 使用 HTTPS)
    • NO_PROXY: 不使用代理的地址列表,通常包括:
      • localhost, 127.0.0.1: 本地地址
      • *.local: 本地域名
      • 内网私有镜像仓库域名
    1. 重载配置并重启 Docker

      # 重载 systemd 配置
      sudo systemctl daemon-reload
      # 重启 Docker 服务
      sudo systemctl restart docker
      
    2. 验证配置

      # 查看 Docker 服务的环境变量
      sudo systemctl show --property=Environment docker
      

      预期输出:

      Environment=HTTP_PROXY=http://your-proxy-ip:port HTTPS_PROXY=http://your-proxy-ip:port NO_PROXY=localhost,127.0.0.1
      
    3. 测试代理连接

      # 测试是否能通过代理访问 Docker Hub
      curl -x http://your-proxy-ip:port -I https://registry-1.docker.io/v2/
      # 拉取测试镜像
      docker pull hello-world
      
  • 入职满 11 周年纪念日

    26-01-20 10:19 2171 0 生活

    79EE5F71-BDDD_thumb.jpg

    IMG_7957.JPG

  • 在 macOS(Apple Silicon)根目录下创建目录的正确方式

    25-10-29 17:30 3267 0 技术

    在 macOS 上,我想在根目录(/)下创建一个目录,比如 /data1,用于放置项目数据。

    mkdir /data1
    

    结果系统提示:

    mkdir: /data1: Read-only file system
    

    一开始我以为是权限问题,于是又试了:

    sudo mkdir /data1
    

    但依然报错,说明即使 sudo 也不行。

    为什么会这样?

    从 macOS Big Sur(11) 开始,苹果对系统盘启用了 Signed System Volume(SSV)签名保护机制。

    这意味着:

    系统卷 / 是 只读的 APFS 快照;

    即使是 root 用户,也不能直接修改;

    mount -uw / 在 Apple Silicon(M1/M2/M3)上会报错:

    mount_apfs: volume could not be mounted: Permission denied
    mount: / failed with 66
    

    简单来说:根目录是锁死的。

  • 2025 海淀马拉松 3:39 安全完赛

    25-10-14 17:28 2928 0 跑步

    2025 海淀马拉松 3:39 安全完赛

    9c43b356be68a5.JPG
    IMG_0984_thumb.jpg
  • 西北旺第四届十公里竞速赛 PB 44:11

    25-09-28 15:00 2972 0 跑步

    西北旺第四届十公里竞速赛 PB,成绩 44:11,配速 4:25,排名 40(500 人参赛)

    西北旺十公里竞速赛_thumb.jpeg

    IMG_7516.PNG

    43c45a461d7f085af8ccf003bf824033.JPG

    IMG_7506.PNG

  • 2025北京亦庄半程马拉松暨人形机器人马拉松安全完赛

    25-04-19 15:52 3801 0 跑步

    2025北京亦庄半程马拉松暨人形机器人马拉松安全完赛,第一次和机器人一起参加比赛,最近太忙训练太少,虽然没有 PB,但是今天的发挥也相当满意!

    aedd09da708030ae2501b73fe9b278_thumb.jpg

    IMG_6782_thumb.jpg

    IMG_6783_thumb.jpg

  • 入职满 10 周年纪念日

    25-01-20 09:49 6003 0 生活

    时光荏苒,岁月如梭,十年风雨,不负韶华。

    lALPDfJ6ffmvLUbNCMDNBNo_1242_2240_thumb.jpg

    WechatIMG324_thumb.jpg

  • 通过 pyenv 配合 venv 来创建项目专属的虚拟环境

    24-12-03 17:37 6824 0 技术

    安装 pyenv

    curl https://pyenv.run | bash
    

    这条命令会自动安装以下工具:

    • pyenv
    • pyenv-doctor(检查 pyenv 安装的健康状况)
    • pyenv-virtualenv(用于创建 Python 虚拟环境)

    更新 Shell 配置

    vim ~/.bashrc
    
    echo -e 'export PATH="$HOME/.pyenv/bin:$PATH"\n' \
        'eval "$(pyenv init --path)"\n' \
        'eval "$(pyenv init -)"\n' \
        'eval "$(pyenv virtualenv-init -)"' >> ~/.bashrc
    
    source ~/.bashrc
    

    安装 Python 版本

    pyenv install 3.11.9
    

    设置全局或本地 Python 版本

    设置一个全局的 Python 版本(用于所有项目):

    pyenv global 3.11.9
    

    你还可以为特定目录设置本地版本,例如在某个项目目录下:

    pyenv local 3.8.12
    

    这会创建一个 .python-version 文件,记录该项目使用的 Python 版本。

    创建虚拟环境(使用 venv)

    python -m venv venv
    

    激活虚拟环境

    对于 Bash/Zsh(Linux/macOS):

    source venv/bin/activate
    

    对于 Windows(CMD):

    .\venv\Scripts\activate
    

文章归档

文章日历

2026 年 11 月
日 一 二 三 四 五 六
01 02 03 04 05 06 07
08 09 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
30 01 02 03 04 05 06

文章标签

最新评论

友情链接