Error Cron sudo /usr/local/hestia/bin/v-update-letsencrypt-ssl

Hello everyone, when there is one month left before the Let’s Encrypt certificate expires, I start receiving this email:
Cron <admin> sudo /usr/local/hestia/bin/v-update-letsencrypt-ssl

Error: Let’s Encrypt finalize bad status 403

I have tried using this command via SSH, but the certificate doesn’t renew. However, if I remove the certificate from the domain through the graphical interface and generate a new one, it works. I would like to automate this process.
I would also like to mention that this is a dedicated mail server with several domains, and it is behind an Nginx proxy. I need help to automate the Let’s Encrypt renewal process.

Thank you.

Hestia will automatically update the execution for you. It sends you an email to remind you that the certificate is about to expire.

Hi @cheemi99

Regarding the 403 error, try this fix (it should resolve the 403 errors when renewing the certificates automatically):

sudo -i
cd /usr/local/hestia/bin/
mv v-add-letsencrypt-domain v-add-letsencrypt-domain.original
wget https://raw.githubusercontent.com/hestiacp/hestiacp/64210fd8ccee8718a861856e99f9965e40ff3932/bin/v-add-letsencrypt-domain
chmod +x v-add-letsencrypt-domain
1 Like

Hello Sahsanu, thank you for your response!

After following your suggestion, I ran the command:
sudo /usr/local/hestia/bin/v-update-letsencrypt-ssl "domain.com"

And I get the error shown in the image below.
imagen

v-update-letsencrypt-ssl doesn’t use arguments so it is ignoring the "domain.com" part.

Next time, please copy and paste the output; reading a screenshot is a hassle.

Said that, to know what’s going on we need to know the domain name.

1 Like

On the server, I have over 50 domains. The problem is that the automatic renewal doesn’t work with any domain. That’s why I was previously receiving the 403 error, and now the 400 error shown in the image. I apologize, I won’t attach any more images.

To understand the issue better, we need the actual domain name. If you prefer not to share it publicly, feel free to send it to me via a private message.

Additionally, you can find the debug log for Let’s Encrypt renewals at:
/var/log/hestia/LE-YourUser-YourDomain.log

1 Like

One of the domains we can work with is frouexperiencia.c om

The log for the /var/log/LE-user-frouexperiencia.com-log.1
This is the log:


Date Time: 2024-12-16 09:14:15
WEB_SYSTEM: apache2
PROXY_SYSTEM: nginx
user: soporte
domain: frouexperiencia.c om

    aliases:
    proto: http-01
    wildcard:

==[Step 1]==

    status: 200
    nonce: WVWTDxmJ9euVHAFFEDmW-dnQzxh1CcKc97vOfM-wFB8aLMQcJ_g
    answer: HTTP/2 200
    server: nginx
    date: Mon, 16 Dec 2024 08:14:15 GMT
    content-type: application/json
    content-length: 746
    cache-control: public, max-age=0, no-cache
    replay-nonce: WVWTDxmJ9euVHAFFEDmW-dnQzxh1CcKc97vOfM-wFB8aLMQcJ_g
    x-frame-options: DENY
    strict-transport-security: max-age=604800

==[API call]==
exit status: 0

==[Step 2]==

    status: 201
    nonce: LPSR-4-s64tPIFvUDuSpkIIS6betX3yHAsUlSy8UwPxaq96MVLk
    authz:
    finalize:
    payload: {“identifiers”:[{“type”:“dns”,“value”:“frouexperiencia.c om”}]}
    answer: HTTP/2 201
    server: nginx
    date: Mon, 16 Dec 2024 08:14:16 GMT
    content-type: application/json
    content-length: 353
    boulder-requester: 1739930902
    cache-control: public, max-age=0, no-cache
    link: <>;rel=“index”
    location:
    replay-nonce: LPSR-4-s64tPIFvUDuSpkIIS6betX3yHAsUlSy8UwPxaq96MVLk
    x-frame-options: DENY
    strict-transport-security: max-age=604800

