Skip to content

Instantly share code, notes, and snippets.

@elvith-de

elvith-de/.env Secret

Last active October 6, 2025 11:13
Show Gist options
  • Save elvith-de/fecd13bb05209fb7abf5ae473483534b to your computer and use it in GitHub Desktop.
Save elvith-de/fecd13bb05209fb7abf5ae473483534b to your computer and use it in GitHub Desktop.
SearXNG Quadlet + Config
SEARXNG_HOSTNAME=searxng.example.com
LETSENCRYPT_EMAIL=certbot@example.com
SEARXNG_BASE_URL=https://searxng.example.com/
[Unit]
Description=Caddy Caddyfile volume
[Volume]
VolumeName=caddy-caddyfile
[Unit]
Description=Caddy config volume
[Volume]
VolumeName=caddy-config
[Unit]
Description=Caddy data volume
[Volume]
VolumeName=caddy-data
[Unit]
Description=Caddy container
After=network-online.target
WantedBy=multi-user.target
[Container]
AutoUpdate=registry
ContainerName=caddy
EnvironmentFile=/usr/local/searxng/.env
Image=docker.io/library/caddy:2-alpine
LogDriver=json-file
LogOpt=path=/var/log/caddy/caddy.json
LogOpt=max-size=1m
LogOpt=max-file=1
Network=host
Volume=caddy-caddyfile.volume:/etc/caddy/:ro
Volume=caddy-data.volume:/data
Volume=caddy-config.volume:/config
[Service]
Restart=always
[Install]
WantedBy=default.target
{
admin off
email {$LETSENCRYPT_EMAIL}
}
{$SEARXNG_HOSTNAME} {
log {
output stderr
format filter {
resp_headers delete
request>uri query {
delete q
delete url
delete h
}
}
}
encode zstd gzip
@api {
path /config
path /healthz
path /stats/errors
path /stats/checker
}
@search {
path /search
}
@imageproxy {
path /image_proxy
}
@static {
path /static/*
}
header {
# CSP (https://content-security-policy.com)
Content-Security-Policy "upgrade-insecure-requests; default-src 'none'; script-src 'self'; style-src 'self' 'unsafe-inline'; form-action 'self' https://github.com/searxng/searxng/issues/new; font-src 'self'; frame-ancestors 'self'; base-uri 'self'; connect-src 'self' https://overpass-api.de; img-src * data:; frame-src https://www.youtube-nocookie.com https://player.vimeo.com https://www.dailymotion.com https://www.deezer.com https://www.mixcloud.com https://w.soundcloud.com https://embed.spotify.com;"
# Disable some browser features
Permissions-Policy "accelerometer=(),camera=(),geolocation=(),gyroscope=(),magnetometer=(),microphone=(),payment=(),usb=()"
# Set referrer policy
Referrer-Policy "no-referrer"
# Force clients to use HTTPS
Strict-Transport-Security "max-age=31536000"
# Prevent MIME type sniffing from the declared Content-Type
X-Content-Type-Options "nosniff"
# X-Robots-Tag (comment to allow site indexing)
X-Robots-Tag "noindex, noarchive, nofollow"
# Remove "Server" header
-Server
}
header @api {
Access-Control-Allow-Methods "GET, OPTIONS"
Access-Control-Allow-Origin "*"
}
route {
# Cache policy
header Cache-Control "max-age=0, no-store"
header @search Cache-Control "max-age=5, private"
header @imageproxy Cache-Control "max-age=604800, public"
header @static Cache-Control "max-age=31536000, public, immutable"
}
# SearXNG (uWSGI)
reverse_proxy localhost:8088 {
header_up X-Forwarded-Port {http.request.port}
header_up X-Real-IP {http.request.remote.host}
# https://github.com/searx/searx-docker/issues/24
header_up Connection "close"
}
}
[favicons]
cfg_schema = 1 # config's schema version no.
[favicons.cache]
db_url = "/tmp/faviconcache.db" # default: "/tmp/faviconcache.db"
LIMIT_TOTAL_BYTES = 2147483648 # 2 GB / default: 50 MB
HOLD_TIME = 2592000 # default: 30 days
BLOB_MAX_BYTES = 40960 # 40 KB / default 20 KB
MAINTENANCE_MODE = "auto" # default: "auto"
MAINTENANCE_PERIOD = 6000 # default: 1h

This is assuming a deployment like the official searxng-dockercompose.yaml with Caddy included. You may ignore all things Caddy related if you do not use a reverse proxy or want to use your own reverse proxy. Note: If omitting the reverse proxy or changing to another one you may need to adjust the limiter config (or switch it off for a private loacl deployment).

Caddy will be deployed in the host network, the other containers will reside in the searxng network.

This is not 100% up to date to the current state of the example-repository, but "works for me". I'm constantly adjusting things and I'm currently also trying to port this to rootless podman - but I'm struggeling to get eversthing deployed and running with Ansible. There might be adjustments needed when running this rootless.
Another thing "under construction" for this ist to put this together in a pod for easier management, but I need to seperate some services/containers first in my deployment...

How to deploy (assuming you're NOT using rootless podman. If so, read below):

  1. Create/download all those files
  2. Enter your domain, mail adress and base url in .env
  3. adjust settings.yaml - if deploying privately (e.g. at home) you can turn off the limiter - and also omit the limiter.toml. If this instance is (theoretically) reachable from the internet, maybe leave it on...
  4. don't forget to set a random secret key in the settings.yaml - e.g. by doing sed -i "s|ultrasecretkey|$(openssl rand -hex 32)|g" settings.yml
  5. If you use another reverse proxy (config) AND use the limiter, you might need to check the limiter.toml so that everything works as expected. Also you might want to remove the caddy.service from line 4 in searxng.container then.
  6. Create a directory - e.g /usr/local/searxng/ and put the .env there
  7. Put the Caddyfile in /var/lib/containers/storage/volumes/caddy-caddyfile/_data/
  8. Put favicons.toml, /settings.yml and limiter.toml (if using the limiter) to /var/lib/containers/storage/volumes/searxng/_data/
  9. Put *.container, *.network and *.volume files in /etc/containers/systemd/
  10. Reload systemd units with sudo systemctl daemon-reload
  11. Start searxng with sudo systemctl start searxng

Note, if using rootless podman, you need to change /var/lib/containers/storage/volumes to ~/.local/share/containers/storage/volumes in all paths above. And you need to change /etc/containers/systemd/ to e.g. ~/.config/containers/systemd/.

[real_ip]
# Number of values to trust for X-Forwarded-For.
x_for = 1
# 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
[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
[Unit]
Description=Redis container
After=network-online.target
[Container]
AutoUpdate=registry
AddCapability=SETGID SETUID DAC_OVERRIDE
ContainerName=redis
DropCapability=ALL
Exec=valkey-server --save 30 1 --loglevel warning
Image=docker.io/valkey/valkey:8-alpine
LogDriver=json-file
Network=searxng.network
PodmanArgs=--log-opt 'max-size=1m' --log-opt 'max-file=1'
Volume=valkey-data2:/data
[Service]
Restart=always
[Install]
WantedBy=default.target
[Unit]
Description=Searxng container
After=network-online.target redis.service
Requires=redis.service caddy.service
[Container]
AutoUpdate=registry
AddCapability=CHOWN SETGID SETUID
ContainerName=searxng
EnvironmentFile=/usr/local/searxng/.env
Image=docker.io/searxng/searxng:latest
LogDriver=json-file
Network=searxng.network
PodmanArgs=--log-opt 'max-size=1m' --log-opt 'max-file=1'
PublishPort=127.0.0.1:8088:8080
Volume=searxng.volume:/etc/searxng
[Service]
Restart=always
[Install]
WantedBy=default.target
[Network]
Label=app=searxng
[Unit]
Description=Searxng config volume
[Volume]
VolumeName=searxng
# 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
secret_key: "ultrasecretkey" # change this!
limiter: true # can be disabled for a private instance
image_proxy: true
method: "GET"
public_instance: false # you can enable this, but if this is not listed as public and just accessible on a random public URL, you might want to leave this on false.
ui:
static_use_hash: true
infinite_scroll: false
default_locale: "en"
theme_args:
# style of simple theme: auto, light, dark
simple_style: dark
query_in_title: true
redis:
url: redis://redis:6379/0
search:
favicon_resolver: "duckduckgo"
autocomplete: "duckduckgo"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment