trinary systems

Setting up a Tuwunel server with Caddy on Debian

I recently set up a Tuwunel server for myself, and...in my opinion the documentation needs a little bit of work. So, here's the steps I took to set Tuwunel up myself, along with the Caddy webserver as a reverse proxy.

After following this tutorial, you will have Caddy set up to serve a static website on your main domain (i.e. your.domain), and Tuwunel set up delegated to a subdomain (i.e. connecting to matrix.your.domain - with your usernames apperaing as @username:your.domain).

This tutorial assumes you are running Debian, and have ports 80, 443, and 8448 open in your firewall (and port forwarded if you're running on your home connection), and you have a registered domain name pointed to your server's IP address. Replace all instances of "your.domain" with your domain name.

Install and set up Caddy

Commands shamelessly copied from https://caddyserver.com/docs/install#debian-ubuntu-raspbian:

sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https curl
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list
sudo chmod o+r /usr/share/keyrings/caddy-stable-archive-keyring.gpg
sudo chmod o+r /etc/apt/sources.list.d/caddy-stable.list
sudo apt update
sudo apt install caddy

Caddy should start itself once it's installed. Visit http://your.domain/ and you should get Caddy's default page.

Now let's follow the instructions on that page to be able to serve our own webpage:

your.domain {
    # Set this path to your site's directory
    root * /var/www/html

    # Enable the static file server
    file_server
}

Next, reload Caddy's configuration with sudo systemctl reload caddy.

You should now be able to visit https://your.domain/ with a fresh, fancy SSL certificate automatically set up with Caddy! (ngl, the automatic SSL certs and easy reverse proxying are why I chose Caddy over Nginx)

Install Tuwunel

Visit https://github.com/matrix-construct/tuwunel/releases and download the latest .deb release for your architecture. Throw it into like, your home folder on your server or something. Install the .deb with sudo dpkg -i <path-to-tuwunel-deb>.deb.

Configure Tuwunel

Tuwunel's config file is located at /etc/tuwunel/tuwunel.toml. You will probably open this file and then scream at how long it is. Don't worry, you really don't need to edit much of it, the defaults are mostly fine.

Find server_name and set it to "your.domain". DO NOT INCLUDE matrix. IN THIS. This is the name that will be in your user identifiers, i.e. @username:your.domain - we'll make the server accessible via matrix.your.domain later.

If you don't want cringy little 💕s at the end of the name of every user who registers by default, change new_user_displayname_suffix to just "".

Next we'll enable registration. Find allow_registration and set it to true. Next, generate a random string (like a password), and set registration_token to that string. Anyone who registers on the server will need this token in order to register.

Now find [global.well_known] and uncomment it, along with the client and server keys below it. Set client to "https://matrix.your.domain" and server to "matrix.your.domain:443".

Save the config and now you can start Tuwunel!

Start Tuwunel

Start Tuwunel's systemd service with sudo systemctl start tuwunel.

But wait, we can't actually access it yet! We need to configure the reverse proxy.

Configure Caddy Reverse Proxy

Go back to your Caddyfile (/etc/caddy/Caddyfile). We'll add a new block for matrix.your.domain, and add a block into your.domain's config to delegate to matrix.your.domain through .well-known files.

First, within your.domain {}, add:

reverse_proxy /.well-known/matrix* https://matrix.your.domain {
    header_up Host {upstream_hostport}
}

Remember the [global.well_known] keys we edited earlier? This will forward requests to https://your.domain/.well-known/matrix/client and https://your.domain/.well-known/matrix/server to Tuwunel. These files tell Matrix clients and other servers where to actually find your Tuwunel server, which is actually at matrix.your.domain.

Now we'll add a block to reverse proxy matrix.your.domain to Tuwunel:

matrix.your.domain, matrix.your.domain:8448 {
        reverse_proxy localhost:8008
}

So, overall your Caddyfile should look something like this:

your.domain {
    # Set this path to your site's directory
    root * /var/www/html

    # Enable the static file server
    file_server

    # Matrix .well-known reverse proxy
    reverse_proxy /.well-known/matrix* https://matrix.your.domain {
        header_up Host {upstream_hostport}
    }
}

# Matrix tuwunel
matrix.your.domain, matrix.your.domain:8448 {
        reverse_proxy localhost:8008
}

Save the config, and sudo systemctl reload caddy again.

If you try to visit https://matrix.your.domain/ again, you should now see Tuwunel's lowkey kinda cringy "hewwo from tuwunel woof!" message!

Connect to your server!

You should now be able to open any Matrix client like Element (personally I like Cinny), and enter matrix.your.domain OR just your.domain as your homeserver, and register an account. You'll need that registration_token you set earlier. The first account registered on the server is automatically made an admin and will automatically join Tuwunel's admin room, allowing you to administer your server.

Enjoy!