Skip to content

AmneziaWG deployment profile

F-Layer prepares an AmneziaWG 3.1 server and a separate importable .conf file for each device. The server runs on Ubuntu 24.04, x86-64, with systemd and a working /dev/net/tun. It uses the official userspace implementation, so it does not require a third-party kernel module.

The public example is examples/vpn/amneziawg.toml. Its device addresses belong to 10.66.0.0/24; 10.66.0.1 is reserved for the server. Choose a different private subnet if this overlaps a network you use.

Traffic and client support

In full mode, all IPv4 destinations use the tunnel. In split mode, only the listed destinations use it. The DNS addresses must be covered by those routes. Server forwarding follows the same destination list and applies IPv4 NAT. Clients cannot forward traffic to other VPN clients or the cloud metadata address range.

IPv6 is not supported by this profile. Disable IPv6 on the client connection before using it as a full tunnel; ipv6_policy = "disabled" records that prerequisite, but does not change the client's operating system. F-Layer does not add ::/0 to an IPv4-only server. Enabling a client kill switch or disabling IPv6 is a separate client-side action and must be verified on the actual device.

Use a native AmneziaWG client that supports protocol 3.1:

Import the device's amneziawg.conf using the client's Import from file action, then activate the tunnel. Keep one configuration per device. A plain WireGuard client and older AmneziaWG clients cannot read all the generated 3.1 settings. See the official import instructions.

Preparation and credential handling

GenerateAmneziaWgSecrets() creates Curve25519 keys with the cryptography optional dependency, plus an independent 32-byte header-protection key. PrepareAmneziaWg() renders the validated public profile, endpoint, settings, and those keys into owned server and device bundles. Rendering performs no filesystem, network, or cloud operations. The same inputs produce the same bytes.

The server bundle has five files:

File Purpose
server.conf Server private key, obfuscation settings, and peer public keys.
install.sh Pinned installation, health checks, replacement, and removal.
firewall.nft Per-interface IPv4 forwarding restrictions and NAT.
network.sh Tunnel address, MTU, forwarding, and owned firewall activation.
service.service Persistent systemd service for the userspace tunnel.

All bundle files are classified as sensitive. Client private keys appear only in their respective client bundles and the controller's private credential store. They are absent from server.conf. Never copy the controller's encoded credential material to the guest, cloud-init metadata, generic resource state, logs, or a Git repository.

EncodeAmneziaWgSecrets() and DecodeAmneziaWgSecrets() support bounded private controller storage. This allows preparation before the cloud assigns an IP address, followed by client rendering with the real endpoint and the same keys. Store those bytes using the existing private owned-artifact contract.

To add or remove a device, change public intent and call GenerateAmneziaWgSecrets(profile, previous) with the retained credentials. Unchanged devices and the server retain their keys. To replace one compromised device key, explicitly supply rotate_device_ids=("phone",). Preparation alone does not revoke a device. The initial guest installer accepts only a new deployment or an identical retry; it refuses changed existing deployments until an explicit expected-deployment receipt is supported end to end. For now, changed credentials require controlled removal and recreation. Verify the resulting server before removing obsolete local client artifacts.

Guest installation contract

The provisioning adapter must verify the SSH host key and transfer the five server files into a private staging directory on the intended guest. Files must be regular, root-owned, mode 0600, and have exactly one hard link. Execute:

sudo bash ./install.sh
sudo bash ./install.sh --check

The installer verifies Ubuntu 24.04 and x86-64, installs standard build/network dependencies through the distribution's authenticated APT repositories, and builds the pinned official upstream source. It verifies the Go archive's SHA-256 before extraction, verifies both Git revisions before building, and requires Go's module checksum database with a read-only dependency graph. HTTPS access to GitHub, go.dev, and the Go module proxy/checksum service is required during initial installation.

Component Pin
AmneziaWG Go v3.1.20260828, commit b5928efb6ca19f0153958460c3d141f04abc5c2e
AmneziaWG tools v3.1.20260812, commit ee0f0a9aa34ff0a0da4b3433b9512781cfe02843
Go compiler 1.27.2, official Linux amd64 archive with a pinned SHA-256.

The service and interface names derive from the complete stack ownership identity. Installation refuses foreign or symlinked managed paths. Repeating an unchanged healthy installation returns without reinstalling dependencies. A changed or missing saved payload receipt stops installation before downloads or service changes. An unhealthy identical installation can be repaired; its files are backed up first, and a failed start restores the previous files and attempts to restart the previous service. The systemd unit starts the tunnel and its owned firewall rules after a reboot.

The guest bootstrap must explicitly allow the declared UDP ingress and permit the forwarding path used by this profile. The original SSH application gateway has a forwarding policy of drop and cannot be reused unchanged: an accept rule in another nftables base chain does not override that drop. This installer never flushes unrelated firewall rules. network.sh enables IPv4 forwarding when the service starts.

--check verifies the systemd unit, tunnel listen port, assigned IPv4 address, IPv4 forwarding, and owned nftables table. It does not claim a client handshake, internet reachability, DNS success, or protection against a particular network's traffic filtering. Test those from a real client after deployment.

sudo bash ./install.sh --remove removes only the ownership-verified service and its private guest files. It leaves distribution packages and global forwarding settings alone because other profiles may use them. Destroying the owned cloud instance remains the lifecycle adapter's responsibility.

Evidence and upstream references

Targeted tests cover distinct device keys, exact secret redaction, native client INI parsing, deterministic bundles, full/split routes, peer replacement, malformed inputs, encoded private material, ownership-derived names, and shell syntax. The official pinned AmneziaWG tools parser also accepted a generated server configuration in a local parser-only probe. Both pinned upstream tools and the Go daemon compiled locally with the selected dependencies. This does not constitute a live cloud or device tunnel test.

Repository source