Jitsi Let's Encrypt certificate failed: how to diagnose it

Short answer

Start with the exact ACME error and identify which component owns HTTPS. Check DNS A and AAAA records, public port 80 and challenge routing before another certificate request. An HTTP response alone does not prove validation works. Preserve ACME state, respect the CA's retry time and verify the certificate actually served. [S1][S2][S3][S7]

Scope, checked 23 October 2026: Docker examples are reviewed against stable-11248-1, commit 274d3e4, released 22 October. Package differences are reviewed at jitsi-meet_11248, not asserted for every installed package. These are source-reviewed diagnostics, not a new live ACME issuance or full meeting test. [S5][S12]

Commands use a Linux/Bash shell. Docker checks require Compose; external checks use dig, curl and OpenSSL on a diagnostic machine. Run network checks from outside the meeting server’s network where indicated. [S8][S10][S11][S13][S14]

First identify the error and the HTTPS owner

From your normal Compose project directory, retain any -f files and project options your deployment uses. Read service state and recent web logs privately; redact domains, addresses, account details and tokens before sharing output. These commands do not request a certificate. [S6][S13]

Terminal
docker compose ps --all web
docker compose logs --tail=100 web

Record the full ACME error, failing hostname or URL, and whether HTTPS belongs to the Docker web container, an external proxy or a package installation. In the reviewed source, the built-in issuer uses standalone HTTP validation on container port 8000; Compose maps ${HTTP_PORT} to 8000 and ${HTTPS_PORT} to 8443. A custom proxy has a separate request path. [S6][S7]

Symptom Check next, not a confirmed cause
NXDOMAIN, missing address or unexpected IP DNS and IPv6
Timeout or connection refused during HTTP validation Public HTTP reachability
unauthorized, invalid response or challenge 404 Challenge routing
A CA rate-limit error Retry limits and staging
Certificate expired after previously working Renewal and installed client
Unexpected certificate or browser warning Served certificate

Use the actual error and endpoint observations to select a branch. These symptoms alone do not establish their cause. [S1][S2][S3][S7][S10][S11]

1. Check DNS and IPv6

Replace meet.example.com everywhere with your meeting hostname. From outside the server’s network, query both address types. dig is a separate utility; install it through your operating system’s package manager if absent. [S2][S14]

Terminal
dig +short A meet.example.com
dig +short AAAA meet.example.com

Compare every result with the intended public endpoint in your hosting or proxy configuration. An outbound “what is my IP” lookup is not proof of inbound routing. With a proxy, its public address can legitimately differ from the origin. [S1][S14]

If an AAAA record exists, verify IPv6 reaches the correct challenge handler. Let’s Encrypt prefers IPv6 initially; some failures do not fall back to IPv4, and redirects have additional fallback limitations. Fix incorrect routing or remove an unwanted stale record only after confirming other services do not need it. An IPv4 browser test alone does not resolve this question. [S2]

2. Check public HTTP reachability

HTTP-01 starts on public TCP port 80. Publishing only 8000 does not make the CA choose that port. Check cloud and host firewalls, plus router forwarding where applicable. With HTTP_PORT=80, the reviewed Compose file maps host port 80 to container port 8000. [S1][S6]

From another network, make bounded GET requests over IPv4 and, if you publish IPv6, IPv6. The filename below is a probe, not an ACME token. These commands print headers, discard the body and do not follow redirects. [S8]

Terminal
curl -4 --connect-timeout 5 --max-time 15 -sS -D - -o /dev/null \
  http://meet.example.com/.well-known/acme-challenge/jitsi-help-probe

# Only if AAAA is intentional and the test client has IPv6 connectivity.
curl -6 --connect-timeout 5 --max-time 15 -sS -D - -o /dev/null \
  http://meet.example.com/.well-known/acme-challenge/jitsi-help-probe

A 404 for this made-up filename is not, by itself, an ACME failure. An HTTP response shows a responder was reachable from this client at this time. It does not prove the actual token, every published IP or the CA’s requests reach the right handler. A timeout does not identify the failing network layer; an IPv6 test can also fail because the test client has no IPv6 route. [S1][S2][S8]

3. Check challenge routing and port ownership

