A practical way to run AmneziaWG under your own control, with script-based deployment, local-first administration, and an optional web UI for routine user management.
In short: if you do not want to route your traffic through opaque third-party VPN infrastructure, a self-hosted AmneziaWG setup is a reasonable alternative. This approach keeps deployment simple: start with a scriptable VPN installation, then add a web panel only if day-to-day administration actually requires it.
The familiar wave of warnings is back: VPNs and other censorship circumvention tools are being presented as not merely undesirable, but inherently dangerous. The argument is predictable enough. Fraudulent services steal data, compromise accounts, siphon off money, and the end user is left absorbing the damage.
There is a valid point buried in that narrative. Random VPN services, especially free ones, opaque ones, or those promising “complete anonymity in one click,” are often a poor security choice. Once all of your traffic is routed through infrastructure operated by an unknown party, trust is no longer a theoretical concern. It becomes the central issue.
But that is usually where the argument shifts from reasonable caution to something else entirely. “Do not use untrustworthy services” quickly turns into “do not use circumvention tools at all.” At that point, it stops sounding like security advice and starts sounding like another attempt to present a restricted internet as the normal one.
Reality works the other way around. The more restrictions there are, the more demand there is for ways around them. And if the choice is between an arbitrary commercial VPN, a free app with a dubious business model, and your own server, the self-hosted option deserves serious attention.
That is what this article is about. Not why VPNs are supposedly scary, but how to run one under your own control: deploy a self-hosted AmneziaWG instance with an installation script and, if needed, add a web management layer for handling users more conveniently.
Root access by app? I would rather not
To Amnezia’s credit, the project already makes deployment relatively straightforward. Its official client can provision the server side automatically if you give it access to a VPS. For many people, that is probably a perfectly acceptable workflow.
I am not one of them.
When a desktop application effectively asks for root on a remote machine and expects me not to overthink it, my first reaction is not convenience but inspection. I want to know what is being installed, how it is being configured, and what exactly is changing on the host.
So I took the less convenient route. The overall approach is not particularly novel: a deployment script, a reproducible setup, and a server you can inspect without guesswork. From there, I adapted the implementation to my own requirements and updated it for compatibility with AmneziaWG 2.0.
That also meant narrowing the list of supported operating systems. Some distributions had to be dropped for now, not because they are unsuitable in principle, but because up-to-date AmneziaWG 2.0 packages are not currently available for them.
That trade-off was acceptable. What mattered more was preserving control. No black-box automation, no “something configured itself somehow,” and no need to later reconstruct what a helper application actually did to the server.
First it was for myself, then it stopped being small
For a while, that was enough.
The server was up, users could be added, client configurations were generated, and everything worked. A perfectly reasonable level of self-hosted comfort for personal use, a few friends, and the occasional message from someone asking whether I could “set one up for them too.”
Then the setup did what small personal infrastructure usually does: it grew.
Once the number of users increases, so does the background maintenance. Add another device. Reissue a config. Revoke access. Check who has what. None of these tasks is especially difficult, but together they introduce a steady stream of routine work. What starts as a clean technical setup gradually turns into low-level administrative friction.
At that point, the console remains powerful, but it stops being the most efficient interface for repeated everyday tasks. That is when a web panel starts to make sense: not because the system cannot function without one, but because routine operations should not require unnecessary effort.
So that became the next step.
Two scripts, one practical deployment model
The design goal was simple from the beginning: keep the practical deployment path minimal. No mandatory web interface, no oversized stack, and no requirement to assemble extra infrastructure just to support a handful of users.
The foundation is amneziawg-install.sh. It installs the AmneziaWG server component, generates the required parameters, and creates client configurations. Importantly, it is not just a one-time bootstrap helper. It remains useful after deployment as an operational tool for managing the installation.
There is one caveat worth noting: the S4 parameter should be handled carefully. It directly affects MTU, which means overly aggressive values may not break the installation itself, but can later surface as degraded or unstable connectivity.
On top of that base layer, there is an optional second component: the web panel. Its lifecycle is managed separately via amneziawg-web.sh, which handles installation, upgrades, removal, and status checks.
That separation is deliberate. I did not want an architecture where installing a management interface automatically drags in a broader dependency graph or turns the entire setup into a monolith. The panel is an optional layer above an already working VPN, not a requirement for getting the VPN online in the first place.
Internally, the panel is implemented as a standalone Rust service, built with Cargo, using SQLite, and intentionally light on external dependencies. And to state the obvious plainly, GitHub Copilot was genuinely helpful during development.
The resulting model is straightforward: start with a working VPN and a scriptable operational toolchain; add the web interface later if the number of users and the amount of repetitive administration justify it.
Deployment without ceremony
The practical deployment flow mirrors that philosophy.
First install the VPN itself:
curl -O https://raw.githubusercontent.com/wiresock/amneziawg-install/main/amneziawg-install.sh
chmod +x amneziawg-install.sh
sudo ./amneziawg-install.sh
If you later decide that a web interface would be useful, install it separately on top of the existing deployment:
curl -O https://raw.githubusercontent.com/wiresock/amneziawg-install/main/amneziawg-web.sh
chmod +x amneziawg-web.sh
sudo ./amneziawg-web.sh install
If working from a repository checkout is more convenient, the same setup can be done like this:
git clone https://github.com/wiresock/amneziawg-install.git
cd amneziawg-install
sudo ./amneziawg-install.sh
sudo ./amneziawg-web.sh install
The principle is more important than the exact command sequence: establish the smallest viable working configuration first, then decide whether additional management tooling is actually necessary.
The install script is also not limited to interactive use. It supports non-interactive deployment as well:
sudo AUTO_INSTALL=y ./amneziawg-install.sh
And it can be used for routine client management after the initial setup:
sudo ./amneziawg-install.sh --add-client alice
sudo ./amneziawg-install.sh --remove-client alice
sudo ./amneziawg-install.sh --list-clients
That is an important part of the overall design. This is not just a bootstrap script for getting a server up once. It is meant to remain useful as part of normal ongoing administration.
The panel should not be public by default
One requirement mattered from the outset: the web panel should not be internet-facing unless the administrator explicitly decides otherwise.
By default, it binds to 127.0.0.1:8080. That leaves the exposure model entirely up to the operator. If permanent external access is needed, a reverse proxy can be added. If the panel is only meant for the administrator, it can remain private and be accessed over an SSH tunnel.
For example:
ssh -L 8080:127.0.0.1:8080 [email protected]
That makes the panel available locally at http://127.0.0.1:8080 while keeping it inaccessible from the outside.
For an administrative interface, this is a much healthier default than exposing it publicly from day one and only later discovering why that was a mistake.
Getting the server online is only half the problem
Once the server is up, the more interesting part begins.
A functioning tunnel is not enough on its own. Under real-world conditions, it also matters how that traffic appears from the outside and whether it attracts attention.
In AmneziaWG, that role is handled by the I1–I5 parameters. Their purpose is to make traffic resemble a benign, recognizable protocol rather than something that is easy to classify and filter. Without that kind of shaping, it becomes much harder to build something resilient enough for practical use.
In fact, in some scenarios it may be easier to get acceptable results from Cloudflare WARP with well-chosen initial camouflage than from a full AmneziaWG 2.0 deployment that lacks appropriate tuning.
That said, direct work with low-level packet-shaping parameters is not especially user-friendly. In WireSock, we approached the same problem differently. Instead of making users work directly with I1–I5, the configuration model is expressed through higher-level choices such as protocol, domain, and browser profile, particularly for QUIC-based scenarios. The implementation differs, but the intent is the same.
I am deliberately not going deeper into specific tactical parameter recommendations here. Values that behave well today may be ineffective tomorrow, and turning an article into a catalog of disposable evasion settings is rarely useful.
When the console is no longer the right interface
With only a few users, the web panel is optional in the strongest possible sense. The base script already does everything required for normal operation.
But once the installation grows beyond a tiny personal setup, repetitive tasks start accumulating. Individually they are trivial; collectively they become a time sink.
That is the real reason the web panel exists.
It is not a replacement for the install script. It is a more convenient surface for the exact same operations that become routine once the installation has actual users behind it.
The panel itself is intentionally simple. That is not an accident. I did not want an admin UI that tries to impress anyone with architecture diagrams in human form. I wanted one that opens quickly, does the necessary things, and gets out of the way.
In its current form, it covers the same user-related operations already supported by the script: adding users, removing them, temporarily disabling access, and exposing a small amount of related operational data. At the same time, I do not think of it as a finished platform. It is still evolving, and for me it remains what it was from the start: a working tool that grows in the directions that prove useful in practice.
Client choices
The client side, at least in my case, ended up being fairly pragmatic.
On Windows, I would recommend WireSock Secure Connect. That recommendation is not entirely neutral, since it is my own project. Starting with version 3.3.1, it supports AmneziaWG 2.0. Beta builds are available on the official site, while the newest builds typically appear first in the official Telegram channel.
On iOS, AmneziaWG has worked well in practice.
On Android, WG Tunnel has been the most convenient option in my own usage.
This is not meant to be a definitive cross-platform ranking. It is simply the set of clients that has proven the most practical for real everyday use in my environment.
Conclusion
The end result is a deliberately practical stack: an install script for deploying self-hosted AmneziaWG, an optional web panel for day-to-day user management, and a client-side workflow that avoids unnecessary complexity.
It is not a universal answer for every network environment. It is not a platform, not an ecosystem, and not an excuse to build half a DevOps department around a handful of users.
It is just a working toolchain for a clear, concrete problem.
That is enough.
