xcancel Forwarder

Every twitter.com and x.com link on my home network transparently redirects to xcancel.com, a privacy-respecting frontend. The interesting part isn't the redirect — it's the setup wizard: a single HTML file that generates a certificate authority in your browser tab and hands you a ready-to-deploy ZIP, without a backend anywhere.

nginx Caddy Docker DNS node-forge JSZip

What It Is

The mechanism is simple: your DNS server (Pi-hole, dnsmasq, or router) answers queries for twitter.com, x.com, and t.co with the IP of a local nginx container, which issues a 301 to xcancel.com. Any device on the network — phones, laptops, guests — follows a shared tweet link and lands on xcancel instead of X, with no per-device configuration beyond trusting one certificate.

HTTPS is the wrinkle. Browsers hit twitter.com over TLS, so the local proxy needs a certificate for twitter.com that your devices trust — which means running your own little certificate authority. That's usually the step that turns a five-minute setup into an afternoon of OpenSSL incantations, and it's the step the wizard makes disappear.

A Setup Wizard With No Backend

The web wizard is one self-contained HTML file, hosted on GitHub Pages. It walks through the real decisions — nginx or Caddy, bridge or macvlan networking, which DNS method fits your network, which upstream resolver — and every artifact it produces adapts to your answers. Choose Pi-hole and the nginx config grows a dynamically generated hosts.txt endpoint you can subscribe to as an adlist, built from nginx's own $server_addr so the IP is always correct. Choose Caddy and you get a Caddyfile instead of an nginx conf. The review step ends with tailored step-by-step install instructions, not a generic README.

A Certificate Authority in a Browser Tab

Pick "generate in browser" for SSL and the wizard becomes a CA. Using node-forge, it generates RSA key pairs, self-signs a root CA with your own subject parameters, then issues a server certificate with subject alternative names covering twitter.com, x.com, t.co and their wildcards — SHA-256 signed, chain-bundled for nginx. Nothing is sent anywhere; the private keys exist only in the page's memory until you download them.

The details are handled the way a real CA tool would: you choose whether the CA private key is discarded after signing (more secure, no renewals) or kept — optionally encrypted with AES-256 via PBKDF2 before it's written out. The CA certificate is exported in PEM for Linux and macOS, DER (.cer) for Windows, and a PKCS#12 bundle (.p12/.pfx) for import dialogs that want one, with the SHA-256 fingerprint displayed so you can verify what you're trusting. Prefer to run the commands yourself? The manual path generates a complete OpenSSL script with your parameters substituted in.

One ZIP, Ready to Deploy

The last step assembles the entire deployment in memory with JSZip: Docker Compose file, environment file, the nginx or Caddy config, the freshly minted certificates already placed in the paths the config expects, plus per-platform CA installation guides. One click downloads a directory tree you unzip on your server and start with docker compose up -d. The browser never talks to a server, and the config never exists anywhere but your machine — the static page is the whole product.

Nice Touches

The nginx config speaks HTTP/2 and HTTP/3 (QUIC with Alt-Svc advertisement), because if you're going to intercept twitter.com you might as well do it with a more modern protocol stack than the real one. For headless servers there's a parallel Python CLI wizard that auto-detects network settings and can drive mkcert directly, and for the curious there's a fully documented manual path — the docs cover Pi-hole, dnsmasq, router DNS, hosts files, testing, and troubleshooting for every combination the wizard supports.