# syntax=docker/dockerfile:1 ############################################################################### # awg_profiler — alternative container image, Linux Mint base # # The default image (Dockerfile) uses Alpine, which has no AmneziaWG package # at all, so amneziawg-tools has to be compiled from source and the profiler # is steered onto its OpenRC code path (direct `awg-quick`, no init system) # to avoid systemd. That path works, but it is a workaround: it ships # self-built binaries instead of the vendor-maintained ones, and it exists # only because Alpine isn't a distro AmneziaWG actually supports. # # Linux Mint (Ubuntu-based) IS officially supported: the project's own docs # describe installing it via `ppa:amnezia/ppa` + `apt-get install amneziawg`. # This image follows that exact documented flow to obtain `awg`/`awg-quick` # as prebuilt, vendor-maintained packages instead of compiling them here. # # Two things still don't change, for the same reason as the Alpine image: # - No kernel module. A container can't load one (and doing so would need # the much larger CAP_SYS_MODULE, not just NET_ADMIN), so only # `amneziawg-tools` is installed — never the `amneziawg` DKMS package. # awg-quick (same upstream script either way) auto-falls-back to the # userspace `amneziawg-go` data plane when /sys/module/amneziawg is # absent, exactly like on Alpine, so amneziawg-go is still built from # source in its own stage below. # - No systemd as PID 1 inside the container. osdetect.go now detects this # at runtime (absence of /run/systemd/system) and falls back to driving # awg-quick directly, the same way the Alpine/OpenRC path always has. # # The Alpine build (Dockerfile) is unchanged and remains the default/smaller # option; this is an alternative for cases where the Alpine workarounds are # themselves the problem (e.g. wanting vendor-built awg/awg-quick binaries). ############################################################################### ARG AWG_GO_REF=master # Pin to a specific Linux Mint release image; "latest" tracks whatever the # linuxmintd maintainer currently publishes. ARG MINT_IMAGE=linuxmintd/mint22-amd64:latest # ─── Stage 1: build the profiler binary (static, CGO off) ──────────────────── FROM golang:1.26-alpine AS app-builder WORKDIR /src # Assets in webui/ are compiled into the binary via //go:embed, so the whole # module source is needed but nothing has to be shipped alongside the binary. COPY go.mod ./ COPY *.go ./ COPY webui/ ./webui/ COPY webui_glass/ ./webui_glass/ ENV CGO_ENABLED=0 RUN go build -trimpath -ldflags="-s -w" -o /out/awg_profiler . # ─── Stage 2: build amneziawg-go (userspace data plane, not packaged anywhere) ─ FROM golang:1.26-alpine AS awggo-builder ARG AWG_GO_REF RUN apk add --no-cache git make WORKDIR /src RUN git clone --depth=1 --branch "${AWG_GO_REF}" \ https://github.com/amnezia-vpn/amneziawg-go . \ && CGO_ENABLED=0 make \ && install -Dm0755 amneziawg-go /out/amneziawg-go # ─── Stage 3: runtime — Linux Mint, AmneziaWG via the official PPA ──────────── FROM ${MINT_IMAGE} ENV DEBIAN_FRONTEND=noninteractive # The official docs add this PPA via `add-apt-repository ppa:amnezia/ppa` # (Software Sources → PPAs, after enabling "Source code repositories"). That # tool fails in this base image with "OS codename: 'noble'. This codename # isn't currently supported" — a codename-database bug in the bundled # software-properties-common/python3-launchpadlib, unrelated to AmneziaWG # (the PPA itself does publish for noble). Same end result — packages from # ppa:amnezia/ppa — added the way most Dockerfiles add a PPA non-interactively: # fetch its signing key and write the sources.list entry directly, keyed off # the base image's own Ubuntu codename so it still works if MINT_IMAGE points # at a different Mint/Ubuntu release. RUN apt-get update -qq \ && apt-get install -y --no-install-recommends ca-certificates gnupg curl \ && install -d -m 0755 /etc/apt/keyrings \ && curl -fsSL 'https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x75C9DD72C799870E310542E24166F2C257290828' \ | gpg --dearmor -o /etc/apt/keyrings/amnezia.gpg \ && . /etc/os-release \ && echo "deb [signed-by=/etc/apt/keyrings/amnezia.gpg] https://ppa.launchpadcontent.net/amnezia/ppa/ubuntu ${VERSION_CODENAME} main" \ > /etc/apt/sources.list.d/amnezia-ppa.list \ && apt-get update -qq \ && apt-get install -y --no-install-recommends \ amneziawg-tools iproute2 nftables qrencode procps \ && rm -rf /var/lib/apt/lists/* # Note: deliberately no `apt-get purge --auto-remove` cleanup pass here — the # base image ships mintsources with an already-broken dependency # (python3-repolib, unrelated to AmneziaWG) that makes the resolver bail out # on *any* autoremove/purge. Leaving gnupg/curl installed costs a few MB, # which is immaterial next to the size of the Mint base image itself. # AmneziaWG userspace data plane (built above) + the profiler itself. COPY --from=awggo-builder /out/amneziawg-go /usr/bin/amneziawg-go COPY --from=app-builder /out/awg_profiler /usr/local/bin/awg_profiler COPY entrypoint.mint.sh /usr/local/bin/entrypoint.sh RUN chmod +x /usr/local/bin/entrypoint.sh # All mutable profiler state (config, client registry, generated profiles, the # deps-installed flag) lives here; the interface .conf + nft ruleset live in # /etc/amnezia/amneziawg. Mount volumes on both to persist across restarts. ENV AWG_PROFILER_DIR=/data VOLUME ["/data", "/etc/amnezia/amneziawg"] # WireGuard/AmneziaWG listen port (UDP) and the management web UI (TCP). EXPOSE 51820/udp EXPOSE 8080/tcp ENTRYPOINT ["/usr/local/bin/entrypoint.sh"] # Default to the web UI on all interfaces; override with any profiler subcommand. CMD ["web", "--addr", "0.0.0.0:8080"]