Install Meilisearch Search Engine on VPS
Meilisearch is a fast, typo-tolerant search engine written in Rust that you can self-host on your VPS. It provides a simple REST API without the complexity of enterprise search systems. Most websites and applications need search that responds instantly, handles misspellings gracefully, and keeps data under your control — Meilisearch does all of this well. It works best for indexes with millions of documents, performs efficient full-text search with minimal overhead, and stores everything on your own server.
Install Meilisearch
The simplest approach is to download the official binary or use Docker to run a containerized instance.
# Download Linux 64-bit binary
mkdir -p ~/meilisearch
cd ~/meilisearch
curl -L https://github.com/meilisearch/meilisearch/releases/download/v1.13.0/meilisearch-linux-amd64 -o meilisearch
chmod +x meilisearch
# Test the binary
./meilisearch --version
Alternatively, use Docker if it's already installed:
docker run -it --rm \
-p 7700:7700 \
-v ~/meilisearch_data:/meili_data \
getmeili/meilisearch:latest
Run Meilisearch as a Systemd Service
To ensure Meilisearch runs continuously and restarts automatically on failure, create a systemd unit file:
sudo nano /etc/systemd/system/meilisearch.service
Add the following content:
[Unit]
Description=Meilisearch search engine
After=network.target
[Service]
Type=simple
User=meilisearch
WorkingDirectory=/opt/meilisearch
ExecStart=/opt/meilisearch/meilisearch --db-path /var/lib/meilisearch
Restart=on-failure
RestartSec=10
[Install]
WantedBy=multi-user.target
# Create directories and copy binary
sudo mkdir -p /opt/meilisearch /var/lib/meilisearch
sudo cp ~/meilisearch/meilisearch /opt/meilisearch/
sudo chown -R meilisearch:meilisearch /opt/meilisearch /var/lib/meilisearch
# Enable and start the service
sudo systemctl daemon-reload
sudo systemctl enable meilisearch
sudo systemctl start meilisearch
Set a Master Key for Security
By default, Meilisearch has no authentication. Add protection with a strong master key:
# Generate a random string for the master key
openssl rand -base64 32
Edit the systemd service to use the master key:
sudo nano /etc/systemd/system/meilisearch.service
# Modify the ExecStart line like this:
ExecStart=/opt/meilisearch/meilisearch --db-path /var/lib/meilisearch --master-key YOUR_GENERATED_KEY
sudo systemctl restart meilisearch
Create an Index and Add Documents
An index is a collection of searchable documents. Each index has a defined primary key. Create one with curl:
# Create an index named "products"
curl -X POST http://localhost:7700/indexes \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_MASTER_KEY" \
-d '{
"uid": "products",
"primaryKey": "id"
}'
Add documents to the index:
curl -X POST http://localhost:7700/indexes/products/documents \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_MASTER_KEY" \
-d '[
{"id": 1, "name": "Laptop", "price": 999, "category": "electronics"},
{"id": 2, "name": "Mouse", "price": 25, "category": "electronics"},
{"id": 3, "name": "Keyboard", "price": 75, "category": "electronics"}
]'
Perform Searches
Query the index with a GET request to the /search endpoint:
# Search for "laptop"
curl http://localhost:7700/indexes/products/search \
-H "Content-Type: application/json" \
-d '{"q": "laptop"}'
# Typo-tolerant search: "lapto" also finds "laptop"
curl http://localhost:7700/indexes/products/search \
-H "Content-Type: application/json" \
-d '{"q": "lapto"}'
# Example JSON response:
# {"hits":[{"id":1,"name":"Laptop","price":999,"category":"electronics"}]}
Verify That Meilisearch Is Working Correctly
# Check systemd service status
sudo systemctl status meilisearch
# Query the health endpoint (no master key needed)
curl http://localhost:7700/health
# Check version
curl http://localhost:7700/version
# List all indexes
curl http://localhost:7700/indexes \
-H "Authorization: Bearer YOUR_MASTER_KEY"
# View statistics (document count, etc.)
curl http://localhost:7700/stats \
-H "Authorization: Bearer YOUR_MASTER_KEY"
{"status":"available"}, Meilisearch is running correctly. If you see connection timeout or refused errors, the service may not be running or the port is incorrect.
Common Issues & Troubleshooting
Error: Authorization header is invalid
The master key is missing or incorrect. Write operations (POST, PUT, DELETE) require the master key in the Authorization header:
# Verify the master key in your service
sudo grep "master-key" /etc/systemd/system/meilisearch.service
# Include it correctly in curl requests
curl -X POST http://localhost:7700/indexes/products/documents \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_EXACT_KEY" \
-d '[...]'
Error: Connection refused on port 7700
Meilisearch is not running or listening on the wrong port. Troubleshoot with:
# Check service status
sudo systemctl status meilisearch
# View recent logs
sudo journalctl -u meilisearch -n 20
# Verify port 7700 is listening
sudo lsof -i :7700
# Or
netstat -tuln | grep 7700
# Restart if needed
sudo systemctl restart meilisearch
Error: Index not found
You're trying to search an index that doesn't exist or the name is incorrect:
# List all existing indexes
curl http://localhost:7700/indexes \
-H "Authorization: Bearer YOUR_MASTER_KEY"
# If the index is missing, create it first
curl -X POST http://localhost:7700/indexes \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_MASTER_KEY" \
-d '{"uid": "products", "primaryKey": "id"}'
Meilisearch using excessive disk space
Meilisearch stores a full index in memory and on disk for fast queries. Large datasets with millions of documents or many fields can consume significant storage. Reduce the index size by removing unsearchable fields or deleting old indexes:
# Delete an entire index
curl -X DELETE http://localhost:7700/indexes/old_index \
-H "Authorization: Bearer YOUR_MASTER_KEY"
Frequently Asked Questions
How does Meilisearch compare to Elasticsearch?
Meilisearch is much easier to set up and focuses on search UX, with typo-tolerance enabled by default. Elasticsearch is more complex but scales to much larger datasets. Meilisearch fits typical websites and apps that just need a fast, simple search box, while Elasticsearch is the better fit for logging, analytics, and enterprise-scale datasets.
How fast is Meilisearch?
Most queries respond in 1-10 milliseconds, depending on index size and query complexity. Meilisearch is written in Rust, making it faster than Python-based search solutions. It operates in-memory, resulting in very low latency and excellent throughput.
Do I need to expose Meilisearch to the internet?
If Meilisearch and your web server run on the same VPS, bind it to localhost (127.0.0.1) only. Never expose port 7700 to the public internet. For distributed clients, run Meilisearch behind a reverse proxy (Nginx) with IP whitelisting or additional authentication.