How do I create automatic SSL renewals with certbot

Please fill out the fields below so we can help you better. Note: you must provide your domain name to get help. Domain names for issued certificates are all made public in Certificate Transparency logs (e.g. crt.sh | example.com), so withholding your domain name here does not increase secrecy, but only makes it harder for us to provide help.

My domain is:a01.sj.js.cn

I ran this command:sudo certbot --nginx -d a01.sj.js.cn

It produced this output:
http-01 challenge for a01.sj.js.cn
Waiting for verification...
Challenge failed for domain a01.sj.js.cn
http-01 challenge for a01.sj.js.cn

Certbot failed to authenticate some domains (authenticator: nginx). The Certificate Authority reported these problems:
Domain: a01.sj.js.cn
Type: connection
Detail: 47.108.73.109: Fetching http://a01.sj.js.cn/.well-known/acme-challenge/NNa1YxSdfClaulfIiZjBrwy_teiVlL1puBCGQC_KNtE: Connection reset by peer

Hint: The Certificate Authority failed to verify the temporary nginx configuration changes made by Certbot. Ensure the listed domains point to this nginx server and that it is accessible from the internet.

Cleaning up challenges
Some challenges have failed.
Ask for help or search for solutions at https://community.letsencrypt.org. See the logfile /var/log/letsencrypt/letsencrypt.log or re-run Certbot with -v for more details.

My web server is (include version):nginx version: nginx/1.22.1

The operating system my web server runs on is (include version):
Distributor ID: Debian
Description: Debian GNU/Linux 12 (bookworm)
Release: 12
Codename: bookworm

My hosting provider, if applicable, is:aliyun

