flow-iron 0.1.0

Infrastructure-as-code CLI — deploy Docker Compose apps with Caddy reverse proxy and Cloudflare DNS
Documentation
# iron

Infrastructure-as-code for the Flow ecosystem. The `flow` CLI reads `fleet.toml` and handles deployment, DNS, reverse proxy, and server bootstrapping.

## Stack

- **CLI:** Rust (`flow`)
- **Config:** `fleet.toml` (servers, apps, routing) + `fleet.env.toml` (secrets, gitignored)
- **Containers:** Docker Compose
- **Auto-deploy:** WUD (What's Up Docker) + docker-rollout for zero-downtime
- **Reverse proxy:** Caddy (automatic HTTPS)
- **DNS:** Cloudflare API
- **Server setup:** Ansible (hardening, Docker, firewall, fail2ban)

## Prerequisites

- Rust toolchain
- SSH agent with key for target servers
- `fleet.env.toml` with `cloudflare_api_token` and `ghcr_token`

## Quick Start

```bash
cargo build --release

# Initialize a new fleet.toml
flow init

# Deploy everything
flow deploy

# Deploy a single app
flow deploy site

# Fleet status
flow status
flow status --server flow-1

# Verify fleet.toml matches reality on servers
flow check
flow check --server flow-1

# Stop an app (keeps config, files, and DNS intact)
flow stop site
flow stop site --server flow-1

# Restart an app's containers
flow restart site
flow restart site --server flow-1

# Add an app to fleet.toml (then run flow deploy <app>)
flow app add site --image ghcr.io/org/site:latest --server flow-1 --port 3000 \
    --route flow.industries --health-path /health
flow app add worker --image ghcr.io/org/worker:latest --server flow-1
flow app add game --image ghcr.io/org/game:latest --server game-1 \
    --deploy-strategy recreate --port-map 9999:9999/tcp

# Add/remove sidecar services
flow app add-service auth postgres --image postgres:17 \
    --volume pgdata:/var/lib/postgresql/data --healthcheck "pg_isready -U flow"
flow app remove-service auth postgres

# Remove an app (tears down everything + removes from fleet.toml)
flow remove site
flow remove site --yes

# Tail logs
flow logs site
flow logs site -f
flow logs site --server flow-1

# Add a new server (creates DNS, bootstraps via Ansible)
flow server add fl-2 --ip 164.90.130.5
flow server add fl-2 --ip 164.90.130.5 --host custom.flow.industries
flow server add fl-2 --ip 164.90.130.5 --ssh-user ubuntu

# Remove a server
flow server remove fl-2

# Check server health
flow server check
flow server check flow-1
```

## Services

| App | Domain | Server | Strategy |
|-----|--------|--------|----------|
| site | flow.industries | flow-1 | rolling |
| auth | id.flow.industries | flow-1 | rolling |
| talk | flow.talk | flow-1 | rolling |
| game-web | flow.game | game-1 | rolling |
| game-server | *(direct TCP :9999)* | game-1 | recreate |

## How Deploy Works

```
flow deploy <app>
  → generate docker-compose.yml + .env from fleet.toml/fleet.env.toml
  → SSH to target server
  → upload files to /opt/flow/<app>/
  → docker compose pull + docker rollout (or recreate)
  → generate Caddy fragment, reload Caddy
  → ensure Cloudflare DNS A record
```

## Auto-Deploy

```
Service repo pushes code → CI builds image → pushes to GHCR
WUD detects new image → docker compose pull → docker rollout (zero-downtime)
```

## Adding a Service

1. Create service repo with Dockerfile + CI pushing to GHCR
2. `flow app add <name> --image ghcr.io/org/<name>:latest --server <srv> --port 3000 --route <domain>`
3. Add env vars to `fleet.env.toml` if needed
4. Run `flow deploy <name>`

## Project Structure

```
src/
  main.rs         CLI entrypoint
  lib.rs          public module re-exports
  cli.rs          clap command definitions
  config.rs       fleet.toml parsing and validation
  compose.rs      docker-compose.yml generation
  caddy.rs        Caddy reverse proxy fragments
  cloudflare.rs   DNS A record management
  deploy.rs       full deploy pipeline
  stop.rs         stop app containers
  restart.rs      restart app containers
  remove.rs       remove app (teardown + config cleanup)
  check.rs        verify fleet.toml matches server reality
  init.rs         initialize new fleet.toml
  app.rs          app add, add-service, remove-service
  server.rs       server add/remove/check
  ssh.rs          SSH connection pool
  status.rs       fleet status display
  logs.rs         log tailing
  ui.rs           terminal output helpers
tests/
  config.rs       config parsing and validation
  compose.rs      compose generation
  caddy.rs        Caddy fragment generation
  cloudflare.rs   Cloudflare API
  init.rs         init command
  app.rs          app management
  server.rs       server management
ansible/
  setup.yml       server bootstrapping playbook
  ansible.cfg     Ansible configuration
  requirements.yml  Galaxy role dependencies
  group_vars/     host group variables
stacks/
  caddy/
    docker-compose.yml  shared Caddy reverse proxy
  wud/
    docker-compose.yml  WUD auto-deploy watcher
    rollout.sh          zero-downtime deploy script
fleet.toml        server and app definitions
fleet.env.toml    secrets and env vars (gitignored)
```