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.
87 lines
5.9 KiB
Markdown
87 lines
5.9 KiB
Markdown
---
|
|
type: reference
|
|
description: "Gluetun is a lightweight VPN client container."
|
|
tags:
|
|
- dankclaw
|
|
- gluetun
|
|
timestamp: 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
|
|
|
|
```yaml
|
|
environment:
|
|
VPN_SERVICE_PROVIDER: "${VPN_SERVICE_PROVIDER}" # e.g. mullvad, protonvpn
|
|
VPN_TYPE: wireguard
|
|
WIREGUARD_PRIVATE_KEY: "${WIREGUARD_PRIVATE_KEY}" # from .env, never committed
|
|
```
|
|
|
|
- `VPN_TYPE` default is `openvpn`; WireGuard preferred when the provider supports it (https://github.com/qdm12/gluetun-wiki/blob/main/setup/options/vpn.md). This deployment runs WireGuard (`WIREGUARD_*` variables, `dankclaw/searxng/quadlet/gluetun.container:24-30`).
|
|
- Provider-specific variables come from the Gluetun wiki (https://github.com/qdm12/gluetun-wiki); set them in `.env`.
|
|
|
|
## 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:
|
|
|
|
```ini
|
|
[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
|
|
|
|
```bash
|
|
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
|
|
|
|
- [[SearXNG]] — the consumer of the tunnel
|
|
- [[Dankclaw Stack]]
|
|
- Knowledge base: [[SearXNG]]
|