> Source: https://meetrix.io/blogs/jitsi-meet-ssl-certificate-renewal/
> Markdown copy of that page. Cite the URL above, not this file.

IAM & Security

# Jitsi SSL Certificate Renewal: Let's Encrypt on One Server or Several Shards

[By Hiruna Kumara](https://meetrix.io/blogs/authors/hiruna-kumara/) • September 18, 2026 • 5 min read

An expired certificate is one of the few Jitsi failures that takes down every meeting at once. Browsers refuse the page, the mobile apps refuse to connect, and it always seems to happen on a Monday morning. Renewal is meant to be automatic. Here is how it works, why it quietly stops, and how we handle it on setups with more than one shard.

## Check when your certificate expires

Start with the certificate your users actually get, not the file on disk:

```bash
echo | openssl s_client -connect meet.example.com:443 -servername meet.example.com 2>/dev/null \
  | openssl x509 -noout -issuer -enddate
```

Let's Encrypt certificates last 90 days and are normally renewed around 30 days before `notAfter`. If the date is less than three weeks away, renewal has probably been failing for a while.

No more reminder emails

Let's Encrypt stopped sending expiry warning emails in 2025. If you relied on those, nothing will warn you now. Add the expiry date to your monitoring.

## SSL certificate renewal process on a single Jitsi server

How renewal works depends on how the certificate was created.

### Installed with the Jitsi Let's Encrypt option (acme.sh)

Current Jitsi packages set up Let's Encrypt with [acme.sh](https://github.com/acmesh-official/acme.sh), installed under `/opt/acmesh`. It issues the certificate using the web root `/usr/share/jitsi-meet`, copies it to `/etc/jitsi/meet/`, and adds a daily cron job that renews it and reloads nginx.

```bash
# list certificates and their next renewal date
sudo /opt/acmesh/.acme.sh/acme.sh --list --home /opt/acmesh/.acme.sh

# renew now, even if it is not due yet
sudo /opt/acmesh/.acme.sh/acme.sh --renew -d meet.example.com --force --home /opt/acmesh/.acme.sh
```

If the certificate was never set up, or you replaced it by hand, rerun Jitsi's script: `sudo /usr/share/jitsi-meet/scripts/install-letsencrypt-cert.sh`. It installs acme.sh, issues the certificate and wires up renewal.

### Older installs with certbot

Servers set up before Jitsi switched to acme.sh often use [certbot](https://eff-certbot.readthedocs.io/). Test the renewal without touching the live certificate:

```bash
sudo certbot renew --dry-run
systemctl list-timers | grep certbot   # is the renewal timer running?
```

## Why Jitsi certificate renewal fails

| Symptom | Usual cause |
| --- | --- |
| Timeout during the challenge | TCP port 80 closed in the firewall or security group. Meetings only need 443, so it gets closed "for security". |
| Wrong IP in the challenge | DNS points somewhere else: a new Elastic IP, a CDN, or a second shard. |
| Renewed, but browsers still see the old one | nginx was not reloaded, or the certificate was copied to the wrong path. |
| Web works, calls through TURN fail | coturn uses its own copy of the certificate and was not restarted. |

Port 80 is the big one. Keep it open and redirect it to HTTPS in nginx, which the Jitsi config already does. Our list of [ports Jitsi Meet needs](https://meetrix.io/blogs/jitsi-meet-ports/) includes it for exactly this reason. If you run coturn on the same domain, add a coturn restart to the renewal's reload command; [setting up a TURN server for Jitsi Meet](https://meetrix.io/blogs/setting-up-a-turn-server-for-jitsi-meet/) shows where coturn reads its certificate.

## Renewing SSL on a multi-shard Jitsi setup

Larger setups run two or more shards, each with its own HAProxy or Meet server, behind a single domain. That breaks the HTTP challenge: Let's Encrypt connects to whichever shard DNS gives it, and that may not be the one that asked.

### Option 1: one shard at a time with Route 53 weights

This is the process we used in 2021, and it still works when the shards sit behind [weighted Route 53 records](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/routing-policy-weighted.html):

1.  Set shard 2's record weight to 0, so all traffic, including the challenge, goes to shard 1.
2.  Wait for the old DNS answers to expire (the record's TTL), then run the certificate script on shard 1's server.
3.  Swap: shard 1 to 0, shard 2 back up, wait for the TTL, run the script on shard 2.
4.  Set both weights back to their normal values. Forget this step and one shard carries every meeting.

It works, but it is manual, every 60 days, and step 4 is easy to miss. Only do it outside busy hours, because the shard you drain still hosts running conferences until they end.

### Option 2: DNS-01 challenge through Route 53

Better. With the DNS challenge, Let's Encrypt checks a TXT record instead of connecting to the server, so it doesn't matter which shard DNS points at. acme.sh has a Route 53 plugin (`--dns dns_aws`); give the instance an IAM role allowed to change that one hosted zone, and each shard renews on its own, with no weight changes.

### Option 3: terminate TLS on the load balancer

If the web traffic already passes through an AWS Application or Network Load Balancer, put an ACM certificate on it. ACM renews by itself and there is nothing on the shards to renew. Media still flows directly to the videobridges on UDP 10000, which doesn't use this certificate.

For Jitsi on Kubernetes, the certificates live in Secrets and the process is different again; see [updating SSL certificates in Jitsi Meet and TURN servers on Kubernetes](https://meetrix.io/blogs/updating-ssl-jitsi-kubernetes/). And if you're still planning how shards fit together, read [Jitsi load balancing with multiple videobridges](https://meetrix.io/blogs/jitsi-meet-load-balancing/) first.

## Frequently Asked Questions

Does Jitsi Meet renew its Let's Encrypt certificate automatically?

Yes, if you used the installer's Let's Encrypt option. Current Jitsi packages use acme.sh, which installs a daily cron job and renews the certificate before it expires. Older installs used certbot with its own timer.

Why did my Jitsi SSL certificate renewal fail?

Most often port 80 is closed. Let's Encrypt's HTTP challenge fetches a file over plain HTTP, so the firewall or security group must allow TCP 80 even though meetings run on 443. A changed DNS record or a load balancer in front is the next most common cause.

How do I check when my Jitsi certificate expires?

Run openssl s\_client against your domain on port 443 and pipe it to openssl x509 -noout -enddate. It prints the notAfter date of the certificate your users actually receive.

How do I renew SSL on a multi-shard Jitsi setup?

Either renew one shard at a time while DNS sends traffic to the other, or switch to the DNS-01 challenge through Route 53 so every shard can renew without being reachable on port 80. Terminating TLS on an AWS load balancer with ACM removes renewal work entirely.

Will Let's Encrypt email me before my certificate expires?

No longer. Let's Encrypt stopped sending expiry reminder emails in 2025. Monitor the expiry date yourself, for example with an uptime checker that alerts two weeks before notAfter.

Meetrix Store

Jitsi Meet

Self-hosted video calls for 50 to 500 users

[Deploy it](https://meetrix.io/store/jitsi-meet/)

Meetrix Store New

Deploy what this guide covers, pre-configured.

-    [Jitsi Meet Self-hosted video calls for 50 to 500 users](https://meetrix.io/store/jitsi-meet/)
-    [Coturn TURN/STUN for WebRTC, no per-minute relay fees](https://meetrix.io/store/coturn/)
-    [Mattermost Team chat, a self-hosted Slack alternative](https://meetrix.io/store/mattermost/)
-    [RustDesk Remote desktop AMI, a TeamViewer alternative](https://meetrix.io/store/rustdesk/)
-    [Listmonk Newsletters with no per-subscriber fees](https://meetrix.io/store/listmonk/)
-    [Supabase Postgres, Auth, Storage and Realtime, self-hosted](https://meetrix.io/store/supabase/)

[Browse all products](https://meetrix.io/store/)
