Guides

Private Locations

Deploy Yorker runners on your own infrastructure to monitor internal services, staging environments, and VPNs.

View as Markdown

A private location runs the Yorker check runner on your own infrastructure instead of Yorker's hosted fleet. Use it to monitor internal services, staging environments, or anything behind a VPN -- from inside your own network. The same monitors, alerting, and dashboards work identically, with one exception: scripted browser monitors run on hosted locations only.

Private location runs are billed at 50% of hosted runs because you provide the compute.

Prerequisites

  • A Yorker plan that includes private locations (free tier: 0; paid: up to 2; enterprise: unlimited)
  • Docker installed on the target machine
  • Outbound HTTPS access from the agent machine to yorkermonitoring.com:443 -- no inbound connections are required

Step 1: Create a Location

To create a location via the CLI, provide a unique slug (--name) and a human-readable label (--display-name):

yorker locations create --name hq-data-center --display-name "HQ Data Center"

The CLI also auto-generates a runner key. Use the key and location ID from the output when continuing with Step 3 below.

To create a location via the dashboard: go to Settings > Locations and click Add Location.

Both paths return a location ID in the form loc_.... Save it -- you will need it in the next step.


Step 2: Generate a Runner Key

Runner keys authenticate the agent to the control plane. Each key is shown only once.

To generate a key via the CLI:

yorker locations keys create <location-id>

To generate a key via the dashboard: expand the location row, enter a key name, and click Create Key.

Copy the key immediately -- it cannot be retrieved after the page is closed.


Step 3: Deploy the Agent

The agent is published as a Docker image. Download the Compose file and the environment template into an empty directory on the machine that will run it:

curl -fsSLO https://yorkermonitoring.com/agent/docker-compose.yml
curl -fsSL -o .env https://yorkermonitoring.com/agent/agent.env.example

The template pre-fills RUNNER_MODE, CONTROL_PLANE_URL, and LOCATION_TYPE with their required values. Open .env and fill in the four values specific to your deployment:

RUNNER_API_KEY=rk_...          # The runner key from Step 2
LOCATION_ID=loc_...            # The location ID from Step 1
TEAM_ID=team_...               # Included in the `yorker locations create` CLI output
LOCATION_NAME=HQ Data Center   # Human-readable label for logs and telemetry

The runner key is a credential. Keeping it in .env keeps it out of your shell history and the process list, which a one-line docker run -e RUNNER_API_KEY=... does not. Restrict the file to your own user with chmod 600 .env.

The dashboard and the CLI also print a docker run command when you create a runner key, for trying an agent quickly without Compose. It comes in two steps: the first reads the key into your shell without showing it, and the second starts the agent, so the key is not written into the command. The image in that command is the current release, named by version and by digest (yorker-agent:1.0.2@sha256:...) instead of latest, so Docker only runs the exact image that was released.

Then start the agent:

docker compose up -d

Choosing an image

Two images are published, for linux/amd64 and linux/arm64:

ImageRunsSize
ghcr.io/reverse-sweep-ltd/yorker-agentHTTP, MCP, and browser monitors (includes Playwright + Chromium)~550 MB download, ~2 GB on disk
ghcr.io/reverse-sweep-ltd/yorker-agent-lightHTTP and MCP monitors only~130 MB download, ~570 MB on disk

Both images run as an unprivileged user, and the Compose file drops all Linux capabilities and sets no-new-privileges. The agent needs no inbound ports, no volumes, and no elevated permissions.

The Compose file runs yorker-agent by default. To run the lighter image, add this line to .env and run docker compose up -d again:

YORKER_AGENT_IMAGE=yorker-agent-light

Screenshots

Browser monitors on a private location capture the same screenshots as hosted ones. The agent sends each screenshot to Yorker over the outbound HTTPS connection it already uses for results, and they appear in the monitor's filmstrip. There is nothing to configure, and no extra host to allow through a firewall. Each screenshot can be up to 4 MB, and a location can send up to 12,000 an hour, which is far more than its monitors produce in normal use.

This needs agent 1.0.2 or later. An older agent runs browser monitors but its screenshots never reach Yorker; update it.

Screenshots are images of the pages the agent loads, so with the default setup those images leave your network and are stored by Yorker, with the same retention as hosted screenshots. If they must stay in storage you control, give the agent an S3-compatible bucket in .env:

ARTIFACT_S3_ENDPOINT=https://s3.eu-west-2.amazonaws.com
ARTIFACT_S3_BUCKET=synthetics-artifacts
ARTIFACT_S3_ACCESS_KEY_ID=...
ARTIFACT_S3_SECRET_ACCESS_KEY=...
ARTIFACT_S3_REGION=eu-west-2            # "auto" for Cloudflare R2 and MinIO
ARTIFACT_PUBLIC_URL=                    # optional: base URL put in front of each object key in telemetry

The agent then uploads screenshots to that bucket instead of sending them to Yorker. Yorker cannot read your bucket, so the filmstrip in the dashboard stays empty for that location. The screenshot links are included in the OTLP telemetry the agent emits, so you can open them from your own backend.

Direct OTLP export

The agent can export metrics, traces, and logs straight to your own OTel-compatible backend, entirely from inside your network (this connection never transits Yorker). Set these in .env:

OTLP_ENDPOINT=https://api.honeycomb.io
OTLP_API_KEY=                              # sent verbatim as "Authorization" (leave unset if not needed)
OTEL_EXPORTER_OTLP_HEADERS=x-honeycomb-team=your-team-key,x-honeycomb-dataset=yorker

