add docs, protocol, plugins, README, CHANGELOG

This commit is contained in:
loki5512344 2026-07-09 12:30:55 +02:00
parent 1d2209bfac
commit f262da222b
Signed by: boba
GPG key ID: 253067914055423B
44 changed files with 9269 additions and 0 deletions

34
docs/03-server/README.md Normal file
View file

@ -0,0 +1,34 @@
# Server / Gateway
A VNOX node consists of two processes:
```
gateway — TCP, handles auth / chat / channels / permissions
voice-node — UDP, handles voice relay
```
Both are written in Rust. They can run on the same machine or separately.
For most self-hosted setups, running both on one machine is fine.
---
## Minimum requirements
| | Minimum | Recommended |
|---|---|---|
| CPU | 1 core | 2+ cores |
| RAM | 256 MB | 512 MB |
| Bandwidth | 1 Mbps up | 10 Mbps up |
| OS | Linux x86_64 | Linux x86_64 |
| Ports | TCP 7600, UDP 7700 | configurable |
Voice bandwidth scales with concurrent speakers:
~64 kbps per active speaker (default 64k bitrate, 20ms frames).
---
## Sections
- [deployment.md](deployment.md) — how to install and run a node
- [configuration.md](configuration.md) — full config.toml reference
- [operations.md](operations.md) — metrics, logs, backup, upgrades

View file

@ -0,0 +1,220 @@
# Configuration
All configuration lives in a single `config.toml` file.
Path: `/etc/vnox/config.toml` (or passed via `--config`).
For local development, see [dev/README.md](../../dev/README.md) and `dev/config.toml`.
Environment variables prefixed with `VNOX_` override any config file value.
Example: `VNOX_NODE_NAME=my-node` overrides `[node] name`.
---
## Full reference
```toml
# ─── NODE ──────────────────────────────────────────────────────────────────
[node]
# Human-readable name shown to connecting clients.
name = "my-node"
# Public address of this node. Used by federation and relay routing.
# Can be domain name or IP address.
address = "my-node.example.com"
# LNEx protocol version this node advertises.
# Do not change unless you know what you're doing.
lnex_version = "v1"
# ─── GATEWAY ───────────────────────────────────────────────────────────────
[gateway]
# Address and port to listen for TCP client connections.
bind = "0.0.0.0:7600"
# Maximum concurrent client connections.
max_connections = 1000
# Idle session timeout in seconds. Sessions older than this
# without activity are terminated.
session_timeout = 300
# Maximum message size in bytes (text chat).
max_message_size = 4096
# Rate limits
[gateway.rate_limits]
auth_attempts_per_minute = 5 # per IP
messages_per_second = 10 # per user
connections_per_ip = 4 # concurrent
# ─── VOICE ─────────────────────────────────────────────────────────────────
[voice]
# Address and port to listen for UDP voice packets.
bind = "0.0.0.0:7700"
# Maximum concurrent voice sessions.
max_sessions = 500
# Jitter buffer default size in milliseconds.
# Clients may override this locally.
jitter_buffer_ms = 40
# Maximum relay packet rate per user (packets per second).
# At 20ms frames: 50 pps. Increase only for 10ms frame configs.
max_pps_per_user = 60
# ─── IDENTITY / TLS ────────────────────────────────────────────────────────
[identity]
# Path to the node's keypair file (Ed25519).
# Generated automatically on first start if not present.
keypair_path = "/var/lib/vnox/node.key"
# TLS certificate for the TCP gateway.
# If not set, a self-signed certificate is generated.
# tls_cert = "/etc/vnox/tls/cert.pem"
# tls_key = "/etc/vnox/tls/key.pem"
# ─── CHANNELS ──────────────────────────────────────────────────────────────
[channels]
# Default channels created on first start.
# After that, channels are managed via the admin API or client.
defaults = [
{ name = "general", type = "text" },
{ name = "lobby", type = "voice" },
]
# Maximum channels per node.
max_channels = 256
# Maximum users per voice channel.
max_voice_per_channel = 50
# ─── PERMISSIONS ───────────────────────────────────────────────────────────
[permissions]
# Default permission level for new users connecting for the first time.
# Options: guest | member | moderator | admin
default_role = "member"
# If true, new connections are allowed by default.
# If false, users must be explicitly whitelisted.
open = true
# ─── STORAGE ───────────────────────────────────────────────────────────────
[storage]
# Directory for persistent data (message history, user records, etc.)
data_dir = "/var/lib/vnox"
# Database backend.
# Options: sqlite (default), postgres
backend = "sqlite"
# SQLite database path (used if backend = "sqlite")
sqlite_path = "/var/lib/vnox/vnox.db"
# PostgreSQL connection string (used if backend = "postgres")
# postgres_url = "postgresql://user:pass@localhost/vnox"
# Message history retention in days. 0 = keep forever.
history_retention_days = 90
# ─── FEDERATION ────────────────────────────────────────────────────────────
[federation]
# Enable federation with other nodes.
# Phase 3 feature — disabled by default.
enabled = false
# Static list of trusted nodes to connect to on startup.
# bootstrap = [
# "relay.other-node.example.com",
# "192.168.1.20:7700",
# ]
# Maximum incoming federation connections.
max_incoming = 16
# Maximum bridged channels.
max_bridges = 64
# Message rate limit per federation link (messages per second).
rate_limit_msgs = 100
# Denylist — nodes that will never be allowed to federate.
# denylist = ["bad-node.example.com"]
# ─── RELAY ─────────────────────────────────────────────────────────────────
[relay]
# This node acts as a relay for other nodes' voice traffic.
# Useful for nodes behind NAT.
enabled = false
# relay_secret = "shared-secret-with-trusted-nodes"
# ─── LOGGING ───────────────────────────────────────────────────────────────
[logging]
# Log level: error | warn | info | debug | trace
level = "info"
# Log format: text | json
format = "text"
# Log file path. If not set, logs go to stdout.
# file = "/var/log/vnox/gateway.log"
# Log voice packet events (very verbose, debug only).
log_voice_packets = false
# ─── METRICS ───────────────────────────────────────────────────────────────
[metrics]
# Expose Prometheus metrics endpoint.
enabled = false
bind = "127.0.0.1:9090"
path = "/metrics"
```
---
## Environment variable overrides
Any config key can be overridden with an env var using the pattern:
`VNOX_` + section + `_` + key, uppercased, dots replaced with `_`.
Examples:
```bash
VNOX_NODE_NAME=my-node
VNOX_GATEWAY_BIND=0.0.0.0:7600
VNOX_LOGGING_LEVEL=debug
VNOX_STORAGE_BACKEND=postgres
VNOX_STORAGE_POSTGRES_URL=postgresql://user:pass@db/vnox
```
---
## Validating config
```bash
vnox-gateway --config /etc/vnox/config.toml --check
```
Exits 0 if config is valid, prints errors otherwise.