{
“status”: “pending”,
“expires”: “2024-12-23T08:14:16Z”,
“identifiers”: [
{
“type”: “dns”,
“value”: “frouexperiencia.c om”
}
],
“authorizations”: [

],

}

==[API call]==
exit status: 0

==[Step 3]==

    status: 200
    nonce: WVWTDxmJa82iZjX_5Ip9dsJqjZ20Hcn0XfxbOswyDThk6aLpdSo
    token: vSPMf0nDrtvga3if-abIHKh6RIT-M79AX8aAooDAdng
    answer: HTTP/2 200
    server: nginx
    date: Mon, 16 Dec 2024 08:14:16 GMT
    content-type: application/json
    content-length: 827
    boulder-requester: 1739930902
    cache-control: public, max-age=0, no-cache
    ;rel=“index”
    replay-nonce: WVWTDxmJa82iZjX_5Ip9dsJqjZ20Hcn0XfxbOswyDThk6aLpdSo
    x-frame-options: DENY
    strict-transport-security: max-age=604800

{
“identifier”: {
“type”: “dns”,
“value”: “frouexperiencia.c om”
},
“status”: “pending”,
“expires”: “2024-12-23T08:14:16Z”,
“challenges”: [
{
“type”: “tls-alpn-01”,
“status”: “pending”,
“token”: “vSPMf0nDrtvga3if-abIHKh6RIT-M79AX8aAooDAdng”
},
{
“type”: “http-01”,

  "status": "pending",
  "token": "vSPMf0nDrtvga3if-abIHKh6RIT-M79AX8aAooDAdng"
},
{
  "type": "dns-01",
  "status": "pending",
  "token": "vSPMf0nDrtvga3if-abIHKh6RIT-M79AX8aAooDAdng"
}

]
}

==[API call]==
exit status: 0

==[Step 5]==

    status: 200

    nonce: WVWTDxmJPi7NK5IE4ZhDnX1uajV7fj56F8_IM83qJkF0E8bout0

    validation:acme-v02.api.letsencrypt.org/acme/chall/1739930902/445656803325/yd-pLA

    details:

    answer: HTTP/2 200
    server: nginx
    date: Mon, 16 Dec 2024 08:14:22 GMT
    content-type: application/json
    content-length: 195
    boulder-requester: 1739930902
    cache-control: public, max-age=0, no-cache
    rel=“index”

replay-nonce: WVWTDxmJPi7NK5IE4ZhDnX1uajV7fj56F8_IM83qJkF0E8bout0
x-frame-options: DENY
strict-transport-security: max-age=604800

{
",
“status”: “pending”,
“token”: “vSPMf0nDrtvga3if-abIHKh6RIT-M79AX8aAooDAdng”
}

==[API call]==
exit status: 0

