What Is Ultraviolet Proxy and Why Self-Host?

Ultraviolet is an open-source, service-worker-based web proxy originally developed under the Titanium Network umbrella. Unlike traditional server-side proxies that route all traffic through a central machine, Ultraviolet rewrites HTTP requests directly inside the visitor's browser using the Service Worker API. This makes it significantly harder for network-level filters to detect.

Self-hosting your own ultraviolet proxy server gives you full control over uptime, performance, and configuration. Public instances get blocked regularly; your own deployment stays alive as long as your server does. It also lets you customize allowed sites, bandwidth limits, and access rules — none of which are possible on shared ultraviolet proxy websites.

Prerequisites Before You Start the Ultraviolet Proxy Setup

Before running through this ultraviolet proxy tutorial, confirm you have the following ready:

  • Node.js 18 or later — Ultraviolet's core server components require a modern Node.js runtime. Use node --version to check.
  • npm or yarn — For installing dependencies. npm ships with Node.js.
  • Git — To clone the source repositories from GitHub.
  • A hosting account or local machine — Locally for testing; a VPS, Replit, Railway, or Render for public deployment.
  • Basic command-line familiarity — You'll be running a handful of terminal commands.

On Windows, use PowerShell or Windows Terminal. On Linux and macOS, the standard terminal works perfectly.

Understanding the Two Ultraviolet Deployment Models

Before diving into commands, understand the architectural split that determines how you deploy.

Ultraviolet Static Proxy

The ultraviolet static proxy model serves the client-side JavaScript bundle (uv.bundle.js, uv.sw.js, uv.config.js) as plain static files. The actual proxy routing is handled by a separate bare server or wisp server running as a separate Node.js process. This separation is ideal for CDN-fronted deployments — Cloudflare Pages or Netlify can serve the static assets while your Node process handles the WebSocket tunnel.

Ultraviolet Node Proxy

The ultraviolet node proxy bundles both the static frontend and the bare/wisp server inside a single Express or Fastify application. This is the simpler model for beginners. One npm start command launches everything. It's ideal for VPS deployments, Replit, and Railway where you control a single Node.js process.

Step-by-Step Ultraviolet Proxy Setup

Step 1 — Clone the Repository

The recommended starting point is the official Ultraviolet-App template, which pre-wires the bare server, the wisp server, and the static frontend into one deployable unit.

git clone https://github.com/titaniumnetwork-dev/Ultraviolet-App.git
cd Ultraviolet-App
npm install

The npm install step pulls in @titaniumnetwork-dev/ultraviolet, wisp-server-node, and Express. These are the three pillars of a working ultraviolet proxy server.

Step 2 — Review uv.config.js

Open static/uv/uv.config.js. The two most important fields are prefix (the URL path Ultraviolet proxies traffic through — default /service/) and bare (the path to your bare server — default /bare/). Leave these as defaults unless you have a specific reason to change them.

Step 3 — Start the Development Server

npm start

Navigate to http://localhost:8080. You should see a search bar. Enter any URL — if pages load, your ultraviolet node proxy is functioning correctly.

Step 4 — Test Service Worker Registration

Open DevTools → Application → Service Workers. You should see a service worker registered at the /uv/uv.sw.js scope. If the worker is missing, clear site data and reload. A missing service worker is the most common reason the ultraviolet proxy setup appears broken on first run.

Ultraviolet Proxy Deploy — Choosing the Right Host

Hosting choice determines uptime and latency. Here is a practical breakdown for anyone looking to ultraviolet proxy host their own instance:

  • Replit — Zero cost for hobbyists, one-click deploy. Sleeps on inactivity unless you use an uptime monitor. Best for private use.
  • Railway — Free tier with 500 execution-hours per month. Better uptime than Replit free. Supports environment variables natively, which is useful for configuring the bare server endpoint.
  • Render — Free web services that spin down after 15 minutes of inactivity. Slightly slower cold start than Railway but a clean deployment experience.
  • VPS (DigitalOcean, Hetzner, Linode) — The gold standard. Full control, no sleep, no traffic limits. A €4/month Hetzner CX11 runs Ultraviolet comfortably for hundreds of concurrent users.
  • Cloudflare Pages + Workers — Advanced setup. Serves the ultraviolet static proxy assets from Pages and routes the bare server through a Worker. Near-zero latency globally.

Configuring the Ultraviolet Static Proxy for Production

For production deployments, set the NODE_ENV environment variable to production. This disables verbose error output that could leak internal paths. Add a reverse proxy (Nginx or Caddy) in front of your Node.js process on a VPS deployment. A minimal Caddy config looks like this:

yourdomain.com {
  reverse_proxy localhost:8080
}

Caddy handles HTTPS automatically via Let's Encrypt. HTTPS is mandatory — service workers refuse to register on HTTP origins (except localhost), so your ultraviolet proxy server will not function over plain HTTP in production.

Keeping the Node Process Running

On a VPS, use PM2 to keep the ultraviolet node proxy alive across reboots:

npm install -g pm2
pm2 start npm --name "ultraviolet" -- start
pm2 save
pm2 startup

pm2 startup generates a systemd command that registers PM2 as a boot service. After a reboot, your ultraviolet proxy server restarts automatically.

Troubleshooting Common Setup Problems

Pages load as blank white: The bare server is unreachable. Confirm the bare path in uv.config.js matches the actual route your Express app exposes.

Service worker not registering: You are running on HTTP in production, or your Content-Security-Policy header blocks worker scripts. Check response headers in DevTools Network tab.

Port already in use: Another process holds port 8080. Change the port in index.js or kill the conflicting process with lsof -i :8080 on Linux/macOS.

npm install fails: Ensure your Node.js version is 18 or above. Run nvm use 18 if you use NVM, or update Node.js from the official website.

Next Steps After Setup

Once your ultraviolet proxy deploy is live and stable, consider these additions: add a custom domain with a clean SSL certificate, enable gzip compression in your Express config to cut bandwidth costs, restrict access with an IP allowlist if this is a private instance, and set up uptime monitoring via UptimeRobot so you know immediately if the server goes down.

The Ultraviolet community on Discord is the fastest source of help for anything not covered in this ultraviolet proxy tutorial. Developers who maintain the core library actively participate and can debug edge cases that generic documentation does not address.

Skip the Setup — Use Our Free Instance

Not ready to self-host? Use the live Ultraviolet Proxy right now — no setup required.

Launch Free Proxy →