背景
给朋友做了个作品集网站joshuasprings.art,使用nodejs后端,Nginx反向代理,部署在阿里云的服务器上,用免费的Let's Encrypt提供的certbot做SSL证书注册。
遇到的这个问题,感觉在云平台部署类似的网页服务很容易遇到,但没有查到有关解决方法,所以自己写一个吧。
问题
用这条命令来尝试续期
sudo certbot renew --dry-run
出现的问题是
Certbot failed to authenticate some domains (authenticator: webroot). The Certificate Authority reported these problems:
Domain: joshuasprings.art
Type: unauthorized
Detail: xxx.xxx.xxx.xxx: Invalid response from http://joshuasprings.art/.well-known/acme-challenge/xxxx: 403
Domain: www.joshuasprings.art
Type: unauthorized
Detail: xxx.xxx.xxx.xxx: Invalid response from http://www.joshuasprings.art/.well-known/acme-challenge/xxxx: 403
Hint: The Certificate Authority failed to download the temporary challenge files created by Certbot. Ensure that the listed domains serve their content from the provided --webroot-path/-w and that files created there can be downloaded from the internet.
Failed to renew certificate joshuasprings.art with error: Some challenges have failed.
Let's Encrypt 无法访问验证文件,返回了 403 Forbidden 错误。
无法访问验证文件可能是因为文件权限问题、文件路径配置问题、Nginx配置文件的.well-known/acme-challenge/设置问题、云服务防火墙拦截之类的原因,ai会优先检查这些,网上现有关于这个报错的解决方法也是和这些有关。
尝试解决
用cursor尝试了一个小时,它完全陷入试图解决上述问题的死胡同,禁用了默认server改用webroot。
Claude在检查了文件创建和鉴权之后,想到了外部能否访问的问题,让我使用另一台服务器访问该服务器的测试文件,定位了问题,外部访问返回的重要信息是
HTTP/1.1 403 Forbidden
Server: Beaver
Non-compliance ICP Filing
因为没有ICP备案,所以被阿里云的检查系统拦截了。
让专精模型间协作的cursor思考可能是有些勉强。
解决方法
不使用 HTTP 验证,改用DNS TXT记录验证:
# 停止当前的续期配置
sudo certbot delete --cert-name joshuasprings.art
# 使用 DNS 验证重新获取证书
sudo certbot certonly --manual --preferred-challenges dns -d joshuasprings.art -d www.joshuasprings.art
使用阿里云的DNS插件进行自动续期:
安装阿里云 DNS 插件
# 安装 pip3 (如果还没有)
sudo apt update
sudo apt install python3-pip -y
# 安装阿里云 DNS 插件
sudo pip3 install certbot-dns-aliyun
获取阿里云 AccessKey
- 登录阿里云控制台
- 进入 RAM 访问控制 → 用户 → 创建用户
- 勾选 OpenAPI 调用访问
- 保存 AccessKey ID 和 AccessKey Secret
- 给用户添加权限:找到 AliyunDNSFullAccess 权限并授予
配置凭证文件
# 创建凭证目录
sudo mkdir -p /etc/letsencrypt/.secrets
# 创建凭证文件
sudo vi /etc/letsencrypt/.secrets/aliyun.ini
添加以下内容(替换为你的 AccessKey):
dns_aliyun_access_key = YOUR_ACCESS_KEY_ID
dns_aliyun_access_key_secret = YOUR_ACCESS_KEY_SECRET
保存后设置权限:
sudo chmod 600 /etc/letsencrypt/.secrets/aliyun.ini
修改续期配置
sudo vi /etc/letsencrypt/renewal/joshuasprings.art.conf
在续期配置中加上
authenticator = dns-aliyun
dns_aliyun_credentials = /etc/letsencrypt/.secrets/aliyun.ini