Files
serverAppConfigs/serverAppConfigs-docs/Dankclaw/Gluetun.md
T
Frank e7f0d93c86 docs(vault): fleet-wide fact re-verification pass (67 pages)
The docs-fact census wave re-read the live hosts and re-keyed every page
it could: runtime/payload identities, ports, sizes, ledger figures, unit
state, and the retirement banners that drifted as the fleet moved. The
wave was interrupted mid-run, so this commit carries only what passed the
integrity gates: every touched page parses (front matter or H1+status
convention intact, balanced fences, no truncated tables, trailing
newline), the docs_completeness and link-integrity seams are green, and
bats is 384/384.

Numbers that this session proved on live hosts are keyed to the measured
value, not the page's earlier claim.
2026-10-18 13:15:43 -07:00

5.9 KiB

type, description, tags, timestamp
type description tags timestamp
reference Gluetun is a lightweight VPN client container.
dankclaw
gluetun
2026-08-28

Gluetun

Gluetun is a lightweight VPN client container. It connects to a VPN provider (WireGuard or OpenVPN) and shares that tunnel with other containers that attach to its network namespace.

Host: Dankclaw — Tunnel: WireGuard (VPN type: wireguard, journal 2026-10-18) to ProtonVPN US-WA per dankclaw/searxng/quadlet/gluetun.container:6 — Exit: 149.22.88.19, United States, Washington, Seattle (journalctl --user -u gluetun, [ip getter], 2026-10-18; the journal never names the provider, so the provider attribution is the repo's) — Docs: https://github.com/qdm12/gluetun

Facts (from research, primary source)

Item Value
Image docker.io/qmcgaw/gluetun:latest (dankclaw/searxng/quadlet/gluetun.container:19; live 2026-10-18). Tagged :latest, so a redeploy can move the version — pin it deliberately if that ever matters.
Capabilities NET_ADMIN required (dankclaw/searxng/quadlet/gluetun.container:20)
Device /dev/net/tun:/dev/net/tun (dankclaw/searxng/quadlet/gluetun.container:21)
Ports published Two, both on this container because it owns the netns: 8081 → 8080 (SearXNG) and 8082 → 8085 (Marreta) (dankclaw/searxng/quadlet/gluetun.container:31-32; podman inspect gluetun --format '{{json .NetworkSettings.Ports}}' and ss -ltnp 2026-10-18). Neither consumer container publishes anything.
Tunnel check the tun0 interface exists — the boot config dump logs Network interface: tun0 (journalctl --user -u gluetun 2026-10-18). The control server listens on :8000 inside the netns only (.NetworkSettings.Ports shows "8000/tcp": null, 2026-10-18), so nothing on the host can reach it.

Required Environment

environment:
  VPN_SERVICE_PROVIDER: "${VPN_SERVICE_PROVIDER}"   # e.g. mullvad, protonvpn
  VPN_TYPE: wireguard
  WIREGUARD_PRIVATE_KEY: "${WIREGUARD_PRIVATE_KEY}" # from .env, never committed

Optional DNS (from research)

Variable Default Purpose
DNS_UPSTREAM_RESOLVER_TYPE dot DNS over TLS
DNS_UPSTREAM_RESOLVERS cloudflare upstream DoT providers
DNS_CACHING on cache queries
BLOCK_MALICIOUS on block malicious hostnames

Names and defaults match the upstream wiki (https://github.com/qdm12/gluetun-wiki/blob/main/setup/options/dns.md); live confirmation 2026-10-18: [dns] ready and using DNS server with dot upstream resolvers and [dns] downloading hostnames and IP block lists.

Warning from the wiki: do NOT set DNS_UPSTREAM_PLAIN_ADDRESSES to a LAN/bridge address — DNS queries leak out of the tunnel.

Attaching a Container

Three units reuse gluetun's network namespace — SearXNG and both Marreta containers:

[Container]
ContainerName=searxng
Network=gluetun.container

Network=gluetun.container also adds a systemd dependency on gluetun, so the consumer starts after the tunnel (dankclaw/searxng/quadlet/searxng.container:13-18, dankclaw/marreta/quadlet/marreta.container:29-34, dankclaw/marreta/quadlet/marreta-browser.container:20-25). Live 2026-10-18 all three report HostConfig.NetworkMode=container:03a75714…, which is gluetun's own container id (podman inspect gluetun --format '{{.Id}}') — one netns, four containers, ports published only by gluetun.

Boot Persistence

gluetun runs as the gluetun quadlet unit (see SearXNG for the full trio). It sets WantedBy=default.target and Restart=always (dankclaw/searxng/quadlet/gluetun.container:37,39-40) and user linger is on, so the tunnel starts at boot — live 2026-10-18 systemctl --user is-enabled gluetun → generated, is-active → active, NRestarts=0 since the 01:25 boot. The WireGuard credentials live in /opt/searxng/.env (mode 0600 — -rw------- dank:dank, ls -l 2026-10-18). Deploy with scripts/deploy.sh dankclaw --service gluetun (scripts/deploy-remote.sh:596-597); scripts/deploy-searxng-quadlet.sh dankclaw is a compatibility wrapper that now forwards to deploy.sh --service searxng, so it does not deploy the tunnel.

Verify the Tunnel

podman exec gluetun curl -s ifconfig.me

The returned IP must differ from the host IP. A read-only alternative is the journal: gluetun logs its own egress at start, and on 2026-10-18 it logged [ip getter] Public IP address is 149.22.88.19 (United States, Washington, Seattle …) — not the host's address.

Gotchas

  • The container that holds the published port must be the one with the ports mapping (gluetun) — searxng, marreta and marreta_browser publish nothing of their own (dankclaw/searxng/quadlet/searxng.container and dankclaw/marreta/quadlet/*.container have no PublishPort=; ss -ltnp 2026-10-18 shows only gluetun's rootlessport on 8081/8082).
  • Restart=always on gluetun (dankclaw/searxng/quadlet/gluetun.container:37) so the tunnel reconnects after VPN drops.
  • When gluetun restarts, attached containers inherit the new network state; searxng may need a restart to re-resolve DNS.
  • The gluetun health-check probe cannot open ICMP sockets: it logs listening for ICMP packets: not permitted: you can try adding NET_RAW capability to resolve this; permanently falling back to plain DNS (journal 2026-10-18). The unit grants NET_ADMIN only; the fallback works, so this is expected noise, not a fault.

See Also