Run Mattermost and Jitsi behind one HTTPS proxy

Short answer

Use chat.example.com for Mattermost and meet.example.com for Jitsi, both pointing to the same server. Let a host-installed Caddy own ports 80 and 443 and manage HTTPS. Bind Mattermost to 127.0.0.1:8065 and Jitsi web to 127.0.0.1:8000. Jitsi media still needs direct UDP 10000 access. One proxy can manage both certificates; copying certificate files between the apps is unnecessary.

This guide is for administrators connecting two existing Docker deployments on one Ubuntu or Debian server, including a DigitalOcean Droplet. The result is two HTTPS hostnames with one certificate manager. Mattermost’s database and Jitsi’s internal services remain in their own Compose projects.

Before changing the proxy

  • Have a working Mattermost Docker installation, its database and persistent volumes, following the official container deployment guide. [S1]
  • Have a working Jitsi installation with generated internal passwords. Use matching Compose files and image tags. The example below uses docker-jitsi-meet stable-11248, released September 14, 2026. Its web container uses internal HTTP port 8000. [S2]
  • Use Docker Compose 2.24.4 or newer: the port replacement below uses !override. [S3]
  • Install Caddy on the host using its official package instructions. The paths and service commands below assume that package. [S4]
  • Back up both .env files, Compose overrides and the existing proxy configuration. Schedule a maintenance window when moving an existing service off ports 80/443.

Choose VM resources for Mattermost, PostgreSQL and Jitsi together, including concurrent meetings. A Jitsi-only sizing recommendation is not a capacity estimate for the combined server.

Use these placeholders throughout:

Placeholder Replace with
chat.example.com Your Mattermost hostname
meet.example.com Your Jitsi hostname
203.0.113.10 The Droplet’s reachable public IP, not its private VPC IP
/opt/mattermost Your existing Mattermost Compose directory
/opt/jitsi-meet Your existing Jitsi Compose directory

1. Give each app its own hostname

Point both DNS A records to the server’s public IPv4 address. Only publish AAAA records if IPv6 also reaches the correct server. Caddy’s automatic HTTPS needs reachable domains and certificate-validation traffic. [S5]

In the DigitalOcean Cloud Firewall and the host firewall, permit TCP 80/443 for HTTPS and certificate validation, and UDP 10000 for Jitsi media. Restrict SSH to the administrators who need it. Keep the database and HTTP backends private. Cloud Firewall rules and the host firewall both need to agree. [S6][S2]

The traffic paths will be:

Text
chat.example.com -> Caddy on the host -> 127.0.0.1:8065 -> Mattermost
meet.example.com -> Caddy on the host -> 127.0.0.1:8000 -> Jitsi web
Jitsi media     -> public IP, UDP 10000               -> Jitsi Videobridge

2. Bind Mattermost’s HTTP backend to loopback

In the existing Mattermost .env, set its public URL:

dotenv
DOMAIN=chat.example.com
MM_SERVICESETTINGS_SITEURL=https://chat.example.com

Keep the existing database credentials and image version. The official Mattermost base Compose file includes the application and PostgreSQL, and passes MM_SERVICESETTINGS_SITEURL to the application. [S7]

Save this as /opt/mattermost/compose.proxy.yml:

YAML
services:
  mattermost:
    ports: !override
      - "127.0.0.1:8065:8065"

Run the base file with this override:

Terminal
cd /opt/mattermost
docker compose -f docker-compose.yml -f compose.proxy.yml config --quiet
docker compose -f docker-compose.yml -f compose.proxy.yml up -d
curl -I http://127.0.0.1:8065/

Use this same file list for subsequent up, ps and logs commands. This replaces the bundled Nginx or without-Nginx file list for the proxy arrangement shown here. If a previous Nginx container still owns 80/443, stop that specific proxy in the maintenance window; preserve application and database volumes. The official Mattermost proxy guide recommends restricting port 8065 to the proxy. [S1][S8]

This example serves Mattermost chat and the Jitsi integration. Mattermost’s separate Calls feature has its own media-network requirements; enabling it needs additional configuration.

3. Put Jitsi web behind the same host proxy

In Jitsi’s existing .env, use:

dotenv
JITSI_IMAGE_VERSION=stable-11248
PUBLIC_URL=https://meet.example.com
HTTP_PORT=8000
DISABLE_HTTPS=1
ENABLE_LETSENCRYPT=0
ENABLE_HTTP_REDIRECT=0
JVB_ADVERTISE_IPS=203.0.113.10

Use these values with the Compose file from the same Jitsi release. If your installation is on an older release, follow the upgrade guide first; changing the image tag alone is not an upgrade procedure. Preserve generated internal passwords. [S2]

Save /opt/jitsi-meet/compose.proxy.yml:

YAML
services:
  web:
    ports: !override
      - "127.0.0.1:8000:8000"

!override replaces the base web port list instead of adding another binding. The videobridge’s UDP port remains in the base file. The Jitsi handbook documents disabling internal HTTPS behind a same-host proxy and keeping web ports off public interfaces. [S3][S9]