View file

@ -0,0 +1,221 @@
# Deployment
> **Phase 1 note:** published container images and HTTP health checks are not available yet.
> For local development, build from source and use [dev/README.md](../../dev/README.md).
## Option A - Docker (when images are published)
The fastest way to get a node running once official images exist.
### Prerequisites
- Docker 24+
- Docker Compose v2
### docker-compose.yml
```yaml
version: "3.9"
services:
gateway:
# Build locally until ghcr.io/vnox images are published:
# build: { context: ../.., dockerfile: docker/gateway.Dockerfile }
image: ghcr.io/vnox/gateway:latest
restart: unless-stopped
ports:
- "7600:7600" # TCP — client connections
volumes:
- ./config.toml:/etc/vnox/config.toml:ro
- vnox-data:/var/lib/vnox
environment:
- VNOX_LOG=info
voice-node:
image: ghcr.io/vnox/voice-node:latest
restart: unless-stopped
ports:
- "7700:7700/udp" # UDP — voice packets
volumes:
- ./config.toml:/etc/vnox/config.toml:ro
environment:
- VNOX_LOG=info
volumes:
vnox-data:
```
### Start
```bash
docker compose up -d
docker compose logs -f
```
### Verify
```bash
# Phase 1: no /health endpoint yet. Check TCP instead:
nc -zv localhost 7600
# Or watch gateway logs after start:
# VNOX_LOG=info cargo run -p vnox-gateway -- --config dev/config.toml
```
When an HTTP health endpoint ships (Phase 2), it may look like:
```bash
curl http://localhost:7600/health
# {"status":"ok","version":"LNEx v1","node":"your-node-name"}
```
---
## Option B - systemd (bare binary)
For servers where Docker is not available or not desired.
### Download
```bash
# Replace VERSION with the latest release tag
VERSION=0.1.0
curl -L https://github.com/vnox/vnox/releases/download/v${VERSION}/vnox-linux-x86_64.tar.gz \
| tar xz -C /usr/local/bin/
```
Binaries installed:
- `/usr/local/bin/vnox-gateway`
- `/usr/local/bin/vnox-voice-node`
### Config
```bash
mkdir -p /etc/vnox /var/lib/vnox
cp config.example.toml /etc/vnox/config.toml
$EDITOR /etc/vnox/config.toml
```
### systemd units
`/etc/systemd/system/vnox-gateway.service`:
```ini
[Unit]
Description=VNOX Gateway
After=network.target
[Service]
ExecStart=/usr/local/bin/vnox-gateway --config /etc/vnox/config.toml
Restart=on-failure
RestartSec=5s
User=vnox
Group=vnox
StateDirectory=vnox
RuntimeDirectory=vnox
[Install]
WantedBy=multi-user.target
```
`/etc/systemd/system/vnox-voice-node.service`:
```ini
[Unit]
Description=VNOX Voice Node
After=network.target vnox-gateway.service
[Service]
ExecStart=/usr/local/bin/vnox-voice-node --config /etc/vnox/config.toml
Restart=on-failure
RestartSec=5s
User=vnox
Group=vnox
[Install]
WantedBy=multi-user.target
```
### Enable and start
```bash
# Create service user
useradd -r -s /sbin/nologin vnox
# Enable services
systemctl daemon-reload
systemctl enable --now vnox-gateway vnox-voice-node
# Check status
systemctl status vnox-gateway
systemctl status vnox-voice-node
```
---
## Option C - bare binary (dev / test)
For local development and testing without systemd, see [dev/README.md](../../dev/README.md).
```bash
# Terminal 1 - gateway
cargo run -p vnox-gateway -- --config dev/config.toml
# Terminal 2 - voice node
cargo run -p vnox-voice-node -- --config dev/config.toml
```
---
## Minimal config.toml
The minimum required configuration to get a node running:
```toml
[node]
name = "my-node" # displayed to clients
address = "my-node.example.com" # public address (domain or IP)
[gateway]
bind = "0.0.0.0:7600"
[voice]
bind = "0.0.0.0:7700"
[identity]
# Generated on first start if not present
# keypair_path = "/var/lib/vnox/node.key"
```
See [configuration.md](configuration.md) for the full reference.
---
## Firewall
Open the following ports:
```bash
# TCP — client connections
ufw allow 7600/tcp
# UDP — voice packets
ufw allow 7700/udp
```
If running behind a reverse proxy (nginx / caddy), only expose port 443 externally
and proxy to 7600 internally. UDP 7700 must be directly accessible.
---
## First connection test
1. Download the VNOX client
2. Open VNOX → Add node → enter your server address
3. The client will generate an identity on first launch
4. Connect — you should see your node's channels
If connection fails, check:
- gateway is running: `systemctl status vnox-gateway`
- port 7600 is open: `nc -zv your-server 7600`
- logs: `journalctl -u vnox-gateway -f`

