Set up Let's Encrypt SSL for Jitsi Meet

Short answer

Choose which service owns HTTPS before configuring certificates. For direct Docker HTTPS, use matching release files, a hostname that reaches the server, public port 80 for HTTP-01 and persistent writable certificate storage. Select Let's Encrypt explicitly, apply changed settings by recreating web, then verify the certificate visitors actually receive. A successful first issuance does not prove future renewal.

For a public Jitsi Meet server, use HTTPS with a certificate your clients trust. Browser camera and microphone access requires a secure context, with exceptions such as localhost development. Fixing TLS is one part of getting a meeting working; it does not test signaling or media. [S1]

Scope: Docker instructions were source-reviewed on 23 October 2026 against stable-11248-1, commit 274d3e4c4e6e7d4a2ec90bacb4579dc0463cccd2. Keep Compose files and images from the same release. This is a setup guide for administrators; for an existing certificate error, start with certificate failure diagnostics. No public certificate issuance or full Jitsi deployment was tested for this revision. [S2][S3]

Choose who owns HTTPS

Your deployment Certificate and renewal owner Continue with
Jitsi web is the public HTTPS endpoint The web container’s built-in ACME client Direct setup below
You already obtain a certificate elsewhere Your certificate automation, with files supplied to web Own certificate below
An external proxy serves public HTTPS The proxy and its certificate automation Reverse proxy section

These paths use different settings and files. Choose one owner before applying changes. The reviewed web template selects its certificate paths according to ENABLE_LETSENCRYPT; DISABLE_HTTPS=1 turns off container HTTPS. [S3][S4][S5]

The built-in Let’s Encrypt setup

Check the prerequisites

Use an existing Docker installation with generated service passwords, the release’s required directories and a configured CONFIG location. Follow Docker installation for the base installation, or the rootless upgrade guide for an older deployment. The web container needs persistent writable ${CONFIG}/storage/web; do not delete existing ACME account or certificate state to start over. [S3][S4][S6]

Before requesting a certificate:

  1. Check both the hostname’s A and AAAA records. Each published address must route to the intended validation endpoint. Let’s Encrypt prefers IPv6 initially when both record types exist; an incorrect AAAA record can break validation even when IPv4 works. [S7]
  2. Allow public TCP port 80 through the relevant network and host firewalls to the challenge responder. HTTP-01 begins there. In this release, built-in standalone validation listens on container port 8000; the example below maps host 80 to it. Port 443 serves public HTTPS. [S3][S4][S8]
  3. Check that another web server is not already using those host ports. If a proxy owns them, use the proxy path below. A generic HTTP response is only a reachability check, not proof that a real ACME token is served correctly. [S3][S8]

Configure direct HTTPS

In your project’s .env, replace the hostname and email placeholders. This block is an addition to the release configuration, not a complete .env. Explicitly select Let’s Encrypt: the reviewed environment example documents a different default ACME provider. [S3][S9]

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

For a new, fully configured stack, start it from the release directory and review web startup logs. Include any extra Compose files or project options your installation requires. The following shell commands require Docker Compose v2. [S6][S10][S11]

Terminal
docker compose up -d
docker compose ps
docker compose logs --tail 100 web

For an existing running stack where only web’s SSL environment settings changed, schedule a maintenance window. After checking DNS, ports and storage, recreate web with your usual Compose files and project options. This interrupts web access and can trigger issuance. restart alone does not apply changed environment variables. Avoid repeatedly recreating a failing service. [S4][S10]

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

Test against staging first

Use a separate lab deployment and hostname when experimenting with issuance. In that lab’s configuration, LETSENCRYPT_USE_STAGING=1 selects staging for the reviewed startup script. Staging certificates are deliberately untrusted; do not switch a working production endpoint to staging or teach users to bypass certificate warnings. [S4][S12]

A successful staging request checks that particular staging attempt. It does not prove production issuance, client trust or future renewal. Moving to production requires production settings, a controlled web recreation and fresh HTTPS verification; a simple restart does not apply the environment change. Preserve the existing state and follow the diagnostic guide if the client retains an unexpected certificate. [S10][S12]

Using your own certificate

Choose this when your existing automation supplies a certificate, for example a wildcard obtained through DNS validation. With container HTTPS enabled, set the following in .env. Built-in ACME must be disabled for the custom-file branch. [S4][S5][S8][S9]

Config
DISABLE_HTTPS=0
ENABLE_LETSENCRYPT=0
PUBLIC_URL=https://meet.example.com

Use the actual CONFIG path from your Compose deployment, not a fixed /opt path. In the reviewed release, startup reads this pair and copies it to writable storage: [S3][S4][S5]

Purpose Host input Container input Active container file
Certificate and intermediate chain ${CONFIG}/web/keys/cert.crt /config/keys/cert.crt /storage/keys/cert.crt
Matching private key ${CONFIG}/web/keys/cert.key /config/keys/cert.key /storage/keys/cert.key

Before replacing files, back up the existing pair securely. Use the hostname’s certificate first, followed by the required intermediate certificates in cert.crt. Restrict private-key access while allowing the rootless container user to read it; allow that user to write the storage directory. A root-owned, owner-only key can prevent startup. Do not publish the key or put certificate material in the website repository. [S4][S13]

