Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions src/content/changelog/access/2026-06-05-worker-destinations.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
title: Protect Workers directly with Access applications
description: Access applications now support Workers as destinations. Select a Worker by name instead of managing URL patterns.
date: 2026-06-05
products:
- access
---

Access applications now support [Worker destinations](/cloudflare-one/access-controls/applications/http-apps/worker-destinations/), a new way to protect Cloudflare Workers without managing URL-based routing patterns. Instead of matching hostname patterns and keeping Access applications in sync with Workers routes, you select the Worker directly and Access covers every route automatically.

Four destination types are available:

- **`worker`** — Protects a specific Worker and all of its preview deployments.
- **`preview_worker`** — Protects only the preview deployments for a specific Worker.
- **`all_workers`** — Protects every Worker on the account, including preview deployments.
- **`all_preview_workers`** — Protects all preview deployments across the account.

You can configure Worker destinations in the [Cloudflare dashboard](https://dash.cloudflare.com/) or via the API using the `destinations` array. The API also supports new `worker_id` and `destination_type` query parameters for filtering applications by Worker.

To get started, refer to [Protect a Worker with Access](/cloudflare-one/access-controls/applications/http-apps/worker-destinations/).
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,18 @@ For setup instructions, refer to [Add a self-hosted private application](/cloudf

### Protecting Workers

Self-hosted applications can also protect a Cloudflare Worker directly by name, rather than by hostname or IP. When you select a Worker as the destination, you can cover the Worker together with all of its preview deployments, or cover the preview deployments only.
Self-hosted applications can protect a Cloudflare Worker directly by name, rather than by hostname or IP. You add a Worker destination to your application, and Access checks every request to that Worker against your policies before letting it through. This covers all routes on the Worker automatically, so you do not need to keep Access applications in sync with Workers routes.

This is the safest and most straightforward way to put authentication in front of a Worker. Instead of configuring individual routes on the Worker and managing authentication at the route level, you link the entire Worker (and optionally its preview deployments) to an Access application. Any request to the Worker on any route passes through Access first.
Worker destination configurations range from a single Worker to account-wide:

- **Worker** — Protects a specific Worker and all of its preview deployments.
- **Preview Worker** — Protects only the preview deployments for a single Worker.
- **All Workers** — Protects every Worker on the account, including preview deployments.
- **All Preview Workers** — Protects all preview deployments across the account.

You can combine Worker destinations with public hostname destinations in the same application. For example, you might protect both `app.example.com` and a Worker by name in a single app.

For setup instructions, refer to [Protect a Worker with Access](/cloudflare-one/access-controls/applications/http-apps/worker-destinations/).

### CLI access with cloudflared

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ You can protect the following types of web applications:
- [**Public hostname applications**](/cloudflare-one/access-controls/applications/http-apps/self-hosted-public-app/) are web applications that have public DNS records. Anyone on the Internet can access the application by entering the URL in their browser and authenticating through Cloudflare Access. Securing access to a public website requires a Cloudflare DNS [full setup](/dns/zone-setups/full-setup/) or [partial CNAME setup](/dns/zone-setups/partial-setup/).
- [**Private network applications**](/cloudflare-one/access-controls/applications/non-http/self-hosted-private-app/) do not have public DNS records, meaning they are not reachable from the public Internet. To connect using a private IP or private hostname, the user's traffic must route through Cloudflare Gateway. The preferred method is to install the [Cloudflare One Client](/cloudflare-one/team-and-resources/devices/cloudflare-one-client/) on the user's device. Alternative options include forwarding traffic from a [network location](/cloudflare-wan/), using [PAC files](/cloudflare-one/networks/resolvers-and-proxies/proxy-endpoints/), or [Clientless Web Isolation](/cloudflare-one/remote-browser-isolation/setup/clientless-browser-isolation/).

- [**Worker destinations**](/cloudflare-one/access-controls/applications/http-apps/worker-destinations/) let you protect a Cloudflare Worker by name instead of by hostname. Access covers every route on the Worker automatically, including preview deployments.

- [**Model Context Protocol (MCP) servers**](/cloudflare-one/access-controls/ai-controls/) are web applications that enable generative AI tools to read and write data within your business applications. For example, Salesforce provides an [MCP server](https://github.com/salesforcecli/mcp) for developers to interact with resources in their Salesforce tenant using GitHub Copilot or other AI code editors.

- [**Cloudflare Dashboard SSO**](/fundamentals/manage-members/dashboard-sso/) is a special type of SaaS application that manages SSO settings for the Cloudflare dashboard and has limited permissions for administrator edits.
Original file line number Diff line number Diff line change
@@ -0,0 +1,274 @@
---
pcx_content_type: how-to
products:
- cloudflare-one
title: Protect a Worker with Access
description: Add a Cloudflare Worker as a destination in a self-hosted Access application so that every request to the Worker passes through Access first.
sidebar:
order: 3
label: Worker destinations
---

import { Tabs, TabItem } from "~/components";

Cloudflare Access can protect a Worker directly by name, without requiring you to set up URL-based routing patterns. When you add a Worker as a destination on a self-hosted application, Access checks every incoming request to that Worker against your policies before letting it through. This covers all routes on the Worker automatically.

Worker destinations are different from the hostname-based Access toggle available on the Workers dashboard. The hostname-based toggle protects a specific `workers.dev` or custom domain URL. Worker destinations protect the Worker itself, regardless of what hostnames it is reachable on.

## Use cases

Worker destinations support five configurations:

| Configuration | What it protects | Destination type |
| --- | --- | --- |
| Specific Worker | A Worker and all of its preview deployments | `worker` |
| Specific preview Worker | Only the preview deployments for a single Worker | `preview_worker` |
| All Workers | Every Worker on the account, including preview deployments | `all_workers` |
| All preview Workers | All preview deployments across the account | `all_preview_workers` |

The `worker` and `preview_worker` types require a `worker_id`. The `all_workers` and `all_preview_workers` types do not take a `worker_id` because they apply account-wide.

:::note
The `all_workers` and `all_preview_workers` types are powerful and should be used with caution. Accidentally creating an `all_workers` destination can gate every Worker on the account behind Access, potentially causing downtime for production Workers.
:::

You can combine Worker destinations with public hostname destinations in the same application. For example, a single app might protect both `app.example.com` and a Worker by name.

## Prerequisites

- A deployed [Cloudflare Worker](/workers/get-started/guide/)
- An active [Cloudflare One](/cloudflare-one/) plan

## 1. Create a self-hosted application with a Worker destination

<Tabs>
<TabItem label="Dashboard">

1. In [Zero Trust](https://one.dash.cloudflare.com/), go to **Access** > **Applications**.
2. Select **Add an application**.
3. Select **Self-hosted**.
4. Name your application.
5. In the **Destination** section, select **Worker** as the destination type.
6. Choose the Worker you want to protect from the dropdown.
7. To also protect preview deployments separately, add another destination and select **Preview Worker**.
8. Select **Next** and configure your [Access policies](/cloudflare-one/access-controls/policies/).
9. Select **Add application**.

</TabItem>
<TabItem label="API">

Call the Access applications endpoint with a `destinations` array containing `worker` or `preview_worker` entries. The `worker_id` is the immutable ID of the Worker (called `tag` in the [Workers scripts API](/api/resources/workers/subresources/scripts/methods/list/) or `id` in the [Workers beta API](/api/resources/workers/subresources/beta/subresources/workers/methods/list/)).

**Protect a Worker and its preview deployments:**

```bash
curl "https://api.cloudflare.com/client/v4/accounts/{account_id}/access/apps" \
--header "Authorization: Bearer {api_token}" \
--header "Content-Type: application/json" \
--data '{
"type": "self_hosted",
"name": "My Worker app",
"destinations": [
{
"type": "worker",
"worker_id": "c81a2d22c29840ed9d61681a3270dbff"
}
],
"policies": [
{
"name": "Allow employees",
"decision": "allow",
"include": [
{
"email_domain": {
"domain": "example.com"
}
}
]
}
]
}'
```

**Protect only preview deployments for a specific Worker:**

```bash
curl "https://api.cloudflare.com/client/v4/accounts/{account_id}/access/apps" \
--header "Authorization: Bearer {api_token}" \
--header "Content-Type: application/json" \
--data '{
"type": "self_hosted",
"name": "My Worker previews",
"destinations": [
{
"type": "preview_worker",
"worker_id": "c81a2d22c29840ed9d61681a3270dbff"
}
],
"policies": [
{
"name": "Allow employees",
"decision": "allow",
"include": [
{
"email_domain": {
"domain": "example.com"
}
}
]
}
]
}'
```

**Protect all Workers on the account:**

```bash
curl "https://api.cloudflare.com/client/v4/accounts/{account_id}/access/apps" \
--header "Authorization: Bearer {api_token}" \
--header "Content-Type: application/json" \
--data '{
"type": "self_hosted",
"name": "All Workers",
"destinations": [
{
"type": "all_workers"
}
],
"policies": [
{
"name": "Allow employees",
"decision": "allow",
"include": [
{
"email_domain": {
"domain": "example.com"
}
}
]
}
]
}'
```

**Protect all preview deployments on the account:**

```bash
curl "https://api.cloudflare.com/client/v4/accounts/{account_id}/access/apps" \
--header "Authorization: Bearer {api_token}" \
--header "Content-Type: application/json" \
--data '{
"type": "self_hosted",
"name": "All preview deployments",
"destinations": [
{
"type": "all_preview_workers"
}
],
"policies": [
{
"name": "Allow employees",
"decision": "allow",
"include": [
{
"email_domain": {
"domain": "example.com"
}
}
]
}
]
}'
```

</TabItem>
</Tabs>

## 2. Filter applications by Worker

To find which Access applications protect a specific Worker, you can filter the application list by `worker_id` or `destination_type`.

```bash
curl "https://api.cloudflare.com/client/v4/accounts/{account_id}/access/apps?destination_type=worker&worker_id=c81a2d22c29840ed9d61681a3270dbff" \
--header "Authorization: Bearer {api_token}"
```

You can also use the standard filter format:

```bash
curl "https://api.cloudflare.com/client/v4/accounts/{account_id}/access/apps?filter=destination_type:worker&filter=worker_id:c81a2d22c29840ed9d61681a3270dbff" \
--header "Authorization: Bearer {api_token}"
```

To find applications that protect all Workers or all preview Workers:

```bash
curl "https://api.cloudflare.com/client/v4/accounts/{account_id}/access/apps?destination_type=all_preview_workers" \
--header "Authorization: Bearer {api_token}"
```

The existing `domain` filter also accepts Worker IDs, so `?domain=c81a2d22c29840ed9d61681a3270dbff` will return applications with that Worker as a destination.

## How Worker destinations work

When a request arrives at Cloudflare and Workers routing matches it to a Worker, Access checks whether any application has a destination for that Worker. The matching order is:

1. If a traditional URL-based Access application matches the request hostname, that application takes precedence. This lets you create bypasses for specific URLs when needed (for example, to exempt `/.well-known` paths).
2. If the request is for a preview deployment, Access looks for a `preview_worker` destination matching that specific Worker ID.
3. Access then looks for a `worker` destination matching the Worker ID (which covers both production and preview).
4. For preview deployments, Access checks for an `all_preview_workers` destination.
5. Access checks for an `all_workers` destination.

The first match wins. If none match, the request proceeds without Access.

## Mixing Worker and public destinations

A single application can contain both Worker destinations and public hostname destinations. This is useful when a Worker is reachable both through a custom domain and through `workers.dev`.

```json
{
"type": "self_hosted",
"name": "My app",
"destinations": [
{
"type": "worker",
"worker_id": "c81a2d22c29840ed9d61681a3270dbff"
},
{
"type": "public",
"uri": "app.example.com"
}
]
}
```

## Uniqueness constraints

Worker IDs must be unique within each destination type across the account:

- You cannot have two applications with `type: "worker"` destinations pointing to the same `worker_id`.
- You cannot have two applications with `type: "preview_worker"` destinations pointing to the same `worker_id`.
- You can have both a `worker` and a `preview_worker` destination for the same `worker_id` (on different applications or the same application) if you want different policies for production and preview traffic.
- You can only have one `all_workers` destination per account.
- You can only have one `all_preview_workers` destination per account.

## Limitations

- The Worker must exist when you create the destination. Access resolves the Worker name to an internal ID at creation time.
- Deleting a Worker does not automatically remove Access applications that reference it. You must manually remove the destination or delete the application.
- Worker destinations do not currently appear in App Launcher. If the application has a mix of Worker and public hostname destinations, the App Launcher link uses the public hostname.
- Terraform support for Worker destinations is not yet available.

## Compare with hostname-based Worker protection

The Workers dashboard offers a one-click toggle to protect a Worker's `workers.dev` URL or preview URLs with Access. That approach creates a hostname-based Access application under the hood.

| | Worker destination | Hostname toggle |
| --- | --- | --- |
| **Configured from** | Access dashboard or API | Workers dashboard |
| **What it protects** | The Worker itself, regardless of hostname | A specific `workers.dev` or custom domain URL |
| **Covers new routes automatically** | Yes | Only if the route shares the same hostname |
| **Covers preview deployments** | Configurable per destination type | Separate toggle for preview URLs |
| **Requires DNS on Cloudflare** | No | Yes (for custom domains) |

For most new configurations, Worker destinations are the simpler option because they follow the Worker rather than its hostnames. If your Worker is only reachable on a single hostname and you want quick setup from the Workers dashboard, the hostname toggle works fine.
4 changes: 4 additions & 0 deletions src/content/docs/workers/configuration/previews.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,10 @@ The resulting alias would be associated with this version, and immediately avail

When enabled, all preview URLs are available publicly. You can use [Cloudflare Access](/cloudflare-one/access-controls/policies/) to require visitors to authenticate before accessing preview URLs. You can limit access to yourself, your teammates, your organization, or anyone else you specify in your [access policy](/cloudflare-one/access-controls/policies/).

:::note
You can also protect preview deployments by adding a [Worker destination](/cloudflare-one/access-controls/applications/http-apps/worker-destinations/) in an Access application. Worker destinations protect the Worker by name rather than by URL, and can cover preview deployments across your entire account.
:::

To limit your preview URLs to authorized emails only:

1. In the Cloudflare dashboard, go to the **Workers & Pages** page.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ All Workers are assigned a `workers.dev` route when they are created or renamed

When enabled, your `workers.dev` URL is available publicly. You can use [Cloudflare Access](/cloudflare-one/access-controls/policies/) to require visitors to authenticate before accessing preview URLs. You can limit access to yourself, your teammates, your organization, or anyone else you specify in your [access policy](/cloudflare-one/access-controls/policies/).

:::note
As an alternative, you can protect the Worker itself (rather than a specific URL) by adding a [Worker destination](/cloudflare-one/access-controls/applications/http-apps/worker-destinations/) in an Access application. Worker destinations cover all routes on the Worker automatically, including `workers.dev` and any custom domains.
:::

To limit your `workers.dev` URL to authorized emails only:

1. In the Cloudflare dashboard, go to the **Workers & Pages** page.
Expand Down
Loading