# Let's Encrypt Certificate Renewal Failure

**URL:** <https://forum.pritunl.com/t/lets-encrypt-certificate-renewal-failure/3633>\
**Category:** Pritunl VPN\
**Created:** [November 18, 2025, 10:36pm UTC](https://forum.pritunl.com/t/lets-encrypt-certificate-renewal-failure/3633 "2025-11-18T22:36:02Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![wvoyek](https://forum.pritunl.com/user_avatar/forum.pritunl.com/wvoyek/32/800_2.png) [@wvoyek](https://forum.pritunl.com/u/wvoyek)\
**Post date:** [November 18, 2025, 10:36pm UTC](https://forum.pritunl.com/t/lets-encrypt-certificate-renewal-failure/3633/1 "2025-11-18T22:36:02Z")

</div>

I have a Pritunl Enterprise VPN server that has been in production use since Mar 7, 2019. Starting last week it can no longer renew the Let’s Encrypt certificate. When trying to renew the following error shows in the log:

```auto
[patient-waterfall-1365][2025-11-18 17:21:24,737][ERROR] Failed to get LetsEncrypt cert
Traceback (most recent call last):
  File "/usr/lib/pritunl/usr/lib/python3.9/site-packages/pritunl/handlers/settings.py", line 1112, in settings_put
    acme.update_acme_cert()
  File "/usr/lib/pritunl/usr/lib/python3.9/site-packages/pritunl/acme.py", line 73, in update_acme_cert
    cert = get_acme_cert(settings.app.acme_key, csr, cmdline)
  File "/usr/lib/pritunl/usr/lib/python3.9/site-packages/pritunl/acme.py", line 45, in get_acme_cert
    certificate = acmetiny.get_crt(
  File "/usr/lib/pritunl/usr/lib/python3.9/site-packages/pritunl/acmetiny.py", line 138, in get_crt
    raise ValueError("Challenge did not pass for {0}: {1}".format(domain, authorization))
ValueError: Challenge did not pass for vpn.server.hostname.tld: {'identifier': {'type': 'dns', 'value': 'vpn.server.hostname.tld'}, 'status': 'invalid', 'expires': '2025-11-25T22:21:21Z', 'challenges': [{'type': 'http-01', 'url': 'https://acme-v02.api.letsencrypt.org/acme/chall/2810300146/614933220256/CHk61A', 'status': 'invalid', 'validated': '2025-11-18T22:21:22Z', 'error': {'type': 'urn:ietf:params:acme:error:unauthorized', 'detail': 'During secondary validation: xxx.xxx.xxx.xxx: Invalid response from http://vpn.server.hostname.tld/.well-known/acme-challenge/YUUYdx_VaV5Rmw-c2X4oZ84TJ4RkoBUfoRruEn_8oZo: 403', 'status': 403}, 'token': 'YUUYdx_VaV5Rmw-c2X4oZ84TJ4RkoBUfoRruEn_8oZo', 'validationRecord': [{'url': 'http://vpn.server.hostname.tld/.well-known/acme-challenge/YUUYdx_VaV5Rmw-c2X4oZ84TJ4RkoBUfoRruEn_8oZo', 'hostname': 'vpn.server.hostname.tld', 'port': '80', 'addressesResolved': ['xxx.xxx.xxx.xxx'], 'addressUsed': 'xxx.xxx.xxx.xxx'}]}]}
  acme_domain = "vpn.server.hostname.tld"

```

Note: I have replaced the actual hostname and IP address with vpn.server.hostname.tld and xxx.xxx.xxx.xxx respectively.

In troubleshooting I have:

- verified there is available space on the disks
- restarted the `pritunl`service
- ran the command `pritunl reset-ssl-cert` to reinstall a self-signed certificate
- checked there are no updates available with `dnf update`
- rebooted the server

The server is running Oracle Linux 8.10 and the latest pritunl is installed: `pritunl v1.32.4400.99`

Prior to this, certificate renewals have functioned automatically as expected. All existing client sessions appear to be still functional and users can connect, but any new sessions/users get an error in the pritunl client about a self-signed certificate and cannot connect.

Last week I sent an email to [priority@pritunl.com](mailto:priority@pritunl.com) that is listed on [support.pritunl.com](http://support.pritunl.com) but I have yet to receive a response. How can I resolve this error and get certificate renewal functioning again?

---

<div class="post-metadata">

**Author:** ![wvoyek](https://forum.pritunl.com/user_avatar/forum.pritunl.com/wvoyek/32/800_2.png) [@wvoyek](https://forum.pritunl.com/u/wvoyek)\
**Post date:** [November 18, 2025, 11:49pm UTC](https://forum.pritunl.com/t/lets-encrypt-certificate-renewal-failure/3633/2 "2025-11-18T23:49:35Z")

</div>

I also have manually visited the validation URL shown in the logs from multiple systems without issue, all return 200 and the expected validation text.

---

<div class="post-metadata">

**Author:** ![zach](https://forum.pritunl.com/user_avatar/forum.pritunl.com/zach/32/1105_2.png) [@zach](https://forum.pritunl.com/u/zach)\
**Post date:** [November 19, 2025, 12:35am UTC](https://forum.pritunl.com/t/lets-encrypt-certificate-renewal-failure/3633/3 "2025-11-19T00:35:46Z")

</div>

Verify it’s working on port 80 and verify port 80 is open. The Pritunl web server shouldn’t return a 403 error at that path even if the token doesn’t exist so it’s likely a load balancer issue.

---

<div class="post-metadata">

**Author:** ![wvoyek](https://forum.pritunl.com/user_avatar/forum.pritunl.com/wvoyek/32/800_2.png) [@wvoyek](https://forum.pritunl.com/u/wvoyek)\
**Post date:** [November 19, 2025, 2:57pm UTC](https://forum.pritunl.com/t/lets-encrypt-certificate-renewal-failure/3633/4 "2025-11-19T14:57:47Z")

</div>

Yes, it is on port 80 and working when I manually browse to that URL. There is no load balancer.

---

<div class="post-metadata">

**Author:** ![wvoyek](https://forum.pritunl.com/user_avatar/forum.pritunl.com/wvoyek/32/800_2.png) [@wvoyek](https://forum.pritunl.com/u/wvoyek)\
**Post date:** [November 19, 2025, 4:16pm UTC](https://forum.pritunl.com/t/lets-encrypt-certificate-renewal-failure/3633/5 "2025-11-19T16:16:34Z")

</div>

Here is a connection to the URL from an external network using curl:

 ![CleanShot 2025-11-19 at 08.11.34@2x](https://forum-static.pritunl.com/original/2X/7/73a8e8f8887cdd15efc943776e7a6a7b7c97ae95.jpeg)

---

<div class="post-metadata">

**Author:** ![zach](https://forum.pritunl.com/user_avatar/forum.pritunl.com/zach/32/1105_2.png) [@zach](https://forum.pritunl.com/u/zach)\
**Post date:** [November 19, 2025, 4:52pm UTC](https://forum.pritunl.com/t/lets-encrypt-certificate-renewal-failure/3633/6 "2025-11-19T16:52:50Z")

</div>

Try running `sudo pritunl renew-ssl-cert` to manually trigger a certificate renewal. Then verify the `addressesResolved` in the error is the IP address of the Pritunl server.

---

<div class="post-metadata">

**Author:** ![wvoyek](https://forum.pritunl.com/user_avatar/forum.pritunl.com/wvoyek/32/800_2.png) [@wvoyek](https://forum.pritunl.com/u/wvoyek)\
**Post date:** [November 19, 2025, 5:37pm UTC](https://forum.pritunl.com/t/lets-encrypt-certificate-renewal-failure/3633/7 "2025-11-19T17:37:18Z")

</div>

Running that command gives the following error:

```auto
Server does not have Lets Encrypt domain configured

```

I’m sure this is because I ran `pritunl reset-ssl-cert` previously in my attempt to troubleshoot the issue. Is there any way to manually set the domain outside the UI since when I try to set it there it attempts to renew the certificate and fails so the domain is not saved.

---

<div class="post-metadata">

**Author:** ![wvoyek](https://forum.pritunl.com/user_avatar/forum.pritunl.com/wvoyek/32/800_2.png) [@wvoyek](https://forum.pritunl.com/u/wvoyek)\
**Post date:** [November 19, 2025, 5:47pm UTC](https://forum.pritunl.com/t/lets-encrypt-certificate-renewal-failure/3633/8 "2025-11-19T17:47:44Z")

</div>

I found the setting in the source: `pritunl set app.acme_domain`

I have run the command you gave and verified the `addressResolved` is the correct IP address

---

<div class="post-metadata">

**Author:** ![zach](https://forum.pritunl.com/user_avatar/forum.pritunl.com/zach/32/1105_2.png) [@zach](https://forum.pritunl.com/u/zach)\
**Post date:** [November 20, 2025, 2:38am UTC](https://forum.pritunl.com/t/lets-encrypt-certificate-renewal-failure/3633/9 "2025-11-20T02:38:51Z")

</div>

Test the request on another system, it’s possible there is some WAF in front of the server. There isn’t likely any other cause the pritunl web server has no code to return a 403 error for this path.

Also run the commands below to add a log message to the acme\_token\_get function as shown below then watch to see if it is received in the top right log output.

```bash
sudo nano /usr/lib/pritunl/usr/lib/python3.9/site-packages/pritunl/app.py

@app.route('/.well-known/acme-challenge/<token>', methods=['GET'])
@auth.open_auth
def acme_token_get(token):
    logger.info('Acme challenge', 'app',
        token=token,
    )
    token = utils.filter_str(token[:96])
    authorization = acme.get_authorization(token)
    if authorization:
        return flask.Response(authorization, mimetype='text/plain')
    return flask.abort(404)

sudo systemctl restart pritunl

```

---

<div class="post-metadata">

**Author:** ![wvoyek](https://forum.pritunl.com/user_avatar/forum.pritunl.com/wvoyek/32/800_2.png) [@wvoyek](https://forum.pritunl.com/u/wvoyek)\
**Post date:** [November 20, 2025, 3:45pm UTC](https://forum.pritunl.com/t/lets-encrypt-certificate-renewal-failure/3633/10 "2025-11-20T15:45:54Z")

</div>

I added the logger and it definitely isn’t reaching there. I had noticed while looking through the source for how to manually set the domain that there was no code to return a 403. The server is behind a hardware firewall in the data center of course but that shouldn’t return a 403 either. If it was denying access it would just drop the packets. I’m really confused where the request from Let’s Encrypt is getting routed to. For now I have used certbot to generate a manual request with DNS validation and have added the new certificate and key to the UI. This has allowed us to get back to a usable state while I try to figure out what is going on.

Thanks for your help.
