How Vane Integrates with SearxNG: Architecture and Implementation Guide
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 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, the UI definition links this setting to the SEARXNG_API_URL environment variable:
// 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 retrieves this value:
// 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 – 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 script launches SearxNG in the background on port 8080, performs a health check, and then starts the Vane server:
# 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:
ENV SEARXNG_API_URL=http://localhost:8080
Application Layer: The searchSearxNG Wrapper
The searchSearxng function in 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:
// 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 performs site-restricted news searches:
// 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:
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 directly:
{
"search": {
"searxngURL": "http://my-searxng-host:8080"
}
}
Using the Search Helper in Custom Agents
Import searchSearxng to execute searches within your own Vane extensions:
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 viagetSearxngURL()and configurable through theSEARXNG_API_URLenvironment variable. - Container Integration: The
Dockerfileandentrypoint.shembed a SearxNG instance on port 8080, creating a self-contained deployment that requires no external search services. - API Abstraction: The
searchSearxnghelper insrc/lib/searxng.tsstandardizes 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.tsdemonstrate 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. 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, the runtime accessor in src/lib/config/serverRegistry.ts, and the Docker environment variables in the Dockerfile and entrypoint.sh scripts. The application code wrapper resides in src/lib/searxng.ts.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →