SearXNG on Google Kubernetes Engine (GKE Autopilot)
This document provides a comprehensive reference for the modules/SearXNG_GKE Terraform module. It covers architecture, IAM, configuration variables, SearXNG-specific behaviours, and operational patterns for deploying SearXNG on GKE Autopilot.
1. Module Overview
SearXNG is a privacy-respecting, self-hosted metasearch engine with 10,000+ GitHub stars that aggregates results from 70+ search services without tracking users or serving ads. SearXNG GKE is a wrapper module built on top of App GKE. It uses App GKE for all GCP infrastructure provisioning and injects SearXNG-specific application configuration via SearXNG Common.
Key Capabilities:
- Compute: GKE Autopilot, Kubernetes Deployment.
min_instance_count = 1 (hardcoded in searxng.tf), max_instance_count user-configurable (default: 3). Default resources: 500m CPU / 512 Mi.
- Stateless: SearXNG does not use a database. No Cloud SQL instance is provisioned.
- IAM: Workload Identity binds the Kubernetes SA to a GCP SA for Secret Manager access (
SEARXNG_SECRET).
- Redis (optional): Redis for rate limiting and bot detection via
enable_redis.
- SEARXNG_SECRET: Auto-generated by
SearXNG Common and stored in Secret Manager. Injected via the CSI Secret Manager driver.
- Health: Health probes target
/healthz.
Project & Application Identity
| Variable | Group | Type | Default | Description |
|---|
project_id | 1 | string | — | GCP project ID. Required. |
tenant_deployment_id | 2 | string | 'demo' | Short suffix appended to all resource names. |
support_users | 2 | list(string) | [] | Email recipients for monitoring alerts. |
resource_labels | 2 | map(string) | {} | Labels applied to all provisioned resources. |
application_name | 3 | string | 'searxng' | Base resource name. Do not change after initial deployment. |
application_display_name | 3 | string | 'SearXNG Search' | Human-readable name. |
application_description | 3 | string | 'SearXNG — privacy-respecting metasearch engine on GKE Autopilot' | Application description. |
application_version | 3 | string | 'latest' | SearXNG image version tag. |
Wrapper architecture: SearXNG GKE calls SearXNG Common to produce the application configuration. min_instance_count = 1 is hardcoded in the searxng_module merge in searxng.tf. SEARXNG_BIND_ADDRESS, ENABLE_REDIS, and REDIS_URL are injected via module_env_vars. The SEARXNG_SECRET is injected via Kubernetes secret (CSI Secret Manager driver) rather than a direct environment variable reference.
2. IAM & Access Control
Workload Identity binds the Kubernetes SA to a GCP SA. The only Secret Manager secret accessed is SEARXNG_SECRET. SearXNG Common outputs the explicit secret value so the CSI driver can inject it without read-after-write consistency issues on first apply.
3. Core Service Configuration
A. Compute (GKE Autopilot)
| Variable | Group | Default | Description |
|---|
deploy_application | 4 | true | Set false for infrastructure-only deployment. |
container_image_source | 4 | 'prebuilt' | 'prebuilt' (official image) or 'custom'. |
container_image | 4 | "" | Container image URI override. |
container_resources | 4 | { cpu_limit="500m", memory_limit="512Mi" } | CPU/memory limits and requests. |
min_instance_count | 4 | 1 [fixed in searxng.tf] | Minimum pod replicas. Hardcoded to 1 in the module merge. |
max_instance_count | 4 | 3 | Maximum pod replicas. |
container_port | 4 | 8080 | SearXNG's HTTP port. |
enable_vertical_pod_autoscaling | 4 | false | Enables VPA. |
enable_image_mirroring | 4 | true | Mirrors the SearXNG image into Artifact Registry. |
B. GKE Backend Configuration
| Variable | Group | Default | Description |
|---|
gke_cluster_name | — | "" | GKE cluster name. Leave empty to auto-discover. |
namespace_name | — | "" | Kubernetes namespace. Leave empty to auto-generate. |
service_type | — | 'ClusterIP' | Kubernetes Service type. Use 'LoadBalancer' for external access. |
workload_type | — | null | 'Deployment' (default for SearXNG) or 'StatefulSet'. |
C. Environment Variables
| Variable | Group | Default | Description |
|---|
environment_variables | — | {} | Additional plain-text env vars for SearXNG configuration. |
SEARXNG_BIND_ADDRESS, ENABLE_REDIS, and REDIS_URL are injected automatically via module_env_vars.
D. Observability
| Variable | Group | Default | Description |
|---|
startup_probe | — | { path="/healthz", initial_delay_seconds=10, failure_threshold=6 } | Startup probe. |
liveness_probe | — | { path="/healthz", initial_delay_seconds=15, failure_threshold=3 } | Liveness probe. |
4. Redis Integration
| Variable | Group | Default | Description |
|---|
enable_redis | 15 | false | Enables Redis for rate limiting and bot detection. |
redis_host | 15 | "" | Redis hostname/IP. Defaults to 127.0.0.1 when enable_redis = true and no host is specified. |
redis_port | 15 | '6379' | Redis TCP port. |
redis_auth | 15 | "" | Redis AUTH password. Sensitive. |
5. CI/CD
| Variable | Group | Default | Description |
|---|
enable_cicd_trigger | 8 | false | Provisions a Cloud Build GitHub trigger. |
github_repository_url | 8 | "" | Full HTTPS URL of the GitHub repository. |
enable_cloud_deploy | 8 | false | Provisions a Cloud Deploy pipeline. |
Configuration Pitfalls & Sensible Defaults
Risk levels: Critical (data loss, full outage, security breach) — High (service unavailable or significant degradation) — Medium (degraded function or increased cost) — Low (minor impact).
| Variable | Sensible Default | Risk | Consequence of Incorrect Value |
|---|
SEARXNG_SECRET (auto-generated by Common) | (auto-generated — stored in Secret Manager) | Critical | SearXNG uses SEARXNG_SECRET to sign sessions and HMAC parameters. On GKE, the secret is stable (stored in Secret Manager and injected at pod start). However, if the secret is somehow different across pod replicas (e.g., due to a custom override that generates per-pod values), session cookies from one pod are invalid on another pod, breaking load-balanced sessions. Use the auto-generated Secret Manager value — never override with a per-pod random. |
min_instance_count | 1 | High | GKE default is 1 (required). If HPA scales to zero, the next scale-up triggers a cold start with no session continuity. For SearXNG, ensure HPA minimum replicas remain at 1 or more. |
enable_redis | false | High | Without Redis, SearXNG has no rate limiting or result caching. Public-facing deployments without Redis are vulnerable to scraping and upstream API quota exhaustion. Enable Redis and set redis_host for production. |
redis_host | "" | High | When enable_redis = true and redis_host is empty, SearXNG defaults to 127.0.0.1 (no reachable Redis in a GKE pod). Rate limiting and caching are silently disabled. Set to the Memorystore Redis IP from Services GCP. |
memory_limit | "512Mi" | Medium | SearXNG is lightweight but aggregates results from many engines concurrently. Under high load, 256Mi causes OOM kills. Scale to 1Gi for heavy-traffic public instances. |
cpu_limit | "1000m" | Medium | Result aggregation and de-duplication are CPU-bound. Below 500m, high-concurrency requests degrade in latency. |
stateful_pvc_enabled | null | Low | SearXNG is stateless — no PVC is needed. Leave null. Setting stateful_pvc_enabled = true provisions an unused disk, wasting cost. |
workload_type | null | Low | SearXNG is stateless — Deployment is the correct workload type. Using StatefulSet without a PVC is unnecessary and wastes scheduler resources. |
application_version | "latest" | Medium | Using "latest" makes deployments non-reproducible. Pin to a specific SearXNG version for production. |
enable_iap | false | Medium | For internal-only search deployments, enable IAP to restrict access to authenticated users. For public meta-search, rely on Redis rate limiting. |
SerpAPI key / engine API keys (env vars) | (not set) | Medium | Many search engines require API keys for reliable scraping. Inject via secret_environment_variables for production to avoid key exposure in logs. |
quota_memory_requests | "" | Critical | If enable_resource_quota = true and set without binary suffixes (e.g. "4" instead of "4Gi"), Kubernetes treats it as bytes, blocking all pod scheduling. Always use Gi or Mi. |
max_instance_count | 1 | Medium | Multiple SearXNG replicas share Redis for session state. Ensure Redis maxmemory-policy = allkeys-lru to prevent unbounded growth as session keys accumulate across replicas. |
6. Outputs
| Output | Description |
|---|
service_name | Name of the Kubernetes Service. |
service_url | URL of the SearXNG deployment. |
project_id | GCP project ID. |
deployment_id | Deployment ID suffix used in resource names. |