> ## Documentation Index
> Fetch the complete documentation index at: https://docs.controlplane.com/llms.txt
> Use this file to discover all available pages before exploring further.

# SearXNG

> Deploy SearXNG on Control Plane using the Template Catalog. Privacy-respecting metasearch engine that merges results from ~200 upstream engines and serves them over a JSON API with no API key or vendor quota. Covers the prerequisite signing key, the rate limiter, and access modes.

## Overview

SearXNG is a privacy-respecting metasearch engine: it holds no index of its own, forwards each query to roughly 200 upstream engines, and merges the results while keeping no profile and setting no tracking cookies. This template deploys it as a stateless workload on port `8080`, with the JSON API switched on, plus a small bundled datastore that backs the optional rate limiter.

**The JSON API is the reason this template exists.** `GET /search?q=...&format=json` returns merged web results as JSON — no API key to obtain, no per-query bill, and no vendor rate limit — which makes it a search backend an AI agent can call directly. `formats` ships as `[html, json]`, so the API is live on a default install alongside the human UI.

The install is **private by default**: `publicAccess.enabled` is `false` and `limiter.enabled` is `false`. Those two defaults belong together, and choosing differently is the one real decision this template asks of you — see [Choosing an Access Shape](#choosing-an-access-shape).

### Architecture

* **SearXNG server** — A `standard` (stateless) workload serving the UI and the API on port `8080`. `replicas` instances run behind the platform load balancer with no session affinity, because there is no server-side session to pin: preferences live in a cookie in the user's own browser.
* **Redis and Sentinel (optional, on by default)** — The [redis](/template-catalog/templates/redis) template as a subchart, pinned to one master and one sentinel. It holds the rate limiter's counters and the shared state a multi-replica install needs. **It is not a result cache** — search results are never stored there.
* **Settings** — The rendered `settings.yml` is mounted read-only at `/etc/searxng/settings.yml` from a template-created secret.
* **Signing key** — Supplied by you as a prerequisite secret and injected as an environment variable, so it is never written into the rendered configuration and never enters the Helm release.
* **No volume set, no database, and no login.** Everything durable is either your prerequisite secret or a cookie in a user's browser.

### What Gets Created

* **Standard SearXNG Workload** — `{release}-searxng`, serving the UI and API on port `8080` with `replicas` replicas and configurable CPU and memory.
* **Stateful Redis and Sentinel Workloads** — `{release}-redis` on `6379` and `{release}-sentinel` on `26379`, created only when `redis.enabled` is `true`. Both are in-memory; neither mounts a volume.
* **Settings Secret** — An opaque secret (`{release}-searxng-settings`) holding the rendered `settings.yml`.
* **Start-Script Secret** — An opaque secret (`{release}-searxng-startup`) holding the container's start-up script, created only when the bundled datastore is enabled.
* **Identity & Policy** — An identity bound to the SearXNG workload and a policy granting it `reveal` on exactly the secrets it reads: the settings secret, your prerequisite signing key, the start-up script, and the datastore password when `redis.redis.auth.password.enabled` is `true`. The Redis subchart brings its own identity, policy, and config secret.

No volume set is created anywhere in this template, so an uninstall leaves no storage behind.

<Note>
  This template does not create a GVC. You must deploy it into an existing GVC.
</Note>

## Prerequisites

**One [opaque secret](/guides/create-secret/opaque) must exist before you install.** It holds `server.secret_key`, which signs preference cookies and CSRF tokens. Because it is a secret you create and reference by name, the value never passes through Helm values and never lands in the release.

```bash theme={null}
printf '%s' "$(openssl rand -hex 32)" | \
  cpln secret create-opaque --name my-searxng-secret-key --encoding plain -f -
```

Then set `secretKey.secretName` to the name you used. Installing with an empty `secretKey.secretName` fails at render time.

<Warning>
  **Create the secret before installing.** A name pointing at a secret that does not exist installs "successfully" and then wedges silently: every resource reports created, the workload never becomes ready, and **`cpln logs` returns zero lines** because no container ever starts. The only diagnostic is `status.versions[].message`:

  ```bash theme={null}
  cpln workload get-deployments {release}-searxng --gvc {gvc} -o yaml
  ```

  It names the missing secret: `The secret <name> no longer exists. Workload updates are paused until the secret is added or the reference to the secret removed.` The command is `get-deployments` — plain `cpln workload get` has no `versions` key at all. Creating the secret recovers the workload on its own, measured here at **9 minutes**; `cpln workload force-redeployment {release}-searxng --gvc {gvc}` skips the wait.
</Warning>

<Warning>
  **Rotating the signing key invalidates every saved preference.** User preferences live in a cookie signed with this key, so replacing it discards every stored setting in every browser. Treat it as write-once rather than something to rotate on a schedule, and keep a copy outside Control Plane — reinstalling against the same secret loses nothing.
</Warning>

Nothing else is required: no cloud account, no domain, no external database.

## Installation

To install, follow the instructions for your preferred method:

<CardGroup cols={2}>
  <Card title="UI" href="/template-catalog/install-manage/ui" icon="laptop">
    Browse, install, and manage templates visually
  </Card>

  <Card title="CLI" href="/template-catalog/install-manage/cli" icon="terminal">
    Manage templates from your terminal
  </Card>

  <Card title="Terraform" href="/template-catalog/install-manage/terraform" icon={<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128"><g fill-rule="evenodd"><path d="M77.941 44.5v36.836L46.324 62.918V26.082zm0 0" fill="#5c4ee5"/><path d="M81.41 81.336l31.633-18.418V26.082L81.41 44.5zm0 0" fill="#4040b2"/><path d="M11.242 42.36L42.86 60.776V23.941L11.242 5.523zm0 0M77.941 85.375L46.324 66.957v36.82l31.617 18.418zm0 0" fill="#5c4ee5"/></g></svg>}>
    Declare templates in your Terraform configurations
  </Card>

  <Card
    title="Pulumi"
    href="/template-catalog/install-manage/pulumi"
    icon={<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" id="Pulumi-Icon--Streamline-Svg-Logos" height="24" width="24">
    <desc>
        Pulumi Icon Streamline Icon: https://streamlinehq.com
    </desc>
    <path fill="#f26e7e" d="M4.683025 13.3318c0.869125 -0.5018 0.870575 -2.1264 0.003225 -3.62865s-2.27504 -2.313275 -3.1441725 -1.811475C0.672945 8.3935 0.6715 10.0181 1.53885 11.52035c0.86735 1.502275 2.27505 2.313275 3.144175 1.81145Zm0.0052 3.2167c0.86735 1.502275 0.865925 3.126875 -0.003225 3.628675 -0.86915 0.5018 -2.2768275 -0.309225 -3.144175 -1.81145 -0.8673525 -1.50225 -0.8659075 -3.126875 0.003225 -3.628675 0.8691325 -0.5018 2.276825 0.309225 3.144175 1.81145Zm5.922875 3.4243c0.86735 1.50225 0.8659 3.126775 -0.003225 3.62875 -0.869125 0.501775 -2.27685 -0.309325 -3.1442 -1.81155 -0.867325 -1.50225 -0.865875 -3.12685 0.00325 -3.628675 0.869125 -0.5018 2.276825 0.309225 3.144175 1.811475Zm-0.001925 -6.845275c0.86735 1.50225 0.8659 3.12685 -0.003225 3.628675 -0.869125 0.5018 -2.276825 -0.309225 -3.144175 -1.811475 -0.86735 -1.50225 -0.8659 -3.12685 0.003225 -3.62865 0.869125 -0.501825 2.276825 0.3092 3.144175 1.81145Z" stroke-width="0.25"></path>
    <path fill="#8a3391" d="M22.45775 11.524125c0.86725 -1.502225 0.865925 -3.12685 -0.003225 -3.62865 -0.869125 -0.501825 -2.276825 0.3092 -3.144175 1.811475 -0.86735 1.50225 -0.8659 3.126825 0.003225 3.62865 0.869125 0.501825 2.276825 -0.3092 3.144175 -1.811475Zm0.000175 3.2151c0.869075 0.5018 0.870625 2.1264 0.003225 3.62865 -0.86735 1.50225 -2.27505 2.313275 -3.144175 1.81145 -0.869125 -0.5018 -0.870575 -2.126425 -0.003225 -3.62865 0.86735 -1.50225 2.27505 -2.313275 3.144175 -1.81145ZM16.536225 18.157875c0.86915 0.501825 0.8706 2.126425 0.00325 3.628675 -0.86735 1.502125 -2.275075 2.313225 -3.1442 1.81145 -0.869125 -0.50175 -0.870575 -2.126425 -0.003225 -3.62865 0.867375 -1.502275 2.27505 -2.3133 3.144175 -1.811475Zm-0.003325 -6.843775c0.869125 0.5018 0.870575 2.126425 0.003225 3.628675s-2.27505 2.313275 -3.1442 1.811475c-0.869125 -0.501825 -0.870575 -2.126425 -0.003225 -3.628675 0.86735 -1.502275 2.27505 -2.313275 3.1442 -1.811475Z" stroke-width="0.25"></path>
    <path fill="#f7bf2a" d="M15.138225 2.06721c0 1.003615 -1.40625 1.817215 -3.14095 1.817215 -1.7347 0 -3.14095 -0.8136 -3.14095 -1.817215C8.856325 1.06359 10.262575 0.25 11.997275 0.25c1.7347 0 3.14095 0.81359 3.14095 1.81721ZM9.2166 5.482375c0 1.003625 -1.40625 1.8172 -3.14095 1.8172 -1.7347 0 -3.14095 -0.813575 -3.14095 -1.8172s1.40625 -1.817225 3.14095 -1.817225c1.7347 0 3.14095 0.8136 3.14095 1.817225Zm8.71005 1.8172c1.7347 0 3.14095 -0.813575 3.14095 -1.8172s-1.40625 -1.817225 -3.14095 -1.817225c-1.7347 0 -3.14095 0.8136 -3.14095 1.817225s1.40625 1.8172 3.14095 1.8172Zm-2.788425 1.605625c0 1.003625 -1.40625 1.8172 -3.14095 1.8172 -1.7347 0 -3.14095 -0.813575 -3.14095 -1.8172 0 -1.0036 1.40625 -1.8172 3.14095 -1.8172 1.7347 0 3.14095 0.8136 3.14095 1.8172Z" stroke-width="0.25"></path>
    </svg>}
  >
    Declare templates in your Pulumi programs
  </Card>
</CardGroup>

## Choosing an Access Shape

The rate limiter and the JSON API pull in opposite directions, and this is the decision to get right before you publish anything.

The limiter is **bot detection**, not a simple request counter: it inspects the request and rejects anything that does not look like a real browser. A plain `curl`, a Python HTTP client, or an AI agent therefore gets `429 Too Many Requests` on every route it cares about — `/search`, `/search?format=json`, and `/config` alike — while a browser-shaped request is served normally and then throttled at a burst ceiling of 15 searches. Both halves were measured: with the limiter on, 25 plain-client requests returned `429` every time, and 25 browser-shaped searches returned `200` fifteen times and `429` for the rest.

Turning the limiter off makes the JSON API usable by any client. It also means nothing throttles the instance, which is fine behind a closed firewall and a problem on the open internet.

|                              | Private + JSON API **(default)**                                        | Public + limiter                                    |
| ---------------------------- | ----------------------------------------------------------------------- | --------------------------------------------------- |
| `publicAccess.enabled`       | `false`                                                                 | `true`                                              |
| `limiter.enabled`            | `false`                                                                 | `true`                                              |
| Who can reach it             | Workloads in the GVC per `internalAccess`, plus you over a port-forward | Anyone on the internet                              |
| Plain `curl` and agent calls | Served                                                                  | `429` — the client must send browser-shaped headers |
| Best for                     | Agents, scripts, and internal services                                  | A search page for humans                            |

The combination to avoid is **public with the limiter off**: an open, unthrottled metasearch instance that anyone can drive. Upstream engines respond to the traffic it attracts by throttling or blocking your egress address, and the result is a slow decline in result quality rather than an outright failure. That degradation is real and was observed during testing — after roughly 150 rapid queries, DuckDuckGo, Brave, and Startpage all began answering with CAPTCHA and "too many requests" responses, and result counts fell from 20 to single digits before recovering.

SearXNG has **no login of any kind**, so the limiter is the only control a public instance has.

Two constraints the chart enforces at render time: `limiter.enabled: true` requires `redis.enabled: true`, and `redis.redis.replicas` must stay `1`.

## Reaching the UI

A default install is private, so a port-forward is the operator's path to it. This works even when the workload is closed to the internet *and* to the GVC (`internalAccess.type: none`), because the tunnel does not go through the data-plane firewall:

```bash theme={null}
cpln port-forward {release}-searxng 8080:8080 --gvc {gvc}
```

Then browse `http://localhost:8080`. Note that `cpln port-forward` is a top-level command, not a `cpln workload` subcommand.

To publish the UI instead, upgrade with `publicAccess.enabled: true` and `limiter.enabled: true`, then read the assigned `*.cpln.app` address from `status.canonicalEndpoint`:

```bash theme={null}
cpln workload get {release}-searxng --gvc {gvc} -o yaml
```

<Note>
  Firewall changes are not instantaneous. Publishing the endpoint took **20 seconds** to start returning `200` in testing, and closing internal access took about **50 seconds** to start refusing in-GVC callers. Allow up to a couple of minutes and re-test rather than concluding the knob did not work. A port-forward keeps serving throughout.
</Note>

<Note>
  A port-forward is unreliable while replicas are being replaced — during a scale-down or a redeployment the tunnel can follow a replica that is going away. Re-run it once the deployment has settled.
</Note>

## Configuration

The default `values.yaml` for this template:

```yaml theme={null}
# ─── SearXNG ──────────────────────────────────────────────────────
image: searxng/searxng:2026.8.22-9fea41204
replicas: 1                    # 1 = proven single shape; >=2 = load-balanced tier (limiter state is shared via redis)
resources:
  minCpu: 250m
  maxCpu: 1000m
  minMemory: 256Mi
  maxMemory: 512Mi

# ─── Search behaviour ─────────────────────────────────────────────
instanceName: SearXNG          # shown in the UI and returned by /config
formats:                       # allowed: html, json, csv, rss (upstream default is html only)
  - html
  - json                       # the JSON API AI agents call: /search?q=...&format=json
imageProxy: true               # proxy result images through this instance instead of hotlinking third parties
baseUrl: ""                    # set only behind a custom domain, e.g. https://search.example.com (empty = derive from request)
limiter:
  enabled: false               # bot-detection rate limiter; requires redis.enabled. NOTE: it 429s non-browser clients, including the JSON API
extraSettings: {}              # merged into settings.yml verbatim, e.g. {general: {enable_metrics: false}}

# ─── Signing key (USER-CREATED PREREQUISITE — MUST EXIST BEFORE INSTALL) ─
# Opaque secret, encoding: plain, whose payload is the session/CSRF signing key.
# Create it FIRST — a missing secret WEDGES the deployment silently (logs
# return zero lines; the reason appears only in status.versions[].message).
# The exact create command is in the README Prerequisites section.
# Never rotate it casually: it invalidates every saved preference cookie.
secretKey:
  secretName: my-searxng-secret-key

# ─── Access ───────────────────────────────────────────────────────
# SearXNG has NO login of any kind. Default is private — see the README
# "Reaching the UI" section for the port-forward command.
# Before setting publicAccess.enabled: true, turn limiter.enabled on.
publicAccess:
  enabled: false               # true = UI + API on the canonical *.cpln.app endpoint, unauthenticated
internalAccess:
  type: same-gvc               # options: none, same-gvc, same-org, workload-list
  workloads: []                # used only with workload-list
  # workloads:
  #   - //gvc/GVC_NAME/workload/WORKLOAD_NAME

# ─── Redis (subchart: redis) — limiter counters / shared state ────
# Pinned single-instance ON PURPOSE: SearXNG's valkey client is not
# Sentinel-aware, so it must talk to the master directly. redis.replicas
# must stay 1 (validated). One sentinel is required by the redis chart's
# boot-time master discovery; it cannot be scaled to zero.
redis:
  enabled: true                # false = no datastore; limiter must then stay off
  redis:
    image: redis:8
    replicas: 1                # MUST be 1 (validated) — SearXNG must reach the master directly
    auth:
      password:
        enabled: false         # true = require AUTH; password is wired into the connection URL
        value: change-me-searxng-redis
    resources:
      minCpu: 80m
      maxCpu: 200m
      minMemory: 128Mi
      maxMemory: 256Mi
  sentinel:
    image: redis:8
    replicas: 1
    resources:
      minCpu: 80m
      maxCpu: 200m
      minMemory: 128Mi
      maxMemory: 256Mi
```

### Image and resources

* `image` — The SearXNG server image. Pin a concrete tag.
* `replicas` — Number of instances. `1` is the proven single shape; `2` or more form a load-balanced tier that shares limiter state through the bundled datastore. At two replicas, a rolling restart served 300 of 300 requests and an abrupt replica loss served 75 of 75, with the replacement serving 11 seconds later.
* `resources.minCpu` / `resources.maxCpu` / `resources.minMemory` / `resources.maxMemory` — CPU reservation and limit, memory reservation and limit for the SearXNG container.

### Search Behavior

* `instanceName` — The name shown in the UI and returned by `/config`.
* `formats` — Output formats the instance will serve. Allowed values are `html`, `json`, `csv`, and `rss`; upstream defaults to `html` only, and this template ships `[html, json]`. A format that is not listed is refused with `403`, so removing `json` disables the API.
* `imageProxy` — When `true` (default), result images are relayed through this instance instead of being hotlinked from third parties, so a user's browser never contacts the origin. On a public instance that also makes it an open image relay.
* `baseUrl` — Set only when the instance sits behind a custom domain (for example `https://search.example.com`). Empty derives the URL from the request, which is correct for the canonical `*.cpln.app` endpoint. It drives the `opensearch.xml` document browsers use to add the instance as a search provider.
* `limiter.enabled` — The bot-detection rate limiter. Off by default; requires `redis.enabled`. See [Choosing an Access Shape](#choosing-an-access-shape) before turning it on.
* `extraSettings` — Merged verbatim into `settings.yml` over the keys above, so anything in the upstream [settings reference](https://docs.searxng.org/admin/settings/index.html) is reachable — engine selection, `safe_search`, `outgoing` timeouts. An override of a key this template also sets wins cleanly instead of producing a duplicate YAML key.

### Signing Key

* `secretKey.secretName` — The name of your prerequisite opaque secret, whose whole payload is the signing key. Every replica reads the same one, which is what lets any replica verify any user's preference cookie. The chart grants the workload `reveal` on exactly that secret.

### Access

* `publicAccess.enabled` — When `true`, the UI and API are served over HTTPS on the automatically assigned `*.cpln.app` endpoint, **unauthenticated**. When `false` (default), external requests are refused at the edge with `403`.
* `internalAccess.type` — Internal firewall scope of the workload:

| Type            | Description                                                            |
| --------------- | ---------------------------------------------------------------------- |
| `none`          | No internal access — in-GVC traffic is refused.                        |
| `same-gvc`      | Allow access from all workloads in the same GVC (default).             |
| `same-org`      | Allow access from all workloads in the same organization.              |
| `workload-list` | Allow access only from workloads listed in `internalAccess.workloads`. |

* `internalAccess.workloads` — Workload links (`//gvc/GVC_NAME/workload/WORKLOAD_NAME`), used only with `workload-list`.

Outbound access is always open to `0.0.0.0/0` and is not configurable: querying upstream engines over the public internet is the entire function of the service, and narrowing it makes every engine fail.

### Redis

The bundled datastore exists for the limiter and for shared state across replicas. It stores no search results and nothing durable.

* `redis.enabled` — When `false`, no datastore is deployed and SearXNG runs standalone. `limiter.enabled` must then stay `false`; the chart refuses to render the combination, because without the datastore SearXNG would install no limiter at all while its configuration still claimed one.
* `redis.redis.replicas` — **Must stay `1`**, and the chart rejects anything else. SearXNG's client is not Sentinel-aware and has to reach the master directly, so extra replicas would serve read-only connections and silently break the limiter. One sentinel is required by the Redis chart's boot-time master discovery and cannot be scaled to zero.
* `redis.redis.auth.password.enabled` / `redis.redis.auth.password.value` — When enabled, the datastore requires `AUTH` and the password is wired into the connection URL through a template-created secret. Change the placeholder value if you turn this on.
* `redis.redis.image` / `redis.sentinel.image` / `redis.redis.resources` / `redis.sentinel.resources` — Image and CPU and memory bounds for the two datastore workloads.

<Note>
  With the limiter **on**, a SearXNG container that starts while the datastore is unreachable refuses to start rather than coming up silently unthrottled: the deployment reports a container exit instead of serving. If a fresh install with `limiter.enabled: true` never becomes ready, check the `{release}-redis` workload first. With the limiter **off**, the same container logs a warning and starts normally.
</Note>

## Using the JSON API

From another workload in the same GVC, using the **fully-qualified** internal name:

```bash theme={null}
curl 'http://{release}-searxng.{gvc}.cpln.local:8080/search?q=control+plane&format=json'
```

The bare short name does not resolve to this workload — the fully-qualified `.cpln.local` form is required.

The response carries the merged results, the engines that answered, and an `unresponsive_engines` list naming any that timed out or returned a CAPTCHA. Useful query parameters include `categories` (for example `general`, `images`, `news`), `language`, `time_range`, and `pageno`; the full set is in the upstream [search API reference](https://docs.searxng.org/dev/search_api.html).

Keep `limiter.enabled: false` for this: the limiter rejects requests that do not look like a browser, which includes plain `curl` and most HTTP client libraries. If the instance must be public *and* callable by an agent, the agent has to send browser-shaped headers — a realistic `User-Agent` plus `Accept`, `Accept-Language`, and `Accept-Encoding` — and it will still be throttled after 15 searches in the limiter's burst window.

## Connecting

| Target                           | Address                                                                            | Credentials                                                |
| -------------------------------- | ---------------------------------------------------------------------------------- | ---------------------------------------------------------- |
| Public UI and API *(if enabled)* | `https://<canonical>.cpln.app` — `status.canonicalEndpoint` of `{release}-searxng` | None — SearXNG has no login                                |
| Internal UI and API              | `http://{release}-searxng.{gvc}.cpln.local:8080`                                   | None                                                       |
| Private UI (default)             | `http://localhost:8080` over a port-forward                                        | None                                                       |
| Health                           | `GET /healthz` on `8080`                                                           | None — unaffected by the limiter                           |
| Redis *(if enabled)*             | `{release}-redis.{gvc}.cpln.local:6379`                                            | None, unless `redis.redis.auth.password.enabled` is `true` |

A fresh install typically has all three workloads ready within about half a minute of the install command returning.

## Important Notes

* **There is no authentication of any kind.** With `publicAccess.enabled: true` the UI, the API, `/config`, and `/stats` are all served to anyone who finds the endpoint. Turn `limiter.enabled` on before you publish.
* **The limiter blocks the JSON API for non-browser clients.** Plain `curl` and HTTP client libraries get `429` on `/search` while the limiter is on. Pick one of the two shapes in [Choosing an Access Shape](#choosing-an-access-shape) deliberately.
* **`/config` and `/stats` are unauthenticated** and go public with the UI. `/config` lists your engine and plugin configuration. Setting `extraSettings: {general: {enable_metrics: false}}` stops collecting the data behind `/stats`.
* **`/metrics` is not open, and cannot be opened without a password.** Upstream gates it on `general.open_metrics`, which is empty by default, so the route returns `404` as shipped. Setting it through `extraSettings` enables the route and requires that password over HTTP basic auth.
* **Create the signing-key secret before installing, and treat it as write-once.** A missing secret wedges the deployment with zero log output; rotating it invalidates every saved preference cookie.
* **`redis.redis.replicas` must stay `1`, and `limiter.enabled` requires `redis.enabled`.** Both are enforced at render time, so a bad combination fails the install rather than shipping a silently unlimited instance.
* **The datastore holds no durable data.** If it restarts, limiter counters reset and nothing is lost, because search results were never stored there.
* **Going public throttles your own results.** Upstream engines answer heavy or bot-like traffic with CAPTCHAs and rate limits, which shows up as fewer results rather than an error. A limiter and a modest instance are what keep result quality up.
* **The first `helm upgrade` after an install can re-apply resources that did not change**, including the bundled datastore, which bounces those workloads once. Values were byte-identical across the re-apply in testing, and later upgrades of the same release report everything unchanged. At `replicas: 1` budget a brief blip on that first upgrade.
* **Firewall changes take effect after a delay** — flipping `publicAccess.enabled` or `internalAccess.type` can take from twenty seconds to a couple of minutes to be enforced after the upgrade reports success.
* **Install into a single-location GVC unless you mean otherwise.** A workload runs in every location its GVC has, so extra locations multiply both the instance count and the outbound query volume upstream engines see from you.
* **Uninstalling removes everything the template created** — workloads, secrets, identity, and policy, with no volume sets left behind. Your own signing-key secret survives, so a reinstall against the same name keeps preference cookies valid.

## External References

<CardGroup cols={2}>
  <Card title="SearXNG Project" icon="globe" href="https://searxng.org/">
    Project home, public instance list, and overview
  </Card>

  <Card title="Settings Reference" icon="sliders" href="https://docs.searxng.org/admin/settings/index.html">
    Every key that can be set through `extraSettings`
  </Card>

  <Card title="Server Settings" icon="server" href="https://docs.searxng.org/admin/settings/settings_server.html">
    The `server.*` block, including the limiter and image proxy
  </Card>

  <Card title="The Limiter" icon="shield" href="https://docs.searxng.org/admin/searx.limiter.html">
    How bot detection and rate limiting work upstream
  </Card>

  <Card title="Search API" icon="code" href="https://docs.searxng.org/dev/search_api.html">
    Parameters and response format for `/search`
  </Card>

  <Card title="SearXNG Template" icon="github" href="https://github.com/controlplane-com/templates/tree/main/searxng">
    View the source files, default values, and chart definition
  </Card>
</CardGroup>
