Date: 2026-05-11
Time: 15:39
This is an FTL2 AI-loop rule that ensures Caddy reverse proxy is correctly configured on the stargate host, proxying stargate.catbeez18.com to localhost:8000. It follows the observe/condition/action pattern: observe system state, check if remediation is needed, then converge to the desired state. This rule was auto-generated by the ftl2-ai-loop system.
This rule is not called directly — it is loaded and executed by the FTL2 AI reconciliation loop. The loop evaluates it periodically or on trigger.
The file defines three top-level constructs:
observe — a list of observation tasks run on the stargate host to gather current state (Caddyfile content, service status, firewall rules)condition(state) — an async function that returns True if the system has drifted from desired stateaction(ftl) — an async function that converges the system to desired state
# The condition receives observed state as a dict keyed by observation name
async def condition(state: dict) -> bool:
caddyfile = state.get("caddyfile_content", {}).get("stdout", "")
...
# The action receives the ftl runtime for executing modules against hosts
async def action(ftl) -> None:
await ftl["stargate"].copy(content=..., dest="/etc/caddy/Caddyfile", ...)
Observations use the command module with cmd and host params. Each observation is named and its results appear in the state dict passed to condition().
Action modules used:
| Module | Purpose | Key Params |
|--------|---------|------------|
| copy | Deploy file content | content, dest, owner, group, mode |
| ansible.posix.firewalld | Manage firewall rules | service, permanent, immediate, state |
| service | Manage systemd services | name, state, enabled |
Host targeting: All operations target "stargate" via ftl["stargate"].
Expected Caddyfile content:
stargate.catbeez18.com {
reverse_proxy localhost:8000
}
observe list is duplicated in the file (appears twice with slightly different docstrings) — likely a copy-paste artifact. The AI-loop runtime presumably uses the last definition.|| true to prevent non-zero exit codes from halting observation (graceful failure if files/services don't exist yet).condition function checks three independent concerns: Caddyfile correctness, caddy service active+enabled, and firewall http/https services. Any single drift triggers the full action.action always applies all three fixes (Caddyfile, firewall, service) regardless of which specific check failed — a full convergence approach rather than targeted remediation.permanent=True and immediate=True, so they persist across reboots and take effect immediately.copy, service, and ansible.posix.firewalld modules via the ftl host accessorstargate in the FTL2 inventory