Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ Debian servers without Kubernetes (see the [fleet goals](docs/fleet-goals.md)),
on a config the team already owns. This document describes the durable
design; [`ROADMAP.md`](ROADMAP.md) is the authoritative source for what is
implemented today, and the [brownfield design](docs/brownfield-design.md)
describes the proposed next step, none of which is built.
describes the next step, whose operations catalog, gate and record are
built while safe edits and autonomy from the record are not.

Every layer keeps the same invariants: no action without declared config, no
status without evidence, no compliance without audit, no decision without a
Expand Down
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,11 @@ Notable changes to Cloudfall. The format follows

### Changed

- The README, the site, the roadmap and the architecture say what is built
on a team's own Ansible repository (the operations catalog, the gate,
decision records and `cloudfall why`) instead of calling it unbuilt, show
a real `cloudfall why` answer, and address both teams leaving a PaaS and
teams already running Ansible
- The README opens with what Cloudfall is, a diagram of the gate, a short
quickstart and a guide index; the long walkthroughs moved to
[docs/getting-started.md](docs/getting-started.md). The repository has issue
Expand Down
6 changes: 2 additions & 4 deletions MANIFESTO.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,10 +81,8 @@ marketing copy; it is the release policy.
## 8 · Open core, never crippled

Cloudfall is AGPL-3.0. The free tool must be genuinely sufficient to leave
a PaaS and run your own server; sustainability comes from the hosted
operator and commercial licensing, never from holding back the open core.
What is free stays free, and the line between the two is stated in the
README, not discovered at checkout.
a PaaS and run your own server; sustainability never comes from holding
back the open core. What is free stays free.

---