OTEL_EXPORTER_OTLP_HEADERS follows the standard OTel env var format: comma-separated key=value pairs, values URL-encoded. Use it for backends that need a header other than Authorization (Honeycomb, Datadog's dd-api-key, New Relic's api-key, SigNoz Cloud's signoz-ingestion-key) or more than one header. If a header name here collides with OTLP_API_KEY's Authorization, the entry in OTEL_EXPORTER_OTLP_HEADERS wins.


Step 4: Verify Health

After the agent starts, it begins polling the control plane. To verify it is connected:

  • Dashboard: the location's status badge turns green (Active) in Settings > Locations.
  • CLI: run yorker locations list and check the status column.

Health states are derived from the time since the last successful poll:

StatusMeaning
ActiveLast poll within the past 5 minutes
DegradedLast poll 5--10 minutes ago
OfflineLast poll more than 10 minutes ago, or never connected

If the agent does not appear Active within a few minutes, see Troubleshooting below.


Step 5: Assign the Location to a Monitor

Monitors only execute in the locations they are assigned to. A monitor can be assigned to any mix of hosted and private locations.

To assign via the dashboard: edit a monitor and open the location picker. Your private location appears under the Private group with its current health badge.

To assign via yorker.config.yaml, add the location ID to the monitor's locations array:

monitors:
  - name: Internal API
    type: http
    url: https://api.internal.example.com/health
    locations:
      - loc_us_east          # hosted location
      - loc_abcdef123456     # your private location

Deploy the config to apply:

yorker deploy

Updating the Agent

Hosted locations pick up runner changes automatically. A private agent runs on your infrastructure, so it stays on the image it was started with until you update it. An agent that falls behind keeps running the monitors it understands, but it cannot run monitor types or settings that were added after its release.

To move to the newest release:

docker compose pull
docker compose up -d

The agent restarts in a few seconds and resumes polling. Monitors assigned to hosted locations are unaffected while it restarts.

If you started the agent with the docker run command from the dashboard or the CLI instead of Compose, that command names a specific release, so running it again starts the same version. To upgrade:

  1. Create a new runner key for the location, in the dashboard or with yorker locations keys create <location-id>. It comes with the start command for the current release.

  2. Remove the old container:

    docker rm -f yorker-agent-loc_abcdef123456   # your location ID
  3. Run the two commands shown with the new key.

  4. Revoke the old key.

If you pinned a release with YORKER_AGENT_VERSION, change the pin first; docker compose pull on its own fetches the pinned version again.

Choosing how updates arrive

By default the Compose file tracks the latest tag, so every docker compose pull fetches the newest release. Two common setups:

  • Follow releases automatically. Keep latest and run the two commands above on a schedule, for example a weekly cron job.

  • Control each upgrade. Pin a release in .env and change the line when you are ready to upgrade:

    YORKER_AGENT_VERSION=1.0.1

Released version tags are never overwritten, so a pinned agent runs the same image until you change the pin.

Checking what is running

The agent reports its version to Yorker each time it polls. Settings > Locations and yorker locations list show it in the Agent column, flagged Update available when a newer release exists. An agent started from a build that predates published releases shows Unknown version; update it the same way.

The agent also serves its version, build, and what it can run on the health port:

docker compose exec yorker-agent curl -s http://localhost:8080/version

Monitors an agent cannot run

Some monitors cannot run on a given agent. When one is assigned to a private location, the location is flagged in Settings > Locations (expand the row for the list) and in yorker locations list, with the reason:

MonitorRuns on
HTTP, MCPyorker-agent and yorker-agent-light
Browser (URL mode)yorker-agent only
Browser (scripted)Hosted locations only

A monitor that cannot run on a private location still runs on its other locations.


Network Requirements

The agent only needs outbound connectivity -- no inbound connections are required and no firewall rules need to be opened toward Yorker.

RequirementDetail
Outbound HTTPSyorkermonitoring.com:443 -- for polling checks and submitting results and screenshots
Outbound HTTPS (install and update only)ghcr.io:443 and pkg-containers.githubusercontent.com:443 -- for pulling the agent image
Internal network accessThe agent must be able to reach the services it monitors (e.g., internal hostnames, VPN resources)

There is no VPN tunnel from the agent to Yorker's infrastructure. All communication is initiated by the agent over standard HTTPS.


Troubleshooting

SymptomLikely causeFix
Location stays OfflineWrong runner key or location IDVerify RUNNER_API_KEY and LOCATION_ID in .env match what was generated in Steps 1 and 2
Location stays OfflineFirewall blocking outbound HTTPSAllow outbound connections from the agent machine to yorkermonitoring.com:443
Location is Active but no checks runWrong TEAM_IDThe runner polls with team scoping -- verify TEAM_ID matches your team in Settings
Checks not executingAgent is connected but no checks assignedAssign the private location to at least one monitor (Step 5)
docker compose pull failsRegistry blocked by an egress firewallAllow outbound HTTPS to ghcr.io and pkg-containers.githubusercontent.com
Browser checks failUsing the light imageRemove YORKER_AGENT_IMAGE=yorker-agent-light from .env to run yorker-agent, which includes Playwright and Chromium
Browser monitors run but show no screenshotsAgent is older than 1.0.2Update the agent
Browser monitors run but show no screenshotsARTIFACT_S3_* is set, so screenshots go to your own bucketExpected. Remove the ARTIFACT_S3_* lines from .env to have them sent to Yorker and shown in the filmstrip; see Screenshots
A new monitor type or setting does not workAgent is older than the featureUpdate the agent