diff --git a/charts/searx/.helmignore b/charts/searx/.helmignore new file mode 100644 index 00000000..ede8444e --- /dev/null +++ b/charts/searx/.helmignore @@ -0,0 +1,24 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*~ +# Various IDEs +.project +.idea/ +.vscode/ +*.tmproj +# OWNERS file for Kubernetes +OWNERS diff --git a/charts/searx/Chart.yaml b/charts/searx/Chart.yaml new file mode 100644 index 00000000..81006dcd --- /dev/null +++ b/charts/searx/Chart.yaml @@ -0,0 +1,22 @@ +apiVersion: v2 +appVersion: 0.18.0 +description: Searx is a privacy-respecting, hackable metasearch engine +name: searx +version: 1.0.0 +keywords: + - searx + - search engine + - privacy +home: https://github.com/k8s-at-home/charts/tree/master/charts/searx +icon: https://github.com/searx/searx/blob/master/searx/static/themes/simple/img/logo_searx_a.png?raw=true +sources: + - https://github.com/searx/searx + - https://searx.github.io/searx/ + - https://hub.docker.com/r/searx/searx +maintainers: + - name: auricom + email: k8s-at-home@xpander.eml.cc +dependencies: + - name: common + repository: https://k8s-at-home.com/charts/ + version: 2.1.1 diff --git a/charts/searx/OWNERS b/charts/searx/OWNERS new file mode 100644 index 00000000..e882d048 --- /dev/null +++ b/charts/searx/OWNERS @@ -0,0 +1,4 @@ +approvers: +- auricom +reviewers: +- auricom diff --git a/charts/searx/README.md b/charts/searx/README.md new file mode 100644 index 00000000..10f6c58a --- /dev/null +++ b/charts/searx/README.md @@ -0,0 +1,77 @@ +# Searx + +This is a helm chart for [Searx](https://github.com/searx/searx). + +**This chart is not maintained by the upstream project and any issues with the chart should be raised [here](https://github.com/k8s-at-home/charts/issues/new/choose)** + +## TL;DR; + +```shell +$ helm repo add k8s-at-home https://k8s-at-home.com/charts/ +$ helm install k8s-at-home/searx +``` + +## Configuration + +The following table lists the configurable parameters of the nextcloud chart and their default values that have to be overriden. + +| Parameter | Description | Default | +| --------------------------------------------------------- | ------------------------------------------------------- | ------------------------------------------- | +| `searx.baseUrl` | external url | `https://serax.DOMAIN` | +| `searx.mortyKey` | Morty reverse proxy unique key | `changeme` | + + +## Installing the Chart + +To install the chart with the release name `my-release`: + +```console +helm install --name my-release k8s-at-home/searx +``` + +## Uninstalling the Chart + +To uninstall/delete the `my-release` deployment: + +```console +helm delete my-release --purge +``` + +The command removes all the Kubernetes components associated with the chart and deletes the release. + +## Configuration +Read through the charts [values.yaml](https://github.com/k8s-at-home/charts/blob/master/charts/searx/values.yaml) +file. It has several commented out suggested values. +Additionally you can take a look at the common library [values.yaml](https://github.com/k8s-at-home/charts/blob/master/charts/common/values.yaml) for more (advanced) configuration options. + +Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. For example, +```console +helm install searx \ + --set env.TZ="America/New_York" \ + k8s-at-home/searx +``` +Alternatively, a YAML file that specifies the values for the above parameters can be provided while installing the +chart. For example, +```console +helm install searx k8s-at-home/searx --values values.yaml +``` + +```yaml +image: + tag: ... +``` + +--- +**NOTE** + +If you get +```console +Error: rendered manifests contain a resource that already exists. Unable to continue with install: existing resource conflict: ...` +``` +it may be because you uninstalled the chart with `skipuninstall` enabled, you need to manually delete the pvc or use `existingClaim`. + +--- + +## Upgrading an existing Release to a new major version + +A major chart version change (like 1.0.1 -> 2.0.0) indicates that there is an incompatible breaking change potentially needing manual actions. diff --git a/charts/searx/ci/ct-values.yaml b/charts/searx/ci/ct-values.yaml new file mode 100644 index 00000000..f6ccc628 --- /dev/null +++ b/charts/searx/ci/ct-values.yaml @@ -0,0 +1,2 @@ +ingress: + enabled: true diff --git a/charts/searx/templates/NOTES.txt b/charts/searx/templates/NOTES.txt new file mode 100644 index 00000000..90f7b653 --- /dev/null +++ b/charts/searx/templates/NOTES.txt @@ -0,0 +1 @@ +{{- include "common.notes.defaultNotes" . -}} diff --git a/charts/searx/templates/common.yaml b/charts/searx/templates/common.yaml new file mode 100644 index 00000000..a6613c2c --- /dev/null +++ b/charts/searx/templates/common.yaml @@ -0,0 +1 @@ +{{ include "common.all" . }} diff --git a/charts/searx/templates/configmap.yaml b/charts/searx/templates/configmap.yaml new file mode 100644 index 00000000..7c4861a8 --- /dev/null +++ b/charts/searx/templates/configmap.yaml @@ -0,0 +1,269 @@ + +{{/* +Searx Configuration files. +*/}} +apiVersion: v1 +kind: ConfigMap +metadata: + name: "searx-config" + labels: + {{- include "common.labels" . | nindent 4 }} +data: + Caddyfile: |- + { + admin off + } + + :80 { + log { + output discard + } + + @api { + path /config + path /status + } + + @static { + path /static/* + } + + @notstatic { + not path /static/* + } + + @morty { + path /morty/* + } + + @notmorty { + not path /morty/* + } + + header { + # Enable HTTP Strict Transport Security (HSTS) to force clients to always connect via HTTPS + Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" + + # Enable cross-site filter (XSS) and tell browser to block detected attacks + X-XSS-Protection "1; mode=block" + + # Prevent some browsers from MIME-sniffing a response away from the declared Content-Type + X-Content-Type-Options "nosniff" + + # Disallow the site to be rendered within a frame (clickjacking protection) + X-Frame-Options "SAMEORIGIN" + + # Disable some features + Feature-Policy "accelerometer 'none';ambient-light-sensor 'none'; autoplay 'none';camera 'none';encrypted-media 'none';focus-without-user-activation 'none'; geolocation 'none';gyroscope 'none';magnetometer 'none';microphone 'none';midi 'none';payment 'none';picture-in-picture 'none'; speaker 'none';sync-xhr 'none';usb 'none';vr 'none'" + + # Referer + Referrer-Policy "no-referrer" + + # X-Robots-Tag + X-Robots-Tag "noindex, noarchive, nofollow" + + # Remove Server header + -Server + } + + header @api { + Access-Control-Allow-Methods "GET, OPTIONS" + Access-Control-Allow-Origin "*" + } + + # Cache + header @static { + # Cache + Cache-Control "public, max-age=31536000" + defer + } + + header @notstatic { + # No Cache + Cache-Control "no-cache, no-store" + Pragma "no-cache" + } + + # CSP (see http://content-security-policy.com/ ) + header @morty { + Content-Security-Policy "default-src 'none'; style-src 'self' 'unsafe-inline'; form-action 'self'; frame-ancestors 'self'; base-uri 'self'; img-src 'self' data:; font-src 'self'; frame-src 'self'" + } + + header @notmorty { + Content-Security-Policy "upgrade-insecure-requests; default-src 'none'; script-src 'self'; style-src 'self' 'unsafe-inline'; form-action 'self'; font-src 'self'; frame-ancestors 'self'; base-uri 'self'; connect-src 'self' https://overpass-api.de; img-src 'self' data: https://*.tile.openstreetmap.org; 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" + } + + # Searx-Checker + uri replace /status /searx-checker/status.json + handle /searx-checker/status.json { + root * /srv + file_server + } + + # Morty + handle @morty { + reverse_proxy localhost:3000 + } + + # Filtron + handle { + encode zstd gzip + + reverse_proxy localhost:4040 { + header_up X-Forwarded-Port {http.request.port} + header_up X-Forwarded-Proto {http.request.scheme} + header_up X-Forwarded-TlsProto {tls_protocol} + header_up X-Forwarded-TlsCipher {tls_cipher} + header_up X-Forwarded-HttpsProto {proto} + } + } + + } + rules.json: |- + [ + { + "name": "searx.space", + "filters": ["Header:X-Forwarded-For=nslookup(check.searx.space)"], + "stop": true, + "actions": [{ "name": "log"}] + }, + { + "name": "IP limit, all paths", + "interval": 3, + "limit": 25, + "aggregations": ["Header:X-Forwarded-For"], + "actions": [ + {"name": "block", + "params": {"message": "Rate limit exceeded, try again later."}} + ] + }, + { + "name": "useragent limit, all paths", + "interval": 30, + "limit": 200, + "aggregations": ["Header:X-Forwarded-For", "Header:User-Agent"], + "stop": true, + "actions": [ + {"name": "block", + "params": {"message": "Rate limit exceeded, try again later."}} + ] + }, + { + "name": "search request", + "filters": ["Param:q", "Path=^(/|/search)$"], + "subrules": [ + { + "name": "allow Firefox Android (issue #48 and #60)", + "filters": [ + "Param:q=^1$", + "Header:User-Agent=(^MozacFetch/[0-9]{2,3}.[0-9].[0-9]+$|^Mozilla/5.0 \\(Android [0-9]{1,2}(.[0-9]{1,2}.[0-9]{1,2})?; Mobile; rv:[0-9]{2,3}.[0-9]\\) Gecko/[0-9]{2,3}.[0-9] Firefox/[0-9]{2,3}.[0-9]$)" + ], + "stop": true, + "actions": [{"name": "log"}] + }, + { + "name": "robot agent forbidden", + "limit": 0, + "stop": true, + "filters": ["Header:User-Agent=([Cc][Uu][Rr][Ll]|[wW]get|Scrapy|splash|JavaFX|FeedFetcher|python-requests|Go-http-client|Java|Jakarta|okhttp|HttpClient|Jersey|Python|libwww-perl|Ruby|SynHttpClient|UniversalFeedParser)"], + "actions": [ + {"name": "block", + "params": {"message": "Rate limit exceeded"}} + ] + }, + { + "name": "bot forbidden", + "limit": 0, + "stop": true, + "filters": ["Header:User-Agent=(Googlebot|GoogleImageProxy|bingbot|Baiduspider|yacybot|YandexMobileBot|YandexBot|Yahoo! Slurp|MJ12bot|AhrefsBot|archive.org_bot|msnbot|MJ12bot|SeznamBot|linkdexbot|Netvibes|SMTBot|zgrab|James BOT|Sogou|Abonti|Pixray|Spinn3r|SemrushBot|Exabot|ZmEu|BLEXBot|bitlybot)"], + "actions": [ + {"name": "block", + "params": {"message": "Rate limit exceeded"}} + ] + }, + { + "name": "block missing accept-language", + "filters": ["!Header:Accept-Language"], + "limit": 0, + "stop": true, + "actions": [ + {"name": "block", + "params": {"message": "Rate limit exceeded"}} + ] + }, + { + "name": "block Connection:close", + "filters": ["Header:Connection=close"], + "limit": 0, + "stop": true, + "actions": [ + {"name": "block", + "params": {"message": "Rate limit exceeded"}} + ] + }, + { + "name": "block no gzip support", + "filters": ["!Header:Accept-Encoding=(^gzip$|^gzip[;,]|[; ]gzip$|[; ]gzip[;,])"], + "limit": 0, + "stop": true, + "actions": [ + {"name": "block", + "params": {"message": "Rate limit exceeded"}} + ] + }, + { + "name": "block no deflate support", + "filters": ["!Header:Accept-Encoding=(^deflate$|^deflate[;,]|[; ]deflate$|[; ]deflate[;,])"], + "limit": 0, + "stop": true, + "actions": [ + {"name": "block", + "params": {"message": "Rate limit exceeded"}} + ] + }, + { + "name": "block accept everything", + "filters": ["!Header:Accept=text/html"], + "limit": 0, + "stop": true, + "actions": [ + {"name": "block", + "params": {"message": "Rate limit exceeded"}} + ] + }, + { + "name": "rss/json limit", + "interval": 3600, + "limit": 4, + "stop": true, + "filters": ["Param:format=(csv|json|rss)"], + "aggregations": ["Header:X-Forwarded-For"], + "actions": [ + {"name": "block", + "params": {"message": "Rate limit exceeded, try again later."}} + ] + }, + { + "name": "IP limit", + "interval": 3, + "limit": 3, + "aggregations": ["Header:X-Forwarded-For"], + "actions": [ + {"name": "block", + "params": {"message": "Rate limit exceeded, try again later."}} + ] + }, + { + "name": "IP and useragent limit", + "interval": 600, + "limit": 60, + "stop": true, + "aggregations": ["Header:X-Forwarded-For", "Header:User-Agent"], + "actions": [ + {"name": "block", + "params": {"message": "Rate limit exceeded, try again later."}} + ] + } + ] + } + ] \ No newline at end of file diff --git a/charts/searx/templates/helpers.tpl b/charts/searx/templates/helpers.tpl new file mode 100644 index 00000000..1163c34e --- /dev/null +++ b/charts/searx/templates/helpers.tpl @@ -0,0 +1,27 @@ +{{/* vim: set filetype=mustache: */}} + +{{/* +Expand the name of the chart. +*/}} +{{- define "speedtest.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "speedtest.fullname" -}} +{{- if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} \ No newline at end of file diff --git a/charts/searx/templates/secrets.yaml b/charts/searx/templates/secrets.yaml new file mode 100644 index 00000000..e3531cfa --- /dev/null +++ b/charts/searx/templates/secrets.yaml @@ -0,0 +1,15 @@ + +{{/* +Searx Configuration files. +*/}} +apiVersion: v1 +kind: Secret +metadata: + name: "searx-config" + labels: + {{- include "common.labels" . | nindent 4 }} +stringData: + BIND_ADDRESS: "0.0.0.0:8080" + BASE_URL: {{ .Values.searx.baseUrl }} + MORTY_URL: {{ print .Values.searx.baseUrl "/morty/" }} + MORTY_KEY: {{ .Values.searx.mortyKey }} \ No newline at end of file diff --git a/charts/searx/values.yaml b/charts/searx/values.yaml new file mode 100644 index 00000000..6c856ba5 --- /dev/null +++ b/charts/searx/values.yaml @@ -0,0 +1,86 @@ +# Default values for Searx. + +image: + repository: searx/searx + pullPolicy: IfNotPresent + tag: 0.18.0 + +searx: + # external URL + baseUrl: "https://searx.DOMAIN" + # generate a random key used by Morty (Privacy aware web content sanitizer proxy as a service) + # example : `openssl rand -base64 24` + mortyKey: "changeme" + +strategy: + type: Recreate + +service: + port: + port: 80 + +envFrom: + - secretRef: + name: searx-config + +persistence: + config: + enabled: false + emptyDir: false + +additionalContainers: +- name: caddy + image: caddy:2.2.0-alpine + ports: + - containerPort: 80 + name: http + volumeMounts: + - name: searx-config + mountPath: /etc/caddy/Caddyfile + subPath: Caddyfile + - name: searx-checker + mountPath: /srv/searx-checker +- image: dalf/filtron:latest + imagePullPolicy: Always + name: filtron + args: + [ + "-listen", + "0.0.0.0:4040", + "-api", + "0.0.0.0:4041", + "-target", + "localhost:8080", + ] + ports: + - containerPort: 4040 + name: filtron + - containerPort: 4041 + name: api + volumeMounts: + - name: searx-config + mountPath: /etc/filtron/rules.json + subPath: rules.json +- image: dalf/morty:latest + imagePullPolicy: Always + name: morty + envFrom: + - secretRef: + name: searx-config + args: ["-listen", "localhost:3000", "-timeout", "6", "ipv6"] + ports: + - containerPort: 3000 + name: morty +- name: searx-checker + image: searx/searx-checker:latest + args: + ["-cron", "-o", "html/data/status.json", "http://localhost:8080"] + volumeMounts: + - name: searx-checker + mountPath: /usr/local/searx-checker/html/data +additionalVolumes: +- name: searx-config + configMap: + name: searx-config +- name: searx-checker + emptyDir: {}