Skip to content

Getting started

PainScaler runs as two pieces:

  • Backend - Go binary on port 8080. Calls ZPA via the official zscaler-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 /api to 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

ThingVersion
Go1.25 or newer
Node22 LTS
Yarn1.x (classic)
ZPA tenantRead-only API client recommended

You also need ZPA OAuth client credentials. The tool reads them from environment variables - see Environment variables.

First run, native

Terminal window
git clone --recurse-submodules git@github.com:FakeApate/painscaler.git
cd painscaler
cp example.env .env
$EDITOR .env # fill in ZPA_* values
source .env
go run ./cmd/painscaler

In another terminal:

Terminal window
cd frontend
yarn install
yarn dev # http://localhost:5173, proxies /api to :8080

Open http://localhost:5173, watch the loading screen run through the fetch phases, then start poking around.

First run, Docker

Terminal window
cd deploy
make init # generate .env + secrets + render configs
$EDITOR .env # fill ZPA_* values
make build
make up
make show-admin # generated admin password
make ca # extracts Caddy root CA

Trust 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