Hosting your own Chat Relay
+Chat relays are used to deliver channel messages in SimpleX Network. Read more about channels in this whitepaper and this blog post.
+A chat relay is the SimpleX Chat CLI (simplex-chat) running in relay mode (--relay). It has its own profile (a display name and a picture), its own address, and in addition to delivering messages, it can generate data for web previews of the channels it delivers.
This guide explains how to set up a chat relay on a Linux server, how to run it, and (optionally) how to configure Caddy to serve data for channel web previews.
+++Please note: This guide applies only to SimpleX Chat v7.0.0-beta.4 and later.
+
Table of Contents
+-
+
- Install the CLI +
- Run the relay + + +
- Channel web previews + + +
Install the CLI
+The relay is the standard simplex-chat CLI binary. Install or update it with the install script:
curl -o- https://raw.githubusercontent.com/simplex-chat/simplex-chat/stable/install.sh | bash
+
+Other options (manual binary download, building from source) are in the CLI guide.
+Copy the installed simplex-chat binary to /usr/local/bin/simplex-chat-relay. The guide uses that name so the relay is separate from any interactive simplex-chat you also run on the server.
Create a dedicated user for the relay (called relay below), so it does not run as root and keeps its database in one place:
sudo useradd -m relay
+
+The useradd -m flag creates its home directory /home/relay, where the guide keeps the database and picture. Run the relay commands (the -e commands below) as this user, for example with sudo -u relay ...; run the systemd and Caddy steps as root.
Run the relay
+Run the relay as a systemd service. With --headless it starts without any interactive prompts. It creates its profile and address on the first start, and writes its output to the journal.
Create a run script /usr/local/bin/relay-run:
#!/bin/sh
+exec /usr/local/bin/simplex-chat-relay \
+ --relay \
+ --headless \
+ --user-display-name "My Relay" \
+ --user-image-file /home/relay/avatar.png \
+ -d /home/relay/relay
+
+chmod +x /usr/local/bin/relay-run
+
+Create /etc/systemd/system/simplex-relay.service:
[Unit]
+Description=SimpleX Chat relay
+After=network.target
+
+[Service]
+User=relay
+ExecStart=/usr/local/bin/relay-run
+Restart=always
+StandardInput=null
+
+[Install]
+WantedBy=multi-user.target
+
+Enable and start it:
+systemctl daemon-reload
+systemctl enable --now simplex-relay
+
+The first start creates the relay profile (with the given name and picture) and its address; later starts reuse them. Both are written to the journal:
+Current user: My Relay
+Chat relay address is created:
+https://smp4.simplex.im/r#73iEnnvCqPTVGArCAWUcRaj5hxRb7TbPCSZ2JY2VjCQ
+
+Relay options
+| Option | +Purpose | +
|---|---|
--relay |
+Run as a chat relay. Required. | +
--headless |
+Don't ask interactive questions; create the profile and address automatically. On first start it also needs --user-display-name. |
+
--user-display-name NAME |
+The relay's display name. Creates the profile on first start; on later starts it must match the existing profile. | +
--user-image-file FILE |
+The relay's picture, from a .png, .jpg or .jpeg file. Applied only when the profile is created; ignored afterwards. |
+
--relay-address-server SERVER |
+Create the relay address on a specific SMP server, e.g. smp://<fingerprint>@smp.example.com. By default a preset server is used. Requires --relay. |
+
Get the relay address
+The address is created and logged on the first start. Read it from the journal at any time:
+journalctl -u simplex-relay | grep -A1 "address is created"
+
+Run relay commands
+The service runs headless, so there is no attached terminal to type into. To run a one-off command, stop the service, run the command against the relay's database with -e, then start it again. For example, to change the picture (--user-image-file only sets it when the profile is first created):
systemctl stop simplex-relay
+simplex-chat-relay -d /home/relay/relay -e "/set profile image file /home/relay/new-avatar.png"
+systemctl start simplex-relay
+
+Channel web previews
+Chat relays can render recent messages of its public channels as JSON files, which can be served over HTTPS using a web server to create channel web previews. This is optional.
+Relay web options
+Add these to the run script (--relay-web-domain and --relay-web-dir must be given together):
--relay-web-domain relay.example.com \
+ --relay-web-dir /var/www/relay-web-channels/channel \
+ --relay-web-cors-file /var/www/relay-web-channels/cors.conf \
+ --relay-web-interval 30 \
+
+| Option | +Purpose | +
|---|---|
--relay-web-domain DOMAIN |
+Domain the previews are served from. | +
--relay-web-dir DIR |
+Directory the relay writes channel JSON files to. | +
--relay-web-cors-file FILE |
+File the relay writes the generated Caddy CORS config to. | +
--relay-web-interval SECONDS |
+How often previews are regenerated (default 300). |
+
--relay-web-item-count COUNT |
+Recent messages per channel preview (default 50). |
+
Create the web directory, owned by the relay user:
+mkdir -p /var/www/relay-web-channels/channel
+chmod 0755 /var/www/relay-web-channels
+chown -R relay:relay /var/www/relay-web-channels
+
+Restart the relay so the new flags take effect:
+systemctl restart simplex-relay
+
+Serve the previews with Caddy
+This section uses Caddy as the web server. Install it (Debian/Ubuntu):
+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 apt update && sudo apt install caddy
+
+The relay writes files to /var/www/relay-web-channels/channel/<id>.json. Serve them, and import the relay's generated CORS rules, in your Caddyfile:
relay.example.com {
+ encode zstd gzip
+
+ handle /channel/* {
+ root * /var/www/relay-web-channels # files resolve to .../channel/<id>.json
+ file_server
+ import /etc/caddy/simplex-cors.conf
+ }
+}
+
+Keep root at the parent directory with a non-stripping handle. That is what makes /channel/<id>.json resolve to .../channel/<id>.json. Do not point root at the channel subdirectory: the relay's generated CORS matchers are /channel/*.json, which only match when the prefix is kept.
touch /etc/caddy/simplex-cors.conf # so the import doesn't fail before the first write
+usermod -aG relay caddy # let caddy read the relay user's files
+systemctl restart caddy # restart (not reload) to pick up the group
+
+Reload CORS automatically
+The relay updates its CORS file as channels change. Copy it into Caddy's config and reload Caddy whenever it changes.
+Create /usr/local/bin/simplex-cors-sync.sh:
#!/bin/sh
+set -eu
+SRC=/var/www/relay-web-channels/cors.conf
+DST=/etc/caddy/simplex-cors.conf
+[ -f "$SRC" ] || exit 0
+cmp -s "$SRC" "$DST" 2>/dev/null && exit 0
+install -m 0644 "$SRC" "$DST"
+systemctl reload caddy
+logger -t simplex-cors "reloaded caddy"
+
+Create /etc/systemd/system/simplex-cors-sync.service:
[Unit]
+Description=Sync SimpleX relay CORS config to Caddy
+StartLimitIntervalSec=30
+StartLimitBurst=10
+[Service]
+Type=oneshot
+ExecStartPre=/bin/sleep 2
+ExecStart=/usr/local/bin/simplex-cors-sync.sh
+
+Create /etc/systemd/system/simplex-cors-sync.path to run the service whenever the relay's CORS file changes:
[Unit]
+Description=Watch SimpleX relay CORS config
+After=caddy.service
+[Path]
+PathChanged=/var/www/relay-web-channels/cors.conf
+Unit=simplex-cors-sync.service
+[Install]
+WantedBy=multi-user.target
+
+Enable it:
+chmod +x /usr/local/bin/simplex-cors-sync.sh
+systemctl daemon-reload
+systemctl enable --now simplex-cors-sync.path
+
+Verify
+systemctl status simplex-cors-sync.path # active (waiting)
+ls /var/www/relay-web-channels/channel # a JSON file appears once a public channel renders
+curl -sI https://relay.example.com/channel/<id>.json | grep -i access-control
+
+The curl should return access-control-* headers, and the channel link should open a web preview in a browser.
+
+
+
+
+