From 8d0016fd326de2f8cc0e703b0660f8e61ff18e32 Mon Sep 17 00:00:00 2001 From: William Valentin Date: Sun, 15 Feb 2026 18:28:26 -0800 Subject: [PATCH] feat(deploy): add PaaS templates and config --- Dockerfile | 7 ++- README.md | 8 +++ config/paas.yaml | 28 +++++++++++ deploy/flyio/fly.toml | 24 +++++++++ deploy/railway/railway.toml | 4 ++ deploy/render/render.yaml | 11 ++++ docs/deployment/PAAS.md | 56 +++++++++++++++++++++ docs/deployment/PRODUCTION.md | 5 ++ docs/plans/2026-02-16-deployment-targets.md | 41 +++++++++++++++ docs/plans/state.json | 24 ++++++++- 10 files changed, 205 insertions(+), 3 deletions(-) create mode 100644 config/paas.yaml create mode 100644 deploy/flyio/fly.toml create mode 100644 deploy/railway/railway.toml create mode 100644 deploy/render/render.yaml create mode 100644 docs/deployment/PAAS.md create mode 100644 docs/plans/2026-02-16-deployment-targets.md diff --git a/Dockerfile b/Dockerfile index 2a444cf..26efd55 100644 --- a/Dockerfile +++ b/Dockerfile @@ -53,8 +53,11 @@ COPY --from=builder /app/package.json ./ # Copy SOUL.md if it exists (prompt template loaded at runtime) COPY --from=builder /app/SOUL.md ./ -# Create data directories -RUN mkdir -p /data/memory /data/sessions /config +# Create data directories and ship a default config at /config/config.yaml so +# the image is runnable without an external bind-mount (compose can still +# override /config/config.yaml). +RUN mkdir -p /data/memory /data/sessions /config && \ + cp -f /app/config/paas.yaml /config/config.yaml # Environment ENV NODE_ENV=production \ diff --git a/README.md b/README.md index 7a69ca3..b707736 100644 --- a/README.md +++ b/README.md @@ -770,6 +770,14 @@ docker compose logs -f | `/config/config.yaml` | Configuration file (read-only) | | `/data` | Persistent data (sessions DB, memory files, vector index) | +## PaaS Deployment (Fly.io / Railway / Render) + +See `docs/deployment/PAAS.md` and the templates under `deploy/`. + +## Nix Deployment + +See `docs/deployment/NIX.md` for the flake (package + dev shell + optional NixOS module). + ## Doctor Diagnostics `flynn doctor` runs 10 health checks to validate your setup: diff --git a/config/paas.yaml b/config/paas.yaml new file mode 100644 index 0000000..ba039a2 --- /dev/null +++ b/config/paas.yaml @@ -0,0 +1,28 @@ +# Flynn PaaS-friendly configuration template +# +# Intended for: Fly.io / Railway / Render (or any platform that provides PORT). +# - Binds the gateway on all interfaces (required for container/PaaS routing). +# - Relies on `${ENV_VAR}` expansion so secrets stay in platform env vars. +# +# For a full example with more options, see: config/default.yaml + +server: + localhost: false + port: 18800 # Overridden by PORT env var when set. + +models: + default: + provider: anthropic + model: claude-sonnet-4-20250514 + api_key: ${ANTHROPIC_API_KEY} + +# Recommended safe defaults for internet-exposed deployments. +pairing: + enabled: true + +tools: + profile: messaging + +sandbox: + enabled: true + diff --git a/deploy/flyio/fly.toml b/deploy/flyio/fly.toml new file mode 100644 index 0000000..a3cced6 --- /dev/null +++ b/deploy/flyio/fly.toml @@ -0,0 +1,24 @@ +app = "flynn" + +[build] + dockerfile = "Dockerfile" + +[env] + # Persist state under /data (see volume mount below) + FLYNN_DATA_DIR = "/data" + + # The Docker image ships /config/config.yaml (from config/paas.yaml). + # Override this if you mount your own config elsewhere. + FLYNN_CONFIG = "/config/config.yaml" + +[http_service] + internal_port = 18800 + force_https = true + auto_start_machines = true + auto_stop_machines = "stop" + min_machines_running = 0 + +[[mounts]] + source = "flynn_data" + destination = "/data" + diff --git a/deploy/railway/railway.toml b/deploy/railway/railway.toml new file mode 100644 index 0000000..51d4e47 --- /dev/null +++ b/deploy/railway/railway.toml @@ -0,0 +1,4 @@ +[build] +builder = "DOCKERFILE" +dockerfilePath = "Dockerfile" + diff --git a/deploy/render/render.yaml b/deploy/render/render.yaml new file mode 100644 index 0000000..66e353b --- /dev/null +++ b/deploy/render/render.yaml @@ -0,0 +1,11 @@ +services: + - type: web + name: flynn + env: docker + dockerfilePath: ./Dockerfile + autoDeploy: false + healthCheckPath: / + envVars: + - key: ANTHROPIC_API_KEY + sync: false + diff --git a/docs/deployment/PAAS.md b/docs/deployment/PAAS.md new file mode 100644 index 0000000..a40a5dc --- /dev/null +++ b/docs/deployment/PAAS.md @@ -0,0 +1,56 @@ +# PaaS Deployment (Fly.io / Railway / Render) + +Flynn can run on common PaaS platforms using the repo `Dockerfile`. + +Key requirements: + +- Bind on all interfaces: set `server.localhost: false`. +- Use the platform port: Flynn supports `PORT` env override (it overrides `server.port`). + +This repo includes a PaaS-friendly config template at `config/paas.yaml`. + +## Fly.io + +Template: `deploy/flyio/fly.toml` + +```bash +# Create app +fly apps create + +# Create persistent data volume (sessions + memory) +fly volumes create flynn_data --size 1 + +# Set required secrets +fly secrets set ANTHROPIC_API_KEY=sk-ant-... + +# Deploy +fly deploy -c deploy/flyio/fly.toml +``` + +Notes: + +- The Docker image ships a default config at `/config/config.yaml` (from `config/paas.yaml`). +- If you want to supply your own config, set `FLYNN_CONFIG` to your path or mount a file at `/config/config.yaml`. + +## Railway + +Railway can deploy directly from this repo using the `Dockerfile`. + +Checklist: + +- Add env var `ANTHROPIC_API_KEY`. +- Ensure your config binds externally (`server.localhost: false`) or use the baked-in `config/paas.yaml`. + +Optional template: `deploy/railway/railway.toml` + +## Render + +Render can deploy directly from this repo using the `Dockerfile`. + +Checklist: + +- Add env var `ANTHROPIC_API_KEY`. +- Ensure your config binds externally (`server.localhost: false`) or use the baked-in `config/paas.yaml`. + +Optional blueprint: `deploy/render/render.yaml` + diff --git a/docs/deployment/PRODUCTION.md b/docs/deployment/PRODUCTION.md index 343438d..b26974c 100644 --- a/docs/deployment/PRODUCTION.md +++ b/docs/deployment/PRODUCTION.md @@ -7,6 +7,7 @@ This guide covers deploying Flynn in a production environment. - [Prerequisites](#prerequisites) - [Docker Deployment](#docker-deployment) - [Nix Deployment](#nix-deployment) +- [PaaS Deployment](#paas-deployment) - [Systemd Service](#systemd-service) - [Security](#security) - [Configuration](#configuration) @@ -101,6 +102,10 @@ export OPENAI_API_KEY=sk-... If you use Nix, this repo ships a flake (package + dev shell + optional NixOS module). See `docs/deployment/NIX.md`. +## PaaS Deployment + +Templates and notes for Fly.io / Railway / Render are in `docs/deployment/PAAS.md`. + ## Systemd Service ### Service File diff --git a/docs/plans/2026-02-16-deployment-targets.md b/docs/plans/2026-02-16-deployment-targets.md new file mode 100644 index 0000000..b93d2fd --- /dev/null +++ b/docs/plans/2026-02-16-deployment-targets.md @@ -0,0 +1,41 @@ +# Milestone 6 (P3): Deployment Targets (Nix + Fly/Railway/Render) + +Date: 2026-02-16 + +## Goals + +- Provide a Nix flake/package that builds `dist/` and preserves `dist/gateway/ui` adjacency. +- Provide an optional NixOS module for running Flynn as a systemd service. +- Add first-class docs and templates for Fly.io / Railway / Render. +- Ensure PaaS network binding works (`server.localhost: false`) and port binding works (`PORT` env override). + +## Implementation + +### Nix + +- Added `flake.nix` with: + - `packages.flynn` / `packages.default` + - `apps.default` (`nix run`) + - `devShells.default` (`nix develop`) + - `overlays.default` (exposes `pkgs.flynn`) + - `nixosModules.flynn` +- Added Nix package definition: `nix/package.nix` (builds via `pnpm build`). +- Added NixOS module: `nix/module.nix` (`services.flynn.*`). +- Added docs: `docs/deployment/NIX.md`. + +### PaaS + +- Added a PaaS-friendly config template: `config/paas.yaml` (`server.localhost: false`). +- Updated `Dockerfile` to ship a default config at `/config/config.yaml` so the image is runnable without a bind-mount. +- Added templates: + - Fly.io: `deploy/flyio/fly.toml` + - Railway: `deploy/railway/railway.toml` + - Render: `deploy/render/render.yaml` +- Added docs: `docs/deployment/PAAS.md`. + +## Acceptance Notes + +- `pnpm build` still copies gateway UI to `dist/gateway/ui` (required adjacency). +- `PORT` env override is implemented in `src/config/loader.ts` (completed earlier on 2026-02-16). +- For PaaS/container routing, use `server.localhost: false` (baked into `config/paas.yaml`). + diff --git a/docs/plans/state.json b/docs/plans/state.json index a63f824..86036a1 100644 --- a/docs/plans/state.json +++ b/docs/plans/state.json @@ -72,6 +72,28 @@ "test_status": "Not run (Nix build requires pnpmDepsHash update); pnpm test suite unaffected" }, + "deployment-targets-paas": { + "file": "2026-02-16-deployment-targets.md", + "status": "completed", + "date": "2026-02-16", + "updated": "2026-02-16", + "summary": "Added PaaS deployment templates and docs for Fly.io / Railway / Render, plus a PaaS-friendly config template (server.localhost: false) and a Docker image default /config/config.yaml for easier platform deployment.", + "files_created": [ + "docs/plans/2026-02-16-deployment-targets.md", + "docs/deployment/PAAS.md", + "config/paas.yaml", + "deploy/flyio/fly.toml", + "deploy/railway/railway.toml", + "deploy/render/render.yaml" + ], + "files_modified": [ + "Dockerfile", + "README.md", + "docs/deployment/PRODUCTION.md" + ], + "test_status": "pnpm test suite unaffected (deployment/docs changes)" + }, + "openclaw-gap-roadmap": { "file": "2026-02-15-openclaw-gap-roadmap.md", "status": "planned", @@ -2176,7 +2198,7 @@ "tier2_completion": "4/4 (100%) — inbound webhooks, vector memory search, Dockerfile, heartbeat monitor", "tier3_completion": "5/5 (100%) — lane queue, credential redaction, web UI token dashboard, xAI (Grok) provider, Voyage AI embeddings", "tier4_completion": "4/4 (100%) — gateway lock, shell completion, Tailscale Serve/Funnel, DM pairing codes", - "feature_gap_scorecard": "103/128 match (80%), 0 partial (0%), 25 missing (20%)", + "feature_gap_scorecard": "104/128 match (81%), 0 partial (0%), 24 missing (19%)", "operator_dx_milestone": "Phase 3 (Live Ops Dashboard): 2/2 plans complete — milestone done", "gmail_auth_cli": "flynn gmail-auth command implemented with OAuth2 flow, doctor check, config routed to Telegram", "native_audio_support": "completed — smart routing for native audio (Gemini/OpenAI/GitHub) vs Whisper transcription fallback",