CipherFS
In development · unreleased · format may change

Relay setup

This guide explains how to set up your own iroh relay server for CipherFS P2P synchronization.

Why Self-Host a Relay?

Advantages

  • ✅ Privacy - All traffic goes through your own infrastructure
  • ✅ Control - Full control over relay configuration and policies
  • ✅ Compliance - Meet data sovereignty requirements
  • ✅ Performance - Deploy closer to your users
  • ✅ No limits - No usage limits or throttling

Disadvantages

  • ❌ Maintenance - You need to maintain and monitor the server
  • ❌ Cost - Server hosting costs
  • ❌ Availability - You're responsible for uptime

Quick Start

Option 1: Use Docker (Recommended)

# Clone the relay repository
git clone https://github.com/n0-computer/iroh
cd iroh

# Build the relay Docker image
docker build -t iroh-relay -f crates/iroh-net/Dockerfile .

# Run the relay server
docker run -d \
  --name iroh-relay \
  -p 443:443 \
  -p 3478:3478 \
  -v /var/lib/iroh-relay:/data \
  -e RUST_LOG=info \
  iroh-relay

# Check logs
docker logs -f iroh-relay

Option 2: Build from Source

# Install Rust
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

# Clone and build
git clone https://github.com/n0-computer/iroh
cd iroh
cargo build --release --bin iroh-relay

# Run the relay
./target/release/iroh-relay

Configuration

Environment Variables

VariableDescriptionDefault
IROH_RELAY_PORTQUIC relay port443
IROH_STUN_PORTSTUN port for hole punching3478
RUST_LOGLog levelinfo
IROH_RELAY_ADDRPublic address to advertiseAuto-detected

Example Configuration

# /etc/iroh-relay/config.sh
export IROH_RELAY_PORT=443
export IROH_STUN_PORT=3478
export RUST_LOG=iroh_relay=debug
export IROH_RELAY_ADDR=relay.example.com

Production Deployment

Using Docker Compose

Create docker-compose.yml:

version: '3.8'

