A private location is a collection of synthetics job managers (SJMs) — containers you run in your own environment. Because SJM only makes outbound calls to New Relic's collector (the "Horde" endpoint), you can monitor internal, firewalled, or otherwise private targets without opening any inbound access to your network. Test scripts, secrets, and traffic stay inside your infrastructure. This contrasts with New Relic's managed public locations, which run from New Relic-operated infrastructure around the world.
The following table summarizes what private locations support. Each capability is detailed in the sections below.
Run monitors inside your own infrastructure, behind the firewall
Custom CA certificates
Trust internal or private-PKI HTTPS endpoints
mTLS client certificates
Present client certs to internal mTLS endpoints (cert-map.json)
Non-root execution
Run the SJM as a non-root user in hardened containers
Verified script execution (VSE)
Passphrase-gate who can run scripts on your location
Secure credentials
Store secrets in an encrypted vault, redacted from results and logs
FedRAMP Moderate
Use synthetic monitoring in FedRAMP-authorized accounts
Dual stack (IPv4 + IPv6)
Monitor both IPv4 and IPv6 endpoints
Outbound proxy
Reach New Relic through an HTTP/HTTPS proxy
Custom Node modules
Use your own npm packages in scripts
User-defined variables
Inject non-secret configuration into scripts
Horizontal and vertical scaling
Add SJMs (same key) or add CPU/RAM for throughput
Automation and infrastructure as code
Manage locations with NerdGraph and Terraform
Shared locations
Share one location across all accounts in an organization
Health and observability
Track status events with a prebuilt job manager dashboard
Custom hostnames (RUNTIME_EXTRA_HOSTS)
Map internal hostnames to IPs for runtime DNS resolution
Foundation: Deploy monitoring in your own infrastructure
Problem it solves: Your internal applications sit behind a firewall where New Relic's public locations can't reach them, and opening inbound access to satisfy a monitoring tool isn't acceptable. Private locations monitor those systems from inside your own network, outbound-only.
Private locations run entirely on infrastructure you control:
A private location can hold any number of SJMs. You assign monitors to the location in the UI, and the SJM pulls jobs and reports results back to New Relic.
The SJM runs on Docker, Podman, Kubernetes, and OpenShift from a single image (newrelic/synthetics-job-manager).
Per-check sandboxing: For each scripted or browser check, the SJM spins up a fresh runtime container or pod, then tears it down, isolating runs from one another.
synthetics-node-browser-runtime — simple and scripted browser monitors (Chrome)
Outbound only: The SJM must reach the Horde endpoint (US https://synthetics-horde.nr-data.net/, EU https://synthetics-horde.eu01.nr-data.net/, JP https://synthetics-horde.jp.nr-data.net/). Test connectivity with:
bash
$
curl-X GET https://synthetics-horde.nr-data.net/synthetics/api/v1/ping
You control the runtime version. On private locations, the runtime version is determined entirely by the runtime images your SJM deploys — set them with DESIRED_RUNTIMES (Docker and Podman) or synthetics.desiredRuntimes (Kubernetes). Use the latest tag to run the current supported runtime images from Docker Hub — that's the recommended setup for private locations. If you need to validate an upgrade before adopting it, you can pin a specific published image tag instead. Either way, the images are pulled when the SJM starts, so restart or redeploy it to apply a change.
The Browser and Runtime version dropdowns in General settings have no effect on private locations, and runtimeTypeVersion in SyntheticCheck isn't a reliable way to identify a private job's runtime — query nr.runtimeVersion instead. The current runtimes are Node.js 22 with Chrome 147 or higher. The older Node.js 16 and Chrome 134 runtimes have reached end of life. See the runtime transition guide for details.
Security and hardening
Custom CA certificates
Problem it solves: Monitors can't verify internal HTTPS endpoints signed by your own certificate authority, so business-critical internal apps either go unmonitored or force you to maintain custom runtime images. Mounting your CA certificates makes those endpoints monitorable with TLS validation intact.
The SJM auto-detects mounted certificates and propagates them (read-only) to every runtime it spawns, so you don't need a custom runtime image.
Format: PEM, with a .pem extension, readable by UID 2000. The SJM loads only certificates with the CA:TRUE basic constraint and ignores leaf certificates.
Docker: Mount to /var/lib/newrelic/synthetics/certs read-only.
Kubernetes: Create a Secret and reference it with global.customCertificates.volume.secret.secretName.
Problem it solves: Services that require the caller to present a client certificate reject your monitors outright, which typically pushes you into building and maintaining a proxy per service just to get coverage. Hostname-mapped client certificates remove that workaround entirely.
Monitors present the correct certificate per hostname automatically, with no script changes.
Provide a cert-map.json mapping hostnames to PEM cert/key files (matching priority: exact → wildcard *.domain.com → default → no certificate).
Docker: Mount your client-cert directory to /var/lib/newrelic/synthetics/client-cert read-only.
Kubernetes: Create a Secret (the Kubernetes resource type) containing cert-map.json and the cert/key files, then reference it with global.clientCertificates.volume.secret.secretName.
Because mTLS is mutual, the monitor must also trust the server. If the endpoint's certificate is issued by a private CA, mount that CA as a custom CA certificate (Docker: /var/lib/newrelic/synthetics/certs, Kubernetes: global.customCertificates.volume.secret.secretName).
If the mTLS hostnames aren't resolvable via DNS inside the runtime, map them with custom hostnames.
Certificate support limitations
Custom CA and mTLS certificates apply to scripted API and scripted browser monitors only (ping monitors are unaffected). Certificates load at container startup, so restart the job manager (or the runtime pods on Kubernetes) after adding, removing, or rotating them. For mTLS, each client certificate needs a unique Subject CN — Chrome uses it to auto-select the correct certificate per hostname.
Problem it solves: Container security standards in many organizations prohibit running workloads as root, which would otherwise block you from deploying the job manager at all. Non-root execution lets monitoring pass your platform security review.
The SJM runs as root by default (safe because execution is sandboxed), but it also supports running as a non-root user.
Docker: The user must be in the docker group (or use the Docker TCP socket via DOCKER_HOST) and have read/write access to mounted volumes, then run with -u UID:GID.
Runtime containers always run as UID 2000.
Kubernetes exposes a podSecurityContext Helm value for runAsUser, runAsNonRoot, and fsGroup. Podman supports a fully rootless model.
Problem it solves: Scripted monitors are arbitrary code, so anyone with account access can run their scripts on your infrastructure inside your network. A passphrase you alone hold ensures only trusted scripts execute on your job manager.
You must set a passphrase before anyone can assign scripts to your location or add SJMs to it. Note that VSE applies only to scripted monitors. Non-scripted monitors (like simple ping) are exempt from entering the passphrase.
Set the passphrase with VSE_PASSPHRASE (Docker/Podman) or synthetics.vsePassphrase / synthetics.vsePassphraseSecretName (Kubernetes), then enable VSE in the location's Edit menu and enter the passphrase for each monitor.
Caution
New Relic never stores the VSE passphrase, and no one — including New Relic Support — can recover it. If it's lost, you must reset it on the SJM and reauthenticate every monitor assigned to the location.
Problem it solves: A private location created in one account isn't usable by other accounts by default, so each account has its dedicated job managers for the same network — duplicating infrastructure, cost, and maintenance. Sharing lets one location serve many accounts.
Sharing is controlled per location, so you decide which accounts can send jobs to your infrastructure.
Setting shared to true makes the location usable by all accounts in your organization.
A location created on a parent account is usable by its child accounts. A location created on a child account stays private to that account.
You can't unshare a location while monitors in other accounts still use it — migrate those monitors first.
Problem it solves: Testing authenticated journeys requires real credentials, but putting them in scripts exposes them to anyone who can read the script or the check results. An encrypted vault keeps secrets usable but unreadable, and rotating one value updates every monitor at once.
Reference stored secrets in your scripts with $secure.MY_KEY.
Uses AES-GCM 256-bit encryption at rest, with AWS Key Management Service (KMS) managing the keys. You can never read values back — you can only reference them.
New Relic scrubs the values from all results and alerts — including percent-encoded forms — replacing them with _SECURECREDENTIAL_.
Available for scripted browser, API, and step monitors. Limit of 1,000 credentials per account. Admins control create, view, delete, and use permissions.
Important
If a monitor running in a private location is compromised, rotate its secure credentials and rotate the private location key.
Problem it solves: Public-sector and regulated workloads can only run on services that meet FedRAMP requirements, which otherwise rules a monitoring tool out before evaluation begins.
Here's how synthetic monitoring fits the FedRAMP program:
New Relic is FedRAMP Authorized (Moderate), and synthetic monitoring is in scope — it isn't on the list of services not in scope.
There's no separate gov- synthetics Horde endpoint. Per New Relic's endpoint rule, a service whose endpoint isn't separately listed and isn't out of scope meets FedRAMP requirements on its standard endpoint. Private-location SJMs in FedRAMP accounts use the standard Horde endpoint.
Customer obligations include a New Relic-approved account, Enterprise edition with Data Plus (or an approved alternative), agents and services configured to FedRAMP-designated endpoints, and use of FedRAMP-authorized features only. FedRAMP is inherited by child accounts.
Problem it solves: As networks adopt IPv6, monitors that can only reach IPv4 leave the IPv6 path unverified — a gap where users hit failures you never see. Dual stack validates both address families from one location.
There's no in-product toggle — SJM inherits dual-stack capability from the host or cluster network, gated on minimum image versions:
Job manager 519 or later, ping runtime 1.65.0 or later, and current Node API and browser runtime images — use the latest tag.
Docker: The host and Docker daemon must have IPv6 enabled.
Kubernetes: The cluster must be v1.20+ with dual stack enabled.
Problem it solves: Locked-down networks don't permit direct egress, so the job manager can't reach New Relic and the whole private location goes offline. Proxy support keeps it reporting without changing your egress policy.
Set these variables on the job manager:
Docker/Podman:HORDE_API_PROXY_HOST, HORDE_API_PROXY_PORT, HORDE_API_PROXY_USERNAME, HORDE_API_PROXY_PW, and HORDE_API_PROXY_ACCEPT_SELF_SIGNED_CERT.
Kubernetes:synthetics.apiProxyHost, synthetics.apiProxyPort, synthetics.hordeApiProxyUsername, synthetics.hordeApiProxyPw, and synthetics.hordeApiProxySelfSignedCert.
Tip
These variables govern SJM-to-New-Relic traffic. There's no documented general-purpose proxy variable for arbitrary monitor-target traffic.
Problem it solves: Monitors can't reach an internal service whose hostname resolves only inside your network — or resolves to the wrong address inside the runtime container — so the check fails on DNS instead of on the thing you meant to test.
On Docker deployments, set RUNTIME_EXTRA_HOSTS on the job manager and it passes the mappings into every runtime container it spawns, so your scripts can use the same hostnames your applications use.
Format: Comma-separated hostname:ip pairs, for example api.internal.example.com:10.0.0.1,svc.internal:10.0.0.2.
Useful whenever an internal name isn't resolvable from the runtime — including mTLS targets referenced in cert-map.json.
Problem it solves: Prevents unmonitored gaps and extra tool sprawl by allowing you to import third-party packages for protocols, cloud SDKs, or data formats missing from the default runtime.
Bundle your own npm packages (hosted or local) for use with require() in scripted API and browser monitors.
Provide a directory with a root package.json, and SJM runs npm install on startup.
Mount to /var/lib/newrelic/synthetics/modules (Docker/Podman, read/write). On Kubernetes, use a PersistentVolume (ReadWriteMany if shared across pods) via global.customNodeModules.customNodeModulesPath.
Problem it solves: Hardcoding environment-specific values into scripts means maintaining a near-duplicate script per environment and editing each one whenever something changes. Injecting configuration lets one script run everywhere.
Access injected values in your scripts with $env.USER_DEFINED_VARIABLES.MY_VARIABLE. Set USER_DEFINED_VARIABLES (a JSON string) or mount a user_defined_variables.json file.
Caution
User-defined variables are not sanitized from logs. Use secure credentials for anything sensitive.
Problem it solves: A single job manager has a fixed throughput ceiling, so as your monitor count grows the queue backs up and checks run late or not at all — silently reducing coverage. Scaling out adds capacity and failover.
Private locations scale to match your monitoring load:
Job types: Heavyweight jobs (simple and scripted browser, scripted API) use roughly one CPU core per concurrent job. Lightweight jobs (ping) run on a worker-thread pool rather than a full core each.
Throughput per SJM: By design, there's a limit of 15 heavyweight jobs per minute and 75 ping checks per minute. For more details on the factors that affect performance, see heavyweight jobs, ping jobs
Scale out (horizontal): Deploy more SJMs with the same private location key. Jobs load-balance across them, throughput is additive, and you gain failover.
Scale up (vertical): Add CPU and memory to the host, or size each runtime independently in the Helm chart (parallelism/completions for API and browser runtimes, replicaCount for ping).
Health and observability: Each SJM shows a status indicator. The NRQL events SyntheticsPrivateLocationStatus and SyntheticsPrivateMinion expose queue and resource metrics, and New Relic provides a prebuilt "Synthetics job manager" dashboard.
Queue management: Clear a backed-up queue in the UI, or purge it with the NerdGraph mutation syntheticsPurgePrivateLocationQueue.
Key rotation: Keys can't be rotated in place. Create a new location, migrate monitors to it, redeploy your SJMs with the new key, then delete the old location. Rotate any secure credentials the monitors used.
Problem it solves: Creating and configuring locations by hand doesn't scale across teams and environments, and hand-built setups drift apart over time. Managing them as code makes monitoring reproducible and reviewable.
You can create and manage private locations programmatically:
NerdGraph API:syntheticsCreatePrivateLocation, syntheticsUpdatePrivateLocation, syntheticsPurgePrivateLocationQueue, and syntheticsDeletePrivateLocation, plus the secure-credential mutations. Creating a location returns a guid.
Terraform: The newrelic_synthetics_private_location resource (required name and description; optional shared and verified_script_execution). It exports the key you feed to your SJMs, so you can provision the location and wire up the runtime in one pipeline.