Inspect docker compose ps --all web for published ports and stopped containers. If another service owns the intended host port, identify it before changing anything. Do not stop a shared proxy or another website merely to free a port. Follow the reverse-proxy guide when the proxy is the intended HTTPS owner. [S6][S7][S13]

For unauthorized or invalid-content errors, inspect the actual challenge URL named in the ACME log during the attempt. A login page, generic application response or wrong token is not the challenge answer. Review proxy/CDN routing and redirects instead of assuming one CDN is always responsible. Let’s Encrypt allows certain HTTP-to-HTTPS redirects; blanket removal of redirects or proxying is not the default fix. [S1]

Use ports and firewall diagnostics for network layers and three-participant media diagnostics after HTTPS works. Certificate validation and meeting media are separate checks. [S1][S6]

4. Review Docker settings before one controlled retry

For direct HTTPS in the reviewed Docker web container, compare .env privately with this example. Use your own hostname and account email. Set LETSENCRYPT_ACME_SERVER=letsencrypt explicitly when that is your intended CA; the feature’s name alone does not establish the selected CA. [S6][S7][S15]

Config
ENABLE_LETSENCRYPT=1
DISABLE_HTTPS=0
LETSENCRYPT_DOMAIN=meet.example.com
LETSENCRYPT_EMAIL=admin@example.com
LETSENCRYPT_ACME_SERVER=letsencrypt
PUBLIC_URL=https://meet.example.com
HTTP_PORT=80
HTTPS_PORT=443

If a proxy owns public HTTPS, use its certificate manager and configuration path instead. Keep release files and images consistent; see checking your Jitsi version. [S5][S6]

After resolving the observed cause, apply environment changes during a maintenance window. Recreating web interrupts its connections and startup can attempt issuance. Retain your normal Compose files/options and persistent storage, then make one controlled attempt: [S7][S9]

Terminal
docker compose up -d --no-deps --force-recreate web
docker compose logs --tail=100 web

docker compose restart web alone does not update environment settings. If validation fails again, investigate the new error rather than looping this command. In the reviewed source, an issuance error can stop startup; not every failure falls back to a working self-signed site. [S7][S9]

5. Respect retry limits and use staging carefully

Let’s Encrypt has different limits for orders, certificates and failed authorizations. Read the exact error and retry time; “wait a week” is not the answer to every limit. Preserve client/account state instead of deleting it or reinstalling the client to try again. [S3]

On a separate test deployment, LETSENCRYPT_USE_STAGING=1 selects staging in the reviewed Docker source. Staging certificates are deliberately untrusted by ordinary browsers. Do not install a staging CA as a trusted root on participant devices. Success tests that setup at that time, not production issuance or future renewal. [S4][S7][S15]

Do not toggle staging on a working meeting server as a casual experiment. Stored state and CA selection matter. Before returning a test deployment to production, review its ACME state, remove the staging setting, apply the intended configuration and verify a trusted certificate at the public endpoint. [S3][S4][S7]

6. Separate renewal from first issuance

For the reviewed rootless Docker release, ACME state is under /storage/acme.sh and installed certificates under /storage/acme-certs/<hostname>/; Compose persists web storage at ${CONFIG}/storage/web. A separate service checks due renewals. Preserve these directories and inspect permissions/mounts before recreating anything. [S6][S7][S16]

Expiry alone does not identify the cause. Routing may have changed, a scheduled service may have failed, or the endpoint may still serve an old file. For the specific seteuid: Operation not permitted regression on stable-11146 and stable-11146-1, use the rootless renewal recovery guide and its version boundaries. [S16][S17]

Debian and Ubuntu package installs

The helper reviewed at jitsi-meet_11248 uses acme.sh under /opt/acmesh/.acme.sh, writes /etc/jitsi/meet/<hostname>.crt and its key, and configures a web-server reload. An older/custom installation may use Certbot: identify the installed client and scheduler before choosing renewal commands or log paths. The helper is not read-only, so do not rerun it blindly or apply Docker paths to a package installation. [S12]

The renewal guide’s package section separates reviewed acme.sh and older Certbot paths. Never share private keys or an unredacted ACME account directory. [S12]

Verify the certificate clients receive

From outside the server, test HTTPS without -k or --insecure. This checks the endpoint with this client’s trust store, not a meeting or every participant device. [S8]

Terminal
curl --connect-timeout 5 --max-time 15 -I https://meet.example.com/

