All new Registrations are manually reviewed and approved, so a short delay after registration may occur before your account becomes active.
[Tutorial] One-command AmneziaWG VPN server install on Ubuntu / Debian / ARM
Short writeup of a script I maintain — useful for anyone on a $3-5/month VPS who wants a self-hosted VPN that survives DPI/obfuscation filtering (Russia ТСПУ, Iran, China, school/corp firewalls).
Disclosure: I'm the author of amneziawg-installer (MIT, GitHub). Posting here because the LET audience is exactly the target — cheap Ubuntu/Debian boxes, ARM, single-tenant servers.
What it is
AmneziaWG is a WireGuard fork that adds junk packets, randomized handshake fields and CPS concealment on top of the standard WG handshake. The handshake fingerprint that DPI uses to block WireGuard is no longer there.
The installer is a single Bash script:
wget https://raw.githubusercontent.com/bivlked/amneziawg-installer/v5.13.0/install_amneziawg_en.sh
sudo bash install_amneziawg_en.sh
Tested on
- Ubuntu 24.04 LTS, 25.10, 26.04 (PPA noble fallback for non-LTS)
- Debian 12 (bookworm), 13 (trixie)
- amd64 + arm64 (ARM prebuilts shipped since v5.9)
- 512 MB RAM VPS — works fine, single Bash, no Docker, no web panel
Client management
After install, manage_amneziawg.sh handles add/remove/list/regen/backup/restore/stats and supports --expires=7d for time-limited configs.
Why this might be useful on LET
- 1 command, no Docker overhead, no web panel attack surface
- Survives kernel upgrades via DKMS auto-repair (apt hook)
- --force guard against accidental re-runs that pull a new kernel
- ARM-first — works on $4 Hetzner CAX11 or Pi 4
GitHub: https://github.com/bivlked/amneziawg-installer
License: MIT
Releases: bilingual changelog (EN + RU), latest v5.13.0
Happy to answer questions about deployment, obfuscation tuning for specific carriers, or VPS provider quirks (Hetzner subnet blocks in RU, Oracle ARM, etc.).