services:
  iroh-relay:
    image: iroh-relay:latest
    container_name: iroh-relay
    restart: unless-stopped

    ports:
      - "443:443"   # QUIC relay
      - "3478:3478" # STUN

    volumes:
      - relay-data:/data
      - ./logs:/var/log/iroh

    environment:
      - RUST_LOG=info
      - IROH_RELAY_ADDR=relay.yourdomain.com

    # Resource limits
    deploy:
      resources:
        limits:
          cpus: '2'
          memory: 4G
        reservations:
          cpus: '0.5'
          memory: 512M

    # Health check
    healthcheck:
      test: ["CMD", "nc", "-z", "localhost", "443"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s

    # Logging
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"

volumes:
  relay-data:

Deploy:

docker-compose up -d

Using systemd

Create /etc/systemd/system/iroh-relay.service:

[Unit]
Description=Iroh Relay Server
After=network.target

[Service]
Type=simple
User=iroh
Group=iroh

WorkingDirectory=/var/lib/iroh-relay
ExecStart=/usr/local/bin/iroh-relay

Restart=always
RestartSec=10

# Security
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true

# Resource limits
LimitNOFILE=65536
MemoryMax=4G

# Logging
StandardOutput=journal
StandardError=journal
SyslogIdentifier=iroh-relay

[Install]
WantedBy=multi-user.target

Enable and start:

sudo systemctl daemon-reload
sudo systemctl enable iroh-relay
sudo systemctl start iroh-relay
sudo systemctl status iroh-relay

Firewall Configuration

Required Ports

# Allow QUIC relay (UDP/TCP)
sudo ufw allow 443/tcp
sudo ufw allow 443/udp

# Allow STUN (UDP)
sudo ufw allow 3478/udp

Using firewalld

sudo firewall-cmd --permanent --add-port=443/tcp
sudo firewall-cmd --permanent --add-port=443/udp
sudo firewall-cmd --permanent --add-port=3478/udp
sudo firewall-cmd --reload

TLS Certificate

Using Let's Encrypt (Recommended)

# Install certbot
sudo apt install certbot

# Obtain certificate
sudo certbot certonly --standalone -d relay.yourdomain.com

# Certificate location:
# /etc/letsencrypt/live/relay.yourdomain.com/fullchain.pem
# /etc/letsencrypt/live/relay.yourdomain.com/privkey.pem

Configure relay to use certificates:

export IROH_RELAY_CERT=/etc/letsencrypt/live/relay.yourdomain.com/fullchain.pem
export IROH_RELAY_KEY=/etc/letsencrypt/live/relay.yourdomain.com/privkey.pem

Auto-renewal

# Test renewal
sudo certbot renew --dry-run

# Certbot automatically sets up cron job
# Verify: cat /etc/cron.d/certbot

Monitoring

Health Check

# Check if relay is listening
nc -zv relay.yourdomain.com 443

# Check STUN
nc -zv relay.yourdomain.com 3478

Metrics

iroh-relay exposes metrics on /metrics endpoint (Prometheus format):

# prometheus.yml
scrape_configs:
  - job_name: 'iroh-relay'
    static_configs:
      - targets: ['relay.yourdomain.com:443']
    metrics_path: /metrics

Logging

# View logs
docker logs -f iroh-relay

# Or with systemd
journalctl -u iroh-relay -f

CipherFS Configuration

Using Your Relay

Update your CipherFS configuration:

use cipherfs_sync::iroh_p2p::{IrohNode, RelayConfig};

// Use your custom relay
let relay_config = RelayConfig::custom_relay(
    "https://relay.yourdomain.com:443".to_string()
);

let node = IrohNode::new_with_config(
    "/path/to/vault",
    relay_config
).await?;

CLI Usage

# Set custom relay
cipherfs config set relay.url "https://relay.yourdomain.com:443"

# Verify
cipherfs config get relay.url

Performance Tuning

Server Requirements

Minimum:

  • CPU: 2 cores
  • RAM: 2 GB
  • Network: 100 Mbps
  • Storage: 20 GB

Recommended (100+ concurrent connections):

  • CPU: 4-8 cores
  • RAM: 4-8 GB
  • Network: 1 Gbps
  • Storage: 50 GB SSD

Optimizations

# Increase UDP buffer sizes
sudo sysctl -w net.core.rmem_max=134217728
sudo sysctl -w net.core.wmem_max=134217728

# Make persistent
cat >> /etc/sysctl.conf <<EOF
net.core.rmem_max=134217728
net.core.wmem_max=134217728
net.core.rmem_default=262144
net.core.wmem_default=262144
EOF

sudo sysctl -p

Security Best Practices

  1. Use TLS - Always use HTTPS for relay connections
  2. Limit Resources - Set CPU/memory limits
  3. Monitor Usage - Track connections and bandwidth
  4. Update Regularly - Keep iroh-relay updated
  5. Backup Configuration - Backup certificates and keys
  6. Isolate - Run in separate container/VM

Troubleshooting

Relay Not Starting

# Check logs
docker logs iroh-relay

# Common issues:
# - Port already in use: sudo lsof -i :443
# - Permission denied: Run with appropriate user
# - Certificate missing: Check cert paths

Clients Cannot Connect

# Test relay connectivity
telnet relay.yourdomain.com 443

# Check firewall
sudo ufw status

# Verify DNS
nslookup relay.yourdomain.com

# Test from client machine
curl -v https://relay.yourdomain.com:443

High CPU Usage

# Check connection count
docker exec iroh-relay netstat -an | grep :443 | wc -l

# Limit connections if needed
# (requires iroh-relay restart with connection limit config)

Cost Estimation

Hosting Options

ProviderPlanCost/MonthSuitable For
DigitalOcean4GB/2CPU$24Small team (10-50 users)
AWSt3.large$60Medium team (50-200 users)
GCPe2-standard-4$120Large team (200+ users)
Linode8GB/4CPU$48Medium-large team

Bandwidth

Estimate based on usage:

  • Light (10 users, <1GB/day): ~10GB/month
  • Medium (100 users, 10GB/day): ~300GB/month
  • Heavy (1000 users, 100GB/day): ~3TB/month

Alternatives

Use n0.network (Free)

If you don't want to self-host, use the default n0.network relay:

// Default (no configuration needed)
let node = IrohNode::new("/path/to/vault").await?;

Use Tailscale

Tailscale provides built-in DERP relay servers:

# Install Tailscale on all devices
# No relay configuration needed
# Tailscale handles everything

References


Last updated: 2026-01-14

Source file in the repository