SSD Nodes Learn 8GB di RAM — $66/anno
Guide Matt ConnorDi Matt Connor · Aggiornato 2026-08-02

SearXNG privato: installazione con Docker Compose

Installa SearXNG sul tuo VPS con Docker Compose: configura settings.yml e limiter, abilita nginx con TLS e usa l'API JSON nei tuoi script.

Cosa stai configurando

Gestire autonomamente SearXNG ti offre un motore di ricerca privato che viene eseguito sul tuo server. SearXNG è un metamotore di ricerca: prende la tua query, interroga altri motori come Google, Bing, DuckDuckGo e Wikipedia, quindi unisce i risultati in un’unica pagina. Non viene creato alcun profilo e non viene impostato alcun cookie di tracciamento, perché l’unica macchina che conserva la tua query è la tua.

Lo stack è ridotto. Due container, un file di configurazione e un reverse proxy. La decisione principale riguarda la privacy dell’istanza: privata, cioè raggiungibile solo da te e dai tuoi script, oppure pubblica, cioè interrogabile da chiunque su internet. Questa scelta modifica le impostazioni di sicurezza, quindi prendila prima di digitare qualsiasi comando. La scelta predefinita è privata.

C’è un secondo motivo per eseguire un’istanza. SearXNG espone un’API JSON, quindi qualsiasi script o agente AI che scrivi può usare un’API di ricerca di tua proprietà, senza chiavi, costi per query o messaggi relativi alle quote.

Installare SearXNG con Docker Compose

Il progetto pubblica un'immagine del container e un file Compose. Scaricali entrambi su un server Ubuntu 24.04 appena installato, che disponga già di Docker Engine e del plugin Compose. Se Docker è una novità per te, inizia da Nozioni di base su Docker Compose su un VPS e poi torna qui.

sudo install -d -o "$USER" -g "$USER" -m 750 /opt/searxng
cd /opt/searxng
mkdir -p core-config
curl -fsSL \
  -O https://raw.githubusercontent.com/searxng/searxng/master/container/docker-compose.yml \
  -O https://raw.githubusercontent.com/searxng/searxng/master/container/.env.example
cp -i .env.example .env

Il file Compose definisce due servizi. core è SearXNG, mentre valkey è un archivio dati in memoria usato per limitare la frequenza delle richieste e per lo stato temporaneo. Esegue il mount di ./core-config/ in /etc/searxng/ all'interno del container, quindi tutta la configurazione si trova in un'unica directory sull'host.

Ora modifica .env. Tutte le righe dell'esempio fornito sono commentate. Per questo il container si avvia sulla porta 8080 su ogni indirizzo. Decommenta e imposta questi tre valori.

SEARXNG_VERSION=latest
SEARXNG_HOST=127.0.0.1
SEARXNG_PORT=8080

SEARXNG_HOST=127.0.0.1 è l'impostazione più importante. Pubblica la porta 127.0.0.1:8080:8080 invece di [::]:8080:8080, quindi il container risponde solo sull'indirizzo di loopback e Internet non può raggiungerlo direttamente. Se ometti questa impostazione, il container viene esposto non appena si avvia, perché una porta Docker pubblicata viene inserita prima delle regole del firewall. Questo rischio merita una lettura completa: le porte Docker pubblicate bypassano ufw.

SEARXNG_VERSION=latest va bene durante la fase di apprendimento. Su un server importante, blocca il tag a una versione specifica. A luglio 2026 i tag delle release sono basati sulla data e hanno un formato simile a 2026.3.25-541c6c3cb. In questo modo un deployment con versione bloccata viene aggiornato quando lo decidi tu, non quando cambia il registry.

settings.yml: le parti importanti

Crea core-config/settings.yml prima del primo avvio. use_default_settings: true indica a SearXNG di caricare i valori predefiniti inclusi nel prodotto e di applicare solo le chiavi scritte nel file. In questo modo il file resta breve e continua a funzionare dopo gli aggiornamenti che aggiungono nuove opzioni.

Genera prima il segreto, perché il valore viene inserito direttamente nel file.

openssl rand -hex 32
use_default_settings: true

general:
  instance_name: "search.example.com"

server:
  base_url: "https://search.example.com/"
  secret_key: "paste-the-openssl-output-here"
  limiter: false
  public_instance: false
  image_proxy: true

valkey:
  url: valkey://valkey:6379/0

search:
  safe_search: 0
  autocomplete: "duckduckgo"
  formats:
    - html
    - json

secret_key firma i dati delle sessioni e dei token. Il valore predefinito incluso nel prodotto è la stringa letterale ultrasecretkey. Se lo lasci invariato, chiunque conosca quel valore predefinito può falsificare quei token. Sostituiscilo una volta e poi non modificarlo più: cambiarlo in seguito elimina tutte le preferenze salvate.