Inspect the leaf certificate’s hostname coverage, issuer, serial and dates with SNI. This inspection pipeline alone does not establish chain trust or successful hostname verification. Stop a stalled connection with Ctrl+C. [S10][S11]

Terminal
openssl s_client -connect meet.example.com:443 \
  -servername meet.example.com </dev/null 2>/dev/null \
  | openssl x509 -noout -subject -issuer -serial -dates -ext subjectAltName

Compare the result with the intended hostname, current time and certificate installed by the actual HTTPS owner. A trusted issuer other than Let’s Encrypt is not inherently wrong. Check in a browser without bypassing warnings, then test three-client media separately before declaring the meeting service ready. [S8][S10][S11]

Prevention and open questions

Keep the chosen challenge route available for renewal, preserve persistent ACME state and check the served certificate after proxy, DNS or release changes. Record installation type, image/package version, exact sanitized error and whether IPv4/IPv6 checks differed. [S1][S2][S3][S6]

A customer’s actual client, routing, affected addresses and CA response cannot be determined from a browser warning alone. This review did not run public CA issuance, wait for renewal or reproduce a customer’s deployment.

Sources

Checked 23 October 2026. Docker links pin commit 274d3e4; the package helper pins f765042.

Written by the Jitsi Help engineering team

Jitsi infrastructure engineers who deploy and run Jitsi Meet servers in production. Last updated . How we write our guides

Stuck on something this page does not cover? Ask a question below. Jitsi Help engineers read every one.

Did this fix it?

Something on this page is outdated or wrong?

Collect debug info

These commands gather what an engineer needs to diagnose a Jitsi server. Copy them, run them, and keep the output.

Terminal
# Run on the server, from your docker-jitsi-meet folder

# 1. Every service should be "running" (or "healthy")
docker compose ps

# 2. Which images and release tags are running
docker compose images

# 3. Recent logs from the core services
docker compose logs --tail=200 web prosody jicofo jvb

# 4. The settings most fixes depend on
grep -E '^(PUBLIC_URL|JVB_ADVERTISE_IPS|ENABLE_LETSENCRYPT|ENABLE_AUTH|AUTH_TYPE)=' .env

# 5. Is anything listening for media on UDP 10000?
sudo ss -ulnp | grep 10000

Installed with the Debian packages instead of Docker? Read the service logs with:

Terminal
sudo journalctl -u prosody -u jicofo -u jitsi-videobridge2 --since "1 hour ago"

Remove passwords, secrets and tokens before you share any output.

Send the output to an engineer

Frequently asked questions

Why can my Jitsi website load while Let's Encrypt validation fails?

The website and challenge request can reach different handlers or address families. An HTTP response from the homepage or a made-up challenge path does not prove the real ACME token is served correctly. Check the failing URL, returned content, redirects and both A and AAAA records. [S1][S2]

Does restarting Docker apply my changed Let's Encrypt settings?

No. docker compose restart does not update container environment settings. After reviewing the change, use the same Compose files as your deployment and recreate the web service during a maintenance window. [S9]

Does a non-Let's Encrypt issuer mean my certificate is broken?

No. Another trusted CA or your reverse proxy can legitimately issue the certificate. Check hostname coverage, validity dates and chain trust at the endpoint clients actually use. The issuer name alone is not a failure test. [S10][S11]

Should I delete the certificate folders or keep retrying?

No. Preserve ACME account and certificate state, diagnose the failed validation and follow the CA's retry guidance. Reinstalling the client or deleting its state can consume issuance limits. Use staging on a separate test deployment while developing the setup. [S3][S4][S7]

Do Debian and Ubuntu Jitsi installs always use Certbot?

No. The helper reviewed at jitsi-meet_11248 uses acme.sh under /opt/acmesh/.acme.sh. Older or customized installations can use another client. Identify the installed client before following renewal instructions. [S12]

Discussion

    Stuck, or would rather not do this by hand?

    Deploy it in one click

    A private Jitsi server in your own AWS account with SSL, your domain and optional recording, transcription and JWT. Free 15 minute trial.

    Start free trial

    Talk to a Jitsi engineer

    Setup, fixes, branding, recording, scaling. Tell us what is happening and we reply with a plan and a quote.

    Get expert help

    Related

    Recently updated