# Hetzner Setup Guide

This guide walks through setting up Hetzner Cloud infrastructure for running Shardok on-demand compute.

## Prerequisites

- All code PRs merged (#4990, #4996, #4998, #5001, #5009)
- Access to DigitalOcean Container Registry (for pulling Shardok ARM64 image)

---

## Step 1: Create Hetzner Cloud Account

1. Go to https://console.hetzner.cloud/
2. Sign up and add payment method
3. Create a new project (e.g., "eagle0")

---

## Step 2: Generate Hetzner API Token

1. In Hetzner Console → Security → API Tokens
2. Click "Generate API Token"
3. Give it **Read & Write** permissions
4. Copy the token (you'll only see it once)

---

## Step 3: Generate Shardok Auth Token

Generate a 256-bit random token for Eagle-Shardok authentication:

```bash
openssl rand -hex 32
```

Save this output - it's the shared secret between Eagle and Shardok.

---

## Step 4: Store Secrets in GitHub Actions

Add these secrets in GitHub → Settings → Secrets and variables → Actions:

| Secret Name | Description |
|-------------|-------------|
| `HETZNER_API_TOKEN` | From Step 2 - for Hetzner API calls |
| `SHARDOK_AUTH_TOKEN` | From Step 3 - shared secret for gRPC auth |

Note: `DO_REGISTRY_TOKEN` already exists and will be used for Hetzner to pull container images.

These secrets will be passed to Eagle at runtime via `docker_build.yml`, similar to how `OPENAI_API_KEY` and other secrets are handled.

---

## Step 5: DNS Setup (for Let's Encrypt)

You need a domain pointing to the Shardok instance for TLS certificates.

### Option A: Floating IP (Recommended)

1. In Hetzner Console → Networking → Floating IPs
2. Create a **Floating IPv6** in **Hillsboro, Oregon (hil)** region
   - IPv6 costs €1/month vs €3/month for IPv4
   - Hillsboro has better latency to DigitalOcean SFO than Ashburn
   - Server-to-server communication works fine with IPv6-only
3. Point `shardok.prod.eagle0.net` to this IP via AAAA record
4. The ShardokInstanceManager will attach this IP to instances on spin-up

**Location choice**: Hillsboro, OR (`hil`) is recommended for US West Coast. Same pricing as Ashburn (`ash`).

### Option B: Dynamic DNS

Update DNS programmatically when instance spins up. More complex but avoids floating IP cost.

---

## Step 6: Upload SSH Key to Hetzner

For debugging access to instances:

1. In Hetzner Console → Security → SSH Keys
2. Click "Add SSH Key"
3. Paste your public key (e.g., `~/.ssh/id_rsa.pub`)
4. Give it a name (e.g., "eagle-deploy")

---

## Step 7: Wire Security Config into Eagle

Update Eagle's startup code to use the security config when connecting to remote Shardok:

```scala
val securityConfig = ShardokSecurityConfig(
  useTls = true,
  authToken = Some(sys.env("SHARDOK_AUTH_TOKEN"))
)

val channel = ServerSetupHelpers.newChannel(
  "shardok.prod.eagle0.net",
  50051,
  securityConfig
)
```

---

## Testing

### Manual Instance Spin-up

Test the Hetzner integration by triggering instance creation:

```scala
val manager = new ShardokInstanceManager(
  hetznerApiToken = sys.env("HETZNER_API_TOKEN"),
  // ... other config
)

manager.ensureInstanceRunning()
```

### Verify TLS and Auth

1. Instance spins up and gets Let's Encrypt certificate
2. Eagle connects via TLS
3. Auth token is validated on each request

---

## Cost Estimate

| Component | Cost |
|-----------|------|
| CAX41 (16 ARM cores) | ~$0.04/hour |
| Floating IP | ~$4/month |
| Typical usage (20 hrs/week) | ~$3.50/month compute |

**Total: ~$7-8/month** for typical usage.

---

## Troubleshooting

### Instance won't start
- Check Hetzner API token has Read & Write permissions
- Verify you're using the correct region (`hil` for Hillsboro OR, or `ash` for Ashburn VA)

### TLS certificate fails
- Ensure DNS points to the instance IP before certbot runs
- Check port 80 is open for Let's Encrypt HTTP-01 challenge

### Auth failures
- Verify `SHARDOK_AUTH_TOKEN` matches on both Eagle and Shardok
- Check the token file is readable by Shardok container

### Can't pull container image
- Ensure `DO_REGISTRY_TOKEN` is passed to cloud-init
- Verify the ARM64 image exists: `registry.digitalocean.com/eagle0/shardok-server:arm64-latest`
