# AWS Deployment Guide for QuinkGL Tunnel Server

Complete guide to deploy the tunnel server on AWS EC2 for NAT traversal.

## Prerequisites

- AWS account
- AWS CLI installed (`brew install awscli`)
- SSH client

## Step 1: Configure AWS CLI

```bash
# Configure AWS credentials
aws configure

# You'll be prompted for:
# - AWS Access Key ID: [Your access key]
# - AWS Secret Access Key: [Your secret key]
# - Default region name: us-east-1 (or your preferred region)
# - Default output format: json
```

## Step 2: Create Security Group

```bash
# Create security group
aws ec2 create-security-group \
  --group-name quinkgl-tunnel \
  --description "QuinkGL Tunnel Server Security Group"

# Allow SSH (port 22)
aws ec2 authorize-security-group-ingress \
  --group-name quinkgl-tunnel \
  --protocol tcp \
  --port 22 \
  --cidr 0.0.0.0/0

# Allow gRPC tunnel port (50051)
aws ec2 authorize-security-group-ingress \
  --group-name quinkgl-tunnel \
  --protocol tcp \
  --port 50051 \
  --cidr 0.0.0.0/0
```

## Step 3: Create SSH Key Pair

```bash
# Create key pair
aws ec2 create-key-pair \
  --key-name quinkgl-tunnel-key \
  --query 'KeyMaterial' \
  --output text > ~/.ssh/quinkgl-tunnel-key.pem

# Set permissions
chmod 400 ~/.ssh/quinkgl-tunnel-key.pem
```

## Step 4: Launch EC2 Instance

```bash
# Find Ubuntu 22.04 AMI ID for your region
# For us-east-1: ami-0c55b159cbfafe1f0
# For eu-west-1: ami-0d71ea30463e0ff8d

# Launch t2.micro instance (free tier)
aws ec2 run-instances \
  --image-id ami-0c55b159cbfafe1f0 \
  --instance-type t2.micro \
  --key-name quinkgl-tunnel-key \
  --security-groups quinkgl-tunnel \
  --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=QuinkGL-Tunnel}]'

# Wait for instance to be running
aws ec2 wait instance-running \
  --filters "Name=tag:Name,Values=QuinkGL-Tunnel"

# Get instance public IP
INSTANCE_IP=$(aws ec2 describe-instances \
  --filters "Name=tag:Name,Values=QuinkGL-Tunnel" "Name=instance-state-name,Values=running" \
  --query 'Reservations[0].Instances[0].PublicIpAddress' \
  --output text)

echo "Instance IP: $INSTANCE_IP"
```

## Step 5: Deploy Tunnel Server

### 5.1 Connect to Instance

```bash
# SSH to instance
ssh -i ~/.ssh/quinkgl-tunnel-key.pem ubuntu@$INSTANCE_IP
```

### 5.2 Install Dependencies (on EC2)

```bash
# Update system
sudo apt update
sudo apt upgrade -y

# Install Python and pip
sudo apt install -y python3 python3-pip git

# Install gRPC
pip3 install grpcio grpcio-tools protobuf numpy
```

### 5.3 Upload Project Files (from local machine)

```bash
# Create deployment package
cd /Users/aliseyhan/Desktop/QuinkGL
tar -czf tunnel-deploy.tar.gz \
  tunnel_server.py \
  protos/tunnel.proto \
  quinkgl/network/tunnel_pb2.py \
  quinkgl/network/tunnel_pb2_grpc.py \
  quinkgl/__init__.py \
  quinkgl/network/__init__.py

# Upload to EC2
scp -i ~/.ssh/quinkgl-tunnel-key.pem tunnel-deploy.tar.gz ubuntu@$INSTANCE_IP:~

# SSH back to EC2 and extract
ssh -i ~/.ssh/quinkgl-tunnel-key.pem ubuntu@$INSTANCE_IP
cd ~
tar -xzf tunnel-deploy.tar.gz

# Recompile Protobufs (Crucial for new P2P messages)
python3 -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. protos/tunnel.proto

# Fix imports in generated files (if needed, similar to Dockerfile)
sed -i 's/import tunnel_pb2 as tunnel__pb2/from . import tunnel_pb2 as tunnel__pb2/' quinkgl/network/tunnel_pb2_grpc.py
```

### 5.4 Run Tunnel Server (on EC2)

```bash
# Run in foreground (for testing)
python3 tunnel_server.py --host 0.0.0.0 --port 50051

# Or run in background with nohup
nohup python3 tunnel_server.py --host 0.0.0.0 --port 50051 > tunnel.log 2>&1 &

# Check logs
tail -f tunnel.log
```

### 5.5 Setup as Systemd Service (Optional - Recommended)

```bash
# Create systemd service file
sudo tee /etc/systemd/system/quinkgl-tunnel.service > /dev/null <<EOF
[Unit]
Description=QuinkGL Tunnel Server
After=network.target

[Service]
Type=simple
User=ubuntu
WorkingDirectory=/home/ubuntu
ExecStart=/usr/bin/python3 /home/ubuntu/tunnel_server.py --host 0.0.0.0 --port 50051
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target
EOF

# Enable and start service
sudo systemctl daemon-reload
sudo systemctl enable quinkgl-tunnel
sudo systemctl start quinkgl-tunnel

# Check status
sudo systemctl status quinkgl-tunnel

# View logs
sudo journalctl -u quinkgl-tunnel -f
```

## Step 6: Test Tunnel Connection

### 6.1 Test from Local Machine

```bash
# Terminal 1: Start local node with tunnel
python3 run_node.py \
  --port 50051 \
  --node-id nodeA \
  --tunnel $INSTANCE_IP:50051

# Terminal 2: Start another local node
python3 run_node.py \
  --port 50052 \
  --node-id nodeB \
  --tunnel $INSTANCE_IP:50051 \
  --tunnel-peers nodeA
```

