//------------------------------------------------------------------- //-------------------------------------------------------------------
Self-Host SearXNG Docker

How to Self-Host SearXNG with Docker, Redis, and a Secure Public JSON API

SearXNG is a free, open-source metasearch engine that gives you private search results without tracking. It can also work as a JSON search backend for AI agents and automation tools. In this guide, you will set up a self-host SearXNG Docker instance with Redis, Nginx, TLS, and a secure public JSON API.

If you need a reliable server to run this setup, you can use a lightweight Linux VPS from PerLod.

What You Need Before Starting Self-Host SearXNG Docker

To self-host SearXNG Docker instance, you need:

  • A Linux VPS running Ubuntu 22.04 or 24.04.
  • A domain name with an A record pointing to your server’s IP.
  • Root or sudo access via SSH.
  • Docker and Docker Compose are installed.
  • Ports 80 and 443 are open on your firewall.

Verify that Docker and Docker Compose are working correctly:

docker --version
docker compose version

Once everything is ready, proceed to the following steps to self-host SearXNG Docker instance.

Step 1. Create the SearXNG Project Directory

To keep everything organized, create the project directory:

mkdir -p ~/searxng/searxng
cd ~/searxng

This gives you:

  • ~/searxng/: The project root where your docker-compose.yml lives.
  • ~/searxng/searxng/: The config folder is mounted into the container.

Step 2. Create SearXNG Docker Compose File

This is the core of the self-host SearXNG Docker setup. Use your desired text editor to create the file:

nano ~/searxng/docker-compose.yml

Paste this with your domain:

services:
  redis:
    container_name: redis
    image: redis:7-alpine
    command: redis-server --save "" --appendonly no
    networks:
      - searxng
    tmpfs:
      - /var/lib/redis
    cap_drop:
      - ALL
    cap_add:
      - SETGID
      - SETUID
      - DAC_OVERRIDE
    restart: unless-stopped

  searxng:
    container_name: searxng
    image: docker.io/searxng/searxng:latest
    networks:
      - searxng
    ports:
      - "127.0.0.1:8080:8080"
    volumes:
      - ./searxng:/etc/searxng:rw
    environment:
      - SEARXNG_BASE_URL=https://search.yourdomain.com/
    restart: unless-stopped
    depends_on:
      - redis

networks:
  searxng:

This self-host SearXNG Docker layout keeps SearXNG on 127.0.0.1:8080, so it is not exposed directly to the public internet.

Redis runs without persistence here because the cache is mainly used for temporary limiter and session data in this setup.

Step 3. Configure SearXNG Settings YAML File

This SearXNG settings file controls everything from the secret key to format support.

First, generate a secret key:

openssl rand -hex 32

Copy the output. Now use the command below to create the settings file:

nano ~/searxng/searxng/settings.yml

Paste and fill in your values:

use_default_settings: true

server:
  secret_key: "PASTE_YOUR_GENERATED_KEY_HERE"
  limiter: false
  image_proxy: true
  public_instance: false
  default_http_headers:
    X-Content-Type-Options: nosniff
    X-Download-Options: noopen
    X-Robots-Tag: noindex, nofollow
    Referrer-Policy: no-referrer

valkey:
  url: redis://redis:6379/0

search:
  safe_search: 0
  autocomplete: "duckduckgo"
  default_lang: "en"
  formats:
    - html
    - json

ui:
  default_theme: simple
  infinite_scroll: false

This is the best way to start a self-host SearXNG Docker setup for testing. SearXNG supports limiter: false and public_instance: false, and that avoids local testing problems while you check that the app is working first.

The formats list must include json if you want the API to work. If json is not enabled, requests that use ?format=json can fail.

The cache setting is now uses valkey.url, because current SearXNG versions warn that redis.url is deprecated and valkey.url should be used instead.

Step 4. Configure the SearXNG Rate Limiter

When limiter: true is set in settings.yml, SearXNG looks for a limiter.toml file. You can create it:

nano ~/searxng/searxng/limiter.toml

Add this config:

[botdetection]
ipv4_prefix = 32
ipv6_prefix = 48
trusted_proxies = [
  '127.0.0.0/8',
  '::1',
  '172.16.0.0/12',
  '10.0.0.0/8',
]

[botdetection.ip_limit]
filter_link_local = false
link_token = true

[botdetection.ip_lists]
block_ip = []
pass_ip = []
pass_searxng_org = true

You will not use the limiter right away, but it is good to create the file now. Later, when you change the self-host SearXNG Docker instance from local testing to public API use, this file will help with bot protection and request control.

link_token = true helps block bad bots. Requests without a valid token can be limited or denied.

The trusted_proxies list tells SearXNG to trust your reverse proxy and use the real client IP from X-Forwarded-For.

Step 5. Start the SearXNG Containers

Now you can start your containers with the commands below:

cd ~/searxng
docker compose up -d
Start SearXNG containers

Check that both containers started:

docker compose ps
docker compose logs -f searxng
Check SearXNG container's status

If the service starts and the worker comes up, your self-host SearXNG Docker stack is running locally.

Step 6. Configure Nginx with TLS and Rate Limiting

Install Nginx and Certbot with the command below:

sudo apt install nginx certbot python3-certbot-nginx -y

Allow HTTP and HTTPS through the firewall:

sudo ufw allow 'Nginx Full'

