[SOLVED] Can't get letsencrypt to work on brand new NCP install

The Basics

  • Nextcloud Server version (e.g., 29.x.x):
    • Nextcloud 33.0.2
  • Operating system and version (e.g., Ubuntu 24.04):
  • PHP version (e.g, 8.3):
    • 8.3
  • Is this the first time you’ve seen this error? (Yes / No):
    • Yes
  • When did this problem seem to first start?
    • At installation
  • Installation method (e.g. AlO, NCP, Bare Metal/Archive, etc.)
    • From disk image on bare RPi
  • Are you using CloudfIare, mod_security, or similar? (Yes / No)
    • No

Summary of the issue you are facing:

After failing last year to set up Nextcloud last year I’m having another go starting from scratch! I flashed the disk image, booted up the RPi and set up port forwarding. I have a static IP address so have not set up DDNS, I have just pointed my domain name to redirect to my IP address. I can now connect to my Nextcloud both from inside and outside my local network using either the IP address or the domain name, although I get the warnings about it being an untrusted site and I have to click through the options to ignore the warnings and go to it anyway.
So basically, as far as I can tell, everything is working EXCEPT letsencrypt. I’m just running it from the NextcloudPi panel, I’m just checking the “Active” box, typing in my domain, typing in my email (which happens to be on the same domain, does it matter what email I use?) and hitting Apply, but it’s not working.

Log entries

NextcloudPi Panel

Output from within the NCP panel:

[ letsencrypt ] (Thu Apr 16 19:49:23 UTC 2026)
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Requesting a certificate for xxx.xxx.co.uk

Certbot failed to authenticate some domains (authenticator: webroot). The Certificate Authority reported these problems:
Domain: xxx.xxx.co.uk
Type: unauthorized
Detail: 77.72.1.30: Invalid response from http://xxx.xxx.co.uk/.well-known/acme-challenge/_w7OUCVJ7Vz-iPCJDyAc-tMGMaEtMMx8umW7edXoxyE: 404

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.

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.

Full log file

The full contents of /var/log/letsencrypt/letsencrypt.log are here:

