diff options
| -rw-r--r-- | config/networking.nix | 24 | ||||
| -rw-r--r-- | config/searx/default.nix | 277 | ||||
| -rw-r--r-- | config/services/default.nix | 5 | ||||
| -rw-r--r-- | config/services/web/default.nix | 24 | ||||
| -rw-r--r-- | config/services/web/quentin/default.nix | 13 | ||||
| -rw-r--r-- | config/services/web/quentin/ihatemoney/default.nix (renamed from config/ihatemoney.nix) | 11 | ||||
| -rw-r--r-- | config/services/web/searx/default.nix | 32 | ||||
| -rw-r--r-- | config/services/web/searx/filtron/default.nix | 122 | ||||
| -rw-r--r-- | config/services/web/searx/morty/default.nix | 22 | ||||
| -rw-r--r-- | config/services/web/searx/searx/default.nix | 119 |
10 files changed, 345 insertions, 304 deletions
diff --git a/config/networking.nix b/config/networking.nix index 0a103c4..decd84e 100644 --- a/config/networking.nix +++ b/config/networking.nix @@ -19,30 +19,6 @@ }; }; - security.acme = { - acceptTerms = true; - email = "quentin@aristote.fr"; - }; - - services.nginx = { - enable = true; - virtualHosts = { - # return 444 when trying to connect directly through the IP address - "_" = { - default = true; - extraConfig = '' - return 444; - ''; - }; - - "quentin.aristote.fr" = { - locations."/".root = "${pkgs.personal.academic-webpage}"; - forceSSL = true; - enableACME = true; - }; - }; - }; - services.openssh = { enable = true; permitRootLogin = "no"; diff --git a/config/searx/default.nix b/config/searx/default.nix deleted file mode 100644 index 5e2c4c4..0000000 --- a/config/searx/default.nix +++ /dev/null @@ -1,277 +0,0 @@ -{ pkgs, lib, config, ... }: - -let - ports = { - searx = 8888; - filtron = { - listen = 4004; - api = 4005; - }; - morty = 3000; - }; - keys = { morty = "1t/rvXuoX/9OKwZ6Zby1zBc5t1DRFYIiE15xhIi72TKX"; }; -in { - # Nginx - services.nginx.virtualHosts."searx.aristote.fr" = { - forceSSL = true; - enableACME = true; - locations = { - "/" = { - proxyPass = "http://127.0.0.1:${toString ports.filtron.listen}"; - extraConfig = '' - 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-Scheme $scheme; - # proxy_set_header X-Script-Name /; - ''; - }; - "/static/" = { alias = "${pkgs.searx}/share/static/"; }; - "/morty" = lib.mkIf (config.services.morty.enable) { - proxyPass = "http://127.0.0.1:${toString ports.morty}"; - extraConfig = '' - 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-Scheme $scheme; - ''; - }; - }; - }; - - # Searx - services.searx = { - enable = true; - environmentFile = /etc/searx/secrets; - settings = { - use_default_settings = true; - general = { - debug = false; - contact_url = "mailto:quentin@aristote.fr"; - enable_stats = false; - }; - search = { - autocomplete = "dbpedia"; - default_lang = "fr-FR"; - }; - server = { - secret_key = "@SECRET_KEY@"; - image_proxy = true; - http_protocol_version = "1.0"; - method = "GET"; - }; - ui = { theme_args = { oscar_style = "pointhi"; }; }; - # result_proxy = { - # url = "http://searx.aristote.fr/morty"; - # key = ''!!binary | "${keys.morty}"''; - # }; - enabled_plugins = [ - "Open Access DOI rewrite" - "Hash plugin" - "HTTPS rewrite" - "Self Informations" - "Search on category select" - "Tracker URL remover" - "Vim-like hotkeys" - ]; - engines = let - disable = names: - map (name: { - inherit name; - disabled = true; - }) names; - in (disable [ - # general - "bing" - "currency" - "dictzone" - # files - "btdigg" - "torrentz" - # images - "bing images" - "ccengine" - "library of congress" - "qwant images" - # it - "hoogle" - # map - "photon" - ]) ++ [ - { - name = "emojipedia"; - engine = "xpath"; - search_url = "https://emojipedia.org/search/?q={query}"; - url_xpath = ''//ol[@class="search-results"]/li/h2/a/@href''; - title_xpath = ''//ol[@class="search-results"]/li/h2/a''; - content_xpath = ''//ol[@class="search-results"]/li/p''; - shortcut = "emoji"; - disabled = true; - about = { - website = "https://emojipedia.org/"; - wikidata_id = "Q22908129"; - official_api_documentation = ""; - use_official_api = false; - require_api_key = false; - results = "HTML"; - }; - } - { - name = "alternativeTo"; - engine = "xpath"; - paging = true; - search_url = "https://alternativeto.net/browse/search?q={query}&p={pageno}"; - results_xpath = ''//article[@class="row app-list-item"]/div[@class="col-xs-10 col-sm-10 col-md-11 col-lg-offset-1 col-lg-11"]''; - url_xpath = ''./h3/a/@href''; - title_xpath = ''./h3/a''; - content_xpath = ''./div[@class="itemDesc read-more-box"]/p[@class="text"]''; - shortcut = "a2"; - categories = "it"; - disabled = true; - about = { - website = "https://alternativeto.net"; - wikidata_id = "Q3613175"; - official_api_documentation = ""; - use_official_api = false; - require_api_key = false; - results = "HTML"; - }; - } - ]; - }; - runInUwsgi = true; - uwsgiConfig = { - cache2 = "name=searxcache,items=2000,blocks=2000,blocksize=4096,bitmap=1"; - http = ":${toString ports.searx}"; - }; - }; - - # Filtron - services.filtron = { - enable = true; - rules = [ - { - name = "roboagent limit"; - filters = [ - "Header:User-Agent=(curl|cURL|Wget|python-requests|Scrapy|FeedFetcher|Go-http-client|Ruby|UniversalFeedParser)" - ]; - limit = 0; - stop = true; - actions = [ - { name = "log"; } - { - name = "block"; - params = { message = "Rate limit exceeded"; }; - } - ]; - } - { - name = "botlimit"; - filters = [ - "Header:User-Agent=(Googlebot|bingbot|Baiduspider|yacybot|YandexMobileBot|YandexBot|Yahoo! Slurp|MJ12bot|AhrefsBot|archive.org_bot|msnbot|MJ12bot|SeznamBot|linkdexbot|Netvibes|SMTBot|zgrab|James BOT)" - ]; - limit = 0; - stop = true; - actions = [ - { name = "log"; } - { - name = "block"; - params = { message = "Rate limit exceeded"; }; - } - ]; - } - { - name = "suspiciously frequent IP"; - filters = [ ]; - interval = 600; - limit = 30; - aggregations = [ "Header:X-Forwarded-For" ]; - actions = [{ name = "log"; }]; - } - { - name = "search request"; - filters = [ "Param:q" "Path=^(/|/search)$" ]; - interval = 61; - limit = 999; - subrules = [ - { - name = "missing Accept-Language"; - filters = [ "!Header:Accept-Language" ]; - limit = 0; - stop = true; - actions = [ - { name = "log"; } - { - name = "block"; - params = { message = "Rate limit exceeded"; }; - } - ]; - } - # { - # name = "suspiciously Connection=close header"; - # filters = [ "Header:Connection=close" ]; - # limit = 0; - # stop = true; - # actions = [ - # { name = "log"; } - # { - # name = "block"; - # params = { message = "Rate limit exceeded"; }; - # } - # ]; - # } - { - name = "IP limit"; - interval = 61; - limit = 9; - stop = true; - aggregations = [ "Header:X-Forwarded-For" ]; - actions = [ - { name = "log"; } - { - name = "block"; - params = { message = "Rate limit exceeded"; }; - } - ]; - } - { - name = "rss/json limit"; - filters = [ "Param:format=(csv|json|rss)" ]; - interval = 121; - limit = 2; - stop = true; - actions = [ - { name = "log"; } - { - name = "block"; - params = { message = "Rate limit exceeded"; }; - } - ]; - } - { - name = "useragent limit"; - interval = 61; - limit = 199; - aggregations = [ "Header:User-Agent" ]; - actions = [ - { name = "log"; } - { - name = "block"; - params = { message = "Rate limit exceeded"; }; - } - ]; - } - ]; - } - ]; - }; - - # Morty - # services.morty = { - # enable = true; - # key = keys.morty; - # port = ports.morty; - # }; -} diff --git a/config/services/default.nix b/config/services/default.nix new file mode 100644 index 0000000..e1dcb81 --- /dev/null +++ b/config/services/default.nix @@ -0,0 +1,5 @@ +{ ... }: + +{ + imports = [ ./web ]; +} diff --git a/config/services/web/default.nix b/config/services/web/default.nix new file mode 100644 index 0000000..e0bdae8 --- /dev/null +++ b/config/services/web/default.nix @@ -0,0 +1,24 @@ +{ ... }: + +{ + import = [ + ./quentin + ./searx + ]; + + security.acme = { + acceptTerms = true; + email = "quentin@aristote.fr"; + }; + + services.nginx = { + enable = true; + # return 444 when trying to connect directly through the IP address + virtualHosts."_" = { + default = true; + extraConfig = '' + return 444 + ''; + }; + }; +} diff --git a/config/services/web/quentin/default.nix b/config/services/web/quentin/default.nix new file mode 100644 index 0000000..6ca712c --- /dev/null +++ b/config/services/web/quentin/default.nix @@ -0,0 +1,13 @@ +{ pkgs, lib, config, ... }: + +{ + import = [ + ./ihatemoney + ]; + + services.nginx.virtualHosts."quentin.aristote.fr" = { + locations."/".root = "${pkgs.personal.academic-webpage}"; + forceSSL = true; + enableACME = true; + }; +} diff --git a/config/ihatemoney.nix b/config/services/web/quentin/ihatemoney/default.nix index 5eb086b..8a29aec 100644 --- a/config/ihatemoney.nix +++ b/config/services/web/quentin/ihatemoney/default.nix @@ -1,6 +1,12 @@ -{ ... }: +{ lib, config, ... }: + +let cfg = config.services.ihatemoney; +in { + services.nginx.virtualHosts."quentin.aristote.fr".locations = + lib.mkIf cfg.enable { + "/money/".proxyPass = "http://127.0.0.1${cfg.uwsgiConfig}"; + }; -{ services.ihatemoney = { enable = true; enableAdminDashboard = true; @@ -12,5 +18,4 @@ ''; }; - services.nginx.virtualHosts."quentin.aristote.fr".locations."/money/".proxyPass = "http://127.0.0.1:8000/"; } diff --git a/config/services/web/searx/default.nix b/config/services/web/searx/default.nix new file mode 100644 index 0000000..7c5e593 --- /dev/null +++ b/config/services/web/searx/default.nix @@ -0,0 +1,32 @@ +{ config, lib, ... }: + +let + cfg = { + searx = config.services.searx; + filtron = config.services.filtron; + }; +in { + imports = [ ./searx ./filtron ./morty ]; + + services.nginx.virtualHosts."searx.aristote.fr" = + lib.mkIf (cfg.searx.enable && cfg.filtron.enable) { + locations = { + "/" = { + proxyPass = "http://${cfg.filtron.listen.address}:${ + toString cfg.filtron.listen.port + }"; + extraConfig = '' + 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-Scheme $scheme; + # proxy_set_header X-Script-Name /; + ''; + }; + "/static".alias = "${pkgs.searx}/sjare/static"; + }; + forceSSL = true; + enableACME = true; + }; +} diff --git a/config/services/web/searx/filtron/default.nix b/config/services/web/searx/filtron/default.nix new file mode 100644 index 0000000..cc637c3 --- /dev/null +++ b/config/services/web/searx/filtron/default.nix @@ -0,0 +1,122 @@ +{ ... }: + +{ + services.filtron = { + enable = true; + rules = [ + { + name = "roboagent limit"; + filters = [ + "Header:User-Agent=(curl|cURL|Wget|python-requests|Scrapy|FeedFetcher|Go-http-client|Ruby|UniversalFeedParser)" + ]; + limit = 0; + stop = true; + actions = [ + { name = "log"; } + { + name = "block"; + params = { message = "Rate limit exceeded"; }; + } + ]; + } + { + name = "botlimit"; + filters = [ + "Header:User-Agent=(Googlebot|bingbot|Baiduspider|yacybot|YandexMobileBot|YandexBot|Yahoo! Slurp|MJ12bot|AhrefsBot|archive.org_bot|msnbot|MJ12bot|SeznamBot|linkdexbot|Netvibes|SMTBot|zgrab|James BOT)" + ]; + limit = 0; + stop = true; + actions = [ + { name = "log"; } + { + name = "block"; + params = { message = "Rate limit exceeded"; }; + } + ]; + } + { + name = "suspiciously frequent IP"; + filters = [ ]; + interval = 600; + limit = 30; + aggregations = [ "Header:X-Forwarded-For" ]; + actions = [{ name = "log"; }]; + } + { + name = "search request"; + filters = [ "Param:q" "Path=^(/|/search)$" ]; + interval = 61; + limit = 999; + subrules = [ + { + name = "missing Accept-Language"; + filters = [ "!Header:Accept-Language" ]; + limit = 0; + stop = true; + actions = [ + { name = "log"; } + { + name = "block"; + params = { message = "Rate limit exceeded"; }; + } + ]; + } + # { + # name = "suspiciously Connection=close header"; + # filters = [ "Header:Connection=close" ]; + # limit = 0; + # stop = true; + # actions = [ + # { name = "log"; } + # { + # name = "block"; + # params = { message = "Rate limit exceeded"; }; + # } + # ]; + # } + { + name = "IP limit"; + interval = 61; + limit = 9; + stop = true; + aggregations = [ "Header:X-Forwarded-For" ]; + actions = [ + { name = "log"; } + { + name = "block"; + params = { message = "Rate limit exceeded"; }; + } + ]; + } + { + name = "rss/json limit"; + filters = [ "Param:format=(csv|json|rss)" ]; + interval = 121; + limit = 2; + stop = true; + actions = [ + { name = "log"; } + { + name = "block"; + params = { message = "Rate limit exceeded"; }; + } + ]; + } + { + name = "useragent limit"; + interval = 61; + limit = 199; + aggregations = [ "Header:User-Agent" ]; + actions = [ + { name = "log"; } + { + name = "block"; + params = { message = "Rate limit exceeded"; }; + } + ]; + } + ]; + } + ]; + }; +} diff --git a/config/services/web/searx/morty/default.nix b/config/services/web/searx/morty/default.nix new file mode 100644 index 0000000..1a2b0e7 --- /dev/null +++ b/config/services/web/searx/morty/default.nix @@ -0,0 +1,22 @@ +{ config, lib, ... }: + +let cfg = config.services.morty; +in { + services.nginx.virtualHosts."searx.aristote.fr".locations = + lib.mkIf cfg.enable { + "/morty/" = { + proxyPass = "http://127.0.0.1:${toString cfg.port}"; + extraConfig = '' + 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-Scheme $scheme; + ''; + }; + }; + + services.morty = { + enable = false; + }; +} diff --git a/config/services/web/searx/searx/default.nix b/config/services/web/searx/searx/default.nix new file mode 100644 index 0000000..575b978 --- /dev/null +++ b/config/services/web/searx/searx/default.nix @@ -0,0 +1,119 @@ +{ config, lib, ... }: + +let + cfg = { + morty = config.services.morty; + filtron = config.services.filtron; + }; +in { + services.searx = { + enable = true; + + runInUwsgi = true; + uwsgiConfig = { + cache2 = "name=searxcache,items=2000,blocks=2000,blocksize=4096,bitmap=1"; + http = "$http://${cfg.filtron.target.address}:${toString cfg.filtron.target.port}"; + }; + + environmentFile = /etc/searx/secrets; + settings = { + use_default_settings = true; + general = { + debug = false; + contact_url = "mailto:quentin@aristote.fr"; + enable_stats = false; + }; + search = { + autocomplete = "dbpedia"; + default_lang = "fr-FR"; + }; + server = { + secret_key = "@SECRET_KEY@"; + image_proxy = true; + http_protocol_version = "1.0"; + method = "GET"; + }; + ui = { theme_args = { oscar_style = "pointhi"; }; }; + result_proxy = lib.mkIf cfg.morty.enable { + url = "http://searx.aristote.fr/morty"; + key = ''!!binary | "${keys.morty}"''; + }; + enabled_plugins = [ + "Open Access DOI rewrite" + "Hash plugin" + "HTTPS rewrite" + "Self Informations" + "Search on category select" + "Tracker URL remover" + "Vim-like hotkeys" + ]; + engines = let + disable = names: + map (name: { + inherit name; + disabled = true; + }) names; + in (disable [ + # general + "bing" + "currency" + "dictzone" + # files + "btdigg" + "torrentz" + # images + "bing images" + "ccengine" + "library of congress" + "qwant images" + # it + "hoogle" + # map + "photon" + ]) ++ [ + { + name = "emojipedia"; + engine = "xpath"; + search_url = "https://emojipedia.org/search/?q={query}"; + url_xpath = ''//ol[@class="search-results"]/li/h2/a/@href''; + title_xpath = ''//ol[@class="search-results"]/li/h2/a''; + content_xpath = ''//ol[@class="search-results"]/li/p''; + shortcut = "emoji"; + disabled = true; + about = { + website = "https://emojipedia.org/"; + wikidata_id = "Q22908129"; + official_api_documentation = ""; + use_official_api = false; + require_api_key = false; + results = "HTML"; + }; + } + { + name = "alternativeTo"; + engine = "xpath"; + paging = true; + search_url = + "https://alternativeto.net/browse/search?q={query}&p={pageno}"; + results_xpath = '' + //article[@class="row app-list-item"]/div[@class="col-xs-10 col-sm-10 col-md-11 col-lg-offset-1 col-lg-11"]''; + url_xpath = "./h3/a/@href"; + title_xpath = "./h3/a"; + content_xpath = + ''./div[@class="itemDesc read-more-box"]/p[@class="text"]''; + shortcut = "a2"; + categories = "it"; + disabled = true; + about = { + website = "https://alternativeto.net"; + wikidata_id = "Q3613175"; + official_api_documentation = ""; + use_official_api = false; + require_api_key = false; + results = "HTML"; + }; + } + ]; + }; + }; +} |
