-
部署 Let's Encrypt 免费 SSL 证书及自动续期
一、环境说明
本文使用 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=../wwwDocker 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 算法 注意:
- 所有域名都需要正确解析到服务器。
- 公网 TCP 80 端口必须可以访问。
- 验证路径不能被 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/nullacme.sh 会定期检查证书有效期,到达续期条件后自动完成:
- 申请新证书。
- 自动完成 HTTP-01 域名验证。
- 更新宿主机证书文件。
- 执行 Nginx 配置检查。
- 自动 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 进行技术文档翻译:从入门到实践
在开源项目中,文档的多语言支持是提升项目影响力的重要环节。最近在为 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 配置代理完整指南
背景
在国内环境下使用 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创建代理配置文件
sudo vim /etc/systemd/system/docker.service.d/http-proxy.conf添加代理配置
[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: 本地域名
- 内网私有镜像仓库域名
重载配置并重启 Docker
# 重载 systemd 配置 sudo systemctl daemon-reload # 重启 Docker 服务 sudo systemctl restart docker验证配置
# 查看 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测试代理连接
# 测试是否能通过代理访问 Docker Hub curl -x http://your-proxy-ip:port -I https://registry-1.docker.io/v2/ # 拉取测试镜像 docker pull hello-world
-
入职满 11 周年纪念日


-
在 macOS(Apple Silicon)根目录下创建目录的正确方式
在 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 安全完赛
2025 海淀马拉松 3:39 安全完赛


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




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



-
入职满 10 周年纪念日
时光荏苒,岁月如梭,十年风雨,不负韶华。


-
通过 pyenv 配合 venv 来创建项目专属的虚拟环境
安装
pyenvcurl https://pyenv.run | bash这条命令会自动安装以下工具:
pyenvpyenv-doctor(检查pyenv安装的健康状况)pyenv-virtualenv(用于创建 Python 虚拟环境)
更新 Shell 配置
vim ~/.bashrcecho -e 'export PATH="$HOME/.pyenv/bin:$PATH"\n' \ 'eval "$(pyenv init --path)"\n' \ 'eval "$(pyenv init -)"\n' \ 'eval "$(pyenv virtualenv-init -)"' >> ~/.bashrcsource ~/.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 |
文章标签
- Linux
- Go
- Yii
- 新浪
- CentOS
- PHP
- Git
- WSL
- Composer
- Mac
- 入职
- Bootstrap
- 翻译
- UCenter
- 厦门
- 出差
- 长沙
- 湖南卫视
- 微博
- Tengine
- YUI
- 泰国
- pecl
- 优化
- GitLab
- 迁移
- rootless
- 年会
- 生日
- Tengin
- RedHat
- Sphinx
- cygwin
- Windows
- Tmux
- Zsh
- 升级
- MySQL
- sql_mode
- Shadowsockets
- 面向对象
- HTTP
- 状态码
- grep
- unoconv
- PPT
- Nginx
- htpasswd
- golang
最新评论
-
Tengine 2.2.2 配置 http2 协议出现的坑 -
Yii China 是官方唯一认可的中文社区 -
Go 语言中 json 的操作以及常见问题 -
新浪赴泰国曼谷和芭提雅团建 -
CentOS 安装 PHP7 -
WordPress 如何控制每页显示的条数 -
关于 phpMyAdmin 免输入用户名和密码,直接进入管理界面 -
PHP 5.4 的新特性 -
PHP 5.4 的新特性 -
PHP 5.4 的新特性