You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
No CLI command applies one Domain: its vhost and certificate come only from migrate, which converges every server #87
Found while deploying Abecra's staging on 2026-10-19 to a server lent from another fleet. That server's baseline, firewall and services belong to its owner's project, so the Abecra project may run per-component cloudfall deploy on it, never migrate or baseline convergence.
The Domain was declared (abecra.cloudfall.dev, proxy and origin on the lent server), but there was no safe way to apply it:
cloudfall migrate is the only CLI path to domains.yml (sdk/src/cloudfall/migrate.py: steps domains-http, dns-verify, domains-tls), and the same plan runs baseline and services on every declared server first
the converge_domains MCP tool runs domains.yml without the baseline, but it is MCP only, renders every declared domain on every server in cloudfall_servers, and takes no domain or server argument
task domains:deploy exists in the repository Taskfile, not in the installed CLI
So the nginx vhost and the Let's Encrypt certificate were written by hand, outside the receipts, and the next domains.yml run from anywhere will overwrite that file with no record of what it replaced.
apply runs cloudfall_nginx_site for one Domain, limited to its proxy.server (and origin.server when it differs); without --yes it shows the plan, like deploy
--issue-certificate runs the HTTP-then-TLS sequence migrate uses (domains-http, then issuance), refusing when DNS for primaryName and aliases does not resolve to the proxy server
It touches no baseline, firewall or service, so it is safe on a server whose baseline another project owns
A DeploymentReceipt per run, as today, with the hash of the vhost it replaced if one was there
The same scoping (domain argument) added to the converge_domains MCP tool
Alternatives
migrate --only domains-http,domains-tls: reuses the plan, but a step filter on a resumable plan is easy to get wrong and still reads as "migrate"
A server-level managedBaseline: false flag that makes migrate skip baseline on lent servers: useful too, but a per-domain command is needed regardless (adding a domain to a running fleet should not mean rerunning a migration)
Acceptance
In a project with two servers, cloudfall domains apply <d> --yes changes only the Domain's proxy server, and its Ansible run reports no baseline, firewall or service tasks
--issue-certificate on a fresh domain ends with a valid Let's Encrypt certificate, certbot.timer enabled, and a receipt; a second run reports no changes
Without --yes it exits 0 and changes nothing
An unknown domain id fails with CONFIG_INVALID before any SSH connection
Confirmed on main (348ed73): cloudfall migrate (sdk/src/cloudfall/migrate.py) is the only CLI path to domains.yml, and its plan converges baseline and services first; converge_domains is MCP only and takes no domain or server. A scoped cloudfall domains apply / observe is a new command group with its own plan, receipts and certificate sequence, so it gets a spec with acceptance criteria first, covering the converge_domains scoping too.
Writing it alongside #88's spec, since both extend the per-component deploy shape (plan without --yes, a receipt per run).
The spec PR is being written now (docs/specs/004-domains-apply.md); I'll put its link and the hold line here. Merging it is the approval.
The spec is in #100 (docs/specs/004-domains-apply.md). Where it departs from the issue, following the code: an unknown domain exits PRECONDITION like deploy's unknown component, not CONFIG_INVALID; apply touches only the proxy server, since no playbook acts on origin.server; DNS is checked once before a single role run, and skipped for proxied edges as migrate does. The new optional receipt field means an older cloudfall rejects the newer receipts, which is worth a look in review.
Activity
shipmill-romamo commentedon Oct 20, 2026
Triage: feature.
Confirmed on main (348ed73):
cloudfall migrate(sdk/src/cloudfall/migrate.py) is the only CLI path todomains.yml, and its plan convergesbaselineandservicesfirst;converge_domainsis MCP only and takes no domain or server. A scopedcloudfall domains apply/observeis a new command group with its own plan, receipts and certificate sequence, so it gets a spec with acceptance criteria first, covering theconverge_domainsscoping too.Writing it alongside #88's spec, since both extend the per-component deploy shape (plan without
--yes, a receipt per run).The spec PR is being written now (
docs/specs/004-domains-apply.md); I'll put its link and the hold line here. Merging it is the approval.shipmill-romamo commentedon Oct 20, 2026
The spec is in #100 (
docs/specs/004-domains-apply.md). Where it departs from the issue, following the code: an unknown domain exitsPRECONDITIONlikedeploy's unknown component, notCONFIG_INVALID;applytouches only the proxy server, since no playbook acts onorigin.server; DNS is checked once before a single role run, and skipped for proxied edges asmigratedoes. The new optional receipt field means an oldercloudfallrejects the newer receipts, which is worth a look in review.On hold: the build waits on #100, the spec