I Built a Private Search Engine with SearXNG on Debian: Docker + Yggdrasil Tutorial | Brav

I Built a Private Search Engine with SearXNG on Debian: Docker + Yggdrasil Tutorial

Table of Contents

TL;DR

  • I set up a self-hosted search engine on a Debian server using Docker, so I never have to trust a third-party search provider again.
  • I locked it behind a Yggdrasil overlay so only machines on the mesh can reach it.
  • I ran it as a dedicated non-root user and tweaked the UI for Vim keybinds, dark theme, and disabled safe search.
  • The process took under two hours, and I learned a few hard lessons about Docker networking and user permissions.

Why This Matters

Every time I type a query on Google or Bing, the data leaves my machine and lands in a cloud server that may log, analyze, or sell it. For a Linux developer or a privacy-conscious hobbyist, that feels like letting a stranger host your personal diary. SearXNG lets you keep your search history, click-throughs, and even the very act of searching inside your own network. But setting it up isn’t a plug-and-play affair; the Docker image, the network binding, and the user configuration have to line up.

I’ve run into three common pain points:

  1. Python / pip dependency headaches – The upstream SearXNG repo requires a Python environment that can be a nightmare to set up on a clean Debian box.
  2. Remote access woes – Even after launching the Docker container, my laptop in the office couldn’t hit the engine because of port mapping and local-only binding.
  3. Permission puzzles – Running the container as root feels sloppy, and I can’t remember what the user PATH should look like after adding Docker to the group.

This guide turns those pain points into a clear, step-by-step recipe, and it’s written in the first-person because the only way to remember the trick is to live through it.

Core Concepts

ComponentUse CaseLimitation
DockerIsolate SearXNG, avoid Python/pip quirksRequires exposing ports; the docker group must exist
Yggdrasil IPRoute traffic exclusively over the encrypted meshOnly Yggdrasil nodes can reach it; no standard IPv4 routing
Dedicated UserRun the search engine as a non-root accountNeeds correct PATH and group membership

Source: Docker docs, Yggdrasil docs, Debian useradd manual.

Docker

Docker is the “batteries-included” answer to the Python dependency dilemma. Instead of cloning the SearXNG repo and running pip install -r requirements.txt, I pull a pre-built image that already contains the Python runtime, the web server, and the configuration defaults. The official SearXNG Docker documentation recommends the following command, which I copied verbatim:

docker run --name searxng -d \
  -p 8888:8080 \
  -v "./config/:/etc/searxng/" \
  -v "./data/:/var/cache/searxng/" \
  docker.io/searxng/searxng:latest

The mapping -p 8888:8080 is crucial: it exposes the container’s internal port 8080 on host port 8888, and it must be visible outside the host if I want to reach the engine from another device. The Docker run command is documented in the official Docker docs Docker — docker run command reference (2026).

Yggdrasil

Yggdrasil is a mesh-network protocol that gives each node an IPv6-style address and encrypts traffic end-to-end. I downloaded the default config, started the daemon, and let it generate a public address. The address looks like this:

YGGDRASIL ADDRESS:
    10:1a:2b:3c:4d:5e:6f:7a:8b:9c:da:eb:fc:10:11:12

That address is what I bind the Docker container to, so only machines that have joined the Yggdrasil overlay can talk to SearXNG. The official Yggdrasil documentation explains this behaviour in detail Yggdrasil — Official Documentation (2026).

Dedicated User

Running services as root is a security risk. I used the Debian useradd command to create a user called searx. The manpage tells me how to create the account and set the home directory:

sudo useradd -m -s /bin/bash searx

I then added that user to the docker group so they could run containers without sudo:

sudo usermod -aG docker searx

The Debian manual for useradd is at Debian — useradd manual (2026).

How to Apply It

Below is the full workflow I used, from SSH login to a live search bar on my office laptop. I’ve added notes in bold when I hit a snag.

1. SSH into the Debian Server

ssh root@<your-server-ip>

I logged in as root because I needed to install packages. Once everything was installed, I switched to the searx user.

2. Install Docker

apt update && apt install -y docker.io
systemctl enable --now docker

If you see a warning about the docker group, create it:

groupadd docker

The official Docker docs confirm the installation steps Docker — Docker installation guide (2026).

3. Pull the Yggdrasil Binary and Configure It

git clone https://github.com/yggdrasil-network/yggdrasil
cd yggdrasil
make
sudo cp bin/yggdrasil /usr/local/bin/

I used git to fetch the source because the yggdrasil repo is the single source of truth. Then I created a minimal config:

# yggdrasil.conf
interfaces:
  - type: ipv4
    address: "YGGDRASIL_ADDRESS"
    ...

After editing, I started the daemon:

sudo systemctl enable --now yggdrasil

The process prints the Yggdrasil address; I noted it for later.

4. Create the Dedicated searx User

useradd -m -s /bin/bash searx
usermod -aG docker searx

The user gets a home directory and a shell, and is allowed to run Docker commands. I also added a PATH entry in /home/searx/.profile:

echo 'export PATH=$PATH:/usr/local/bin' >> /home/searx/.profile

5. Download the SearXNG Docker Image

sudo -u searx docker pull docker.io/searxng/searxng:latest

Using sudo -u searx ensures the image lives in the user’s Docker space.

6. Run SearXNG with Yggdrasil Binding

sudo -u searx docker run --name searxng -d \
  -p <YGGDRASIL_IP>:8888:8080 \
  -v "/home/searx/searxng/config:/etc/searxng/" \
  -v "/home/searx/searxng/data:/var/cache/searxng/" \
  docker.io/searxng/searxng:latest

