Files
command-center/omp-docs/agentic-web-research/vpn-routing.md
T
Frank c99eb8e11b docs(fleet): live-probe corrections across dankclaw, caddy, gitea, searxng, vpn docs
Live read-only probes on Dankclaw (BatchMode ssh, 2026-10-19):

- system/dankclaw.md: full 32-container census added (authentik IdP,
  prometheus/grafana/loki/alloy/alertmanager monitoring, pihole, ntfy,
  seerr, hermes stack, anubis, frank-tts :7772 all undocumented);
  dragoon pool corrected 401,408 @ ctx 200,704 (was conflated);
  zealot corrected to PrismML build 10777, Ternary-Bonsai-2-9B
  PQ2_0-MTP, 2x262,144 over one 524,288 pool, f16 K+V (doc claimed
  build 10754, 27B, 2x200,704)
- caddy/index.md: v2.11.7 (in-container ), deduped
  caddyfile listing
- gitea: version 1.27.3 probed via API; systemd-gitea network + rootless
  100999 mapping confirmed live (gitea-server attaches systemd-gitea;
  dank subuid 100000:65536); index See-Also de-duplicated
- searxng-tuning.md: live instance section (ghcr image, valkey:9-alpine,
  marreta netns-sharing explains duplicate port maps); POLICY DRIFT FLAG:
  tuned engine policy (google/bing disabled, verified 2026-08-16) is NOT
  live — /config now shows all 262 engines enabled; upstream settings.yml
  count corrected 388@master; limiter table already matched source
- vpn-routing.md: verify snippet fixed — gluetun image ships no curl;
  health server is 127.0.0.1:9999/health ('OK'), :8000 is the CONTROL
  server (404s on health paths); correct probes provided

Refs #29
2026-10-19 04:12:04 -07:00

5.4 KiB

type, title, description, tags, verified, timestamp, resource
type title description tags verified timestamp resource
concept VPN Routing for SearXNG Send only SearXNG outbound requests through a VPN while leaving all other local traffic alone.
vpn
searxng
networking
proxy
unverified
2026-08-28 2026-08-19 https://docs.searxng.org/admin/settings/settings_outgoing.html

VPN Routing for SearXNG

SearXNG talks to many upstream engines. Some of them rate-limit or block the source IP. You can send only that outbound path through a VPN and leave every other process on the host untouched.

This page gives four working patterns. Choose the one that matches how you run SearXNG.

Your setup: SearXNG runs on another host at 192.168.0.143:8081 (dankclaw). Apply the Docker patterns on that host. The proxy pattern works from any host.

The Goal

graph LR
    A[Local agent] --> B[SearXNG]
    B -->|through VPN| C[Upstream engines]
    D[Other local traffic] --> E[Plain internet]

The VPN carries only the SearXNG outbound path. Nothing else changes.

Pattern 1: SearXNG Proxy Setting

SearXNG supports HTTP and SOCKS proxies natively. Point the outbound settings at a local proxy that exits through the VPN.

outgoing:
  proxies:
    all://:
      - socks5://vpn-proxy:1080
  extra_proxy_timeout: 10.0

Apply the proxy to one engine only:

engines:
  - name: google
    engine: google
    proxies:
      https:
        - socks5://vpn-proxy:1080

To force the VPN source IP on a multi-homed host, add source_ips and pin the engine to IPv4:

outgoing:
  source_ips:
    - 10.8.0.2

engines:
  - name: my-search
    engine: duckduckgo
    network: ipv4

Gluetun is a VPN container (WireGuard or OpenVPN). Attach SearXNG to its network namespace. Only SearXNG shares the tunnel. Other containers stay on the default network.

services:
  gluetun:
    image: qmcgaw/gluetun:latest
    cap_add: [NET_ADMIN]
    devices: [/dev/net/tun:/dev/net/tun]
    ports:
      - "8081:8080"
    environment:
      VPN_SERVICE_PROVIDER: mullvad
      VPN_TYPE: wireguard
      WIREGUARD_PRIVATE_KEY: <key>
    restart: always

  searxng:
    image: searxng/searxng:latest
    network_mode: service:gluetun
    depends_on:
      - gluetun
    volumes:
      - ./core-config:/etc/searxng
    restart: unless-stopped

Put the port mapping on the gluetun service. The searxng container does not get its own ports.

Pattern 3: Dedicated Internal Network

Create a network that only SearXNG shares with a lighter VPN client.

services:
  searxng:
    image: searxng/searxng:latest
    networks:
      - searxng-vpn
    volumes:
      - ./core-config:/etc/searxng

  vpn-client:
    image: dperson/openvpn-client:latest
    networks:
      - searxng-vpn
    cap_add:
      - NET_ADMIN

networks:
  searxng-vpn:
    internal: true

An OpenVPN client container is simpler than Gluetun when your provider uses OpenVPN.

Pattern 4: Run SearXNG Inside the VPN Container

services:
  searxng:
    image: searxng/searxng:latest
    network_mode: "container:vpn-client"
    depends_on:
      - vpn-client
    volumes:
      - ./core-config:/etc/searxng

  vpn-client:
    image: dperson/openvpn-client:latest
    cap_add: [NET_ADMIN]
    environment:
      VPN: server.address;username;password
    restart: always

This pattern places the whole SearXNG process inside the tunnel namespace. The host sees the tunnel as the only route for SearXNG.

Compare the Patterns

Pattern Complexity Isolation Per-engine control
Proxy setting Low Medium Yes
Gluetun Medium High No
Dedicated network Medium High No
Inside VPN container Medium Highest No

Decisions That Matter

  • A SOCKS proxy keeps the per-engine control. Use Pattern 1.
  • Gluetun gives the cleanest full-tunnel setup. Use Pattern 2.
  • Mullvad ships its own WireGuard keys for Gluetun.
  • An OpenVPN-only provider works with Pattern 3 or 4.

Verify the Route

  1. Run the instance with the VPN active.
  2. Query an IP-echo page through SearXNG.
  3. Confirm that the returned IP differs from your host IP.
  4. Confirm that unrelated host traffic keeps the host IP.
# Gluetun ships no curl; use its own endpoints or a throwaway container.
podman exec gluetun sh -c 'test -e /sys/class/net/tun0 && echo tunnel-up'
podman exec gluetun sh -c 'wget -qO- 127.0.0.1:9999/health'   # "OK" when up
# NOTE: :9999 is Gluetun's HTTP health server (200 "OK" / 500); :8000 is the
# CONTROL server (/v1/* API), which 404s on everything else. Do not health-
# probe :8000. Egress-IP check needs a real binary — run a companion
# container on gluetun's network: docker run --rm --net container:gluetun
# curlimages/curl -s ifconfig.me

Citations

See Also