benvin 335c61383a
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/build Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
Render the NAT tier into per-device configs
The compiler now projects the global NAT intents through each device's bindings
into the rendered config:
- snat/masquerade: renders on a device that binds the egress zone (and, when the
  source is a zone, that zone too), resolving the egress interface — this
  auto-scopes masquerade to edge devices. A literal-CIDR source needs only the
  egress binding.
- netmap: renders on the device its anchor (device:zone|interface) names,
  resolving a zone anchor to its bound interface.
- 1:1 nat: renders on the device it is bound to.
Adds RenderedSNAT/RenderedNetmap/RenderedNAT to the rendered config, fetches the
tiers in Compile, and unit-tests binding-scoping (edge vs interior/other device).
2026-07-21 22:19:20 +10:00

tomswallapi

Fleet control plane for tomswall.

Declare zones, address groups, and firewall policy once; the API compiles each intent into the concrete per-device rules every firewall and router on the path needs, and serves each device its rendered tomswall.yaml. A connection that crosses several firewalls — src → rt1 → rt2 → rt3 → dest — is expressed as a single rule.

The full design (data model, compile algorithm, invariants, agent protocol) lives in DESIGN.md in the tomswall repo.

Architecture

  • tomswallapi (this repo) — Terraform-managed HTTP API. Stores the fleet model in Postgres, peers with FRR for reachability, compiles intents into per-device configs, and serves them.
  • tomswall agent — pulls its rendered config, runs the existing differential apply, maintains dns-backed ipsets via an on-device resolver, and reports the config generation it has applied. Does not fail closed on API-unreachable.

Running locally

docker compose up --build
# API on :8000, Postgres on :5432
curl -s localhost:8000/healthz

Configuration

All configuration is via environment variables (TOMSWALLAPI_*):

var default purpose
TOMSWALLAPI_LISTEN_ADDR :8000 HTTP listen address
TOMSWALLAPI_DB_HOST localhost Postgres host
TOMSWALLAPI_DB_PORT 5432 Postgres port
TOMSWALLAPI_DB_USER tomswallapi Postgres user
TOMSWALLAPI_DB_PASSWORD Postgres password
TOMSWALLAPI_DB_NAME tomswallapi Postgres database
TOMSWALLAPI_DB_SSLMODE disable Postgres sslmode
TOMSWALLAPI_WRITE_TOKEN bearer token guarding mutating endpoints (Terraform)
TOMSWALLAPI_AGENT_TOKEN bearer token guarding the per-device config endpoint (agents)
TOMSWALLAPI_IPLOCATE_API_KEY iplocate key for ASN address-group expansion

Migrations are embedded and applied automatically on startup.

Development

make build      # build the binary
make test       # run tests
make lint       # gofmt + go vet
make run        # build and run

Releases

make patch|minor|major computes and pushes the next v* tag, which triggers the Woodpecker docker pipeline to build and push the image to git.unkin.net/unkin/tomswallapi.

S
Description
Fleet control plane for tomswall firewalls. Terraform-managed API that compiles fleet-wide zones, address groups, and firewall policy into per-device tomswall configs; agents pull and differentially apply.
Readme 238 KiB
Languages
Go 99.1%
Makefile 0.7%
Dockerfile 0.2%