==[Step 6]==

    status: 403
    nonce: WVWTDxmJ6d3Z2paCxft-93SyQUHeOAmPTcOiu8y-hzZoDOm5vgc
    payload: {“csr”:“MIIE5TCCAs0CAQAwgZ8xJzAlBgkqhkiG9w0BCQEWGGluZm9AZnJvdWV4cGVyaWVuY2lhLmNvbTELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDVNhbiBGcmFuY2lzY28xDzANBgNVBAoMBkhlc3RpYTELMAkGA1UECwwCSVQxHDAaBgNVBAMME2Zyb3VleHBlcmllbmNpYS5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC7mHthPrtXc8EutdRAMWMZUYpZBfK0_U7ZaRPn5LsfMyufkWBfS8vlkIjHzzPI2_76aXy3uBnC1mtcBm4FcfmX6CPJWwvbaAJM33YZbAqHR4MQvwc0dSXSHqGsyYDY8Bga86U7xbDdTzfpY7Wg84ucgO5S2qWfP79glDo5SzpPxNU0FFvuHAL7hRMLpi4SkygpnLCbL4paa8y8rsTa2x5ibAhNb4MSiinFteMmT6w9xUmGfW1Mlvy8mJkzYrtvep9P3IAfI8P-708MSaYJLayZoMCT-dknrWGMqiFsxIRC67ZmU15SBVXyJaUxsS0xrU_CV5Y5n4bQ6KRmzZT8ciyJGQPXp-bdYK0W62JA75-0C0LvQcSKDrkw1PaC9BNygk_7kXJZFX0REo2-WMi4RwlrURnIBD46Q1y2YussZYQ3I0hr-MO9Lw8hTgqLJlV7kUEEwxfvVMEZ4T9WpgnQUDWtI5NqKMziOMBNr1wLxymeOwlKJ1l1gAOUW6wLuSe6MKJ4A2EHWidP1rQk81asqQ2ON1AAQjVOpY9VSgBVsrgm8kbaOGwgraDgBp25wL67dJqS7Emw5vFVyhjamTW9OqWGAkAlVGpo4_ysBojPWkswzvYv9mWje2Mhrpq051fjTPsn2a9lhnR_-wxnZ1FLeCTiLIn9zen0nLjaZfSIjKAm-QIDAQABoAAwDQYJKoZIhvcNAQELBQADggIBAEvdgtRFuj5bvI5i8ibKH7MN_iPc1O27khCxXmvHGqUD8dDQrcXcnw5WktPEHZDgf5ynuv2jH_QWuXYLSytewUHkIYB9Injht3AnvCpfbVb5U9QohA1s1gNGygFMBneRCj3y1l4BC0MuyiAS51SP3_eQwqvBdHqvq6XlZRgOGiv6VmRQvOegaoIC7Ssx7KuCXXXqjjNahbQeemOkvyVFuFeGpFaKlnotSQNxbmmfVJnEsDqHx93zCneuZezhc5CAUFTHJm4W7xEMRTtKqtPqNCQkBMnwKprYRkR78byq18SpN8VAto4CzCrYOnchiNkRdw1NaKd9qIhobIjoSzoS5ul1M28112bZrug4EKZAOlwBUqvZCFS_f_QyQrPTZcjMBv39S35J0_qbb1TLHeIPqd7AAZQqgGEr9o2_3Dih4s06Qcn894n8BQ_2PCWZIg3RaLzgpuAkT69ZN9Hj9qJfLvooyWXv8TqTxyel8aZNzUK_Wnf0aF20L5C_5OC7Xs_uHBA3miX7AMk_02LAKJKuNdj0ramA2cdw1q-6bgikqABjmfBTiP_LdGCkCXb2rFDLCnJ6an1VQt4cZY5ovnIIMwptFhO0WHshxNijnJd197ra81V0fpZjj2KeBvCMqZGSN53aZ7_DEfnGTIQ-bB-59Bju2TglrPx0RmpZYyTz1g0E”}
    certificate:
    answer: HTTP/2 403
    server: nginx
    date: Mon, 16 Dec 2024 08:14:27 GMT
    content-type: application/problem+json
    content-length: 152
    boulder-requester: 1739930902
    cache-control: public, max-age=0, no-cache
    rel=“index”
    replay-nonce: WVWTDxmJ6d3Z2paCxft-93SyQUHeOAmPTcOiu8y-hzZoDOm5vgc

{
“type”: “urn:ietf:params:acme:error:orderNotReady”,
“detail”: “Order’s status ("invalid") is not acceptable for finalization”,
“status”: 403
}

The log is too old.

I suppose you added the space to the TLD.

What I can check is whether your site is serving the required challenge and it isn’t.

$ curl -IkL http://frouexperiencia.com/.well-known/acme-challenge/test
HTTP/1.1 404 Not Found
Server: openresty
Date: Thu, 09 Jan 2025 14:46:36 GMT
Content-Type: text/html
Content-Length: 150
Connection: keep-alive

Additionally, you are not using the default Nginx provided by Hestia; instead, you are using OpenResty. You should review how you are configuring it.

Sorry for the previous log. Here I have one from this morning, but from another domain. How could I use the Nginx provided by Hestia? To understand how my Nginx is set up, I can check the configuration file.