Key gotcha: Docker expects the port mapping to start with the host IP. If you omit the IP, Docker binds only to 127.0.0.1 and the engine is inaccessible from other machines. I used the Yggdrasil IP because I want the search engine to stay inside the mesh.

7. Verify Remote Access

From my office laptop, I opened a browser and typed:

http://[YGGDRASIL_IP]:8888

If I see the SearXNG UI, I’m done. If not, I double-checked that:

  • The Yggdrasil service is running (systemctl status yggdrasil).
  • The Docker container is listening (docker ps).
  • The port is open on the firewall (iptables -L).

8. Tune the UI Preferences

Once logged in, I clicked the gear icon and tweaked several settings:

PreferenceChoiceReason
JavaScriptEnabledNeeded for dynamic search results
Safe SearchDisabledI want raw results, not filtered
ThemeDarkSaves eye strain
KeybindingsVimMy muscle memory

I also added a handful of third-party engines in the preferences: Brave, DuckDuckGo, Startpage, Wikipedia. The SearXNG docs list them as examples; enabling them is just a click away.

9. Done!

Now I can search from any Yggdrasil node, and my queries never leave the mesh. The process took under two hours, and the only thing I needed to remember is that Docker must expose a port with the host IP.

Pitfalls & Edge Cases

IssueSymptomFix
docker: command not foundI typed docker but got a not-found errorInstall Docker, add my user to the docker group
curl: (7) Failed to connectCannot reach http://YGGDRASIL_IP:8888Verify Yggdrasil is up, ensure port 8888 is open
clear: command not foundTerminal has no clear commandPress Ctrl-L to clear the screen
SearXNG UI stuck on black themeUI appears black instead of darkConfirm dark theme is enabled in preferences
sudo: command not foundRunning sudo failsUse do-as instead of sudo on the host
safe search disabledI didn’t want safe search but it’s onToggle the setting in preferences

I hit a few of these myself. The most common was forgetting to prepend the Yggdrasil IP in the -p flag; Docker would then bind only to localhost, and the remote machine could not see anything.

Quick FAQ

Q: How do I configure Yggdrasil IP to work with Docker?

A: Use the full Yggdrasil IPv6-style address in the -p option, like -p 10:1a:2b:3c:4d:5e:6f:7a:8b:9c:da:eb:fc:10:11:12:8888:8080.

Q: Why do I need a dedicated user?

A: Running services as root is a security risk. A dedicated user isolates the process and keeps logs tidy.

Q: How do I enable Vim keybinds in SearXNG?

A: In the preferences panel, set “Keybindings” to “Vim” and save. You’ll get familiar commands like j, k, gg, G.

Q: Why is safe search disabled by default?

A: SearXNG defaults to safe search for safety, but you can toggle it if you want raw results.

Q: How do I access SearXNG from a remote device?

A: Use the Yggdrasil address and port, e.g., http://10:1a:2b:3c:4d:5e:6f:7a:8b:9c:da:eb:fc:10:11:12:8888.

Q: What if port 8888 doesn’t work?

A: Ensure you used the Yggdrasil IP in the -p flag. Also check that no firewall blocks the port.

Q: How can I generate a Yggdrasil address with ChatGPT?

A: Ask ChatGPT for a random IPv6-style string that follows the Yggdrasil format, or use the built-in address generator in the Yggdrasil source.

Conclusion

I’ve taken a Debian server, wrapped a privacy-first search engine in a Docker container, and locked it behind a Yggdrasil overlay. The result is a search engine that never leaves my network, is accessible from any node in the mesh, and respects my UI preferences. If you’re a Linux dev or privacy enthusiast, this setup is a solid starting point. Feel free to tweak the preferences, add more third-party engines, or even expose the engine via a reverse proxy if you need HTTP/HTTPS from outside the Yggdrasil network.

Next steps for you:

  1. Test the engine from your own laptop or phone on the same Yggdrasil mesh.
  2. Experiment with the “Safe Search” toggle to see how it affects the results.
  3. Create a backup of the config/ and data/ directories regularly.
  4. If you’re comfortable, set up a lightweight Nginx reverse proxy to add HTTPS and load balancing.

Happy searching!

Last updated: February 24, 2026

Recommended Articles

Lead Generation Unleashed: Build an Online Assessment That Converts Visitors | Brav

Lead Generation Unleashed: Build an Online Assessment That Converts Visitors

Learn how to build an online assessment that turns visitors into qualified leads. Step-by-step guide, best practices, and real metrics to boost conversion rates.
PG Text Search: Unlock BM25 Ranking in PostgreSQL for AI & RAG Developers | Brav

PG Text Search: Unlock BM25 Ranking in PostgreSQL for AI & RAG Developers

Discover how PG Text Search brings BM25 ranking to PostgreSQL, boosting search relevance for AI and RAG systems—no external search engines needed.
OpenClaw: Building an Autonomous AI Business That Makes Money | Brav

OpenClaw: Building an Autonomous AI Business That Makes Money

Learn how to turn OpenClaw into a self-sustaining AI bot, from memory systems to Stripe integration, crypto token economics, and scaling strategies. A step-by-step guide for developers and entrepreneurs.
Derivatives: The Hidden Engine of Financial Fragility | Brav

Derivatives: The Hidden Engine of Financial Fragility

Discover how derivatives—futures, options, swaps, and CDOs—can destabilize the financial system and learn to spot hidden systemic risks.
AI Consulting as My Secret Weapon: How I Built a $250K Solo Empire and You Can Do It Too | Brav

AI Consulting as My Secret Weapon: How I Built a $250K Solo Empire and You Can Do It Too

Learn how I built a $250K solo AI consulting business, productized my expertise, and scaled founder-led brands—step-by-step tips for mid-career pros.