Getting started
PainScaler runs as two pieces:
- Backend - Go binary on port
8080. Calls ZPA via the officialzscaler-sdk-go, builds an in-memory index, exposes a small JSON API. - Frontend - React + Vite + PatternFly v6 SPA. In production, served
static. In dev, Vite dev server proxies
/apito the backend.
You can run them on the same host (single binary plus a static bundle), or as
two containers behind a reverse proxy. The Docker stack in deploy/ does the
second for you, with auth bolted on. See Docker
compose when you are ready.
Prerequisites
| Thing | Version |
|---|---|
| Go | 1.25 or newer |
| Node | 22 LTS |
| Yarn | 1.x (classic) |
| ZPA tenant | Read-only API client recommended |
You also need ZPA OAuth client credentials. The tool reads them from environment variables - see Environment variables.
First run, native
git clone --recurse-submodules git@github.com:FakeApate/painscaler.gitcd painscalercp example.env .env$EDITOR .env # fill in ZPA_* values
source .envgo run ./cmd/painscalerIn another terminal:
cd frontendyarn installyarn dev # http://localhost:5173, proxies /api to :8080Open http://localhost:5173, watch the loading screen run through the fetch
phases, then start poking around.
First run, Docker
cd deploymake init # generate .env + secrets + render configs$EDITOR .env # fill ZPA_* valuesmake buildmake upmake show-admin # generated admin passwordmake ca # extracts Caddy root CATrust painscaler-ca.crt in your browser, add painscaler.lan and auth.lan
to /etc/hosts, then visit https://painscaler.lan.
Full deploy walkthrough: Docker compose.
What you should see
After the index builds (a few seconds on a small tenant, longer on a busy one), you have access to:
- A search bar that hits every resource type at once.
- A reachability query: paste a hostname, see every segment + policy that covers it.
- A simulator: pick a segment, fake some SCIM groups, get the verdict and trace.
- A flow graph: SCIM groups, policies, connector groups, segment groups, segments, with route highlighting.
- Analytics tabs: orphans, overlaps, shadows, blast radius, connector load, SCIM reach.
Read-only is non-negotiable
PainScaler only reads from ZPA. It does not write, mutate, or push anything. Your API client should be read-only. If your tenant policy forces you to use a write-capable client, that is on you, not the tool.
Next
- Policy simulator - the FSM and the trace
- Search and reachability - what the index gives you
- ZPA data-model quirks - the things that cost hours to discover the hard way