After applying changed environment settings, use the controlled web recreation above. Your external certificate automation remains responsible for renewal, supplying the updated pair and arranging a controlled activation. The built-in renewal service disables itself when ENABLE_LETSENCRYPT is not 1. Verify the served certificate after each activation. [S4][S10][S14]

Behind a reverse proxy

If an external proxy owns public HTTPS, let it manage the certificate and renewal. The Jitsi handbook’s HTTP-upstream configuration uses these settings: [S6]

Config
DISABLE_HTTPS=1
ENABLE_LETSENCRYPT=0
ENABLE_HTTP_REDIRECT=0
PUBLIC_URL=https://meet.example.com

Set up the upstream address, host-port bindings and signaling routes using Jitsi behind a reverse proxy. Setting HTTP_PORT=8000 alone does not bind a published port to localhost: the stock Compose mapping has no loopback address. Use an explicitly restricted binding for a host proxy or the appropriate private container network. [S3][S6]

Validate the certificate at the public proxy endpoint. For connectivity beyond HTTPS, follow the ports and firewall guide; a working web proxy does not establish media connectivity. [S6]

IP address only, no domain

Trusted IP certificates are possible: Let’s Encrypt made short-lived IPv4 and IPv6 certificates generally available in January 2026. They require an ACME client that requests the appropriate certificate profile. That CA capability is separate from support in Jitsi’s built-in configuration. [S15]

This guide’s verified source path uses a DNS hostname. We have not tested IP-only issuance, its shorter renewal lifecycle or Jitsi client compatibility. Use a hostname for this recipe, or validate an IP-certificate deployment separately. Disabling certificate checks is not a substitute for a trusted certificate.

Verify HTTPS and renewal

From a client outside the server’s network, replace the placeholder and run this with curl. Do not add -k: it would disable certificate verification. The request must succeed without a certificate error and reach your expected Jitsi endpoint. Then check the same URL in a browser without bypassing warnings. [S16]

Terminal
curl --fail --show-error --silent --output /dev/null \
  --write-out 'HTTP %{http_code}\n' https://meet.example.com/

With OpenSSL available inside the web image, inspect the built-in ACME certificate’s metadata. This command reads the public certificate, not the private key. Metadata is not proof that a browser trusts the chain, or that a proxy serves this file. [S4][S17]

Terminal
docker compose exec -T web openssl x509 \
  -in /storage/acme-certs/meet.example.com/fullchain.pem \
  -noout -subject -issuer -serial -dates -ext subjectAltName

The reviewed renewal service waits 60 seconds after starting, then runs due-renewal checks every 12 hours. It needs the installed ACME client and persistent writable state; it stops when container HTTPS or built-in ACME is disabled. Check logs, monitor the externally served expiry and verify a later successful renewal. Initial issuance alone does not establish that renewal will work. For the historical rootless cron failure, use renewal recovery. [S14]

Debian and Ubuntu packages

Do not copy Docker paths or recreation commands into a package installation. The helper reviewed at jitsi-meet_11248, commit f765042bf280cbd7dcd4a9bbdb63b09e9e4d3259, uses acme.sh with its own installation, certificate files and web-server reload commands. Older installations may use Certbot. Identify the installed client and scheduler before changing renewal; rerunning the installation helper is not a read-only test. [S18]

When it fails

Use Let’s Encrypt and SSL error diagnostics to distinguish DNS/IPv6, challenge routing, permissions, CA limits and an unexpected served certificate. Correct the evidenced cause before another issuance attempt. Preserve account and certificate state; repeated fresh requests are not a renewal strategy. [S4][S14]

Open questions and maintenance

This revision was checked against upstream source and documentation, with publication checks on the built page. We have not issued a public certificate, exercised real renewal, deployed each proxy variant or tested a complete meeting for this revision. Custom-key ownership depends on your host and container mapping. IP-only Jitsi is outside the tested scope. Recheck these paths and service behavior when upgrading beyond the pinned release.

Sources

Reviewed 23 October 2026. Docker source links are pinned to the reviewed release commit.

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 guide work for you?

Something on this page is outdated or wrong?

Frequently asked questions

Does Jitsi need HTTPS for camera and microphone access?

For a public deployment, serve Jitsi over HTTPS with a certificate clients trust. Browser camera and microphone APIs require a secure context; localhost development has exceptions. A valid certificate does not by itself prove meeting media works.

Does docker compose restart apply changed SSL settings?

No. Restart does not update container environment variables. After checking the settings, recreate the web service with the same Compose files and project options you normally use, during a maintenance window.

Where do custom certificates go in rootless Docker Jitsi?

In the reviewed stable-11248-1 layout, supply cert.crt and cert.key under the host CONFIG/web/keys directory. With built-in ACME disabled, startup copies that pair from /config/keys to persistent /storage/keys. The rootless container must be able to read the inputs and write the storage.

Can a reverse proxy manage Jitsi's certificate?

Yes. Let the proxy own HTTPS and renewal, disable HTTPS and built-in ACME in the web container, and configure a protected HTTP upstream with the required signaling routes. Certificate checks must target the public proxy endpoint.

Can Let's Encrypt issue a certificate for an IP address?

Yes. Let's Encrypt offers short-lived IP address certificates. That does not establish support in Jitsi's built-in hostname recipe. This guide covers a DNS hostname; IP-only Jitsi issuance, renewal and client compatibility have not been verified here.

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