Self-hosted service
nellimonix/warp-config-generator-vercel avatar
nellimonix/warp-config-generator-vercel

warp-config-generator: build Cloudflare WARP configs for any client

WARP configuration generator with support for various deployment platforms (Vercel, Netlify, Cloudflare)

1,042 stars48 forksTypeScriptMIT

At a glance

What is it?
The warp-config-generator is an open source generator that turns a set of options into a Cloudflare WARP configuration for WireGuard, AmneziaWG, Clash, Throne, Nekoray, Husi, Karing or WireSock, and it ships as a web app you can deploy to Vercel, Netlify, Cloudflare Workers or Docker. It suits someone who wants a working WARP config without hand-editing key material.
Who is it for?
Adopt warp-config-generator if you need to produce working Cloudflare WARP configurations for several client applications and want to self-host the generator rather than paste keys into a third party. Skip it if you only need one config once, since a single WireGuard profile can be written by hand in a minute.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What the generator is for

This is an open-source generator for Cloudflare WARP configs, producing output for WireGuard, AmneziaWG, Clash, Throne, Nekoray, Husi, Karing and WireSock. The problem it solves is narrow and real. WARP gives you a free network client, but the configuration is not one format, it is eight, and each client wants different fields, different key names and a different way of expressing the endpoint and the allowed addresses. Writing those by hand is error prone, and a config with the wrong AllowedIPs either fails to route or routes everything. The project is public branch with no captcha, no analytics and no promo blocks, and the README is explicit that you should deploy your own. The primary language is TypeScript, the licence is MIT, the last push was on 2026-10-19, and the repository has no GitHub releases, so the deployment platforms are the distribution channel.

Running it as a container, prebuilt or local

Docker is the recommended route and there is a prebuilt image published to GHCR on every push to master:

bash
docker run -d --name warp-generator \
  -p 3000:3000 \
  --restart unless-stopped \
  ghcr.io/nellimonix/warp-config-generator-vercel-public:latest

After which you open http://localhost:3000. To build it locally instead:

bash
docker build -t warp-generator-public .
docker run -d -p 3000:3000 --name warp-generator warp-generator-public

The compose file is the same thing expressed as a service:

yaml
services:
  warp-generator:
    image: ghcr.io/nellimonix/warp-config-generator-vercel-public:latest
    container_name: warp-generator
    ports:
      - "3000:3000"
    restart: unless-stopped

The Dockerfile is a three-stage build on node:22-alpine, with a dependencies stage, a builder stage that sets `DOCKER_BUILD=1` and a `NODE_OPTIONS` heap of 2048, and a runner stage that copies the Next.js standalone output, the static assets, the public files and the `config` directory, then drops to a non-root user nextjs and starts `node server.js` on port 3000.

The same app on four hosting platforms

The unusual part of this project is that it targets four deployment models from one codebase, and the README gives each of them a path. On Vercel there is a deploy button, or the CLI with `vercel deploy`, and `vercel dev` for local development. On Netlify there is a deploy button, `netlify deploy`, and `netlify dev`. On Cloudflare Workers there is a deploy button, `wrangler deploy` and `wrangler dev`. And Cloudflare Pages uses the same `wrangler.jsonc` with a static export:

bash
CLOUDFLARE_WORKERS=1 npm run build
npx wrangler pages deploy out --project-name=warp-generator

or you connect the repository in the Cloudflare dashboard with the build command `CLOUDFLARE_WORKERS=1 npm run build` and the output directory `out`. The `CLOUDFLARE_WORKERS=1` flag is what switches the build between the Next.js server output and a static export, and it is the single build-time difference between the four targets. The local development commands are the usual ones, `npm install`, then `npm run dev` for a dev server on port 3000, `npm run build`, `npm run start` to serve the production build, and `npm run lint`.

The options, and the ones that silently change behaviour

The generator exposes the same options in the UI and in the `POST /api/generate` endpoint, and the option table is the most informative part of the documentation. `endpointRandom: true` selects a fresh Cloudflare host and port during generation, and for MASQUE it uses dedicated MASQUE address and port pools. `clashProtocol` accepts `awg`, `masque` or `awg_masque`, with the combined mode emitting selectable AWG, MASQUE QUIC and MASQUE H2 proxies. IPv6 is enabled by default, and disabling it removes IPv6 from the interface address, the DNS list and the default all-sites AllowedIPs. Exclude LAN is only available in All sites mode, where it replaces the default routes with public address ranges so private ranges stay outside the tunnel. PersistentKeepalive is off by default, and enabling it with an empty field uses 25 while the API accepts integers from 1 through 65535 and omits invalid values.

The custom I1 mask, and the silent fallback

The Custom I1 option is the one to read carefully, because its failure mode is invisible. A non-empty value is trimmed and must be at most 253 characters with no whitespace. AmneziaWG WireGuard uses it to generate a QUIC I1 mask, and WireSock uses it as an Id. Empty or invalid input silently falls back to a bundled random mask or domain. That last clause is the important one, since a user who types a value with a space in it gets a valid config that is not the one they asked for, with no error to tell them. The comparison with PersistentKeepalive is instructive, because there the API omits invalid values rather than substituting a default, so the two options fail in opposite ways. The I1 value is a domain-shaped mask used to disguise the WireGuard handshake, and getting it wrong is a network debugging problem rather than a configuration error.

