aboutsummaryrefslogtreecommitdiff
path: root/roles/searxng
diff options
context:
space:
mode:
authorMiguel Dalberto Pedro <miguel.pedro@precisioninno.com>2026-10-29 12:48:06 -0300
committerMiguel Dalberto Pedro <miguel.pedro@precisioninno.com>2026-10-29 12:48:06 -0300
commit4b7379914a1865f07b2c54252234cc90158fc253 (patch)
treea476c7e08bb994034d7d04b5b1cdfce216f49c43 /roles/searxng
downloadmy-infra-4b7379914a1865f07b2c54252234cc90158fc253.tar.gz
my-infra-4b7379914a1865f07b2c54252234cc90158fc253.zip
feat(iac): establish Ansible baseline for Nginx, SearXNG, Valkey, and Certbot
- Reverse-engineer live Debian 13 (trixie) VPS state at miguelpedro.xyz.br - Add modular Ansible roles: common, certbot, valkey, searxng, and nginx - Encrypt SearXNG secret_key using ansible-vault in group_vars/all/vault.yml - Cleanly remove unused example.com Nginx stub symlink (sites-enabled/miguelpedro.xyz.br) - Scaffold cgit + fcgiwrap role (cgit_enabled: false) for upcoming deployment - Add DISCOVERY_REPORT.md, COMMAND_LOG.md, README.md, and AGENT_INSTRUCTIONS.md with Self-Updating Protocol
Diffstat (limited to 'roles/searxng')
-rw-r--r--roles/searxng/handlers/main.yml5
-rw-r--r--roles/searxng/tasks/main.yml84
-rw-r--r--roles/searxng/templates/limiter.toml.j249
-rw-r--r--roles/searxng/templates/settings.yml.j225
-rw-r--r--roles/searxng/templates/uwsgi-searxng.ini.j278
5 files changed, 241 insertions, 0 deletions
diff --git a/roles/searxng/handlers/main.yml b/roles/searxng/handlers/main.yml
new file mode 100644
index 0000000..e049618
--- /dev/null
+++ b/roles/searxng/handlers/main.yml
@@ -0,0 +1,5 @@
+---
+- name: Restart uwsgi
+ ansible.builtin.service:
+ name: uwsgi
+ state: restarted
diff --git a/roles/searxng/tasks/main.yml b/roles/searxng/tasks/main.yml
new file mode 100644
index 0000000..c7d45d4
--- /dev/null
+++ b/roles/searxng/tasks/main.yml
@@ -0,0 +1,84 @@
+---
+- name: Ensure searxng system group exists
+ ansible.builtin.group:
+ name: "{{ searxng_group }}"
+ gid: "{{ searxng_gid }}"
+ system: true
+ state: present
+
+- name: Ensure searxng system user exists
+ ansible.builtin.user:
+ name: "{{ searxng_user }}"
+ uid: "{{ searxng_uid }}"
+ group: "{{ searxng_group }}"
+ groups: sudo
+ append: true
+ comment: "Privacy-respecting metasearch engine"
+ home: "{{ searxng_home }}"
+ shell: /bin/bash
+ system: true
+ state: present
+
+- name: Ensure SearXNG directories exist
+ ansible.builtin.file:
+ path: "{{ item.path }}"
+ state: directory
+ owner: "{{ item.owner }}"
+ group: "{{ item.group }}"
+ mode: "{{ item.mode }}"
+ loop:
+ - { path: "{{ searxng_home }}", owner: "{{ searxng_user }}", group: "{{ searxng_group }}", mode: "0755" }
+ - { path: "{{ searxng_home }}/.ansible/tmp", owner: "{{ searxng_user }}", group: "{{ searxng_group }}", mode: "0700" }
+ - { path: "{{ searxng_run_dir }}", owner: "{{ searxng_user }}", group: "{{ searxng_group }}", mode: "0755" }
+ - { path: "/etc/searxng", owner: "root", group: "root", mode: "0755" }
+ - { path: "/etc/uwsgi/apps-available", owner: "root", group: "root", mode: "0755" }
+ - { path: "/etc/uwsgi/apps-enabled", owner: "root", group: "root", mode: "0755" }
+
+- name: Clone or update SearXNG source repository
+ ansible.builtin.git:
+ repo: "{{ searxng_git_repo }}"
+ dest: "{{ searxng_src_dir }}"
+ version: "{{ searxng_git_version }}"
+ update: false
+ become: true
+ become_user: "{{ searxng_user }}"
+
+- name: Deploy /etc/searxng/settings.yml
+ ansible.builtin.template:
+ src: settings.yml.j2
+ dest: /etc/searxng/settings.yml
+ owner: "{{ searxng_user }}"
+ group: "{{ searxng_group }}"
+ mode: "0640"
+ notify: Restart uwsgi
+
+- name: Deploy /etc/searxng/limiter.toml
+ ansible.builtin.template:
+ src: limiter.toml.j2
+ dest: /etc/searxng/limiter.toml
+ owner: "{{ searxng_user }}"
+ group: "{{ searxng_group }}"
+ mode: "0644"
+ notify: Restart uwsgi
+
+- name: Deploy uWSGI app configuration for SearXNG
+ ansible.builtin.template:
+ src: uwsgi-searxng.ini.j2
+ dest: /etc/uwsgi/apps-available/searxng.ini
+ owner: root
+ group: root
+ mode: "0644"
+ notify: Restart uwsgi
+
+- name: Enable uWSGI SearXNG app symlink
+ ansible.builtin.file:
+ src: /etc/uwsgi/apps-available/searxng.ini
+ dest: /etc/uwsgi/apps-enabled/searxng.ini
+ state: link
+ notify: Restart uwsgi
+
+- name: Ensure uwsgi service is enabled and running
+ ansible.builtin.service:
+ name: uwsgi
+ enabled: true
+ state: started
diff --git a/roles/searxng/templates/limiter.toml.j2 b/roles/searxng/templates/limiter.toml.j2
new file mode 100644
index 0000000..0b40bf8
--- /dev/null
+++ b/roles/searxng/templates/limiter.toml.j2
@@ -0,0 +1,49 @@
+[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
diff --git a/roles/searxng/templates/settings.yml.j2 b/roles/searxng/templates/settings.yml.j2
new file mode 100644
index 0000000..ae23d6f
--- /dev/null
+++ b/roles/searxng/templates/settings.yml.j2
@@ -0,0 +1,25 @@
+# SearXNG settings
+
+use_default_settings: true
+
+general:
+ debug: false
+ instance_name: "{{ searxng_instance_name }}"
+
+search:
+ safe_search: 0
+ autocomplete: "duckduckgo"
+ formats:
+ - html
+ - json
+
+server:
+ # Is overwritten by ${SEARXNG_SECRET}
+ secret_key: "{{ searxng_secret_key }}"
+ limiter: true
+ image_proxy: true
+ base_url: {{ searxng_base_url }}
+
+valkey:
+ # URL to connect valkey database. Is overwritten by ${SEARXNG_VALKEY_URL}.
+ url: {{ searxng_valkey_url }}
diff --git a/roles/searxng/templates/uwsgi-searxng.ini.j2 b/roles/searxng/templates/uwsgi-searxng.ini.j2
new file mode 100644
index 0000000..87e333f
--- /dev/null
+++ b/roles/searxng/templates/uwsgi-searxng.ini.j2
@@ -0,0 +1,78 @@
+# -*- mode: conf; coding: utf-8 -*-
+[uwsgi]
+
+# uWSGI core
+# ----------
+#
+# https://uwsgi-docs.readthedocs.io/en/latest/Options.html#uwsgi-core
+
+# Who will run the code / Hint: in emperor-tyrant mode uid & gid setting will be
+# ignored [1]. Mode emperor-tyrant is the default on fedora (/etc/uwsgi.ini).
+#
+# [1] https://uwsgi-docs.readthedocs.io/en/latest/Emperor.html#tyrant-mode-secure-multi-user-hosting
+#
+uid = {{ searxng_user }}
+gid = {{ searxng_group }}
+
+# set (python) default encoding UTF-8
+env = LANG=C.UTF-8
+env = LANGUAGE=C.UTF-8
+env = LC_ALL=C.UTF-8
+
+# chdir to specified directory before apps loading
+chdir = {{ searxng_src_dir }}/searx
+
+# SearXNG configuration (settings.yml)
+env = SEARXNG_SETTINGS_PATH=/etc/searxng/settings.yml
+
+# disable logging for privacy
+disable-logging = true
+
+# The right granted on the created socket
+chmod-socket = 666
+
+# Plugin to use and interpreter config
+single-interpreter = true
+
+# enable master process
+master = true
+
+# load apps in each worker instead of the master
+lazy-apps = true
+
+# load uWSGI plugins
+plugin = python3,http
+
+# By default the Python plugin does not initialize the GIL. This means your
+# app-generated threads will not run. If you need threads, remember to enable
+# them with enable-threads. Running uWSGI in multithreading mode (with the
+# threads options) will automatically enable threading support. This *strange*
+# default behaviour is for performance reasons.
+enable-threads = true
+
+# Number of workers (usually CPU count)
+workers = %k
+threads = 4
+
+# plugin: python
+# --------------
+#
+# https://uwsgi-docs.readthedocs.io/en/latest/Options.html#plugin-python
+
+# load a WSGI module
+module = searx.webapp
+
+# set PYTHONHOME/virtualenv
+virtualenv = {{ searxng_venv_dir }}
+
+# add directory (or glob) to pythonpath
+pythonpath = {{ searxng_src_dir }}
+
+
+# speak to upstream
+# -----------------
+
+socket = {{ searxng_socket_path }}
+buffer-size = 8192
+
+offload-threads = %k