# cf-workers-proxy: a Cloudflare Workers script that forwards one host to a hidden domain

> jonssonyan/cf-workers-proxy is a single Worker script that reverse proxies a hostname you choose, with regex based filtering on path, user agent, IP and region. It is deliberately a personal use tool rather than a general purpose CDN in front of a site.

**jonssonyan/cf-workers-proxy** — Cloudflare Workers HTTP 反向代理

- Repository: https://github.com/jonssonyan/cf-workers-proxy
- Website: https://t.me/jonssonyan_channel
- Stars: 961 · Forks: 714
- Language: JavaScript
- License: GPL-3.0
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/jonssonyan-cf-workers-proxy

## One hostname, one Worker, no configuration file

cf-workers-proxy is a reverse proxy that runs on Cloudflare Workers and forwards traffic to a hostname you select. The whole configuration is a set of environment variables attached to the Worker, and the target is declared with PROXY_HOSTNAME. The README states that in theory any blocked domain can be proxied this way, and that you then reach it through the custom domain attached to your Worker.

That framing matters more than it first appears. This is not a general purpose reverse proxy that sits in front of an application you run. There is no origin server to configure, no routing table, no TLS termination story for your own backend. You pick one upstream host, the script fetches from it, and the Worker answers under its own hostname.

The consequence is a small, readable artefact. The repository root holds `_worker.js`, a `docker.js` variant, a package.json, a yarn.lock, the two language READMEs and a GPL-3.0 LICENSE. The Worker file is copied into the Cloudflare dashboard, so there is no build step, no bundler configuration and no runtime dependency to install. The package.json exists for tooling rather than for the proxy itself: its only script is a Prettier pass over the source tree, Prettier is the single dev dependency, and the file declares that Node 18.12.0 or newer is required.

## The environment variables decide what gets proxied

The filter surface is the interesting part of the design, because each variable is a regular expression evaluated against one dimension of the request. PROXY_HOSTNAME is the only mandatory value and it holds the upstream hostname. PROXY_PROTOCOL has a default of https and carries the upstream scheme, so a plain hostname and an explicit URL are handled by two separate variables.

PATHNAME_REGEX restricts which request paths are proxied, with the example value `^/jonssonyan/`. UA_WHITELIST_REGEX and UA_BLACKLIST_REGEX both take a User-Agent pattern, and IP_WHITELIST_REGEX and IP_BLACKLIST_REGEX do the same for the client address. REGION_WHITELIST_REGEX and REGION_BLACKLIST_REGEX repeat the pattern for the visitor's region, with the example value `(JP)`. REGION_WHITELIST_REGEX is the only variable whose filter depends on something the Worker infers rather than something the client sends, which is worth remembering when you debug why a request was not proxied.

The last three variables handle behaviour rather than access. URL302 sets a redirect target, KEEP_PATH decides whether the original path is preserved when that redirect fires, and its default is false. DEBUG toggles debug output, also defaulting to false. Nothing in the README describes what DEBUG prints, so if you need that output you will be reading the Worker source to learn it.

## Two ways to deploy, and two files to choose from

The README offers a Workers route and a Pages route. On the Workers route you copy `_worker.js` and save and deploy it in the Cloudflare dashboard. On the Pages route you fork the repository on GitHub and connect that fork to Cloudflare for a one click deployment.

The file choice is not arbitrary. The README states that in most cases `_worker.js` is enough, but some proxy addresses need special handling and require the designated file instead. The table that maps names to files lists a general entry pointing at `_worker.js` and a Docker entry pointing at `docker.js`. In practice this means the Docker registry use case has its own script, and that the general script may not behave correctly for every upstream.

Two operational details follow from the deployment model. The first is that your custom domain is the public face of the proxy, so the Worker hostname is what clients see and what upstream servers will attribute the traffic to. The second is that because the configuration lives in environment variables, changing a filter does not require a redeploy of the script itself, but a new variable does require the Worker settings to be edited in the Cloudflare dashboard.

## Pointing Docker at a mirror hosted on your Worker

The README documents a specific accelerator workflow, which is the clearest end to end use case in the project. The idea is to run a container registry mirror behind your Worker domain and then tell the local Docker daemon to use that mirror.

Step one is configuration on the Docker host. The README gives a file to write and two commands to apply it:

```bash
   mkdir -p /etc/docker
   cat >/etc/docker/daemon.json <<EOF
   {
     "registry-mirrors":["https://dockerhub.xxx.com"]
   }
   EOF
   systemctl daemon-reload
   systemctl restart docker
```

Replace the placeholder host with your own Worker custom domain, then reload and restart the daemon so the mirror setting takes effect.

Step two is confirming that the mirror answers. The README uses a search against the mirror domain:

```bash
   docker search dockerhub.xxx.com/image_name
```

Here the mirror host is your Worker custom domain and the image name is whatever you are looking for. The search against a specific registry host is the check that tells you whether the Worker is forwarding correctly, because it exercises the same path that a pull would take.

