VoxMotoChat - server

Administrator manual

document version: 1.0.0 (2026-07-01)

Index

 

Description

VoxMotoChat Server is a high-performance communication server based on the UDP protocol. The server supports secure chat rooms with full end-to-end encryption (E2EE) and reliable packet delivery (ACK) mechanisms..

 

Features:

  • Encryption: a server with public: true set is protected against Man-in-the-Middle (MiTM) attacks. Ed25519 is used to authenticate the server’s identity and protect against Man-in-the-Middle (MITM) attacks, whilst X25519 is used for secure session key agreement. A server with public: true set sends its public identity_key to the public trusted server list (the server list is a trusted web service), clients connecting to the server retrieve this key and thereby verify the server's identity, which protects against MiTM attacks. The calculated SessionKey for ChaCha20 -Poly1305 with a nonce is used to encrypt transport communication, a separate ChaCha20 SenderKey is calculated to encrypt the audio stream. Thanks to the use of Ed25519 and X25519, neither the SessionKey nor the SenderKey is transmitted in any way, instead, they are calculated on each side, which significantly improves security.
    For servers where public = false, Ed25519 is still used to authenticate the server's identity and X25519 is used for secure session key agreement, however, the clients cannot verify the identity_key, leaving the transport layer vulnerable to a MitM attack, as the server is not registered on the public server list and has not published its identity_key on the serverlist (the serverlist is a trusted web service containing a list of servers), which means that clients are unable to verify the server's identity, but communication remains fully encrypted.
  • Synchronization: automatic synchronization of user and key lists
  • Public List: ability to submit the server to the global VoxMotoChat directory
  • Administration: CLI interface (commands)
  • Man-in-the-Middle Attack Protection (Eavesdropping): VoxMotoChat prevents third parties from intercepting or modifying transmissions/packets/conversations with multi-layered verification (only applies to servers visible in the public server list)

Encryption - why this solution?

  • The server does not hold any "master keys": the server does not generate or hold clients private keys, it does not hold a single ChaCha20 session key (each client has a dedicated session key that is calculated on the fly) nor does it hold any keys for decrypting audio. Each user's session has its own unique and temporary cryptographic foundation. Private keys never leave the user's phone, and the server's private keys never leave the server. Client-side keys and server-side keys are always regenerated with every connection (new session) and server identity_key (for signature) is always regenerated every time the server is started.
  • Ephemeral Handshake: (Ed25519, X25519) and Ephemeral Session (ChaCha20-Poly1305)
  • Performance: Ed25519 and X25519 are used for the handshake and for establishing keys for transport layer encryption and audio layer encryption (furthermore, for servers that have sent an identity_key to the server list, communication is protected against Man-in-the-Middle (MitM) attacks). ChaCha20 (ChaCha20-Poly1305) encryption is optimised for ARM processor instructions in mobile phones, enabling phones to encrypt communications quickly and efficiently.
  • Security: all keys are generated in the phone's RAM only for the duration of the connection to the server. Even if someone intercepts all UDP traffic, they will not be able to determine the session keys for the transport layer or the audio layer.
  • Perfect Forward Secrecy (PFS): by generating new encryption keys for the transport layer and audio layer and establishing new ChaCha20 session keys with every connection (of the VoxMotoChat app) to the server, the compromise of a single session does not allow new or past sessions to be compromised. Each client generates its own key and has individually generated encryption keys (a transport layer session key for encrypting traffic with the server and a Sender key for encrypting the audio layer)
    Even if an attacker were to intercept server traffic in the future and breach the server's security, they would not be able to decrypt the historical packets already intercepted from previous sessions, as each connection is encrypted using different keys.
  • Double Encryption:
    • Transport Encryption (Client-to-Server) - protects all UDP communication between the application and the server. It hides packet types, usernames and metadata from third parties.
    • End-to-End Encryption (Client-to-Client) - additional encryption of the audio payload. The server does not possess the E2EE keys used to encrypt individual users audio. Upon receiving an audio packet, the server only decrypts the transport layer to send the packet to recipients, but the audio content itself remains encrypted (unreadable) to the server. The server acts as a relay/router for audio packets and forwards encrypted audio packets without knowledge of the transmitted content.

 

Technical Information

If the server is behind a router (NAT), you must forward the port to the server machine's IP address.

 

Ports

Service Protocol Port Description
Server UDP 27977 Default server communication port, incoming/outgoing port (requires forwarding if behind NAT)
Webservice TCP 443 For communication with the VoxMotoChat webservice if the server is public, outgoing port (does not require forwarding)

 

Security Mechanism (Rate Limiting)

The server has a built-in request limiter. When the limit is exceeded, packets are ignored and a warning appears in the logs.

 

Logs

Logs are saved in a human-readable format and rotated daily at midnight. Old files are automatically compressed.

 

Auto-Cleanup Mechanism

The server automatically:

  • Deletes empty rooms after 5 seconds
  • Deletes expired invitation tokens
  • Disconnects clients that do not send a heartbeat/do not respond to pings (configurable in config.json in the timeouts section)

 

