How to Set Up SearXNG with Open WebUI
Step-by-step guide to integrate SearXNG with Open WebUI. Covers Docker networking, JSON config, GUI setup, and troubleshooting connection issues.
- SearXNG is a self-hosted search engine that integrates with Open WebUI without API keys or costs
- Docker networking requires the correct hostname: host.docker.internal on Mac/Windows, 172.17.0.1 on Linux, or the service name in Compose
- Configure SearXNG for JSON output so Open WebUI can parse results as structured data
- Set function calling to Legacy for small models (3B or less) and Native for larger ones
- Most setup problems stem from wrong hostnames, short timeouts, or incorrect query formats
SearXNG is an open-source search engine you host yourself. Open WebUI can integrate it for web search without API calls. You run both in Docker, configure SearXNG to output JSON, tell Open WebUI where to find it, and enable the search feature in the GUI. Setup takes 15 minutes. This guide walks through each step and the networking problem most people hit first.
Why SearXNG for Open WebUI?
Most AI apps that search the web use API-based providers: Google Search, Brave, DuckDuckGo, Tavily. They cost money. They log your queries. Open WebUI's alternative is SearXNG, a self-hosted metasearch engine that aggregates results from 60+ public search engines, metadata sites, and news feeds. You host it on your own machine. No API keys. No logs sold to third parties. No rate limits beyond what the upstream engines themselves apply.
If you're running Open WebUI locally already (with Ollama or another LLM), adding SearXNG is the natural next step. You control everything: the data centers your search queries hit, which upstream engines to use, how long to wait for results, and what gets logged.
Cost-wise: zero after setup. API-based search costs $5-50 per month depending on query volume. SearXNG consumes CPU and network bandwidth on your machine. For small teams or solo work, that trade favors self-hosted. Privacy-wise: your queries never leave your network. Upstream engines see requests from SearXNG's IP, not yours. That's not perfect anonymity, but it's better than sending your query directly to Google.
The self-hosted AI search engine landing page at Opsily covers 20+ web search providers. SearXNG is one option, best when you already have local infrastructure and want to minimize costs and keep data private.
What You'll Need
You need a machine running Docker or Podman (Windows, Mac, Linux). You need a working Open WebUI instance: either managed on Opsily or self-hosted. You need a SearXNG instance running in a separate container or machine. You should be comfortable with Docker Compose syntax or basic docker run commands. The entire setup takes about 15 minutes.
This guide assumes Open WebUI and SearXNG run in separate Docker containers. If you're running them on different physical machines, the networking steps change, which we cover in the troubleshooting section. If you're using Podman instead of Docker, the steps are identical, just replace "docker" with "podman" in every command.
Step 1: Configure SearXNG for JSON Output
By default, SearXNG serves HTML pages when you search it. Open WebUI cannot parse HTML search results into structured data. It needs JSON: a data format that tells Open WebUI exactly where the title, description, and URL live in each result.
When Open WebUI needs search results, it sends a request to SearXNG with your query. SearXNG processes it and returns a JSON object with an array of result objects. Each object contains a title, content snippet, and URL. Open WebUI then extracts these fields and passes them to the LLM as context for the response.
If SearXNG returns HTML instead of JSON, Open WebUI silently fails. You see "No results found" in the UI, but the LLM never received anything to work with. This is the second most common setup mistake (after networking).
To force JSON output, edit SearXNG's YAML configuration. If you're running SearXNG in Docker, create a settings.yml file and mount it into the container:
outgoing:
request_timeout: 10
max_retries: 0
server:
port: 8888
listen_on: "0.0.0.0"
secret_key: "your-secret-key"
The outgoing section controls how SearXNG talks to upstream engines. request_timeout: 10 tells SearXNG to wait up to 10 seconds for results from each engine. Increase this if you see "No results" often; decrease it if searches are too slow. max_retries: 0 means each request gets one shot with no retries.
Here's a working docker-compose.yml that mounts settings.yml:
version: '3.8'
services:
searxng:
image: searxng/searxng:latest
container_name: searxng
ports:
- "8888:8888"
volumes:
-./settings.yml:/etc/searxng/settings.yml
environment:
- SEARXNG_SECRET=your-secret-key
restart: unless-stopped
Then run:
docker-compose up -d searxng
SearXNG is now running on port 8888. But localhost means something different inside a Docker container. That's where the networking problem starts.
Step 2: Connect SearXNG to Open WebUI (Docker Networking)
Here's the trap that catches most people: inside one Docker container, localhost points to that container itself. If Open WebUI tries to reach the SearXNG container on localhost, it looks for SearXNG inside its own container. It's not there. The connection fails silently. Open WebUI logs say "Connection refused" or "No results". You'll spend an hour here if you're new to Docker.
The fix depends on your setup. We have four scenarios.
Scenario 1: Docker Compose (both containers in one file). Use the service name as the hostname. Docker's internal DNS resolves it to the container's IP.
version: '3.8'
services:
searxng:
image: searxng/searxng:latest
container_name: searxng
ports:
- "8888:8888"
volumes:
-./settings.yml:/etc/searxng/settings.yml
restart: unless-stopped
open-webui:
image: ghcr.io/open-webui/open-webui:latest
container_name: open-webui
ports:
- "3000:8080"
volumes:
-./webui-data:/app/backend/data
depends_on:
- searxng
restart: unless-stopped
Inside Open WebUI's web search settings, use searxng:8888. The service name resolves automatically.
Scenario 2: Windows with Docker Desktop. Docker Desktop on Windows has a special hostname: host.docker.internal. Use it to reach services on your machine:
host.docker.internal:8888
Scenario 3: Mac with Docker Desktop. Same as Windows: use host.docker.internal:8888.
Scenario 4: Linux. Docker on Linux does not provide host.docker.internal by default. Three options:
- Use the Docker bridge gateway IP. For the default bridge network, this is usually
172.17.0.1:8888. Verify withdocker inspect searxng | grep Gateway. - Create a custom Docker network and use the service name, like Compose does.
- Add
--add-host host.docker.internal:host-gatewayto your docker run command.
The easiest on Linux: create a network, then run both containers on it:
docker network create mynet
docker run --network mynet --name searxng -p 8888:8888 searxng/searxng:latest
docker run --network mynet --name open-webui -p 3000:8080 ghcr.io/open-webui/open-webui:latest
Then use searxng:8888 in Open WebUI. Service names work on custom networks.
Step 3: Enable Web Search in Open WebUI's Admin Panel
Now the containers can reach each other. Tell Open WebUI to use SearXNG for search.
Open Open WebUI in your browser (port 3000, or the port you mapped). Log in as an admin user. Click the settings gear icon, usually in the top right corner. Look for a "Web Search" or "Search Engine" section. Select SearXNG or "Custom" from the dropdown. Enter the URL you determined in Step 2: searxng:8888 for Compose, host.docker.internal:8888 for Mac/Windows, or 172.17.0.1:8888 for Linux.
Set the query format to JSON. Some versions of Open WebUI have a dropdown; others have a hidden setting. If you don't see a format selector, leave it blank; Open WebUI defaults to JSON for SearXNG.
Click "Test Connection" or Save. A green checkmark means success. A red X or error message means something is wrong.
If the test fails, troubleshoot:
- Is SearXNG running? Run
docker ps | grep searxngto check. - Can you open the URL in your browser (from the host machine)? Open a browser to localhost:8888 and you should see SearXNG's web interface.
- Are both containers on the same network? Run
docker network inspect bridge(or the name of your custom network) and verify both containers are listed.
Step 4: Optimize for Your Models
Web search works now. But responses might be slow, or the search doesn't trigger when you expect it to.
Function Calling: Open WebUI asks the LLM whether to search the web for each query. The LLM's function-calling ability is critical here. Large models (7B parameters or bigger, like Mistral 7B or Llama 2 13B) handle function calling natively and reliably. Smaller models (3B parameters or less) often struggle. They either refuse to call functions or call them for every query.
In Open WebUI's model settings, find the "Function Calling" option. It has two modes:
- Native: The model decides on its own. Works best for large models.
- Legacy: Open WebUI injects instructions into the prompt to guide the model. Works better for small models but costs extra tokens.
If you're using a 3B model and web search never triggers, or if it triggers for every query, switch to Legacy mode. If you're using a 13B+ model, use Native.
Always On toggle: There's an "Always On" checkbox in the search settings. When enabled, Open WebUI searches for every query, regardless of what the LLM decides. Useful if you want search to be mandatory, but it slows down every response and wastes bandwidth on queries that don't need web results. Leave it off unless you have a specific reason.
Slow search results: By default, SearXNG waits 10 seconds for results from each upstream engine. If one engine is slow in your region, the whole response is delayed. Speed it up by reducing the timeout in settings.yml:
outgoing:
request_timeout: 5
max_retries: 0
Reduce the timeout if you want faster results at the cost of fewer results from slow engines.
Disable slow engines: In SearXNG's settings, you can disable specific engines (Google, Bing, DuckDuckGo, etc.). Fewer engines mean faster results. Edit settings.yml:
engines:
- name: google
disabled: true
- name: bing
disabled: true
This is personal preference. Some engines are slow in some regions; others have stricter rate limits. Test and adjust.
Troubleshooting: Common Errors and Fixes
"No search results found" in Open WebUI. Open WebUI asked SearXNG for results but got nothing back. Check: Is SearXNG running? Run docker logs searxng to see errors. Is the URL correct? Try curl localhost:8888/?q=test from your host machine (or use host.docker.internal:8888 on Mac/Windows). You should see HTML results. If nothing returns, SearXNG crashed or didn't start. If you see HTML, the JSON format might be wrong. Increase the request_timeout in settings.yml to 15 seconds in case the timeout is too aggressive.
"403 Forbidden" or "429 Too Many Requests". An upstream engine (Google, Bing, DuckDuckGo) blocked SearXNG's IP. This happens when: You're running many search queries in quick succession (rate limiting). The public instance is hitting the engine's rate limit. Solution: Wait a few minutes, then retry. Or disable that engine in settings.yml so SearXNG stops hitting it.
"Connection refused: connect ECONNREFUSED 127.0.0.1:8888". Open WebUI tried to reach localhost:8888 from inside its container. Localhost means "this container", and SearXNG isn't there. Use the correct hostname for your setup: host.docker.internal on Mac/Windows, 172.17.0.1 on Linux, or the service name if using Compose.
SearXNG works in the browser, but Open WebUI says "No results". You can open localhost:8888 in your browser and see search results. But Open WebUI gets nothing. This means: Open WebUI is sending HTML format requests instead of JSON. SearXNG is returning HTML instead of JSON. Check the URL in Open WebUI's search settings. It should be the bare hostname: searxng:8888, not with any query parameters or format specifications.
Responses are very slow. Network latency between containers, or SearXNG waiting too long for engines. Reduce the timeout in settings.yml. Check disk I/O: docker stats searxng. Disable slow engines. If both containers are on the same machine, they're usually fast; if they're on different machines, network latency matters.
Frequently Asked Questions
How do you set up SearXNG with Open WebUI?
Configure SearXNG for JSON output in settings.yml, connect the Docker containers using the correct hostname (host.docker.internal on Mac/Windows, 172.17.0.1 or service name on Linux), then enter the URL in Open WebUI's web search settings and test the connection. All three steps are essential.
Why does Open WebUI require JSON output from SearXNG?
Open WebUI parses search results as structured data: title, snippet, and URL for each result. HTML pages are unstructured; the LLM can't reliably extract this information. JSON gives Open WebUI a predictable format.
How do you configure Docker networking for SearXNG and Open WebUI?
Use the service name if both run in the same Docker Compose file (searxng:8888). On Windows/Mac with Docker Desktop, use host.docker.internal:8888. On Linux, use 172.17.0.1:8888 or create a custom Docker network and use the service name.
What is the "Always On" toggle and why do small models need Legacy Function Calling?
The "Always On" toggle forces web search for every query, bypassing the LLM's decision. Smaller models (3B parameters or less) struggle with function calling; Legacy mode injects instructions into the prompt, costing tokens. Use Legacy for small models, Native for larger ones.
Why does SearXNG return "No results" or "403 Forbidden" errors?
"No results" usually means the timeout is too short (increase request_timeout in settings.yml to 15 seconds) or the URL is wrong. "403 Forbidden" means an upstream engine blocked SearXNG's IP due to rate limiting. Wait a few minutes or disable that engine.
How do you disable specific search engines in SearXNG to speed up results?
Edit settings.yml and set disabled: true for engines you don't need. Fewer engines means faster responses. Google and Bing are often slower in some regions; test and adjust based on your use case.
What is the difference between SearXNG and DuckDuckGo or Brave Search for Open WebUI?
DuckDuckGo and Brave are API services: you need an API key, they log requests, and they have costs or rate limits. SearXNG is self-hosted, free, and private: your queries never leave your network. Trade-off: SearXNG takes 15 minutes to set up; API services are instant.
Can you run SearXNG and Open WebUI on different machines?
Yes. On the machine with Open WebUI, point the search URL to SearXNG's IP and port (for example, 192.168.1.50:8888). Both machines must be on the same network. Latency increases, but setup is flexible.
The Bottom Line
SearXNG plus Open WebUI is the self-hosted way to add web search to your local LLM without API costs. JSON format is non-negotiable. Docker networking is the first gotcha. Function calling and timeouts are the optimization levers.
Most issues boil down to three things: wrong hostname, incorrect timeout, or the URL missing the JSON requirement. Test the connection in Open WebUI's settings before assuming it's broken. If you're running Open WebUI on Opsily managed hosting, you can pair it with a self-hosted SearXNG instance on your own machine. Start a free trial on Opsily to offload the infrastructure work.