Comments
I’ve tried it, and the speed is just average.
The network routing is quite poor, and the overall experience is not as good as V2RayN.
This one is the still easiest and cleanest one to run but sadly it's not maintained anymore but still works fine: https://github.com/spcfox/amnezia-wg-easy
i prefer using https://github.com/wg-easy/wg-easy
they added amnezia-wg support a few months ago
Different layers — V2RayN is a client app for proxy stacks (VLESS/REALITY/Trojan over TCP), this installs a kernel-space UDP VPN. Performance ceiling depends on the server and your carrier path.
Common reasons AmneziaWG can feel slow:
Happy to help diagnose if you share the VPS provider + your carrier — I keep notes on tested setups.
Both solid projects, Docker + web-panel approach. This installer is the opposite end: single Bash script, no Docker daemon, no web UI exposed on a public IP, smaller attack surface. Different fits — wg-easy for point-and-click admin, this one for minimum-footprint SSH-managed setup on a 512 MB box. I'll add a comparison note to the README so future visitors can pick the right tool faster. Thanks both for the pointers.
might as well just use the amnezia vpn app. input server ip and private key or pw, and it'll run the installation commands. better supported and is the recommended way to do it.
https://docs.amnezia.org/documentation/instructions/install-vpn-on-server
Is this effective when carriers throttle UDP while exempting QUIC?
The Amnezia client's SSH-deploy is a nice fit if you've got the GUI handy — works well for desktop-driven setups, and the upstream docs you linked are the canonical reference.
This script aims at a different slice:
wget+sudo, no GUI client needed. CI runners, bastion hosts, fully scripted deploys.apt upgradetaking the kernel module offline mid-session.Different tool for the headless / automation slice, not a replacement for the GUI flow.
Depends on the DPI sophistication:
ListenPort = 443on the AmneziaWG server. Often enough.Most consumer carriers fall in #1 or #2; corporate filters and РФ TSPU profiles more often sit at #3.
Heh, fair both ways. The README and FAQ push the clueless user toward
--yesplus sane defaults — UFW doeslimit(notdeny) on SSH out of the box, so a typo on the prompts doesn't lock anyone out. Open to bug reports if anyone hits something genuinely surprising.It's won't kernel panic? I'm using xanmod ATM. I tried install the dkms for ameneziawg boom kernel panic no snapshot available from provider
Disclaimer: I don't know anything about this project.
Well, in theory DKMS should make sure that the module is always 100% compatible with the kernel you are running. I'm not completely sure what happens if you install a custom 3rd party kernel. If the kernel being used goes out of sync with the sources supplied by your distributions there might be some trouble. I mean, the sensible thing in this case would be for DKMS to just refuse building the module but i've never had that constellation with my personal setups so it might not be that clever after all.
There's obviously also always the possibility of the code being broken. DKMS might as well work perfectly fine than but the result will still crash.
Edit: I don't see why you would need a snapshot. Just reboot and don't load the module (or try booting into single user mode vand remove the respective modprobe configuration - in general not a good idea to add this before testing)?
What about wgproxy? Any self installable script?
Yeah, personally i'd also prefer something that comes with an old-fashioned INSTALL.txt but then i don't need an obfuscated VPN (at least not yet) anyways.
That's a rough one — kernel panic with no snapshot is the worst combo. A few thoughts:
Likely cause. XanMod ships a lot of custom patches across the scheduler and networking layers. DKMS handles the compile-time half (kernel headers match, build succeeds), but it can't detect when an internal struct or symbol the module relies on has shifted in a patched tree. The build looks clean, modprobe finds the module, and the panic only shows up at load or first packet.
Recovery without a snapshot. At the GRUB menu pick a previous kernel entry (or stock kernel if you have one installed). Once you're back in userspace:
If XanMod is your only kernel, boot into rescue mode (at GRUB, edit the entry and append
singleto the kernel line), then run the same cleanup before rebooting normally.Useful for an upstream report. If you can grab
journalctl -k -b -1after the next boot (persistent journal must be enabled) or photograph the panic screen, file it atamnezia-vpn/amneziawg-linux-kernel-modulewith youruname -routput. I haven't seen a XanMod-specific issue open there yet, so your repro would carry weight.You're right on the theoretical layer — the compile-time match is what DKMS solves. The gap, as above, is internal struct/symbol divergence on heavily patched trees: build clean, runtime broken. Your blacklist-and-reboot trick is exactly the practical recovery path; it's the one I'd reach for first if the panic happens late in boot.
Safer baseline: stock
linux-image-generic(Debian/Ubuntu) is what the DKMS module gets tested against. For ARM the project ships prebuilt .deb packages, so DKMS is skipped entirely — a different escape hatch if XanMod stays in the mix.It seems like you're using a good amount of AI to diagnose and debug... which makes me doubt if you actually know the stack behind whatever you've done.
I see. Maybe it would make some sense to test if what it is being build against looks like stock Debian/Ubuntu/Devuan/... sources (ie something that doesn't stray far off the beaten path) and abort or at least warn if something else is detected. I figure there should be a good amount of opportunities around in the various package/DKMS scripts. I mean, in theory it's the user's problem to make sure their patch monster behaves but as is demonstrated above not every single ne of those will be all too familiar with kernel stuff.
what is the lowest specs for this?
Not only there. I guess it'll still take a bit of time to adjust my brain but i really need to get more vigilant when it comes to those god damned long dashes... Clear sign of people not interested in an actual conversation.
AI script, AI replies, what’s point going to a forum seriously?
Talk back to the AI, better.
Ai Ai captain.
@totally_not_banned
No need for txt, it can be a premade executable file.
Pretty low. 1 vCPU, 512 MB RAM, 5 GB disk on a minimal Ubuntu or Debian install works. Bump to 1 GB if you want headroom during DKMS compile (peaks around 400 MB). ARM works the same. I've run it on Hetzner CAX11 (2 GB) and Oracle Free Tier (24 GB). No bandwidth floor, protocol overhead barely shows up.
(@totally_not_banned alright, you talked me out of it. Putting Alt+0151 down. Was going for polish. Got the opposite...)
Oh cool thanks, I looked it up myself and was seeing a lot of people said 1gb so I was unsure if 512mb would be OK for basic use. I'll give it a try!
Wrote up the install doc that came up earlier: INSTALL_VPS.md. Covers wget+sudo, what prompts to expect, rollback, and the usual troubleshooting, separate from the README.
Also dropped a Similar tools section into the README so wg-easy, spcfox/amnezia-wg-easy, and the Amnezia desktop client are easier to compare against this installer.
I'm wondering if there's any effective QUIC obfuscation that uses an existing nginx setup as a reverse proxy. All the stuff I've seen requires port 443 udp all to itself.
@david yeah, sharing UDP 443 cleanly with nginx is the part that doesn't work. ssl_preread reads ClientHello, that's TCP-only. nginx 1.25+ added stream_quic but that's a QUIC server, not an SNI proxy.
What folks do is leave nginx on TCP 443 for HTTPS and bind Hysteria2 / TUIC / sing-box quic-inbound on UDP 443 standalone. Same port, different protocol, kernel doesn't care. Or grab a second IPv4 (around a buck a month on most hosts) and put the obfuscated stack there.
If TCP works for you, REALITY-over-TCP fits behind nginx via ssl_preread SNI routing. Not QUIC though.