aboutsummaryrefslogtreecommitdiff
path: root/roles
diff options
context:
space:
mode:
Diffstat (limited to 'roles')
-rw-r--r--roles/certbot/tasks/main.yml23
-rw-r--r--roles/cgit/tasks/main.yml47
-rw-r--r--roles/cgit/templates/cgitrc.j226
-rw-r--r--roles/cgit/templates/site-cgit.conf.j221
-rw-r--r--roles/common/tasks/main.yml26
-rw-r--r--roles/nginx/handlers/main.yml11
-rw-r--r--roles/nginx/tasks/main.yml87
-rw-r--r--roles/nginx/templates/default-app-searxng.conf.j223
-rw-r--r--roles/nginx/templates/nginx.conf.j284
-rw-r--r--roles/nginx/templates/site-default.conf.j2173
-rw-r--r--roles/nginx/templates/site-searxng.conf.j247
-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
-rw-r--r--roles/valkey/tasks/main.yml12
17 files changed, 821 insertions, 0 deletions
diff --git a/roles/certbot/tasks/main.yml b/roles/certbot/tasks/main.yml
new file mode 100644
index 0000000..02e8c0b
--- /dev/null
+++ b/roles/certbot/tasks/main.yml
@@ -0,0 +1,23 @@
+---
+- name: Ensure Certbot and Nginx plugin are installed
+ ansible.builtin.apt:
+ name:
+ - certbot
+ - python3-certbot-nginx
+ state: present
+
+- name: Ensure certbot renewal timer is enabled and active
+ ansible.builtin.systemd:
+ name: certbot.timer
+ enabled: true
+ state: started
+
+- name: Verify primary domain TLS certificate exists
+ ansible.builtin.stat:
+ path: "/etc/letsencrypt/live/{{ primary_domain }}/fullchain.pem"
+ register: primary_cert
+
+- name: Verify SearXNG domain TLS certificate exists
+ ansible.builtin.stat:
+ path: "/etc/letsencrypt/live/{{ searxng_domain }}/fullchain.pem"
+ register: searxng_cert
diff --git a/roles/cgit/tasks/main.yml b/roles/cgit/tasks/main.yml
new file mode 100644
index 0000000..44f9459
--- /dev/null
+++ b/roles/cgit/tasks/main.yml
@@ -0,0 +1,47 @@
+---
+- name: Install cgit and FastCGI dependencies
+ ansible.builtin.apt:
+ name:
+ - cgit
+ - fcgiwrap
+ - python3-pygments
+ - python3-markdown
+ state: present
+
+- name: Ensure Git repositories root directory exists
+ ansible.builtin.file:
+ path: "{{ cgit_repos_path }}"
+ state: directory
+ owner: www-data
+ group: www-data
+ mode: "0755"
+
+- name: Deploy /etc/cgitrc configuration
+ ansible.builtin.template:
+ src: cgitrc.j2
+ dest: /etc/cgitrc
+ owner: root
+ group: root
+ mode: "0644"
+
+- name: Ensure fcgiwrap socket/service is enabled and running
+ ansible.builtin.systemd:
+ name: fcgiwrap.socket
+ enabled: true
+ state: started
+
+- name: Deploy Nginx virtual host for cgit
+ ansible.builtin.template:
+ src: site-cgit.conf.j2
+ dest: /etc/nginx/sites-available/cgit.conf
+ owner: root
+ group: root
+ mode: "0644"
+ notify: Reload nginx
+
+- name: Enable Nginx virtual host for cgit
+ ansible.builtin.file:
+ src: /etc/nginx/sites-available/cgit.conf
+ dest: /etc/nginx/sites-enabled/cgit.conf
+ state: link
+ notify: Reload nginx
diff --git a/roles/cgit/templates/cgitrc.j2 b/roles/cgit/templates/cgitrc.j2
new file mode 100644
index 0000000..0cae2ab
--- /dev/null
+++ b/roles/cgit/templates/cgitrc.j2
@@ -0,0 +1,26 @@
+# /etc/cgitrc - Managed by Ansible
+css=/cgit-css/cgit.css
+logo=/cgit-css/cgit.png
+favicon=/cgit-css/favicon.ico
+
+root-title={{ cgit_title }}
+root-desc={{ cgit_description }}
+virtual-root=/
+
+enable-index-links=1
+enable-index-owner=0
+enable-commit-graph=1
+enable-log-filecount=1
+enable-log-linecount=1
+snapshots=tar.gz zip
+
+about-filter=/usr/lib/cgit/filters/about-formatting.sh
+source-filter=/usr/lib/cgit/filters/syntax-highlighting.py
+
+readme=:README.md
+readme=:readme.md
+readme=:README.rst
+readme=:README.txt
+readme=:README
+
+scan-path={{ cgit_repos_path }}
diff --git a/roles/cgit/templates/site-cgit.conf.j2 b/roles/cgit/templates/site-cgit.conf.j2
new file mode 100644
index 0000000..557c364
--- /dev/null
+++ b/roles/cgit/templates/site-cgit.conf.j2
@@ -0,0 +1,21 @@
+server {
+ listen 80;
+ listen [::]:80;
+ server_name {{ cgit_domain }};
+
+ root /usr/share/cgit;
+ try_files $uri @cgit;
+
+ location ~* ^/cgit-css/(.*)$ {
+ alias /usr/share/cgit/$1;
+ }
+
+ location @cgit {
+ include fastcgi_params;
+ fastcgi_param SCRIPT_FILENAME /usr/lib/cgit/cgit.cgi;
+ fastcgi_param PATH_INFO $uri;
+ fastcgi_param QUERY_STRING $args;
+ fastcgi_param HTTP_HOST $server_name;
+ fastcgi_pass unix:/run/fcgiwrap.socket;
+ }
+}
diff --git a/roles/common/tasks/main.yml b/roles/common/tasks/main.yml
new file mode 100644
index 0000000..413a3dd
--- /dev/null
+++ b/roles/common/tasks/main.yml
@@ -0,0 +1,26 @@
+---
+- name: Ensure base system and build dependencies are installed
+ ansible.builtin.apt:
+ name:
+ - build-essential
+ - ca-certificates
+ - curl
+ - git
+ - libffi-dev
+ - libssl-dev
+ - libxslt1-dev
+ - nftables
+ - python-is-python3
+ - python3
+ - python3-babel
+ - python3-dev
+ - python3-venv
+ - screen
+ - shellcheck
+ - uwsgi
+ - uwsgi-plugin-python3
+ - vim
+ - wget
+ - zlib1g-dev
+ state: present
+ update_cache: false
diff --git a/roles/nginx/handlers/main.yml b/roles/nginx/handlers/main.yml
new file mode 100644
index 0000000..3940edb
--- /dev/null
+++ b/roles/nginx/handlers/main.yml
@@ -0,0 +1,11 @@
+---
+- name: Validate and reload nginx
+ ansible.builtin.command: /usr/sbin/nginx -t
+ changed_when: false
+ notify: Reload nginx service
+
+- name: Reload nginx service
+ ansible.builtin.systemd:
+ name: nginx.service
+ state: reloaded
+ listen: Reload nginx
diff --git a/roles/nginx/tasks/main.yml b/roles/nginx/tasks/main.yml
new file mode 100644
index 0000000..c4f55b6
--- /dev/null
+++ b/roles/nginx/tasks/main.yml
@@ -0,0 +1,87 @@
+---
+- name: Ensure nginx is installed
+ ansible.builtin.apt:
+ name:
+ - nginx
+ state: present
+
+- name: Ensure Nginx directories exist
+ ansible.builtin.file:
+ path: "{{ item }}"
+ state: directory
+ owner: root
+ group: root
+ mode: "0755"
+ loop:
+ - /etc/nginx/sites-available
+ - /etc/nginx/sites-enabled
+ - /etc/nginx/default.apps-available
+ - /etc/nginx/default.d
+ - "{{ default_web_root }}"
+
+- name: Deploy /etc/nginx/nginx.conf
+ ansible.builtin.template:
+ src: nginx.conf.j2
+ dest: /etc/nginx/nginx.conf
+ owner: root
+ group: root
+ mode: "0644"
+ validate: "/usr/sbin/nginx -t -c %s"
+ notify: Reload nginx
+
+- name: Deploy /etc/nginx/default.apps-available/searxng.conf
+ ansible.builtin.template:
+ src: default-app-searxng.conf.j2
+ dest: /etc/nginx/default.apps-available/searxng.conf
+ owner: root
+ group: root
+ mode: "0644"
+ notify: Reload nginx
+
+- name: Enable /etc/nginx/default.d/searxng.conf symlink
+ ansible.builtin.file:
+ src: /etc/nginx/default.apps-available/searxng.conf
+ dest: /etc/nginx/default.d/searxng.conf
+ state: link
+ notify: Reload nginx
+
+- name: Deploy /etc/nginx/sites-available/default
+ ansible.builtin.template:
+ src: site-default.conf.j2
+ dest: /etc/nginx/sites-available/default
+ owner: root
+ group: root
+ mode: "0644"
+ notify: Reload nginx
+
+- name: Deploy /etc/nginx/sites-available/searxng.conf
+ ansible.builtin.template:
+ src: site-searxng.conf.j2
+ dest: /etc/nginx/sites-available/searxng.conf
+ owner: root
+ group: root
+ mode: "0644"
+ notify: Reload nginx
+
+- name: Enable active Nginx sites
+ ansible.builtin.file:
+ src: "/etc/nginx/sites-available/{{ item }}"
+ dest: "/etc/nginx/sites-enabled/{{ item }}"
+ state: link
+ loop:
+ - default
+ - searxng.conf
+ notify: Reload nginx
+
+- name: Remove unused/stub Nginx site symlinks (clean tracking)
+ ansible.builtin.file:
+ path: "/etc/nginx/sites-enabled/{{ item }}"
+ state: absent
+ loop: "{{ nginx_remove_unused_sites | default([]) }}"
+ notify: Reload nginx
+
+- name: Ensure nginx service is enabled and running
+ ansible.builtin.systemd:
+ name: nginx.service
+ enabled: true
+ state: started
diff --git a/roles/nginx/templates/default-app-searxng.conf.j2 b/roles/nginx/templates/default-app-searxng.conf.j2
new file mode 100644
index 0000000..66b1f86
--- /dev/null
+++ b/roles/nginx/templates/default-app-searxng.conf.j2
@@ -0,0 +1,23 @@
+location /searxng {
+
+ uwsgi_pass unix://{{ searxng_socket_path }};
+
+ include uwsgi_params;
+
+ uwsgi_param HTTP_HOST $host;
+ uwsgi_param HTTP_CONNECTION $http_connection;
+
+ # see flaskfix.py
+ uwsgi_param HTTP_X_FORWARDED_PROTO $scheme;
+ uwsgi_param HTTP_X_SCRIPT_NAME /searxng;
+
+ # see botdetection/trusted_proxies.py
+ uwsgi_param HTTP_X_REAL_IP $remote_addr;
+ uwsgi_param HTTP_X_FORWARDED_FOR $proxy_add_x_forwarded_for;
+}
+
+# To serve the static files via the HTTP server
+#
+# location /searxng/static/ {
+# alias /usr/local/searxng/searxng-src/searx/static/;
+# }
diff --git a/roles/nginx/templates/nginx.conf.j2 b/roles/nginx/templates/nginx.conf.j2
new file mode 100644
index 0000000..68a8fd4
--- /dev/null
+++ b/roles/nginx/templates/nginx.conf.j2
@@ -0,0 +1,84 @@
+user www-data;
+worker_processes auto;
+worker_cpu_affinity auto;
+pid /run/nginx.pid;
+error_log /var/log/nginx/error.log;
+include /etc/nginx/modules-enabled/*.conf;
+
+events {
+ worker_connections 768;
+ # multi_accept on;
+}
+
+http {
+
+ ##
+ # Basic Settings
+ ##
+
+ sendfile on;
+ tcp_nopush on;
+ types_hash_max_size 2048;
+ server_tokens off; # Recommended practice is to turn this off
+
+ # server_names_hash_bucket_size 64;
+ # server_name_in_redirect off;
+
+ include /etc/nginx/mime.types;
+ default_type application/octet-stream;
+
+ ##
+ # SSL Settings
+ ##
+
+ ssl_protocols TLSv1.2 TLSv1.3; # Dropping SSLv3 (POODLE), TLS 1.0, 1.1
+ ssl_prefer_server_ciphers off; # Don't force server cipher order.
+
+ ##
+ # Logging Settings
+ ##
+
+ access_log /var/log/nginx/access.log;
+
+ ##
+ # Gzip Settings
+ ##
+
+ gzip on;
+
+ # gzip_vary on;
+ # gzip_proxied any;
+ # gzip_comp_level 6;
+ # gzip_buffers 16 8k;
+ # gzip_http_version 1.1;
+ # gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
+
+ ##
+ # Virtual Host Configs
+ ##
+
+ include /etc/nginx/conf.d/*.conf;
+ include /etc/nginx/sites-enabled/*;
+}
+
+
+#mail {
+# # See sample authentication script at:
+# # http://wiki.nginx.org/ImapAuthenticateWithApachePhpScript
+#
+# # auth_http localhost/auth.php;
+# # pop3_capabilities "TOP" "USER";
+# # imap_capabilities "IMAP4rev1" "UIDPLUS";
+#
+# server {
+# listen localhost:110;
+# protocol pop3;
+# proxy on;
+# }
+#
+# server {
+# listen localhost:143;
+# protocol imap;
+# proxy on;
+# }
+#}
diff --git a/roles/nginx/templates/site-default.conf.j2 b/roles/nginx/templates/site-default.conf.j2
new file mode 100644
index 0000000..2542a3a
--- /dev/null
+++ b/roles/nginx/templates/site-default.conf.j2
@@ -0,0 +1,173 @@
+##
+# You should look at the following URL's in order to grasp a solid understanding
+# of Nginx configuration files in order to fully unleash the power of Nginx.
+# https://www.nginx.com/resources/wiki/start/
+# https://www.nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/
+# https://wiki.debian.org/Nginx/DirectoryStructure
+#
+# In most cases, administrators will remove this file from sites-enabled/ and
+# leave it as reference inside of sites-available where it will continue to be
+# updated by the nginx packaging team.
+#
+# This file will automatically load configuration files provided by other
+# applications, such as Drupal or Wordpress. These applications will be made
+# available underneath a path with that package name, such as /drupal8.
+#
+# Please see /usr/share/doc/nginx-doc/examples/ for more detailed examples.
+##
+
+# Default server configuration
+#
+server {
+ # Load configuration files for the default server block.
+ include /etc/nginx/default.d/*.conf;
+
+ listen 80 default_server;
+ listen [::]:80 default_server;
+
+ # SSL configuration
+ #
+ # listen 443 ssl default_server;
+ # listen [::]:443 ssl default_server;
+ #
+ # Note: You should disable gzip for SSL traffic.
+ # See: https://bugs.debian.org/773332
+ #
+ # Read up on ssl_ciphers to ensure a secure configuration.
+ # See: https://bugs.debian.org/765782
+ #
+ # Self signed certs generated by the ssl-cert package
+ # Don't use them in a production server!
+ #
+ # include snippets/snakeoil.conf;
+
+ root {{ default_web_root }};
+
+ # Add index.php to the list if you are using PHP
+ index index.html index.htm index.nginx-debian.html;
+
+ server_name _;
+
+ location / {
+ # First attempt to serve request as file, then
+ # as directory, then fall back to displaying a 404.
+ try_files $uri $uri/ =404;
+ }
+
+ # pass PHP scripts to FastCGI server
+ #
+ #location ~ \.php$ {
+ # include snippets/fastcgi-php.conf;
+ #
+ # # With php-fpm (or other unix sockets):
+ # fastcgi_pass unix:/run/php/php7.4-fpm.sock;
+ # # With php-cgi (or other tcp sockets):
+ # fastcgi_pass 127.0.0.1:9000;
+ #}
+
+ # deny access to .htaccess files, if Apache's document root
+ # concurs with nginx's one
+ #
+ #location ~ /\.ht {
+ # deny all;
+ #}
+}
+
+
+# Virtual Host configuration for example.com
+#
+# You can move that to a different file under sites-available/ and symlink that
+# to sites-enabled/ to enable it.
+#
+#server {
+# listen 80;
+# listen [::]:80;
+#
+# server_name example.com;
+#
+# root /var/www/example.com;
+# index index.html;
+#
+# location / {
+# try_files $uri $uri/ =404;
+# }
+#}
+
+server {
+
+ # SSL configuration
+ #
+ # listen 443 ssl default_server;
+ # listen [::]:443 ssl default_server;
+ #
+ # Note: You should disable gzip for SSL traffic.
+ # See: https://bugs.debian.org/773332
+ #
+ # Read up on ssl_ciphers to ensure a secure configuration.
+ # See: https://bugs.debian.org/765782
+ #
+ # Self signed certs generated by the ssl-cert package
+ # Don't use them in a production server!
+ #
+ # include snippets/snakeoil.conf;
+
+ root {{ default_web_root }};
+
+ # Add index.php to the list if you are using PHP
+ index index.html index.htm index.nginx-debian.html;
+ server_name {{ primary_domain_aliases | join(' ') }} {{ primary_domain }}; # managed by Certbot
+
+
+ location / {
+ # First attempt to serve request as file, then
+ # as directory, then fall back to displaying a 404.
+ try_files $uri $uri/ =404;
+ }
+
+ # pass PHP scripts to FastCGI server
+ #
+ #location ~ \.php$ {
+ # include snippets/fastcgi-php.conf;
+ #
+ # # With php-fpm (or other unix sockets):
+ # fastcgi_pass unix:/run/php/php7.4-fpm.sock;
+ # # With php-cgi (or other tcp sockets):
+ # fastcgi_pass 127.0.0.1:9000;
+ #}
+
+ # deny access to .htaccess files, if Apache's document root
+ # concurs with nginx's one
+ #
+ #location ~ /\.ht {
+ # deny all;
+ #}
+
+
+ listen 443 ssl; # managed by Certbot
+ listen [::]:443 ssl ipv6only=on; # managed by Certbot
+ ssl_certificate /etc/letsencrypt/live/{{ primary_domain }}/fullchain.pem; # managed by Certbot
+ ssl_certificate_key /etc/letsencrypt/live/{{ primary_domain }}/privkey.pem; # managed by Certbot
+ include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
+ ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
+
+
+
+}
+server {
+{% for alias in primary_domain_aliases %}
+ if ($host = {{ alias }}) {
+ return 301 https://$host$request_uri;
+ } # managed by Certbot
+
+
+{% endfor %}
+ if ($host = {{ primary_domain }}) {
+ return 301 https://$host$request_uri;
+ } # managed by Certbot
+
+
+ listen 80 ;
+ listen [::]:80 ;
+ server_name {{ primary_domain_aliases | join(' ') }} {{ primary_domain }};
+ return 404; # managed by Certbot
+}
diff --git a/roles/nginx/templates/site-searxng.conf.j2 b/roles/nginx/templates/site-searxng.conf.j2
new file mode 100644
index 0000000..67a5a2d
--- /dev/null
+++ b/roles/nginx/templates/site-searxng.conf.j2
@@ -0,0 +1,47 @@
+server {
+ server_name {{ searxng_domain }};
+
+ # Disable logging for user privacy
+ access_log /dev/null;
+ error_log /dev/null;
+
+ # Security headers
+ add_header X-Frame-Options "SAMEORIGIN" always;
+ add_header X-Content-Type-Options "nosniff" always;
+ add_header Referrer-Policy "no-referrer" always;
+ add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
+
+ location / {
+ uwsgi_pass unix://{{ searxng_socket_path }};
+
+ include uwsgi_params;
+
+ uwsgi_param HTTP_HOST $host;
+ uwsgi_param HTTP_CONNECTION $http_connection;
+
+ # see flaskfix.py
+ uwsgi_param HTTP_X_SCHEME $scheme;
+
+ # see limiter.py
+ uwsgi_param HTTP_X_REAL_IP $remote_addr;
+ uwsgi_param HTTP_X_FORWARDED_FOR $proxy_add_x_forwarded_for;
+ }
+
+ listen 443 ssl; # managed by Certbot
+ listen [::]:443 ssl; # managed by Certbot
+ ssl_certificate /etc/letsencrypt/live/{{ searxng_domain }}/fullchain.pem; # managed by Certbot
+ ssl_certificate_key /etc/letsencrypt/live/{{ searxng_domain }}/privkey.pem; # managed by Certbot
+ include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
+ ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
+}
+
+server {
+ if ($host = {{ searxng_domain }}) {
+ return 301 https://$host$request_uri;
+ } # managed by Certbot
+
+ listen 80;
+ listen [::]:80;
+ server_name {{ searxng_domain }};
+ return 404; # managed by Certbot
+}
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
diff --git a/roles/valkey/tasks/main.yml b/roles/valkey/tasks/main.yml
new file mode 100644
index 0000000..553869a
--- /dev/null
+++ b/roles/valkey/tasks/main.yml
@@ -0,0 +1,12 @@
+---
+- name: Ensure valkey-server is installed
+ ansible.builtin.apt:
+ name:
+ - valkey-server
+ state: present
+
+- name: Ensure valkey-server is enabled and running
+ ansible.builtin.systemd:
+ name: valkey-server.service
+ enabled: true
+ state: started