Skip to main content

Deploy Nexus PDP

Run Permit Nexus PDP (permitio/pdp-v3), a self-hosted policy decision point (PDP), with Docker or on Kubernetes, and verify that it answers permission checks. This page lists the storage, memory, port, probe, and shutdown requirements, gives a runnable command and a pod spec, and covers the Nexus PDP logs and security properties an operator needs. For what Nexus PDP is, see Permit Nexus PDP.

Prerequisites

  • Nexus PDP enabled for your Permit account. Nexus PDP is in early access as of September 2026; to request access, book a call with Permit.
  • The API key of the Permit environment the Nexus PDP serves. See Get your API key.
  • A container platform that provides persistent volumes, such as Kubernetes.

Deployment requirements

Nexus PDP has operational requirements that the container PDP (the Edge PDP image permitio/pdp-v2) does not have. Meet each requirement before you send traffic to a Nexus PDP.

RequirementSettingWhat happens if you skip it
Imagepermitio/pdp-v3, pinned to a specific tagAn unpinned image can pull a release with renamed configuration variables. See Nexus PDP configuration reference.
One container per environmentSet PDP_API_KEY to the API key of one Permit environmentNexus PDP has no multi-environment mode. The API key binds the container to exactly one environment.
Persistent storageMount a persistent volume at /var/lib/edge-pdp, which holds the embedded database and the event store at default pathsOn ephemeral storage, every restart runs a full cold start with a snapshot transfer of your whole data set.
Memory4 GiB to startAt default storage-engine settings, a container with a few hundred MiB is killed for running out of memory (OOM) at startup. See Nexus PDP resource footprint.
Volume permissionsThe volume is writable by user ID and group ID 10001Nexus PDP runs as the non-root user 10001 and cannot write its database or event store.
Exposed ports7000 (authorization API) and 7001 (health) onlyOther ports bind to loopback inside the container and are not reachable from outside.
Termination grace periodterminationGracePeriodSeconds: 40 or higher40 seconds is the sum of the default shutdown budgets EDGE_DRAIN_TIMEOUT_SECS (10) and EDGE_CHILD_TERMINATION_TIMEOUT_SECS (30). With a shorter grace period, Kubernetes kills the NATS leaf node before its on-disk event store finishes flushing.
Liveness probeGET /health on port 7001A liveness probe on port 7000 fails during the cold start and restarts the container. See Health and readiness.
Readiness probeGET /health/ready on port 7001Traffic reaches a Nexus PDP that cannot answer yet.
Startup probeEnough time for a cold start of your data setA cold start takes longer as your data grows. A short startup probe restarts a first boot that is still loading data.

Run Nexus PDP with Docker

Replace <tag> with a specific permitio/pdp-v3 release tag, and set PERMIT_API_KEY in your shell to the API key of the environment this container serves. The command maps the authorization API to host port 7766, keeps the health port on 7001, and stores the embedded database in the named volume nexus-data:

docker run -d --name nexus-pdp \
-p 7766:7000 -p 7001:7001 \
-e PDP_API_KEY="$PERMIT_API_KEY" \
-v nexus-data:/var/lib/edge-pdp \
--memory 4g \
permitio/pdp-v3:<tag>

Kubernetes pod settings for Nexus PDP

This pod-spec excerpt sets the ports, probes, memory request, volume, and shutdown budget from the requirements table. fsGroup: 10001 makes the mounted volume writable by the non-root user that Nexus PDP runs as. Create the permit-env-api-key secret with the environment API key, size the nexus-pdp-data claim for your data set, and add a startup probe with enough time for a cold start:

terminationGracePeriodSeconds: 40
securityContext:
fsGroup: 10001
containers:
- name: nexus-pdp
image: permitio/pdp-v3:<tag>
ports:
- containerPort: 7000 # authorization API
- containerPort: 7001 # health
resources:
requests:
memory: 4Gi
env:
- name: PDP_API_KEY
valueFrom:
secretKeyRef:
name: permit-env-api-key
key: PDP_API_KEY
livenessProbe:
httpGet: { path: /health, port: 7001 }
readinessProbe:
httpGet: { path: /health/ready, port: 7001 }
volumeMounts:
- name: nexus-data
mountPath: /var/lib/edge-pdp
volumes:
- name: nexus-data
persistentVolumeClaim:
claimName: nexus-pdp-data
Run Nexus PDP locally on macOS

The macOS AirPlay Receiver uses port 7000. Map the Nexus PDP authorization API to another host port, for example -p 7766:7000, and set your SDK's PDP URL to http://localhost:7766.

