Files
featherChat/warzone/docs/SERVER.md
Siavash Sameni 76cac77259 v0.0.28: BotFather-only registration, per-instance bot toggle, docs update
Security:
- Bot registration restricted to BotFather (requires botfather_token)
- Direct POST /v1/bot/register without BotFather auth → rejected

Deploy:
- systemd service reads /home/warzone/server.env for EXTRA_ARGS
- deploy/warzone-server.env.mequ: no bots (default)
- deploy/warzone-server.env.kh3rad3ree: --enable-bots
- setup.sh copies per-hostname env file

Docs updated:
- LLM_HELP.md: BotFather flow, plaintext bot messaging, E2E option, bridge
- LLM_BOT_DEV.md: botfather_token requirement, E2E mode, bridge section
- BOT_API.md: full BotFather flow, ownership, numeric IDs, webhook delivery
- SERVER.md: --enable-bots flag, per-instance config, bot system section
- USAGE.md: bot messaging, BotFather, bridge tool

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 09:52:12 +04:00

16 KiB

Warzone Server -- Administration Guide

Version 0.0.21


1. Building

Local Build

From the workspace root:

# Debug
cargo build -p warzone-server

# Release (recommended for deployment)
cargo build -p warzone-server --release

Binary output: target/release/warzone-server.

Cross-Compile for Linux (x86_64)

The scripts/build-linux.sh script spins up a Hetzner Cloud VPS, builds Linux release binaries, and pulls them back to target/linux-x86_64/.

# Full pipeline: build + deploy to all production servers + destroy VM
./scripts/build-linux.sh --ship

# Step-by-step:
./scripts/build-linux.sh --prepare     # create VM, install deps, upload source
./scripts/build-linux.sh --build       # compile release binaries on the VM
./scripts/build-linux.sh --transfer    # download binaries to target/linux-x86_64/
./scripts/build-linux.sh --destroy     # delete the VM

# Or all three build steps at once (VM persists):
./scripts/build-linux.sh --all

Minimum Rust Version

Rust 1.75 or later (rust-version = "1.75" in Cargo.toml).


2. Running

Basic

# Defaults: bind 0.0.0.0:7700, data in ./warzone-data
./warzone-server

# Custom bind address and data directory
./warzone-server --bind 0.0.0.0:7700 --data-dir ./data

# With federation enabled
./warzone-server --federation federation.json

CLI Flags

Flag Short Default Description
--bind -b 0.0.0.0:7700 Address and port to listen on
--data-dir -d ./warzone-data Directory for the sled database
--federation -f (none) Path to federation JSON config file
--enable-bots (off) Enable Bot API and auto-create BotFather on startup

Environment Variables

Variable Default Description
RUST_LOG warn (production) Log filter. Examples: info, warzone_server=debug, trace
WZP_RELAY_ADDR (none) WZP voice relay address advertised to clients

Per-Instance Configuration (server.env)

Each server instance can use a server.env file for per-instance settings. Place it in the working directory or alongside the binary. This allows different instances to have different configurations (e.g., bots enabled on one server but not another).

Example server.env:

RUST_LOG=info
WZP_RELAY_ADDR=relay.example.com:3478
ENABLE_BOTS=true

systemd Service

A production-ready unit file is provided at deploy/warzone-server.service:

[Unit]
Description=Warzone Messenger Server (featherChat)
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=warzone
Group=warzone
WorkingDirectory=/home/warzone
ExecStart=/home/warzone/warzone-server --bind 0.0.0.0:7700 --data-dir /home/warzone/data --federation /home/warzone/federation.json
Restart=always
RestartSec=3
LimitNOFILE=65536

# Security hardening
NoNewPrivileges=yes
ProtectSystem=strict
ProtectHome=read-only
ReadWritePaths=/home/warzone/data
PrivateTmp=yes

Environment=RUST_LOG=warn,warzone_server::federation=info

[Install]
WantedBy=multi-user.target

Install and enable:

sudo cp deploy/warzone-server.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now warzone-server

3. Configuration

Federation JSON

Enable federation by passing --federation <path> on startup. The config file specifies the local server identity, peer connection details, and a shared secret for authentication.

Format (see federation.example.json):

{
  "server_id": "alpha",
  "shared_secret": "change-me-to-a-long-random-string-shared-between-both-servers",
  "peer": {
    "id": "bravo",
    "url": "http://10.0.0.2:7700"
  },
  "presence_interval_secs": 5
}
Field Description
server_id Unique name for this server (e.g. "alpha")
shared_secret Pre-shared secret; must match on both sides
peer.id The remote server's server_id
peer.url HTTP base URL of the remote server
presence_interval_secs How often to broadcast online-user lists (default 5)

4. Federation

Federation connects two Warzone servers over a persistent WebSocket so their users can communicate transparently.

