> ## Documentation Index
> Fetch the complete documentation index at: https://docs.oasm.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Worker

> Connect and scale the distributed scanning workers that run security scans for your workspace

Workers are the **distributed scanning engine** of OASM. A worker is a small program that connects securely to the platform, authenticates with a workspace API key, and pulls scan jobs as capacity frees up. It executes the configured scanning tools, reports progress and results back to the platform, and lets you scale scanning horizontally by running more instances.

Workers are stateless: they can join or leave the system at any time without affecting the platform, the Console, or other workers. This pull-based model makes the execution layer fault-tolerant — if a worker stops mid-job, the job stays visible in the [Job Registry](/jobs) and can be re-run once the worker layer is healthy again.

## Key concepts

| Concept | Description |
| - | - |
| Worker | A program that connects to the platform, pulls scan jobs, and executes the scanning tools |
| Workspace API key | The credential a worker uses to authenticate — generated in **Settings → API Keys** |
| Concurrency | How many jobs a single worker executes in parallel |
| Scope | Whether the worker serves **this workspace** or **all workspaces** (Global) |

## How a worker connects

The connection is established once at startup and then kept alive for the lifetime of the process:

1. The worker starts and reads its connection settings.
2. It authenticates to the platform with the workspace API key.
3. It registers with the platform and starts pulling scan jobs.
4. It executes each job's steps, reporting progress and results back.
5. The platform's job registry tracks the job through each stage: waiting, running, and then finished successfully, failed, or cancelled.

> [!NOTE]
>
> A worker that cannot connect is almost always a credential problem: an invalid, revoked, or missing workspace API key. Check the worker logs first — they name the failing request and the platform's response.

Workers execute job steps grouped by **category**. Each job belongs to one of the scanning categories, and the worker runs the tools associated with it:

| Category | Work performed |
| - | - |
| Subdomain discovery | Finds the subdomains of your monitored domains |
| HTTP probing | Identifies live web services |
| Port scanning | Scans for open ports |
| Vulnerability scanning | Detects known vulnerabilities |
| Screenshots | Captures screenshots of web services |

## Connector tools on a worker

Not every tool is built into the worker. A [connector](/tools) is an external security tool packaged as a container image. When a job targets a connector, the worker acts as a container supervisor:

1. The platform sends the run to the worker with the connector's container image, its per-run inputs, and the resolved configuration.
2. The worker pulls the image if it is not already cached, then starts the container.
3. The container starts the connector, which dials **back** to the worker over a private endpoint. The connector never listens for inbound connections.
4. The connector registers, runs the scan, and streams findings back to the worker, which persists them through the platform.
5. When the run finishes, the outcome is recorded in the [job registry](/jobs).

| Property | Behavior |
| - | - |
| Outbound only | Connector containers expose no inbound ports — they dial the worker. |
| Warm pool | After a clean run the container is kept alive and reused for the next job of the same image, so image pulls and process start-up are paid once. Idle containers are stopped and removed after a timeout. |
| One execution at a time | A container runs a single job at a time; parallel jobs are served by additional containers. |
| Cancellation | Cancelling a job sends the connector a cancel message; the run is aborted promptly. |
| Resource limits | Each connector declares its CPU, memory, and timeout defaults; the worker enforces them on the container. |
| Isolated credentials | Every execution is authorised with a short-lived, single-use token. |

### Connector runtime requirements

* **A container runtime.** The worker needs access to a Docker daemon to start connector containers. In the production Compose stack the worker runs in `node` mode with the Docker socket mounted — see [Deployment](/deployment).
* **A reachable dial address.** Connector containers must be able to reach the worker at `WORKER_CONNECTOR_ADDR` (`host:port`). If the address is empty and autodetect is not enabled, the worker stops at startup rather than starting containers that could never connect.
* **Optional authentication.** Set `WORKER_CONNECTOR_TOKEN` for a shared-secret handshake, or enable mTLS on the connector endpoint.

> [!CAUTION]
>
> Mounting the Docker socket gives the worker root-equivalent control of its host. Only run connector images you trust, and keep the worker host dedicated to scanning.

## Connect a worker

### Prerequisites

* A running platform that the worker can reach.
* A workspace API key. Generate or copy one from **Settings → API Keys** — see [API keys](/api-keys).

> [!CAUTION]
>
> Always use a real workspace API key. A worker running with a placeholder value cannot connect to your workspace.

### Step-by-step

**1. Generate or obtain a workspace API key**

Open **Settings → API Keys** in the Console. If no key exists yet, click **Rotate** to create one and copy it immediately — the key is shown once and cannot be retrieved later. Treat it like a password.

**2. Configure the connection settings on the worker host**

Set the worker's connection settings — at minimum the workspace API key. The remaining settings have sensible defaults for a standard deployment.

**3. Start the worker**

Run the worker in the way that fits your environment — as a container, a system service, or the local CLI.

