From atum-workflows
Fly.io deployment pattern library — deploy Docker containers to Fly's global edge platform across 35+ regions. Covers fly.toml config, Dockerfile optimization, multi-region deployment with primary region + read replicas, Fly Postgres (managed HA Postgres cluster), Fly Volumes (NVMe persistent storage), private networking via 6PN (IPv6 mesh), custom domains and SSL via Let's Encrypt, machine-based vs app-based model (2024+ Fly Machines API), health checks, secrets management, scaling strategies (horizontal + vertical), and release commands. Use when deploying a Docker-based service to Fly.io, configuring multi-region apps, provisioning Postgres clusters, setting up private networking, or migrating from Heroku. Differentiates from deploy-railway by offering true multi-region edge deployment, Docker-first builds, and machine-level control. Best choice for latency-sensitive backends or geo-distributed apps.
npx claudepluginhub arnwaldn/atum-plugins-collection --plugin atum-workflowsThis skill uses the workspace's default tool permissions.
Fly.io déploie des containers Docker dans 35+ régions à travers le monde via des micro-VMs (Fly Machines). Idéal pour les backends latency-sensitive ou multi-region.
Searches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.
Searches prompts.chat for AI prompt templates by keyword or category, retrieves by ID with variable handling, and improves prompts via AI. Use for discovering or enhancing prompts.
Executes pre-written implementation plans: critically reviews, follows bite-sized steps exactly, runs verifications, tracks progress with checkpoints, uses git worktrees, stops on blockers.
Fly.io déploie des containers Docker dans 35+ régions à travers le monde via des micro-VMs (Fly Machines). Idéal pour les backends latency-sensitive ou multi-region.
# Install CLI
curl -L https://fly.io/install.sh | sh
# Login
fly auth login
# Launch un projet (interactive, crée fly.toml)
cd my-app
fly launch
fly.tomlapp = "my-app"
primary_region = "cdg"
[build]
[env]
PORT = "8080"
NODE_ENV = "production"
[http_service]
internal_port = 8080
force_https = true
auto_stop_machines = true
auto_start_machines = true
min_machines_running = 1
processes = ["app"]
[[services]]
protocol = "tcp"
internal_port = 8080
[[services.ports]]
port = 80
handlers = ["http"]
force_https = true
[[services.ports]]
port = 443
handlers = ["tls", "http"]
[[vm]]
cpu_kind = "shared"
cpus = 1
memory_mb = 512
FROM node:20-alpine AS base
FROM base AS deps
WORKDIR /app
COPY package.json pnpm-lock.yaml ./
RUN corepack enable && pnpm install --frozen-lockfile --prod
FROM base AS builder
WORKDIR /app
COPY package.json pnpm-lock.yaml ./
RUN corepack enable && pnpm install --frozen-lockfile
COPY . .
RUN pnpm build
FROM base AS runner
WORKDIR /app
ENV NODE_ENV=production
COPY --from=deps /app/node_modules ./node_modules
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/package.json ./package.json
EXPOSE 8080
CMD ["node", "dist/index.js"]
Multi-stage build = image finale plus petite = cold start plus rapide.
# Ajouter des régions
fly regions add fra sjc syd
# Scale une app sur N machines par région
fly scale count 2 --region cdg
fly scale count 1 --region sjc
Fly répartit automatiquement le traffic vers la région la plus proche de chaque user via anycast.
# Créer un cluster Postgres
fly postgres create --name my-app-db --region cdg --initial-cluster-size 2
# Attacher à l'app
fly postgres attach my-app-db --app my-app
# Injecte DATABASE_URL automatiquement
Fly Postgres est basé sur stolon pour la HA. Inclut :
# Créer un volume NVMe
fly volumes create data --region cdg --size 10
# Mount dans fly.toml
[mounts]
source = "data"
destination = "/data"
Limite : un volume = une machine. Pour du shared storage, utiliser Fly Object Storage (compatible S3) ou R2.
Tous les services d'une même org Fly sont sur un réseau privé IPv6 (.internal DNS).
// Depuis une app
const redis = 'redis://my-redis.internal:6379'
const db = 'postgres://my-app-db.internal:5432/db'
# Ajouter un secret (chiffré)
fly secrets set STRIPE_SECRET_KEY=sk_live_xxx
# Liste
fly secrets list
# Remove
fly secrets unset OLD_KEY
Secrets injectés comme env vars au runtime, jamais en clair dans les logs.
# Ajouter un domaine
fly certs add example.com
# Instructions DNS affichées — ajouter un A/AAAA record
# SSL provisionné automatiquement via Let's Encrypt
[[services.http_checks]]
interval = "30s"
timeout = "5s"
grace_period = "10s"
method = "GET"
path = "/health"
protocol = "http"
restart_limit = 0
Endpoint /health minimal :
app.get('/health', async (req, res) => {
// Vérif DB
try {
await db.raw('SELECT 1')
} catch {
return res.status(503).json({ status: 'db down' })
}
res.json({ status: 'ok', uptime: process.uptime() })
})
Exécuter une commande une fois avant chaque déploiement (ex. migrations) :
[deploy]
release_command = "node dist/scripts/migrate.js"
Fly lance une machine temporaire qui exécute le command, et n'active le deploy que si exit 0.
fly scale count 4 --region cdg
fly scale count 2 --region fra
fly scale vm performance-2x # 2 CPU, 4 GB RAM
fly scale memory 2048 # augmenter juste la RAM
Liste des VMs disponibles : fly platform vm-sizes
fly.toml → toujours via fly secrets set/ → touche des routes lourdes, timeout facileauto_stop_machines sur les apps à faible trafic → facture cherfly secrets setdeploy-verceldeploy-railwaydeploy-cloudflaredeploy-docker-registries