| last_verified | 2026-05-10 |
|---|---|
| verified_against | v0.2.4 |
| quadrant | tutorial |
| audience | developer |
Five minutes from a fresh machine to a backend service running behind Flowplane with a curl that proves traffic flowed through Envoy. Single happy path — no choices to make.
This tutorial gets you to a working gateway. Once you're here, the how-to recipes cover the next layer: multi-route exposes, JWT auth, OpenAPI export.
- Docker (or Podman — both auto-detected by the CLI)
- A POSIX shell,
curl, andtar(preinstalled on macOS and most Linux distros)
That's the whole list — Flowplane ships prebuilt binaries and pulls its container images automatically.
curl -fsSL https://raw.githubusercontent.com/rajeevramani/flowplane/main/scripts/install.sh | shThe installer detects your platform (macOS arm64 or Linux x86_64), downloads the latest release tarball from GitHub, and places the two binaries it ships with on your PATH:
flowplane— the control plane CLI you'll use from here on.flowplane-agent— a sidecar that runs alongside Envoy in dev mode, watching for misconfigurations Envoy detects and reporting them back to the control plane. The dev stack expects it.
The installer prefers /usr/local/bin and falls back to ~/.local/bin if that's not writable.
Need a pinned version or a custom install location?
install.sh --helpshows the flags.
Verify the install:
flowplane --version
flowplane-agent --versionBuilding from source (contributors only): see CONTRIBUTING.md —
make installwraps the twocargo installcommands.
cd ~ # init works from any directory
flowplane initflowplane init writes a Compose file to ~/.flowplane/docker-compose-init.yml and brings up the full dev stack:
| Service | Address |
|---|---|
| API | http://localhost:8080 |
| Swagger UI | http://localhost:8080/swagger-ui/ |
| httpbin | http://localhost:8000 (direct, not through Envoy) |
| Envoy | listeners on ports 10001-10020 (assigned by expose) |
flowplane-agent |
sidecar in Envoy's network namespace |
Dev mode skips Zitadel — a token is generated automatically and saved to ~/.flowplane/credentials. Every CLI command reads the credentials file automatically.
Confirm the auth mode:
curl http://localhost:8080/api/v1/auth/mode{"auth_mode":"dev"}If you previously ran
make demo(the prod-mode evaluation harness), remove its network before booting dev mode:docker network rm flowplane-network. The two stacks use the same network name and won't share it.
flowplane expose http://httpbin:80 --name demoExposed 'demo' -> http://httpbin:80
Port: 10001
Paths: /
curl http://localhost:10001/
A single expose call wires together four resources: a cluster pointing at httpbin:80, a route config with a catch-all route to that cluster, a virtual host, and a listener on the auto-assigned port. Envoy picks them up via xDS within a second or two.
Use
httpbin, notlocalhost. Inside the Compose network,localhostresolves to the container itself, not to the httpbin service. The CLI rejects loopback upstreams in dev mode for exactly this reason.
The port is auto-assigned from the 10001-10020 pool. On a fresh stack the first expose lands on 10001; if you've exposed services already, check the Port: line in the output.
curl http://localhost:10001/get{
"args": {},
"headers": {
"Accept": "*/*",
"Host": "localhost:10001",
"User-Agent": "curl/8.7.1",
"X-Envoy-Expected-Rq-Timeout-Ms": "15000"
},
"origin": "10.89.0.5",
"url": "http://localhost:10001/get"
}The X-Envoy-Expected-Rq-Timeout-Ms header is the proof: httpbin doesn't generate it, Envoy does. The request entered the gateway on port 10001, ran through the listener's filter chain, matched the catch-all route, and was forwarded to the httpbin:80 cluster.
That's the loop. You have a working API gateway.
flowplane down # stop containers, keep data
flowplane down --volumes # stop and delete all dataUse --volumes if you want a clean slate next time. Without it, the database, audit log, and any resources you created persist across init cycles.
You've shipped one route. The how-to recipes pick up from there:
- Expose an API — multi-path routing, multiple clusters, custom listener ports.
- Add JWT auth — drop a JWT validation filter in front of an exposed service.
- Learn and export OpenAPI — record live traffic and export an OpenAPI 3.1 spec.
Or, depending on where you go next:
- Quickstart — MCP — drive the same surface from an AI client instead of the CLI.
- Quickstart — Platform — the production install with Zitadel, mTLS, and multi-team auth.
- CLI reference — every command and flag.
- Filter reference — every registered filter type and its config schema.