SearXNG na własnym VPS: prywatna wyszukiwarka
Uruchom SearXNG na VPS za pomocą Docker Compose. Skonfiguruj settings.yml, limiter, nginx z TLS oraz JSON API wywoływane przez własne skrypty.
Co jest budowane
Samodzielne hostowanie SearXNG zapewnia prywatną wyszukiwarkę działającą na własnym serwerze. SearXNG jest metawyszukiwarką: przekazuje zapytanie do innych wyszukiwarek, takich jak Google, Bing, DuckDuckGo i Wikipedia, a następnie łączy otrzymane wyniki na jednej stronie. Nie jest tworzony profil ani ustawiany plik cookie do śledzenia, ponieważ jedyną maszyną przechowującą zapytanie jest własny serwer.
Stos jest niewielki. Obejmuje dwa kontenery, jeden plik ustawień i jeden reverse proxy. Najważniejszą decyzją jest określenie, czy instancja ma być prywatna, czyli dostępna tylko dla użytkownika i jego własnych skryptów, czy publiczna, czyli dostępna dla każdego w internecie. Wybór ten zmienia ustawienia zabezpieczeń, dlatego należy podjąć go przed wprowadzeniem jakichkolwiek danych. Domyślnie należy wybrać tryb prywatny.
Istnieje drugi powód, aby uruchomić własną instancję. Instancja SearXNG obsługuje JSON, dzięki czemu każdy napisany skrypt lub agent AI otrzymuje własne API wyszukiwania, bez klucza, opłat za pojedyncze zapytania i wiadomości o limitach.
Instalacja SearXNG za pomocą Docker Compose
Projekt udostępnia obraz kontenera oraz plik Compose. Pobierz oba elementy na nowy serwer Ubuntu 24.04, na którym jest już zainstalowany Docker Engine wraz z wtyczką Compose. Jeśli Docker jest nowym narzędziem, rozpocznij od podstaw Docker Compose na VPS i wróć tutaj.
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 .envPlik Compose definiuje dwie usługi. core to sam SearXNG, a valkey to magazyn danych w pamięci używany do ograniczania częstotliwości żądań oraz przechowywania krótkotrwałego stanu. Montuje on ./core-config/ w /etc/searxng/ wewnątrz kontenera, dlatego cała konfiguracja znajduje się w jednym katalogu na hoście.
Teraz edytuj .env. Każdy wiersz w dostarczonym przykładzie jest zakomentowany. Z tego powodu kontener uruchamia się na porcie 8080 na każdym adresie. Usuń znaki komentarza i ustaw poniższe trzy wartości.
SEARXNG_VERSION=latest
SEARXNG_HOST=127.0.0.1
SEARXNG_PORT=8080SEARXNG_HOST=127.0.0.1 ma kluczowe znaczenie. Powoduje publikowanie portu 127.0.0.1:8080:8080 zamiast [::]:8080:8080, dzięki czemu kontener odpowiada tylko na adresie loopback i nie można uzyskać do niego bezpośredniego dostępu z Internetu. Jeśli pominiesz ten krok, kontener zostanie udostępniony natychmiast po uruchomieniu, ponieważ opublikowany port Docker jest umieszczany przed regułami zapory sieciowej. Ten problem opisano szczegółowo tutaj: opublikowane porty Docker omijają ufw.
SEARXNG_VERSION=latest jest odpowiednią wartością podczas nauki. Na serwerze, który ma znaczenie produkcyjne, przypnij tag. W lipcu 2026 tagi wydań są oparte na dacie i mają format taki jak 2026.3.25-541c6c3cb. Dzięki temu przypięte wdrożenie zostanie zaktualizowane wtedy, gdy zdecydujesz, a nie wtedy, gdy zmieni się zawartość rejestru.
settings.yml: najważniejsze elementy
Utwórz core-config/settings.yml przed pierwszym uruchomieniem. use_default_settings: true nakazuje SearXNG wczytać dostarczone ustawienia domyślne, a następnie zastosować tylko określone klucze. Dzięki temu plik pozostaje krótki i zachowuje zgodność z aktualizacjami, które dodają nowe opcje.
Najpierw wygeneruj sekret, ponieważ jego wartość zostanie bezpośrednio wpisana do pliku.
openssl rand -hex 32use_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
- jsonsecret_key służy do podpisywania danych sesji i tokenów. Dostarczoną wartością domyślną jest dosłowny ciąg ultrasecretkey. Pozostawienie tej wartości umożliwia każdemu, kto ją zna, fałszowanie tych tokenów. Zastąp ją raz i pozostaw bez zmian. Późniejsza zmiana usuwa wszystkie zapisane preferencje.
base_url musi być publicznym adresem HTTPS zakończonym ukośnikiem. SearXNG umieszcza ten adres w generowanych odnośnikach. Jeśli pozostanie ustawiony na localhost, odnośnik „następna strona” w zdalnej przeglądarce będzie wskazywać komputer użytkownika i nie zadziała.
formats określa typy danych wyjściowych generowanych przez endpoint sieciowy. json nie znajduje się na liście domyślnej, dlatego żądanie JSON zwraca kod 403 do czasu jego dodania. image_proxy: true przekazuje miniatury wyników przez serwer, dzięki czemu witryny hostujące te obrazy nie poznają adresów użytkowników.
valkey.url używa nazwy hosta valkey, ponieważ jest to nazwa usługi w pliku Compose. Compose umieszcza oba kontenery w jednej sieci, w której nazwy usług są rozwiązywane. Wskazanie localhost powoduje awarię ogranicznika, ponieważ wewnątrz kontenera core localhost oznacza ten kontener.
Sekret znajduje się w zwykłym pliku, dlatego należy zabezpieczyć katalog, w którym się znajduje, zamiast samego pliku. chmod 750 /opt/searxng uniemożliwia dostęp innym użytkownikom hosta. Nie ustawiaj core-config/settings.yml na tryb 600. Kontener działa jako własny użytkownik bez uprawnień, a brak możliwości odczytu pliku uniemożliwia uruchomienie SearXNG.
Uruchom stos i sprawdź jego stan.
cd /opt/searxng
docker compose up -d
docker compose ps
curl -I http://127.0.0.1:8080/docker compose ps powinno wyświetlić oba kontenery w stanie running. curl powinien odpowiadać pod adresem HTTP/1.1 200 OK. Jeśli nie odpowiada, odczytaj docker compose logs core, ponieważ błąd YAML w settings.yml pojawi się tam jako błąd analizy składni wskazujący numer wiersza.
Umieść usługę za nginx z TLS
Kontener nasłuchuje wyłącznie na interfejsie loopback, dlatego nginx zapewnia jego dostępność. nginx dodaje również zabezpieczenia warstwy transportowej (TLS). Zapisz /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.comnginx -t wyświetla syntax is ok i test is successful przed ponownym załadowaniem konfiguracji. Certbot przepisuje ten sam plik, aby nasłuchiwał na porcie 443 z certyfikatem, oraz dodaje przekierowanie z portu 80. Rekord DNS dla search.example.com musi już wskazywać na ten serwer, ponieważ urząd certyfikacji potwierdza własność, pobierając plik przez HTTP. Pełna instrukcja, w tym odnawianie certyfikatu, znajduje się w przewodniku dotyczącym Certbot i nginx dla Ubuntu 24.04.
Dwa nagłówki przekazywania nie są zbędne. Bez X-Forwarded-For i X-Real-IP każde żądanie docierające do SearXNG zawiera adres proxy. W rezultacie ogranicznik szybkości widzi jednego klienta generującego cały ruch i nie może rozróżnić odwiedzających.
Dlaczego skrypty i agenty potrzebują interfejsu API wyszukiwania w formacie JSON
W przypadku json w formats ten sam endpoint, który renderuje stronę, zwraca dane strukturalne.
curl -s 'http://127.0.0.1:8080/search?q=wireguard+mtu&format=json' \
| jq -r '.results[0:5][] | .url'Otrzymywany jest obiekt z tablicą results, w której każdy wpis zawiera url, title, content oraz silnik, który dostarczył wynik, a także answers, infoboxes i suggestions. To wystarcza do zasilenia modułu podsumowującego, narzędzia do sprawdzania łączy lub pętli badawczej.
Ma to znaczenie w przypadku rozwiązań wykorzystujących agenty. Model językowy ma określoną datę odcięcia danych treningowych, dlatego do odpowiadania na pytania dotyczące bieżących wydarzeń potrzebuje wyszukiwania na żywo. Komercyjne interfejsy API wyszukiwania naliczają opłaty za każde zapytanie i stosują ścisłe ograniczenia częstotliwości. Lokalna instancja wymaga tylko jednego kontenera na serwerze, za który już się płaci, a zapytania nie opuszczają tego środowiska. W przypadku integrowania narzędzi z modelem ta sama zasada dotyczy uruchamiania serwerów MCP na VPS, gdzie narzędzie wyszukiwania jest zwykle pierwszym dodawanym narzędziem.
W przypadku korzystania z API obowiązują dwie zasady. Instancja powinna pozostać prywatna. Należy powiązać stronę API z adresem loopback lub siecią prywatną i zezwolić na dostęp wyłącznie własnym hostom. Zapytania należy wysyłać z umiarkowaną częstotliwością. SearXNG przekazuje żądania do rzeczywistych silników wyszukiwania, dlatego skrypt wykonujący sto zapytań na sekundę może spowodować zablokowanie serwera przez Google.
Ogranicznik i zmiany dotyczące instancji publicznej
Ogranicznik chroni SearXNG przed botami. Monitoruje nagłówki żądań, adresy i częstotliwość żądań. Odrzuca ruch, który wygląda na zautomatyzowany. Do przechowywania tego stanu potrzebuje Valkey. Z tego powodu Valkey znajduje się w pliku Compose.
W przypadku instancji prywatnej należy zachować limiter: false. Własne skrypty są z definicji ruchem zautomatyzowanym, dlatego ogranicznik blokowałby dokładnie te wywołania JSON, do których utworzono instancję. Za kontrolę dostępu powinien odpowiadać odwrotny serwer proxy. Można użyć pary allow i deny w pliku nginx location, uwierzytelniania podstawowego HTTP albo zapory sieciowej, która zezwala na połączenia tylko z pozostałych serwerów.
Jeśli instancja ma być udostępniona innym osobom, należy włączyć oba przełączniki.
server:
limiter: true
public_instance: trueDokładniejszą kontrolę zapewnia core-config/limiter.toml, który kontener odczytuje z /etc/searxng/limiter.toml. Należy zapisać tylko klucze, które mają zostać zmienione. Za serwerem proxy trzeba zadeklarować proxy. W przeciwnym razie ogranicznik uzna adres nginx za adres jedynego klienta generującego nadużycia.
[botdetection]
trusted_proxies = [
'127.0.0.0/8',
'::1',
]
[botdetection.ip_limit]
link_token = truelink_token = true powoduje, że SearXNG wydaje token, który pobiera tylko prawdziwa sesja przeglądarki. Ogranicza to większość prostych scraperów. Należy oczekiwać, że w ciągu kilku dni instancja publiczna zacznie przyciągać takie narzędzia. Należy również oczekiwać błędów silników. Im więcej ruchu jest przekazywane, tym szybciej silniki upstream zaczną zwracać CAPTCHA na adres serwera. Publiczna instancja SearXNG wymaga stałej obsługi. Prywatna instancja jej nie wymaga. Z tego powodu znajduje się na większości krótkich list rzeczy wartych samodzielnego hostowania w 2026 roku.
Dlaczego wyszukiwanie nie zwraca wyników
Otwórz /stats w swojej instancji. Wyświetla on każdy silnik wraz ze wskaźnikiem błędów i czasem odpowiedzi. Jest to pierwsze miejsce, które należy sprawdzić, gdy wyników jest niewiele.
Silnik wyświetlany z błędami „Access denied” lub „CAPTCHA” zablokował adres serwera. Jest to częste w przypadku adresów z zakresów używanych przez centra danych, ponieważ wyszukiwarki zakładają, że należą one do scraperów. SearXNG zawiesza następnie wadliwy silnik na określony czas zamiast ponawiać próbę. Jeden zablokowany silnik przestaje więc niepostrzeżenie dostarczać wyniki. Wyłącz go w settings.yml albo zaakceptuj ten ubytek. Pozostałe silniki nadal odpowiadają.
Jeśli wszystkie silniki przestają działać jednocześnie, kontener nie ma działającego rozpoznawania nazw wychodzącego lub trasy do internetu. Sprawdź to wewnątrz kontenera.
docker compose exec core wget -qO- https://duckduckgo.com > /dev/null && echo okFAQ
Czy SearXNG zapewnia anonimowość wyszukiwania?
Ukrywa tożsamość użytkownika przed wyszukiwarkami, do których kieruje zapytania, ponieważ wyszukiwarki widzą żądanie wysłane przez serwer, a nie przez przeglądarkę. Nie ukrywa zapytania przed serwerem i nie ukrywa serwera przed wyszukiwarkami. W przypadku instancji używanej przez jednego użytkownika cały ruch z tego adresu pochodzi od tego użytkownika, dlatego sam adres staje się identyfikatorem. Ruch między przeglądarką a instancją jest chroniony certyfikatem TLS.
Dlaczego żądanie JSON zwraca błąd 403 Forbidden?
Występują dwie przyczyny i obie dotyczą konfiguracji. Albo json brakuje na liście formats w sekcji search: pliku settings.yml, co jest stanem domyślnym, albo limiter jest włączony i sklasyfikował skrypt jako bota. Najpierw dodaj format, uruchom ponownie usługę za pomocą docker compose restart core, a następnie spróbuj ponownie. Jeśli problem nadal występuje, ustaw limiter: false i kontroluj dostęp w reverse proxy.
Czy kontener Valkey jest potrzebny, jeśli limiter pozostaje wyłączony?
Należy pozostawić go uruchomionego. SearXNG działa bez niego, ale bez tego kontenera nie można później włączyć limitera. Kontener przechowuje także inne dane o krótkim czasie życia. Jest mały i przechowuje wyłącznie dane w pamięci podręcznej, dlatego jego usunięcie zapewnia niewielką oszczędność i pozbawia możliwości późniejszego włączenia limitera.
Jak zaktualizować SearXNG?
Uruchom docker compose pull, a następnie docker compose up -d w /opt/searxng. Compose odtwarza każdy kontener, którego obraz został zmieniony, i pozostawia katalog core-config/ bez zmian, dlatego settings.yml zostaje zachowane. Ponieważ use_default_settings: true scala własne klucze z domyślnymi wartościami dostarczonymi wraz z oprogramowaniem, opcje dodane w nowszej wersji są wprowadzane z odpowiednimi wartościami zamiast powodować uszkodzenie pliku.
Czy jedna instancja może być współużytkowana przez kilka osób?
Tak. W takim przypadku należy włączyć limiter i ustawić public_instance: true. Preferencje są przechowywane w przeglądarce każdego użytkownika, dlatego nie trzeba zarządzać kontami. Po udostępnieniu instancji należy przez tydzień monitorować /stats, ponieważ wyszukiwarki zewnętrzne zaczynają odrzucać żądania serwera na długo przed zauważeniem braku wyników.