# How Vane Integrates with SearxNG: Architecture and Implementation Guide

> Learn how Vane integrates with SearxNG using its three-layer architecture. Discover environment-aware config, Dockerization, and a TypeScript HTTP wrapper for standardized search queries.

- Repository: [Kushagra Srivastava/Vane](https://github.com/ItzCrazyKns/Vane)
- Tags: architecture
- Published: 2026-03-11

---

**TLDR:** Vane integrates with SearxNG through a three-layer architecture comprising environment-aware configuration management, Docker containerization that embeds a dedicated SearxNG process on port 8080, and a TypeScript HTTP wrapper that standardizes search queries across research agents.

The [Vane](https://github.com/ItzCrazyKns/Vane) open-source project embeds SearxNG as its meta-search backend to power research and discovery features without exposing user data to third-party trackers. This integration allows the Next.js application to aggregate results from multiple search engines through a thin abstraction layer over SearxNG's JSON API.

## Configuration Layer: Managing the SearxNG Endpoint

Vane stores the SearxNG endpoint URL in its JSON configuration under `search.searxngURL`. In [`src/lib/config/index.ts`](https://github.com/ItzCrazyKns/Vane/blob/main/src/lib/config/index.ts), the UI definition links this setting to the `SEARXNG_API_URL` environment variable:

```typescript
// src/lib/config/index.ts – UI definition
{
  name: 'SearXNG URL',
  key: 'searxngURL',
  type: 'string',
  description: 'The URL of your SearchXNG instance',
  placeholder: 'http://localhost:4000',
  default: '',
  scope: 'server',
  env: 'SEARXNG_API_URL',
}

```

At runtime, the helper function `getSearxngURL()` in [`src/lib/config/serverRegistry.ts`](https://github.com/ItzCrazyKns/Vane/blob/main/src/lib/config/serverRegistry.ts) retrieves this value:

```typescript
// src/lib/config/serverRegistry.ts
export const getSearxngURL = () =>
  configManager.getConfig('search.searxngURL', '');

```

This design allows operators to configure the endpoint either through environment variables at startup or via the settings UI after deployment.

## Docker and Entrypoint: Embedding SearxNG

The integration includes a fully containerized SearxNG instance that runs alongside the Vane application. The `Dockerfile` installs SearxNG from source, creates a dedicated `searxng` user, and establishes a Python virtual environment:

```dockerfile

# Dockerfile – install SearxNG

RUN useradd --shell /bin/bash --system \
    --home-dir "/usr/local/searxng" \
    --comment 'Privacy-respecting metasearch engine' \
    searxng
...
RUN git clone "https://github.com/searxng/searxng" \
               "/usr/local/searxng/searxng-src"
RUN python3 -m venv "/usr/local/searxng/searx-pyenv"
RUN "/usr/local/searxng/searx-pyenv/bin/pip" install --upgrade pip setuptools wheel pyyaml msgspec typing_extensions
RUN cd "/usr/local/searxng/searxng-src" && \
    "/usr/local/searxng/searx-pyenv/bin/pip" install --use-pep517 --no-build-isolation -e .

```

The [`entrypoint.sh`](https://github.com/ItzCrazyKns/Vane/blob/main/entrypoint.sh) script launches SearxNG in the background on port 8080, performs a health check, and then starts the Vane server:

```bash

# entrypoint.sh – start SearxNG then Vane

sudo -H -u searxng bash -c "cd /usr/local/searxng/searxng-src && \
  export SEARXNG_SETTINGS_PATH='/etc/searxng/settings.yml' && \
  export FLASK_APP=searx/webapp.py && \
  /usr/local/searxng/searx-pyenv/bin/python -m flask run --host=0.0.0.0 --port=8080" &
...
exec node server.js

```

The Dockerfile injects the default endpoint URL via the `SEARXNG_API_URL` environment variable:

```dockerfile
ENV SEARXNG_API_URL=http://localhost:8080

```

## Application Layer: The searchSearxNG Wrapper

The `searchSearxng` function in [`src/lib/searxng.ts`](https://github.com/ItzCrazyKns/Vane/blob/main/src/lib/searxng.ts) provides a thin TypeScript wrapper around SearxNG's HTTP API. It constructs the request URL, appends query parameters, implements a 10-second timeout using `AbortController`, and returns typed results:

```typescript
// src/lib/searxng.ts
export const searchSearxng = async (query: string, opts?: SearxngSearchOptions) => {
  const searxngURL = getSearxngURL();                 // ← reads config
  const url = new URL(`${searxngURL}/search?format=json`);
  url.searchParams.append('q', query);
  // …append optional params…
  const controller = new AbortController();
  const timeoutId = setTimeout(() => controller.abort(), 10_000);
  const res = await fetch(url, { signal: controller.signal });
  // …error handling…
  const data = await res.json();
  return { results: data.results, suggestions: data.suggestions };
};

```

Consumer modules import this helper to execute searches. For example, the Discover API in [`src/app/api/discover/route.ts`](https://github.com/ItzCrazyKns/Vane/blob/main/src/app/api/discover/route.ts) performs site-restricted news searches:

```typescript
// src/app/api/discover/route.ts
await searchSearxng(`site:${link} ${query}`, {
  engines: ['bing news'],
  pageno: 1,
  language: 'en',
});

```

Other agents, including the media search and research modules, reuse this same wrapper, ensuring consistent timeout handling and error management across the application.

## Practical Implementation Examples

### Configuring an External SearxNG Instance

To use an external SearxNG installation instead of the embedded instance, pass the `SEARXNG_API_URL` environment variable when running the container:

```bash
docker run -d -p 3000:3000 \
  -e SEARXNG_API_URL=http://my-searxng-host:8080 \
  -v vane-data:/home/vane/data \
  itzcrazykns1337/vane:slim-latest

```

Alternatively, modify [`data/config.json`](https://github.com/ItzCrazyKns/Vane/blob/main/data/config.json) directly:

```json
{
  "search": {
    "searxngURL": "http://my-searxng-host:8080"
  }
}

```

### Using the Search Helper in Custom Agents

Import `searchSearxng` to execute searches within your own Vane extensions:

```typescript
import { searchSearxng } from '@/lib/searxng';

async function getTechNews() {
  const { results } = await searchSearxng('technology news', {
    engines: ['bing news'],
    language: 'en',
    pageno: 1,
  });

  return results.map(r => ({
    title: r.title,
    url: r.url,
    snippet: r.content,
  }));
}

```

## Summary

- **Configuration Management**: Vane stores the SearxNG endpoint in `search.searxngURL`, accessible via `getSearxngURL()` and configurable through the `SEARXNG_API_URL` environment variable.
- **Container Integration**: The `Dockerfile` and [`entrypoint.sh`](https://github.com/ItzCrazyKns/Vane/blob/main/entrypoint.sh) embed a SearxNG instance on port 8080, creating a self-contained deployment that requires no external search services.
- **API Abstraction**: The `searchSearxng` helper in [`src/lib/searxng.ts`](https://github.com/ItzCrazyKns/Vane/blob/main/src/lib/searxng.ts) standardizes HTTP requests to the SearxNG JSON API with 10-second timeouts and typed responses.
- **Consumer Pattern**: Agents like the Discover endpoint in [`src/app/api/discover/route.ts`](https://github.com/ItzCrazyKns/Vane/blob/main/src/app/api/discover/route.ts) demonstrate site-restricted queries and engine-specific filtering using the shared wrapper.

## Frequently Asked Questions

### Can Vane connect to an external SearxNG instance instead of the embedded one?

Yes. Set the `SEARXNG_API_URL` environment variable when starting the container, or update the `search.searxngURL` value in [`data/config.json`](https://github.com/ItzCrazyKns/Vane/blob/main/data/config.json). The `getSearxngURL()` function will read this configuration and direct all search queries to your specified endpoint.

### What timeout does Vane use for SearxNG requests?

The `searchSearxng` function implements a **10-second timeout** using `AbortController`. If SearxNG does not respond within this window, the request aborts and the function handles the error appropriately.

### Which search engines does Vane configure SearxNG to use?

Vane does not hardcode specific engines in the wrapper itself. Instead, consumers pass engine preferences through the `opts` parameter. For example, the Discover agent requests `['bing news']`, while other agents may specify different engines or leave the parameter empty to use SearxNG's default configuration.

### Where is SearxNG configured within the Vane repository?

SearxNG settings are distributed across three locations: the UI configuration in [`src/lib/config/index.ts`](https://github.com/ItzCrazyKns/Vane/blob/main/src/lib/config/index.ts), the runtime accessor in [`src/lib/config/serverRegistry.ts`](https://github.com/ItzCrazyKns/Vane/blob/main/src/lib/config/serverRegistry.ts), and the Docker environment variables in the `Dockerfile` and [`entrypoint.sh`](https://github.com/ItzCrazyKns/Vane/blob/main/entrypoint.sh) scripts. The application code wrapper resides in [`src/lib/searxng.ts`](https://github.com/ItzCrazyKns/Vane/blob/main/src/lib/searxng.ts).