Deploy the Relay Server
Deploy the Relay Server
This guide assumes you have a Linux server with Docker and Docker Compose installed. If not, install them first: docs.docker.com/engine/install.
Get the code
Clone the repository to your server:
git clone https://github.com/your-org/proto.git
cd proto/infra/relay
Configure
Copy the example environment file:
cp .env.example .env
Edit .env:
# The public URL your relay is reachable at.
# If using Tor, this will be your .onion address (set after tor setup).
RELAY_BASE_URL=https://your-server.example.com
# The name shown on the invitation landing page.
APP_NAME=My Family Tree
# Token expiry in hours. 72 hours is the default.
TOKEN_TTL_HOURS=72
# Port the relay listens on inside the container.
# You do not need to change this unless you have a port conflict.
RELAY_PORT=3000
Start the relay
docker compose up -d
Check that it is running:
curl http://localhost:3000/health
Expected response:
{ "status": "ok" }
Test a token flow
Post a test token:
curl -s -X POST http://localhost:3000/api/token \
-H "Content-Type: application/json" \
-d '{"ciphertext":"dGVzdA","ttlHours":1}' | jq
You should receive a response with an invite URL.
Claim the token:
curl -s http://localhost:3000/api/invite/<token-from-above> | jq
The ciphertext should be returned and the token deleted. Claiming again should return a 404.
Expose the relay
If you want HTTPS with a domain name, set up Caddy in front of the relay:
# Add to docker-compose.yml under services:
caddy:
image: caddy:alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- caddy-data:/data
# Caddyfile
your-server.example.com {
reverse_proxy relay:3000
}
For Tor configuration (recommended over public HTTPS), see Configure Tor Hidden Service.
Logs
The relay logs nothing about tokens or IP addresses by design. The only log output is startup confirmation and health check responses.
To view operational logs:
docker compose logs -f relay
Stop and restart
docker compose down # stop
docker compose up -d # start
Token data lives in memory. Pending tokens are lost on restart. This is intentional — restart clears all pending invitations. Tell your users to regenerate any pending links after a server restart.
Update
git pull
docker compose build
docker compose up -d
Self-Hosting Overview
What it means to run your own relay server, why you might want to, and what is required.
Configure Tor Hidden Service
How to make your relay reachable only via a .onion address. Nobody sees the server's IP — not the user, not their ISP, not the platform they use to share the link.