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

196 lines
5.4 KiB
Markdown

---
type: concept
title: VPN Routing for SearXNG
description: Send only SearXNG outbound requests through a VPN while leaving all other local traffic alone.
tags:
- vpn
- searxng
- networking
- proxy
- unverified
verified: 2026-08-28
timestamp: 2026-08-19
resource: 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
```mermaid
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.
```yaml
outgoing:
proxies:
all://:
- socks5://vpn-proxy:1080
extra_proxy_timeout: 10.0
```
Apply the proxy to one engine only:
```yaml
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:
```yaml
outgoing:
source_ips:
- 10.8.0.2
engines:
- name: my-search
engine: duckduckgo
network: ipv4
```
## Pattern 2: Gluetun (Recommended)
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.
```yaml
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.
```yaml
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
```yaml
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.
```bash
# 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
- SearXNG outgoing settings: <https://docs.searxng.org/admin/settings/settings_outgoing.html>
- SearXNG engine settings: <https://docs.searxng.org/admin/settings/settings_engines.html>
- Gluetun: <https://github.com/qdm12/gluetun>
- Connect a container to Gluetun: <https://github.com/qdm12/gluetun-wiki/blob/main/setup/connect-a-container-to-gluetun.md>
- Docker Compose networking: <https://docs.docker.com/compose/networking/>
## See Also
- [SearXNG Tuning](searxng-tuning.md) — The instance these patterns protect.
- [Agentic Search Best Practices](agentic-search-best-practices.md) — Proxy rotation and retries.