The Dusk Chat relay server
Go to file
cloudwithax ea21aa55b6 feat(turn): add embedded TURN server with credential service
Integrate a TURN/STUN server into the relay for NAT traversal of
WebRTC connections. Clients request time-limited HMAC-SHA1 credentials
over a new libp2p request-response protocol and then talk to the TURN
server directly via UDP/TCP.

Key changes:
- Add `turn` module with server, credentials, and configuration
- Register `/dusk/turn-credentials/1.0.0` request-response protocol
  so clients can obtain time-limited TURN credentials (24h TTL)
- Expose TURN signaling (3478/udp+tcp) and relay allocation ports
  (49152-65535/udp) in Dockerfile and docker-compose
- Add TURN-related environment variables for public IP, shared secret,
  realm, port ranges, and allocation limits
- Validate directory display_name (1-64 chars) and return typed errors
- Restrict keypair file permissions to 0600 on Unix
2026-02-24 20:57:05 -05:00
src feat(turn): add embedded TURN server with credential service 2026-02-24 20:57:05 -05:00
.dockerignore init commit 2026-02-13 18:01:15 -05:00
.gitignore added readme; removed target 2026-02-13 18:09:21 -05:00
Cargo.lock add directory service for peer profile management with SQLite integration 2026-02-19 17:48:07 -05:00
Cargo.toml add directory service for peer profile management with SQLite integration 2026-02-19 17:48:07 -05:00
DOCKER.md init commit 2026-02-13 18:01:15 -05:00
Dockerfile feat(turn): add embedded TURN server with credential service 2026-02-24 20:57:05 -05:00
LICENSE update Dockerfile to use Rust 1.85-slim; add MIT License 2026-02-13 19:01:46 -05:00
README.md added readme; removed target 2026-02-13 18:09:21 -05:00
docker-compose.yml feat(turn): add embedded TURN server with credential service 2026-02-24 20:57:05 -05:00

README.md

dusk relay server

a lightweight tracker-style node that helps dusk peers find each other without revealing their ip addresses.

what it does

the relay server provides two critical services for the dusk p2p network:

  • circuit relay v2: peers connect through this node, never seeing each other's ips. this enables nat traversal without exposing peer locations.
  • rendezvous: peers register under community namespaces and discover each other by peer id. this allows peers to find each other without a central directory.

the relay is stateless - it doesn't store messages or user data. it only brokers connections.

architecture

peer a --[encrypted circuit]--> relay <--[encrypted circuit]-- peer b

neither peer sees the other's ip address. the relay only forwards encrypted bytes.

quick start

local development

# install rust if needed
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

# run the relay
cargo run

the relay will start on port 4001 and print its multiaddress:

relay address: /ip4/0.0.0.0/tcp/4001/p2p/12D3KooW...

docker deployment

see DOCKER.md for complete docker deployment instructions.

cd relay-server
docker-compose up -d

configuration

environment variables

variable default description
RUST_LOG info log level (error, warn, info, debug, trace)
DUSK_RELAY_PORT 4001 port the relay listens on

example

# custom port and debug logging
RUST_LOG=debug DUSK_RELAY_PORT=8080 cargo run

persistence

the relay persists its keypair to disk so the peer id remains stable across restarts. the keypair is stored at:

  • linux: ~/.local/share/dusk-relay/keypair
  • macos: ~/Library/Application Support/dusk-relay/keypair
  • fallback: ./relay_keypair

to reset the relay's identity, delete this file and restart.

connecting clients

configure dusk clients to use the relay by setting the DUSK_RELAY_ADDR environment variable:

DUSK_RELAY_ADDR=/ip4/<relay-ip>/tcp/4001/p2p/<relay-peer-id> bun run tauri dev

replace <relay-ip> with your relay server's public ip address and <relay-peer-id> with the peer id printed when the relay starts.

monitoring

the relay logs important events:

  • peer connections and disconnections
  • relay reservations (circuits being established)
  • rendezvous registrations (peers discovering each other)
  • circuit creation and closure

example log output:

[2024-01-15T10:30:00Z INFO dusk_relay] dusk relay server starting
[2024-01-15T10:30:00Z INFO dusk_relay] peer id: 12D3KooW...
[2024-01-15T10:30:05Z INFO dusk_relay] peer connected: 12D3KooW... (total connections: 1)
[2024-01-15T10:30:06Z INFO dusk_relay] relay reservation accepted for peer 12D3KooW... (total: 1)
[2024-01-15T10:30:07Z INFO dusk_relay] circuit opened: 12D3KooW... -> 12D3KooW... (through relay)

production deployment

for production deployment, use docker. see DOCKER.md for:

  • docker compose setup
  • health checks
  • persistence configuration
  • security best practices
  • troubleshooting guide

security considerations

  • the relay runs as a non-root user in docker
  • only the necessary port is exposed
  • the relay never sees message content, only encrypted bytes
  • peer ids are cryptographic, not tied to ip addresses
  • no user data is stored on the relay

performance

the relay is lightweight and can handle many concurrent connections. typical resource usage:

  • cpu: minimal (mostly idle, spikes on connection events)
  • memory: ~50-100mb
  • network: scales with peer traffic

troubleshooting

port already in use

# check what's using port 4001
lsof -i :4001

# use a different port
DUSK_RELAY_PORT=8080 cargo run

peers can't connect

  • verify the port is open in your firewall
  • check the relay address format in client configuration
  • ensure the relay is running and listening

keypair issues

if the relay's peer id changes unexpectedly, the keypair file may have been lost. check the file exists:

ls -la ~/.local/share/dusk-relay/keypair

license

see the main project license file.