Application Infrastructure Azure

SearXNG on Ubuntu 24.04 on Azure User Guide

| Product: SearXNG Privacy Metasearch Engine on Ubuntu 24.04 LTS on Azure

Overview

SearXNG is a free, open source, privacy-respecting metasearch engine. Instead of profiling you, it forwards your query to 70 plus upstream engines (Google, Bing, DuckDuckGo, Brave, Startpage, Wikipedia and many more), aggregates and de-duplicates the results, and returns them without ever storing your search history, setting tracking cookies or building an advertising profile. The cloudimg image installs SearXNG at a pinned upstream commit into a dedicated Python virtualenv, runs it as a hardened non-root searxng systemd service bound to loopback, and fronts it on port 80 with an nginx reverse proxy that adds a per-VM HTTP Basic Auth gate so the instance is never left open as a public search proxy. A unique Basic Auth password and a fresh SearXNG secret key are generated on the first boot of every VM, and the configuration and secret live on a dedicated Azure data disk. Backed by 24/7 cloudimg support.

What is included:

  • SearXNG (pinned upstream commit) served by the granian WSGI application server as the searxng systemd service, bound to loopback 127.0.0.1:8080
  • An nginx reverse proxy on :80 adding a per-VM HTTP Basic Auth gate (user admin) with a unique password generated on first boot
  • A fresh, random SearXNG secret_key generated per VM on first boot, never the shipped default
  • The JSON search API enabled (format=json) alongside the HTML interface for scripting and integrations
  • The rate limiter disabled for this single-tenant, password-gated instance, so no external Valkey or Redis is required
  • A dedicated Azure data disk at /var/lib/searxng holding the settings, the per-VM secret and the Basic Auth file
  • searxng.service + nginx.service as systemd units, enabled and active
  • An unauthenticated /healthz endpoint for Azure Load Balancer health probes
  • 24/7 cloudimg support

SearXNG is licensed under the GNU Affero General Public License v3 (AGPL-3.0). If you modify SearXNG and offer the modified version to users over a network, the AGPL requires you to make your modified source available to those users. Running the unmodified cloudimg image places no source-distribution obligation on you.

Prerequisites

An active Azure subscription, an SSH key pair, and a VNet plus subnet in the target region. Standard_B2s (2 vCPU / 4 GiB RAM) is a comfortable starting point; SearXNG is light on resources. NSG inbound: allow 22/tcp from your management network, 80/tcp for the web interface, and 443/tcp if you add TLS. SearXNG serves plain HTTP on port 80; for production use, terminate TLS in front of it with your own domain (see Maintenance).

Step 1 - Deploy from the Azure Marketplace

Sign in to the Azure Portal, choose Create a resource, search the Marketplace for SearXNG by cloudimg, and select Create. On Basics pick your subscription, resource group, region and size; under Administrator account choose SSH public key and paste your key; under Inbound port rules allow SSH (22) and HTTP (80). Review the dedicated data disk on the Disks tab, then Review + create -> Create.

Step 2 - Deploy from the Azure CLI

az vm create \
  --resource-group <your-rg> \
  --name searxng \
  --image <marketplace-image-urn> \
  --size Standard_B2s \
  --admin-username azureuser \
  --ssh-key-values ~/.ssh/id_ed25519.pub \
  --vnet-name <your-vnet> --subnet <your-subnet> \
  --public-ip-sku Standard

az vm open-port --resource-group <your-rg> --name searxng --port 80 --priority 1010

Step 3 - Connect to your VM

ssh azureuser@<vm-public-ip>

Step 4 - Confirm the services are running

systemctl is-active searxng.service nginx.service

Both report active. SearXNG runs under the granian WSGI server as the dedicated searxng user, bound to the loopback connector 127.0.0.1:8080; nginx fronts it on port 80, adds the per-VM HTTP Basic Auth gate, and exposes an unauthenticated /healthz. SearXNG's settings, its per-VM secret key and the Basic Auth file all live on the dedicated Azure data disk mounted at /var/lib/searxng.

The searxng and nginx services reporting active, the loopback SearXNG listener on 127.0.0.1:8080 behind nginx on port 80, the dedicated data disk mounted at /var/lib/searxng, and the pinned SearXNG commit

Step 5 - Retrieve your password

nginx protects SearXNG with HTTP Basic Auth. The username is admin and a unique password is generated on the first boot of your VM and written to a root-only file:

sudo cat /root/searxng-credentials.txt

This file contains SEARXNG_USERNAME, SEARXNG_PASSWORD and the SEARXNG_URL to open in a browser. The password is stored on disk only as a bcrypt hash in /var/lib/searxng/.htpasswd, so no plaintext password ships in the image, and the SearXNG secret_key is rotated to a fresh random value on first boot rather than the shipped default. Store the password somewhere safe.

The rolling SearXNG version, the per-VM credentials file with the generated admin password and URL, the per-VM secret_key rotated away from the shipped default, and the bcrypt .htpasswd entry proving no plaintext password ships

Step 6 - Confirm the health endpoint

nginx serves an unauthenticated health endpoint for load balancers and probes:

curl -s http://localhost/healthz