I’m attaching today’s log:


=============================
Date Time: 2025-01-10 08:20:57
WEB_SYSTEM: apache2
PROXY_SYSTEM: nginx
user: soporte
domain: mail.ignifugacionessalinas.es


- aliases: correo.ignifugacionessalinas.es
- proto: http-01
- wildcard:


==[Step 1]==
- status: 200
- nonce: o6qEBv53xc6p8DpUQ0tXvGFTeWqTM61eOjqEeaWTewg0sQ1Mnpk
- answer: HTTP/2 200
server: nginx
date: Fri, 10 Jan 2025 07:20:58 GMT
content-type: application/json
content-length: 746
cache-control: public, max-age=0, no-cache
replay-nonce: o6qEBv53xc6p8DpUQ0tXvGFTeWqTM61eOjqEeaWTewg0sQ1Mnpk
x-frame-options: DENY
strict-transport-security: max-age=604800



==[API call]==
exit status: 0


==[Step 2]==
- status: 201
- nonce: yoRvt02Q_yyrN63KxIZriPTMzzm4sO1dScgy0LRTemiRbCXEml4
- authz: /acme-v02.api.letsencrypt.org/acme/authz/1739930902/458404352315
- finalize: /acme-v02.api.letsencrypt.org/acme/finalize/1739930902/342818549125
- payload: {"identifiers":[{"type":"dns","value":"correo.ignifugacionessalinas.es"},{"type":"dns","value":"mail.ignifugacionessalinas.es"}]}
- answer: HTTP/2 201
server: nginx
date: Fri, 10 Jan 2025 07:20:58 GMT
content-type: application/json
content-length: 525
boulder-requester: 1739930902
cache-control: public, max-age=0, no-cache
location: /acme-v02.api.letsencrypt.org/acme/order/1739930902/342818549125
replay-nonce: yoRvt02Q_yyrN63KxIZriPTMzzm4sO1dScgy0LRTemiRbCXEml4
x-frame-options: DENY
strict-transport-security: max-age=604800

{
  "status": "pending",
  "expires": "2025-01-17T05:31:03Z",
  "identifiers": [
    {
      "type": "dns",
      "value": "correo.ignifugacionessalinas.es"
    },
    {
      "type": "dns",
      "value": "mail.ignifugacionessalinas.es"
    }
  ],
  "authorizations": [
  ],
  "finalize": "/acme-v02.api.letsencrypt.org/acme/finalize/1739930902/342818549125"
}
 order: /acme-v02.api.letsencrypt.org/acme/order/1739930902/342818549125


==[API call]==
exit status: 0


==[Step 3]==
- status: 200
- nonce: o6qEBv53S_ZXxJdocbsw9LRAFoKkXlvkBtkPWanldoiGf8m2Kzw
- token: PA7U_3tcLsTHmYYV7U4CcHMx_cYMOLc3gWfvzzmOSh4
- answer: HTTP/2 200
server: nginx
date: Fri, 10 Jan 2025 07:20:59 GMT
content-type: application/json
content-length: 839
boulder-requester: 1739930902
cache-control: public, max-age=0, no-cache
replay-nonce: o6qEBv53S_ZXxJdocbsw9LRAFoKkXlvkBtkPWanldoiGf8m2Kzw
x-frame-options: DENY
strict-transport-security: max-age=604800

{
  "identifier": {
    "type": "dns",
    "value": "correo.ignifugacionessalinas.es"
  },
  "status": "pending",
  "expires": "2025-01-17T05:31:03Z",
  "challenges": [
    {
      "type": "tls-alpn-01",,
      "status": "pending",
      "token": "PA7U_3tcLsTHmYYV7U4CcHMx_cYMOLc3gWfvzzmOSh4"
    },
    {
      "type": "dns-01",
      "url": "/acme-v02.api.letsencrypt.org/acme/chall/1739930902/458404352315/XkiSaA",
      "status": "pending",
      "token": "PA7U_3tcLsTHmYYV7U4CcHMx_cYMOLc3gWfvzzmOSh4"
    },
    {
      "type": "http-01",
      "url": "/acme-v02.api.letsencrypt.org/acme/chall/1739930902/458404352315/zYrimg",
      "status": "pending",
      "token": "PA7U_3tcLsTHmYYV7U4CcHMx_cYMOLc3gWfvzzmOSh4"
    }
  ]
}


