Deploy a Relay
Prerequisites
- Rust toolchain (1.75+)
- Linux server with a public IP
- UDP port 4433 open (QUIC transport)
- TCP port 8443 open (HTTP health check)
- TCP port 5000 open (gRPC DataPlaneService)
Build from source
git clone https://github.com/nicholasraimbault/static.gitcd staticcargo build --release -p static-supernodeThe binary is at target/release/static-supernode.
Configure
Create supernode.toml:
[server]listen_port = 4433data_dir = "/opt/static/data"health_listen_addr = "0.0.0.0:8443"grpc_listen_addr = "0.0.0.0:5000"jwt_secret = "your-hs256-secret-here"message_ttl_days = 7
[privacy]batch_interval_ms = 500accept_direct_connections = false
[limits]max_connections = 256max_channels = 64max_message_size = 1048576Configuration reference
| Section | Field | Default | Description |
|---|---|---|---|
server | listen_port | 4433 | QUIC transport port |
server | data_dir | ./data | Persistent data directory |
server | health_listen_addr | 0.0.0.0:8443 | HTTP health endpoint |
server | grpc_listen_addr | (none) | gRPC address — set to enable SLIM interface |
server | jwt_secret | (none) | HS256 secret for JWT auth — set to enable authentication |
server | grpc_tls_cert | (none) | Path to PEM TLS certificate for gRPC |
server | grpc_tls_key | (none) | Path to PEM TLS private key for gRPC |
server | message_ttl_days | 7 | Days to retain archived messages |
privacy | batch_interval_ms | 500 | Message batching interval (0 to disable) |
privacy | accept_direct_connections | false | Accept non-relay QUIC connections |
limits | max_connections | 256 | Maximum concurrent connections |
limits | max_channels | 64 | Maximum channels |
limits | max_message_size | 262144 | Maximum message payload (bytes) |
Enabling TLS on gRPC
To secure the gRPC endpoint with TLS, add both cert and key paths:
[server]grpc_tls_cert = "/etc/ssl/relay.crt"grpc_tls_key = "/etc/ssl/relay.key"Both fields must be set together. When configured, the gRPC server terminates TLS. Agents connect via https:// instead of http://.
Run
./static-supernode --config supernode.tomlCLI options:
| Flag | Default | Description |
|---|---|---|
-c, --config | supernode.toml | Config file path |
-p, --port | (from config) | Override QUIC listen port |
--log-level | info | Log level (trace, debug, info, warn, error) |
--drain-timeout | 60 | Seconds to drain connections on graceful restart |
Verify
-
HTTP health check
Terminal window curl http://localhost:8443/health# {"status":"ok","uptime":42} -
gRPC health check
Terminal window grpcurl -plaintext localhost:5000 grpc.health.v1.Health/Check# { "status": "SERVING" } -
gRPC reflection (list available services)
Terminal window grpcurl -plaintext localhost:5000 list# dataplane.proto.v1.DataPlaneService# grpc.health.v1.Health# grpc.reflection.v1.ServerReflection
gRPC services
When grpc_listen_addr is set, the relay serves three gRPC services:
| Service | Description |
|---|---|
DataPlaneService | SLIM bidirectional streaming (Subscribe, Publish, Unsubscribe) |
grpc.health.v1.Health | Standard health check — reports DataPlaneService as SERVING |
grpc.reflection.v1.ServerReflection | Schema discovery — agents introspect the API at runtime |
Systemd
Example unit file:
[Unit]Description=Skytale RelayAfter=network-online.targetWants=network-online.target
[Service]Type=simpleUser=staticExecStart=/opt/static/bin/static-supernode --config /opt/static/config/supernode.tomlRestart=on-failureRestartSec=5LimitNOFILE=65535NoNewPrivileges=yesProtectSystem=strictReadWritePaths=/opt/static/data
[Install]WantedBy=multi-user.targetPoint your SDK at the relay
from static_sdk import StaticClient
client = StaticClient( "https://your-relay:5000", "/tmp/agent", b"my-agent", api_key="sk_live_...", api_url="https://api.skytale.sh",)