Terminal
cd /opt/jitsi-meet
docker compose -f docker-compose.yml -f compose.proxy.yml config --quiet
docker compose -f docker-compose.yml -f compose.proxy.yml up -d
curl -I http://127.0.0.1:8000/

For a fresh Jitsi setup, complete the Docker installation prerequisites before applying this proxy arrangement.

4. Let Caddy manage HTTPS for both domains

Merge these site blocks into /etc/caddy/Caddyfile, preserving any other sites the proxy serves:

Text
chat.example.com {
    reverse_proxy 127.0.0.1:8065
}

meet.example.com {
    reverse_proxy 127.0.0.1:8000
}

Caddy’s reverse_proxy supports WebSocket upgrades, including Mattermost’s WebSocket endpoint and Jitsi’s /xmpp-websocket route. Automatic HTTPS manages certificates for the configured hostnames and HTTP-to-HTTPS redirects. You do not need to mount either app’s certificate files into the other. [S5][S10]

Terminal
sudo caddy validate --config /etc/caddy/Caddyfile --adapter caddyfile
sudo systemctl enable --now caddy
sudo systemctl reload caddy
sudo journalctl -u caddy --since "10 minutes ago" --no-pager

Use Caddy’s packaged service for this arrangement. Reload during the maintenance window: existing WebSocket connections can close on a configuration reload. Review the certificate and upstream messages in the service log. [S4][S10][S11]

A certificate must cover every hostname using it. Sharing one certificate file would require coverage for both names and a coordinated renewal process. One proxy managing the hostnames is sufficient; this example does not require a shared wildcard certificate. [S5]

5. Connect the Mattermost Jitsi plugin

Install the community Jitsi plugin from its official repository, then configure its Jitsi server URL as https://meet.example.com. Follow the Mattermost integration settings for plugin options. [S12]

HTTPS is transport protection. Decide separately who can create rooms and join them. If your Jitsi server requires JWT, configure the plugin’s app ID and secret to match that server and verify room access. See Jitsi JWT authentication. Keep signing secrets out of browser code and support screenshots.

Verify web, signaling and media separately

  1. Open both HTTPS URLs. Check that the certificate matches each hostname, Mattermost loads its login page and Jitsi loads its preview.
  2. Sign in to Mattermost and check its browser Network panel for the WebSocket connection. A successful upgrade uses HTTP 101. [S8]
  3. Start a Jitsi meeting from the plugin. Check /xmpp-websocket for a successful WebSocket connection, or the configured BOSH signaling flow if WebSockets are intentionally disabled. [S9]
  4. Run a three-person meeting, including a guest on a different network. Check two-way audio, video and screen sharing. Successful HTTPS alone does not validate videobridge connectivity. [S2]
  5. Test the chosen password, lobby or token rules with a separate guest session. Save sanitized results and recheck after upgrades.

These are verification steps for your deployment. Our publication checks validate the example configuration syntax, not a live Mattermost/Jitsi meeting or a load test.

Troubleshooting and rollback

Symptom Next check
Proxy cannot bind 80/443 Identify the old proxy or container still publishing those ports before starting Caddy.
Caddy returns 502 Test the corresponding loopback URL and check the application’s Compose logs using the same file list.
Certificate issuance fails Check DNS, any published AAAA record and firewall access, then read Caddy’s certificate error. [S5]
Chat loads but real-time updates fail Check Mattermost’s public Site URL and WebSocket connection. [S8]
Jitsi disconnects before joining Check signaling with the disconnection checklist.
Two-person calls work but larger calls fail Check the advertised public IP, UDP path and videobridge troubleshooting.
Caddy is in Docker and localhost fails This example runs Caddy on the host. A container proxy needs reachable service names on shared Docker networks.

If a proxy migration fails, restore the saved proxy configuration, .env files and previous Compose file lists, then re-create the affected services in the maintenance window. Preserve database and application volumes. Review this guide when Jitsi’s internal ports, Mattermost’s Compose layout or Caddy’s proxy behavior changes.

Sources and scope

Researched October 13, 2026. This is a configuration guide for existing deployments. Jitsi examples are pinned to stable-11248; Mattermost’s Docker layout was checked at commit 497414659ee7127677d2b91b44bb4f3ea9d14695. Keep your own application versions pinned and supported. It is not an assertion of a tested production integration or capacity guarantee.

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

Can Mattermost and Jitsi share an SSL certificate?

A certificate must cover each hostname using it. A single proxy can manage HTTPS for both apps, so they do not need copies of each other's certificate files. In this example Caddy manages certificates for chat.example.com and meet.example.com.

Why does localhost fail when Caddy is in Docker?

Inside a Caddy container, 127.0.0.1 is that container, not the host or another container. This guide runs Caddy on the host. A container-based proxy needs a shared Docker network and service names instead.

Does HTTPS make Jitsi audio and video work?

HTTPS covers the web app and signaling. The videobridge also needs its advertised public IP and direct media connectivity, normally UDP 10000. Test a three-person meeting after setting up HTTPS.

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