View file

@ -0,0 +1,218 @@
# Operations
## Health check
```bash
curl http://localhost:7600/health
```
```json
{
"status": "ok",
"version": "LNEx v1",
"node": "my-node",
"uptime_seconds": 86400,
"connections": 12,
"voice_sessions": 4
}
```
---
## Logs
### View live logs
```bash
# systemd
journalctl -u vnox-gateway -f
journalctl -u vnox-voice-node -f
# Docker
docker compose logs -f gateway
docker compose logs -f voice-node
```
### Log levels
Set in `config.toml` under `[logging] level` or via `VNOX_LOGGING_LEVEL`:
```
error — only errors
warn — errors + warnings
info — normal operation (default)
debug — detailed internal events
trace — everything including packet events (very verbose)
```
For production: `info`.
For debugging a specific issue: `debug`.
Never run `trace` in production — it logs packet contents.
### Useful log patterns
```bash
# Auth failures
journalctl -u vnox-gateway | grep "AUTH_FAILED"
# New connections
journalctl -u vnox-gateway | grep "SESSION"
# Voice node errors
journalctl -u vnox-voice-node | grep "ERROR"
# Rate limit events
journalctl -u vnox-gateway | grep "RATE_LIMITED"
```
---
## Metrics (Prometheus)
Enable in `config.toml`:
```toml
[metrics]
enabled = true
bind = "127.0.0.1:9090"
path = "/metrics"
```
Available metrics:
```
vnox_connections_total # total connections since start
vnox_connections_active # current active connections
vnox_auth_success_total # successful authentications
vnox_auth_failure_total # failed authentications
vnox_messages_total # text messages delivered
vnox_voice_sessions_active # current voice sessions
vnox_voice_packets_total # voice packets relayed
vnox_voice_packet_loss_ratio # packet loss (rolling average)
vnox_federation_links_active # active federation connections (Phase 3)
vnox_gateway_latency_ms # gateway processing latency histogram
```
Scrape config for `prometheus.yml`:
```yaml
scrape_configs:
- job_name: vnox
static_configs:
- targets: ['localhost:9090']
scrape_interval: 15s
```
---
## Backup
### What to back up
| Path | Contents | Priority |
|------|----------|---------|
| `/var/lib/vnox/node.key` | Node identity keypair | **Critical** |
| `/var/lib/vnox/vnox.db` | Message history, user records | High |
| `/etc/vnox/config.toml` | Node configuration | Medium |
Losing `node.key` means the node loses its federated identity.
Other nodes that trusted this node's pubkey will not recognize the replacement.
### Backup node.key
```bash
# Copy to secure location
cp /var/lib/vnox/node.key /backup/vnox-node-$(date +%Y%m%d).key
chmod 600 /backup/vnox-node-*.key
```
Store this file encrypted, offline, and in multiple locations.
### Backup SQLite database
```bash
# While gateway is running — SQLite WAL-safe copy
sqlite3 /var/lib/vnox/vnox.db ".backup /backup/vnox-$(date +%Y%m%d).db"
# Or stop gateway first for a simple copy
systemctl stop vnox-gateway
cp /var/lib/vnox/vnox.db /backup/vnox-$(date +%Y%m%d).db
systemctl start vnox-gateway
```
### Restore
```bash
systemctl stop vnox-gateway vnox-voice-node
cp /backup/vnox-node-20260101.key /var/lib/vnox/node.key
cp /backup/vnox-20260101.db /var/lib/vnox/vnox.db
chown vnox:vnox /var/lib/vnox/node.key /var/lib/vnox/vnox.db
chmod 600 /var/lib/vnox/node.key
systemctl start vnox-gateway vnox-voice-node
```
---
## Upgrades
### Check current version
```bash
vnox-gateway --version
# VNOX Gateway 0.2.0 (LNEx v1)
```
### Docker upgrade
```bash
docker compose pull
docker compose up -d
```
### systemd upgrade
```bash
# Download new binary
VERSION=0.2.0
curl -L https://github.com/vnox/vnox/releases/download/v${VERSION}/vnox-linux-x86_64.tar.gz \
| tar xz -C /tmp/vnox-upgrade/
# Validate config against new binary
/tmp/vnox-upgrade/vnox-gateway --config /etc/vnox/config.toml --check
# Replace binaries
systemctl stop vnox-gateway vnox-voice-node
cp /tmp/vnox-upgrade/vnox-gateway /usr/local/bin/
cp /tmp/vnox-upgrade/vnox-voice-node /usr/local/bin/
systemctl start vnox-gateway vnox-voice-node
```
### LNEx protocol upgrades
When a new LNEx version is released:
- old clients can still connect if the gateway supports multiple versions
- the gateway advertises supported versions in `HELLO`
- both sides negotiate the highest mutually supported version
- a grace period is announced before old versions are dropped
Breaking changes in LNEx are rare and will be documented in the changelog
with a migration guide.
---
## Security hardening checklist
- [ ] Gateway runs as unprivileged user (`vnox`, not root)
- [ ] `node.key` is `chmod 600`, owned by `vnox`
- [ ] Metrics endpoint is not exposed publicly (bound to `127.0.0.1`)
- [ ] Firewall: only TCP 7600 and UDP 7700 are open externally
- [ ] Log retention policy configured (rotate logs, don't fill disk)
- [ ] `node.key` backup exists and is stored securely
- [ ] `VNOX_LOGGING_LEVEL` is `info` or `warn` in production (not `trace`)
- [ ] `[gateway.rate_limits]` are configured appropriately for your user base
- [ ] TLS certificate is valid (or TOFU is acceptable for your use case)
- [ ] Federation disabled if not needed (`[federation] enabled = false`)