Skip to main content
SearXNG

SearXNG #

Self-host using: searxng/searxng-docker: The docker-compose files for setting up a SearXNG instance with docker.

Docker setup #

Tree:

# tree --dirsfirst -L 2 .
.
├── searxng
│   ├── limiter.toml
│   └── settings.yml
├── docker-compose.yml
└── searxng-docker.service.template

Docker compose file:

docker-compose.yml yaml
services:
  redis:
    container_name: redis
    image: docker.io/valkey/valkey:8-alpine
    command: valkey-server --save 30 1 --loglevel warning
    restart: unless-stopped
    networks:
      - searxng
    volumes:
      - valkey-data2:/data
    logging:
      driver: "json-file"
      options:
        max-size: "1m"
        max-file: "1"

  searxng:
    container_name: searxng
    image: docker.io/searxng/searxng:latest
    restart: unless-stopped
    networks:
      - searxng
    ports:
      - 5502:8080
    volumes:
      - ./searxng:/etc/searxng:rw
      - searxng-data:/var/cache/searxng:rw
    environment:
      - SEARXNG_BASE_URL=https://${SEARXNG_HOSTNAME:-localhost}/
    logging:
      driver: "json-file"
      options:
        max-size: "1m"
        max-file: "1"

networks:
  searxng:

volumes:
  valkey-data2:
  searxng-data:

Docker service template:

searxng-docker.service.template sh
[Unit]
Description=SearXNG service
Requires=docker.service
After=docker.service

[Service]
Restart=on-failure

Environment=SEARXNG_DOCKERCOMPOSEFILE=docker-compose.yaml

WorkingDirectory=/usr/local/searxng-docker
ExecStart=/usr/local/bin/docker compose -f ${SEARXNG_DOCKERCOMPOSEFILE} up --remove-orphans
ExecStop=/usr/local/bin/docker compose -f ${SEARXNG_DOCKERCOMPOSEFILE} down

[Install]
WantedBy=multi-user.target

Settings:

./searxng/settings.yml yaml
# see https://docs.searxng.org/admin/settings/settings.html#settings-use-default-settings
use_default_settings: true
server:
  # base_url is defined in the SEARXNG_BASE_URL environment variable, see .env and docker-compose.yml
  base_url: "https://search.your.domain"
  secret_key: "123456"  # change this!
  limiter: true  # enable this when running the instance for a public usage on the internet
  image_proxy: true
redis:
  url: redis://redis:6379/0
search:
  safe_search: 0
  autocomplete: ""
  default_lang: ""
  formats:
    - html
    - json

Limiter:

./searxng/limiter.toml toml
# See https://github.com/searxng/searxng/blob/master/searx/limiter.toml

[botdetection]

# The prefix defines the number of leading bits in an address that are compared
# to determine whether or not an address is part of a (client) network.

ipv4_prefix = 32
ipv6_prefix = 48

# If the request IP is in trusted_proxies list, the client IP address is
# extracted from the X-Forwarded-For and X-Real-IP headers. This should be
# used if SearXNG is behind a reverse proxy or load balancer.

trusted_proxies = [
  '127.0.0.0/8',
  '::1',
  # '192.168.0.0/16',
  # '172.16.0.0/12',
  # '10.0.0.0/8',
  # 'fd00::/8',
]

[botdetection.ip_limit]

# To get unlimited access in a local network, by default link-local addresses
# (networks) are not monitored by the ip_limit
filter_link_local = false

# activate link_token method in the ip_limit method
link_token = false

[botdetection.ip_lists]

# In the limiter, the ip_lists method has priority over all other methods -> if
# an IP is in the pass_ip list, it has unrestricted access and it is also not
# checked if e.g. the "user agent" suggests a bot (e.g. curl).

block_ip = [
  # '93.184.216.34',  # IPv4 of example.org
  # '257.1.1.1',      # invalid IP --> will be ignored, logged in ERROR class
]

pass_ip = [
  # '192.168.0.0/16',      # IPv4 private network
  # 'fe80::/10'            # IPv6 linklocal / wins over botdetection.ip_limit.filter_link_local
]

# Activate passlist of (hardcoded) IPs from the SearXNG organization,
# e.g. `check.searx.space`.
pass_searxng_org = true

nginx setup #

/etc/nginx/sites-available/searxng.conf sh
server {
    server_name searxng.your.domain;

    listen 443 ssl;
    ssl_certificate /ADMIN/https-certs/all.your.domain.public.pem;
    ssl_certificate_key /ADMIN/https-certs/all.your.domain.private.key;

  location / {
    proxy_pass http://localhost:5502/;
    
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    
    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;
    proxy_set_header X-Forwarded-Host $host;
    proxy_set_header X-Forwarded-Port $server_port;
    
    proxy_connect_timeout 60s;
    proxy_send_timeout 60s;
    proxy_read_timeout 60s;
    
    proxy_buffering on;
    proxy_buffer_size 4k;
    proxy_buffers 8 4k;
    proxy_busy_buffers_size 8k;
    
    proxy_redirect off;
    proxy_cache_bypass $http_upgrade;
  }
}

Usage:

sudo vim /etc/nginx/sites-available/searxng.conf
sudo ln -s /etc/nginx/sites-available/searxng.conf /etc/nginx/sites-enabled/searxng.conf