Files
tuwunel/docs/deploying/root-domain-delegation.md
André Lametti 505b331534 Docs: add example for root domain delegation
- Change link in README to internal documentation link; original more
  detailed link is preserved in documentation page as a reference.
- Add Caddy example.

TODO:
- [x] Add example for Caddy
- [ ] Add example for Traefik
2026-03-04 16:06:02 -05:00

5.8 KiB

Example: using the root domain as the homeserver name

<= Back to Generic Deployment Guide

It is possible to host tuwunel on a subdomain such as matrix.example.com but delegate from example.com as the server name. This means that usernames will be @user:example.com rather than @user:matrix.example.com.

Federating servers and clients accessing tuwunel at example.com will attempt to discover the subdomain by accessing the example.com/.well-known/matrix/client and example.com/.well-known/matrix/server endpoints. These need to be set up to point back to matrix.example.com.

Note

In all of the following examples, replace matrix.example.com with the subdomain where tuwunel is hosted, <PORT> with the external port for federation, and example.com with the domain you want to use as the public-facing homeserver.

Configuration

Make sure the following are set in your configuration file or via environment variables:

  1. Server name: set TUWUNEL_SERVER_NAME=example.com or in the configuration file:
    [global]
    ~
    ~# The server_name is the pretty name of this server. It is used as a
    ~# suffix for user and room IDs/aliases.
    ~#
    ~# See the docs for reverse proxying and delegation:
    ~# https://tuwunel.chat/deploying/generic.html#setting-up-the-reverse-proxy
    ~#
    ~# Also see the `[global.well_known]` config section at the very bottom.
    ~#
    ~# Examples of delegation:
    ~# - https://matrix.org/.well-known/matrix/server
    ~# - https://matrix.org/.well-known/matrix/client
    ~#
    ~# YOU NEED TO EDIT THIS. THIS CANNOT BE CHANGED AFTER WITHOUT A DATABASE
    ~# WIPE.
    ~#
    ~# example: "girlboss.ceo"
    ~#
    server_name = example.com
    
  2. Client-server URL: set TUWUNEL_WELL_KNOWN__CLIENT=https://matrix.example.com or in the configuration file:
    [global.well_known]
    ~
    ~# The server URL that the client well-known file will serve. This should
    ~# not contain a port, and should just be a valid HTTPS URL.
    ~#
    ~# example: "https://matrix.example.com"
    ~#
    client = https://matrix.example.com
    
  3. Server-server federation domain and port: where <PORT> is the external port for federation (default 8448, but often 443 when reverse proxying), set TUWUNEL_WELL_KNOWN__SERVER=matrix.example.com:<PORT> or in the configuration file:
    [global.well_known]
    ~
    ~# The server URL that the client well-known file will serve. This should
    ~# not contain a port, and should just be a valid HTTPS URL.
    ~#
    ~# example: "https://matrix.example.com"
    ~#
    ~client = https://matrix.example.com
    ~
    ~# The server base domain of the URL with a specific port that the server
    ~# well-known file will serve. This should contain a port at the end, and
    ~# should not be a URL.
    ~#
    ~# example: "matrix.example.com:443"
    ~#
    server = matrix.example.com:<PORT> # e.g. matrix.example.com:443
    

Serving .well-known endpoints

With the above configuration, tuwunel will generate and serve the appropriate /.well-known/matrix entries for delegation, so these can be served by reverse proxying /.well-known/matrix on example.com to tuwunel. Alternatively, if example.com is not behind a reverse proxy, static JSON files can be served directly.

Option 1: Static JSON files

At a minimum, the following JSON files should be created:

  1. At example.com/.well-known/matrix/client:
    {
        "m.homeserver": {
            "base_url": "https://matrix.example.com/"
        }
    }
    
  2. At example.com/.well-known/matrix/server (substituting <PORT> as above):
    {
        "m.server": "matrix.example.com:<PORT>" // e.g. "matrix.example.com:443"
    }
    

Option 2: Reverse proxy

These are example configurations if example.com is reverse-proxied behing Nginx or Caddy.

Note

Replace tuwunel with the URL where tuwunel is listening; this may look like 127.0.0.1:8008, matrix.example.com, or tuwunel if you declared an upstream tuwunel block.

Important

These configurations need to be applied to the reverse proxy for example.com, not matrix.example.com.

Caddy

example.com {
	reverse_proxy /.well-known/matrix/* https://matrix.example.com {
		header_up Host {upstream_hostport}
	}
}

Nginx

server {
  ~listen 443 ssl http2;
  ~listen [::]:443 ssl http2;
  server_name example.com;

  location /.well-known/matrix {
    proxy_pass http://tuwunel/.well-known/matrix;
    proxy_set_header X-Forwarded-For $remote_addr;
    proxy_ssl_server_name on;
  }
  ~
  ~# The remainder of your nginx configuration for example.com including SSL termination, other locations, etc.
}

Testing

Navigate to example.com/.well-known/matrix/client and example.com/.well-known/matrix/server. These should display results similar to the JSON snippets above.

Entering example.com in the Matrix federation tester should also work.

Additional resources

For a more complete guide, see the Matrix setup with Ansible and Docker documentation on setting up .well-known.