How It Works

  • On startup, each server opens an outgoing WebSocket to its peer at /v1/federation/ws and authenticates with the shared secret.
  • The connection auto-reconnects on failure.
  • Presence (online fingerprints) is synced on the configured interval.
  • Messages to users on the remote server are forwarded automatically.

Federated Features

Feature Behavior
Key lookup proxy If a key bundle is not found locally, the server queries the peer
Message forwarding Messages addressed to a remote fingerprint are relayed over the WS
Alias resolution /v1/resolve/:address checks the peer if the alias is not local
Presence sync Each server broadcasts its online fingerprints to the peer

Two-Server Setup

Server A (alpha, e.g. mequ):

{
  "server_id": "alpha",
  "shared_secret": "s3cret-shared-between-both",
  "peer": { "id": "bravo", "url": "http://bravo-host:7700" },
  "presence_interval_secs": 5
}

Server B (bravo, e.g. kh3rad3ree):

{
  "server_id": "bravo",
  "shared_secret": "s3cret-shared-between-both",
  "peer": { "id": "alpha", "url": "http://alpha-host:7700" },
  "presence_interval_secs": 5
}

Both files use the same shared_secret. Each server's peer.id matches the other server's server_id.

Federation Status Endpoint

curl http://localhost:7700/v1/federation/status

Returns JSON with connection state, peer info, and presence data.


4b. Bot System

Enabling Bots

Start the server with --enable-bots to activate bot functionality. Without this flag, all bot endpoints return 403.

./warzone-server --bind 0.0.0.0:7700 --enable-bots

BotFather Auto-Creation

On first start with --enable-bots, the server auto-creates the @botfather bot. The BotFather token is printed to the server logs. Users interact with @botfather to register new bots.

Per-Instance Bot Toggle

Bot support can be enabled independently per server instance:

Instance Bots Config
mequ Disabled No --enable-bots flag
kh3rad3ree Enabled --enable-bots flag set

Bot Webhook Delivery

When a bot has a webhook configured (via setWebhook), incoming messages are delivered live to the webhook URL via HTTP POST instead of being queued for getUpdates polling. This is integrated into the standard message routing pipeline -- deliver_or_queue checks for webhook configuration before queueing.


5. API Reference

All endpoints are prefixed with /v1. The web UI is served at /.

Notation

  • Auth = requires Authorization: Bearer <token> header (write routes).
  • Public = no authentication needed (read routes).

Health

Method Path Auth Description
GET /v1/health Public Health check; returns {"status":"ok"}

Keys

Method Path Auth Description
POST /v1/keys/register Public Register a pre-key bundle
POST /v1/keys/replenish Public Upload additional one-time pre-keys
GET /v1/keys/:fingerprint Public Fetch a key bundle (falls back to federation peer)
GET /v1/keys/list Public List all registered fingerprints
GET /v1/keys/:fingerprint/otpk-count Public Remaining one-time pre-key count
GET /v1/keys/:fingerprint/devices Public List devices for a fingerprint

Messages

Method Path Auth Description
POST /v1/messages/send Auth Send an encrypted message blob
GET /v1/messages/poll/:fingerprint Public Poll queued messages
DELETE /v1/messages/:id/ack Public Acknowledge (delete) a message

Groups

Method Path Auth Description
POST /v1/groups/create Auth Create a group
POST /v1/groups/:name/join Auth Join a group
POST /v1/groups/:name/send Auth Send a message to a group
POST /v1/groups/:name/leave Auth Leave a group
POST /v1/groups/:name/kick Auth Kick a member from a group
GET /v1/groups Public List all groups
GET /v1/groups/:name Public Get group details
GET /v1/groups/:name/members Public List members (includes online status)

Aliases

Method Path Auth Description
POST /v1/alias/register Auth Register a human-readable alias
POST /v1/alias/unregister Auth Remove your alias
POST /v1/alias/recover Auth Transfer alias to a new fingerprint
POST /v1/alias/renew Auth Renew alias expiry
POST /v1/alias/admin-remove Auth Admin-remove an alias
GET /v1/alias/resolve/:name Public Resolve alias to fingerprint
GET /v1/alias/list Public List all registered aliases
GET /v1/alias/whois/:fingerprint Public Reverse-lookup: fingerprint to alias

Calls (WZP)

Method Path Auth Description
POST /v1/calls/initiate Auth Start a 1:1 call
POST /v1/calls/:id/end Auth End an active call
POST /v1/calls/missed Auth Get missed calls for a fingerprint
POST /v1/groups/:name/call Auth Initiate a group call
GET /v1/calls/:id Public Get call details
GET /v1/calls/active Public List active calls

Devices

Method Path Auth Description
POST /v1/devices/:id/kick Auth Disconnect a specific device
POST /v1/devices/revoke-all Auth Disconnect all devices (optional keep one)
GET /v1/devices Auth List your connected devices

Presence