The README also lists the upstream registry hostnames that can be assigned to PROXY_HOSTNAME for this purpose, including registry-1.docker.io, k8s.gcr.io, registry.k8s.io, quay.io, gcr.io, ghcr.io, docker.cloudsmith.io and public.ecr.aws. Setting the variable to one of these hosts is all that is required on the Worker side.

## Why the author asks you not to proxy an entire site

The strongest warning in the README sits at the top and is worth taking literally: the recommendation is for personal use, with request filtering through regular expressions, with a custom domain on the Worker, and without proxying a whole site such as GitHub, because doing that can trigger official risk control on the account and the author accepts no responsibility for it.

That is not a technical footnote. A proxy in front of a large site carries the upstream's traffic, and the upstream can respond in ways that have nothing to do with your intentions, from rate limiting to account suspension. The recommended mitigations all appear in the environment variable table, and they form a coherent design: restrict the paths that are proxied with PATHNAME_REGEX, restrict the clients with the user agent and IP patterns, and restrict the geography with the region patterns.

The mechanism has a sharp edge worth knowing. Both a whitelist and a blacklist exist for user agent, IP and region, and the README does not state the precedence between them when a request matches both, nor does it state what happens when a variable is left empty. Without that precedence, the safest configuration for a personal setup is a whitelist you control, since a blacklist leaves the default case open.

## Where this single file proxy stops working

There are several boundaries, and they come from the design rather than from missing effort.

The first is scope. One Worker handles one upstream hostname, and the README describes exactly one PROXY_HOSTNAME value. Running several proxies means several Workers, several custom domains and several variable sets, with no shared configuration or routing table described in the documentation.

The second is what the script does with responses. The environment variable list covers request filtering, redirect behaviour and debugging, but the README does not document response caching, compression, header rewriting, cookie handling or WebSocket support. The presence of URL302 and KEEP_PATH suggests the script has a redirect path of its own, but the documented behaviour of that path is limited to where the browser is sent and whether the path survives.

The third is release discipline. The repository publishes a single release, v0.0.1, dated 2024-07-28, and the version in package.json is 0.0.1. The last push was on 2026-08-16, so the code is being touched, but the only tag to pin is v0.0.1, with no changelog and no version history beyond it. Anyone deploying this in production is tracking the default branch, not a release.

## An edge proxy versus a proxy you host yourself

The alternative to a Worker script is a proxy on infrastructure you control: a container on a virtual machine, a reverse proxy in your own network, or a tunnel service that forwards to a local service. The difference in approach is where the TLS termination and the egress IP live.

With cf-workers-proxy the traffic is terminated at the Cloudflare edge and leaves from Cloudflare addresses, while the upstream sees a Cloudflare egress rather than your own. Your own proxy keeps the egress address stable and yours, which matters for services that fingerprint clients, and it gives you full control over caching, header rewriting and logging. What the Worker wins on is zero server administration and a custom domain in front of the upstream with nothing else to patch.

For personal access to a single blocked host, the Worker route is much less work, and the README's Docker mirror example is the case where it makes sense: image pulls are high volume but low sensitivity, and the mirror host is a convenience rather than a security boundary. For anything carrying credentials or serving other people, the self hosted route gives you the audit trail and the address stability that a shared edge cannot, and the README's own caution about proxying a whole site points the same way.

## Conclusion

Adopt cf-workers-proxy if you need to reach one specific host through a Cloudflare edge and are willing to restrict it with a path regex and an allowlist. Do not point it at a whole service such as GitHub, since the author warns that doing so risks account rate limiting. Before you deploy, confirm the PROXY_HOSTNAME value, decide whether the upstream terms permit proxying, and note that the only tagged release is v0.0.1 from 2024-07-28 while the last push was on 2026-08-16.

## FAQ

### How do I deploy cf-workers-proxy on Cloudflare Workers?

Copy the _worker.js file from the repository and save and deploy it in the Cloudflare dashboard. A second option is to fork the repository and connect it to Cloudflare for a Pages deployment.

### Which environment variable selects the site that cf-workers-proxy forwards to?

PROXY_HOSTNAME holds the upstream hostname and is the only mandatory variable. PROXY_PROTOCOL carries the upstream scheme and defaults to https.

### Can cf-workers-proxy be used to accelerate Docker image pulls?

Yes. The README lists registry hostnames such as registry-1.docker.io, ghcr.io and quay.io for PROXY_HOSTNAME, and shows how to point the Docker daemon at your Worker custom domain with the registry-mirrors setting in /etc/docker/daemon.json.

### What licence does cf-workers-proxy use and how often is it updated?

The project is GPL-3.0. It has one tagged release, v0.0.1 from 2024-07-28, and the last push was on 2026-08-16, so there is no newer version tag to pin.

## Sources

- [jonssonyan/cf-workers-proxy on GitHub](https://github.com/jonssonyan/cf-workers-proxy)
- [License: GPL-3.0](https://github.com/jonssonyan/cf-workers-proxy/blob/main/LICENSE)
- [Project website](https://t.me/jonssonyan_channel)
- [README](https://github.com/jonssonyan/cf-workers-proxy/blob/main/README.md)
- [Releases](https://github.com/jonssonyan/cf-workers-proxy/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/jonssonyan-cf-workers-proxy