**4. Verify the worker appears as connected**

Open **Workers** in the sidebar (under **Management**) and switch to the **Workspace** tab. The worker should appear with a green **connected** status badge. If it does not, follow the troubleshooting steps below.

### Run a worker with Docker Compose

The simplest path is the worker service shipped in the platform's Docker Compose deployment. Configure the workspace API key and the connection settings for the platform, then start the worker service. The shipped worker runs in **node** mode: it mounts the host Docker socket so it can start [connector](/tools) containers, and publishes the connector port so those containers can dial back to it. The stack also mounts a shared tools folder where the built-in scanning tools are installed once and cached, so tool installation does not repeat for every job.

### Run a worker from the Console

Open the **Connect worker** dialog from either the **Workers** page or the sidebar's **Create** menu (**Create → Connect worker**). The Create menu entry is shown only to members with access to the workspace API key, because the command embeds it.

The dialog shows a ready-to-run command, pre-filled with the workspace API key and the host you are browsing from. When more than one environment applies (running from source in DevMode, Linux, or Windows), pick one from the tabs; when only one applies, the tabs are hidden and the command is shown directly.

## Worker scope

Each worker operates under a scope that determines which jobs it may pull:

| Scope | Behavior |
| - | - |
| **This workspace** | The worker only pulls jobs belonging to its associated workspace |
| **Global** | The worker can pull jobs across all workspaces — typically managed by administrators as shared infrastructure |

The Workers page shows workers under **Global** and **Workspace** tabs. A worker bound to a workspace serves that workspace's jobs; a Global worker has access to jobs from any workspace.

## Scaling workers

Workers scale horizontally without shared state — add instances and the platform distributes jobs among whoever is ready.

* **Run more instances.** Launch additional worker instances using the same workspace API key. Each pulls the next available job when it has capacity.
* **Allow more parallel jobs on powerful hosts.** The default concurrency setting bounds how many jobs one worker executes at once. Treat it as a per-host budget: raise it when the host has spare CPU and memory, lower it when jobs share tools or targets and you see timeouts.
* **Prefer more instances over extreme concurrency.** More instances spread load across machines; a very high concurrency value saturates one machine.

> [!NOTE]
>
> Workers that run connector containers each need their own reachable connector endpoint. The production Compose stack publishes a single connector port, so scale by giving each worker a distinct connector address and port rather than running several replicas behind one address.

## Connection settings

Workers authenticate with the workspace API key and read a small set of connection settings that point them at the platform and control how many jobs they run in parallel. The defaults match a standard deployment; change them only when your setup differs.

Workers that run [connector](/tools) containers read a few connector settings on top of these:

| Setting | Purpose |
| - | - |
| Connector dial address (`WORKER_CONNECTOR_ADDR`) | The `host:port` connector containers use to reach this worker. Required when running connectors. |
| Connector port | The port the worker's connector endpoint listens on (default `26276`). |
| Connector token (`WORKER_CONNECTOR_TOKEN`) | Optional shared secret for the connector handshake. |
| Idle timeout | How long an unused pooled container stays alive before it is swept. |

## Troubleshooting

> **Jobs stay stuck in the waiting stage**
>
> A job only leaves the waiting stage when a connected worker picks it up. If jobs accumulate, check that at least one worker shows a connected status on the **Workers** page, then check the worker logs for registration errors. See [Jobs](/jobs) for the full lifecycle.

> **The worker shows no connected status after starting**
>
> Confirm the API key is valid and belongs to the workspace: rotate it in **Settings → API Keys** if in doubt, update the worker's connection settings, and restart the worker. Then check that the worker can reach the platform from its host.

> **The API key was rotated — the worker stopped pulling jobs**
>
> Rotation invalidates the previous key immediately, so the worker's connection is rejected. Update the worker's connection settings with the new key and restart the worker. Rotate keys on a schedule and update every worker (and other API consumers) before the old key is needed again.

> **The worker cannot reach the platform**
>
> Verify network connectivity from the worker host to the platform. In a Docker Compose deployment, the worker must be on the same network as the platform service.

> **Connector jobs fail to start**
>
> Connector runs need a worker that can start containers. Check that the worker has access to a Docker daemon, that its connector dial address is set, and that the connector image can be pulled from its registry. The worker log names the failing step — image pull, container start, or the connector's registration.

> **Connector containers keep running after a job finishes**
>
> This is the warm pool keeping an idle container ready for the next job. Idle containers are stopped and removed after the idle timeout; lower the timeout if you want them cleared sooner.

## Related

> **[API keys](/api-keys)**
>
> Generate and rotate the workspace API key that workers authenticate with

> **[Jobs](/jobs)**
>
> Watch jobs move from waiting to finished in the registry

> **[Tools & Connectors](/tools)**
>
> The built-in tools and connector containers workers execute


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.