### 6.2 Test from Different Networks

```bash
# On Computer 1 (e.g., home network):
python3 run_node.py \
  --port 50051 \
  --node-id home-node \
  --tunnel $INSTANCE_IP:50051

# On Computer 2 (e.g., mobile hotspot):
python3 run_node.py \
  --port 50051 \
  --node-id mobile-node \
  --tunnel $INSTANCE_IP:50051 \
  --tunnel-peers home-node
```

You should see:
```
✓ Connected to tunnel server
Tunnel peer list updated: ['home-node']
Sent weight update to 'home-node' via tunnel
✓ Received and merged weights from home-node
```

## Step 7: Monitoring and Maintenance

### Check Server Status

```bash
# SSH to EC2
ssh -i ~/.ssh/quinkgl-tunnel-key.pem ubuntu@$INSTANCE_IP

# Check service status
sudo systemctl status quinkgl-tunnel

# View recent logs
sudo journalctl -u quinkgl-tunnel -n 100

# Monitor in real-time
sudo journalctl -u quinkgl-tunnel -f
```

### Restart Server

```bash
sudo systemctl restart quinkgl-tunnel
```

### Update Server Code (For P2P Signaling Support)

```bash
# From local machine, create new package
cd /Users/aliseyhan/Desktop/QuinkGL
tar -czf tunnel-deploy.tar.gz tunnel_server.py protos/ quinkgl/network/tunnel_pb2* quinkgl/__init__.py quinkgl/network/__init__.py

# Upload
scp -i ~/.ssh/quinkgl-tunnel-key.pem tunnel-deploy.tar.gz ubuntu@$INSTANCE_IP:~

# On EC2, extract, recompile and restart
ssh -i ~/.ssh/quinkgl-tunnel-key.pem ubuntu@$INSTANCE_IP
tar -xzf tunnel-deploy.tar.gz

# Recompile protobufs to ensure new message types (SDP_OFFER, etc.) are available
python3 -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. protos/tunnel.proto

# Restart service
sudo systemctl restart quinkgl-tunnel
```

## Step 8: Cost Management

### Free Tier Limits (First 12 Months)

- **EC2**: 750 hours/month of t2.micro (enough for 1 instance 24/7)
- **Bandwidth**: 15GB/month outbound (sufficient for testing)
- **Storage**: 30GB EBS

### After Free Tier

- **t2.micro**: ~$8/month
- **Bandwidth**: $0.09/GB
- **Estimated total**: $10-15/month for light usage

### Stop Instance When Not Needed

```bash
# Stop instance (keeps data, stops charges)
aws ec2 stop-instances \
  --instance-ids $(aws ec2 describe-instances \
    --filters "Name=tag:Name,Values=QuinkGL-Tunnel" \
    --query 'Reservations[0].Instances[0].InstanceId' \
    --output text)

# Start instance again
aws ec2 start-instances \
  --instance-ids $(aws ec2 describe-instances \
    --filters "Name=tag:Name,Values=QuinkGL-Tunnel" \
    --query 'Reservations[0].Instances[0].InstanceId' \
    --output text)

# Get new IP after restart
INSTANCE_IP=$(aws ec2 describe-instances \
  --filters "Name=tag:Name,Values=QuinkGL-Tunnel" "Name=instance-state-name,Values=running" \
  --query 'Reservations[0].Instances[0].PublicIpAddress' \
  --output text)
```

**Note**: Public IP changes when you stop/start. Use Elastic IP for static IP (free if instance is running).

## Step 9: Cleanup (When Done)

```bash
# Terminate instance
aws ec2 terminate-instances \
  --instance-ids $(aws ec2 describe-instances \
    --filters "Name=tag:Name,Values=QuinkGL-Tunnel" \
    --query 'Reservations[0].Instances[0].InstanceId' \
    --output text)

# Delete security group
aws ec2 delete-security-group --group-name quinkgl-tunnel

# Delete key pair
aws ec2 delete-key-pair --key-name quinkgl-tunnel-key
rm ~/.ssh/quinkgl-tunnel-key.pem
```

## Troubleshooting

### Can't Connect to Tunnel Server

```bash
# Check security group allows port 50051
aws ec2 describe-security-groups --group-names quinkgl-tunnel

# Test connection
telnet $INSTANCE_IP 50051

# Check server logs
ssh -i ~/.ssh/quinkgl-tunnel-key.pem ubuntu@$INSTANCE_IP
sudo journalctl -u quinkgl-tunnel -n 50
```

### Tunnel Server Not Starting

```bash
# Check Python and dependencies
python3 --version
pip3 list | grep grpc

# Run manually to see errors
python3 tunnel_server.py --host 0.0.0.0 --port 50051
```

### High Costs

- Stop instance when not testing
- Monitor bandwidth usage in AWS Console
- Consider using Elastic IP to avoid IP changes

## Quick Reference

```bash
# Get instance IP
aws ec2 describe-instances \
  --filters "Name=tag:Name,Values=QuinkGL-Tunnel" "Name=instance-state-name,Values=running" \
  --query 'Reservations[0].Instances[0].PublicIpAddress' \
  --output text

# SSH to instance
ssh -i ~/.ssh/quinkgl-tunnel-key.pem ubuntu@$(aws ec2 describe-instances \
  --filters "Name=tag:Name,Values=QuinkGL-Tunnel" "Name=instance-state-name,Values=running" \
  --query 'Reservations[0].Instances[0].PublicIpAddress' \
  --output text)

# Check tunnel server status
sudo systemctl status quinkgl-tunnel

# View logs
sudo journalctl -u quinkgl-tunnel -f
```
