StartTunnel Documentation
StartTunnel is a virtual private router (VPR) — a minimal, self-hosted router that runs on a VPS instead of sitting in your house. Use it for private remote access to self-hosted services, or to expose services to the public Internet without revealing your home IP address.
Getting Started
User Manual
Reference
Installing
Install StartTunnel on a Debian VPS by renting a server, running the one-line installer script, and initializing the web interface. The entire process takes just a few minutes.
Watch The Video
Prerequisites
Before setting up a VPS, make sure you have an SSH key pair on your laptop or desktop — this is how you’ll log into the server. Most providers require you to upload your public key during server creation. If you don’t have one yet, open a terminal on your computer and run:
ssh-keygen -t ed25519
Your public key will be at ~/.ssh/id_ed25519.pub. You’ll paste its contents into your VPS provider’s dashboard when creating the server.
Get a VPS
Rent a cheap VPS with a dedicated public IP. Minimum CPU/RAM/disk is fine. For bandwidth, no need to exceed your home Internet’s upload speed.
Requirements
- Debian 13
- Root access
- Dedicated public IPv4 address (required for publishing ports to the clearnet)
Important
StartTunnel is designed to be the sole application on your VPS. The installer disables UFW and manages its own firewall rules via iptables. Do not run other Internet-facing services on the same VPS.
Warning
Publishing ports requires a dedicated public IPv4 address assigned to your VPS. Shared IPv4 addresses (CGNAT, shared NAT, or load-balanced IPs) will not work. IPv6-only VPSes will not work for clearnet hosting either — see Can I use an IPv6-only VPS? in the FAQ. Confirm with your VPS provider that the IPv4 address is dedicated to your VM before purchasing.
Cloud firewalls
Some VPS providers have a cloud-panel firewall that sits outside the operating system. This firewall can silently block WireGuard traffic (UDP 51820) before it ever reaches your VPS, even if the OS firewall is correctly configured. If your provider is listed below, you must open UDP 51820 in the cloud panel before devices can connect.
Note
Providers like Hetzner, DigitalOcean, Vultr, and Linode have optional cloud firewalls that are not enabled by default. If you haven’t explicitly enabled one, no action is needed.
IONOS VPSes have a hardware-level firewall that by default only allows TCP 22, 80, 443, 8443, and 8447. UDP 51820 is blocked before it reaches the VM.
- Log into the IONOS Cloud Panel.
- Go to Server & Cloud → select your VPS → Network → Firewall Policies.
- Add an inbound rule: Protocol = UDP, Port = 51820.
- Save and apply.
Connect to your VPS
Most providers let you add an SSH public key during server creation. If you did, connect with:
ssh root@<VPS_IP>
Run the installer
Run:
curl -sSL https://start9.com/start-tunnel/install.sh | sh
Note
If DNS resolution is not working on your VPS, the installer will configure public DNS resolvers (Google, Cloudflare, Quad9) and back up your existing
/etc/resolv.conf.
Initialize the web interface
StartTunnel can be fully managed from the command line, but it also offers a web UI for convenience. To set it up, run:
start-tunnel web init
This initializes a web server, creates a random password, and configures an SSL certificate. You will be prompted to either generate a new Root CA or provide your own certificate.
Save the URL and password to your password manager.
Note
The URL, password, and certificate are only for accessing your StartTunnel’s web user interface. None are needed to use StartTunnel from the command line.
Certificate options
When prompted for a certificate, you have two choices:
If you already have a StartOS server and have trusted its Root CA, you can sign the StartTunnel certificate with that same CA. This means your browser will trust the StartTunnel web UI automatically — no additional certificate to manage.
-
On your StartOS server, generate a certificate for your StartTunnel’s hostname or IP:
start-cli net ssl generate-certificate <HOSTNAME_OR_IP>This outputs a private key and certificate chain in PEM format.
-
During
start-tunnel web init, when prompted for a certificate, select Provide. -
Paste the private key first and press Enter. You may need to press Enter an extra time for it to be accepted.
-
Paste the certificate chain next and press Enter. Again, you may need to press Enter an extra time.
Next steps
- Subnets — Create isolated VLANs
- Devices — Add servers, phones, and laptops
- Published Ports — Expose ports on your VPS’s public IP
Subnets
A subnet is an isolated private network (a VLAN) whose devices can all communicate with each other. By default a subnet is a /24 (254 devices), but the range is configurable: you can give it a larger block (a smaller prefix, e.g. /16) for more devices. /24 is the smallest allowed — StartTunnel rejects a range smaller than /24.
StartTunnel comes with a default subnet, which is sufficient for most users. You can create additional subnets to isolate groups of devices from each other.
Creating a Subnet
- In StartTunnel, navigate to
Subnetsand click “Add”. - Name the subnet and accept or customize the IP range — the block its devices draw addresses from (a
/24by default, or a larger block). The range is fixed once the subnet is created; everything else can be changed later by editing the subnet. - Optionally set the subnet’s DNS resolver, outbound IP, and IPv6 prefix (all covered below).
- Click “Save”.
DNS
Each subnet resolves domain names through one of three modes, chosen with the DNS field in the Add/Edit dialog:
- Default (VPS provider) — use the resolvers your VPS provides. The simplest option, and the default.
- Device — designate one device already on the subnet as its resolver (at least one device must exist first). Use this to point the subnet at a resolver you run yourself.
- Custom — enter up to three DNS server IP addresses to query directly.
This chooses the upstream resolver the subnet uses. It is separate from the private DNS records StartTunnel serves for your own hostnames — see DNS Records for those.
Outbound IP
If your VPS has more than one public IPv4 address, you can choose which one a subnet’s outbound traffic leaves from — its egress (SNAT) address — with the WAN IP field:
- System default — let StartTunnel choose (masquerade through the server’s primary address). When the address it resolves to is known, it’s shown in parentheses, e.g.
System default (203.0.113.10). - A specific address — pin egress to one of the VPS’s detected public IPv4 addresses.
A single-IP VPS has only one choice, so you can leave this on System default. Individual devices can override their subnet’s choice — see Devices › Outbound IP.
IPv6
A subnet can carry a routed IPv6 prefix so every device on it gets a stable, globally-routable address. Set the IPv6 Prefix field (e.g. 2001:db8:abcd::/64) in the Add/Edit dialog, or leave it blank for none. See IPv6 for prefix sizing, routing, and VPS requirements.
Removing a Subnet
- Navigate to
Subnets, select the subnet, and click “Remove”.
Warning
Removing a subnet disconnects all devices on it. Their WireGuard configs will no longer work.
Devices
Every device on a StartTunnel subnet gets its own WireGuard configuration. Devices come in two kinds, listed in separate tables on the Devices page:
- Servers — a StartOS server that may configure the gateway on its own behalf: injecting DNS records for its private domains and auto-publishing ports (via PCP/UPnP). Both capabilities are on by default for a Server.
- Clients — a plain peer such as a phone or laptop that uses the tunnel for connectivity only, with no gateway-configuration abilities.
Adding a Device
-
In StartTunnel, navigate to
Devicesand click Add — on the Servers table for a StartOS box, or on the Clients table for a phone or laptop. Which button you click sets the device’s kind (there is no kind selector in the form). -
Fill out the form:
- Give the device a name (e.g. “Start9 Server”, “Phone”, “Laptop”).
- Select a subnet (the default is fine).
- Accept or choose an IP address on the subnet (the default is fine).
- Optionally set the outbound IP — the WAN address the device’s traffic leaves from.
- For a Server, Allow DNS injection and Allow auto-publish are enabled by default; uncheck either to withhold that capability. A Client has neither.
- Click “Save”.
-
Download the resulting
start-tunnel.conf(or copy to your clipboard). -
Import the config into the appropriate app on the device:
- StartOS server: Navigate to
System > Gateways, click “Add”, name the gateway (e.g. “StartTunnel”), upload or paste the config, and click “Save”. StartOS will now see the VPS as a gateway, and each service interface will automatically acquire new addresses corresponding to it. - Phone or tablet: Scan the QR code shown in StartTunnel using the WireGuard app.
- Laptop or desktop: Download the config and import it into the WireGuard app.
- StartOS server: Navigate to
Server capabilities
A Server has two independently-toggleable capabilities, shown as switches in the Servers table:
- DNS injection — lets the server manage the DNS records StartTunnel serves for your private domains (see DNS Records).
- Auto-publish — lets the server publish its own ports via PCP/UPnP (see Published Ports).
Only enable these for servers you trust. Clients have neither capability.
Changing a device’s role
Use a device’s actions menu to Change to Server or Change to Client. Changing to Server turns both Server capabilities on; changing to Client turns them off and moves the device to the Clients table.
Outbound IP
By default a device’s outbound traffic leaves from its subnet’s outbound IP. On a VPS with more than one public IPv4 address, you can override this per device with the WAN IP field in the device’s Add/Edit dialog — choose Subnet default to inherit the subnet’s setting (the address it resolves to is shown in parentheses), or a specific address to pin this device’s egress. On a single-IP VPS there is only one choice, so leave it on Subnet default.
Removing a Device
- Navigate to
Devices, select the device, and click “Remove”.
Published Ports
Publishing a port exposes a device’s port to the public Internet. StartTunnel can do this over IPv4 (a DNAT from your VPS’s public IPv4) and over IPv6 (a firewall pinhole on the device’s own global address) — one dialog handles both.
Warning
IPv4 publishing requires a dedicated public IPv4 address on your VPS. Shared IPv4 addresses (CGNAT, shared NAT, load-balanced IPs) cannot be used to expose services to the clearnet. IPv6 publishing instead needs a routed IPv6 prefix delegated to the subnet (see IPv6); each device then has its own globally-routable address, so a dedicated public IPv4 isn’t required for the IPv6 path.
Note
StartTunnel acts as a port-control gateway for connected devices, speaking PCP (preferred) and UPnP. A StartOS server using this tunnel opens the ports it needs automatically — over IPv4 and, on a current StartOS (0.4.0-beta.10+) with an IPv6 prefix, over IPv6 too — when you enable a public address, and removes them when the address is disabled or deleted. Each automatic PCP mapping carries a lease that the device renews while it still wants the port; if the device stops renewing (it goes offline, or you withdraw the exposure), the tunnel drops the published port on its own rather than letting it linger. For security, an automatically published port or pinhole always targets the requesting device’s own address; a device can only publish ports to itself. The steps below are for adding or managing published ports manually.
IPv4 published ports vs. IPv6 pinholes
- An IPv4 published port is a DNAT: clients connect to your VPS’s public IPv4 on the external port, and the tunnel rewrites the destination to the device’s tunnel IP and internal port.
- An IPv6 published port is a pinhole: the device already has a globally-routable address (its GUA — see IPv6), so there is no NAT. The tunnel simply permits inbound to
[GUA]:port. If you pick an external port different from the internal port (e.g. an80 → 443redirect) it becomes a port-only translation on that same address.
Because each device has its own IPv6 address, two different devices can both publish on the same external port over IPv6 (whereas over IPv4 they share one public address, so external ports must be unique).
Note
Port 80 on each public IPv4 is claimed by default by an HTTP→HTTPS redirect, so you rarely need to publish it. A redirect and a published port 80 are mutually exclusive and never both enabled: publishing port 80 is rejected while the redirect is on (turn it off first, under
Settings). See HTTP Redirects.
Manual and automatic ports
The Published Ports page shows two tables: Manual ports you added by hand, and Automatic ports opened by connected devices via PCP/UPnP. A row’s External IP is your VPS’s public IPv4 (a v4 published port) or the device’s IPv6 GUA (a v6 pinhole). You can enable, disable, or remove either; automatic ports have no editable label (they’re owned by the device that created them) and may be re-created if you remove one while the device still wants it. Manual ports are persistent — they stay until you delete them. Automatic ports are lease-based: one that stops being renewed (its device went offline or no longer wants the port) expires and is removed on its own.
Deleting a device or demoting it to a client clears all of its published ports (manual and automatic, IPv4 and IPv6). Turning off auto-publish for a device clears its automatic ports but leaves any you added by hand.
Add a port manually
-
In StartTunnel, navigate to
Published Portsand click “Add”. -
Enter the External Port, select the Server (the device to publish to), and enter the Internal Port. In almost all cases they are the same.
-
Choose the IP Version —
IPv4,IPv6, orIPv4 + IPv6.IPv6andIPv4 + IPv6require the selected server to have an IPv6 address, which means its subnet must carry a routed IPv6 prefix (see IPv6); the dialog tells you when the chosen server has none. -
To publish a range of ports, set “Number of Ports” to the size of the range. It counts up from both the external and internal ports — e.g. external
49152, internal49152, count100publishes49152–49251on each side. Leave it at1for a single port. -
Click “Save”.
Note
There is no option to also publish port
80 → 443— HTTP→HTTPS on port 80 is handled by the HTTP redirect that runs by default on every public IPv4.
SNI hostnames (IPv4 only)
When IP Version includes IPv4 (IPv4 or IPv4 + IPv6), an optional Hostname routes by TLS SNI so several hostnames can share one external port. SNI demultiplexing is IPv4-only — in IPv4 + IPv6 mode it applies to the IPv4 side only, and the IPv6 side is a plain pinhole (each device already has its own address, so no demux is needed) — and it cannot be combined with a port range.
HTTP Redirects
StartTunnel runs an HTTP→HTTPS redirect on port 80 of every public IPv4 address your VPS holds. A plain http:// request to one of these addresses is answered with a redirect to the same host over https://, so visitors who leave off the scheme still land on your TLS service instead of getting a connection error.
These redirects are on by default — on a fresh install and after an update, every public IPv4 gets one automatically. You can turn any of them off, and your choice persists.
Where they run
A redirect binds a lightweight listener directly on <public-IPv4>:80 on the tunnel host. Only public IPv4 addresses are eligible (loopback and private/RFC1918 ranges are skipped) — the same set the web UI lists. IPv6 is handled separately: the 80 → 443 upgrade for a device’s IPv6 address is a pinhole port translation, not one of these listeners.
Mutually exclusive with a published port 80
A redirect and a published port cannot both own port 80 on the same IP — they are never both enabled. The two directions are enforced explicitly rather than by one silently overriding the other:
- Publishing port 80 while the redirect is on is rejected. To publish port 80 to a device, first turn the redirect off for that address.
- Enabling the redirect while port 80 is published is rejected. Delete the published port 80 first.
Port 80 is also never opened automatically: StartTunnel refuses PCP/UPnP requests to auto-publish it, since the redirect is the intended behavior there.
Managing them in the UI
The HTTP Redirect (80 → 443) section on the Settings page lists every public IPv4 with a toggle:
- On — the port-80 HTTP→HTTPS redirect is running on that address.
- Off — you have turned it off; port 80 there simply refuses plain HTTP (and is free to publish).
- Disabled toggle — a published port currently occupies port 80 on that address. Remove the published port to re-enable the redirect.
(Most VPSes have a single public IPv4, so this is usually just one toggle.)
Managing them from the CLI
# Show the redirect status of every public IPv4
start-tunnel http-redirect list
# Turn the redirect off for one address (omit --enabled)
start-tunnel http-redirect set-enabled 203.0.113.10
# Turn it back on
start-tunnel http-redirect set-enabled 203.0.113.10 --enabled
See the CLI reference for details.
IPv6
StartTunnel can give the devices on a subnet a real, globally-routable IPv6 address drawn from a prefix your VPS delegates. IPv6 is configured per subnet — each subnet can point at its own prefix (or none). This is optional and off by default; IPv4 published ports work without it.
What your VPS provides
IPv6 addressing depends on the block your provider routes to your VPS. Most budget providers give a single /64 (Hetzner, Vultr, BuyVM); some give less (DigitalOcean routes a /124 — 16 addresses); a few give a /56 or larger on request (Linode) or on dedicated servers. Check your provider’s dashboard or docs for the exact prefix. A /64 per subnet is the natural fit.
Requirements
Delegating a prefix only works if the server can actually route it:
- The server must have working IPv6 egress — an IPv6 default route (
::/0). A device given an IPv6 address routes all its IPv6 through the tunnel (AllowedIPs = ::/0); without upstream IPv6 on the server that traffic simply blackholes.subnet … set-ipv6hard-errors if the server has no IPv6 default route, leaving the configuration unchanged. Confirm withip -6 route show defaultand configure IPv6 on the VPS first. StartTunnel does not configure the server’s own WAN IPv6 — that’s the host/provider’s job (RA,netplan, orcloud-init). - The prefix must be delivered to the server — either on-link on a WAN interface (the server holds a global address inside the covering /64, the usual single-/64 case) or routed to the server by your provider. If the prefix is neither on-link nor something this host can confirm, the command still succeeds but logs a warning: make sure your provider actually routes the block to this host, or the subnet’s devices will have no working IPv6.
Configuring a subnet’s prefix
Assign the routed prefix your provider gave you to a subnet:
start-tunnel subnet 10.59.0.0/24 set-ipv6 --prefix 2001:db8:abcd::/64
Or set the IPv6 Prefix field in the subnet’s Add/Edit dialog in the web UI.
To turn IPv6 back off for a subnet, run the command with no --prefix argument
(or clear the field in the UI).
Once set, StartTunnel re-renders the WireGuard configs of that subnet’s devices to include an IPv6 address. Reconnect (or re-download the config) on each device to pick it up.
Note
Devices can make outbound IPv6 connections and receive their replies. To accept unsolicited inbound connections to a device’s IPv6 address (hosting a service over IPv6), publish a port for it — see Published Ports. Over IPv6 a published port is a firewall pinhole on the device’s global address (no NAT); a connected StartOS server also opens these automatically via PCP.
How addresses are assigned
Every host on a subnet — the tunnel itself and each device — gets one /128
out of the subnet’s prefix, with its tunnel IPv4 embedded in the low bits
(prefix-network | tunnel-IPv4). So a device’s IPv6 is stable and predictable:
the same address every time, derivable from its tunnel IPv4 alone. The tunnel
uses the subnet’s .1 host as its own address on the WireGuard interface and as
the next hop for the subnet’s IPv6 traffic.
When the prefix is delivered on-link (the common single-/64 case), the
tunnel answers Neighbor Discovery for each device’s address on your VPS’s
network, so traffic to it — including the replies to connections it opens — is
delivered over the tunnel. A routed prefix reaches the host without that
step. A /64 is the natural size (its 64 host bits hold the whole tunnel IPv4);
a smaller block works too but keeps only its low host bits of the IPv4. Every
host must get a distinct address, so if a block is too small — or two devices’
low IP bits would collide — StartTunnel rejects adding the device or setting the
prefix rather than hand out a duplicate. Keep the number of devices (and their
low IP bits) within what the block can hold.
Routing
For devices with an IPv6 assignment, all IPv6 traffic is carried through the
tunnel (AllowedIPs = ::/0). This is required: replies sent from a device’s
global address have to return through the tunnel, since that address belongs to
your VPS, not the device’s local network. IPv4 remains split-tunnel (only the
subnet is routed).
DNS
Devices keep using the tunnel’s IPv4 DNS resolver, which serves AAAA records
too. A device that is allowed to inject DNS records can publish an AAAA record
for its global address, so other devices on the tunnel can reach it by name. See
DNS Records.
DNS Records
StartTunnel runs a private DNS resolver for your tunnel. It lets you reach the services you host on tunnel devices by a memorable hostname — e.g. home.example.com or git.lan — instead of memorizing each device’s tunnel IP. These names are private to your tunnel: they resolve for connected devices only, and are never published to the public Internet.
Why use it
- Reach services by name. Point
git.example.comat your server once; every connected device can use it, and it keeps working even if you rebuild the service. - One source of truth. Everyone on the tunnel resolves the same names to the same device — no per-device
hostsfiles to maintain. - Private. The records exist only inside your tunnel; the outside world can’t see or resolve them.
How it works
Devices connected to the tunnel use StartTunnel as their DNS resolver. When a device looks up one of your private hostnames, StartTunnel answers from the records on the DNS Records page; any other lookup falls through to the subnet’s configured upstream resolver (see Subnets › DNS). A record is one of:
- A / AAAA — a hostname → a device’s tunnel IPv4 / IPv6 address.
- CNAME — a hostname → another hostname (an alias).
- TXT — a hostname → arbitrary text (e.g. a verification string).
Records come from two places: you add them by hand, or a trusted device injects them automatically over RFC 2136.
Note
A StartOS server using this tunnel injects the records for its private domains automatically, as long as its device is a Server with DNS injection enabled (which it is by default — see below). You normally won’t need to add records by hand.
Allowing a device to inject records
DNS injection is a Server capability: a device added as a Server has it on by default (along with auto-publish), and Clients don’t have it at all. Leave it enabled only for devices you control and trust — turn it off from the Servers table for any server that shouldn’t manage your DNS.
Warning
A device allowed to inject DNS records can create, overwrite, or delete any record StartTunnel serves. Keep this enabled only for trusted devices, such as your own StartOS server.
-
In StartTunnel, navigate to
Devices. DNS injection is a Server capability — if the device is a Client, change it to a Server first (see Devices). A newly-added Server (or a Client promoted to Server) already has DNS injection on. -
In the Servers table, the DNS injection toggle controls the capability — leave it on to allow injection, or turn it off to withhold it.
An enabled device may add, update, and remove records via RFC 2136 DNS UPDATE. StartTunnel authorizes each request by the device’s tunnel IP, so only that device’s allowance is in effect.
Viewing and managing records
-
In StartTunnel, navigate to
DNS Records. -
Records are shown in two tables: Manual (records you added by hand) and Automatic (records injected by a device, each showing the injecting device’s IP as its source).
-
To add a record manually, click “Add” on the Manual table, enter the name, type (A, AAAA, CNAME, or TXT), value, and TTL, and click “Save”.
-
To remove a record, select it and click “Remove”.
Updating
Keep StartTunnel up to date using the web UI, CLI, or install script.
Web UI
Navigate to Settings > Version > Check for Updates.
CLI
Check for updates:
start-tunnel update check
Install the latest version:
start-tunnel update apply
Install script
Re-run the install command:
curl -sSL https://start9.com/start-tunnel/install.sh | sh
The installer detects the existing installation, prompts for confirmation, and restarts the service.
Uninstalling
StartTunnel is designed to run on a dedicated VPS. To remove it, simply destroy the VPS through your hosting provider. All WireGuard keys and configuration are stored on the VPS and will be removed with it.
start-tunnel CLI Reference
The start-tunnel CLI manages a StartTunnel server — a WireGuard-based gateway that provides clearnet access to devices behind NAT. Run it directly on the StartTunnel server, or use start-cli tunnel to manage it remotely from a StartOS server.
Global Options
-c, --config <PATH>— Configuration file path-H, --host <URL>— StartOS server URL-r, --registry <URL>— Registry URL--registry-hostname <HOST>— Registry server hostname-t, --tunnel <URL>— Tunnel server address-p, --proxy <URL>— HTTP/SOCKS proxy--cookie-path <PATH>— Cookie file path--developer-key-path <PATH>— Developer signing key path
Authentication
Manage passwords, sessions, and authorized SSH keys for remote access.
start-tunnel auth login
Log in and create an authenticated session.
start-tunnel auth logout <SESSION>
End an authentication session.
start-tunnel auth set-password
Set the web UI password.
start-tunnel auth reset-password
Reset the web UI password.
start-tunnel auth get-pubkey
Retrieve the server’s public key.
start-tunnel auth session list
List active sessions.
--format— Output format
start-tunnel auth session kill [IDS...]
Terminate sessions.
start-tunnel auth key add <NAME> <KEY>
Add an authorized SSH key.
start-tunnel auth key list
List authorized SSH keys.
--format— Output format
start-tunnel auth key remove <KEY>
Remove an authorized SSH key.
Subnets
Create and remove WireGuard subnets. Each subnet is an isolated network. The <SUBNET> argument is passed to the parent subnet command.
start-tunnel subnet <SUBNET> add <NAME>
Create a new subnet with the given name.
start-tunnel subnet <SUBNET> remove
Remove a subnet and all its devices.
start-tunnel subnet <SUBNET> set-ipv6
Set (or clear) the routed IPv6 prefix delegated to the subnet. Each host on the
subnet is assigned a globally-routable /128 out of it. See IPv6.
--prefix <PREFIX>— The routed prefix (e.g.2001:db8:abcd::/64). Omit to disable IPv6 on the subnet.
Devices
Manage devices within a subnet. Each device gets a unique WireGuard configuration.
start-tunnel device add <SUBNET> <NAME> [IP]
Add a device to a subnet. Optionally assign a specific IP address.
--kind <client|server>— Device kind (defaultclient). Aserverenables gateway autoconfiguration (DNS injection + auto-publish) by default.
start-tunnel device list <SUBNET>
List all devices in a subnet.
--format— Output format
start-tunnel device remove <SUBNET> <IP>
Remove a device from a subnet.
start-tunnel device show-config <SUBNET> <IP> [WAN_ADDR]
Display the WireGuard configuration file for a device. Optionally override the WAN address in the generated config.
Port Forwarding
Expose a device’s port on the server’s public IP.
start-tunnel port-forward add <EXTERNAL_PORT> <TARGET>
Add a port forwarding rule mapping a public external port to a private target. The external IP is fixed server-side to the target device’s WAN.
--label <LABEL>— Human-readable label--sni <SNI>— Hostname to SNI-demux on a shared external port (TLS services only); repeatable. Omit for a plain port forward.--count <COUNT>— Number of contiguous ports to forward as a range (a PCP PORT_SET range), counting up from both the external port and the target port. Defaults to 1. Not valid together with--sni.
start-tunnel port-forward remove <SOURCE>
Remove a port forwarding rule.
start-tunnel port-forward set-enabled <SOURCE>
Enable or disable a port forwarding rule.
--enabled— Enable the rule
start-tunnel port-forward update-label <SOURCE> [LABEL]
Change or clear the label on a port forwarding rule.
HTTP Redirects
StartTunnel runs an HTTP→HTTPS redirect on port 80 of every public IPv4 it holds, so a plain http:// request to an exposed service bounces to https://. These are on by default; each address can be turned off individually. A redirect and a port-80 forward are mutually exclusive and never both enabled — forwarding port 80 is rejected while the redirect is on, and enabling the redirect is rejected while port 80 is forwarded.
start-tunnel http-redirect list
Show the port-80 redirect status of every public IPv4: whether it is enabled, and whether a port forward already occupies port 80 (which blocks enabling the redirect).
--format— Output format
start-tunnel http-redirect set-enabled <IP>
Turn the port-80 HTTP→HTTPS redirect on or off for a public IPv4. Enabling is rejected if a port-80 forward exists on that IP — delete the forward first.
--enabled— Enable the redirect; omit the flag to turn it off
IPv6 Pinholes
Expose a device’s port over IPv6 by opening a firewall pinhole on the device’s own global address (GUA — see IPv6). Unlike an IPv4 forward there is no NAT; a differing internal port turns it into a port-only translation on the same GUA (e.g. an 80 → 443 redirect). The GUA must be an address the tunnel delegates to a client (its subnet needs an IPv6 prefix).
start-tunnel pinhole add <GUA> <EXTERNAL_PORT>
Open a pinhole for [GUA]:EXTERNAL_PORT.
--internal-port <PORT>— Destination port on the GUA. Omit for a pure pinhole (internal == external); set a different value for a port remap (e.g.80 → 443).--label <LABEL>— Human-readable label--count <COUNT>— Number of contiguous ports to open as a range, counting up from both the external and internal ports. Defaults to 1.
start-tunnel pinhole remove <GUA> <EXTERNAL_PORT>
Remove a pinhole.
start-tunnel pinhole set-enabled <GUA> <EXTERNAL_PORT>
Enable or disable a pinhole.
--enabled— Enable the pinhole
start-tunnel pinhole update-label <GUA> <EXTERNAL_PORT> [LABEL]
Change or clear the label on a pinhole.
Updates
start-tunnel update check
Check the registry for available updates.
--format— Output format
start-tunnel update apply
Apply an available update.
--format— Output format
Server Management
start-tunnel restart
Reboot the StartTunnel server.
Web Interface
Manage the admin web UI.
start-tunnel web init
Initialize the web UI (interactive setup).
start-tunnel web uninit
Remove web UI configuration.
start-tunnel web enable
Enable the web UI.
start-tunnel web disable
Disable the web UI.
start-tunnel web set-listen <LISTEN>
Set the IP and port the web UI listens on.
start-tunnel web get-listen
Display the current listen address.
--format— Output format
start-tunnel web generate-certificate [SUBJECT...]
Generate a self-signed TLS certificate for the web UI. Pass Subject Alternative Names for the certificate.
start-tunnel web import-certificate
Import a TLS certificate from stdin.
start-tunnel web get-certificate
Display the current TLS certificate.
--format— Output format
start-tunnel web get-available-ips
List available IP addresses for binding.
--format— Output format
Database
Low-level access to the StartTunnel database.
start-tunnel db dump [-p <POINTER>] [PATH]
Dump database contents, optionally filtered by JSON pointer.
-p, --pointer <PTR>— JSON pointer to specific value--format— Output format
start-tunnel db apply <EXPR> [PATH]
Apply a patch expression to the database.
StartTunnel
StartTunnel is a virtual private router (VPR) — a minimal, self-hosted router that runs on a VPS instead of sitting in your house. Just like a home router, it creates private networks, assigns IP addresses to devices, and forwards ports to the public Internet. The difference is that it exists in the cloud, so it works regardless of your home network’s limitations.
- Clearnet hosting like Cloudflare Tunnels, but you control the router
- Private access like Tailscale, but fully self-hosted
- Dead simple — one command to install, manage everything from the CLI or web UI
- Open source — audit it, fork it, own it
Note
For setup instructions, see Installing.
Features
- Create Subnets — Each subnet is a private LAN, just like the one your home router creates
- Add Devices — Servers, phones, laptops join the LAN and get an IP address and WireGuard config
- Publish Ports — Expose specific ports on specific devices to the public Internet, the way a home router forwards ports to devices on your LAN. StartTunnel also acts as a port-control gateway (PCP and UPnP), so a StartOS device can open its own ports automatically
How StartTunnel Compares
StartTunnel occupies a unique position between Cloudflare Tunnel and Tailscale. All three solve the problem of connecting devices across the Internet, but they make fundamentally different trade-offs around trust, control, and convenience.
Architecture
StartTunnel is a virtual private router that runs on a VPS you control. Like a home router, it creates private networks, assigns IPs, and forwards ports — but using WireGuard tunnels instead of physical cables. Publishing a port uses kernel-level iptables NAT (Layer 3/4) to route public traffic to devices on the VPN. There is no central service, no coordination server, and no third party in the data path.
Cloudflare Tunnel runs a daemon (cloudflared) on your machine that makes outbound connections to Cloudflare’s global edge network. Public traffic hits Cloudflare’s CDN first, where Cloudflare terminates TLS, inspects the request at Layer 7, and proxies it to your origin through the tunnel.
Tailscale is a mesh VPN built on WireGuard. A proprietary coordination server (hosted by Tailscale Inc.) distributes keys and facilitates peer discovery, while actual traffic flows directly between devices. For public exposure, Tailscale Funnel routes traffic through Tailscale’s ingress servers, which terminate TLS.
Privacy and Trust
This is the most important difference. It comes down to: who can see your traffic?
StartTunnel: Nobody but you. Published ports operate at Layer 3/4 (iptables DNAT), meaning the VPS rewrites IP headers and forwards packets without inspecting payloads. If a service uses HTTPS, TLS terminates at the service itself — the VPS never sees plaintext. For VPN traffic between devices, WireGuard provides end-to-end encryption. Since you own the VPS, there is no third party with access to your traffic or metadata.
Cloudflare Tunnel: Cloudflare terminates TLS at their edge and re-encrypts to your origin. This means Cloudflare can — and does — see plaintext traffic. They offer “TLS inspection” as a feature and can scan request bodies, filter content, and inject responses. Using Cloudflare Tunnel requires trusting a publicly traded company not to misuse its position as a man-in-the-middle on all your traffic.
Tailscale: For device-to-device traffic, encryption is end-to-end — even Tailscale’s DERP relay servers forward encrypted packets they cannot read. However, the coordination server (run by Tailscale Inc.) sees metadata: which devices are connecting, their IPs, OS versions, and connection state. Tailscale explicitly states it is “not an anonymity service.” For public exposure via Funnel, Tailscale’s ingress servers terminate TLS, similar to Cloudflare.
Self-Hosting and Sovereignty
StartTunnel: Fully self-hosted. You rent a VPS, run the installer, and own the entire stack. No phone-home, no telemetry, no accounts, no dependency on any company’s infrastructure. If Start9 disappeared tomorrow, your tunnel would keep working.
Cloudflare Tunnel: The cloudflared client runs on your machine, but all traffic must route through Cloudflare’s proprietary global network. You cannot self-host the edge. If Cloudflare goes down — as happened in a 5.5-hour outage in November 2025 — your services go down with it.
Tailscale: The client is mostly open source, but the coordination server is proprietary. Headscale is a community-built open source alternative, but it reimplements a narrower scope (single tailnet) and is not maintained by Tailscale. By default, you depend on Tailscale Inc. for key distribution, peer discovery, and DERP relays.
Vendor Lock-In and Terms of Service
StartTunnel: MIT licensed. No terms of service. No content restrictions. No account that can be terminated. Use it however you want.
Cloudflare Tunnel: Cloudflare’s ToS prohibit streaming video or large file serving unless you use Cloudflare R2/Stream. Cloudflare reserves the right to terminate accounts “at any time, with or without notice for any reason or no reason at all.” Your services are one policy change away from going dark.
Tailscale: More permissive terms than Cloudflare, but you still depend on a company’s continued goodwill and operation. The free tier (3 users, 100 devices) has limits that paid tiers expand.
Comparison Table
| StartTunnel | Cloudflare Tunnel | Tailscale | |
|---|---|---|---|
| Architecture | WireGuard VPN to your VPS | Outbound tunnel to Cloudflare edge | WireGuard mesh with coordination server |
| Who sees your traffic? | Only you | Cloudflare (TLS terminated at edge) | Nobody for P2P; Tailscale for Funnel |
| TLS termination | At the origin service (L3/L4 passthrough) | At Cloudflare’s edge (L7 proxy) | At origin for P2P; at Tailscale for Funnel |
| Self-hostable? | Fully | Client only; edge is proprietary | Client + DERP relays; coordination server via Headscale |
| Open source | Fully (MIT) | Client only (Apache-2.0) | Client mostly; coordination server proprietary |
| Requires account? | No | Yes (Cloudflare account) | Yes (via third-party identity provider) |
| DNS management | None (bring your own) | Optional (Cloudflare DNS or external) | MagicDNS for private; *.ts.net for Funnel |
| Works behind CGNAT? | Yes (clients initiate outbound UDP) | Yes (client initiates outbound QUIC/HTTP2) | Yes (hole-punching + DERP fallback) |
| Subnet isolation | Yes (isolated VLANs) | N/A | ACLs between devices |
| Protocol | TCP + UDP forwarding | HTTP/S, TCP, UDP (via QUIC) | Any (WireGuard tunnel) |
| DDoS protection | None (use VPS provider’s) | Built-in (Cloudflare network) | None |
| Global edge/CDN | No (single VPS location) | Yes (Cloudflare’s global network) | No (direct P2P or DERP relay) |
| Content restrictions | None | No video streaming without R2/Stream | None |
| Cost | Free + VPS (~$5-10/mo) | Free (50 users); $7/user/mo above | Free (3 users); $5-18/user/mo |
What You Give Up
StartTunnel prioritizes sovereignty over convenience. That means:
- No DDoS protection — Your VPS IP is exposed on published ports. Use your VPS provider’s DDoS protection, or place a CDN in front if needed.
- No global edge network — Traffic routes through one VPS, not a global CDN. Latency depends on VPS location.
- No built-in DNS — You manage your own DNS records.
- No identity provider integration — Authentication is key-based and password-based, not SSO.
- You manage the VPS — Minimal maintenance (Debian + one binary), but it’s yours to keep updated.
For many self-hosters, these trade-offs are not just acceptable — they’re the point.
Security
StartTunnel is built on WireGuard, a modern VPN protocol with a minimal, auditable codebase (~4,000 lines of code in-kernel).
- Encryption: ChaCha20-Poly1305 for symmetric encryption, Curve25519 for key exchange, BLAKE2s for hashing
- Pre-shared keys: Each peer connection uses an additional pre-shared key (PSK) for a layer of post-quantum resistance
- Key isolation: Private keys are generated on-device and never leave the device. Only public keys are exchanged.
- TLS passthrough: Traffic to a published port is not decrypted by the VPS. If your service uses HTTPS, TLS terminates at the service, not the tunnel.
Requirements
- Debian 13
- x86_64, aarch64, or riscv64
- Root access
- Public IP (required for publishing ports to the clearnet; not required for private VPN use)
Source Code
The StartTunnel source code and release binaries live in the StartOS monorepo. The installer script is hosted at start9.com/start-tunnel/install.sh.
To report bugs or request features, open an issue.
FAQ
Answers to common questions about StartTunnel’s security model, compatibility, VPS requirements, and what happens if Start9 goes away.
Can anyone else see my traffic?
No. Published ports operate at Layer 3/4 (iptables DNAT), meaning the VPS rewrites IP headers and forwards packets without inspecting payloads. If your service uses HTTPS, TLS terminates at the service itself — the VPS never sees plaintext. For VPN traffic between devices, WireGuard provides end-to-end encryption. Since you own the VPS, there is no third party in the data path.
Do I need a WireGuard client on my devices?
Only for private access — phones, laptops, and other devices connecting to your server over the VPN. For clearnet hosting (exposing ports to the public Internet), no WireGuard client is needed on the devices accessing your services.
Can I run other services on the same VPS?
No. StartTunnel manages its own firewall rules and disables UFW. It is designed to be the sole application on the VPS.
Does StartTunnel work behind CGNAT?
Yes. WireGuard clients initiate outbound UDP connections, so CGNAT is not a problem for connecting devices to the VPN. Publishing ports still works because public traffic arrives at the VPS’s public IP.
What if I forget my password?
SSH into your VPS and run:
start-tunnel auth reset-password
What if Start9 goes away?
StartTunnel keeps working. It is fully self-hosted with no dependency on Start9 infrastructure. There is no coordination server, no telemetry, and no phone-home. The binary runs entirely on your VPS.
How do I remove StartTunnel?
StartTunnel is designed to run on a dedicated VPS. To remove it, simply destroy the VPS through your hosting provider. All WireGuard keys and configuration are stored on the VPS and will be removed with it.
What VPS providers work with StartTunnel?
Any provider that offers Debian 13 with root access and a dedicated public IPv4 address. Common choices include Hetzner, DigitalOcean, Linode, Vultr, and OVH. Budget VPS providers (~$5/mo) work fine — StartTunnel has minimal resource requirements.
Warning
StartTunnel’s published ports (clearnet hosting) require a dedicated public IPv4 address. Shared IPv4 addresses (CGNAT, shared NAT, load-balanced IPs) will not work. Some budget providers and IPv6-only tiers do not include a dedicated IPv4 — confirm with your provider before purchasing.
Some providers (AWS, Google Cloud, Azure, Oracle Cloud, IONOS) have cloud-panel firewalls that block WireGuard (UDP 51820) by default. See Installing — Cloud firewalls for setup instructions.
Does StartTunnel work on an IPv6-only VPS?
Partially. The WireGuard tunnel itself works over IPv6, so devices with IPv6 connectivity can join your private VPN and reach each other through the VPS. However, published ports for clearnet hosting are IPv4-only and cannot be used on an IPv6-only VPS. Additionally, any device joining the VPN must have IPv6 connectivity on its current network — most modern carriers and home ISPs are dual-stack, but some are still IPv4-only. For clearnet hosting, choose a VPS with a dedicated public IPv4 address.
Does StartTunnel provide DDoS protection?
No. Your VPS IP is exposed on published ports. Use your VPS provider’s built-in DDoS protection, or place a CDN in front if needed. See the Architecture page for a full comparison of trade-offs.