Configuration File (config.json)

The config.json file must be located in the same directory as the server executable.

Example config.json

{
    "server": {
      "port": 27977,
      "bind_address": "0.0.0.0",
      "public_address": "",
      "statusbar": 1,
      "server_name": "Self-Hosted VoxMotoChat Server",
      "public": true,
      "password_protected": false,
      "password_hash": ""
    },
    "logging": {
      "logDir": "logs",
      "filename": "voxmotochat.log",
      "dateFormat": "YYYY-MM-DD",
      "maxSize": "50m",
      "maxFiles": "7d",
      "level": "INFO"
    },
    "timeouts": {
      "clientCheckInterval": 20000,
      "clientTimeout": 600000
    }
}

Server section

Parameter Type Description
port int UDP port on which the server is listening (default: 27666)
bind_address string IP address to bind to. Use 0.0.0.0 to listen on all interfaces (default: 0.0.0.0)
public_address string The server address that will be sent to the public server list (if the server is public -> public: true). This means that bind_address can be 0.0.0.0 and the public_address can be set to a domain or any other IP address, e.g., "public_address": "server.domain.com", and the server will be visible in the public server list (in the application's server list) with the address server.domain.com. If public_address is empty or incorrect, the server will send the server list service whatever is entered in bind_address (in the case of 0.0.0.0 and "public": true, the server list service will read the public address from which the report came).
statusbar int 1 enables the status bar at the top of the console, 0 disables
server_name string Server name visible to clients and on the public list (max 96 characters, allowed characters in the server name: letters, numbers, spaces, dashes, dots, boxes, underscores)
public bool [true/false] (default: false) If true, the server will be visible in the server list in the VoxMotoChat application. If false, the server will not be visible on the server list and you can connect to it by entering the server address and port in the "custom server address" field in the server browser in the application
password_protected boolean [true/false] (default: false) If true, the server will check the server's password (based on the password_hash) before the client can connect to the server/rooms.
password_hash string [bcrypt hash] The bcrypt hash of the server's password (used if "password_protected": true).
The hash can be generated with a command such as voxmotochat-server-amd64 --hashpass password

Logging section

The log file name is rotated every 24 hours.

Parameter Type Description
logDir string Directory where log files will be stored (e.g. "logs")
filename string Log file name
dateFormat string date format
level string Logging level: DEBUG, INFO, WARN, ERROR
maxSize string Maximum log file size before rotation (e.g., "100m")
maxFiles string Old log retention time (e.g., "7d")

Timeouts Section

Parameter Type Description
clientCheckInterval int Client activity check frequency (ms) (recommended minimum 10000), time formula: seconds x 1000 = value
clientTimeout int Time (in ms) after which the client is disconnected if it does not respond to a ping from the server (recommended minimum 300000 = 5 min), time formula: minutes x 60 x 1000 = value

clientTimeout - the minimum recommended timeout is 5 minutes (optimal timeout is 15-20 minutes (15000-20000)). Because in the event of internet outages while driving, the client may not respond to pings for up to several minutes, maintaining a connection with such a client minimizes the number of (automatic) reconnections to the server that the VoxMotoChat app must make on the phone. As soon as the phone regains internet connection the app immediately sends audio packets, which the server receives. When the server detects that the client is unresponsive it kicks the client from the server. This means that when the client regains internet, the app must reconnect to the server (because the client was kicked from the room and the server) and join the selected room to send audio packets to the server.

 

Starting the server - service in Linux

To start the server, download the appropriate server binary file for the system on which the server will be running. Set the file to executable (e.g., chmod +x voxmoto-server-amd64, then ./voxmoto-server-amd64).

 

System Requirements (Minimum)

  • CPU: 1 GHz (depends on the number of users on the server; the more users, the more CPU will be needed)
  • RAM: 128 MB (depends on the number of users on the server; the more users, the more RAM will be needed)
  • HDD: 50-100 MB (binary file + some space for logs. The more users and logs to store, the more space needed)
  • Operating System: AlmaLinux / Debian / Ubuntu
  • Architecture: x86-64 (PC/dedicated server/VPS), ARM64 (Raspberry Pi 3+/Orange Pi 3+), ARM32/ARMv7 (Raspberry Pi Zero W/Zero 2 W, etc.)
  • Golang: Go environment installed (version 1.25 or later recommended).

CLI Support (Commands)

Upon launch, the server offers an interactive console.

Commands:

  • help - Displays a list of all available commands.
  • status - Shows general statistics: CPU usage, RAM, number of clients and bandwidth.
  • statusbar - Enables(1)/disables(0) the permanent status bar at the top of the screen.
  • tree - Displays the server's hierarchical structure (Rooms -> Users).
  • users - Displays a list of all connected users (with UID, IP, and synchronization status).
  • rooms - Displays a list of active rooms.
  • handshakes - Displays a list of clients in the process of establishing a connection.
  • pending - Displays a list of all clients waiting for client list sync.
  • pending - Displays a list of clients waiting to sync the client list of room
  • inboxes - Displays all inboxes on the server.
  • inboxes - Displays inboxes for a specific room.
  • tokens - Displays all tokens assigned to the room (i.e. only 6 chars).
  • kick [uid] [reason] - Forces the disconnection of the user with the given UID. Example: kick 1 inappropriate behavior.
  • loglevel <DEBUG|INFO|WARN|ERROR> - Sets the log level for the CLI console.
  • exit - Safely shuts down the server, unregistering it from the public list.

 

Starting the server as a service (in screenshot)

Steps:

  1. Introduction
  2. Creating the voxmotochatserver.service file
  3. Creating the voxmotochatserver.sh file
  4. Creating config.json
  5. Reloading the service
  6. Launching
  7. Verifying operation
  8. Firewall

Step 1

Create the voxmotochatserver user (or any other user, just remember to change the voxmotochatserver entries to your username and the paths appropriate for the created user).

sudo adduser voxmotochatserver 

The server files are in the download section, you need to download the appropriate file and put it in /home/voxmotochatserver


Downloading the appropriate file for the system architecture:

Linux AMD64 (x86-64)

curl -L -o voxmoto-server-amd64 https://voxmotochat.com/download-process?file=%2Ffiles%2Fserver%2Flatest%2Fvoxmotochat-server-amd64

or Linux ARM64 (Raspberry Pi 3+ / Orange Pi 3+)

curl -L -o voxmoto-server-arm64 https://voxmotochat.com/download-process?file=%2Ffiles%2Fserver%2Flatest%2Fvoxmotochat-server-arm64

or Linux ARM32 ( Raspberry Pi 1, 2, Zero, Zero 2 itd,)

curl -L -o voxmoto-server-armv7 https://voxmotochat.com/download-process?file=%2Ffiles%2Fserver%2Flatest%2Fvoxmotochat-server-armv7

Checking if Golang is installed

go version



GoLang installation (if not present in your system)

AlmaLinux

sudo dnf install golang

Debian/Ubuntu/Raspbian

sudo apt update
sudo apt install golang

or

sudo apt install golang-go



Step 2

Create the file /etc/systemd/system/voxmotochatserver.service

sudo tee /etc/systemd/system/voxmotochatserver.service > /dev/null << 'EOF'
[Unit]
Description=Voxmotochat server screen session
After=network.target

[Service]
Type=forking
User=voxmotochatserver
WorkingDirectory=/home/voxmotochatserver
ExecStart=/usr/bin/voxmotochatserver.sh
ExecStop=/usr/bin/screen -S voxmotochatserver -X quit
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF

Step 3

Create the file /usr/bin/voxmotochatserver.sh

sudo tee /etc/systemd/system/voxmotochatserver.service > /dev/null << 'EOF'
#!/bin/bash

cd /home/voxmotochatserver
screen -AmdS voxmotochatserver bash -c '
while true; do
    ./voxmotochat-server-amd64
    echo "Server crashed. Restarting in 5 seconds..."
    sleep 5
done
'
EOF
  • remember to change voxmotochat-server-amd64 to your file name

Step 4

Create the file /home/voxmotochatserver/config.json

sudo tee /home/voxmotochatserver/config.json > /dev/null << 'EOF'
{
    "server": {
      "port": 27977,
      "bind_address": "0.0.0.0",
      "public_address": "",
      "statusbar": 1,
      "server_name": "Self-Hosted VoxMotoChat Server",
      "public": true,
      "password_protected": false,
      "password_hash": ""
    },
    "logging": {
      "logDir": "logs",
      "filename": "voxmotochat.log",
      "dateFormat": "YYYY-MM-DD",
      "maxSize": "50m",
      "maxFiles": "7d",
      "level": "INFO"
    },
    "timeouts": {
      "clientCheckInterval": 20000,
      "clientTimeout": 600000
    }
}
EOF

Step 5

After creating the files, perform the following:

reload services

sudo systemctl daemon-reload

activating the voxmotochatserver service

systemctl enable voxmotochatserver.service

starting the voxmotochatserver service

systemctl start voxmotochatserver.service

Step 6

Log in as user voxmotochatserver e.g.

su voxmotochatserver

Step 7

then

screen -r voxmotochatserver

A screen will appear in the console (you can check the list of running services in screen with the screen -ls command) with the VoxMotoChatServer server console (leave the screen console -> CTRL+A+D). Now you can enter the help command to display the available commands. That's it, the server is running.



8. Firewall

if the firewall is enabled on the server, you must add the VoxMotoChat server port to the firewall

AlmaLinux firewall-cmd:

sudo firewall-cmd --permanent --add-port=27977/udp
sudo firewall-cmd --reload

verification

sudo firewall-cmd --list-ports

or

sudo firewall-cmd --list-all

result: ports: 27977/udp

Debian ufw:

sudo ufw allow 27977/udp

verification

sudo ufw status numbered

result: 27977/udp ALLOW Anywhere

Debian iptables:

sudo apt install iptables-persistent
sudo iptables -A INPUT -p udp --dport 27977 -j ACCEPT
sudo netfilter-persistent save