Installation
Install Tunploy on a Linux server with one command, or with Docker Compose.
Tunploy runs as a single Docker container and starts one more container for each WireGuard server you create.
Requirements
- A Linux server with a public IP, amd64 or arm64. Any distribution with Linux 5.6 or newer works; Ubuntu 20.04+ and Debian 11+ are fine.
- Root access over SSH.
- A UDP port open to the internet for each VPN server, starting at 51820.
Install
curl -fsSL https://raw.githubusercontent.com/kwa0x2/tunploy/main/install.sh | sudo shThe script installs Docker if it is missing, starts Tunploy, asks for your admin account and prints how to open the panel. You do not install WireGuard yourself: the tools ship inside Tunploy's image, and the kernel module is already part of Linux 5.6+.
Open http://YOUR_SERVER_IP:3000, sign in, and create your first VPN. Have a domain? Give the panel HTTPS next.
What the script does
ghcr.io/kwa0x2/tunploy:latest and starts it with its data in /var/lib/tunploy.tunploy command (see Server commands).There is no sign-up page
The admin account can only be created on the server, so nobody who stumbles on the panel can claim it.
Running the same command again upgrades Tunploy (see Updating). Your servers, peers and account stay in /var/lib/tunploy, and it does not ask for an account again. The port, bind address and trusted proxies you chose before are kept; the panel domain lives in the database, so it is kept too.
Install options
Pass options after sudo, because sudo drops the rest of your environment:
curl -fsSL https://raw.githubusercontent.com/kwa0x2/tunploy/main/install.sh \
| sudo TUNPLOY_PUBLIC_HOST=vpn.example.com sh| Variable | Default | Meaning |
|---|---|---|
TUNPLOY_PUBLIC_HOST | detected public IPv4 | Hostname or IP that VPN clients dial. |
TUNPLOY_HTTPS | true | false leaves TCP 80 and 443 alone, for a server whose web server needs them. The panel then can't serve its own domain. |
TUNPLOY_TRUSTED_PROXIES | none | Your reverse proxy's addresses. See behind your own reverse proxy. |
TUNPLOY_TIMEZONE | the server's time zone | Where days and months begin for data usage and monthly limits, for example Europe/Istanbul. |
TUNPLOY_UPDATE_CHECK | true | false stops the panel from checking GitHub for new releases on its own. |
TUNPLOY_BIND | 0.0.0.0 | Address the panel port listens on. 127.0.0.1 keeps it reachable only over an SSH tunnel. |
TUNPLOY_PORT | 3000 | Panel port. |
TUNPLOY_VERSION | latest | Image tag, for example 0.1.0 or edge. |
TUNPLOY_IMAGE | ghcr.io/kwa0x2/tunploy | Image to install, for forks and mirrors. |
TUNPLOY_ADMIN_NAME, TUNPLOY_ADMIN_EMAIL, TUNPLOY_ADMIN_PASSWORD | asked | Create the admin account without prompting, for automated installs. |
Open the ports
The panel listens on TCP 3000, plus TCP 80 and 443 for its HTTPS domain, and each VPN server on its own UDP port: the first on 51820, the next on 51821, and so on.
Docker publishes these ports itself, past host firewalls such as ufw, so there is nothing to open on the server. Your hosting provider's firewall is separate: in Hetzner, AWS, Oracle Cloud, GCP and most others, add inbound rules for TCP 3000, 80 and 443 and UDP 51820 (and each further UDP port you use) in the provider's console.
Manual install with Docker Compose
If you would rather not pipe a script into a shell, this starts the same container:
services:
tunploy:
image: ghcr.io/kwa0x2/tunploy:latest
container_name: tunploy
restart: unless-stopped
ports:
- "3000:3000"
- "80:80"
- "443:443"
environment:
TUNPLOY_PUBLIC_HOST: "YOUR_SERVER_IP"
TZ: "UTC" # your time zone; monthly data limits reset at its midnight
volumes:
- /var/run/docker.sock:/var/run/docker.sock
# Must be the same path on both sides.
- /var/lib/tunploy:/var/lib/tunploydocker compose up -d
docker exec -it tunploy tunploy admin createSee Configuration for the other environment variables.