2026-04-16 19:00:30,788:DEBUG:certbot._internal.main:certbot version: 2.1.0
2026-04-16 19:00:30,789:DEBUG:certbot._internal.main:Location of certbot entry point: /usr/bin/letsencrypt
2026-04-16 19:00:30,789:DEBUG:certbot._internal.main:Arguments: ['-n', '--cert-name', 'xxx.xxxx.co.uk', '--force-renew', '--no-self-upgrade', '--webroot', '-w', '/var/www/nextcloud', '--hsts', '--agree-tos', '-m', 'timbo@timbilt.co.uk', '-d', 'xxx.xxxx.co.uk']
2026-04-16 19:00:30,789:DEBUG:certbot._internal.main:Discovered plugins: PluginsRegistry(PluginEntryPoint#manual,PluginEntryPoint#null,PluginEntryPoint#standalone,PluginEntryPoint#webroot)
2026-04-16 19:00:30,814:DEBUG:certbot._internal.log:Root logging level set at 30
2026-04-16 19:00:30,855:DEBUG:certbot._internal.plugins.selection:Requested authenticator webroot and installer None
2026-04-16 19:00:30,856:DEBUG:certbot._internal.plugins.selection:Single candidate plugin: * webroot
Description: Place files in webroot directory
Interfaces: Authenticator, Plugin
Entry point: webroot = certbot._internal.plugins.webroot:Authenticator
Initialized: <certbot._internal.plugins.webroot.Authenticator object at 0xffff9b114090>
Prep: True
2026-04-16 19:00:30,857:DEBUG:certbot._internal.plugins.selection:Selected authenticator <certbot._internal.plugins.webroot.Authenticator object at 0xffff9b114090> and installer None
2026-04-16 19:00:30,857:INFO:certbot._internal.plugins.selection:Plugins selected: Authenticator webroot, Installer None
2026-04-16 19:00:31,944:DEBUG:acme.client:Sending GET request to https://acme-v02.api.letsencrypt.org/directory.
2026-04-16 19:00:31,949:DEBUG:urllib3.connectionpool:Starting new HTTPS connection (1): acme-v02.api.letsencrypt.org:443
2026-04-16 19:00:32,332:DEBUG:urllib3.connectionpool:https://acme-v02.api.letsencrypt.org:443 "GET /directory HTTP/1.1" 200 1033
2026-04-16 19:00:32,333:DEBUG:acme.client:Received response:
HTTP 200
Server: nginx
Date: Thu, 16 Apr 2026 19:00:32 GMT
Content-Type: application/json
Content-Length: 1033
Connection: keep-alive
Cache-Control: public, max-age=0, no-cache
X-Frame-Options: DENY
Strict-Transport-Security: max-age=604800

{
  "PzkHS3COv9c": "https://community.letsencrypt.org/t/adding-random-entries-to-the-directory/33417",
  "keyChange": "https://acme-v02.api.letsencrypt.org/acme/key-change",
  "meta": {
    "caaIdentities": [
      "letsencrypt.org"
    ],
    "profiles": {
      "classic": "https://letsencrypt.org/docs/profiles#classic",
      "shortlived": "https://letsencrypt.org/docs/profiles#shortlived",
      "tlsclient": "https://letsencrypt.org/docs/profiles#tlsclient",
      "tlsserver": "https://letsencrypt.org/docs/profiles#tlsserver"
    },
    "termsOfService": "https://letsencrypt.org/documents/LE-SA-v1.6-August-18-2025.pdf",
    "website": "https://letsencrypt.org"
  },
  "newAccount": "https://acme-v02.api.letsencrypt.org/acme/new-acct",
  "newNonce": "https://acme-v02.api.letsencrypt.org/acme/new-nonce",
  "newOrder": "https://acme-v02.api.letsencrypt.org/acme/new-order",
  "renewalInfo": "https://acme-v02.api.letsencrypt.org/acme/renewal-info",
  "revokeCert": "https://acme-v02.api.letsencrypt.org/acme/revoke-cert"
}
2026-04-16 19:00:32,334:DEBUG:acme.client:Requesting fresh nonce
2026-04-16 19:00:32,334:DEBUG:acme.client:Sending HEAD request to https://acme-v02.api.letsencrypt.org/acme/new-nonce.
2026-04-16 19:00:32,454:DEBUG:urllib3.connectionpool:https://acme-v02.api.letsencrypt.org:443 "HEAD /acme/new-nonce HTTP/1.1" 200 0
2026-04-16 19:00:32,455:DEBUG:acme.client:Received response:
HTTP 200
Server: nginx
Date: Thu, 16 Apr 2026 19:00:32 GMT
Connection: keep-alive
Cache-Control: public, max-age=0, no-cache
Link: <https://acme-v02.api.letsencrypt.org/directory>;rel="index"
Replay-Nonce: IRr4kSsseFPwANet83b02E8uuF1t-TT8Asp2TWAf5HZElH3naz8
X-Frame-Options: DENY
Strict-Transport-Security: max-age=604800


2026-04-16 19:00:32,456:DEBUG:acme.client:Storing nonce: IRr4kSsseFPwANet83b02E8uuF1t-TT8Asp2TWAf5HZElH3naz8
2026-04-16 19:00:32,456:DEBUG:acme.client:JWS payload:
b'{\n  "contact": [\n    "mailto:timbo@timbilt.co.uk"\n  ],\n  "termsOfServiceAgreed": true\n}'
2026-04-16 19:00:32,467:DEBUG:acme.client:Sending POST request to https://acme-v02.api.letsencrypt.org/acme/new-acct:
{
  "protected": "eyJhbGciOiAiUlMyNTYiLCAiandrIjogeyJuIjogInJWbTJQSnN3ckJMNWs4elc5SmktNlh4Nk1xX05JMEVOU0UtLUxHemhHTl9jb1ctazRmR0ZiM0w0R1ZsenJMa0JLZ1FvclI0QzNmSmlEbGRqVDAzX0pOOENZX2lENmlMdFREeFQwcW9xWXBGbG02eGl5elVTRWpqTUd6cXV1YTQzelZiTTUxTVZtc2Q5OVloS21HdXhpaHFoUlZRckNIODhkbEhNZ3RyQ1pXNXlLZC04Q0V1VDB6dF9kWjU0YWh0SnF3OERncXh5dEZlNHRBNGNMX2U1bGlwVmF3ZUdQWHExdmRrTjZwWnpmN3pqTHNqc2I3ODd1ME9sV3hnVmNuSWNYWWlJQVFncURkZldpSU9fNU9Od1owRFJMZk15WHhPNS1uRFFWNFZVUWVFRkFsLTB3Y1JMUS1lU1NhdUg5Ykx4ZjF3TFdHYWRwVUg0REpKRm13LTA2USIsICJlIjogIkFRQUIiLCAia3R5IjogIlJTQSJ9LCAibm9uY2UiOiAiSVJyNGtTc3NlRlB3QU5ldDgzYjAyRTh1dUYxdC1UVDhBc3AyVFdBZjVIWkVsSDNuYXo4IiwgInVybCI6ICJodHRwczovL2FjbWUtdjAyLmFwaS5sZXRzZW5jcnlwdC5vcmcvYWNtZS9uZXctYWNjdCJ9",
  "signature": "NE17MLo8X1FXPkKd_hYBNCVfhyB8dz32i6GQ24tcuisrLx38Ijfn5ljy_3fpNayJGjjtEDHHLrv89e8m-cTDryPqJ1a5CF2GeWa1Zj0awiOAGylt8arT2tiwPe28qZ92tHIjqa2PAkanyVwOr8lDFkjoNeS5fUtjWzafXprLT_Uf90SVMFOCEXNSNtFQPsJIJDJ2f_WHEfouxEvu8xiq8Y4w8ZOWru6z7ObYqAbvzpWhUCI5a5rTyIdUH0Ul0TjVqufHeVuKONlxU9LuN8KpJ7RuFBUtYNp6poOHxtcppO5pOSXwgKMiw-RLrXGPtghjunp4rsGCepI3UBUxpsPEHQ",
  "payload": "ewogICJjb250YWN0IjogWwogICAgIm1haWx0bzp0aW1ib0B0aW1iaWx0LmNvLnVrIgogIF0sCiAgInRlcm1zT2ZTZXJ2aWNlQWdyZWVkIjogdHJ1ZQp9"
}
2026-04-16 19:00:32,597:DEBUG:urllib3.connectionpool:https://acme-v02.api.letsencrypt.org:443 "POST /acme/new-acct HTTP/1.1" 201 477
2026-04-16 19:00:32,598:DEBUG:acme.client:Received response:
HTTP 201
Server: nginx
Date: Thu, 16 Apr 2026 19:00:32 GMT
Content-Type: application/json
Content-Length: 477
Connection: keep-alive
Boulder-Requester: 3247224861
Cache-Control: public, max-age=0, no-cache
Link: <https://acme-v02.api.letsencrypt.org/directory>;rel="index", <https://letsencrypt.org/documents/LE-SA-v1.6-August-18-2025.pdf>;rel="terms-of-service"
Location: https://acme-v02.api.letsencrypt.org/acme/acct/3247224861
Replay-Nonce: IRr4kSsszkZcnZ1vwW9PJ9w-bjhxQ-pITi1gJMl9NJ_6hiu6r7Y
X-Frame-Options: DENY
Strict-Transport-Security: max-age=604800

{
  "key": {
    "kty": "RSA",
    "n": "rVm2PJswrBL5k8zW9Ji-6Xx6Mq_NI0ENSE--LGzhGN_coW-k4fGFb3L4GVlzrLkBKgQorR4C3fJiDldjT03_JN8CY_iD6iLtTDxT0qoqYpFlm6xiyzUSEjjMGzquua43zVbM51MVmsd99YhKmGuxihqhRVQrCH88dlHMgtrCZW5yKd-8CEuT0zt_dZ54ahtJqw8DgqxytFe4tA4cL_e5lipVaweGPXq1vdkN6pZzf7zjLsjsb787u0OlWxgVcnIcXYiIAQgqDdfWiIO_5ONwZ0DRLfMyXxO5-nDQV4VUQeEFAl-0wcRLQ-eSSauH9bLxf1wLWGadpUH4DJJFmw-06Q",
    "e": "AQAB"
  },
  "createdAt": "2026-04-16T19:00:32.535983014Z",
  "status": "valid"
}
2026-04-16 19:00:32,599:DEBUG:acme.client:Storing nonce: IRr4kSsszkZcnZ1vwW9PJ9w-bjhxQ-pITi1gJMl9NJ_6hiu6r7Y
2026-04-16 19:00:32,602:DEBUG:certbot._internal.display.obj:Notifying user: Account registered.
2026-04-16 19:00:32,602:DEBUG:certbot._internal.main:Picked account: <Account(RegistrationResource(body=Registration(key=JWKRSA(key=<ComparableRSAKey(<cryptography.hazmat.backends.openssl.rsa._RSAPublicKey object at 0xffff9b3dd190>)>), contact=(), agreement=None, status='valid', terms_of_service_agreed=None, only_return_existing=None, external_account_binding=None), uri='https://acme-v02.api.letsencrypt.org/acme/acct/3247224861', new_authzr_uri=None, terms_of_service='https://letsencrypt.org/documents/LE-SA-v1.6-August-18-2025.pdf'), 1d23c6138dd64e401cfc3d3bf2d6f42d, Meta(creation_dt=datetime.datetime(2026, 4, 16, 19, 0, 32, tzinfo=<UTC>), creation_host='nextcloudpi', register_to_eff=None))>
2026-04-16 19:00:32,604:DEBUG:certbot._internal.display.obj:Notifying user: Requesting a certificate for xxx.xxxx.co.uk
2026-04-16 19:00:32,609:DEBUG:certbot.crypto_util:Generating ECDSA key (2048 bits): /etc/letsencrypt/keys/0000_key-certbot.pem
2026-04-16 19:00:32,616:DEBUG:certbot.crypto_util:Creating CSR: /etc/letsencrypt/csr/0000_csr-certbot.pem
2026-04-16 19:00:32,620:DEBUG:acme.client:JWS payload:
b'{\n  "identifiers": [\n    {\n      "type": "dns",\n      "value": "xxx.xxxx.co.uk"\n    }\n  ]\n}'
2026-04-16 19:00:32,626:DEBUG:acme.client:Sending POST request to https://acme-v02.api.letsencrypt.org/acme/new-order:
{
  "protected": "eyJhbGciOiAiUlMyNTYiLCAia2lkIjogImh0dHBzOi8vYWNtZS12MDIuYXBpLmxldHNlbmNyeXB0Lm9yZy9hY21lL2FjY3QvMzI0NzIyNDg2MSIsICJub25jZSI6ICJJUnI0a1Nzc3prWmNuWjF2d1c5UEo5dy1iamh4US1wSVRpMWdKTWw5TkpfNmhpdTZyN1kiLCAidXJsIjogImh0dHBzOi8vYWNtZS12MDIuYXBpLmxldHNlbmNyeXB0Lm9yZy9hY21lL25ldy1vcmRlciJ9",
  "signature": "XkBQvpqXDyqIZibETxBJy624Uwq7nv7vw6qJjV_TcwujPARgcG9sWe5CbEzEpkzZPQxVdj_39fdn2UKBOT-TCpdkryFOngMaxUI2Rys6IlnBglt_InEExH1epZGKDIKnVgnYF8n_vTBNVGg4_fUxCGrNVTLinfOrk_lVxNCd_IR4aJTnZqoX47YzXwuDYFPWlua00fKOEJEbuwEcofQcNAtc9SuGZ__a4MUQl2AES-PDUNc09sZyhj-TMEc5SQZwlcmYjKryLxpBlaG7jHt5hHPlbw7N5-_lonOO3x01QgsamR8XGqxgCxouwaH8NTgpYo5tm76e7UDSldqMWkDS2w",
  "payload": "ewogICJpZGVudGlmaWVycyI6IFsKICAgIHsKICAgICAgInR5cGUiOiAiZG5zIiwKICAgICAgInZhbHVlIjogImNsb3VkYmFzZS50aW1iaWx0LmNvLnVrIgogICAgfQogIF0KfQ"
}
2026-04-16 19:00:32,799:DEBUG:urllib3.connectionpool:https://acme-v02.api.letsencrypt.org:443 "POST /acme/new-order HTTP/1.1" 201 357
2026-04-16 19:00:32,800:DEBUG:acme.client:Received response:
HTTP 201
Server: nginx
Date: Thu, 16 Apr 2026 19:00:32 GMT
Content-Type: application/json
Content-Length: 357
Connection: keep-alive
Boulder-Requester: 3247224861
Cache-Control: public, max-age=0, no-cache
Link: <https://acme-v02.api.letsencrypt.org/directory>;rel="index"
Location: https://acme-v02.api.letsencrypt.org/acme/order/3247224861/501376216571
Replay-Nonce: a-V5MCAw2s0BSixtgM5l1MUxn_CzklLvpWc4MbEbTOA6Er8KgZA
X-Frame-Options: DENY
Strict-Transport-Security: max-age=604800

{
  "status": "pending",
  "expires": "2026-04-23T19:00:32Z",
  "identifiers": [
    {
      "type": "dns",
      "value": "xxx.xxxx.co.uk"
    }
  ],
  "authorizations": [
    "https://acme-v02.api.letsencrypt.org/acme/authz/3247224861/689206827201"
  ],
  "finalize": "https://acme-v02.api.letsencrypt.org/acme/finalize/3247224861/501376216571"
}
2026-04-16 19:00:32,800:DEBUG:acme.client:Storing nonce: a-V5MCAw2s0BSixtgM5l1MUxn_CzklLvpWc4MbEbTOA6Er8KgZA
2026-04-16 19:00:32,802:DEBUG:acme.client:JWS payload:
b''
2026-04-16 19:00:32,808:DEBUG:acme.client:Sending POST request to https://acme-v02.api.letsencrypt.org/acme/authz/3247224861/689206827201:
{
  "protected": "eyJhbGciOiAiUlMyNTYiLCAia2lkIjogImh0dHBzOi8vYWNtZS12MDIuYXBpLmxldHNlbmNyeXB0Lm9yZy9hY21lL2FjY3QvMzI0NzIyNDg2MSIsICJub25jZSI6ICJhLVY1TUNBdzJzMEJTaXh0Z001bDFNVXhuX0N6a2xMdnBXYzRNYkViVE9BNkVyOEtnWkEiLCAidXJsIjogImh0dHBzOi8vYWNtZS12MDIuYXBpLmxldHNlbmNyeXB0Lm9yZy9hY21lL2F1dGh6LzMyNDcyMjQ4NjEvNjg5MjA2ODI3MjAxIn0",
  "signature": "Va-oAfQz7mi8XmrAaX39fh4iZtOaUrSe9npmu7ceOg7rzDO_EP-8WHN7N5_o7nFU8Yf4xTgB515WfMDs2eYXpj9NEMppliAuv1AMSBkJTVddjrbrEiUnA8kZNzFs0R6_QxWxYk2kAa2GZR98rHHFh80OZBctIpMF-y21suPM7bU-N1M9--Ychm8oRf_-D9uNYu7iBf4I2zjupGmauq7FggVL-5JdGzx-_uNTC_ivtiJQjLeEsOYe8SgYO5gF3QsgyMNHEzJ3TtUCddG7YDJtFiOTYKdlI3yIv8EICqSZ13uNCQe96YfGkJJgGF4bGVKv1Xpll7zKCtZUTCk0803yOw",
  "payload": ""
}
2026-04-16 19:00:32,934:DEBUG:urllib3.connectionpool:https://acme-v02.api.letsencrypt.org:443 "POST /acme/authz/3247224861/689206827201 HTTP/1.1" 200 831
2026-04-16 19:00:32,935:DEBUG:acme.client:Received response:
HTTP 200
Server: nginx
Date: Thu, 16 Apr 2026 19:00:32 GMT
Content-Type: application/json
Content-Length: 831
Connection: keep-alive
Boulder-Requester: 3247224861
Cache-Control: public, max-age=0, no-cache
Link: <https://acme-v02.api.letsencrypt.org/directory>;rel="index"
Replay-Nonce: a-V5MCAw34YY0Y6DOz2QEIdNpWl50ECUene6oBM9OC7dU8IeX2w
X-Frame-Options: DENY
Strict-Transport-Security: max-age=604800

{
  "identifier": {
    "type": "dns",
    "value": "xxx.xxxx.co.uk"
  },
  "status": "pending",
  "expires": "2026-04-23T19:00:32Z",
  "challenges": [
    {
      "type": "tls-alpn-01",
      "url": "https://acme-v02.api.letsencrypt.org/acme/chall/3247224861/689206827201/Zi3Gww",
      "status": "pending",
      "token": "R35fAjfIs9RaVvMA3KJU0dJA-Scg8BbfSxFDrs5AU2c"
    },
    {
      "type": "dns-01",
      "url": "https://acme-v02.api.letsencrypt.org/acme/chall/3247224861/689206827201/j-nFZA",
      "status": "pending",
      "token": "R35fAjfIs9RaVvMA3KJU0dJA-Scg8BbfSxFDrs5AU2c"
    },
    {
      "type": "http-01",
      "url": "https://acme-v02.api.letsencrypt.org/acme/chall/3247224861/689206827201/Lod5Sg",
      "status": "pending",
      "token": "R35fAjfIs9RaVvMA3KJU0dJA-Scg8BbfSxFDrs5AU2c"
    }
  ]
}
2026-04-16 19:00:32,935:DEBUG:acme.client:Storing nonce: a-V5MCAw34YY0Y6DOz2QEIdNpWl50ECUene6oBM9OC7dU8IeX2w
2026-04-16 19:00:32,936:INFO:certbot._internal.auth_handler:Performing the following challenges:
2026-04-16 19:00:32,936:INFO:certbot._internal.auth_handler:http-01 challenge for xxx.xxxx.co.uk
2026-04-16 19:00:32,937:INFO:certbot._internal.plugins.webroot:Using the webroot path /var/www/nextcloud for all unmatched domains.
2026-04-16 19:00:32,937:DEBUG:certbot._internal.plugins.webroot:Creating root challenges validation dir at /var/www/nextcloud/.well-known/acme-challenge
2026-04-16 19:00:32,939:DEBUG:certbot._internal.plugins.webroot:Attempting to save validation to /var/www/nextcloud/.well-known/acme-challenge/R35fAjfIs9RaVvMA3KJU0dJA-Scg8BbfSxFDrs5AU2c
2026-04-16 19:00:32,940:DEBUG:acme.client:JWS payload:
b'{}'
2026-04-16 19:00:32,946:DEBUG:acme.client:Sending POST request to https://acme-v02.api.letsencrypt.org/acme/chall/3247224861/689206827201/Lod5Sg:
{
  "protected": "eyJhbGciOiAiUlMyNTYiLCAia2lkIjogImh0dHBzOi8vYWNtZS12MDIuYXBpLmxldHNlbmNyeXB0Lm9yZy9hY21lL2FjY3QvMzI0NzIyNDg2MSIsICJub25jZSI6ICJhLVY1TUNBdzM0WVkwWTZET3oyUUVJZE5wV2w1MEVDVWVuZTZvQk05T0M3ZFU4SWVYMnciLCAidXJsIjogImh0dHBzOi8vYWNtZS12MDIuYXBpLmxldHNlbmNyeXB0Lm9yZy9hY21lL2NoYWxsLzMyNDcyMjQ4NjEvNjg5MjA2ODI3MjAxL0xvZDVTZyJ9",
  "signature": "IC-m9shUyPlIVgfwdT2QTMTNmonHeL4DXrWNpCjInGdEPl7XIBF4FMkSaSrYn-kn4SoJipVX15tWElHGC91pNqOD-nNcVTV6QUPZ3Yw3O5HdA7NayhfRQ61cbUw_cy9Lha-gBxBN4H0YOK0UhL-a9CEBrlWUkvKIwsAzYVZpe7TCbgJvuOML9-Hf0pVWkE8qWrtdTeqMUTMLBurTC7AxNxD10oERwlJNmJ2si59dgl9IChEeplZLrXTFdZwYrtsJzaleZxResKXcQWCSaYHzoljl1Lzn4ItpceT8u1KreghWFJxOvwlCjLMDoRdFXBSyEy0rlnYlOQ81ltS17Q1KdA",
  "payload": "e30"
}
2026-04-16 19:00:33,073:DEBUG:urllib3.connectionpool:https://acme-v02.api.letsencrypt.org:443 "POST /acme/chall/3247224861/689206827201/Lod5Sg HTTP/1.1" 200 195
2026-04-16 19:00:33,074:DEBUG:acme.client:Received response:
HTTP 200
Server: nginx
Date: Thu, 16 Apr 2026 19:00:33 GMT
Content-Type: application/json
Content-Length: 195
Connection: keep-alive
Boulder-Requester: 3247224861
Cache-Control: public, max-age=0, no-cache
Link: <https://acme-v02.api.letsencrypt.org/directory>;rel="index", <https://acme-v02.api.letsencrypt.org/acme/authz/3247224861/689206827201>;rel="up"
Location: https://acme-v02.api.letsencrypt.org/acme/chall/3247224861/689206827201/Lod5Sg
Replay-Nonce: IRr4kSssKFio9g4avon2QRWuVYIFZhF6SCFbplbutXuWwp_OqAE
X-Frame-Options: DENY
Strict-Transport-Security: max-age=604800

{
  "type": "http-01",
  "url": "https://acme-v02.api.letsencrypt.org/acme/chall/3247224861/689206827201/Lod5Sg",
  "status": "pending",
  "token": "R35fAjfIs9RaVvMA3KJU0dJA-Scg8BbfSxFDrs5AU2c"
}
2026-04-16 19:00:33,074:DEBUG:acme.client:Storing nonce: IRr4kSssKFio9g4avon2QRWuVYIFZhF6SCFbplbutXuWwp_OqAE
2026-04-16 19:00:33,075:INFO:certbot._internal.auth_handler:Waiting for verification...
2026-04-16 19:00:34,075:DEBUG:acme.client:JWS payload:
b''
2026-04-16 19:00:34,082:DEBUG:acme.client:Sending POST request to https://acme-v02.api.letsencrypt.org/acme/authz/3247224861/689206827201:
{
  "protected": "eyJhbGciOiAiUlMyNTYiLCAia2lkIjogImh0dHBzOi8vYWNtZS12MDIuYXBpLmxldHNlbmNyeXB0Lm9yZy9hY21lL2FjY3QvMzI0NzIyNDg2MSIsICJub25jZSI6ICJJUnI0a1Nzc0tGaW85ZzRhdm9uMlFSV3VWWUlGWmhGNlNDRmJwbGJ1dFh1V3dwX09xQUUiLCAidXJsIjogImh0dHBzOi8vYWNtZS12MDIuYXBpLmxldHNlbmNyeXB0Lm9yZy9hY21lL2F1dGh6LzMyNDcyMjQ4NjEvNjg5MjA2ODI3MjAxIn0",
  "signature": "jftfQnwoa0359u4sBUqkxSC83bwtMnCMBBJ03dSVTSSVsFXiGn3i0WnoNjUCkYzigT-7Gh36sRNxg4zC3wZklfX81UHqofeg1dalYYjeQ8NsydHlMnm6m0TK3BYwtrGUi_gh2cEXIWen-yba_4i5LQ8nRXf2eby-xxnnPHsFb6ETqB0HJoMvqTNn0Y2j9gXqHC4hnW8x3Vn143n30IN50l9skl1WKZoMphr21QO-V0MPT-yXWX3E9jaJK4fy58MSXhLfoxq5yPui6iHBVfmag6n1iL1QTdHFLXbQQNvi57PTGbxyzuRdBGhr7wgxTV2mI6Xol_m6_3_E0Mvsv8qxxQ",
  "payload": ""
}
2026-04-16 19:00:34,204:DEBUG:urllib3.connectionpool:https://acme-v02.api.letsencrypt.org:443 "POST /acme/authz/3247224861/689206827201 HTTP/1.1" 200 1059
2026-04-16 19:00:34,204:DEBUG:acme.client:Received response:
HTTP 200
Server: nginx
Date: Thu, 16 Apr 2026 19:00:34 GMT
Content-Type: application/json
Content-Length: 1059
Connection: keep-alive
Boulder-Requester: 3247224861
Cache-Control: public, max-age=0, no-cache
Link: <https://acme-v02.api.letsencrypt.org/directory>;rel="index"
Replay-Nonce: IRr4kSssqn0wbtoW6lWe1PhqauHZgjPr6NVbnNU7g8Ie-nJvgOw
X-Frame-Options: DENY
Strict-Transport-Security: max-age=604800

{
  "identifier": {
    "type": "dns",
    "value": "xxx.xxxx.co.uk"
  },
  "status": "invalid",
  "expires": "2026-04-23T19:00:32Z",
  "challenges": [
    {
      "type": "http-01",
      "url": "https://acme-v02.api.letsencrypt.org/acme/chall/3247224861/689206827201/Lod5Sg",
      "status": "invalid",
      "validated": "2026-04-16T19:00:33Z",
      "error": {
        "type": "urn:ietf:params:acme:error:unauthorized",
        "detail": "77.72.1.30: Invalid response from http://xxx.xxxx.co.uk/.well-known/acme-challenge/R35fAjfIs9RaVvMA3KJU0dJA-Scg8BbfSxFDrs5AU2c: 404",
        "status": 403
      },
      "token": "R35fAjfIs9RaVvMA3KJU0dJA-Scg8BbfSxFDrs5AU2c",
      "validationRecord": [
        {
          "url": "http://xxx.xxxx.co.uk/.well-known/acme-challenge/R35fAjfIs9RaVvMA3KJU0dJA-Scg8BbfSxFDrs5AU2c",
          "hostname": "xxx.xxxx.co.uk",
          "port": "80",
          "addressesResolved": [
            "77.72.1.30"
          ],
          "addressUsed": "77.72.1.30"
        }
      ]
    }
  ]
}
2026-04-16 19:00:34,205:DEBUG:acme.client:Storing nonce: IRr4kSssqn0wbtoW6lWe1PhqauHZgjPr6NVbnNU7g8Ie-nJvgOw
2026-04-16 19:00:34,205:INFO:certbot._internal.auth_handler:Challenge failed for domain xxx.xxxx.co.uk
2026-04-16 19:00:34,206:INFO:certbot._internal.auth_handler:http-01 challenge for xxx.xxxx.co.uk
2026-04-16 19:00:34,206:DEBUG:certbot._internal.display.obj:Notifying user: 
Certbot failed to authenticate some domains (authenticator: webroot). The Certificate Authority reported these problems:
  Domain: xxx.xxxx.co.uk
  Type:   unauthorized
  Detail: 77.72.1.30: Invalid response from http://xxx.xxxx.co.uk/.well-known/acme-challenge/R35fAjfIs9RaVvMA3KJU0dJA-Scg8BbfSxFDrs5AU2c: 404

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.

2026-04-16 19:00:34,209: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.

2026-04-16 19:00:34,209:DEBUG:certbot._internal.error_handler:Calling registered functions
2026-04-16 19:00:34,209:INFO:certbot._internal.auth_handler:Cleaning up challenges
2026-04-16 19:00:34,209:DEBUG:certbot._internal.plugins.webroot:Removing /var/www/nextcloud/.well-known/acme-challenge/R35fAjfIs9RaVvMA3KJU0dJA-Scg8BbfSxFDrs5AU2c
2026-04-16 19:00:34,210:DEBUG:certbot._internal.plugins.webroot:All challenges cleaned up
2026-04-16 19:00:34,211:DEBUG:certbot._internal.log:Exiting abnormally:
Traceback (most recent call last):
  File "/usr/bin/letsencrypt", line 33, in <module>
    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 1590, in certonly
    lineage = _get_and_save_cert(le_client, config, domains, certname, lineage)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  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.
2026-04-16 19:00:34,219:ERROR:certbot._internal.log:Some challenges have failed.
2026-04-16 19:14:34,847:DEBUG:certbot._internal.main:certbot version: 2.1.0
2026-04-16 19:14:34,848:DEBUG:certbot._internal.main:Location of certbot entry point: /usr/bin/letsencrypt
2026-04-16 19:14:34,848:DEBUG:certbot._internal.main:Arguments: ['-n', '--cert-name', 'xxx.xxxx.co.uk', '--force-renew', '--no-self-upgrade', '--webroot', '-w', '/var/www/nextcloud', '--hsts', '--agree-tos', '-m', 'timbo@timbilt.co.uk', '-d', 'xxx.xxxx.co.uk']
2026-04-16 19:14:34,848:DEBUG:certbot._internal.main:Discovered plugins: PluginsRegistry(PluginEntryPoint#manual,PluginEntryPoint#null,PluginEntryPoint#standalone,PluginEntryPoint#webroot)
2026-04-16 19:14:34,872:DEBUG:certbot._internal.log:Root logging level set at 30
2026-04-16 19:14:34,913:DEBUG:certbot._internal.plugins.selection:Requested authenticator webroot and installer None
2026-04-16 19:14:34,913:DEBUG:certbot._internal.plugins.selection:Single candidate plugin: * webroot
Description: Place files in webroot directory
Interfaces: Authenticator, Plugin
Entry point: webroot = certbot._internal.plugins.webroot:Authenticator
Initialized: <certbot._internal.plugins.webroot.Authenticator object at 0xffff9cf79d50>
Prep: True
2026-04-16 19:14:34,914:DEBUG:certbot._internal.plugins.selection:Selected authenticator <certbot._internal.plugins.webroot.Authenticator object at 0xffff9cf79d50> and installer None
2026-04-16 19:14:34,914:INFO:certbot._internal.plugins.selection:Plugins selected: Authenticator webroot, Installer None
2026-04-16 19:14:35,228:DEBUG:certbot._internal.main:Picked account: <Account(RegistrationResource(body=Registration(key=None, contact=(), agreement=None, status=None, terms_of_service_agreed=None, only_return_existing=None, external_account_binding=None), uri='https://acme-v02.api.letsencrypt.org/acme/acct/3247224861', new_authzr_uri=None, terms_of_service=None), 1d23c6138dd64e401cfc3d3bf2d6f42d, Meta(creation_dt=datetime.datetime(2026, 4, 16, 19, 0, 32, tzinfo=<UTC>), creation_host='nextcloudpi', register_to_eff=None))>
2026-04-16 19:14:35,229:DEBUG:acme.client:Sending GET request to https://acme-v02.api.letsencrypt.org/directory.
2026-04-16 19:14:35,233:DEBUG:urllib3.connectionpool:Starting new HTTPS connection (1): acme-v02.api.letsencrypt.org:443
2026-04-16 19:14:35,616:DEBUG:urllib3.connectionpool:https://acme-v02.api.letsencrypt.org:443 "GET /directory HTTP/1.1" 200 1033
2026-04-16 19:14:35,617:DEBUG:acme.client:Received response:
HTTP 200
Server: nginx
Date: Thu, 16 Apr 2026 19:14:35 GMT
Content-Type: application/json
Content-Length: 1033
Connection: keep-alive
Cache-Control: public, max-age=0, no-cache
X-Frame-Options: DENY
Strict-Transport-Security: max-age=604800

{
  "keyChange": "https://acme-v02.api.letsencrypt.org/acme/key-change",
  "meta": {
    "caaIdentities": [
      "letsencrypt.org"
    ],
    "profiles": {
      "classic": "https://letsencrypt.org/docs/profiles#classic",
      "shortlived": "https://letsencrypt.org/docs/profiles#shortlived",
      "tlsclient": "https://letsencrypt.org/docs/profiles#tlsclient",
      "tlsserver": "https://letsencrypt.org/docs/profiles#tlsserver"
    },
    "termsOfService": "https://letsencrypt.org/documents/LE-SA-v1.6-August-18-2025.pdf",
    "website": "https://letsencrypt.org"
  },
  "newAccount": "https://acme-v02.api.letsencrypt.org/acme/new-acct",
  "newNonce": "https://acme-v02.api.letsencrypt.org/acme/new-nonce",
  "newOrder": "https://acme-v02.api.letsencrypt.org/acme/new-order",
  "renewalInfo": "https://acme-v02.api.letsencrypt.org/acme/renewal-info",
  "revokeCert": "https://acme-v02.api.letsencrypt.org/acme/revoke-cert",
  "tWe_uFZSE7U": "https://community.letsencrypt.org/t/adding-random-entries-to-the-directory/33417"
}
2026-04-16 19:14:35,618:DEBUG:certbot._internal.display.obj:Notifying user: Requesting a certificate for xxx.xxxx.co.uk
2026-04-16 19:14:35,624:DEBUG:certbot.crypto_util:Generating ECDSA key (2048 bits): /etc/letsencrypt/keys/0001_key-certbot.pem
2026-04-16 19:14:35,630:DEBUG:certbot.crypto_util:Creating CSR: /etc/letsencrypt/csr/0001_csr-certbot.pem
2026-04-16 19:14:35,633:DEBUG:acme.client:Requesting fresh nonce
2026-04-16 19:14:35,633:DEBUG:acme.client:Sending HEAD request to https://acme-v02.api.letsencrypt.org/acme/new-nonce.
2026-04-16 19:14:35,753:DEBUG:urllib3.connectionpool:https://acme-v02.api.letsencrypt.org:443 "HEAD /acme/new-nonce HTTP/1.1" 200 0
2026-04-16 19:14:35,754:DEBUG:acme.client:Received response:
HTTP 200
Server: nginx
Date: Thu, 16 Apr 2026 19:14:35 GMT
Connection: keep-alive
Cache-Control: public, max-age=0, no-cache
Link: <https://acme-v02.api.letsencrypt.org/directory>;rel="index"
Replay-Nonce: IRr4kSssttglwx-sGpsvfEOvgeu5BcN2mQajYVhRQJLLZ6Efnkk
X-Frame-Options: DENY
Strict-Transport-Security: max-age=604800


2026-04-16 19:14:35,755:DEBUG:acme.client:Storing nonce: IRr4kSssttglwx-sGpsvfEOvgeu5BcN2mQajYVhRQJLLZ6Efnkk
2026-04-16 19:14:35,755:DEBUG:acme.client:JWS payload:
b'{\n  "identifiers": [\n    {\n      "type": "dns",\n      "value": "xxx.xxxx.co.uk"\n    }\n  ]\n}'
2026-04-16 19:14:35,766:DEBUG:acme.client:Sending POST request to https://acme-v02.api.letsencrypt.org/acme/new-order:
{
  "protected": "eyJhbGciOiAiUlMyNTYiLCAia2lkIjogImh0dHBzOi8vYWNtZS12MDIuYXBpLmxldHNlbmNyeXB0Lm9yZy9hY21lL2FjY3QvMzI0NzIyNDg2MSIsICJub25jZSI6ICJJUnI0a1Nzc3R0Z2x3eC1zR3BzdmZFT3ZnZXU1QmNOMm1RYWpZVmhSUUpMTFo2RWZua2siLCAidXJsIjogImh0dHBzOi8vYWNtZS12MDIuYXBpLmxldHNlbmNyeXB0Lm9yZy9hY21lL25ldy1vcmRlciJ9",
  "signature": "V3mdFKxMsecQyn_2FApYDnYfYsmSIm5kZp_yJ2VYNEOJM9yXzy-ezrzwZetXqSE1-hxSBDIikT7UCmWH_T0h2jG-5IRdnquH4a0TfLJoKQXi518X8PNUl4dSHonFUmgOKAOBADRK01QksQceEsVUTHWcVu5DvDjQqZf6Om4hKW61wHNjlAF_zXWiJzA_xkRRygyKRT7toJJBGwcZ9eidyKpoKYohgPSzrnJuPziGoVump7ZeWVcN-5-GUblscFqWjPISxjNpF35qujxZZGeq8IMP3NFsOrsW6jZsxbetNkEKsMiaX9R1PZi26mE0P8p-bMbIooe-LhEtANtvSwL9LQ",
  "payload": "ewogICJpZGVudGlmaWVycyI6IFsKICAgIHsKICAgICAgInR5cGUiOiAiZG5zIiwKICAgICAgInZhbHVlIjogImNsb3VkYmFzZS50aW1iaWx0LmNvLnVrIgogICAgfQogIF0KfQ"
}
2026-04-16 19:14:35,939:DEBUG:urllib3.connectionpool:https://acme-v02.api.letsencrypt.org:443 "POST /acme/new-order HTTP/1.1" 201 357
2026-04-16 19:14:35,940:DEBUG:acme.client:Received response:
HTTP 201
Server: nginx
Date: Thu, 16 Apr 2026 19:14:35 GMT
Content-Type: application/json
Content-Length: 357
Connection: keep-alive
Boulder-Requester: 3247224861
Cache-Control: public, max-age=0, no-cache
Link: <https://acme-v02.api.letsencrypt.org/directory>;rel="index"
Location: https://acme-v02.api.letsencrypt.org/acme/order/3247224861/501379453151
Replay-Nonce: IRr4kSssWKHYNrrz_qDmvnr5UwYJTs8eL9vBpUXED98AXUPUXmo
X-Frame-Options: DENY
Strict-Transport-Security: max-age=604800

{
  "status": "pending",
  "expires": "2026-04-23T19:14:35Z",
  "identifiers": [
    {
      "type": "dns",
      "value": "xxx.xxxx.co.uk"
    }
  ],
  "authorizations": [
    "https://acme-v02.api.letsencrypt.org/acme/authz/3247224861/689211775831"
  ],
  "finalize": "https://acme-v02.api.letsencrypt.org/acme/finalize/3247224861/501379453151"
}
2026-04-16 19:14:35,940:DEBUG:acme.client:Storing nonce: IRr4kSssWKHYNrrz_qDmvnr5UwYJTs8eL9vBpUXED98AXUPUXmo
2026-04-16 19:14:35,940:DEBUG:acme.client:JWS payload:
b''
2026-04-16 19:14:35,947:DEBUG:acme.client:Sending POST request to https://acme-v02.api.letsencrypt.org/acme/authz/3247224861/689211775831:
{
  "protected": "eyJhbGciOiAiUlMyNTYiLCAia2lkIjogImh0dHBzOi8vYWNtZS12MDIuYXBpLmxldHNlbmNyeXB0Lm9yZy9hY21lL2FjY3QvMzI0NzIyNDg2MSIsICJub25jZSI6ICJJUnI0a1Nzc1dLSFlOcnJ6X3FEbXZucjVVd1lKVHM4ZUw5dkJwVVhFRDk4QVhVUFVYbW8iLCAidXJsIjogImh0dHBzOi8vYWNtZS12MDIuYXBpLmxldHNlbmNyeXB0Lm9yZy9hY21lL2F1dGh6LzMyNDcyMjQ4NjEvNjg5MjExNzc1ODMxIn0",
  "signature": "RdU2E9408J85QlRFmDMWBA19XKHYfAhUbyRyoJEptvXzg6LtdCa33-HNK46Mbugx9JE7jwf2Y0YsLlVRhe-ErV99dpeg6C6LdY54iZH0oDhh1PHnhe6duKrqEfUx0g6XzZI3pUvTlED0nTL_dEhTBuZkx3Wq0vcjjSviZ2xymBMxt9xqm3pVhOW-oHUmhOa_pL6pNJsw3Ev2FImy7U0UMjlDIAR_pl8xtSsuqjK0wWneI-P_ubkoUZHs3Je7uw2HoZxD8Nljf5cw0h4N4NaF79lB-uvCVuHQJ5UCR88F1kVjyocglqJVLPtwOx71d9pZPUcc64ayiwlN6tgs6LqwAQ",
  "payload": ""
}
2026-04-16 19:14:36,071:DEBUG:urllib3.connectionpool:https://acme-v02.api.letsencrypt.org:443 "POST /acme/authz/3247224861/689211775831 HTTP/1.1" 200 831
2026-04-16 19:14:36,071:DEBUG:acme.client:Received response:
HTTP 200
Server: nginx
Date: Thu, 16 Apr 2026 19:14:36 GMT
Content-Type: application/json
Content-Length: 831
Connection: keep-alive
Boulder-Requester: 3247224861
Cache-Control: public, max-age=0, no-cache
Link: <https://acme-v02.api.letsencrypt.org/directory>;rel="index"
Replay-Nonce: IRr4kSssuIFITv2Ivfr3JwvvyvGrxlPhAr_BzJKUQVOuBZ1qbKk
X-Frame-Options: DENY
Strict-Transport-Security: max-age=604800

{
  "identifier": {
    "type": "dns",
    "value": "xxx.xxxx.co.uk"
  },
  "status": "pending",
  "expires": "2026-04-23T19:14:35Z",
  "challenges": [
    {
      "type": "tls-alpn-01",
      "url": "https://acme-v02.api.letsencrypt.org/acme/chall/3247224861/689211775831/QBI83Q",
      "status": "pending",
      "token": "mmCpzv_34ZOXZEBbVZ9jY12chmzXLeoYRlmSJt220XM"
    },
    {
      "type": "dns-01",
      "url": "https://acme-v02.api.letsencrypt.org/acme/chall/3247224861/689211775831/2FYXbA",
      "status": "pending",
      "token": "mmCpzv_34ZOXZEBbVZ9jY12chmzXLeoYRlmSJt220XM"
    },
    {
      "type": "http-01",
      "url": "https://acme-v02.api.letsencrypt.org/acme/chall/3247224861/689211775831/rai-mA",
      "status": "pending",
      "token": "mmCpzv_34ZOXZEBbVZ9jY12chmzXLeoYRlmSJt220XM"
    }
  ]
}
2026-04-16 19:14:36,072:DEBUG:acme.client:Storing nonce: IRr4kSssuIFITv2Ivfr3JwvvyvGrxlPhAr_BzJKUQVOuBZ1qbKk
2026-04-16 19:14:36,073:INFO:certbot._internal.auth_handler:Performing the following challenges:
2026-04-16 19:14:36,073:INFO:certbot._internal.auth_handler:http-01 challenge for xxx.xxxx.co.uk
2026-04-16 19:14:36,073:INFO:certbot._internal.plugins.webroot:Using the webroot path /var/www/nextcloud for all unmatched domains.
2026-04-16 19:14:36,074:DEBUG:certbot._internal.plugins.webroot:Creating root challenges validation dir at /var/www/nextcloud/.well-known/acme-challenge
2026-04-16 19:14:36,076:DEBUG:certbot._internal.plugins.webroot:Attempting to save validation to /var/www/nextcloud/.well-known/acme-challenge/mmCpzv_34ZOXZEBbVZ9jY12chmzXLeoYRlmSJt220XM
2026-04-16 19:14:36,077:DEBUG:acme.client:JWS payload:
b'{}'
2026-04-16 19:14:36,083:DEBUG:acme.client:Sending POST request to https://acme-v02.api.letsencrypt.org/acme/chall/3247224861/689211775831/rai-mA:
{
  "protected": "eyJhbGciOiAiUlMyNTYiLCAia2lkIjogImh0dHBzOi8vYWNtZS12MDIuYXBpLmxldHNlbmNyeXB0Lm9yZy9hY21lL2FjY3QvMzI0NzIyNDg2MSIsICJub25jZSI6ICJJUnI0a1Nzc3VJRklUdjJJdmZyM0p3dnZ5dkdyeGxQaEFyX0J6SktVUVZPdUJaMXFiS2siLCAidXJsIjogImh0dHBzOi8vYWNtZS12MDIuYXBpLmxldHNlbmNyeXB0Lm9yZy9hY21lL2NoYWxsLzMyNDcyMjQ4NjEvNjg5MjExNzc1ODMxL3JhaS1tQSJ9",
  "signature": "jTsAg1FiJLBDeXvmXjpLc0K_9S-arvu1qeMu8jIeHLZLgxe3fs9zbNTaXB7HLQcJWO_Xa7eGX1Ed9G7Ymj194Cp3Apj-T5cL90Ern1dTAzPKrbUCbM8dOiAxR2pHfyaSUzqQ1MacNs1o3bk3Q5viZkyzBwKrsGBLmGx0hrfATFFnTo0IzN-RYCBdFQUWB85mcDIjH33vqRvZQgfVkqIJyHnv2nuFYKgzwObVV5GfUyEIlLVi1E9ENzW0yIe72N9XqE4Iw4mZRtsNHB7WI8-tfkjYPc1XLCwhliVqdBN-nFpkX4M2IEJAAp3MWzhFmmA_wO4vIshxuBGmUXJF1w718A",
  "payload": "e30"
}
2026-04-16 19:14:36,209:DEBUG:urllib3.connectionpool:https://acme-v02.api.letsencrypt.org:443 "POST /acme/chall/3247224861/689211775831/rai-mA HTTP/1.1" 200 195
2026-04-16 19:14:36,210:DEBUG:acme.client:Received response:
HTTP 200
Server: nginx
Date: Thu, 16 Apr 2026 19:14:36 GMT
Content-Type: application/json
Content-Length: 195
Connection: keep-alive
Boulder-Requester: 3247224861
Cache-Control: public, max-age=0, no-cache
Link: <https://acme-v02.api.letsencrypt.org/directory>;rel="index", <https://acme-v02.api.letsencrypt.org/acme/authz/3247224861/689211775831>;rel="up"
Location: https://acme-v02.api.letsencrypt.org/acme/chall/3247224861/689211775831/rai-mA
Replay-Nonce: a-V5MCAwpCXM3n9x3BYnH8EHfLEZ0-PfYD_sMuosh0dpPUgEsN8
X-Frame-Options: DENY
Strict-Transport-Security: max-age=604800

{
  "type": "http-01",
  "url": "https://acme-v02.api.letsencrypt.org/acme/chall/3247224861/689211775831/rai-mA",
  "status": "pending",
  "token": "mmCpzv_34ZOXZEBbVZ9jY12chmzXLeoYRlmSJt220XM"
}
2026-04-16 19:14:36,210:DEBUG:acme.client:Storing nonce: a-V5MCAwpCXM3n9x3BYnH8EHfLEZ0-PfYD_sMuosh0dpPUgEsN8
2026-04-16 19:14:36,211:INFO:certbot._internal.auth_handler:Waiting for verification...
2026-04-16 19:14:37,211:DEBUG:acme.client:JWS payload:
b''
2026-04-16 19:14:37,217:DEBUG:acme.client:Sending POST request to https://acme-v02.api.letsencrypt.org/acme/authz/3247224861/689211775831:
{
  "protected": "eyJhbGciOiAiUlMyNTYiLCAia2lkIjogImh0dHBzOi8vYWNtZS12MDIuYXBpLmxldHNlbmNyeXB0Lm9yZy9hY21lL2FjY3QvMzI0NzIyNDg2MSIsICJub25jZSI6ICJhLVY1TUNBd3BDWE0zbjl4M0JZbkg4RUhmTEVaMC1QZllEX3NNdW9zaDBkcFBVZ0VzTjgiLCAidXJsIjogImh0dHBzOi8vYWNtZS12MDIuYXBpLmxldHNlbmNyeXB0Lm9yZy9hY21lL2F1dGh6LzMyNDcyMjQ4NjEvNjg5MjExNzc1ODMxIn0",
  "signature": "VstAngcg706UFgLpkUYUXPadM9CZ_tUaX0sz9GkxJj3yPtW8_oFF5-ot4CJkUFrj_2_-TdgvbfAel12MrUIv6mkbzU838B_jOdPV5pOtHgymlwzHGGoy1P3pGXdeWathGSyBbEU_7QMZOPb6D75JMAsUdPJ_GyR0Gw-GuKXeMGHgNOpP56nazIdyoaol8AWFHhWNxGwTBbKPjibBXKLbd8rQj_J_z6qsea2uwuMGfCqyz6YVyPuGovRiuSWUnh7PTqbqHhJ-7EdeF7yibPJUGbzYhelTayeNzrSze-NCkGu6mryVfhAcCCP2XFGWjC-FnnF988DV8l67B2LoPmreUw",
  "payload": ""
}
2026-04-16 19:14:37,366:DEBUG:urllib3.connectionpool:https://acme-v02.api.letsencrypt.org:443 "POST /acme/authz/3247224861/689211775831 HTTP/1.1" 200 1059
2026-04-16 19:14:37,367:DEBUG:acme.client:Received response:
HTTP 200
Server: nginx
Date: Thu, 16 Apr 2026 19:14:37 GMT
Content-Type: application/json
Content-Length: 1059
Connection: keep-alive
Boulder-Requester: 3247224861
Cache-Control: public, max-age=0, no-cache
Link: <https://acme-v02.api.letsencrypt.org/directory>;rel="index"
Replay-Nonce: IRr4kSssuoCE7RLepVMPKru9nJSL2854eKerz1mUO2_I_hnwkMA
X-Frame-Options: DENY
Strict-Transport-Security: max-age=604800

{
  "identifier": {
    "type": "dns",
    "value": "xxx.xxxx.co.uk"
  },
  "status": "invalid",
  "expires": "2026-04-23T19:14:35Z",
  "challenges": [
    {
      "type": "http-01",
      "url": "https://acme-v02.api.letsencrypt.org/acme/chall/3247224861/689211775831/rai-mA",
      "status": "invalid",
      "validated": "2026-04-16T19:14:36Z",
      "error": {
        "type": "urn:ietf:params:acme:error:unauthorized",
        "detail": "77.72.1.30: Invalid response from http://xxx.xxxx.co.uk/.well-known/acme-challenge/mmCpzv_34ZOXZEBbVZ9jY12chmzXLeoYRlmSJt220XM: 404",
        "status": 403
      },
      "token": "mmCpzv_34ZOXZEBbVZ9jY12chmzXLeoYRlmSJt220XM",
      "validationRecord": [
        {
          "url": "http://xxx.xxxx.co.uk/.well-known/acme-challenge/mmCpzv_34ZOXZEBbVZ9jY12chmzXLeoYRlmSJt220XM",
          "hostname": "xxx.xxxx.co.uk",
          "port": "80",
          "addressesResolved": [
            "77.72.1.30"
          ],
          "addressUsed": "77.72.1.30"
        }
      ]
    }
  ]
}
2026-04-16 19:14:37,367:DEBUG:acme.client:Storing nonce: IRr4kSssuoCE7RLepVMPKru9nJSL2854eKerz1mUO2_I_hnwkMA
2026-04-16 19:14:37,368:INFO:certbot._internal.auth_handler:Challenge failed for domain xxx.xxxx.co.uk
2026-04-16 19:14:37,368:INFO:certbot._internal.auth_handler:http-01 challenge for xxx.xxxx.co.uk
2026-04-16 19:14:37,368:DEBUG:certbot._internal.display.obj:Notifying user: 
Certbot failed to authenticate some domains (authenticator: webroot). The Certificate Authority reported these problems:
  Domain: xxx.xxxx.co.uk
  Type:   unauthorized
  Detail: 77.72.1.30: Invalid response from http://xxx.xxxx.co.uk/.well-known/acme-challenge/mmCpzv_34ZOXZEBbVZ9jY12chmzXLeoYRlmSJt220XM: 404

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.

2026-04-16 19:14:37,370: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.

2026-04-16 19:14:37,370:DEBUG:certbot._internal.error_handler:Calling registered functions
2026-04-16 19:14:37,370:INFO:certbot._internal.auth_handler:Cleaning up challenges
2026-04-16 19:14:37,370:DEBUG:certbot._internal.plugins.webroot:Removing /var/www/nextcloud/.well-known/acme-challenge/mmCpzv_34ZOXZEBbVZ9jY12chmzXLeoYRlmSJt220XM
2026-04-16 19:14:37,384:DEBUG:certbot._internal.plugins.webroot:All challenges cleaned up
2026-04-16 19:14:37,386:DEBUG:certbot._internal.log:Exiting abnormally:
Traceback (most recent call last):
  File "/usr/bin/letsencrypt", line 33, in <module>
    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 1590, in certonly
    lineage = _get_and_save_cert(le_client, config, domains, certname, lineage)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  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.
2026-04-16 19:14:37,397:ERROR:certbot._internal.log:Some challenges have failed.

Also, I can now no longer log into my router! Going to the IP address for the router on my local network (192.168.1.1) now brings me to a Nextcloud page with the below message. If I try the IP address without the RPi connected to it then I just get a not found error! Arrgh!

Well, you messed up this installation wholesale.
First off, your Let’sEncrypt fails because you are using a wrong challenge that will not work on a NC installation. It’s clearly stated in the logs:

Certbot failed to authenticate some domains (authenticator: webroot). The Certificate Authority reported these problems:
Domain: xxx.xxxx.co.uk
Type:   unauthorized

“domain” being your timbilt.co.uk in this case. BTW this domain miraculously redirects to avianonline.co.uk which may indicate another layer of misconfiguration.

Reason: the webroot authenticator works by putting a randomly named file into the webroot of your host, informing Let’s Encrypt what is the filename and asking it to validate by accessing this file on your host.
Since you are running this authenticator on the NC host and apparently it is supposed to only serve NC, the file is placed in the NC webroot.
However, since you configured your NC to ask for authentication, this file will not be served at all, because NC asks any client (including Let’s Encrypt trying to remotely validate your website) for a password to log into NC and only then it will inform the client this file does not exist (because for the NC to serve a file, it needs to be present in the NC database). Let’s Encrypt tries to access the file directly by the URL, fails on authentication that is handled by NC and that’s it. No Let’s Encrypt for you.

Solution: use a DNS challenge authentication in your NC setup.

The router fiasco:
What you should’ve done is setting your router internal IP as “trusted proxy” in config.php just like your NC reminds you to. As I see it, you have put your NC into a “DMZ” of sorts or misconfigured the internal routing. You need to reset your whole setup to a state in which you can reach your router, make sure it works properly including internal and external routing and set up port redirection to a static IP you have blessed your NC with, both ports 80 and 443.
Once this is done, go to your Nginx configuration (/etc/nginx/sites-enabled/nextcloudserverconfigfilename) and follow the official example. Adjust for your server_name. Most probably the configuration file is similar or the same. Restart Nginx.
Confirm working by using internal IP first, external IP second (make sure your router is not set up for some crazy redirection loops, just plain port forwarding of 80 and 443 external to 80 and 443 internal NC IP). Now you can also use Nginx authentication which is easy peasy.

Do not set up two Let’s Encrypt authentication methods simultaneously.

All I did up to this point has been to exactly follow the instructions starting here, clicking through until here. I haven’t edited any files, changed any settings or anything else, literally all I did was: Download the image, flash it to an SSD, plug the SSD into a RPi4, connect the RPi to the router, turn it on, go to the webUI panel at nextcloudpi.local:4443, went to nc-forward-ports and clicked Apply, went to letsencrypt, entered my domain name and email and clicked Apply. Those instructions don’t include editing any config files, so I didn’t edit anything or change anything. I’m trying for the most basic plain vanilla set up as possible (at least to get started).

Clicking the nc-forward-ports Apply button is what looses me access to the router. I can reset the router and regain access, so I tried setting up the Port Forwarding manually. However as soon as I click on Apply in the router configuration menu then it disconnects me from the router, i.e. it does exactly the same as setting the Port Forwarding using nc-forward-ports.

I have now added a line into my config.php file in the trusted proxies array for my router local IP address, so this section of the file now looks like this:

'trusted_proxies' => 
  array (
    0 => '192.168.1.1',
    11 => '127.0.0.1',
    12 => '::1',
    14 => '127.0.1.1',
  ),

(the line 0 => '192.168.1.1', wasn’t there previously)
However this doesn’t appear to have done anything. I’ve rebooted the Pi, rebooted the router but when I turn on the port forwarding then I lose access to the router.

So if you can’t use Lets Encrypt in this way with Nextcloud then why does the NextcloudPi config panel include a letsencrypt button and tell you to use it the official instructions?

Why?
I mean, I know the first answer might be “because the manual says so”, however:

  • this wouldn’t be the first time NC manuals are slightly misleading or based on an isolated case of someone writing it
  • keep in mind you are following instructions from 2022 and a lot could’ve changed since, it was a millennium ago in NC terms
  • what I meant by “why” is expandable to “are you aware of the actual results of your clicks”?

The usual way of setting up a NC instance is: you run it on a static internal IP (or at the very least - a DHCP reservation, so it always gets the same IP from your gateways DHCP server). You manually map your external 80 port to the 80 port on the RPi internal IP and external 443 port to 443 port on the RPi internal IP. This must work, period.
UPNP is (mostly) fun and easy, but it can be messy. It became messy in your case. I can not replicate this right now, as all but one of my RPis are doing something else and I can not be persuaded to try to replicate your situation on a Pi Zero, but here’s what happened: the UPNP “hack” (I find it to be a hack in this very case) mapped the port 80 of the internal IP of your router (192.168.1.1) to port 80 on your RPi internal IP. What it should have done is mapping the external IP of the router to the internal IP of your RPi. It didn’t. This is why when you try to reach your router admin page (192.168.1.1), you land on the NC login (or actually: error) page. IDK if this is a faulty implementation on NC side, router side, but this is irrelevant now. By clicking the “UPNP” button you’ve misconfigured your router and effectively locked yourself out of the admin access.

The good news is, UPNP mappings are temporary. If implemented properly, they should close as soon as the app (in this case - NC) requesting UPNP mapping quits. If less than properly, a reboot will cure it, as you have already found out. So you can have your router back.

Since the very same thing happens when you set up manual port mapping, let me ask you some more questions:

  • do you map the ports on your external interface to your internal RPi IP?
  • Is the IP in your logs your actual IP? (77.72.1.30 according to the log attached in the first post) It does not seem to be a static external address of your connection. This is an IP belonging to krystal.io web hosting service, definitely not running on a RPi. Points to an error page on the hosting site.

Somehow Let’sEncrypt tries to ask this IP to validate a certificate for your domain, and quite obviously, since there is nothing of yours on this IP, especially the file your Let’sEncrypt client has put into the webroot located physically on the RPi, it fails. This raises questions about your DNS setup (both your router DNS client and your domain DNS setup), but this is way beyond the scope of an installation to a Raspberry Pi.

On the port forwarding.

I’m trying to learn by doing with this project, so I don’t see that following the manual as exactly as possible is unreasonable as first step. I have a technical background, but I’m new to networking, I wasn’t aware of UPnP or port forwarding before starting this and only had a hazy idea (it still is pretty hazy to be fair!) about DNS, DDNS, and how domain names point to IP addresses. NextcloudPi seems to be actively developed (the version I’m using was released 4 days ago) and that project’s official documentation points to the posts on this forum including how to access your network from outside. So following the most official source of information you can find seems pretty normal.
Anyway, it also doesn’t seem unreasonable to use UPnP. UPnP was enabled by default on my router when it was shipped (I now know that this probably isn’t a good idea so I’ve turned it off), so nc-forward -ports actually seems to have worked fine and done exactly the same as setting up the port forwarding manually. I’ve searched a bit and found it’s a common problem with Linksys routers. It seems I could set it up so that it doesn’t do this, but then I wouldn’t be able to access my Nextcloud from the external address when on my local network (which I guess might stop the phone app from working when the phone is on my home network?), so I won’t do that. Anyway, I can access the router set up through an app on my phone or by using the router’s IPv6 address, so actually it’s not really a problem anyway. So that’s now basically solved.

On the encryption certificates

No, 77.72.1.30 isn’t my home IP address. Krystal is who I use for webhosting and who administers my domain name. I had set up a 301 redirect from my subdomain.domain.co.uk to my home IP address, but I guess that was wrong. So I have now deleted that and added an A record to my DNS table to point the subdomain to my home IP address. However I’m now getting a 404 Not Found error when I try to access this subdomain. Is there anything else I need to do? I left the TTL set to the default value of 3600, there were no other settings I could see.

Great! We’re getting closer to the goal.
Good job with domain DNS setup. Yes, you need to point an A record (called, for example, home (not “home.mydomain.co.uk”) to your external IP at, well, home. “Type” = A", “Name” = “home”, “value” or “content” = “IP address”. It is a static record, but you’ve got static IP so it is all good.

Intermission: UPNP looks like a good idea but it is designed for ephemeral connections; applications may open and close random ports to their liking. Just because of this, in most cases UPNP works relatively decent on non-standard (“high”) ports, but standardized ports are in some implementations exempt from UPNP mapping completely. So static port mapping is crucial for a stable server.

Now as you have pointed your “home” subdomain to your IP address, the DNS should have already propagated enough so your NC will probably recognize the address it is running on. Depending on your OS, please use ping or nslookup or any other command that needs to resolve your home.yourdomain.co.uk to an IP address and you should see a familiar IP number in response.

Now you may want to access the NC from the local network and set up the hostname (home.yourdomain.co.uk). Disable UPNP in NC. Disconnect the phone from your wifi and try this address with your browser on the phone. Your NC instance web interface should pop up right there.

If not: reduce the “trusted proxies” to your 192.168.1.1 internal router address only.
If still not: try the IP address and not the domain name. If this works, there is something to be corrected in the DNS.

Once you are able to connect from the outside, you can proceed to the Let’sEncrypt part of the NC and it will, most probably, work. I don’t know if there is a toggle for that, but I think once your certificates are successfully obtained, you will be able to redirect cleartext traffic from port 80 to encrypted port 443 automatically or disable non-secure port completely. NC should do either by itself, no configuration necessary.

Thank you for your help, yes, it does seem to be getting closer, although I’m still somehow failing on the DNS settings.

The record I have added is as follows:
Type: A
Name: just the subdomain, i.e. ‘home’ not ‘home.mydomain.co.uk’ in your naming
Content: My static IPv4 address (just the address, no http or https)
TTL: 3600

There is nothing else there related to the subdomain (I have also deleted everything I had set in cPanel for the previous redirect I had). The other entries in this zone are 4 NS entries top level domain for ns1-ns4.kloudns.co.uk and an SOA entry for admin.katapult.io, these were put there by my hosting provider, I haven’t changed them (and they’re all for the top level domain, not the subdomain anyway)

However when I navigated to the <home.mydomain.co.uk> address I just get the Hosting Provider’s placeholder for a broken link. nslookup gives:

Server:		127.0.0.53
Address:	127.0.0.53#53

Non-authoritative answer:
Name:	<home.mydomain.co.uk>
Address: 77.72.1.30

I get the same results whether I’m on the local network or outside it.

OK, I am no expert in CPanel, but will show you how I’ve done the same thing with my DNS provider (Cloudflare). I have merely changed the actual domain name to mydomain.com and the IP addresses I use to 1.2.3.4 and 4.5.6.7 for screenshot purposes:

So, the mydomain.com resolves to 1.2.3.4. Any web server that runs on this IP will answer to a client and display whatever is in the webroot. However, since I have a couple of name-based web servers running on this IP (this is beyond the scope of your setup), if someone types cloud.mydomain.com, the DNS will obviously point them to the same IP my domain points to, but the Nginx server will pick up this request and serve content from the webroot that is dedicated to cloud.mydomain.com. Same goes for other names that indicate 1.2.3.4 as target. Obviously, if someone types backup.mydomain.com, DNS will point them to completely different IP and a server that runs there.

This is exactly what you want to achieve. If your home.mydomain.co.uk still resolves to your main domain, there is something wrong with the DNS setup. Please check your CPanel for a wildcard record, perhaps this is a culprit? Something to the lines of *.example.com. Or check if your Cpanel expects you to actually put home. (note the dot), Cloudflare doesn’t and adds the dot automatically but YMMV.

HOORAY!! Thank you for your help, all working now!

I found the DNS zone editor settings in cPanel and set the A record there. There was a general hosting service provided DNS settings page which was where I originally set the A record, but I think that because I was using cPanel for the top level domain that must have been overriding these settings, when I added the A record in cPanel then it worked. So I then set the trusted domain and ran nc-letsencrypt from the webUI panel and it’s now all working, both from local network and from outside.

Marvelous. Have fun with your NC!