阿里云服务器Nginx SSL证书自动续期认证失败

49 阅读2分钟

背景

给朋友做了个作品集网站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

  1. 登录阿里云控制台
  2. 进入 RAM 访问控制用户 → 创建用户
  3. 勾选 OpenAPI 调用访问
  4. 保存 AccessKey IDAccessKey Secret
  5. 给用户添加权限:找到 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