Expand Down
75 changes: 51 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,15 +44,44 @@ flowchart LR
R -.->|earned autonomy| G
```

### What the record looks like

Ask why something happened and Cloudfall answers from the record alone. This
is a real decision from the maintainer's six-host production fleet, a
`converge` run of the team's own `site.yml` (output abridged to the story):

```console
$ cloudfall why --operation converge
It was based on 6 host snapshots in tmp/observed, the latest observed at 2026-09-21T10:39:30Z.
At 2026-09-22T19:38:45Z the mutating operation converge (site.yml) was proposed against the whole fleet with no inputs.
Check mode would have changed no host and left 3 hosts untouched; the diff is decisions/converge-20260922193845.diff (sha256 4c8458ca26c5…, 48061 bytes).
It waited for an approval: a mutating operation runs in check mode first and waits for an approval of the recorded diff.
roman approved it at 2026-09-22T19:39:51Z.
The run at 2026-09-22T19:39:51Z exited 0 and changed no host; the log is decisions/converge-20260922193845-execution.log.
The verify step at 2026-09-22T19:40:39Z exited 0 and changed no host; the log is decisions/converge-20260922193845-verify.log.
It ended verified: the run succeeded and the verify step changed nothing.
```

Every sentence is drawn from a field of the record. `--format html` renders
the same answer as one page, and agents get it as the `why` tool.

## Who it is for

Teams with one to twenty servers and no platform hire: founders leaving a
PaaS whose bill crossed $1,000 a month, and anyone whose servers are already
run by Claude Code, Codex or another agent. Today Cloudfall moves your
applications and databases onto one or two Hetzner-class servers you own
(hardened baseline, monitoring, PostgreSQL and Redis with backups that
**Founders leaving a PaaS.** A small production app with a database costs
about $83 a month on Render and runs on a Hetzner server for under €10.
Cloudfall moves your applications and databases onto one or two servers you
own (hardened baseline, monitoring, PostgreSQL and Redis with backups that
provably restore, health-gated deploys with rollback, a real DNS cutover),
and an always-on operator runs them there with a receipt for every action.
Start with the [Render migration guide](docs/render-migration-guide.md).

**Teams and agencies that already run Ansible.** Point Cloudfall at your own
repository: it reads your inventory, and each playbook you declare in
`operations/` becomes an operation with a risk level, a verify step and a
record. Your agent sees exactly those operations as tools, a mutating one
runs in check mode and waits for a person to approve the diff, and
`cloudfall why` answers for it afterwards. No import, no second copy of
your fleet. See the [brownfield design](docs/brownfield-design.md).

> **Proven live, not promised.** Everything implemented has run on
> disposable Hetzner Cloud Debian 13 servers: an application actually hosted
Expand Down Expand Up @@ -120,8 +149,8 @@ and drift audit to the live dashboard, is in

```console
uv run cloudfall import render render.yaml --application acme --server h1
uv run cloudfall migrate --build acme-api=main # show the plan
uv run cloudfall migrate --build acme-api=main --yes # run it
uv run cloudfall migrate --build web=main # show the plan
uv run cloudfall migrate --build web=main --yes # run it
```

The importer never guesses silently: `IMPORT-REPORT.md` records what was not
Expand Down Expand Up @@ -161,8 +190,8 @@ contracts. See [ARCHITECTURE.md](ARCHITECTURE.md).

## Status

Cloudfall is pre-1.0 and honestly labeled. Implemented and proven live on
disposable Debian targets:
Cloudfall is pre-1.0 and honestly labeled. On servers Cloudfall sets up,
implemented and proven live on disposable Debian targets:

- Typed YAML config with JSON Schemas, deterministic Ansible inventory,
read-only inspection and config-versus-observed drift audit
Expand All @@ -175,18 +204,19 @@ disposable Debian targets:
- `cloudfall mcp serve` and the always-on operator with receipted proposals
and policy-bounded autonomy

Not yet validated live: bare-metal RAID/storage provisioning. Next up: the
fleet-density track (resource sharing, node drain, PostgreSQL point-in-time
recovery). See the [roadmap](ROADMAP.md).
On your own Ansible repository, implemented and run on the maintainer's
production fleet:

### Direction: your Ansible, not ours
- Read-only observation through your inventory and `ansible.cfg`, and drift
audit without a Cloudfall project
- The operations catalog, the check-then-approve gate, and one decision
record per operation with its evidence, diff, approver and verify result
- `cloudfall why` and `cloudfall mcp serve --repository`, where the tool
list is your catalog

Most teams that would use Cloudfall already run Ansible. The next step reads
their inventory as the only config and exposes each of their playbooks to
the agent as a declared operation with a risk level, a verify step and an
audit entry. Ansible is the hand, the agent is the brain, Cloudfall is the
conscience. Designed, not yet built:
[docs/brownfield-design.md](docs/brownfield-design.md).
Not yet validated live: bare-metal RAID/storage provisioning. Not built yet:
safe edits of your inventory and variables, and autonomy computed from the
record. See the [roadmap](ROADMAP.md).

## Community

Expand All @@ -197,8 +227,5 @@ conscience. Designed, not yet built:

## License

Everything in this repository is free under the
[GNU AGPL-3.0-or-later](LICENSE) and sufficient on its own. The hosted
always-on operator and commercial licensing are how the project sustains
itself; neither holds back the open core. Commercial licensing exceptions
are available from the copyright holder.
Cloudfall is free under the [GNU AGPL-3.0-or-later](LICENSE). Commercial
licensing exceptions are available from the copyright holder.
7 changes: 5 additions & 2 deletions ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,11 @@ The first story, proven live in M0–M10:
> from GitHub with health checks and rollback, and a DNS cutover checklist.
> An always-on operator then runs it there, with a receipt for every action.

The second story, designed and not yet built (M15–M17, see the
[brownfield design](docs/brownfield-design.md)):
The second story, under way (M15–M17, see the
[brownfield design](docs/brownfield-design.md)): the operations catalog,
the gate and the decision record are built and have run on the
maintainer's own production fleet; safe edits and autonomy from the record
are not built yet:

> A team that already runs Ansible points its agent at its own repository.
> Cloudfall reads their inventory as the only config, exposes each of their
Expand Down
73 changes: 65 additions & 8 deletions site/public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@
}
.card h3 { font-size: 18px; margin-bottom: 10px; letter-spacing: -0.01em; }
.card p { color: var(--text-dim); font-size: 15px; }
.card code, .steps code, .proof code {
.card code, .steps code, .proof code, .section-sub code {
font-family: var(--mono); font-size: 0.88em;
background: var(--accent-soft); color: var(--accent);
padding: 1.5px 6px; border-radius: 5px; white-space: nowrap;
Expand Down Expand Up @@ -237,6 +237,7 @@
</a>
<div class="links">
<a class="hide-sm" href="#why">Why</a>
<a class="hide-sm" href="#record">The record</a>
<a class="hide-sm" href="#how">How it works</a>
<a class="hide-sm" href="#status">Status</a>
<a class="hide-sm" href="/manifesto">Manifesto</a>
Expand Down Expand Up @@ -308,6 +309,61 @@ <h1>Your servers, run by an agent.<br>With a <span class="accent">record</span>
</div>
</div>

<section id="record">
<div class="wrap">
<div class="kicker">The record</div>
<h2>Ask why. Get the story, not a log.</h2>
<p class="section-sub">
A real decision from the maintainer's six-host production fleet: a
<code>converge</code> of the team's own <code>site.yml</code>. Every sentence
is drawn from a field of the record, as JSON for agents or as one page for people.
</p>
<div class="term" style="margin-top:32px">
<div class="term-bar">
<span></span><span></span><span></span>
<div class="title">cloudfall why</div>
</div>
<pre style="white-space:pre-wrap;word-break:break-word"><span class="p">$</span> <span class="cmd">cloudfall why --operation converge</span>
<span class="step">It was based on 6 host snapshots in tmp/observed, the latest observed at 2026-09-21T10:39:30Z.</span>
<span class="step">At 2026-09-22T19:38:45Z the mutating operation converge (site.yml) was proposed against the whole fleet with no inputs.</span>
<span class="step">Check mode would have changed no host and left 3 hosts untouched; the diff is decisions/converge-20260922193845.diff (sha256 4c8458ca26c5…, 48061 bytes).</span>
<span class="pause">It waited for an approval: a mutating operation runs in check mode first and waits for an approval of the recorded diff.</span>
<span class="ok">roman approved it at 2026-09-22T19:39:51Z.</span>
<span class="step">The run at 2026-09-22T19:39:51Z exited 0 and changed no host; the log is decisions/converge-20260922193845-execution.log.</span>
<span class="step">The verify step at 2026-09-22T19:40:39Z exited 0 and changed no host; the log is decisions/converge-20260922193845-verify.log.</span>
<span class="ok">It ended verified: the run succeeded and the verify step changed nothing.</span></pre>
</div>
</div>
</section>

<section id="who">
<div class="wrap">
<div class="kicker">Who it is for</div>
<h2>Two ways in, one record</h2>
<div class="grid">
<div class="card">
<h3>Leaving a PaaS</h3>
<p>
A small production app with a database costs about $83 a month on
Render and runs on a Hetzner server for under €10. Cloudfall moves
your applications and data onto servers you own, and an always-on
operator runs them there with a receipt for every action.
</p>
</div>
<div class="card">
<h3>Already running Ansible</h3>
<p>
Point Cloudfall at your own repository. Each playbook you declare
becomes an operation with a risk level, a verify step and a record;
your agent sees exactly those as tools, a mutating one waits for a
person to approve its check-mode diff. No import, no second copy of
your fleet.
</p>
</div>
</div>
</div>
</section>

<section id="why">
<div class="wrap">
<div class="kicker">Why Cloudfall</div>
Expand Down Expand Up @@ -359,9 +415,9 @@ <h3>Autonomy earned, never assumed</h3>
<h3>The bill buys computers, not margins</h3>
<p>
A steady cloud bill is mostly margin on commodity compute and
managed databases. The same workload runs on one or two
Hetzner-class servers for a tenth of the price, and the
difference is runway, every year.
managed databases: an app that costs $83 a month on Render runs
on a Hetzner server for under €10. The difference is runway,
every year.
</p>
</div>
<div class="card">
Expand Down Expand Up @@ -439,6 +495,7 @@ <h3>Implemented and proven live</h3>
<li><code>cloudfall mcp serve</code> agent server, confined to one fleet</li>
<li>sops/age secret references rendered to per-component env files</li>
<li>Always-on operator: receipted proposals, policy-bounded autonomy</li>
<li>On your own Ansible repository: declared operations, check-then-approve gate, decision records and <code>cloudfall why</code>, run on the maintainer's production fleet</li>
</ul>
</div>
<div class="status-card next">
Expand All @@ -448,7 +505,7 @@ <h3>Not there yet</h3>
<li>Broader service catalog: MySQL, Elasticsearch, RabbitMQ, Node runtimes</li>
<li>Enforced per-component resource limits for shared nodes</li>
<li>Importers beyond Render</li>
<li>Your existing Ansible inventory and playbooks as the config and the agent's tool list: <a href="https://github.com/cloudfall-dev/cloudfall/blob/main/docs/brownfield-design.md">design written</a>, nothing built</li>
<li>Safe edits of your inventory and variables, and autonomy computed from the record (<a href="https://github.com/cloudfall-dev/cloudfall/blob/main/docs/brownfield-design.md">design</a>)</li>
</ul>
</div>
</div>
Expand All @@ -459,9 +516,9 @@ <h3>Not there yet</h3>
<div class="wrap">
<div class="kicker">Get started</div>
<h2>Sixty seconds to see how it thinks</h2>
<div class="install"><span class="p">$</span> git clone https://github.com/cloudfall-dev/cloudfall && cd cloudfall
<span class="p">$</span> uv run cloudfall config validate --project config/examples
<span class="p">$</span> uv run cloudfall init ../my-project</div>
<div class="install"><span class="p">$</span> uv tool install cloudfall
<span class="p">$</span> uvx cloudfall init my-project && cd my-project && uv sync
<span class="p">$</span> uv run cloudfall config validate</div>
<div class="cta">
<a class="btn btn-primary" href="https://github.com/cloudfall-dev/cloudfall">Star on GitHub</a>
<a class="btn btn-ghost" href="https://github.com/cloudfall-dev/cloudfall/blob/main/ROADMAP.md">See the roadmap</a>
Expand Down
8 changes: 3 additions & 5 deletions site/public/manifesto.html
Original file line number Diff line number Diff line change
Expand Up @@ -319,11 +319,9 @@ <h2>Proven live or labeled unproven</h2>
<h2>Open core, never crippled</h2>
<p>
Cloudfall is AGPL-3.0. The free tool must be genuinely sufficient
to leave a PaaS and run your own server; sustainability comes from
the hosted operator and commercial licensing, never from holding
back the open core. <strong>What is free stays free, and the line
between the two is stated in the README, not discovered at
checkout.</strong>
to leave a PaaS and run your own server; sustainability never
comes from holding back the open core. <strong>What is free stays
free.</strong>
</p>
</div>

Expand Down
Loading