The API, and what comes back

The generator is usable as an API, and the example request against a local deployment is the reference:

bash
curl -X POST http://localhost:3000/api/generate \
  -H 'Content-Type: application/json' \
  -d '{
    "selectedServices": [],
    "siteMode": "all",
    "deviceType": "awg15",
    "endpoint": "engage.cloudflareclient.com:4500",
    "configFormat": "wireguard",
    "dnsId": "cf",
    "ipv6": false,
    "excludeLan": true,
    "persistentKeepalive": 25,
    "customI1Domain": "google.com"
  }'

A successful response has `success: true` and a `content` object containing `configBase64`, `qrCodeBase64`, `configFormat` and `fileName`. The `configBase64` field carries the Base64-encoded configuration and `qrCodeBase64` is an image data URL, which is how the same generator serves a browser and a script. The `deviceType` of `awg15` in the example reflects that the WARP endpoint is a specific AmneziaWG device profile rather than a generic WireGuard peer, and the `siteMode` of `all` is the mode that excludes the LAN.

The DNS provider list, and the sync that does not exist

The part of this project most likely to cause you a bug is the DNS provider configuration, and the README explains why with unusual honesty. Providers come from `config/dns.ts`, and community providers are marked with a dot. Selecting a community provider forces All sites mode and clears the selected services, because community providers do not support split tunnelling, and an unknown provider id falls back to Cloudflare DNS. The trap is that there are three copies of the provider list. Docker and Vercel use `config/dns.ts` directly, while Cloudflare Workers and Netlify execute the embedded `DNS_PROVIDERS` arrays in `worker/api-handler.js` and `functions/api/generate.js`. Unlike the IP ranges and the I1 masks, DNS providers do not currently have an automatic sync script, so the documentation tells you to mirror the entry by hand and to run `npm run build` before opening the pull request. A provider shown in the static UI that is missing from the embedded list falls back to Cloudflare DNS at generation time, which is a silent behaviour change rather than an error.

Adding a service, and the one file you must not edit

The specific-sites mode lets users pick services to route through WARP, and adding one is a data change rather than a code change. You fork the repository and create a branch, then create `config/services/<your-service-key>.json` with a name, an icon name from react-icons, an iconLibrary such as `fa`, `fa6`, `si`, `bi`, `md` or `ri`, an optional type of `new` to show a NEW badge, and a comma-separated list of CIDR ranges in `ips`. The documentation is specific that you should use a real ASN or IP lookup tool, naming Cloudflare's whois, BGP.tools and a `whois` command against Team Cymru, and that you should verify the icon name exists in the chosen library. The step you must not skip is the third one. Do not edit `worker/api-handler.js` or `functions/api/generate.js`, because a GitHub Action named `build-ip-ranges` rebuilds the `IP_RANGES` blocks in both files automatically on merge to master and syncs the new service into the production branch. You can run the same rebuild locally with `node scripts/build-ip-ranges.mjs`, which reads `config/services/*.json` and rewrites the marked block, and which is idempotent so it is safe to run repeatedly.

Editorial conclusion

Adopt warp-config-generator if you need to produce working Cloudflare WARP configurations for several client applications and want to self-host the generator rather than paste keys into a third party. Skip it if you only need one config once, since a single WireGuard profile can be written by hand in a minute. Before you deploy, read the platform notes, because Docker and Vercel read `config/dns.ts` directly while Cloudflare Workers and Netlify run embedded copies of the provider list, and the README is explicit that DNS providers have no automatic sync script, so the two lists drift unless you mirror them by hand.

Frequently asked questions

How do I run the WARP config generator?

With Docker using the prebuilt image: `docker run -d --name warp-generator -p 3000:3000 --restart unless-stopped ghcr.io/nellimonix/warp-config-generator-vercel-public:latest`, then open http://localhost:3000. You can also deploy to Vercel, Netlify or Cloudflare Workers, and locally with npm install and npm run dev.

Which WARP client formats does the generator produce?

WireGuard, AmneziaWG, Clash, Throne, Nekoray, Husi, Karing and WireSock. The Clash protocol option accepts awg, masque or awg_masque, with the combined mode emitting selectable AWG, MASQUE QUIC and MASQUE H2 proxies.

What does the generate API return?

A successful response has success: true and a content object containing configBase64, qrCodeBase64, configFormat and fileName. The config is Base64-encoded and the QR code is an image data URL.

Why does my new service not appear in the generated config?

The IP_RANGES blocks in worker/api-handler.js and functions/api/generate.js are rebuilt automatically by a GitHub Action on merge to master, and you should not edit those files by hand. You can run the same rebuild locally with `node scripts/build-ip-ranges.mjs`, which reads config/services/*.json and rewrites the marked block idempotently.

What is the custom I1 option for?

A non-empty value is trimmed and must be at most 253 characters with no whitespace. AmneziaWG WireGuard uses it to generate a QUIC I1 mask and WireSock uses it as an Id, while empty or invalid input silently falls back to a bundled random mask or domain.

Official sources

  1. Issues
  2. License: MIT
  3. nellimonix/warp-config-generator-vercel on GitHub
  4. Project website
  5. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/nellimonix-warp-config-generator-vercel.svg)](https://hysenlabs.com/projects/nellimonix-warp-config-generator-vercel)

Was this useful?