AmneziaWG 2.0 / 3.0 VPN server in one command
Turn a clean Ubuntu or Debian VPS into a self-hosted, DPI-resistant VPN. No Docker, no web panel, no Linux experience required.
On servers with a recent kernel the module comes from the third line, while the configuration profile stays 2.0: it is the same on the server and on the clients, so configs handed out earlier keep working untouched. Check what you have
$ wget -O install_amneziawg_en.sh https://github.com/bivlked/amneziawg-installer/releases/latest/download/install_amneziawg_en.sh $ chmod +x install_amneziawg_en.sh $ sudo bash ./install_amneziawg_en.sh
Pin the latest version from the releases page. Three commands, two reboots, about twenty minutes to a working VPN.
What it does
AmneziaWG is WireGuard with traffic obfuscation, so the handshake no longer looks like a standard VPN to deep packet inspection. This script sets up the whole server for you.
You give the command a fresh VPS over SSH. It installs the AmneziaWG kernel module, hardens the firewall, enables forwarding, tunes the system for a single-purpose VPN box, and creates your first client. At the end you get a QR code and a vpn link for one-tap import into the Amnezia client. Adding another device later is a single command.
Features
Everything a small VPN server needs, set up with sane defaults and no manual config files.
DPI bypass
Full AmneziaWG 2.0 obfuscation: junk packets, header masking (H1 to H4), padding (S1 to S4), and I1 to I5 concealment packets.
Hardened by default
UFW firewall with deny-all and SSH rate limiting, Fail2Ban, strict file permissions, and sysctl hardening.
Client management
Add, remove, list, and regenerate clients. QR codes, vpn links for one-tap import, and time-limited guest configs with an expiry date.
IPv6
With the default profile the device IPv6 goes into the tunnel and stops there, so it no longer reaches the internet with its own address. While such a VPN is on, IPv6-only resources are unreachable, and so is the local network over IPv6; over IPv4 it remains reachable. For working IPv6 inside the tunnel use --allow-ipv6-tunnel with native IPv6 on the server.
ARM and Raspberry Pi
Prebuilt kernel modules for Raspberry Pi 3, 4 and 5, Hetzner CAX, Oracle Ampere A1, and AWS Graviton.
Survives reboots
A resume-after-reboot state machine. After a kernel upgrade DKMS builds the module for the new kernel on its own; on the ARM prebuilt path, running the installer again installs it.
Scripts and bots can drive it
Most management commands take --json and answer with a single object even when something fails (list and stats return an array). A third-party Telegram bot already runs on it.
Cellular carriers
The --mobile flag turns on a cellular profile and, unless you pass a port yourself, picks 443/udp, because carriers often drop traffic on unusual UDP ports.
Quick start
From a clean VPS to a working VPN in three steps.
Rent a clean Ubuntu or Debian VPS and connect over SSH as root.
Run the command above. The script reboots when it needs to. After a reboot, run it again and it resumes from where it stopped.
Scan the QR code or open the vpn link in the Amnezia client. You are connected.
For automation, the same script takes --yes --route-all and every other parameter as a flag. The full guide covers VPS choice, ARM notes, troubleshooting, and uninstall.
Supported systems
Tested on clean, minimal server installs. Kernel upgrades are handled automatically through DKMS, and on ARM hosts running a prebuilt module the repair-module command brings it back.
For a new server: Ubuntu 24.04 LTS or Debian 13 are the default choice, and Ubuntu 26.04 works too.
Ubuntu 25.10 and Debian 12 install and work, but they are not a good pick for a new server. Ubuntu 25.10 reached end of life on 1 July 2026 and gets no security updates at all: it is an interim release and will not be extended. Debian 12 left regular support on 11 July 2026; its security updates now come through Debian LTS until 30 June 2028.
Built for cheap budgets: 1 vCPU, 512 MB of RAM minimum, 5 GB of disk. Both amd64 and arm64.
Why a plain bash script
It runs as a kernel module, with nothing extra sitting between you and the tunnel.
A web panel is worth it only if you add and rotate clients constantly. For most people a VPN server is set once and left alone, so the bash approach keeps the footprint tiny and runs comfortably on the cheapest VPS. The kernel-native module is faster than a userspace tunnel, and there is nothing extra to keep patched. If you do want a UI or a different trade-off, the comparison in the README is honest about when another tool fits better. For a side-by-side with the official Amnezia app, see how it differs.
FAQ
What is AmneziaWG?
Is it free?
Do I need Linux experience?
Which VPS should I pick?
--ssh-port=PORT. The installer does detect the port on its own, but an unattended --yes install skips the confirmation, so there is nobody left to double-check it.Does it bypass DPI and censorship?
Which AmneziaWG version does the installer set up, 2.0 or 3.0?
Does it run on ARM and Raspberry Pi?
How do I update to a new release?
--force flag. Server keys, clients, and obfuscation settings survive the reinstall. After a kernel update DKMS builds the module for the new kernel on its own. On the ARM prebuilt path, running the installer again installs the module for the current kernel.Can I drive it from a script or a bot?
--json and answer with a single JSON object even when the command failed, so the reply is always parseable. The exceptions: list and stats return an array, and show and diagnose do not take the flag. New fields show up over time; existing ones do not get renamed. For unattended runs there is --yes, and with AWG_STRICT_CONFIRM=1 a command like removing a client refuses to run when --yes is missing instead of quietly agreeing. A third-party Telegram bot, awgram, already runs on this interface.AmneziaWG won't connect, though plain WireGuard works?
[Interface] parameters on the server and the client. S1-S4 and H1-H4 must match: the receiver strips that padding and checks those headers, so any mismatch here means the packet is dropped and the handshake never completes. In 2.0, H1-H4 are ranges - the ranges must be the same on both sides. Jc/Jmin/Jmax and the 2.0 concealment packets I1-I5 do NOT have to match: they are separate decoy packets, the other side discards them, and a node without I1 simply never sends them. Case does matter for I1-I5: uppercase only. Check the versions too: older amneziawg-tools builds cannot speak 2.0. Full walkthrough in the detailed troubleshooting guide.