Meilisearch
Overview
Meilisearch is a fast, open-source search engine that returns relevant, typo-tolerant results in milliseconds. It offers built-in AI and vector search for hybrid semantic queries, filtering, faceting, custom ranking, synonyms and multi-language tokenization, all through a REST API with official client libraries for most languages.
This SecureAnyCloud image installs the official Meilisearch single binary at /usr/local/bin/meilisearch and runs it as the meilisearch service on loopback 127.0.0.1:7700, behind nginx on port 80. A unique master key is generated on each VM's first boot by meilisearch-firstboot.service, and nginx is ready for your TLS certificate.
Meilisearch is an API-first service. Version 1.49 ships no bundled web interface, and a browser request to / returns a JSON status. You drive it through the REST API, the official client libraries or your own application, and this guide uses curl.
What you get:
- Meilisearch (verified at 1.49.0) as the official single static binary
meilisearch.servicein production mode, bound to127.0.0.1:7700, which refuses to start without a master key- No default login and no insecure development mode: every API endpoint requires authentication
- An nginx reverse proxy on port 80, ready for TLS
meilisearch-firstboot.service, a oneshot that generates a unique master key on each VM's first boot, resolves the instance URL, writes a root-only info note, refreshes the binary and then disables itself- A unique per-VM master key in a root-only
0600file, so no two VMs share a key and none is baked into the image - The newest Meilisearch release downloaded on first boot, falling back to the version baked into the image if the network is unavailable
- An Ubuntu 24.04 LTS base, patched at build time
- 24/7 SecureAnyCloud support, 24h response SLA
Prerequisites
You need an active Azure subscription, an SSH key pair, and a VNet with a subnet.
Meilisearch is lightweight, but search performance and index capacity scale with memory. Use Standard_B2s (2 vCPU, 4 GB RAM) for evaluation and small indexes. Use Standard_D2s_v5 or larger for production workloads with bigger datasets.
Meilisearch keeps its index on the OS disk, so expand the disk before you load large collections.
Deploy from the Azure Portal
Search the Azure Marketplace for Meilisearch on Ubuntu 24.04 and choose your VM size.
Attach a network security group (NSG) that allows TCP 22 (SSH) from your management network. Also allow TCP 80 and 443 (the API) from the networks and applications that need to query it. For production, front port 80 with TLS as described in Step 9.
Deploy from the Azure CLI
RG="meilisearch-prod"; LOCATION="eastus"; VM_NAME="meilisearch-01" IMAGE_URN="sac1647283583153:meilisearch-ubuntu-24-04:default:latest" SSH_KEY="$(cat ~/.ssh/id_rsa.pub)" az group create --name "$RG" --location "$LOCATION" az network vnet create -g "$RG" --name meili-vnet --address-prefix 10.90.0.0/16 --subnet-name meili-subnet --subnet-prefix 10.90.1.0/24 az network nsg create -g "$RG" --name meili-nsg az network nsg rule create -g "$RG" --nsg-name meili-nsg --name allow-ssh --priority 100 \
--source-address-prefixes "<your-mgmt-cidr>" --destination-port-ranges 22 --access Allow --protocol Tcp az network nsg rule create -g "$RG" --nsg-name meili-nsg --name allow-web --priority 110 \
--source-address-prefixes "<your-mgmt-cidr>" --destination-port-ranges 80 443 --access Allow --protocol Tcp
# Accept the Marketplace terms once per subscription (required before the first CLI deploy)
az vm image terms accept --urn sac1647283583153:meilisearch-ubuntu-24-04:default:latest
az vm create -g "$RG" --name "$VM_NAME" --image "$IMAGE_URN" \
--size Standard_B2s --storage-sku StandardSSD_LRS \
--admin-username azureuser --ssh-key-values "$SSH_KEY" \
--vnet-name meili-vnet --subnet meili-subnet --nsg meili-nsg --public-ip-sku StandardConnect over SSH
Connect to the VM as the azureuser administrator:
ssh azureuser@<vm-ip>Verify the services are running
Meilisearch listens on loopback 127.0.0.1:7700, and nginx fronts the API on port 80. The health endpoint is public. Every other endpoint requires your master key.
sudo systemctl start meilisearch nginx 2>/dev/null || true
sudo systemctl is-active meilisearch nginx ss -tln | grep -E ':80 |127.0.0.1:7700' curl -s http://127.0.0.1/healthThe output shows both services active, the two listening sockets, and {"status":"available"} from the health endpoint.
Read your per-VM master key
The first-boot service generated this VM's master key and stored it in a root-only file. Read the file and keep the key secret, because it authenticates every API request. Then confirm that unauthenticated requests are rejected.
sudo cat /root/meilisearch-info.txt echo "unauthenticated /keys -> HTTP $(curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1/keys)"The info note holds MEILI_MASTER_KEY and the instance URL. It is owned by root:root with mode 0600. An unauthenticated call to /keys returns 401, because production mode enforces authentication.
Create an index and run your first search
Load the master key into a shell variable, create a movies index, configure its attributes and add a few documents. Then run a typo-tolerant search.
Indexing is asynchronous, so wait for the documents to be processed before you search.
export
MEILI_KEY=$(sudo grep '^MEILI_MASTER_KEY=' /root/meilisearch-info.txt | cut -d= -f2-) H="Authorization: Bearer $MEILI_KEY" curl -s -X PATCH http://127.0.0.1/indexes/movies/settings -H "$H" -H 'Content-Type: application/json' \
--data '{"filterableAttributes":["genres","release_year"],"sortableAttributes":["release_year"]}' >/dev/null curl -s -X POST 'http://127.0.0.1/indexes/movies/documents?primaryKey=id' -H "$H" -H 'Content-Type: application/json' \
--data '[ {"id":1,"title":"Interstellar","genres":["Science Fiction","Drama"],"release_year":2014}, {"id":2,"title":"Inception","genres":["Action","Science Fiction"],"release_year":2010}, {"id":3,"title":"The Matrix","genres":["Action","Science Fiction"],"release_year":1999}, {"id":4,"title":"Dune","genres":["Science Fiction","Adventure"],"release_year":2021}, {"id":5,"title":"Arrival","genres":["Science Fiction","Drama"],"release_year":2016} ]' >/dev/null for i in $(seq 1 20); do
N=$(curl -s -H "$H" http://127.0.0.1/indexes/movies/stats | jq -r '.numberOfDocuments // 0') [ "$N" -ge 5 ] && break; sleep 1 done echo "indexed documents: $N" curl -s -X POST http://127.0.0.1/indexes/movies/search -H "$H" -H 'Content-Type: application/json' \
--data '{"q":"scince fiction","limit":3}' | jq -r '.hits[].title'The query contains a deliberate typo (scince fiction). Meilisearch still returns the science fiction titles, ranked by relevance, in a fraction of a millisecond.
Filter, sort and facet
In Step 6 you marked genres and release_year as filterable and release_year as sortable, so you can now filter and sort results. This query returns science fiction films released after 2013, newest first.
export
MEILI_KEY=$(sudo grep '^MEILI_MASTER_KEY=' /root/meilisearch-info.txt | cut -d= -f2-) H="Authorization: Bearer $MEILI_KEY" curl -s -X POST http://127.0.0.1/indexes/movies/search -H "$H" -H 'Content-Type: application/json' \
--data '{"q":"","filter":"genres = \"Science Fiction\" AND release_year > 2013","sort":["release_year:desc"],"limit":5,"attributesToRetrieve":["title","release_year"]}' \
| jq -r '.hits[] | .title + " (" + (.release_year|tostring) + ")"'AI-powered hybrid search
Meilisearch combines classic keyword search with vector search, so a query can match on meaning as well as words. Configure an embedder on the index, for example an OpenAI-compatible provider, or supply your own vectors. Then pass a hybrid object on the search request.
The embedder configuration looks like this:
{ "embedders": { "default": { "source": "openAi", "apiKey": "YOUR_PROVIDER_API_KEY", "model": "text-embedding-3-small" } } }Once an embedder is set, add "hybrid": {"embedder": "default", "semanticRatio": 0.5} to any search body to blend keyword and semantic relevance. See the Meilisearch documentation for embedder options and self-hosted models.
Enable HTTPS
nginx fronts the API on port 80 and is ready for TLS. Point a DNS record at the VM, then obtain a certificate with certbot. Certbot configures nginx for port 443.
sudo apt-get update && sudo apt-get install -y certbot python3-certbot-nginx
sudo certbot --nginx -d your-domain.example.comAfter the certificate is issued, restrict the NSG so only port 443 (and port 22 from your management network) is reachable. Then query the API over https://your-domain.example.com/.
Persistence, first boot and updates
The search index lives on the OS disk under /var/lib/meilisearch/data.ms and is captured into the image, so a VM launched from this image is ready immediately.
The first-boot service generates the per-VM master key and refreshes the Meilisearch binary to the latest release. It then disables itself, so later reboots are unaffected. The OS is patched at build time and ships with unattended security upgrades enabled.
Support
Every SecureAnyCloud deployment includes 24/7 support with a 24-hour response SLA. Contact sales@secureanycloud.com for help with deployment, configuration or scaling.
This is a repackaged open-source software product, with additional charges for SecureAnyCloud support services. Meilisearch is a trademark of its respective owner. All product and company names are trademarks or registered trademarks of their respective holders. Use of them does not imply any affiliation with or endorsement by them.
Deploy on Azure
Launch Meilisearch on Ubuntu 24.04 LTS on Azure with 24/7 support from SecureAnyCloud.
View this image
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com