base_url deve essere l'indirizzo HTTPS pubblico, con la barra finale. SearXNG lo inserisce nei link che genera. Se lo lasci puntato a localhost, il link "pagina successiva" visualizzato in un browser remoto punta al computer dell'utente e non funziona.

formats determina i tipi di output che l'endpoint web produrrà. json non è incluso nell'elenco predefinito, quindi una richiesta JSON restituisce 403 finché non lo aggiungi. image_proxy: true inoltra le miniature dei risultati attraverso il tuo server, perciò i siti che ospitano quelle immagini non vedono gli indirizzi dei tuoi visitatori.

Il valkey.url usa il nome host valkey perché questo è il nome del servizio nel file Compose. Compose inserisce entrambi i container nella stessa rete, dove i nomi dei servizi vengono risolti. Se lo punti a localhost, il limitatore non funziona, perché all'interno del container core localhost indica quel container.

Il segreto si trova in un file in chiaro. Proteggi quindi la directory che lo contiene, anziché il file stesso. chmod 750 /opt/searxng impedisce l'accesso agli altri utenti dell'host. Non impostare core-config/settings.yml sulla modalità 600: il container viene eseguito con un utente non privilegiato proprio e, se non può leggere il file, SearXNG non si avvia.

Avvia lo stack e verifica il risultato.

cd /opt/searxng
docker compose up -d
docker compose ps
curl -I http://127.0.0.1:8080/

docker compose ps dovrebbe mostrare entrambi i container nello stato running. curl dovrebbe rispondere con HTTP/1.1 200 OK. Se non restituisce alcuna risposta, leggi docker compose logs core, perché un errore YAML in settings.yml viene mostrato lì come un errore di analisi che indica la riga.

Configuralo dietro nginx con TLS

Il container resta in ascolto solo sull'interfaccia di loopback. nginx lo rende raggiungibile e aggiunge anche la sicurezza del livello di trasporto (TLS). Scrivi /etc/nginx/sites-available/searxng.

server {
    listen 80;
    server_name search.example.com;

    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}
sudo ln -s /etc/nginx/sites-available/searxng /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
sudo certbot --nginx -d search.example.com

nginx -t stampa syntax is ok e test is successful prima del reload. Certbot riscrive lo stesso file per mettersi in ascolto sulla porta 443 con un certificato e aggiunge un reindirizzamento dalla porta 80. Il record DNS di search.example.com deve già puntare a questo server, perché l'autorità di certificazione verifica la proprietà recuperando un file tramite HTTP. La procedura completa, incluso il rinnovo, è disponibile nella guida a Certbot e nginx per Ubuntu 24.04.

I due header di inoltro non sono decorativi. Senza X-Forwarded-For e X-Real-IP, ogni richiesta che arriva a SearXNG contiene l'indirizzo del proxy. Di conseguenza, il limitatore della frequenza vede un solo client che genera tutto il traffico e non riesce a distinguere i visitatori.

Perché gli script e gli agenti richiedono un'API di ricerca JSON

Con json in formats, lo stesso endpoint che visualizza la pagina restituisce dati strutturati.

curl -s 'http://127.0.0.1:8080/search?q=wireguard+mtu&format=json' \
  | jq -r '.results[0:5][] | .url'

Ricevi un oggetto con un array results, in cui ogni voce contiene url, title, content e il motore che l'ha fornita, insieme a answers, infoboxes e suggestions. Questo è sufficiente per alimentare un sistema di riepilogo, un verificatore di collegamenti o un ciclo di ricerca.

Questo è importante per qualsiasi applicazione basata su agenti. Un modello linguistico ha un limite temporale nei dati di addestramento, quindi richiede la ricerca in tempo reale per rispondere a domande sul presente. Le API di ricerca commerciali addebitano il costo per ogni query e applicano limiti di frequenza rigidi. Un'istanza locale richiede un solo container su un server che già paghi e le query non lo lasciano mai. Se stai collegando strumenti a un modello, lo stesso ragionamento porta a eseguire server MCP su un VPS, dove uno strumento di ricerca è spesso il primo che viene aggiunto.

Per usare l'API, segui due regole. Mantieni privata l'istanza: associa il lato API all'indirizzo di loopback o a una rete privata e consenti l'accesso solo ai tuoi host. Poi invia le query con moderazione. SearXNG inoltra la tua richiesta ai motori di ricerca reali, quindi uno script che esegue cento query al secondo sta chiedendo a Google di bloccare il tuo server.

Il limitatore e cosa cambia per un'istanza pubblica

Il limitatore è il meccanismo di difesa anti-bot di SearXNG. Controlla le intestazioni delle richieste, gli indirizzi e la frequenza delle richieste, quindi scarta il traffico che sembra automatizzato. Per conservare questo stato ha bisogno di Valkey, motivo per cui il file Compose lo include.