Method Path Auth Description
POST /v1/presence/batch Auth Batch-query presence for multiple fingerprints
GET /v1/presence/:fingerprint Public Check if a fingerprint is online

Friends

Method Path Auth Description
POST /v1/friends Auth Save friend list (encrypted blob)
GET /v1/friends Auth Retrieve saved friend list

Resolve

Method Path Auth Description
GET /v1/resolve/:address Public Universal resolve: ETH address, alias, or fingerprint. Checks federation peer if not found locally.

WZP Voice Relay

Method Path Auth Description
GET /v1/wzp/relay-config Public Get the WZP relay address for voice calls

Federation

Method Path Auth Description
GET /v1/federation/status Public Federation connection status and peer info
GET /v1/federation/ws Internal WebSocket endpoint for server-to-server communication

Bot API

Method Path Auth Description
POST /v1/bot/register Auth Register a bot; returns an API token
GET /v1/bot/:token/getMe Token Bot identity info
POST /v1/bot/:token/getUpdates Token Long-poll for new messages (Telegram-compatible)
POST /v1/bot/:token/sendMessage Token Send a message as the bot (Telegram-compatible)

Bot tokens are scoped to the bot's fingerprint. The getUpdates and sendMessage endpoints follow the Telegram Bot API conventions so existing Telegram bot libraries can be adapted with minimal changes.


WebSocket

Path Description
/v1/ws/:fingerprint Real-time message delivery. Clients receive instant push of new messages.

Web UI

Path Description
/ Single-page WASM web client
/wasm/warzone_wasm.js WASM JavaScript bindings
/wasm/warzone_wasm_bg.wasm WASM binary

6. Database

The server uses sled (embedded key-value store). All data lives under the --data-dir directory.

Trees

Tree Purpose
keys Pre-key bundles (public keys only)
messages Queued encrypted message blobs
groups Group metadata and membership
aliases Human-readable alias mappings
tokens Authentication tokens (device sessions)
calls Call records (1:1 and group)
missed_calls Missed call notifications
friends Encrypted friend lists
eth_addresses Ethereum address to fingerprint mappings

Data Directory Structure

warzone-data/
  db                    # sled database file
  conf                  # sled config
  blobs/                # sled blob storage
  snap.*/               # sled snapshots

The entire directory should be treated as a unit for backup. Stop the server before copying, or use filesystem-level snapshots (LVM, ZFS, btrfs).


7. Security

Auth Middleware

All write (POST) endpoints require a bearer token in the Authorization header. Tokens are issued during key registration and tied to a fingerprint. Read (GET) endpoints are public.

Rate Limiting

  • 200 concurrent requests (tower ConcurrencyLimitLayer)
  • 5 WebSocket connections per fingerprint (multi-device cap)

Device Management

Users can list connected devices, kick individual devices, or revoke all sessions via the /v1/devices endpoints. The revoke-all endpoint accepts an optional keep_device_id to keep the current device active.

What the Server Can See

Data Visible
Message plaintext No (E2E encrypted blobs)
Sender/recipient fingerprints Yes
Message size and timing Yes
Public pre-key bundles Yes (public by design)
IP addresses Yes (from HTTP)

8. Monitoring

Logging

Control verbosity with RUST_LOG:

RUST_LOG=warn ./warzone-server              # production default
RUST_LOG=info ./warzone-server              # request-level logging
RUST_LOG=warzone_server=debug ./warzone-server  # server internals
RUST_LOG=trace ./warzone-server             # everything

With systemd:

journalctl -u warzone-server -f

Health Check

curl http://localhost:7700/v1/health

Federation Status

curl http://localhost:7700/v1/federation/status

Returns connection state, peer identity, and synced presence data.


9. Deploy Scripts

The scripts/build-linux.sh script handles the full build and deploy lifecycle via Hetzner Cloud VMs.

Key Commands

Command Description
--ship Full pipeline: build on VM, deploy to all production servers, destroy VM
--update-all Upload pre-built binaries to all production servers and restart
--update <user@host> Update a single production server
--status Check service status and federation on all production servers
--logs [user@host] Tail journalctl logs (defaults to first production server)

Typical Deploy Workflow

# One command: build, deploy everywhere, clean up
./scripts/build-linux.sh --ship

# Or step by step:
./scripts/build-linux.sh --all          # build (VM persists)
./scripts/build-linux.sh --update-all   # deploy binaries
./scripts/build-linux.sh --destroy      # clean up VM
./scripts/build-linux.sh --status       # verify

10. Backup and Recovery

Backup

systemctl stop warzone-server
cp -r /home/warzone/data /backup/warzone-$(date +%Y%m%d)
systemctl start warzone-server

Do not copy the sled directory while the server is running without filesystem-level snapshots.

Recovery

  1. Stop the server.
  2. Replace the data directory with the backup.
  3. Start the server.

Messages queued after the backup was taken are permanently lost. All messages are E2E encrypted and cannot be recovered from any other source.