You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

8.0 KiB

AmneziaWG Build Implementation

Summary

The Dockerfile now builds and includes complete AmneziaWG support with two components:

  1. amneziawg-tools - CLI tools (awg, awg-quick)
  2. amneziawg.ko - Kernel module (pre-built for Alpine LTS 6.12.50)

Build Process

Stage 1: Build UI and Tools

FROM node:lts-alpine AS build
  • Builds the web UI with Nuxt/pnpm
  • Compiles amneziawg-tools from source

Stage 2: Build Kernel Module

FROM alpine:3.20 AS kernel_module_builder
  • Installs linux-lts-dev package (provides headers for 6.12.50)
  • Clones amneziawg-linux-kernel-module repository
  • Compiles kernel module against Alpine LTS headers
  • Exports amneziawg.ko if build succeeds

Stage 3: Final Image

FROM node:lts-alpine
  • Copies all built artifacts from stages 1 & 2
  • Installs runtime dependencies (iptables, wireguard-tools, etc.)
  • Sets up environment variables and configurations

What Gets Built

AmneziaWG Tools (/usr/bin/awg, /usr/bin/awg-quick)

AmneziaWG Kernel Module (/lib/modules/amneziawg.ko)

Kernel Module Specifics

Target Kernel

  • Version: 6.12.50-0-lts (Alpine Linux LTS)
  • Headers Source: apk add linux-lts-dev
  • Build Location: /usr/src/linux-headers-6.12.50-0-lts

Compatibility

The kernel module only works on hosts running:

  • Alpine Linux
  • With linux-lts kernel installed
  • Exact version: 6.12.50

For all other systems, the application will fall back to standard WireGuard.

Build Output

  • Success: /build/module/amneziawg.ko → copied to /lib/modules/
  • Failure: Logs warning, continues build (standard WireGuard will be used)
  • Version info: /etc/amneziawg-kernel-version.txt

Runtime Behavior

Automatic Detection (wgHelper.ts:14-22)

if (WG_ENV.EXPERIMENTAL_AWG) {
  if (WG_ENV.OVERRIDE_AUTO_AWG !== undefined) {
    wgExecutable = WG_ENV.OVERRIDE_AUTO_AWG;
  } else {
    wgExecutable = await exec('modinfo amneziawg')
      .then(() => 'awg')
      .catch(() => 'wg');
  }
}

The application checks:

  1. Is EXPERIMENTAL_AWG=true?
  2. Is there a manual override (OVERRIDE_AUTO_AWG)?
  3. Is the amneziawg kernel module available?
  4. Falls back to standard WireGuard if needed

Environment Variables

Variable Default Purpose
EXPERIMENTAL_AWG false Enable AmneziaWG support
OVERRIDE_AUTO_AWG undefined Force awg or wg mode

Example:

environment:
  - EXPERIMENTAL_AWG=true          # Enable AmneziaWG
  - OVERRIDE_AUTO_AWG=awg          # Force userspace mode

Build Commands

Build the Image

docker build -t wg-easy .

Check Build Results

# Check if kernel module was built
docker run --rm wg-easy ls -la /lib/modules/

# Check kernel version target
docker run --rm wg-easy cat /etc/amneziawg-kernel-version.txt

# Check all AmneziaWG binaries
docker run --rm wg-easy ls -la /usr/bin/ | grep -E 'awg|amnezia'

Expected Output

-rwxr-xr-x    1 root     root       1.2M amneziawg-go
-rwxr-xr-x    1 root     root       156K awg
-rwxr-xr-x    1 root     root        45K awg-quick

Deployment Scenarios

Scenario 1: Alpine LTS Host (Kernel Module)

Host: Alpine Linux with kernel 6.12.50-0-lts Mode: Kernel module (best performance)

services:
  wg-easy:
    image: wg-easy
    environment:
      - EXPERIMENTAL_AWG=true
    cap_add:
      - NET_ADMIN
      - SYS_MODULE
    privileged: true

Scenario 2: Other Linux Distributions (Userspace)

Host: Ubuntu/Debian/RHEL/etc. Mode: Userspace amneziawg-go (portable)

services:
  wg-easy:
    image: wg-easy
    environment:
      - EXPERIMENTAL_AWG=true
      - OVERRIDE_AUTO_AWG=awg  # Force userspace
    cap_add:
      - NET_ADMIN

Scenario 3: Standard WireGuard (Fallback)

Host: Any Linux Mode: Standard WireGuard kernel module

services:
  wg-easy:
    image: wg-easy
    environment:
      - EXPERIMENTAL_AWG=false
      # OR
      - OVERRIDE_AUTO_AWG=wg

Verification

Check Kernel Module Load

# On host
lsmod | grep amneziawg

# Expected output if loaded:
# amneziawg              81920  0

Check Which Mode is Active

# Check detection
docker exec wg-easy awg show

# If working, you'll see interface details

Troubleshooting

Kernel Module Won't Build

Symptom: Build completes but no /lib/modules/amneziawg.ko

Solutions:

  • This is expected on build hosts with different kernel versions
  • The image will still work with standard WireGuard
  • No action needed - module is for Alpine LTS 6.12.50 only

Kernel Module Won't Load at Runtime

Symptom: Module file exists but modprobe amneziawg fails

Causes:

  • Host kernel version != 6.12.50
  • Missing SYS_MODULE capability
  • Not running with privileged: true

Solution:

environment:
  - OVERRIDE_AUTO_AWG=wg  # Force standard WireGuard

Files Modified

  1. Dockerfile - Added multi-stage build for kernel module
  2. docs/content/advanced/config/amnezia-kernel-module.md - New documentation
  3. AMNEZIAWG_BUILD.md - This file

References

Build Architecture

┌─────────────────────────────────────────────────────────┐
│ Stage 1: Build (node:lts-alpine)                        │
│  - Web UI (Nuxt/TypeScript)                             │
│  - amneziawg-tools (C)                                  │
└────────────────┬────────────────────────────────────────┘
                 │
┌────────────────▼────────────────────────────────────────┐
│ Stage 2: Kernel Module Builder (alpine:3.20)           │
│  - Install linux-lts-dev (6.12.50 headers)              │
│  - Clone amneziawg-linux-kernel-module                  │
│  - Build amneziawg.ko                                   │
└────────────────┬────────────────────────────────────────┘
                 │
┌────────────────▼────────────────────────────────────────┐
│ Stage 3: Final Image (node:lts-alpine)                 │
│  - Copy built UI from stage 1                           │
│  - Copy amneziawg-tools from stage 1                    │
│  - Copy amneziawg.ko from stage 2 (if built)            │
│  - Install runtime dependencies                         │
│  - Configure environment                                │
└─────────────────────────────────────────────────────────┘

Key Design Decisions

  1. Multi-stage build - Minimizes final image size
  2. Pre-built kernel module - Avoids runtime compilation complexity
  3. Graceful fallback - Falls back to standard WireGuard if module fails
  4. Alpine LTS target - Matches bare-metal install script expectations
  5. Kernel module only - No userspace implementation needed