Introduction
SearXNG is a free internet metasearch engine which aggregates results from more than 70 search services. Users are neither tracked nor profiled.
This guide documents the specific method I used to install SearXNG on a YunoHost server using Docker. The challenge with YunoHost is that it already uses Nginx on ports 80/443. Therefore, standard Docker guides often fail or cause conflicts because they try to install "Caddy" (another web server) on the same ports.
This method runs SearXNG locally on a specific port and uses the YunoHost "Redirect" app to proxy traffic safely.
Prerequisites
- A VPS running YunoHost.
- Docker and Docker Compose installed (often standard on VPS images or installable via YunoHost).
- SSH access to the server.
- A subdomain configured in YunoHost (e.g.,
search.yourdomain.com).
Step 1: Directory Structure & Docker Compose
First, we create a clean workspace. We will place our files in /opt/searxng.
mkdir -p /opt/searxng
cd /opt/searxng
Create the docker-compose.yml file:
nano docker-compose.yml
Paste the following configuration. Note that we have removed Caddy and bound the port to localhost (127.0.0.1) only. This is a security measure so the raw container isn't exposed to the public internet directly.
version: '3.7'
services:
redis:
container_name: redis
image: redis:alpine
command: redis-server --save "" --appendonly "no"
networks:
- searxng
tmpfs:
- /var/lib/redis
cap_drop:
- ALL
cap_add:
- SETGID
- SETUID
- DAC_OVERRIDE
searxng:
container_name: searxng
image: searxng/searxng:latest
networks:
- searxng
ports:
- "127.0.0.1:8080:8080" # Binds locally. YunoHost will proxy here.
volumes:
- ./searxng:/etc/searxng:rw
environment:
- SEARXNG_BASE_URL=https://search.yourdomain.com/ # CHANGE THIS
cap_drop:
- ALL
cap_add:
- CHOWN
- SETGID
- SETUID
logging:
driver: "json-file"
options:
max-size: "1m"
max-file: "1"
networks:
searxng:
Step 2: Configuration & The "Nested Folder"
This part is crucial and where many people make mistakes. We need to create a nested folder for the settings.
Why a nested folder?
In docker-compose.yml, we have the line:
volumes: - ./searxng:/etc/searxng:rw
This maps the folder ./searxng (on the host) to /etc/searxng (inside the container). If we put the settings.yml file directly in /opt/searxng, the container will see an empty directory and fail to start.
Commands to setup config:
# Create the nested directory
mkdir searxng
# Download the default configuration file into that folder
curl -L https://raw.githubusercontent.com/searxng/searxng/master/searx/settings.yml > searxng/settings.yml
Security: Generating the Secret Key
SearXNG will not start without a unique secret key. Run this command to auto-generate one and inject it into your file:
sed -i "s|ultrasecretkey|$(openssl rand -hex 32)|g" searxng/settings.yml
Step 3: Enabling Safe Search (Optional)
If you want "Safe Search" (filtering explicit content) enabled by default for all users, you need to edit the settings file manually.
- Open the file:
bash nano searxng/settings.yml - Find the
search:section. - Change
safe_searchto 2 (Strict) or 1 (Moderate).
<!-- end list -->
search:
safe_search: 2
autocomplete: ""
default_lang: ""
Step 4: Launching the Service
Now we start the containers.
docker compose up -d
Check if it is running:
docker ps
You should see searxng running and listening on 127.0.0.1:8080.
Note: Restarting the server later will not cause search errors. Redis is configured to not save data to disk (--save ""), so the cache is cleared on restart, but the configuration remains safe.
Step 5: Exposing via YunoHost
We do not use Nginx configurations manually. We use the YunoHost admin panel.
- Log in to the YunoHost web admin.
- Go to Applications > Install.
- Search for the Redirect app.
- Configure it as follows:
- Domain:
search.yourdomain.com - URL Path:
/ - Redirect Type: Proxy (Crucial setting!)
- Destination URL:
http://127.0.0.1:8080
- Domain:
- Click Install.
Conclusion
You now have a private, privacy-respecting search engine. YunoHost handles the SSL certificates (Let's Encrypt) and the firewall, while Docker handles the application logic.
Key Takeaways learnt:
- Always bind Docker ports to
127.0.0.1when using a reverse proxy like Nginx/YunoHost to prevent bypassing the firewall. - Pay close attention to Docker
volumesmappings—the folder structure on the host must match what the container expects. - Redis cache is temporary; it is okay to clear it on reboot.