SearXNG is a meta search engine that you run locally. It provides very fast results without a lot of fluff and tracking. You can fine-tune it to only use certain sources, search certain material types, skip social media, or even exclusively search social media. It is a fantastic tool and something anyone with the inclination and resources should consider setting up.
Setting up the Service
My setup is a lot more complicated than it absolutely has to be. But, you wouldn’t be here if you wanted the generic guide.
The Container
I’m using a container and the podman runtime (a Docker alternative that has several advantages and is my go to solution). I won’t go into details about getting your container runtime functional in this guide, though I plan to at some point in the future show how I have my setup. I am also running podman-compose to orchestrate my containers and help make management easier. Here’s what that looks like:
searxng-core:
container_name: searxng-core
image: searxng/searxng:latest
restart: always
ports:
- "8080:8080"
volumes:
- ./volumes/searxng/core-config/:/etc/searxng/:Z
- ./volumes/searxng/core-data:/var/cache/searxng/
networks:
- majel
searxng-valkey:
container_name: searxng-valkey
image: valkey/valkey:9-alpine
command: valkey-server --save 30 1 --loglevel warning
restart: always
volumes:
- ./volumes/searxng/valkey-data:/data/
networks:
- majel
networks:
majel: {}
In my case I am standardizing my compose file to use directly mounted folders, instead of runtime administered volumes. I have trust issues.
Also, I am explicitly using the majel network to keep all Project: Majel components together. I am not 100% certain this is necessary, but it works so I have not tested it further.
Accessing SearXNG
You can simply access this service now by navigating to http://localhost:8080 and running your search. For other systems on your network, assuming you open the correct firewall ports, they would go to http://<your IP address>:8080. I am particular, and would not accept something so crude, especially knowing it would be a turn off to other denizens of my network (read: family members).
DNSMasq
I will not go into all the arcane things I did to make this service work. Suffice it to say, for what lies ahead you need to have your local DNS point at your server, which should have either a static address, or at least a way to dynamically update DNS. It is for this reason I chose to use DNSMasq, though this Faustian bargain has taken many hours from my life.
Nginx Proxy
Finally, I created an Nginx proxy with a self signed certificate. In combination with the above DNS configuration I am able to use human-friendly URLs. The servername passed to the proxy is used to direct the traffic internally. This also means I do not need to expose those ports to the rest of my network. Everyone wins.
I am using this concept with all of my local services, and keep each endpoint/server as a separate config file under sites-available. Here’s my config for SearXNG:
server {
listen 80;
listen [::]:80;
server_name searxng.local;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name searxng.local;
ssl_certificate /etc/nginx/cert/local.crt;
ssl_certificate_key /etc/nginx/cert/local.key;
location / {
proxy_pass http://localhost:8080;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Setting Your Default Search Engine
In Firefox, and I assume something very similar for other browsers, go to Settings -> Search -> Add Search Engine. Enter in the following information:
- Name:
SearXNG - URL:
https://searxng.local/search?q=%s - Keyword:
@xng
I decided to make this my default search engine and have not looked back.