Open-source self-hosted VPN
Share secure internet with the people you care about
One command turns a fresh VPS into a hardened VPN server that blends in with ordinary HTTPS, with a built-in web panel for you and a one-tap connection page for each person.

How it works
Two commands to a working VPN
You need a Debian or Ubuntu VPS (a $5/month one is enough) and a terminal on your computer. Meridian sets up the rest.
meridian setup, start to finish: 3½ minutes. Download the videocurl -sSf https://getmeridian.org/install.sh | bashmeridian setupThe wizard asks a few plain questions, shows a review, then sets up your server. For one server with no questions, run meridian deploy IP — see the CLI reference.
What happens behind the scenes
Installs the control service and web panel with a node agent that runs Xray — no Docker, no third-party panel
Generates x25519 keypair — unique encryption keys for Reality authentication
Hardens the server — UFW opens only your SSH port, 443 (TCP and UDP), and 80 for certificates; SSH key-only login, fail2ban, BBR congestion control
Configures VLESS+Reality on TCP 443, where probes see a real website's certificate
Adds XHTTP and Hysteria2 — XHTTP through nginx on the same port, Hysteria2 on UDP 443 with salamander obfuscation
Outputs QR codes and a connection page once real traffic has passed through the new subscription
See it
What you and your people get
Every deployment includes a connection page for each person and a web panel for you. Both demos run in your browser on invented data: click around, nothing is real and nothing is sent anywhere.
Connection page
Each person opens their subscription link in a browser: they pick their platform and app, import with one tap or a QR code, check their traffic and expiry, and read notices and plain help in four languages.
Try the connection pageWeb panel
Run meridian panel to open your management panel (owner console). Add people, share links and QR codes, set expiry dates, traffic limits, and device caps, keep private notes and tags, post a notice for everyone, and issue scoped API tokens.
Try the web panel
One person: links and QR codes, traffic limit, expiry, device cap, private notes and tags, reissue, or session cut-off.

Servers: live health, Xray version, traffic, monthly allowances, and payment reminders.

Privacy: client IPs are never logged, and device limits and daily history start off with clear disclosures.
Command builder
Build your command
Pick options and copy the full command. Covers deploy, relays, checks, camouflage scans, diagnostics, and teardown.
Deploy Reality, XHTTP, and Hysteria2 on one server. Sets up the control service, web panel, nginx, the firewall, and TLS.
meridian deployFirst time? Just run meridian setup — the wizard asks for everything it needs.
Technology
How it avoids detection
OpenVPN and WireGuard have recognizable traffic signatures. A VLESS+Reality connection is hard to tell apart from ordinary HTTPS to a real website.
Deep Packet Inspection (DPI)
DPI inspects traffic patterns to identify VPN and proxy protocols. OpenVPN and WireGuard have handshakes that are easy to recognize and block.
VLESS+Reality runs inside a standard TLS 1.3 connection on port 443, so DPI sees what looks like ordinary HTTPS to the camouflage site. Every server also offers XHTTP and Hysteria2, so a block on one method leaves the others working.
Active probing
Censors connect to suspicious servers and try to fingerprint them. If a server responds differently than the website it claims to be, it gets blocked.
Reality borrows the TLS identity of a real website: by default a site hosted near your server, or www.google.com. A probe without your key is passed through to that site and sees its genuine certificate. Only clients with your key enter the VPN tunnel.
TLS fingerprinting
Every TLS client sends a unique "Client Hello" fingerprint. Censors flag connections where the fingerprint doesn't match the claimed application.
Client apps use uTLS to send the same Client Hello as Chrome. Meridian also publishes a Firefox copy of each Reality and XHTTP entry, so if censors flag one fingerprint, the other keeps working.
Connect
Scan and go
After deploying, each person gets a connection page with QR codes and one-tap import. Send them the link — they tap once and connect.
Connection pages list these apps first and link others for each platform. See the demo.
Architecture
Under the hood
Standalone mode (no domain)
nginx owns TCP port 443 and routes connections by TLS SNI with its stream module. Reality connections go to Xray. Everything else reaches nginx's http module, which serves the connection pages, subscriptions, and XHTTP over HTTPS with a short-lived Let's Encrypt certificate for the server's IP (issued by acme.sh). Hysteria2 listens on UDP 443 with salamander obfuscation.
Meridian's control service sits behind nginx on a secret path: it keeps your users, serves their subscriptions, and hosts the web panel over HTTPS, with no SSH tunnel needed. A small agent on each server dials out to it, so nodes open no extra ports.
Domain mode (CDN fallback)
With --domain, nginx gets a Let's Encrypt certificate for your domain and routes that SNI to the domain's paths. XHTTP moves to the domain and VLESS+WSS is added. With Cloudflare proxying the domain, both travel through the CDN and keep working if your server's IP is blocked. The control service and connection pages stay on the IP certificate.
Relay mode (domestic entry point)
A Realm TCP forwarder on a server inside your country passes connections to your exit abroad. Relays carry Reality only; XHTTP, WSS, and Hysteria2 still connect to the exit directly. Encryption runs end to end between the app and the exit, so the relay never sees plaintext.
Add one with meridian relay add RELAY_IP --exit EXIT. Subscriptions and connection pages pick up the relay entries automatically.
Ready to get started?
Install Meridian, deploy your VPN server, and share access with the people who need it. A deploy usually takes 3 to 10 minutes.



