VPS Tutorials
Self-Host Perplexica Private AI Search Engine on a VPS (2026): SearXNG, Docker, Ollama/OpenAI and HTTPS Deployment Guide
This tutorial explains how to self-host Perplexica / Vane on a VPS to build a private AI search engine similar to Perplexity. It covers the SearXNG search backend, single-container Docker deployment, an advanced standalone SearXNG setup, OpenAI/Ollama model integration, Caddy HTTPS, search privacy, backup and upgrade, and common issues such as 502 errors, no search results, and model connection failures.

These days, when I look things up, I increasingly stop relying only on traditional search results pages.
It's not that search engines have become useless, but that many questions simply aren't suited to clicking through page after page: for example, "how do I deploy a certain tool," "how do I fix this error," or "what's the difference between several approaches." A normal search gives you 10 links, and you still have to open them yourself, compare them, and filter out ads and outdated articles.
AI search tools like Perplexity became popular precisely because they combine "search + summary + cited sources" into one.
But the problem is also obvious: what you search, what you click, and what you ask are, by default, all on someone else's platform.
If you want an AI search entry point that you control yourself, take a look at Perplexica. The project is now gradually using the name Vane on GitHub, but many people still search by the old name Perplexica. For ease of understanding, I'll mainly call it Perplexica below.
Its approach is straightforward:
- Use SearXNG as the search backend
- Use a large model to organize the search results
- Give you an answer with cited sources
- Can connect to OpenAI, Claude, Groq, or local Ollama models
This article covers VPS self-hosting: how to deploy, what configuration you need, how to set up HTTPS, why SearXNG's JSON is critical, and which pitfalls to avoid.
Perplexica is not an ordinary search engine, nor is it a pure chatbot.
It fits scenarios like these:
| Need | Suitable for Perplexica | Reason |
|---|---|---|
| Want to self-build an AI search similar to Perplexity | Suitable | Search results are organized into answers by the model |
| Want to reduce search behavior being recorded by platforms | Suitable | The search entry point and SearXNG are both on your own VPS |
| SEO, competitor, and technical material research | Suitable | Can quickly aggregate multiple sources |
| Just want to set up an ordinary search box | Not necessarily | SearXNG alone is lighter |
| Want private document Q&A | Not very suitable | AnythingLLM / Dify are more suitable |
| Want to run fully local AI search | Possible, but the machine must be big enough | Local Ollama inference is very resource-intensive |
I understand it as: SearXNG is responsible for finding material, and the large model is responsible for reading it.
If you just want to search web pages, SearXNG is enough. If you want to get answers with sources directly after searching, then Perplexica makes sense.
Here too, there are two cases.
If you use APIs like OpenAI, Claude, Groq, or OpenRouter, the VPS load is not heavy.
The VPS mainly runs:
- Perplexica / Vane web application
- Built-in or standalone SearXNG
- SQLite / configuration data
- Reverse proxy and HTTPS
Recommended configuration:
| Usage | VPS configuration |
|---|---|
| Personal testing | 1 core / 2GB / 20GB SSD |
| Long-term personal use | 2 cores / 4GB / 40GB SSD |
| Multi-user use | 4 cores / 8GB / 80GB SSD |
This type of deployment does not need a GPU. Model inference happens at the API provider, and the VPS is only responsible for searching and forwarding requests.
If you want the model to also run on the VPS, the configuration requirements go up.
| Approach | Recommended configuration |
|---|---|
| Perplexica + cloud API | 2 cores 4GB is quite comfortable |
| Perplexica + Ollama small model | Start from 4 cores 16GB |
| Want to run models above 14B | GPU VPS or a local machine with a graphics card |
A cheap small VPS can run Perplexica, but don't expect 2GB of memory to run an Ollama 7B model at the same time. Being able to start and being usable are two different things.
The officially recommended simple way is Docker. Perplexica's full image packs SearXNG inside, so you don't need to deploy the search backend separately.
First log in to the VPS:
ssh root@your_server_ip
Update the system:
apt update && apt upgrade -y
Install Docker:
apt install -y ca-certificates curl gnupg ufw
install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
chmod a+r /etc/apt/keyrings/docker.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo $VERSION_CODENAME) stable" > /etc/apt/sources.list.d/docker.list
apt update
apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
Confirm Docker:
docker --version
docker compose version
Run Perplexica:
docker run -d \
--name perplexica \
--restart unless-stopped \
-p 127.0.0.1:3000:3000 \
-v perplexica-data:/home/perplexica/data \
itzcrazykns1337/perplexica:latest
Here I deliberately used:
127.0.0.1:3000:3000
This means only local access is allowed, and it is not directly exposed to the public internet. Later, use Caddy to reverse proxy to an HTTPS domain.
Check container status:
docker ps --filter "name=perplexica"
Check logs:
docker logs perplexica --tail=100
Test locally:
curl -I http://127.0.0.1:3000
If it returns 200, 302, or a similar response, the service is basically up.
If you prefer a more maintainable approach, use Compose.
Create the directory:
mkdir -p /opt/perplexica
cd /opt/perplexica
Write docker-compose.yml:
services:
perplexica:
image: itzcrazykns1337/perplexica:latest
container_name: perplexica
restart: unless-stopped
ports:
- "127.0.0.1:3000:3000"
volumes:
- perplexica-data:/home/perplexica/data
volumes:
perplexica-data:
Start:
docker compose up -d
Check:
docker compose ps
docker logs perplexica --tail=100
This approach suits most people: one container, built-in SearXNG, and data persisted with a volume.
Assume you plan to use:
search.example.com
Add an A record in DNS:
search.example.com -> your_server_ip
Install Caddy:
apt install -y debian-keyring debian-archive-keyring apt-transport-https curl
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' > /etc/apt/sources.list.d/caddy-stable.list
apt update
apt install -y caddy
Edit the configuration:
nano /etc/caddy/Caddyfile
Write:
search.example.com {
reverse_proxy 127.0.0.1:3000
}
Check and reload:
caddy validate --config /etc/caddy/Caddyfile
systemctl reload caddy
Now visit:
https://search.example.com
Caddy will automatically apply for and renew HTTPS certificates.
If you use Caddy reverse proxy, you only need to open SSH, HTTP, and HTTPS:
ufw allow 22/tcp
ufw allow 80/tcp
ufw allow 443/tcp
ufw enable
ufw status
It is not recommended to expose port 3000 directly to the public internet:
ufw deny 3000/tcp
If Docker above has already bound to 127.0.0.1:3000:3000, port 3000 is not accessible from outside anyway, which is more secure.
After opening the web page, first configure the AI Provider.
Common choices:
| Provider | Suitable for whom |
|---|---|
| OpenAI | Those who want convenience and stable answer quality |
| Claude | Long-form summaries and many explanatory questions |
| Groq | Those who want faster responses |
| OpenRouter | Those who want one Key to connect multiple models |
| Ollama | Those who want to run models locally and keep data on the machine as much as possible |
If you're just using it personally, I suggest first getting the flow working with an API Provider. Once you're sure you really need a local model, then tinker with Ollama.
After configuration is complete, ask a simple question to test:
最近 Docker Compose 部署自托管服务有哪些常见坑?
Focus on three things:
- Whether it can return an answer
- Whether there are cited sources
- Whether the search results are relevant to the question
If there are no search sources and it just looks like an ordinary chatbot, then check whether SearXNG is working properly.
If you want to connect Ollama, first install it on the host machine:
curl -fsSL https://ollama.com/install.sh | sh
Pull a model:
ollama pull qwen2.5:7b
Test Ollama:
curl http://127.0.0.1:11434/api/tags
If Perplexica is in a Docker container, it cannot use localhost to access the host machine's Ollama.
On Linux, a more reliable approach is to add this in Compose:
extra_hosts:
- "host.docker.internal:host-gateway"
Complete example:
services:
perplexica:
image: itzcrazykns1337/perplexica:latest
container_name: perplexica
restart: unless-stopped
ports:
- "127.0.0.1:3000:3000"
extra_hosts:
- "host.docker.internal:host-gateway"
volumes:
- perplexica-data:/home/perplexica/data
volumes:
perplexica-data:
Then in the web page, fill in the Ollama address as:
http://host.docker.internal:11434
Don't fill in http://localhost:11434. That's the container itself, not the host machine.
The single-container full image is suitable for quick deployment, but if you want finer control over search engines, or want multiple tools to share one SearXNG, you can deploy SearXNG separately and connect it with the slim version of Perplexica.
For example:
- Perplexica uses SearXNG
- Open WebUI also connects to SearXNG for Web Search
- You want to adjust search engines, language, and safe search separately
- You want to control SearXNG's access policy
In this case, you can use perplexica:slim-latest.
Create the directory:
mkdir -p /opt/perplexica/searxng
cd /opt/perplexica
Create the SearXNG configuration:
cat > searxng/settings.yml << 'EOF'
use_default_settings: true
server:
secret_key: "replace-with-a-long-random-secret"
search:
formats:
- html
- json
EOF
Note that json here is critical. Perplexica needs JSON results when calling SearXNG. If it is not enabled, you will often encounter the situation where "SearXNG opens fine, but Perplexica has no search results."
Write the Compose file:
services:
searxng:
image: searxng/searxng:latest
container_name: perplexica-searxng
restart: unless-stopped
volumes:
- ./searxng:/etc/searxng
networks:
- perplexica-net
perplexica:
image: itzcrazykns1337/perplexica:slim-latest
container_name: perplexica
restart: unless-stopped
environment:
- SEARXNG_API_URL=http://searxng:8080
ports:
- "127.0.0.1:3000:3000"
volumes:
- perplexica-data:/home/perplexica/data
depends_on:
- searxng
networks:
- perplexica-net
volumes:
perplexica-data:
networks:
perplexica-net:
Start:
docker compose up -d
Check:
docker compose ps
docker logs perplexica-searxng --tail=80
docker logs perplexica --tail=80
Test SearXNG JSON:
docker exec perplexica-searxng sh -c "wget -qO- 'http://127.0.0.1:8080/search?q=vps&format=json' | head"
If there is no JSON output here, fix SearXNG first, and don't rush to change Perplexica.
Self-hosting Perplexica does not equal complete anonymity.
What you can control is:
- The search entry point is under your own domain
- SearXNG does not profile users
- You can choose which search backends to use
- Query records are not by default handed to an AI search platform
But if you connect to cloud models like OpenAI, Claude, or Groq, questions and search summaries are still sent to the corresponding API provider.
So a more accurate way to put it is:
- Using cloud models: the search entry point and search aggregation are self-hosted, and model processing is at a third party
- Using Ollama: search and model are kept on your own machine as much as possible, but the VPS configuration needs to be higher
Don't understand "self-hosting" as "all data never leaves home." It depends on the model and search sources you connect to.
Perplexica's key data is in the Docker volume.
First look at the volume:
docker volume ls | grep perplexica
If you use a named volume, you can back it up like this:
mkdir -p /opt/backups
docker run --rm \
-v perplexica-data:/data \
-v /opt/backups:/backup \
alpine \
tar -czf /backup/perplexica-data-$(date +%F).tar.gz -C /data .
If you use a bind mount, such as /opt/perplexica/data, just package the directory directly:
tar -czf /opt/backups/perplexica-data-$(date +%F).tar.gz /opt/perplexica
Then sync to object storage:
rclone copy /opt/backups/perplexica-data-$(date +%F).tar.gz r2:backup-bucket/perplexica/
At minimum back up:
- Perplexica data volume
- Compose file
- SearXNG settings.yml
- Caddyfile
- The environment variables and model configuration notes you use
Single-container approach:
docker pull itzcrazykns1337/perplexica:latest
docker stop perplexica
docker rm perplexica
docker run -d \
--name perplexica \
--restart unless-stopped \
-p 127.0.0.1:3000:3000 \
-v perplexica-data:/home/perplexica/data \
itzcrazykns1337/perplexica:latest
Compose approach:
cd /opt/perplexica
docker compose pull
docker compose up -d
Back up before upgrading. After upgrading, check:
docker compose ps
docker logs perplexica --tail=100
curl -I http://127.0.0.1:3000
Then actually search a question in the web page to confirm that search, citations, and model answers all work properly.
First check whether Perplexica is up:
docker ps --filter "name=perplexica"
docker logs perplexica --tail=100
Then check the local port:
curl -I http://127.0.0.1:3000
If it's not accessible even locally, the problem is in the container. If it's normal locally but the domain shows 502, the problem is most likely in Caddy:
caddy validate --config /etc/caddy/Caddyfile
journalctl -u caddy -n 100 --no-pager
If you use the full image, first check the logs:
docker logs perplexica --tail=100
If you use standalone SearXNG, focus on checking JSON:
docker exec perplexica-searxng sh -c "wget -qO- 'http://127.0.0.1:8080/search?q=test&format=json' | head"
settings.yml must contain:
search:
formats:
- html
- json
Restart after changing:
docker compose restart searxng perplexica
First confirm the Provider configuration.
If using OpenAI / OpenRouter:
- Whether the API Key is correct
- Whether the account has balance
- Whether the selected model is available
- Whether the VPS can access the API address
You can test the network on the VPS:
curl -I https://api.openai.com
If using Ollama:
curl http://127.0.0.1:11434/api/tags
For a container to access the host machine's Ollama, use host.docker.internal or the host machine gateway address.
Slowness usually has three causes:
- Slow response from search sources
- Slow cloud model API
- Local Ollama model too large or machine too weak
Test them separately first.
Test SearXNG:
time curl -s 'http://127.0.0.1:3000' > /dev/null
Check resources:
htop
free -h
docker stats
If the local Ollama model is slow, switching to a smaller model is usually more effective than adding a bunch of parameters.
If you use Cloudflare's orange-cloud proxy, first confirm HTTPS works properly, then turn on the proxy.
When you encounter problems, temporarily switch back to DNS only to rule out Cloudflare interference. AI search applications may use long connections or streaming output, and response interruptions can occur when the proxy layer configuration is inappropriate.
These tools are easy to confuse.
| Tool | More suitable for |
|---|---|
| SearXNG | Private metasearch, no AI summary needed |
| Perplexica / Vane | Self-built Perplexity-like AI search |
| Open WebUI | Chat entry point, local model frontend |
| AnythingLLM | Private document knowledge base Q&A |
| Dify | AI applications and workflow orchestration |
My suggestions:
- Just want to search web pages: SearXNG
- Want "search + AI summary + citations": Perplexica
- Want to chat with models: Open WebUI
- Want to ask your own documents: AnythingLLM
- Want to build AI applications for others to use: Dify
Don't install every tool. Start by choosing one based on your core need.
If it were for my own use, I would do this:
- VPS: start from 2 cores 4GB
- Deployment: get the Perplexica full image running first
- Domain: Caddy reverse proxy HTTPS
- Ports: only open 80/443, do not open 3000
- Model: connect OpenRouter or OpenAI first to confirm the experience
- Later: if used often, then consider standalone SearXNG
- High privacy requirements: then connect Ollama, but the machine needs an upgrade
The greatest value of Perplexica is not "installing yet another AI tool," but turning search results into answers with traceable sources. For people doing technical research, SEO, competitor analysis, and operations troubleshooting, this saves more time than ordinary search.
But it is not omnipotent either. Poor search source quality, models summarizing randomly, and inaccurate citations can all happen. The real prerequisite for long-term usability is that you are willing to maintain SearXNG, model configuration, reverse proxy, and backups, rather than installing it and forgetting about it.