I can login to a root shell on my machine (yes or no, or I don't know):yes,maybe

I'm using a control panel to manage my site (no, or provide the name and version of the control panel):

The version of my client is (e.g. output of certbot --version or certbot-auto --version if you're using Certbot):certbot 2.1.0

ison@ali-01:~$ sudo tail -n 50 /var/log/letsencrypt/letsencrypt.log
2025-04-07 14:29:46,436:DEBUG:certbot._internal.display.obj:Notifying user:
Certbot failed to authenticate some domains (authenticator: nginx). The Certificate Authority reported these problems:
Domain: a01.sj.js.cn
Type: connection
Detail: 47.108.73.109: Fetching http://a01.sj.js.cn/.well-known/acme-challenge/NNa1YxSdfClaulfIiZjBrwy_teiVlL1puBCGQC_KNtE: Connection reset by peer

Hint: The Certificate Authority failed to verify the temporary nginx configuration changes made by Certbot. Ensure the listed domains point to this nginx server and that it is accessible from the internet.

2025-04-07 14:29:46,437:DEBUG:certbot._internal.error_handler:Encountered exception:
Traceback (most recent call last):
File "/usr/lib/python3/dist-packages/certbot/_internal/auth_handler.py", line 106, in handle_authorizations
self._poll_authorizations(authzrs, max_retries, best_effort)
File "/usr/lib/python3/dist-packages/certbot/_internal/auth_handler.py", line 206, in _poll_authorizations
raise errors.AuthorizationError('Some challenges have failed.')
certbot.errors.AuthorizationError: Some challenges have failed.

2025-04-07 14:29:46,437:DEBUG:certbot._internal.error_handler:Calling registered functions
2025-04-07 14:29:46,437:INFO:certbot._internal.auth_handler:Cleaning up challenges
2025-04-07 14:29:47,534:DEBUG:certbot._internal.log:Exiting abnormally:
Traceback (most recent call last):
File "/usr/bin/certbot", line 33, in
sys.exit(load_entry_point('certbot==2.1.0', 'console_scripts', 'certbot')())
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3/dist-packages/certbot/main.py", line 19, in main
return internal_main.main(cli_args)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3/dist-packages/certbot/_internal/main.py", line 1736, in main
return config.func(config, plugins)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3/dist-packages/certbot/_internal/main.py", line 1440, in run
new_lineage = _get_and_save_cert(le_client, config, domains,
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3/dist-packages/certbot/_internal/main.py", line 138, in _get_and_save_cert
lineage = le_client.obtain_and_enroll_certificate(domains, certname)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3/dist-packages/certbot/_internal/client.py", line 516, in obtain_and_enroll_certificate
cert, chain, key, _ = self.obtain_certificate(domains)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3/dist-packages/certbot/_internal/client.py", line 428, in obtain_certificate
orderr = self._get_order_and_authorizations(csr.data, self.config.allow_subset_of_names)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3/dist-packages/certbot/_internal/client.py", line 496, in _get_order_and_authorizations
authzr = self.auth_handler.handle_authorizations(orderr, self.config, best_effort)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3/dist-packages/certbot/_internal/auth_handler.py", line 106, in handle_authorizations
self._poll_authorizations(authzrs, max_retries, best_effort)
File "/usr/lib/python3/dist-packages/certbot/_internal/auth_handler.py", line 206, in _poll_authorizations
raise errors.AuthorizationError('Some challenges have failed.')
certbot.errors.AuthorizationError: Some challenges have failed.
2025-04-07 14:29:47,535:ERROR:certbot._internal.log:Some challenges have failed.

Welcome @Isonjia

I cannot reproduce your "reset by peer" error any more. Perhaps you fixed that. But, it looks like you need to resolve your ICP Filing yet.

I get this error for any HTTP request (even your home page)

curl -i http://a01.sj.js.cn/.well-known/acme-challenge/Test404

HTTP/1.1 403 Forbidden
Server: Beaver

<html>
<head>

<title>Non-compliance ICP Filing</title>
1 Like

Hello, I am very glad to receive your reply. I reinstalled my cloud server and tried the operation again. The operation is as follows。
1 # 更新软件包列表
2 sudo apt update
3 # 升级已安装的软件包
4 sudo apt upgrade -y
5 # 安装 Nginx 服务器
6 sudo apt install nginx -y
7 # 添加 Certbot 软件源
8 sudo apt install certbot python3-certbot-nginx -y
9 # 编辑 Nginx 配置文件
10 sudo nano /etc/nginx/sites-available/a01.sj.js.cn
11 sudo ln -s /etc/nginx/sites-available/a01.sj.js.cn /etc/nginx/sites-enabled/
12 sudo nginx -t
13 sudo systemctl restart nginx
14 # 创建验证目录
15 sudo mkdir -p /var/www/html/.well-known/acme-challenge
16 # 设置目录权限
17 sudo chown -R www-data:www-data /var/www/html
18 sudo chmod -R 755 /var/www/html
19 sudo certbot --nginx -d a01.sj.js.cn
20 ping a01.sj.js.cn
21 dig a01.sj.js.cn
22 sudo tail -n 50 /var/log/letsencrypt/letsencrypt.log
23 history
Here is my nginx configuration information:
server {
listen 80;
server_name a01.sj.js.cn;

# 配置 Let's Encrypt 验证路径
location ^~ /.well-known/acme-challenge/ {
    default_type "text/plain";
    root /var/www/html;
}

# 其他配置
location / {
    # 这里可以添加你的网站配置
    return 301 https://$host$request_uri; # 重定向到 HTTPS
}

}
Also this is my log file information:
ison@ali-01:~$ sudo tail -n 100 /var/log/letsencrypt/letsencrypt.log
2025-04-09 13:46:11,544:DEBUG:acme.client:Received response:
HTTP 200
Server: nginx
Date: Wed, 09 Apr 2025 05:46:11 GMT
Content-Type: application/json
Content-Length: 1024
Connection: keep-alive
Boulder-Requester: 2330585977
Cache-Control: public, max-age=0, no-cache
Link: https://acme-v02.api.letsencrypt.org/directory;rel="index"
Replay-Nonce: 6Oat0CnApgCpxt7kNThTGt9Dq4104-RuKbJdQQSKbopc-YpusQ8
X-Frame-Options: DENY
Strict-Transport-Security: max-age=604800

{
"identifier": {
"type": "dns",
"value": "a01.sj.js.cn"
},
"status": "invalid",
"expires": "2025-04-16T05:46:07Z",
"challenges": [
{
"type": "http-01",
"url": "https://acme-v02.api.letsencrypt.org/acme/chall/2330585977/502726103917/LrSO6Q",
"status": "invalid",
"validated": "2025-04-09T05:46:09Z",
"error": {
"type": "urn:ietf:params:acme:error:unauthorized",
"detail": "47.108.73.109: Invalid response from http://a01.sj.js.cn/.well-known/acme-challenge/Bw9Qu7Op8TkkT_zZCT6VO_z8P45jVm5e8GBEviwiM08: 403",
"status": 403
},
"token": "Bw9Qu7Op8TkkT_zZCT6VO_z8P45jVm5e8GBEviwiM08",
"validationRecord": [
{
"url": "http://a01.sj.js.cn/.well-known/acme-challenge/Bw9Qu7Op8TkkT_zZCT6VO_z8P45jVm5e8GBEviwiM08",
"hostname": "a01.sj.js.cn",
"port": "80",
"addressesResolved": [
"47.108.73.109"
],
"addressUsed": "47.108.73.109"
}
]
}
]
}
2025-04-09 13:46:11,544:DEBUG:acme.client:Storing nonce: 6Oat0CnApgCpxt7kNThTGt9Dq4104-RuKbJdQQSKbopc-YpusQ8
2025-04-09 13:46:11,544:INFO:certbot._internal.auth_handler:Challenge failed for domain a01.sj.js.cn
2025-04-09 13:46:11,544:INFO:certbot._internal.auth_handler:http-01 challenge for a01.sj.js.cn
2025-04-09 13:46:11,545:DEBUG:certbot._internal.display.obj:Notifying user:
Certbot failed to authenticate some domains (authenticator: nginx). The Certificate Authority reported these problems:
Domain: a01.sj.js.cn
Type: unauthorized
Detail: 47.108.73.109: Invalid response from http://a01.sj.js.cn/.well-known/acme-challenge/Bw9Qu7Op8TkkT_zZCT6VO_z8P45jVm5e8GBEviwiM08: 403

Hint: The Certificate Authority failed to verify the temporary nginx configuration changes made by Certbot. Ensure the listed domains point to this nginx server and that it is accessible from the internet.

2025-04-09 13:46:11,546:DEBUG:certbot._internal.error_handler:Encountered exception:
Traceback (most recent call last):
File "/usr/lib/python3/dist-packages/certbot/_internal/auth_handler.py", line 106, in handle_authorizations
self._poll_authorizations(authzrs, max_retries, best_effort)
File "/usr/lib/python3/dist-packages/certbot/_internal/auth_handler.py", line 206, in _poll_authorizations
raise errors.AuthorizationError('Some challenges have failed.')
certbot.errors.AuthorizationError: Some challenges have failed.

2025-04-09 13:46:11,547:DEBUG:certbot._internal.error_handler:Calling registered functions
2025-04-09 13:46:11,547:INFO:certbot._internal.auth_handler:Cleaning up challenges
2025-04-09 13:46:12,663:DEBUG:certbot._internal.log:Exiting abnormally:
Traceback (most recent call last):
File "/usr/bin/certbot", line 33, in
sys.exit(load_entry_point('certbot==2.1.0', 'console_scripts', 'certbot')())
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3/dist-packages/certbot/main.py", line 19, in main
return internal_main.main(cli_args)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3/dist-packages/certbot/_internal/main.py", line 1736, in main
return config.func(config, plugins)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3/dist-packages/certbot/_internal/main.py", line 1440, in run
new_lineage = _get_and_save_cert(le_client, config, domains,
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3/dist-packages/certbot/_internal/main.py", line 138, in _get_and_save_cert
lineage = le_client.obtain_and_enroll_certificate(domains, certname)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3/dist-packages/certbot/_internal/client.py", line 516, in obtain_and_enroll_certificate
cert, chain, key, _ = self.obtain_certificate(domains)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3/dist-packages/certbot/_internal/client.py", line 428, in obtain_certificate
orderr = self._get_order_and_authorizations(csr.data, self.config.allow_subset_of_names)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3/dist-packages/certbot/_internal/client.py", line 496, in _get_order_and_authorizations
authzr = self.auth_handler.handle_authorizations(orderr, self.config, best_effort)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3/dist-packages/certbot/_internal/auth_handler.py", line 106, in handle_authorizations
self._poll_authorizations(authzrs, max_retries, best_effort)
File "/usr/lib/python3/dist-packages/certbot/_internal/auth_handler.py", line 206, in _poll_authorizations
raise errors.AuthorizationError('Some challenges have failed.')
certbot.errors.AuthorizationError: Some challenges have failed.
2025-04-09 13:46:12,665:ERROR:certbot._internal.log:Some challenges have failed.

My version is Debian 12.10 64-bit, I now suspect that it is python3 in certbot, I wonder if I need to modify python.

I was able to apply for an SSL certificate without using Let's Encrypt technology, that is, without adding /.well-known/acme-challenge to the nginx configuration file. I feel like this is the problem with the python3 dependency that Let's Encrypt needs.
Here's my code for that: 1. 系统更新

在安装新软件之前,先更新系统的软件包列表和已安装的软件包到最新版本。

bash

# 更新软件包列表
sudo apt update
# 升级已安装的软件包到最新版本
sudo apt upgrade -y

2. 安装 Nginx

如果系统中尚未安装 Nginx,需要进行安装。

bash

# 安装 Nginx
sudo apt install nginx -y

3. 配置 Nginx 服务器块

在获取 SSL 证书之前,需要确保 Nginx 配置正确地指向你的域名。创建或编辑 Nginx 服务器块配置文件。

bash

# 创建 Nginx 服务器块配置文件
sudo nano /etc/nginx/sites-available/a01.sj.js.cn

在打开的文件中添加以下内容:

nginx

server {
    listen 80;
    server_name a01.sj.js.cn;

    # 网站文件根目录,根据实际情况修改
    root /var/www/a01.sj.js.cn;
    index index.html index.htm;

    location / {
        try_files $uri $uri/ =404;
    }
}

保存并退出文件。然后创建从 sites-availablesites-enabled 的符号链接,启用该服务器块:

bash

sudo ln -s /etc/nginx/sites-available/a01.sj.js.cn /etc/nginx/sites-enabled/

检查 Nginx 配置文件的语法是否正确:

bash

sudo nginx -t

如果语法检查通过,重新加载 Nginx 服务使配置生效:

bash

sudo systemctl reload nginx

4. 安装 Certbot

Certbot 是用于获取和管理 Let's Encrypt SSL 证书的工具,通过 snap 包管理器来安装它。

bash

# 安装 snapd 以支持 snap 包管理
sudo apt install snapd -y
# 确保 snapd 最新
sudo snap install core
sudo snap refresh core
# 移除旧版本的 certbot(如果有)
sudo apt remove certbot
# 安装 certbot
sudo snap install --classic certbot
# 创建 certbot 命令的软链接
sudo ln -s /snap/bin/certbot /usr/bin/certbot

5. 获取 SSL 证书

使用 certbot 为域名 a01.sj.js.cn 获取 SSL 证书。

bash

# 运行 certbot 以获取并安装 SSL 证书
sudo certbot --nginx -d a01.sj.js.cn

执行该命令后,certbot 会检查你的域名配置,验证域名所有权,然后自动下载并安装 SSL 证书。你需要按照提示输入邮箱地址、同意服务条款等。

6. 验证 Certbot 自动配置的 Nginx 配置

certbot 在获取证书后会自动更新 Nginx 配置文件,使其支持 HTTPS。可以查看 /etc/nginx/sites-available/a01.sj.js.cn 文件,确认配置是否正确。更新后的配置文件大致如下:

nginx

server {
    listen 80;
    server_name a01.sj.js.cn;
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl;
    server_name a01.sj.js.cn;

    # SSL 证书配置
    ssl_certificate /etc/letsencrypt/live/a01.sj.js.cn/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/a01.sj.js.cn/privkey.pem;

    # 网站文件根目录,根据实际情况修改
    root /var/www/a01.sj.js.cn;
    index index.html index.htm;

    location / {
        try_files $uri $uri/ =404;
    }
}

这个配置文件将 HTTP 请求重定向到 HTTPS,并配置了 SSL 证书的路径。

7. 验证 SSL 证书安装

通过访问 https://a01.sj.js.cn 来验证 SSL 证书是否正确安装。若浏览器地址栏显示锁图标,表明证书安装成功。

8. 设置自动续费

Let's Encrypt 证书的有效期为 90 天,需要设置自动续费以保证证书始终有效。certbot 提供了 renew 命令来进行证书续费,可以通过 cron 任务来定期执行该命令。

bash

# 编辑 crontab 文件
sudo crontab -e

在打开的文件中添加以下内容:

plaintext

# 每月 1 号的 3:00 执行证书续费检查
0 3 1 * * /usr/bin/certbot renew --quiet --deploy-hook "/usr/sbin/service nginx reload"

这段代码的含义是在每月 1 号的 3:00 执行 certbot renew 命令来检查证书是否需要续费。--quiet 选项表示在执行过程中不输出多余信息,--deploy-hook 选项指定在证书成功续费时执行的命令,这里是重新加载 Nginx 服务器。

保存并退出文件后,cron 任务就设置好了,会定期检查并自动续费证书。

通过以上步骤,你可以在 Debian 系统上使用 Nginx 为域名 a01.sj.js.cn 添加 SSL 证书并设置自动续费。

Website filing doesn't matter, I just want to test if I can implement a lock on the website, that is, an SSL certificate. For example, https://a02.sj.js.cn/, this is normal. There is an SSL lock, indicating that the link is secure.

Please appreciate the difference between the ACME client (Certbot) and the ACME server (Let's Encrypt). Any local dependency issue would be with the client and thus not with Let's Encrypt (the server).

There's no such thing as "Let's Encrypt technology". There is the ACME protocol (RFC 8555) though.

Also, the /.well-known/acme-challenge/ path is just one of the possible ACME challenges available.

Hate to break it to you, but the --nginx option simply automates the whole /.well-known/acme-challenge/ path thing in a different matter. Glad you got it working though, which is ultimately the goal of course :slight_smile:

The snap version of Certbot should install a systemd timer taking care of the renewals.

When using the --nginx option, nginx should be reloaded automatically after renewal, so this deploy hook is not necessary. It's also not recommended to put a --deploy-hook in your renew subcommand, it's better (I think) to have them in a per-certificate matter. You can add a hook by using the reconfigure subcommand.

1 Like