🚀
Fly Machines
Keine VMs — schnelle Container-Instanzen global
💾
Persistent Volumes
SQLite in Production — sicher und performant
🔒
Secrets Management
flyctl secrets set — keine .env in Git
🌍
Multi-Region
Fly Postgres + LiteFS weltweit repliziert
Wer 2026 eine Webanwendung deployt, will keine Stunden mit Cloud-Konfigurationen verschwenden. Fly.io hat sich als klarer Favorit für Developer etabliert, die schnell global deployen wollen — ohne Kubernetes, ohne komplexe IAM-Rollen, ohne Load-Balancer-Konfiguration von Hand. Claude Code versteht die gesamte Fly.io-Architektur und kann fly.toml-Dateien, Volume-Setups, Secrets-Konfigurationen und Multi-Region-Postgres-Setups in Minuten generieren.
Dieser Guide zeigt, wie du Claude Code als Deployment-Copiloten für Fly.io einsetzt — von der ersten fly.toml bis zum weltweit replizierten Datenbanksetup.
1. Fly.io Grundlagen — Machines, Regions und flyctl
Fly.io unterscheidet sich fundamental von klassischen Cloud-Providern. Der wichtigste Unterschied: Fly arbeitet mit Machines, nicht mit VMs. Eine Fly Machine ist ein leichtgewichtiger Container, der auf Firecracker-MicroVMs basiert und in Millisekunden startet — ideal für serverlose Workloads und globale Deployments.
Grundlagen Fly.io Architektur-Konzepte
| Konzept |
Beschreibung |
Vergleich |
| Machine |
Container-Instanz auf Firecracker-Basis, startet in <500ms |
AWS Fargate Task, aber schneller |
| App |
Logische Gruppe von Machines mit gemeinsamer Konfiguration |
ECS Service / Heroku App |
| Region |
Fly.io hat 30+ Regionen weltweit (ams, fra, sin, lax ...) |
AWS Availability Zone |
| Volume |
Persistenter Block-Storage, an Machine gebunden |
EBS Volume / Persistent Disk |
| Anycast IP |
Globale IP, Traffic wird zur nächsten Region geroutet |
AWS Global Accelerator |
Erste Schritte mit flyctl
Das CLI-Tool flyctl (auch als fly verfügbar) ist das zentrale Werkzeug für alle Fly.io-Operationen. Claude Code kann flyctl-Befehle generieren und erklären:
# flyctl installieren (macOS)
brew install flyctl
# Linux/WSL
curl -L https://fly.io/install.sh | sh
# Einloggen
fly auth login
# Neue App erstellen und initialisieren
fly launch
# Vorhandene App deployen
fly deploy
# Logs in Echtzeit
fly logs
# SSH in laufende Machine
fly ssh console
# App-Status und Machines anzeigen
fly status
fly machines list
💡 Claude Code Prompt: "Ich habe eine Node.js Express API in diesem Verzeichnis. Erstelle eine vollständige fly.toml Konfiguration mit Health-Check, Auto-Stop und 512MB RAM. Erkläre jeden Parameter."
fly launch — der erste Deploy
fly launch erkennt automatisch die Anwendungsstruktur (Dockerfile, package.json, requirements.txt) und erstellt eine initiale fly.toml. Claude Code kann diesen Prozess weiter optimieren:
# Fly.io erkennt automatisch: Node.js / Python / Go / Ruby / etc.
fly launch --name meine-api --region fra --no-deploy
# Danach fly.toml anpassen, dann deployen
fly deploy --strategy rolling
# Deployment-Strategien:
# rolling — schrittweise, ohne Downtime (Standard)
# bluegreen — parallel deploy, dann Switchover
# canary — X% Traffic auf neue Version
# immediate — sofort, mit möglichem kurzen Ausfall
2. fly.toml Konfiguration — [build], [http_service], [env], [mounts]
Die fly.toml ist die zentrale Konfigurationsdatei für jede Fly.io-Anwendung. Sie definiert Build-Prozess, HTTP-Service, Umgebungsvariablen und Storage. Claude Code versteht die komplette fly.toml-Syntax und kann projektspezifische Konfigurationen generieren.
fly.toml Vollständige Beispiel-Konfiguration (Node.js API)
# fly.toml — generiert mit Claude Code
app = "meine-api"
primary_region = "fra"
kill_signal = "SIGTERM"
kill_timeout = 30
[build]
dockerfile = "Dockerfile"
# Alternativ: Buildpacks ohne Dockerfile
# builder = "heroku/buildpacks:20"
[build.args]
NODE_ENV = "production"
BUILD_VERSION = "2026-05-06"
[env]
PORT = "8080"
NODE_ENV = "production"
LOG_LEVEL = "info"
# Keine Secrets hier! Nur nicht-sensitive Werte
[http_service]
internal_port = 8080
force_https = true
auto_stop_machines = "stop"
auto_start_machines = true
min_machines_running = 0
[http_service.concurrency]
type = "requests"
hard_limit = 250
soft_limit = 200
[[http_service.checks]]
grace_period = "5s"
interval = "30s"
method = "GET"
path = "/health"
protocol = "http"
timeout = "5s"
[[vm]]
memory = "512mb"
cpu_kind = "shared"
cpus = 1
Die [build]-Section im Detail
Der [build]-Block steuert, wie Fly.io deine Anwendung containerisiert:
[build]
# Option 1: Eigenes Dockerfile
dockerfile = "Dockerfile"
# Option 2: Nixpacks (automatische Erkennung)
builder = "nixpacks"
# Option 3: Spezifisches Image aus Registry
image = "ghcr.io/mein-user/meine-app:latest"
[build.args]
# Docker Build-Args (nur für Build-Phase)
PYTHON_VERSION = "3.12"
BUNDLE_WITHOUT = "development:test"
Die [http_service]-Section — Traffic und Auto-Scaling
Fly.io bietet eingebautes Auto-Stop und Auto-Start für Machines — ideal für Anwendungen mit variablem Traffic:
[http_service]
internal_port = 8080
force_https = true
# Auto-Stop: "stop" oder "suspend" (suspend = schneller Restart)
auto_stop_machines = "suspend"
auto_start_machines = true
# Minimum laufende Machines (0 = scale-to-zero)
min_machines_running = 1
# Concurrency-Limits für Load-Balancing
[http_service.concurrency]
type = "connections" # oder "requests"
hard_limit = 100
soft_limit = 80
# Custom Headers
[[http_service.checks]]
grace_period = "10s"
interval = "15s"
method = "GET"
path = "/__health"
protocol = "http"
timeout = "3s"
[http_service.checks.headers]
X-Health-Check = "fly"
⚠️ Wichtig: auto_stop_machines = "stop" stoppt die Machine komplett (kalt). "suspend" hält den Memory-State — Restarts dauern nur ~100ms statt mehrerer Sekunden. Für APIs mit niedrigem Traffic ist "suspend" fast immer die bessere Wahl.
3. Persistent Volumes — SQLite in Production mit Fly Volumes
Fly.io Volumes sind persistente Block-Storage-Einheiten, die an eine einzelne Machine in einer spezifischen Region gebunden sind. Das macht sie ideal für SQLite-Datenbanken, lokale Caches und File-Uploads — ohne den Overhead eines externen Datenbankdienstes.
Volumes Volume erstellen und mounten
# Volume erstellen (Region muss mit App-Region übereinstimmen)
fly volumes create app_data \
--region fra \
--size 10 \
--app meine-api
# Volume auflisten
fly volumes list
# Volume-Details anzeigen
fly volumes show vol_xxxxxxxxx
# Volume-Snapshot erstellen (Backup)
fly volumes snapshots create vol_xxxxxxxxx
# Volume-Größe erweitern (nicht verkleinern!)
fly volumes extend vol_xxxxxxxxx --size 20
Volumes in fly.toml einbinden
# fly.toml — Volume Mount Konfiguration
[[mounts]]
source = "app_data" # Name des Volumes (aus fly volumes create)
destination = "/data" # Mount-Pfad im Container
# Mehrere Volumes (z.B. DB + Uploads getrennt)
[[mounts]]
source = "sqlite_db"
destination = "/db"
[[mounts]]
source = "user_uploads"
destination = "/uploads"
SQLite in Production — Best Practices mit Fly Volumes
SQLite auf einem Fly Volume ist eine legitime Production-Strategie für viele Anwendungstypen. Claude Code kann das Setup vollständig konfigurieren:
SQLite SQLite + WAL-Mode auf Fly Volume (Node.js Beispiel)
// db.js — SQLite auf Fly Volume mit WAL-Modus
const Database = require('better-sqlite3');
const path = require('path');
// /data ist das gemountete Fly Volume
const DB_PATH = process.env.DATABASE_PATH || '/data/app.db';
const db = new Database(DB_PATH);
// WAL-Mode: bessere Concurrent-Reads, atomare Writes
db.pragma('journal_mode = WAL');
db.pragma('synchronous = NORMAL');
db.pragma('foreign_keys = ON');
// Busy-Timeout für konkurrierende Zugriffe
db.pragma('busy_timeout = 5000');
module.exports = db;
💡 SQLite vs. Fly Postgres: SQLite auf einem Fly Volume eignet sich hervorragend für Apps mit <10k Writes/Tag und primär Read-Workload. Für Multi-Region-Schreibzugriffe ist Fly Postgres + LiteFS die bessere Wahl (siehe Abschnitt 6).
Volume-Backups und Disaster Recovery
# Automatische Snapshots konfigurieren (via fly.toml)
[[mounts]]
source = "sqlite_db"
destination = "/db"
snapshot_retention = 5 # Letzte 5 Snapshots behalten
auto_extend_size_threshold = 80 # Bei 80% Auslastung auto-erweitern
auto_extend_size_increment = "5GB"
---
# Manuelles SQLite-Backup per SSH
fly ssh console -C "sqlite3 /db/app.db .dump" > backup_$(date +%Y%m%d).sql
# Oder via Python-Script im Container
fly ssh console -C "python3 /app/scripts/backup_db.py"
4. Secrets Management — flyctl secrets und sichere Konfiguration
Fly.io bietet ein eingebautes Secrets-Management-System, das deutlich sicherer ist als .env-Dateien in Git-Repositories. Secrets werden verschlüsselt gespeichert und als Umgebungsvariablen in die Machines injiziert — ohne dass sie jemals in Klartext auf der Festplatte landen.
Secrets flyctl secrets — Grundlegende Befehle
# Einzelnes Secret setzen
fly secrets set DATABASE_URL="postgresql://user:pass@host/db"
# Mehrere Secrets auf einmal
fly secrets set \
API_KEY="sk-..." \
JWT_SECRET="super-secret-jwt-key" \
STRIPE_KEY="sk_live_..."
# Secrets aus .env-Datei importieren (nur einmalig beim Setup)
fly secrets import < .env.production
# Secrets auflisten (Werte werden NICHT angezeigt)
fly secrets list
# Secret löschen
fly secrets unset OLD_API_KEY
# Deployment ohne Neustart (Secret erst beim nächsten Deploy aktiv)
fly secrets set NEW_KEY="value" --stage
.env vs. fly secrets — Ein Vergleich
| Kriterium |
.env Datei (lokal) |
fly secrets |
| Sicherheit |
Risiko bei Git-Commit, Klartext |
Verschlüsselt, nie im Repository |
| Rotation |
Manuell, neues Deploy nötig |
Automatischer Neustart der Machines |
| Audit Trail |
Kein eingebautes Logging |
Fly.io Dashboard + CLI History |
| Team-Zugriff |
Manuell teilen, Sync-Problem |
Zentral in Fly.io App, Rollen-basiert |
| CI/CD |
.env in CI-Secrets hinterlegen |
FLY_API_TOKEN reicht für Deploy |
Secrets in der Anwendung nutzen
Fly Secrets werden als normale Umgebungsvariablen übergeben — kein spezieller SDK nötig:
// Node.js — Secrets als process.env
const config = {
database: process.env.DATABASE_URL,
apiKey: process.env.API_KEY,
jwtSecret: process.env.JWT_SECRET,
};
# Python — via os.environ
import os
DATABASE_URL = os.environ["DATABASE_URL"]
SECRET_KEY = os.environ["DJANGO_SECRET_KEY"]
# Go — via os.Getenv
apiKey := os.Getenv("API_KEY")
if apiKey == "" {
log.Fatal("API_KEY nicht gesetzt")
}
Secrets in CI/CD-Pipelines (GitHub Actions)
# .github/workflows/deploy.yml
name: Deploy to Fly.io
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: superfly/flyctl-actions/setup-flyctl@master
- run: fly deploy --remote-only
env:
FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }}
# FLY_API_TOKEN einmalig generieren:
fly tokens create deploy --expiry 168h
5. Private Networking — Fly WireGuard, 6PN und interne Service Discovery
Fly.io bietet ein integriertes privates Netzwerk für alle Apps innerhalb einer Organisation. Dieses sogenannte 6PN (6-Plane Network) basiert auf WireGuard und ermöglicht sichere Kommunikation zwischen Fly-Anwendungen — ohne öffentliche IPs oder externe Load-Balancer.
6PN Fly Private Networking — Architektur
Jede Fly Machine bekommt automatisch eine IPv6-Adresse im privaten fdaa::/8 Netzwerk. Alle Apps innerhalb einer Organisation können sich gegenseitig über diese Adressen erreichen — verschlüsselt via WireGuard, ohne Latenz-Overhead durch öffentliches Internet.
Internes DNS — .internal Adressen
Fly.io stellt automatisch DNS-Auflösung für interne Services bereit. Das Muster ist einfach und vorhersehbar:
# DNS-Schema für interne Fly-Services
# Format: [qualifier].[app-name].internal
# Alle Machines einer App (round-robin)
meine-api.internal
# Nur Machines in einer spezifischen Region
fra.meine-api.internal
ams.meine-api.internal
# Fly Postgres intern ansprechen
meine-db.internal:5432
# Redis-Cluster intern
mein-redis.internal:6379
# Von App zu App kommunizieren
# KEINE public URL nötig — direkt über .internal
DATABASE_URL = "postgresql://user:pass@meine-db.internal:5432/mydb"
WireGuard Tunnel für lokale Entwicklung
Fly.io erlaubt es, den privaten Tunnel auch lokal zu nutzen — ideal für Datenbankzugriff während der Entwicklung:
# WireGuard-Konfiguration für lokalen Tunnel
fly wireguard create fra
# Peer-Datei exportieren
fly wireguard create fra local-dev > fly-wireguard.conf
# WireGuard Interface aktivieren (Linux/macOS)
sudo wg-quick up fly-wireguard.conf
# Jetzt direkt auf interne Services zugreifen:
psql "postgresql://postgres:pass@meine-db.internal:5432/mydb"
# Tunnel wieder deaktivieren
sudo wg-quick down fly-wireguard.conf
# Alternativ: fly proxy (kein WireGuard nötig)
fly proxy 5432 -a meine-db
# Dann: psql postgresql://localhost:5432/mydb
Service Discovery Interne Kommunikation zwischen Fly Apps
# fly.toml — App die interne Services nutzt
[env]
# Interne URLs — kein SSL-Overhead, direkte Verbindung
REDIS_URL = "redis://mein-redis.internal:6379"
WORKER_URL = "http://mein-worker.internal:8081"
METRICS_URL = "http://mein-metrics.internal:9090"
---
// Node.js — Verbindung zu internem Service
const axios = require('axios');
// Direkte interne Kommunikation ohne DNS-Latenz
async function callWorker(task) {
const url = process.env.WORKER_URL + '/process';
return axios.post(url, task, {
headers: { 'X-Internal-Token': process.env.INTERNAL_TOKEN }
});
}
Fly.io als Service Mesh — wann es sinnvoll ist
Das 6PN-Netzwerk ermöglicht eine Microservices-Architektur ohne externen Service Mesh (Istio/Linkerd):
# Beispiel: Drei-Tier-Architektur auf Fly.io
# frontend.toml — öffentlich zugänglich
app = "meine-frontend"
[http_service]
internal_port = 3000
force_https = true
[env]
API_URL = "http://meine-api.internal:8080"
---
# api.toml — intern + öffentlich für externe Clients
app = "meine-api"
[http_service]
internal_port = 8080
[env]
DB_URL = "postgresql://user:pass@meine-db.internal:5432/prod"
CACHE_URL = "redis://mein-redis.internal:6379"
---
# worker.toml — NUR intern, kein öffentlicher Port
app = "mein-worker"
# Kein [http_service] → nicht öffentlich erreichbar
[env]
DB_URL = "postgresql://user:pass@meine-db.internal:5432/prod"
6. Multi-Region Deployment — primary_region, Read Replicas und Fly Postgres mit LiteFS
Fly.io glänzt bei Multi-Region-Deployments. Während klassische Cloud-Anbieter komplexe Cross-Region-Setups erfordern, genügen bei Fly.io wenige Konfigurationszeilen. Claude Code kann die gesamte Multi-Region-Strategie inklusive Datenbankreplikation planen und implementieren.
fra (Primary)
ams
lhr
sin
nrt
lax
iad
gru
syd
Multi-Region App in mehrere Regionen deployen
# fly.toml — Multi-Region Konfiguration
app = "meine-api"
primary_region = "fra" # Primäre Region für Writes
[http_service]
internal_port = 8080
force_https = true
auto_stop_machines = "suspend"
auto_start_machines = true
min_machines_running = 1
---
# Machines in anderen Regionen hinzufügen
fly machine clone --region ams
fly machine clone --region sin
fly machine clone --region lax
# Machines nach Region auflisten
fly machines list
# Skalieren: Anzahl Machines pro Region
fly scale count 2 --region fra
fly scale count 1 --region ams
Fly Postgres — Managed Database mit Multi-Region-Support
# Fly Postgres Cluster erstellen
fly postgres create \
--name meine-db \
--region fra \
--vm-size shared-cpu-1x \
--volume-size 10 \
--cluster-size 2
# Postgres an App anhängen (setzt DATABASE_URL Secret)
fly postgres attach meine-db --app meine-api
# Read Replica in anderer Region erstellen
fly machine clone \
--app meine-db \
--region sin \
--config '{"env":{"FLY_REGION":"sin","IS_FOLLOWER":"true"}}'
# Failover manuell triggern
fly postgres failover --app meine-db
# Postgres-Status
fly postgres db list --app meine-db
fly postgres users list --app meine-db
LiteFS — SQLite Multi-Region-Replikation
LiteFS ist Fly.ios eigene Lösung für SQLite-Replikation über mehrere Regionen. Es ermöglicht SQLite-Writes auf dem Primary und schnelle Reads in jeder Region:
LiteFS SQLite global repliziert — fly.toml + LiteFS-Konfiguration
# fly.toml — LiteFS Setup
app = "meine-app"
primary_region = "fra"
[[mounts]]
source = "litefs_data"
destination = "/var/lib/litefs"
[env]
LITEFS_DIR = "/var/lib/litefs"
DATABASE_PATH = "/var/lib/litefs/db"
---
# litefs.yml — LiteFS Konfiguration
fuse:
dir: "/var/lib/litefs"
data:
dir: "/var/lib/litefs/.data"
# Consul für Leader-Election (oder Fly Consul)
lease:
type: consul
advertise-url: "http://${HOSTNAME}.vm.${FLY_APP_NAME}.internal:20202"
candidate: ${FLY_REGION == PRIMARY_REGION}
promote: true
consul:
url: "http://localhost:8500"
key: "app/litefs/primary"
exec:
- cmd: "/usr/local/bin/node /app/server.js"
if-candidate: true
---
# Dockerfile — LiteFS + App kombiniert
FROM node:20-slim
# LiteFS installieren
COPY --from=flyio/litefs:0.5 /usr/local/bin/litefs /usr/local/bin/litefs
WORKDIR /app
COPY package*.json ./
RUN npm ci --production
COPY . .
# LiteFS als Entrypoint
ENTRYPOINT ["litefs", "mount"]
Fly-Replay Header — Write-Forwarding an Primary
Fly.io bietet einen eleganten Mechanismus für Write-Forwarding: Der fly-replay-Header leitet Requests automatisch an die Primary-Region weiter:
// Middleware: Write-Requests an Primary weiterleiten
function replayToPrimary(req, res, next) {
const primaryRegion = process.env.PRIMARY_REGION || 'fra';
const currentRegion = process.env.FLY_REGION;
// Schreibende Methoden prüfen
if (['POST', 'PUT', 'PATCH', 'DELETE'].includes(req.method)) {
if (currentRegion !== primaryRegion) {
// Fly.io routet diesen Request automatisch zur Primary-Region
res.set('fly-replay', `region=${primaryRegion}`);
return res.status(409).json({
message: 'Replaying to primary region',
region: primaryRegion
});
}
}
next();
}
app.use(replayToPrimary);
💡 Claude Code für Multi-Region: "Ich habe eine Express-API mit SQLite und LiteFS. Erstelle die komplette Multi-Region-Konfiguration mit fly.toml, litefs.yml und dem Replay-Middleware für Write-Forwarding an die fra-Primary-Region."
Monitoring und Observability für Multi-Region-Deployments
# Fly.io eingebaute Metriken abrufen
fly metrics show --app meine-api
# Logs nach Region filtern
fly logs --region fra
fly logs --region sin
# Machine-spezifische Logs
fly logs --machine
# Dashboard URL
# https://fly.io/apps/meine-api/monitoring
# Health-Check Status global
fly checks list --app meine-api
# Antwortzeiten per Region messen
curl -H "fly-prefer-region: sin" https://meine-api.fly.dev/health
curl -H "fly-prefer-region: fra" https://meine-api.fly.dev/health
Fly.io mit Claude Code — Produktiv in Minuten
Fly.io hat sich 2026 als eine der leistungsfähigsten Deployment-Plattformen für Developer-Teams etabliert. Die Kombination aus schnellen Machines, integriertem privatem Networking, einfachem Secrets-Management und globalem Postgres macht es zur idealen Plattform für moderne Webanwendungen.
Typischer Claude Code Workflow für Fly.io
1
fly.toml generieren: "Erstelle eine fly.toml für meine FastAPI-App mit Auto-Stop, 256MB RAM und Health-Check auf /health"
2
Dockerfile optimieren: "Optimiere mein Dockerfile für Fly.io — multi-stage build, non-root user, Health-Check"
3
Volumes und SQLite: "Konfiguriere ein Fly Volume für SQLite mit WAL-Mode und automatischen Backups"
4
Secrets migrieren: "Konvertiere meine .env.production in flyctl secrets set Befehle (API-Keys anonymisiert)"
5
Multi-Region: "Füge Read-Replicas in sin und lax hinzu und implementiere Write-Forwarding zum fra-Primary"
Cheatsheet Wichtigste flyctl Befehle auf einen Blick
# === DEPLOYMENT ===
fly launch
# App initialisieren
fly deploy
# Deployen
fly deploy --strategy bluegreen
# Zero-Downtime Deploy
# === SCALING ===
fly scale count 3
# 3 Machines
fly scale memory 1024
# 1GB RAM
fly scale vm shared-cpu-2x
# VM-Größe ändern
# === VOLUMES ===
fly volumes create data --size 10
# 10GB Volume
fly volumes list
# Volumes anzeigen
fly volumes snapshots list
# Backups anzeigen
# === SECRETS ===
fly secrets set KEY=VALUE
# Secret setzen
fly secrets list
# Secrets auflisten
fly secrets unset KEY
# Secret löschen
# === DEBUGGING ===
fly ssh console
# SSH in Machine
fly logs
# Echtzeit-Logs
fly status
# App-Status
fly checks list
# Health-Checks
# === POSTGRES ===
fly postgres create
# DB erstellen
fly postgres attach
# App verbinden
fly proxy 5432 -a meine-db # Lokaler Tunnel
Die Stärke von Claude Code liegt darin, nicht nur einzelne Konfigurationsfragmente zu generieren, sondern die gesamte Deployment-Architektur zu verstehen und aufeinander abzustimmen — von der fly.toml über das LiteFS-Setup bis zur GitHub Actions Pipeline. Claude Code kennt die Fly.io-Dokumentation und aktuellen Best Practices und kann projektspezifische Konfigurationen in Minuten erstellen, die sonst Stunden Recherche erfordern würden.
Deployment-Modul im Kurs
Im Claude Code Mastery Kurs: Fly.io, Railway und Render im Vergleich — vollständige Deployment-Guides für Node.js, Python und Go-Anwendungen.
14 Tage kostenlos testen →