Create the site file:

sudo nano /etc/nginx/sites-available/searxng

Paste this HTTP-only config:

server {
    listen 80;
    listen [::]:80;
    server_name search.yourdomain.com;

    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_set_header Host $host;
        proxy_set_header Connection $http_connection;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_buffering off;
    }
}

Enable it and test it:

sudo ln -s /etc/nginx/sites-available/searxng /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

This self-host SearXNG Docker flow is easier because Certbot can read the active Nginx server block and update it for HTTPS automatically.

Then, request the certificate with Certbot:

sudo certbot --nginx -d search.yourdomain.com

After that, test renewal:

sudo certbot renew --dry-run

Now your self-host SearXNG Docker service should be live over HTTPS.

https://search.yourdomain.com
SearXNG UI

After Nginx and HTTPS are working, update settings.yml for public use:

server:
  secret_key: "PASTE_YOUR_GENERATED_KEY_HERE"
  limiter: true
  image_proxy: true
  public_instance: false
  default_http_headers:
    X-Content-Type-Options: nosniff
    X-Download-Options: noopen
    X-Robots-Tag: noindex, nofollow
    Referrer-Policy: no-referrer

valkey:
  url: redis://redis:6379/0

SearXNG’s limiter is meant for protecting public instances, and it relies on the cache backend and proxy-aware client IP handling.

Restart the containers after the change:

cd ~/searxng
docker compose down
docker compose up -d

This makes your self-host SearXNG Docker setup safer before you expose the API to real users or tools.

Step 7. Use the JSON API

This is the part that makes the self-host SearXNG Docker setup useful for developers and AI pipelines. Because you added JSON to the formats list in settings.yml, you can now query the search API directly.

Basic query:

curl 'https://search.yourdomain.com/search?q=linux+vps&format=json'

With filters:

curl 'https://search.yourdomain.com/search?q=docker+tutorial&format=json&language=en&categories=general'

POST method:

curl -X POST 'https://search.yourdomain.com/search' \
  -d 'q=self+hosted+tools&format=json'

Useful API parameters include:

ParameterUse
qSearch query
formatOutput format such as json
categoriesLimit search category
enginesChoose engines
languageSet result language
pagenoChange page number
time_rangeFilter by date
safesearchSet safe search level

The self-host SearXNG Docker API returns structured results that can be used by apps, scripts, and agent workflows.

Protect a Public API Endpoint

A public search API can be abused quickly, so keep the setup simple and strict:

  • Keep public_instance: false unless you have a good reason to change it.
  • Turn limiter: true back on after HTTPS is ready.
  • Keep the proxy headers in Nginx, so SearXNG sees the real client IP.
  • Add Nginx rate limiting if your VPS is small.
  • Consider an API key header if the endpoint is only for your own tools.

Example Nginx rate limiting:

limit_req_zone $binary_remote_addr zone=searxng_limit:10m rate=10r/s;

server {
    listen 443 ssl http2;
    server_name search.yourdomain.com;

    ssl_certificate /etc/letsencrypt/live/search.yourdomain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/search.yourdomain.com/privkey.pem;

    location / {
        limit_req zone=searxng_limit burst=20 nodelay;
        limit_req_status 429;

        proxy_pass http://127.0.0.1:8080;
        proxy_set_header Host $host;
        proxy_set_header Connection $http_connection;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_buffering off;
    }
}

This self-host SearXNG Docker pattern gives you two layers of protection, including Nginx at the edge and SearXNG inside the app.

If you want a developer-only API, add a simple header check in Nginx:

location /search {
    if ($http_x_api_key != "your-secret-api-token") {
        return 403;
    }

    proxy_pass http://127.0.0.1:8080;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
}

How to Update SearXNG

To update the containers later, simply run:

cd ~/searxng
docker compose down
docker compose pull
docker compose up -d

Check the logs after each update:

docker compose logs -f searxng

Keeping the self-host SearXNG Docker stack updated helps you pick up fixes and container changes from current releases.

Conclusion

This guide gives you a practical self-host SearXNG Docker setup that starts simple and becomes safer step by step. You first verify the app locally, then add Nginx, then enable HTTPS, and only after that turn on limiter protection for a public API.

That order is easier to debug, and it fits better for small VPS deployments that need a private search page or a controlled agent-search endpoint.

If you want to run this next to AI workloads, AI hosting plans are another useful option to consider.

We hope you enjoy this guide. For more detailed information, you can check the official SearXNG admin docs.

FAQs

Does SearXNG store my search queries?

No. SearXNG does not log or store search queries by default. Redis is used only for session tokens and rate-limit counters, not search history.

Can I use SearXNG API with LangChain or n8n?

Yes. Both support SearXNG as a tool. Point them to your /search endpoint with ?format=json, and they will parse the results directly.

What if I want to restrict which search engines SearXNG uses?

Edit the engines section in settings.yml. Use disabled: true to turn off engines you do not want, or use keep_only to whitelist a small set.

Post Your Comment

PerLod delivers high-performance hosting with real-time support and unmatched reliability.

Contact us

Payment methods

payment gateway
Perlod Logo
Privacy Overview

This website uses cookies so that we can provide you with the best user experience possible. Cookie information is stored in your browser and performs functions such as recognising you when you return to our website and helping our team to understand which sections of the website you find most interesting and useful.