It returns ok. This endpoint never requires authentication, so it is safe for an Azure Load Balancer health probe.

Step 7 - Confirm authentication and the JSON search API

Because a password is set on first boot, an unauthenticated request returns HTTP 401, so nobody reaches your instance without the password. The following reads the per-VM password from the credentials file and proves the round-trip - unauthenticated is rejected, the correct password authenticates, and an authenticated JSON search returns aggregated results:

PW=$(sudo grep '^SEARXNG_PASSWORD=' /root/searxng-credentials.txt | cut -d= -f2-)
echo "unauth : $(curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1/)"
echo "authed : $(curl -s -o /dev/null -w '%{http_code}' -u admin:$PW http://127.0.0.1/)"
curl -s -u admin:$PW 'http://127.0.0.1/search?q=privacy&format=json' \
  | python3 -c 'import sys,json; d=json.load(sys.stdin); print("results:", len(d.get("results", [])))'

It prints unauth : 401, then authed : 200, then a non-zero result count. The format=json endpoint is enabled on this image so you can drive SearXNG from scripts and integrations; the same query without format=json returns the HTML results page.

The HTTP Basic Auth round-trip returning 401 unauthenticated, 401 for a wrong password and 200 with the per-VM password, followed by an authenticated JSON search returning the query and aggregated result count with the contributing engines

Step 8 - Sign in and open the search page

Browse to http://<vm-public-ip>/. Your browser prompts for a username and password: enter admin and the password from Step 5. SearXNG opens on its clean search home - a single search box with no ads, no tracking and no cookies set until you choose to save preferences. The About and Preferences links sit in the top corner, and the footer shows the running version.

The SearXNG search home page behind the Basic Auth gate, showing the SearXNG logo, the central search box, the About and Preferences links, and the version in the footer

Step 9 - Run a private search

Type a query and press Enter. SearXNG queries the upstream engines in parallel, aggregates and de-duplicates the results, and shows them grouped by category (General, Images, Videos, News, Map, Music, IT, Science, Files, Social Media). Each result lists which engines returned it and offers a cached link, and the right-hand column shows the response time and suggestions. Your query is never logged or tied to a profile.

A SearXNG results page for a sample query showing aggregated, de-duplicated results with per-result engine attribution, the category tabs across the top, and the response time and suggestions panel on the right

Step 10 - Tune engines and preferences

Open Preferences to tailor the instance. From here you set the default categories and search language, choose an autocomplete backend, toggle SafeSearch, and - on the Engines tab - enable or disable any of the 70 plus upstream engines and see their reliability. Preferences are stored in your browser (or an opt-in cookie), so different users of the same instance can keep their own settings.

The SearXNG Preferences page open on the General tab, showing default categories, search language, the duckduckgo autocomplete backend, SafeSearch and the Engines, Privacy and Cookies tabs

Step 11 - Review the engine stats

The Engine stats page (linked from the footer) reports, for every enabled engine, its result count, median response time and a reliability score, so you can see at a glance which engines are healthy and drop any that a network or upstream block is slowing down.

The SearXNG Engine stats page listing each upstream engine with its scores, result count, response time and reliability, so unhealthy engines are easy to spot

Step 12 - Review the configuration and data disk

SearXNG's settings.yml, the per-VM secret key (searxng.env) and the Basic Auth file (.htpasswd) live on the dedicated Azure data disk at /var/lib/searxng, so they are captured into the image and re-provisioned on every VM:

sudo ls -la /var/lib/searxng/
grep -E 'bind_address|port:|limiter|method:|- html|- json' /var/lib/searxng/settings.yml

The settings bind SearXNG to loopback 127.0.0.1:8080, disable the rate limiter (so no Valkey or Redis is needed for this single-tenant, password-gated instance), and enable both the html and json response formats. To repoint SearXNG at a different set of engines or change the instance name, edit settings.yml and run sudo systemctl restart searxng.

The SearXNG data disk mounted at /var/lib/searxng showing the settings.yml, the per-VM searxng.env secret and the bcrypt .htpasswd, plus the key settings values and the enabled systemd units

Maintenance

  • Change the password: regenerate the Basic Auth file with sudo htpasswd -B /var/lib/searxng/.htpasswd admin, then update /root/searxng-credentials.txt for your records.
  • Add engines or change settings: edit /var/lib/searxng/settings.yml (it merges over SearXNG's shipped defaults via use_default_settings: true) and run sudo systemctl restart searxng.
  • Add TLS for production: put your own domain in front of nginx and terminate TLS with a certificate from your CA or Let's Encrypt, then set server.base_url in settings.yml to your https:// URL.
  • Updates: SearXNG is a rolling release pinned to a specific upstream commit in this image for reproducibility. cloudimg publishes refreshed images; for security patches apply OS updates with sudo apt update && sudo apt upgrade.
  • Rate limiting: this image disables the limiter because the nginx Basic Auth gate already restricts access. If you open the instance more widely, enable server.limiter in settings.yml and provision a Valkey instance per the SearXNG documentation.

Support

This image is maintained by cloudimg with 24/7 support. For help deploying or operating SearXNG on Azure, contact cloudimg support through the Azure Marketplace listing.