OpenZiti → Zscaler Private Access
OpenZiti ↔ Zscaler Private Access: integration to migration path.
Private access is load-bearing — break the broker and every internal app goes dark at once. So OpenZiti goes live alongside Zscaler Private Access first, the Ziti tunneler and ZCC running side by side while ZPA keeps serving every App Segment, and only takes over one app's FQDN at a time. No flag day, no forced re-enrollment, and every phase rolls back in minutes.
ZPA and OpenZiti are structurally the same shape — per-app, identity-aware, dark services with outbound-only connectors — so the crypto is the easy part. The honest gaps are PoP density, the integrated ZIA + CASB + DLP suite, the curated posture catalogue and Browser Isolation. We name them up front, because the rest of this only matters if you can trust it.
The idea
Run alongside ZPA first. Retire it App Segment by App Segment last.
The topology that makes this zero-downtime is a per-App-Segment cutover across two identical shapes. OpenZiti deploys in the same zones as your ZPA App Connectors, each App Segment matched one-to-one by a Ziti Service, and both clients coexist on the endpoint. The cutover knob is a single MDM-pushed change: ZCC excludes the FQDN from interception and the Ziti tunneler intercepts it instead — applied before the Dial policy is granted, so the two never fight over the same name. Both halves federate to the same IdP, app teams see the same FQDN, and the transport changes underneath — each app migrated independently, each reversible, never a single big cutover. Big-bang cutovers fail on DNS, not crypto.
The phases
Seven steps. Each one reversible.
Baseline & inventory
We read the ZPA admin API: every App Segment's FQDNs, ports and protocol, its Connector Group and policy bindings, daily distinct users, P95 latency to the nearest Service Edge, posture conditions, Browser Access status, SAML group dependency, and a DLP/CASB sensitivity tag. Read-only — nothing moves.
OpenZiti goes live alongside ZPA
A Ziti Controller stands up in HA — three-plus nodes — federated to the same IdP via an External JWT Signer, with one internal canary edge router and a canary Service on a non-production FQDN. A test identity group enrols the Ziti tunneler alongside ZCC and Dials the canary Service. No production App Segment is touched.
New App Segments default to OpenZiti
Every net-new internal app is published as a Ziti Service from day one — intercept, Bind from the app's runtime identity, Dial from the consuming user-group role — while ZPA keeps serving every pre-existing App Segment. A new-app intake runbook routes every greenfield request to Ziti.
Migrate existing App Segments, cohort by cohort
Each previously-ZPA-served App Segment gets a mirrored Ziti Service. In low / medium / high blast-radius waves we MDM-push a ZCC config that excludes the FQDN from ZPA interception for a 10% cohort so the Ziti tunneler intercepts instead, SIEM-watch for residual ZPA traffic, then ramp to 100% over 7 to 14 days. The ZPA App Segment is held in policy through the bake — the App Connector listens but receives no traffic.
Decide every Browser Access segment
OpenZiti has no native clientless HTTP portal, so each ZPA Browser Access App Segment gets an explicit decision: republish behind a Ziti-fronted HTTP reverse proxy for tunneler-equipped users, retain it on ZPA Browser Access permanently, or replace it with a separate clientless gateway. Genuine clientless users — contractors, kiosks — are never cut over without a resolution.
Drain the ZPA App Connectors
Connector Groups that serve only migrated App Segments are set read-only for a 14-day evidence window, with the hosts kept running warm for rollback. We watch for zero ZPA tunnel-established events from those groups before going further.
Retire the ZPA tenant (full replacement only)
Connector Groups are disabled, App Segments removed from policy, the ZPA SAML trust revoked at the IdP, and ZCC uninstalled via MDM in cohorts. The tenant is held read-only for 30 days as an evidence window before the contract is closed.
Feature parity
Where OpenZiti matches ZPA, and where it does not.
| Capability | OpenZiti | Zscaler Private Access | Parity |
|---|---|---|---|
| Tunnel / transport | Edge-router fabric, outbound mTLS (xchacha20-poly1305 + Ed25519) | ZCC to Public Service Edge proprietary tunnel | At parity |
| Per-app ZTNA | Service (payments.ziti) + Bind/Dial Service Policy | App Segment (FQDN+port) + Access Policy | At parity |
| Identity federation | External JWT Signer (IdP JWKS, enrollment-time) | SAML to the ZPA tenant (runtime per-session assertion) | Partial |
| Device posture | MFA / OS / MAC / process / domain checks, uncurated, enrollment-time + episodic | ZCC posture against a Zscaler-curated EDR/OS catalogue, continuous | Partial |
| ACL policy model | Bind/Dial Service Policy via identity roles, deny-by-default | ZPA Access Policy (user/group + App Segment) | At parity |
| Global edge / PoP | Self-built edge-router fleet; latency is placement-dependent | Anycast Public Service Edge (global PoPs, sub-50ms first hop) | SaaS only |
| NAT traversal / relay | Outbound-dial both ends to an edge router; no inbound port | Outbound-dial ZCC + App Connector to the Service Edge | At parity |
| DNS | Tunneler intercept FQDN / wildcard interception | ZCC DNS interception for App Segment FQDNs | At parity |
| Browser isolation | None | RBI integration at the Service Edge | SaaS only |
| Clientless / browser access | None native (SDK or tunneler required) | Browser Access (clientless reverse proxy at the Service Edge) | SaaS only |
| DLP / CASB integration | None — ZTNA only | Integrated ZIA + CASB + DLP suite | SaaS only |
| RBAC / admin | Controller console + API | ZPA admin console + API | At parity |
| Deployment & HA | Self-hosted Controller (3+ nodes) + edge routers, your on-call | Vendor-operated edge + 24x7 NOC | SaaS only |
| Cost model | Self-hosted compute + ops; NetFoundry support tier | Per-user ZPA subscription | Partial |
| Compliance | Boundary back inside your SSP | Inherited SOC 2 / FedRAMP | SaaS only |
What we're honest about
The caveats most vendors leave out.
Global PoP density is a placement problem you own
ZPA's anycast Service Edge gives a sub-50ms first hop almost anywhere in the world; an OSS edge-router fleet matches that only where you place routers and pay the latency cost in between. This is not a protocol gap — it is a build. We plan edge-router placement against your per-region latency SLO, and where global road-warriors are the binding constraint we keep ZPA in scope for that population permanently rather than ship them a slower path.
ZIA, CASB, DLP and Browser Isolation are out of scope
Zscaler's lever is a single pane covering ZTNA plus SWG, CASB, DLP and RBI. OpenZiti is ZTNA only — it replaces ZPA, not the rest of the suite. If those are in production use we scope their replacement as separate workstreams before retiring anything, and where a hard requirement remains we retire only the ZTNA half and keep ZIA. We will not pretend a tunnel does data-loss prevention or browser isolation.
The posture catalogue is curated; Ziti's is not
ZCC ships a Zscaler-curated catalogue — which CrowdStrike sensor versions and OS builds count as healthy — and reports it continuously. OpenZiti's posture set is narrower and uncurated: you assert which builds and EDR processes pass, and its auth is enrollment-time x509/Ed25519, so continuous evaluation needs explicit re-attestation. We either integrate an EDR's compliance API into custom Ziti posture checks or document the reduction in granularity and cadence, and get auditor sign-off on the substitution.
Self-hosting moves uptime and compliance onto you
Zscaler operates the Service Edge and underwrites its uptime; with OpenZiti the Controller and edge-router fleet are your on-call, and ZPA's inherited SOC 2 / FedRAMP boundary falls back inside your SSP. We run it as a managed service: a three-plus-node multi-AZ Controller, a monitored edge-router fleet capacity-planned from your ZPA session telemetry, a break-glass admin identity in a secrets vault, a tested DR restore with a measured RTO, and at least one audit cycle of overlap before ZPA is retired as control evidence.
Why this beats a flag day
Reversible at every step, with a real soak before anything is cut.
Every phase rolls back in under 15 minutes while both clients remain installed — a ZCC-exclusion revert or a Connector-Group re-enable, never a rebuild, because the ZPA App Segment is held in policy through the entire bake. And before the ZPA contract is closed, each migrated segment soaks at least 30 consecutive days with zero ZPA brokered-session events, the global-remote-user latency SLO is met without ZPA in path, and the DR Controller restore is exercised end to end. A flag day gives you neither; this gives you both.
See whether your private access migrates cleanly.
A 30-minute call with a senior network engineer. We classify every App Segment by transport and Browser Access, map your posture conditions against what Ziti can assert, size the edge-router fleet against your per-region latency SLO, and tell you honestly whether your end state is full ZPA retirement or coexistence for global users — before you commit to anything.
Map my migration →