Home/ Self-host

Self-host a tunnel service on your own VM.

21tunnel is the only tunneling service where the control plane, the dashboard, and the agent are all open-source. One Rust binary, one Postgres database, one nginx config — and your users' traffic never touches anyone else's infrastructure.

The case

Why anyone self-hosts ingress.

There are three honest reasons, and they cover about 95% of the people who reach out to us.

01

Compliance scope

If SOC 2, HIPAA, or FedRAMP is in your audit, every third-party vendor is a question on a spreadsheet. Self-host collapses that row. Your users' payload never leaves infrastructure you control.

02

Data residency

EU-only? India-only? The same binary runs in any region. Pick your VM, pick your Postgres. No cross-border routing, no “our region is eventually-consistent with yours” surprises.

03

Cost at scale

At ~$0.02/GB metered on most hosted tunnel services, a single customer pushing 10 TB/month is $200/mo in egress. A medium VM runs all your customers' ingress for $20/mo — if your economics work at volume, self-host pays off by month three.

Bootstrap

Four commands, fifteen minutes.

Start here if you want to try the whole thing tonight. Uses a single Linux VM; every step below is also in the repo's runbook. See full runbook →

  1. 1

    Clone + build

    Rust 1.75+. Building on the target VM takes about 4 minutes on 2 vCPU.

    git clone https://github.com/vikasswaminh/21tunnel
    cd 21tunnel
    cargo build --release -p qnt-server
  2. 2

    Postgres + config

    Create a database; generate the JWT signing key; drop in server.toml.

    createdb qnt
    head -c 48 /dev/urandom | base64 | tr -d '\n' > /etc/qnt/jwt.key
    chmod 600 /etc/qnt/jwt.key
    cp deploy/server.toml.example /etc/qnt/server.toml
    # Edit server.toml: set [database].url + [server].domain
  3. 3

    Start the server

    Migrations run automatically on first boot (five of them, idempotent). Listens on three ports: 7443 agent, 8080 public proxy, 9090 admin API.

    ./target/release/qnt-server --config /etc/qnt/server.toml
    
    # [INFO] web auth: JWT signing key loaded
    # [INFO] audit retention worker started retention_days=90
    # [INFO] API server accepting local_addr=Some(127.0.0.1:9090)
  4. 4

    Seed a superadmin + log in

    Sign up through the dashboard at your configured domain, then promote yourself to superadmin via SQL. From that point, new signups appear in your Pending Approvals queue.

    # After your first signup:
    psql qnt -c "UPDATE users SET is_superadmin=TRUE, email_verified=TRUE WHERE email='you@example.com';"
    
    # Re-login, and you'll see the red Admin Console in the sidebar.
What you get

Same binary, same features.

Self-hosting is not a degraded mode — it's the same build we run on our hosted tier. Feature parity by default. The only difference is who pays the VM bill.

Included on self-host
  • Multi-tenant dashboard (hybrid signup → superadmin approval)
  • Owner / admin / member / viewer RBAC
  • argon2id passwords + JWT + rotating refresh cookie
  • Optional TOTP MFA + 10 recovery codes
  • Partitioned audit log + retention worker
  • Request inspector with replay
  • Capability-token agent auth (HMAC-signed, scoped)
  • Stripe Checkout + Portal (bring your own account)
  • Resend email (bring your own key)
  • Prometheus metrics + OpenTelemetry exporter
You bring
  • A Linux VM (1 vCPU, 2 GB RAM covers early-stage traffic)
  • Postgres 15+
  • A domain + DNS under your control
  • nginx (for TLS termination and the public :80 frontend)
  • Optional: a Resend account (signup emails)
  • Optional: a Stripe account (if you charge your users)
  • Optional: Certbot (or Cloudflare-managed cert)

No phone-home. The binary has zero outbound telemetry. We don't know you're running it unless you tell us. Add your own metrics endpoint or OTLP collector if you want observability — we integrate, we don't collect.

Support options

Free forever. Paid when you need us.

The source is always free. If you need a throat to choke when something breaks at 3am, here are the paid levels.

OSS community

$0forever
  • Full binary + dashboard + docs
  • GitHub Issues for bug reports
  • Community Discord
  • Best-effort response from maintainers
  • MIT + Apache-2.0 license
Clone the repo

Self-host + SLA

$5,000/ month
  • Everything in Support tier
  • 24×7 on-call + 1h P1 response
  • Migration assistance
  • SOC 2 evidence package
  • Security review letter for audits
Talk to us

Clone tonight. Your users by Friday.

Production-adjacent, not hypothetical — every feature on this page exists in master. Four commands get you to first signup. Your whole platform, on your whole VM.

Clone the repo Read the build log See vs ngrok