Su un'istanza privata mantieni limiter: false. I tuoi script sono per definizione traffico automatizzato, quindi il limitatore bloccherebbe proprio le richieste JSON per cui hai creato l'istanza. Il controllo degli accessi spetta invece al reverse proxy: puoi usare una coppia allow e deny nella configurazione nginx location, l'autenticazione HTTP di base oppure un firewall che consenta l'accesso solo agli altri tuoi server.

Se pubblichi l'istanza per altre persone, attiva entrambe le opzioni.

server:
  limiter: true
  public_instance: true

Un controllo più dettagliato si trova in core-config/limiter.toml, che il container legge da /etc/searxng/limiter.toml. Devi scrivere solo le chiavi che vuoi modificare. Se usi un proxy, devi dichiararlo; altrimenti il limitatore considera l'indirizzo del tuo nginx come quello dell'unico client che genera traffico abusivo.

[botdetection]
trusted_proxies = [
  '127.0.0.0/8',
  '::1',
]

[botdetection.ip_limit]
link_token = true

link_token = true fa sì che SearXNG generi un token che solo una sessione reale del browser può recuperare, bloccando la maggior parte degli scraper più semplici. Prevedi che un'istanza pubblica inizi ad attirarli entro pochi giorni. Prevedi anche errori dei motori, perché più traffico inoltri, più rapidamente i motori upstream inizieranno a restituire CAPTCHA all'indirizzo del tuo server. Un'istanza pubblica di SearXNG richiede attività continuativa. Un'istanza privata no; per questo compare nella maggior parte degli elenchi brevi di cose che vale la pena ospitare autonomamente nel 2026.

Perché le ricerche non restituiscono risultati

Apri /stats nella tua istanza. Elenca tutti i motori con il relativo tasso di errore e tempo di risposta. È il primo punto da controllare quando i risultati sono scarsi.

Un motore che mostra errori "Access denied" o "CAPTCHA" ha bloccato l'indirizzo del server. Questo è comune per gli indirizzi appartenenti a intervalli di un data centre, perché i motori di ricerca presumono che siano utilizzati da scraper. SearXNG sospende quindi il motore in errore per un certo periodo invece di riprovare. Un motore bloccato scompare così dai risultati senza segnali evidenti. Disabilitalo in settings.yml oppure accetta la perdita. Gli altri motori continuano a rispondere.

Se tutti i motori falliscono contemporaneamente, il container non dispone di una risoluzione dei nomi in uscita funzionante oppure non ha una route verso Internet. Esegui il test dall'interno del container.

docker compose exec core wget -qO- https://duckduckgo.com > /dev/null && echo ok

FAQ

SearXNG rende anonime le mie ricerche?

Nasconde la tua identità ai motori a cui invia le query, perché vedono il tuo server effettuare la richiesta invece del tuo browser. Non nasconde la query al tuo server e non nasconde il tuo server ai motori. In un'istanza usata da un solo utente, tutto il traffico proveniente da quell'indirizzo è tuo, quindi l'indirizzo stesso diventa l'identificatore. Il traffico tra il browser e l'istanza è protetto dal certificato TLS.

Perché una richiesta JSON restituisce 403 Forbidden?

Le cause sono due, ed entrambe dipendono dalla configurazione. json non è incluso nell'elenco formats sotto search: in settings.yml, che è lo stato predefinito, oppure il limiter è attivo e ha classificato lo script come bot. Aggiungi prima il formato, riavvia con docker compose restart core e riprova. Se il problema persiste, imposta limiter: false e gestisci il controllo degli accessi nel reverse proxy.

Ho bisogno del container Valkey se tengo disattivato il limiter?

Lascialo in esecuzione. SearXNG funziona anche senza, ma non puoi attivare in seguito il limiter senza di esso e il container conserva anche altri dati temporanei. Il container è piccolo e memorizza solo dati nella cache, quindi rimuoverlo fa risparmiare molto poco e ti fa perdere questa possibilità.

Come aggiorno SearXNG?

Esegui docker compose pull e poi docker compose up -d in /opt/searxng. Compose ricrea ogni container la cui immagine è cambiata e lascia invariata la directory core-config/, quindi settings.yml rimane disponibile. Poiché use_default_settings: true unisce le tue chiavi ai valori predefiniti forniti, le opzioni aggiunte upstream vengono applicate con valori appropriati invece di causare errori nel file.

Più persone possono condividere la stessa istanza?

Sì. Questo è il caso in cui devi attivare il limiter e impostare public_instance: true. Le preferenze vengono memorizzate nel browser di ogni visitatore, quindi non devi gestire account. Monitora /stats per una settimana dopo aver reso l'istanza accessibile, perché i motori upstream iniziano a rifiutare le richieste del tuo server molto prima che tu noti l'assenza di risultati.

#searxng#search#privacy#self-hosting#docker