Verify a Nexus PDP deployment

  1. Send GET /health/ready to the health port, 7001: curl -i http://localhost:7001/health/ready. Nexus PDP returns HTTP 200 when every component that gates readiness is up, and HTTP 503 while any of them is still starting. A cold start can take minutes on a large data set, so retry until the response is 200.
  2. Point an SDK at the authorization port and run a permission check. With the port mapping in Run Nexus PDP with Docker, the PDP URL is http://localhost:7766. See Check permissions. A decision that matches your policy confirms that Nexus PDP has your policy and data.

Health and readiness

Nexus PDP serves health endpoints on the management port, 7001. Point every probe at port 7001.

EndpointAuthenticationBehavior
GET /healthNoneAlways returns 200 and the status of each component. Answers during startup, including a cold start.
GET /health/readyNoneReturns 200 only when every component that gates readiness is up, and 503 otherwise.
GET /health/detailBearer token equal to PDP_API_KEYReturns full diagnostic detail for each component.

Nine components gate readiness: the control-plane link (nats_leaf), the four sync planes (wal_mirror, kv_source, policy_files_source, policy_data_source), the embedded database (embedded_db), Open Policy Agent (OPA) (opa), and both loopback servers (query_loopback, bundle_server).

Probe port 7001, not port 7000

The Nexus PDP authorization port, 7000, also answers GET /health and GET /healthy. Nexus PDP keeps /healthy so tooling written for the container PDP works. Don't point probes at port 7000:

  • Port 7000 has no /health/ready endpoint. A readiness probe on :7000/health/ready gets 404, and the pod never becomes ready.
  • Port 7000 opens only after Nexus PDP is ready. A liveness probe on port 7000 fails during the whole cold start, and Kubernetes restarts the container before it finishes starting.

Port 7001 answers from the moment the Nexus PDP process starts.

Diagnose a stale or lagging Nexus PDP

Call GET /health/detail on port 7001 with the header Authorization: Bearer <PDP_API_KEY>. The response reports:

  • restart counts and exit codes for the OPA and NATS leaf node child processes,
  • the Nexus PDP's position in the change stream compared with the oldest change the control plane still holds,
  • whether the Nexus PDP is serving stale data, and for how long,
  • whether decision-log shipping is configured and working.
Staleness and decision-log failures do not gate Nexus PDP readiness

A Nexus PDP that serves stale data, or that cannot ship decision logs, stays ready and keeps answering authorization queries.

Logs

Nexus PDP writes structured logs to stdout at the info level by default. Set RUST_LOG to change the level: info,edge_pdp=debug adds debug logs from Nexus PDP itself. Nexus PDP captures the output of OPA and the NATS leaf node and writes it to the same log stream, labeled with the source process and log level, so the container logs contain all output.

Raising the log level of the OPA or NATS child processes writes authorization data into the container logs. For the variables that control those levels and what each level exposes, see Nexus PDP child process logging.

Decision logs

The OPA process in Nexus PDP sends decision logs to Permit in batches over HTTPS, with a bounded in-memory buffer. Nexus PDP ships decision logs only when both conditions are true:

  • Decision logging is enabled for the environment in Permit.
  • EDGE_DECISION_LOG_OPT_OUT is not set to true on the container.

EDGE_DECISION_LOG_OPT_OUT can only turn decision logging off. It cannot turn logging on for an environment where Permit has it off.

Security properties to plan your deployment around

Four properties of the container decide how you place, scope, and isolate a Nexus PDP.

PropertyWhat it means for your deployment
Request authenticationEvery caller needs the container's own PDP_API_KEY. Treat the key as a shared secret between the container and the services that query it.
One environment per containerRun one container per Permit environment, and route each service to the container for its environment.
Child process isolationVariables you set on the container do not all reach OPA and the NATS leaf node. Set Nexus PDP variables, not OPA or NATS variables.
Blast radiusA compromised container exposes one environment. Apply the network policy and secret scope of that environment to it.

Request authentication uses the container's own API key

Nexus PDP compares the bearer token on each authorization request, in constant time, with the container's PDP_API_KEY. The Nexus PDP binary does not include a Permit API client, so Nexus PDP never contacts the Permit API to authenticate or authorize a request.

One Nexus PDP container serves one environment

Nexus PDP fixes its environment at startup from PDP_API_KEY. A valid API key for a different environment does not authenticate against the container, and a caller cannot direct a request at data outside the container's environment.

Child processes start with a cleared environment

Nexus PDP starts OPA and the NATS leaf node with an empty environment, except for PATH, and then adds only the variables each child process needs. OPA receives PDP_API_KEY to authenticate to the query loopback server. The NATS leaf node does not receive PDP_API_KEY.

Nexus PDP writes credential files with 0600 permissions, creates them without following symbolic links, and references them by path in generated configuration files.

A compromised Nexus PDP exposes one environment

A Nexus PDP container holds the data and credentials of its own environment only. An attacker who controls one Nexus PDP container gets that environment's authorization data, not data from other environments.