Skip to content

docs(deployment): add Deploy to Fly.io guide#1885

Open
rohitg00 wants to merge 10 commits into
docs/deploy-railway-guidefrom
docs/deploy-fly-guide
Open

docs(deployment): add Deploy to Fly.io guide#1885
rohitg00 wants to merge 10 commits into
docs/deploy-railway-guidefrom
docs/deploy-fly-guide

Conversation

@rohitg00

@rohitg00 rohitg00 commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

Stacked on #1880 (Deploy to Railway), which is stacked on #1872 (Self-hosted deployment).

What changed

  • New dedicated Deploy to Fly.io how-to (next + current): pre-built Docker Hub images, a Fly-ready config.yaml (bind [::], state under /data), the engine + worker placement model (engine plus workers, each worker either in-engine or its own Fly Machine over the 6PN), file_based to external adapters (Redis/RabbitMQ/Postgres), Rust binary workers, worker manifest, hardening, RBAC, Fly Proxy TLS, health checks, observability, the /dev/kvm micro-VM limit, end-to-end verification, and a Fly-specific deployment checklist.
  • Nav: docs.json Deployment group is now Deployment + Deploy to Railway + Deploy to Fly.io, for both versions.

Depends on (merge order)

  1. docs(deployment): expand the deployment how-to with tested guidance #1872 (docs/deployment-guide)
  2. docs(deployment): add Deploy to Railway guide and group nav #1880 (docs/deploy-railway-guide)
  3. this PR

Base branch is docs/deploy-railway-guide; it will retarget to main automatically as the parents merge.

Grounded in real Fly testing

  • Engine on one Fly Machine + a separate worker on its own Fly Machine over the 6PN, verified end-to-end (/hello -> Fly Proxy -> engine -> worker -> state worker); state persisted across Machine reboots.
  • iii-sandbox (libkrun) cannot boot without /dev/kvm and reboots the Machine; binary registry workers (e.g. database) run as host processes.
  • Engine restart policy must be always (a clean config-reload exit is otherwise not restarted).

skill.md note