==[API call]==
exit status: 0


==[Step 5]==
- status: 400
- url: /acme-v02.api.letsencrypt.org/acme/chall/1739930902/458404352315/zYrimg
- nonce: 2NJzUBzXm1FWo4bKDhbTaz8jtxIEsrMfyZrgex0T9XaHiLVpUrA
- validation:
- details: Unable to update challenge :: authorization must be pending
- answer: HTTP/2 400
server: nginx
date: Fri, 10 Jan 2025 07:22:18 GMT
content-type: application/problem+json
content-length: 144
boulder-requester: 1739930902
cache-control: public, max-age=0, no-cache
link: </acme-v02.api.letsencrypt.org/directory>;rel="index"
replay-nonce: 2NJzUBzXm1FWo4bKDhbTaz8jtxIEsrMfyZrgex0T9XaHiLVpUrA

{
  "type": "urn:ietf:params:acme:error:malformed",
  "detail": "Unable to update challenge :: authorization must be pending",
  "status": 400
}


==[Debug information Step 5]==
{
  "type": "http-01",
  "url": "/acme-v02.api.letsencrypt.org/acme/chall/1739930902/458404352315/zYrimg",
  "status": "invalid",
  "validated": "2025-01-10T07:21:04Z",
  "error": {
    "type": "urn:ietf:params:acme:error:tls",
    "detail": Fetching /correo.ignifugacionessalinas.es/.well-known/acme-challenge/PA7U_3tcLsTHmYYV7U4CcHMx_cYMOLc3gWfvzzmOSh4: remote error: tls: unrecognized name",
    "status": 400
  },
  "token": "PA7U_3tcLsTHmYYV7U4CcHMx_cYMOLc3gWfvzzmOSh4",
  "validationRecord": [
    {
      "url": "correo.ignifugacionessalinas.es/.well-known/acme-challenge/PA7U_3tcLsTHmYYV7U4CcHMx_cYMOLc3gWfvzzmOSh4",
      "hostname": "correo.ignifugacionessalinas.es",
      "port": "80",
      "addressesResolved": [
        
      ],
      "addressUsed": 
    },
    {
      "url": "correo.ignifugacionessalinas.es/.well-known/acme-challenge/PA7U_3tcLsTHmYYV7U4CcHMx_cYMOLc3gWfvzzmOSh4",
      "hostname": "correo.ignifugacionessalinas.es",
      "port": "443",
      "addressesResolved": [
        
      ],
      "addressUsed": 
    }
  ]
}


==[Abort Step 5]==
=> Wrong status

In this case the error shown by Let’s Encrypt is remote error: tls: unrecognized name"

And that’s because you are redirecting requests from http to https but https is not configured for your domain.

$ curl -ikL http://correo.ignifugacionessalinas.es/.well-known/acme-challenge/test
HTTP/1.1 301 Moved Permanently
Date: Fri, 10 Jan 2025 12:11:55 GMT
Content-Type: text/html
Content-Length: 162
Connection: keep-alive
Location: https://correo.ignifugacionessalinas.es/.well-known/acme-challenge/test
Server: Proxy
X-Served-By: correo.ignifugacionessalinas.es

curl: (35) OpenSSL/3.0.13: error:0A000458:SSL routines::tlsv1 unrecognized name

In this case the web server announces itself as Proxy (neither Nginx nor OpenResty) so I don’t know how the server has been configured to answer http/https requests.

If you haven’t modified it, there’s nothing you need to do to use the Nginx provided by Hestia. However, if you or the server’s admin have made changes, maybe the proxy used is external to Hestia’s server. That’s something only you would know. You are the one who can answer questions about how your server has been configured.

2 Likes