byJoey/warp-masque-actions: generating Cloudflare WARP MASQUE configs in GitHub Actions
GitHub Actions 自动生成 Cloudflare WARP (MASQUE) 密钥与 mihomo 配置,产物只存 artifact
At a glance
- What is it?
- The repository turns a fork-and-click GitHub Actions workflow into a 57-node mihomo config for Cloudflare WARP over MASQUE, with no local Python or server. The catch is that the client kernel has to be mihomo Alpha, not the stable build.
- Who is it for?
- Adopt it if you already run a mihomo Alpha client such as Clash Verge Rev, ClashMetaForAndroid or ClashMi and want a WARP config without installing Python locally. Do not adopt it if you need country selection, since the README states the free WARP exit is decided by Cloudflare anycast and WARP+ or ZeroTrust is unsupported, or if you rely on Surge, Quantumult X or Karing, which the README lists as incompatible.
- Can I use it commercially?
- Not without permission. GitHub finds no licence file in the repository, and without a licence all rights are reserved by default: you may read the code but not reuse it. Check the README, or ask the authors, before using it.
- Is it still maintained?
- Yes. The repository last received commits 13 days ago.
- What is it written in?
- Mainly JavaScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 16, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
What byJoey/warp-masque-actions actually removes from the setup
Registering a Cloudflare WARP device and producing a mihomo configuration for it usually means running a local script, keeping the generated private key somewhere, and repeating the whole thing whenever the key expires. This repository moves that step into GitHub Actions. You fork it, enable workflows, run the one named 生成 WARP MASQUE 配置, and download an artifact containing warp-masque.yaml, warp-masque-shadowrocket.txt and usque-config.json. The README's stated pitch is exactly that: no environment to install, no server.
The audience is narrow and the README is honest about it. You need a client built on the mihomo kernel that can be switched to the Alpha branch. Clash Verge Rev on Windows, macOS and Linux, ClashMetaForAndroid on the Prerelease-alpha tag, and ClashMi on iOS all qualify. Shadowrocket qualifies through a separate file of masque:// links. Surge, Quantumult X and Karing do not, because they are not mihomo kernels and do not understand masque. If your client is not on that list, the generated config is dead weight.
How the pipeline turns a WARP account into 57 mihomo nodes
The generation logic lives in scripts/gen_masque.py. Three constants at the top of that file define the node pool: V4 for IPv4 endpoints, V6 for IPv6 endpoints, and PORTS for the port list. The 57 nodes are combinations drawn from those lists, which is why the README can describe them as one WARP account reached through different addresses rather than 57 separate accounts. The routing rules come from ACL4SSR and are controlled by the RULESETS list in the same script.
That design has a direct consequence the README repeats in two places: every node shares the same exit IP. Latency differences between nodes come from the network path to each endpoint, not from different egress locations, so picking the lowest-latency node is the intended behaviour rather than testing each one for throughput. Of the 57 nodes, 28 are IPv6; on a connection without IPv6 they will not connect, and the README states the client skips them automatically.
The artifact itself is the delivery mechanism. It is retained for 7 days by default, and the README warns that on a public repository anyone can download it. The private-key field in the config is described as equivalent to an account password, and the suggested mitigation is to make the fork private.
Running the workflow and importing the config for the first time
The README lays out a five-step path, and the only prerequisite is a GitHub account. Fork the repository, open the Actions tab, and accept the prompt that enables workflows on the fork. Then select the workflow named 生成 WARP MASQUE 配置 from the left sidebar, click Run workflow, and click the green button once more. The README says to expect roughly a minute.
When the run finishes, the artifact appears at the bottom of the run page under Artifacts, named warp-masque-config. Downloading and extracting it yields the three files described above.
On the client side, the kernel switch is the step people skip. In Clash Verge Rev the path is 设置 then Clash 内核, where you select Alpha and wait for the download and automatic restart. The README draws a distinction that matters: updating the Verge application itself does not move the kernel to Alpha. If you import without switching, the expected error is:
订阅配置校验失败,请检查订阅配置文件,变更已撤销
level=error msg="proxy 0: unsupport proxy type: masque"For a headless setup, the README points at the mihomo Alpha binary and the command mihomo -d 配置目录, run against the directory holding the config. For iOS, ClashMi takes warp-masque.yaml directly, while Shadowrocket uses the masque:// lines from warp-masque-shadowrocket.txt, one per line.
The Alpha-kernel requirement is the main failure mode
masque support exists only in the mihomo Alpha branch. That single fact generates most of the friction in this project. A stable kernel does not degrade gracefully or fall back to a different protocol; it rejects the configuration with unsupport proxy type: masque. The README calls this the most common trap, and the reason is structural: the client application and the client kernel are separate components with separate update paths, so a user who keeps Clash Verge Rev current still has an unusable kernel.
There is a second failure mode that has nothing to do with the client. Running the workflow produces a login failed error when Cloudflare rate-limits or flags the account:
Failed to connect tunnel: login failed!The README attributes this to creating connections too frequently in a short window and recommends rerunning the workflow to obtain a new account. It also warns against converting the workflow into a high-frequency scheduled job for the same reason. That is a real constraint on how you can use this: it is a manual, occasional generator, not a refresh daemon.
A third limitation is scope. The README states plainly that free WARP accounts cannot choose an egress country, that the exit is decided by Cloudflare anycast, and that WARP+ and ZeroTrust are not supported. If country selection is a requirement, this repository is the wrong tool and the README says so rather than implying otherwise.
The Opera over MASQUE variant, and where it differs
The repository ships a second pipeline named Opera over MASQUE(套娃)that chains Opera's built-in VPN behind the WARP tunnel, giving the path 本机 -> MASQUE 接入点 -> Opera 落地 -> 目标. The README's argument for the extra hop is about what an observer sees: a direct Opera connection exposes 77.111.x.x addresses, while the chained setup shows only Cloudflare addresses such as 162.159.198.x, with the Opera endpoint inside the QUIC tunnel.
The combination space is why this variant produces a different shape of config. Every MASQUE endpoint is paired with every Opera region, and the README puts the result at around 400 nodes, with 9 to 11 landing points. Node names encode the path, so 欧洲1@198.1-443 means the first European landing reached through 162.159.198.1:443. Because that many nodes cannot be listed flat, they are grouped into 亚洲线路, 欧洲线路 and 美洲线路 url-test groups, each with lazy enabled so the client does not test all 400 entries on load.
Two constraints stand out. Opera's anonymous credentials expire, and the README states that opera-proxy refreshes them every 4 hours by default while the API does not return a real expiry time, so a failed connection means rerunning the workflow. And the landing regions are only Asia, Europe and the Americas, with the README naming Singapore, Amsterdam and US East as the observed exits. This pipeline also needs the Alpha kernel, because dialer-proxy is Alpha-only, and Shadowrocket and Stash cannot use it since they do not understand dialer-proxy.
The Worker deployment and its access model
The worker/ directory is a third delivery path for the same idea, aimed at people who want a subscription URL that updates itself rather than a manual Actions run. It is a single bundled file, worker/dist/worker.js, deployed to Cloudflare Workers, and it exposes two kinds of routes: the MASQUE-then-Opera chains that can change country, and a WARP直连 group that uses MASQUE alone with a Cloudflare exit. The README notes that the direct group already existed in the config as the dialer-proxy target and was simply exposed. Proton and Windscribe routes appear only if configured, with Windscribe covering 13 regions and Hong Kong as its only Asian option.
The refresh model avoids cron entirely. Opera credentials expire every 4 hours, and the Worker checks on subscription access: an unexpired credential returns the cache, an expired one triggers re-registration. The README's framing is that idle deployments do nothing. WARP registration data is stored in KV and reused so a new device is not registered on every request.
The access control design is the most specific part of the documentation. The status page and all APIs require a password, and because clients cannot send cookies when fetching a subscription, the subscription URL carries a signed token. Passwords are stored only as a PBKDF2 hash with a random salt, sessions are HMAC-signed tokens, comparison is constant-time, eight consecutive failures from one IP trigger a 15-minute lock, and an invalid path or token returns 404 rather than an enumerable error. Changing the password invalidates old links, since the token is signed with the password hash.
Deployment has two documented routes. The web route is four steps: create a KV namespace, create a Worker from Hello World and paste the contents of worker/dist/worker.js over it, bind the namespace with the variable name KV in capitals, then open the Worker URL and set a password. The command-line route is:
cd worker
npm install
npx wrangler login
# 建 KV,把输出的 id 填进 wrangler.toml
npx wrangler kv namespace create KV
npx wrangler deployAfter changing worker/src, npm run build regenerates the bundle used by the web deployment.
Maintenance, licensing and what the repository does not say
The last push to the default branch was on 2026-09-07, and the repository is not archived. There are no retrieved releases, so there is no versioned upgrade path to follow; the practical upgrade mechanism is to sync your fork with upstream. The README does address one stale-fork symptom directly: an Actions warning reading Node.js 20 is deprecated, which it says does not affect the generated config, and which it says is resolved in the current action versions. For forks created earlier, it points at two lines in .github/workflows/warp-masque.yml:
uses: actions/checkout@v6
uses: actions/upload-artifact@v6Operational cost is mostly credential churn rather than compute. Every workflow run issues a fresh WARP account, so a stale config cannot be refreshed in place; you rerun and re-import. The Opera variant adds credential expiry on a roughly 4-hour cycle, which the Worker handles automatically and the Actions pipeline does not.
The repository does not state a licence. The README contains no licence section and the top-level entries are .github/, .gitignore, README.md, configs/, scripts/ and worker/. Without a licence file, the terms under which you may reuse or redistribute the code are undefined, and that is worth resolving before building anything on top of it. Note also that the generated artifact contains a private key, so the artifact's retention and the visibility of your fork are part of the deployment decision, not an afterthought.
Editorial conclusion
Adopt it if you already run a mihomo Alpha client such as Clash Verge Rev, ClashMetaForAndroid or ClashMi and want a WARP config without installing Python locally. Do not adopt it if you need country selection, since the README states the free WARP exit is decided by Cloudflare anycast and WARP+ or ZeroTrust is unsupported, or if you rely on Surge, Quantumult X or Karing, which the README lists as incompatible. Before trusting an artifact, verify that your client reports the Alpha kernel and not the stable one, because the failure mode is an import error rather than a silent fallback.
Frequently asked questions
Is WARP a safe VPN?
The README does not assess WARP's privacy properties. What it does say is that the private-key field in the generated config is equivalent to an account password and should not be shared, and that artifacts on a public repository can be downloaded by anyone, with a private fork suggested as mitigation. It also notes that every workflow run creates a brand new account.
Which is better, Zero Trust MASQUE or Wireguard?
The README does not compare Zero Trust MASQUE against WireGuard. It states that WARP+ and ZeroTrust are not supported by this repository, and that country selection requires one of them, so the comparison falls outside what the project covers.
Does Cloudflare WARP track you?
The README does not discuss tracking. It only describes the network path, stating that the free WARP exit is determined by Cloudflare anycast and that the 57 nodes share a single exit IP.
Is 1.1.1.1 VPN banned?
The README does not address whether 1.1.1.1 or WARP is banned in any region. It does describe two related failure modes: individual endpoints can be blocked, which is why the config carries multiple addresses, and a login failed error that it attributes to Cloudflare rate-limiting the account.
Community notes