Skip to main content

Fly.io Deployment

This guide covers deploying edgeProxy backends on Fly.io with WireGuard overlay network for global distribution.

Overview

Fly.io Infrastructure

Fly.io provides edge computing with machines in 30+ regions worldwide. We use it to deploy backend servers that connect to the central edgeProxy POP via WireGuard.

Prerequisites

# Install Fly CLI
curl -L https://fly.io/install.sh | sh

# Login to Fly.io
fly auth login

# Verify authentication
fly auth whoami

Available Regions

CodeLocationContinent
gruSao PauloSouth America
iadVirginiaNorth America
ordChicagoNorth America
laxLos AngelesNorth America
lhrLondonEurope
fraFrankfurtEurope
cdgParisEurope
nrtTokyoAsia Pacific
sinSingaporeAsia Pacific
sydSydneyOceania

Project Structure

fly-backend/
├── fly.toml # Fly.io configuration
├── Dockerfile # Multi-stage build with WireGuard
├── main.go # Backend server (Go)
├── entrypoint.sh # WireGuard + backend startup
└── wireguard/
└── keys/ # WireGuard keys per region

Dockerfile

Multi-stage build with WireGuard support:

FROM golang:1.21-alpine AS builder
WORKDIR /app
COPY main.go .
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o backend main.go

FROM alpine:3.19
RUN apk --no-cache add ca-certificates wireguard-tools iptables ip6tables iproute2 bash
WORKDIR /app
COPY --from=builder /app/backend .
COPY entrypoint.sh .
RUN chmod +x entrypoint.sh

EXPOSE 8080
EXPOSE 51820/udp

ENTRYPOINT ["./entrypoint.sh"]

Entrypoint Script

The entrypoint configures WireGuard based on the Fly region:

#!/bin/bash
set -e

# Central edgeProxy endpoint
EC2_ENDPOINT="54.171.48.207:51820"
EC2_PUBKEY="bzM6rw/efq+75VGhBgkCRChDnKfFlXQY560ejhvKCQY="

# Map region to WireGuard IP
case "${FLY_REGION}" in
gru) WG_IP="10.50.1.1/32"; WG_PRIVATE="${WG_KEY_GRU}" ;;
iad) WG_IP="10.50.2.1/32"; WG_PRIVATE="${WG_KEY_IAD}" ;;
ord) WG_IP="10.50.2.2/32"; WG_PRIVATE="${WG_KEY_ORD}" ;;
lax) WG_IP="10.50.2.3/32"; WG_PRIVATE="${WG_KEY_LAX}" ;;
lhr) WG_IP="10.50.3.1/32"; WG_PRIVATE="${WG_KEY_LHR}" ;;
fra) WG_IP="10.50.3.2/32"; WG_PRIVATE="${WG_KEY_FRA}" ;;
cdg) WG_IP="10.50.3.3/32"; WG_PRIVATE="${WG_KEY_CDG}" ;;
nrt) WG_IP="10.50.4.1/32"; WG_PRIVATE="${WG_KEY_NRT}" ;;
sin) WG_IP="10.50.4.2/32"; WG_PRIVATE="${WG_KEY_SIN}" ;;
syd) WG_IP="10.50.4.3/32"; WG_PRIVATE="${WG_KEY_SYD}" ;;
*) echo "Unknown region: ${FLY_REGION}"; exit 1 ;;
esac

# Create WireGuard config
mkdir -p /etc/wireguard
cat > /etc/wireguard/wg0.conf << EOF
[Interface]
PrivateKey = ${WG_PRIVATE}
Address = ${WG_IP}

[Peer]
PublicKey = ${EC2_PUBKEY}
Endpoint = ${EC2_ENDPOINT}
AllowedIPs = 10.50.0.0/16
PersistentKeepalive = 25
EOF

# Start WireGuard
wg-quick up wg0

echo "WireGuard connected: ${FLY_REGION} -> ${WG_IP}"

# Start backend
exec ./backend

fly.toml Configuration

app = "edgeproxy-backend"
primary_region = "gru"

[build]
dockerfile = "Dockerfile"

[env]
PORT = "8080"

[http_service]
internal_port = 8080
force_https = false
auto_stop_machines = false
auto_start_machines = true
min_machines_running = 1

[[vm]]
cpu_kind = "shared"
cpus = 1
memory_mb = 256

WireGuard Keys Setup

Generate Keys

# Generate key pair for each region
for region in gru iad ord lax lhr fra cdg nrt sin syd; do
wg genkey > wireguard/keys/${region}-private.key
cat wireguard/keys/${region}-private.key | wg pubkey > wireguard/keys/${region}-public.key
done

Set Secrets in Fly.io

# Set WireGuard private keys as secrets
fly secrets set \
WG_KEY_GRU="$(cat wireguard/keys/gru-private.key)" \
WG_KEY_IAD="$(cat wireguard/keys/iad-private.key)" \
WG_KEY_ORD="$(cat wireguard/keys/ord-private.key)" \
WG_KEY_LAX="$(cat wireguard/keys/lax-private.key)" \
WG_KEY_LHR="$(cat wireguard/keys/lhr-private.key)" \
WG_KEY_FRA="$(cat wireguard/keys/fra-private.key)" \
WG_KEY_CDG="$(cat wireguard/keys/cdg-private.key)" \
WG_KEY_NRT="$(cat wireguard/keys/nrt-private.key)" \
WG_KEY_SIN="$(cat wireguard/keys/sin-private.key)" \
WG_KEY_SYD="$(cat wireguard/keys/syd-private.key)"

Deployment

Create App

cd fly-backend

# Create new app
fly apps create edgeproxy-backend

# Or launch interactively
fly launch --no-deploy

Deploy to All Regions

# Deploy application
fly deploy --remote-only

# Scale to multiple regions (1 machine per region)
fly scale count 1 --region gru,iad,ord,lax,lhr,fra,cdg,nrt,sin,syd

# Verify deployment
fly status

Scale Individual Regions

# Add more machines to specific region
fly scale count 2 --region gru

# Remove machines from region
fly scale count 0 --region lax

Monitoring

Check Status

# Application status
fly status

# List all machines
fly machines list

# View logs
fly logs

# Logs from specific region
fly logs --region gru

SSH into Machine

# SSH to random machine
fly ssh console

# SSH to specific region
fly ssh console --region gru

# Check WireGuard status inside
wg show

Health Check

# Test specific region
curl https://edgeproxy-backend.fly.dev/api/info

# Test via edgeProxy (should route to nearest backend)
curl http://54.171.48.207:8080/api/info

Troubleshooting

WireGuard Not Connecting

# SSH into machine
fly ssh console

# Check WireGuard status
wg show

# Check if interface exists
ip addr show wg0

# Check logs
cat /var/log/wireguard.log

Machine Not Starting

# Check machine logs
fly logs --instance <machine-id>

# Restart machine
fly machines restart <machine-id>

# Destroy and recreate
fly machines destroy <machine-id>
fly scale count 1 --region <region>

Secrets Not Set

# List secrets
fly secrets list

# Set missing secret
fly secrets set WG_KEY_GRU="<private-key>"

Cost Optimization

Shared CPU Machines

[[vm]]
cpu_kind = "shared"
cpus = 1
memory_mb = 256 # Minimum for WireGuard

Auto-Stop Idle Machines

[http_service]
auto_stop_machines = true
auto_start_machines = true
min_machines_running = 0 # Scale to zero when idle