# Self-Hosted Relay Server Guide

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)

```bash
# 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

```bash
# 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

| Variable | Description | Default |
|----------|-------------|---------|
| `IROH_RELAY_PORT` | QUIC relay port | `443` |
| `IROH_STUN_PORT` | STUN port for hole punching | `3478` |
| `RUST_LOG` | Log level | `info` |
| `IROH_RELAY_ADDR` | Public address to advertise | Auto-detected |

### Example Configuration

```bash
# /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`:

```yaml
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:

```bash
docker-compose up -d
```

### Using systemd

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

```ini
[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:

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

---

## Firewall Configuration

### Required Ports

```bash
# 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

```bash
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)

```bash
# 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:

```bash
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

```bash
# Test renewal
sudo certbot renew --dry-run

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

---

## Monitoring

### Health Check

```bash
# 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):

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

### Logging

```bash
# View logs
docker logs -f iroh-relay

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

---

## CipherFS Configuration

### Using Your Relay

Update your CipherFS configuration:

```rust
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

```bash
# 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

```bash
# 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

```bash
# 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

```bash
# 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

```bash
# 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

| Provider | Plan | Cost/Month | Suitable For |
|----------|------|------------|--------------|
| **DigitalOcean** | 4GB/2CPU | $24 | Small team (10-50 users) |
| **AWS** | t3.large | $60 | Medium team (50-200 users) |
| **GCP** | e2-standard-4 | $120 | Large team (200+ users) |
| **Linode** | 8GB/4CPU | $48 | Medium-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:

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

### Use Tailscale

Tailscale provides built-in DERP relay servers:

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

---

## References

- [iroh GitHub](https://github.com/n0-computer/iroh)
- [iroh Documentation](https://docs.iroh.computer/)
- [Relay Server Code](https://github.com/n0-computer/iroh/tree/main/crates/iroh-net/relay)
- [NAT Traversal Guide](https://tailscale.com/blog/how-nat-traversal-works/)

---

*Last updated: 2026-01-14*