No skill.md committed; rendered artifacts are generated in CI (matching #1880).

Test plan

  • Sidebar shows the Deployment group with Deploy to Fly.io (both versions).
  • Deploy to Fly.io links resolve.
  • CI skill-check passes.

Summary by CodeRabbit

  • Documentation
    • Added complete Fly.io deployment guide covering configuration, engine and worker deployment, scaling, security, observability, and deployment verification.

Add a dedicated Deploy to Fly.io how-to (next + current): pre-built Docker
Hub images, a Fly-ready config.yaml (bind [::], state under /data), the
engine/worker placement model (engine plus workers, each worker either
in-engine or its own Fly Machine over the 6PN), file_based to external
adapters, Rust binary workers, worker manifest, hardening, RBAC, Fly Proxy
TLS, health checks, observability, the /dev/kvm micro-VM limit, end-to-end
verification, and a Fly-specific deployment checklist.

Group docs.json under Deployment (now Deployment, Deploy to Railway, Deploy
to Fly.io) for both versions.

Grounded in real Fly testing: engine plus a separate worker Machine over the
6PN verified end-to-end with state persisting across reboots; libkrun
(iii-sandbox) cannot boot without /dev/kvm and reboots the Machine, while
binary registry workers run as host processes.
@vercel

vercel Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
tech-spec Error Error Jul 1, 2026 1:21pm
1 Skipped Deployment
Project Deployment Actions Updated (UTC)
iii-website Skipped Skipped Jul 1, 2026 1:21pm

Request Review

@coderabbitai

coderabbitai Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 389b5f4c-1f5f-473f-b5e3-e69df96fab06

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch docs/deploy-fly-guide

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

skill-check — docs

1 verified, 600 skipped.

Layer Result
structure
vale
ai
render

Note

114 stale rendered artifact(s) detected on main, unrelated to this PR. This PR is fine; the drift was already there. A maintainer should open a chore PR to re-render these.

  • docs/0-19-0/cli-reference/index.mdx.skill.md
  • docs/0-19-0/creating-workers/channels.mdx.skill.md
  • docs/0-19-0/creating-workers/functions.mdx.skill.md
  • docs/0-19-0/creating-workers/index.mdx.skill.md
  • docs/0-19-0/creating-workers/triggers.mdx.skill.md
  • docs/0-19-0/creating-workers/worker-manifest.mdx.skill.md
  • docs/0-19-0/creating-workers/workers-registry.mdx.skill.md
  • docs/0-19-0/creating-workers/workers.mdx.skill.md
  • docs/0-19-0/how-to/build-a-realtime-todo-app.mdx.skill.md
  • docs/0-19-0/how-to/schedule-cron-task.mdx.skill.md
  • docs/0-19-0/how-to/use-trigger-conditions.mdx.skill.md
  • docs/0-19-0/patterns/adapter-pattern.mdx.skill.md
  • …and 102 more (see the workflow logs)

Replace anthropomorphic 'lives' with 'is stored on' / 'is held in' in the
Fly guide (next + current) to clear Terminology.SlopMarketing errors.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (2)
docs/using-iii/deploy-fly.mdx (1)

597-597: 💤 Low value

Add trailing newline at end of file.

POSIX text files should end with a newline character.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/using-iii/deploy-fly.mdx` at line 597, The file
docs/using-iii/deploy-fly.mdx is missing a trailing newline character at the end
of the file. Add a newline character after the last line of content to ensure
the file ends with a POSIX-compliant newline, which is the standard for text
files.
docs/next/using-iii/deploy-fly.mdx (1)

597-597: 💤 Low value

Add trailing newline at end of file.

POSIX text files should end with a newline character.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/next/using-iii/deploy-fly.mdx` at line 597, The file deploy-fly.mdx is
missing a trailing newline at the end of the file, which violates POSIX text
file standards. Navigate to the very end of the file after the last character
and add a newline character to ensure the file ends with a proper line break.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/next/using-iii/deploy-fly.mdx`:
- Line 255: The SQLite URL in the Fly configuration is using an incorrect format
with a single slash after the colon, which causes the path to be interpreted as
relative instead of absolute. Change the url value from sqlite:/data/iii.db to
sqlite:///data/iii.db by adding one additional slash after the colon to properly
specify an absolute path, ensuring SQLite correctly resolves the database
location on the Fly volume.

In `@docs/using-iii/deploy-fly.mdx`:
- Line 255: The SQLite URL on line 255 uses an incorrect format with only a
single slash after the colon in the protocol. Change the database URL from
sqlite:/data/iii.db to sqlite:///data/iii.db by adding two additional slashes.
The three-slash format (sqlite:///) correctly specifies an absolute path,
whereas the single-slash format (sqlite:/) may be interpreted as a relative
path, which can cause the database to be created in an incorrect location on the
Fly volume.

---

Nitpick comments:
In `@docs/next/using-iii/deploy-fly.mdx`:
- Line 597: The file deploy-fly.mdx is missing a trailing newline at the end of
the file, which violates POSIX text file standards. Navigate to the very end of
the file after the last character and add a newline character to ensure the file
ends with a proper line break.

In `@docs/using-iii/deploy-fly.mdx`:
- Line 597: The file docs/using-iii/deploy-fly.mdx is missing a trailing newline
character at the end of the file. Add a newline character after the last line of
content to ensure the file ends with a POSIX-compliant newline, which is the
standard for text files.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: a1fc3d45-2279-4934-bff1-c5f757d49d58

📥 Commits

Reviewing files that changed from the base of the PR and between 0c25327 and e78fd35.

📒 Files selected for processing (3)
  • docs/docs.json
  • docs/next/using-iii/deploy-fly.mdx
  • docs/using-iii/deploy-fly.mdx

Comment thread docs/next/using-iii/deploy-fly.mdx
Comment thread docs/using-iii/deploy-fly.mdx
Comment thread docs/next/using-iii/deploy-fly.mdx Outdated
Comment thread docs/next/using-iii/deploy-fly.mdx Outdated
```yaml
- name: iii-state
config:
adapter: { name: redis, config: { url: "${REDIS_URL}" } }

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

      adapter:
        class: modules::queue::RedisAdapter
        config:
          redis_url: ${REDIS_URL:redis://localhost:6379}

Comment thread docs/next/using-iii/deploy-fly.mdx Outdated
crash is a real signal.
- `scripts.install`: install from a lockfile without dev deps (`npm ci --omit=dev`).
- `env`: inject production config; keep secrets out of the file and supply them from the
environment (`fly secrets`). `III_URL` / `III_ENGINE_URL` are ignored; the engine sets

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

III_URL / III_ENGINE_URL are ignored

lines 222 and 230 tell you to fly secrets set III_URL=ws://iii-engine.internal:49134 and pass process.env.III_URL directly to registerWorker(). then line 394 says these env vars are ignored — the engine sets the connection URL. an agent following the guide step-by-step would set the secret, wire the SDK with it, and then hit line 394 and not know which is authoritative: does the worker need to read III_URL from the environment, or does the engine inject the URL? worth reconciling who owns the connection URL.

Comment thread docs/next/using-iii/deploy-fly.mdx Outdated
## Observability

Set `iii-observability` to the `otlp` exporter and point it at an OpenTelemetry collector
running as its own Fly app on the 6PN (`http://otel-collector.internal:4318`). The

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't the OTEL port 4317?

Comment thread docs/next/using-iii/deploy-fly.mdx Outdated
destination = "/data"

# Keep the single stateful engine alive. The default policy is "on-failure", which
# does NOT restart on a clean exit (code 0) -- and the engine exits cleanly when it

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this rationale right? the guide says "the engine exits cleanly when it reloads config.yaml at runtime" (lines 141–142), but from the source a successful reload is applied hot in-process — the engine never exits. only a failed reload exits, and that exit is non-zero (so on-failure would also restart it). policy = "always" is still fine, but the stated reason is backwards — the engine does not produce a clean exit code 0 on reload.

Comment thread docs/next/using-iii/deploy-fly.mdx Outdated
<Warning>
This is not a soft failure. Declaring an engine-managed micro-VM worker (for example
`iii worker add iii-sandbox`) makes the engine try to start a guest with no `/dev/kvm`;
in testing this took down the engine's worker connection and **rebooted the Machine**.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does it actually reboot the machine? from the code, a missing /dev/kvm just fails a pre-flight check and the worker exits with an error (clean exit 1) — the engine itself doesn't crash. is the reboot something you saw on fly specifically? might be worth framing it as an observed fly side-effect vs iii behavior.

Comment thread docs/next/using-iii/deploy-fly.mdx Outdated
`configuration`, `iii-observability`).
- Registry workers that deploy as **binaries**: `iii worker add database` resolves to a
binary (`x86_64-unknown-linux-gnu`) and runs as a plain host child process
(`sandbox: n/a`), no `/dev/kvm` needed. Check a worker's deploy type before adding it;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could we point to where the deploy type actually lives? it's the top-level deploy: field in the worker's iii.worker.yaml — binary runs as a host process (ok on fly), while image and bundle both go through libkrun (need /dev/kvm).

Comment thread docs/next/using-iii/deploy-fly.mdx Outdated
```bash
fly logs -a iii-engine

curl https://iii-engine.fly.dev/orders -X POST \

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

where does /orders come from? the only worker example registers database::query/execute — there's no /orders route created anywhere in the guide, so this curl would 404. should we use <your route> or add a small http handler earlier so the verify step is reproducible?

Comment thread docs/next/using-iii/deploy-fly.mdx
Comment thread docs/next/using-iii/deploy-fly.mdx Outdated
[custom domain](https://fly.io/docs/networking/custom-domain/) works the same way with
a `fly certs` entry.
- **WebSocket surfaces** (stream `3112`, RBAC `49135`): Fly Proxy passes WebSocket
upgrades through natively. Expose each on its own service port; each WS surface is

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this says expose stream 3112, but a few lines down (and the checklist) say keep 3112 private — which is it? grouping it with 49135 (the rbac port that is public) makes it read like both should be exposed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants