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.

0

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.

Users see: No user impact.

Rollback: N/A

1

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.

Users see: None for production users. Canary users install the Ziti tunneler next to ZCC.

Rollback: Delete the Controller — no production App Segment trusts it yet. Under 15 minutes.

2

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.

Users see: Users with the tunneler reach new apps natively; users without it cannot — which is intentional, and drives tunneler rollout.

Rollback: Per app: republish the same FQDN as a ZPA App Segment and revert the intake routing. Under 15 minutes.

3

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.

Users see: None when done right — same FQDN, transport changed underneath. P95 latency may shift with edge-router versus Service-Edge placement.

Rollback: Per App Segment: revert the MDM ZCC exclusion, ZCC re-intercepts, and the ZPA App Segment immediately resumes carrying traffic — it was never removed. Under 15 minutes.

4

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.

Users see: Tunneler users and retained Browser Access users: none. Migrated clientless users without a replacement: a hard break, so we don't enter without resolving it first.

Rollback: Per App Segment: republish via ZPA Browser Access from the Phase 0 inventory. Under 15 minutes.

5

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.

Users see: None.

Rollback: Re-enable the Connector Group; rolling back the FQDN traffic itself is the per-FQDN ZCC-exclusion revert from Phase 3. Under 15 minutes.

6

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.

Users see: None for migrated segments; the ZCC icon disappears.

Rollback: Within the 30-day window, reactivate the tenant, redeploy ZCC, restore the SAML trust, and re-import App Segments from inventory. After that window, rollback is not in scope.

Feature parity

Where OpenZiti matches ZPA, and where it does not.

CapabilityOpenZitiZscaler Private AccessParity
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 →