Conduwuit
Conduwuit is a Matrix server written in RUST. Matrix is an open network for secure, decentralised communication. It is a specification which is in turn implemented by many servers and clients, and you can self-host your server as well. This is a new, well supported, lightweight implementation of a Matrix server.
I will show you also how to install Element Web app which is a nice companion for web access everywhere.
Installation of Conduwuit server
Installation instructions: here. While there is a docker approach, it is so simple to install on bare-metal that i preferred this approach to the container one. Actuall accessing the conduwuit command-line admin console is a pain with container, while it's so easy from the prebuilt-binary.
Create user and required folders:
seradd -d /data/daemons/conduwuit conduwuit mkdir -p /data/conduwuit/db /var/log/conduwuit chown conduwuit:conduwuit /data/conduwuit /var/log/conduwuit -R
Download the correct executable from GitHUB releases page. You should pick the one for your architecture. For example, for Linux 64bit would be static-x86_64-unknown-linux-musl:
su - conduwuit mkdir bin cd bin wget https://github.com/girlbossceo/conduwuit/releases/download/<< version >>/static-x86_64-unknown-linux-musl
Installation of Element Web app
Element Web app is a great web based UI for Matrix, that you can pair to your instance.
Again installing bare-metal is the way to go. See here.
Download latest release tarball from here and decompress it:
su - conduwuit wget https://github.com/element-hq/element-web/releases/<< version >> /element-<< version >>.tar.gz tar xvf element-<< version >>.tar.gz ln -s element-<< version >> element-web
Configuration of Conduwuit server
The official Conduwuit configuration documentation can be found here.
Now, you cannot start Conduwuit withour a proper configuration file. I suggest you to put it under /data/conduwuit/conduwuit.toml, and here is an example to start from:
[global] server_name = "chat.mydomain.com" address = ["127.0.0.1", "::1"] port = 6167 database_path = "/data/conduwuit/db" new_user_displayname_suffix = "-|" allow_check_for_updates = false max_request_size = 20971520 # this should match NGINX max request size #log = "info" #log_colors = true #emergency_password = "" [global.well_known] client = "https://chat.mydomain.com" server = "chat.mydomain.com:443"
You are now ready for testing your installation.
Configuration of Element Web App
Rename the file called config.sample.json to config.json inside the element-« version » folder and edit accordingly, and to be sure to backup it properly, i suggest to move it to /data/conduwuit:
cd /data/daemons/conduwuit/element-web cp config.sample.json /data/conduwuit/element-config.json ln -s /data/conduwuit/element-config.json config.json
At the very least perform the following edits:
"default_server_config": { "m.homeserver": { "base_url": "https://chat.gardiol.org", "server_name": "chat.gardiol.org" }, "disable_custom_urls": true, "disable_guests": true,
at the beginning of the file. I suggest to disable both custom URLs and guests, to avoid your web instance to be used too openly. Please note that this does not mean that your instance will be used: Element X is a javascript app that works in the browser of the use anyway.
Manual startup
to run Conduwuit server, run the following command as conduwuit user:
/data/daemons/bin/static-x86_64-unknown-linux-musl -c /data/conduwuit/conduwuit.toml
Of course, replace the proper paths and filenames with your setup.
Running manually is good because you can easily access the admin console by typing CTRL+C from the terminal. You might want to take this opportunity to create your first user, and make it an admin too.
Testing
Call directly this endpoint:
curl https://chat.mydomain.com/_conduwuit/server_version {"name":"Conduwuit","version":"0.5.0 (e5049ca)"}
Check federation and Matrix operability, open the following URL:
https://federationtester.matrix.org/#chat.mydomain.com
Reverse proxy
A Matrix server must be hosted on a dedicated subdomain. Please see my NGINX reverse proxy page for more information about the followint configuration.
- chat.conf
server { server_name chat.mydomain.com; listen 8443 ssl; # external access listen 443 ssl; # internal access access_log /var/log/nginx/chat.mydomain.com_access_log main; error_log /var/log/nginx/chat.mydomain.com_error_log info; location / { root /data/daemons/conduwuit/element-web; } location ~ ^(/_matrix|/_synapse/client) { add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS, PATCH, HEAD'; proxy_pass http://127.0.0.1:6167; #proxy_pass http://127.0.0.1:6167$request_uri; proxy_set_header X-Forwarded-For $remote_addr; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header Host $host; proxy_buffering off; client_max_body_size 30M; proxy_read_timeout 10m; proxy_http_version 1.1; } location /.well-known/matrix/server { return 200 '{"m.server": "chat.mydomain.com:443"}'; types { } default_type "application/json; charset=utf-8"; } location /.well-known/matrix/client { return 200 '{"m.homeserver": {"base_url": "https://chat.mydomain.com"},"org.matrix.msc3575.proxy": {"url": "https://chat.mydomain.com"}}'; types { } default_type "application/json; charset=utf-8"; add_header "Access-Control-Allow-Origin" *; } }
Adding users
From the Contuwuit admin console, which can be accessed by running the conduwuit binary in a terminal then hit CTRL+C, you can do a lot of admin stuff, including creating new users.
To create a user:
uwu> admin users create-user myuser mypassword
To make a user an admin:
uwu> admin users make-user-admin myuser
To change a user password:
uwu> admin users reset-password myuser mynewpassword
You must create at least one user and make it admin!
You can run any admin command later on directly in your favorite Matrix client in the admin chat. You might need the terminal only if you accidentally lock your user out of the instance.
Autostart
Since i use OpenRC, simply drop the following script to /etc/init.d:
- /etc/init.d/conduwuit
#!/sbin/openrc-run # Copyright 2025 Gentoo Authors # Distributed under the terms of the GNU General Public License v2 name="conduwuit daemon" description="Conduwuit Matrix server" pidfile="/run/conduwuit.pid" command_background=true command="/data/daemons/conduwuit/bin/static-x86_64-linux-musl" command_args="-c /data/conduwuit/conduwuit.toml" command_user="conduwuit:conduwuit" output_log="/var/log/conduwuit/conduwuit.log" output_err="/var/log/conduwuit/conduwuit.log" depend() { need net }
Make it executable and add to the proper runlevel:
chmod +x /etc/init.d/conduwuit rc-update add conduwuit default
If you use the telegram bridge described below, also add the following:
- /etc/init.d/conduwuit-telegram
#!/sbin/openrc-run # Copyright 2025 Gentoo Authors # Distributed under the terms of the GNU General Public License v2 name="conduwuit telegram bridge" description="Conduwuit Telegram Matrix Bridge" pidfile="/run/conduwuit-telegram.pid" command_background=true command="/data/daemons/conduwuit/mautrix-telegram/bin/python" command_args="/data/conduwuit/mautrix-telegram-config.yaml -m mautrix_telegram" command_user="conduwuit:conduwuit" output_log="/var/log/conduwuit/conduwuit-telegram.log" output_err="/var/log/conduwuit/conduwuit-telegram.log" start_pre() { cd /data/daemons/conduwuit/mautrix-telegram } depend() { need net }
Make it executable and add to the proper runlevel:
chmod +x /etc/init.d/conduwuit-telegram rc-update add conduwuit-telegram default
If you use the Whatsapp bridge described below, also add the following:
- /etc/init.d/conduwuit-whatsapp
#!/sbin/openrc-run # Copyright 2025 Gentoo Authors # Distributed under the terms of the GNU General Public License v2 name="conduwuit whatsapp bridge" description="Conduwuit whatsapp Matrix Bridge" pidfile="/run/conduwuit-whatsapp.pid" command_background=true command="/data/daemons/conduwuit/mautrix-whatsapp/mautrix-whatsapp" command_args="/data/conduwuit/mautrix-whatsapp-config.yaml" command_user="conduwuit:conduwuit" output_log="/var/log/conduwuit/conduwuit-whatsapp.log" output_err="/var/log/conduwuit/conduwuit-whatsapp.log" start_pre() { cd /data/daemons/conduwuit/mautrix-whatsapp } depend() { need net }
Make it executable and add to the proper runlevel:
chmod +x /etc/init.d/conduwuit-whatsapp rc-update add conduwuit-whatsapp default
Installing the Telegram Bridge
The Mautrix Telegram bridge is currently the best (only?) option. More info here.
Create subfolder and Python venv inside (see PIP):
su - conduwuit mkdir mautrix-telegram cd mautrix-telegram # Enable PIP like in the link above # - create ~/.config/pip/pip.conf # - add ~/.local/bin to the .bashrc python -m venv . # Note the dot at the end! source ./bin/activate # Now flip include-system-site-packages = true in pyvenv.cfg # Install: pip install --upgrade mautrix-telegram[all]
You need to create API keys to connect to Telegram. Go to this page and Grab the example config file here, save it as config.yaml in the /data/conduwuit/ folder and create a link to the mautrix-telegram folder and customize it to your needs:
wget -O /data/conduwuit/mautrix-telegram-config.yaml mv /data/daemons/conduwuit/mautrix-telegram/config.yaml /data/conduwuit/mautrix-telegram-config.yaml
This file is huge, here are the most relevant changes needed:
- config.yaml
address: https://chat.mydomain.com domain: chat.mydomain.com verify_ssl: true database: sqlite:/data/conduwuit/mautrix-telegram.db # place the database into the /data/conduwuit folder telegram: # Get your own API keys at https://my.telegram.org/apps api_id: << put your id here >> api_hash: << put your hash >> # (Optional) Create your own bot at https://t.me/BotFather bot_token: disabled permissions: "*": "relaybot" # non-local users can only see messages "chat.mydomain.com": "full" # full access to all local users "@myself:chat.mydomain.com": "admin" # who can admin the bot
More details on configuration can be found here.
I choose to use SQLite as database because i only have a few users and don't want to spin a PostreSQL instance for that.
At this point you need to register the bridge:
python -m mautrix_telegram -g -c /data/conduwuit/mautrix-telegram-config.yaml
This step will create a registration.yaml file that you need to perform the registration of the bridge as an appservice in Conduwuit. Conduwuit is different from Synapse (the most common Matrix server) because the appservice must be registered from the admin chat with the following command:
!admin appservices register << shift+enter >> ``` << shift+enter >> [ ... copy here the content of registration.yaml ... ] ``` << enter >>
When you see « shift enter » you need to press those two keys in order to create a new line in the same command. The three ``` (backthicks) are the markdown token to create a code block. The « autogenrated » are secret strings found in the registration.yaml file.
The chat should reply with a message like:
Appservice registered with ID: telegram
More details on registering the appservice can be found here.
You need to create the telegrambot user, again from the admin chat:
!admin users create-user telegrambot
Good! Now you can run the bridge:
python -m mautrix_telegram -c /data/conduwuit/mautrix-telegram-config.yaml
If all is well, your bridge should be up and running now.
To login into telegram you need to:
- Start a chat with telegrambot:chat.mydomain.com
- type “login”
- when prompted, type your telegram registered phone number with country code
- when prompted, type the code you received in telegram to authorize the login
- when prompted, type your 2FA password (if enabled in telegram)
You will start seeing your telegram chats appear in Matrix now! It takes time, even hours, and also most chats will only appear the first time the other person messages you.
Note: Telegram does not allow registration from third party clients, so to register a new telegram account, you must use Telegram official app.
General documentation on the Telegram bot can be found here.
To manage animated sticker here
Installing the Telegram Bridge
Work In Progress
su - conduwuit mkdir mautrix-whatsapp cd mautrix-whatsapp wget -O mautrix-whatsapp.zip 'https://mau.dev/mautrix/whatsapp/-/jobs/artifacts/main/download?job=build%20amd64' unzip mautrix-whatsapp.zip
Generate config and edit:
./mautrix-whatsapp -e mv config.yaml /data/conduwuit/mautrix-whatsapp-config.yaml
edit it…
network: displayname_template: "{{or .FullName .BusinessName .PushName .Phone}} (WA)" # This is very important to have usernames instead of phone numbers! database: type: sqlite3-fk-wal uri: file:/data/conduwuit/mautrix-whatsapp.db?_txlock=immediate homeserver: address: https://chat.mydomain.com domain: chat.mydomain.com permissions: # this is probably not needed, but anyway... "*": "relaybot" # non-local users can only see messages "chat.mydomain.com": "full" # full access to all local users "@myself:chat.mydomain.com": "admin" # who can admin the bot backfill: enabled: true # to populate chats with older messages
Note that backfill is disabled by default, you need to enable it to see older messages. Also note that messages cannot be backfilled for already created rooms, so don't forget to enable backfill before the first start!
Generate the appservice files:
./mautrix-whatsapp -c /data/conduwuit/mautrix-whatsapp-config.yaml -g
This step will create a registration.yaml file that you need to perform the registration of the bridge as an appservice in Conduwuit. Conduwuit is different from Synapse (the most common Matrix server) because the appservice must be registered from the admin chat with the following command:
!admin appservices register << shift+enter >> ``` << shift+enter >> id: whatsapp [ ... copy the content of the appservice.yaml .. ] ``` << enter >>
When you see « shift enter » you need to press those two keys in order to create a new line in the same command. The three ``` (backthicks) are the markdown token to create a code block.
The chat should reply with a message like:
Appservice registered with ID: whatsapp
More details on registering the appservice can be found here.
The whatsappbot user should have been created automatically.
Good! Now you can run the bridge:
/data/daemon/mautrix-whatsapp/mautrix-whatsapp -c /data/conduwuit/mautrix-whatsapp-config.yaml
If all is well, your bridge should be up and running now.
To login into whatsapp you need to:
- Start a chat with whatsappbot:chat.mydomain.com
- type “login qr”
- Scan the QR code with your whatsapp on your phone.
You could install whatsapp on a Android Virtual Emulator, but it's discouraged and could lead to a ban of your account.
Note: if your usernames do not get popupated, you should do a search username in the whatsappbot chat.