Manticore Search on Ubuntu 24.04 on Azure User Guide
Overview
Manticore Search is an open source database for search. Its single searchd daemon delivers fast full text search, filtering and real time analytics over your own data, and speaks three interfaces at once: a MySQL compatible SQL protocol, a JSON HTTP API, and a binary protocol. It runs in real time mode, so you create tables and index documents on the fly without restarts, which makes it a lean, self contained alternative to heavier search stacks. The cloudimg image installs the latest stable Manticore from the official repository, runs it under the unprivileged manticore system account, and — because Manticore's own interfaces have no built in authentication — keeps every listener bound to loopback and puts an nginx reverse proxy with HTTP Basic Auth in front as the only externally reachable door. A unique credential is generated on the first boot of every VM. Backed by 24/7 cloudimg support.
What is included:
- The latest stable Manticore Search
searchddaemon, installed from the official apt repository, run by an unprivilegedmanticoreaccount - All three
searchdinterfaces bound to loopback only: SQL127.0.0.1:9306(MySQL protocol), HTTP127.0.0.1:9308(JSON API), and binary127.0.0.1:9312 - nginx reverse proxy on
:80in front of the HTTP interface, protected by HTTP Basic Auth - Secure by default: a strong per VM password (
MANTICORE_PASSWORD) generated at first boot in a root only file, with no default login to change manticore.service+nginx.serviceas systemd units, enabled and active- 24/7 cloudimg support
The /health endpoint is open so load balancers can probe it; every other endpoint requires the credential.
Prerequisites
An active Azure subscription, an SSH key pair, and a VNet + subnet in the target region. Standard_B2s (2 vCPU / 4 GiB RAM) is a good starting point; scale up for larger indexes or higher query volume. NSG inbound: allow 22/tcp from your management network and 80/tcp from the clients that query Manticore (front port 80 with TLS for public exposure — see Enabling HTTPS).
Step 1 — Deploy from the Azure Marketplace
Sign in to the Azure Portal, choose Create a resource, search the Marketplace for Manticore Search by cloudimg, and select Create. On Basics pick your subscription, resource group, region and size; under Administrator account choose SSH public key and paste your key; under Inbound port rules allow SSH (22) and HTTP (80). Then Review + create then Create.
Step 2 — Deploy from the Azure CLI
az vm create \
--resource-group <your-rg> \
--name manticore \
--image <marketplace-image-urn> \
--size Standard_B2s \
--admin-username azureuser \
--ssh-key-values ~/.ssh/id_ed25519.pub \
--vnet-name <your-vnet> --subnet <your-subnet> \
--public-ip-sku Standard
az vm open-port --resource-group <your-rg> --name manticore --port 80 --priority 1010
Step 3 — Connect to your VM
ssh azureuser@<vm-public-ip>
Step 4 — Confirm the services are running
Manticore's searchd daemon and nginx are enabled and active on first boot. Confirm the services, then note that every searchd listener is bound to loopback (127.0.0.1) — the only externally reachable port is nginx on :80.
systemctl is-active manticore.service nginx.service
ss -tln | grep -E ':80 |9306|9308|9312'
searchd --version | head -1
curl -s -o /dev/null -w 'health: HTTP %{http_code}\n' http://127.0.0.1/health
Expected output:
active
active
LISTEN 0 5 127.0.0.1:9306 0.0.0.0:*
LISTEN 0 5 127.0.0.1:9308 0.0.0.0:*
LISTEN 0 5 127.0.0.1:9312 0.0.0.0:*
LISTEN 0 511 0.0.0.0:80 0.0.0.0:*
Manticore 28.4.4 f63d06ecb@26071006 (columnar 13.8.1 ...) (secondary 13.8.1 ...) (knn 13.8.1 ...)
health: HTTP 200

Step 5 — Retrieve the per VM credential
Manticore's SQL and HTTP interfaces have no built in authentication, so the cloudimg image never exposes them directly. nginx on :80 fronts the HTTP interface behind HTTP Basic Auth, and the password is generated uniquely for this VM on first boot and written to a root only file. There is no default login to change.
sudo cat /root/manticoresearch-credentials.txt
You will see a MANTICORE_USER (always manticore), a MANTICORE_PASSWORD unique to this VM (the <MANTICORE_PASSWORD> referenced throughout this guide), and a MANTICORE_URL built from this VM's address. Load the password into a shell variable for the commands below:
PASS=$(sudo grep '^MANTICORE_PASSWORD=' /root/manticoresearch-credentials.txt | cut -d= -f2-)
A request without the credential is rejected with HTTP 401; the same request with -u manticore:$PASS returns HTTP 200.
PASS=$(sudo grep '^MANTICORE_PASSWORD=' /root/manticoresearch-credentials.txt | cut -d= -f2-)
curl -s -o /dev/null -w 'no credential: HTTP %{http_code}\n' http://127.0.0.1/sql -d 'mode=raw&query=SHOW STATUS'
curl -s -o /dev/null -w 'with credential: HTTP %{http_code}\n' -u "manticore:$PASS" http://127.0.0.1/sql -d 'mode=raw&query=SHOW STATUS'
Expected output:
no credential: HTTP 401
with credential: HTTP 200

Step 6 — Create a real time table and index documents
Manticore runs in real time mode, so you create a table and start indexing immediately — no config edits or restarts. Create a products table over the SQL-over-HTTP endpoint, then index two documents through the JSON /insert endpoint.
PASS=$(sudo grep '^MANTICORE_PASSWORD=' /root/manticoresearch-credentials.txt | cut -d= -f2-)
curl -s -u "manticore:$PASS" http://127.0.0.1/sql \
-d 'mode=raw&query=CREATE TABLE IF NOT EXISTS products(title text, brand string, price float)'
echo
curl -s -u "manticore:$PASS" http://127.0.0.1/insert \
-d '{"index":"products","id":1,"doc":{"title":"Wireless noise cancelling headphones","brand":"Acme","price":199.0}}'
echo
curl -s -u "manticore:$PASS" http://127.0.0.1/insert \
-d '{"index":"products","id":2,"doc":{"title":"Wired studio headphones","brand":"Acme","price":89.5}}'
echo
Each insert returns a JSON acknowledgement:
[{"total":0,"error":"","warning":""}]
{"table":"products","id":1,"created":true,"result":"created","status":201}
{"table":"products","id":2,"created":true,"result":"created","status":201}
Step 7 — Run a full text search
Query the products table through the JSON /search endpoint. Manticore returns the matching documents with a relevance _score.
PASS=$(sudo grep '^MANTICORE_PASSWORD=' /root/manticoresearch-credentials.txt | cut -d= -f2-)
curl -s -u "manticore:$PASS" http://127.0.0.1/search \
-d '{"index":"products","query":{"match":{"title":"headphones"}},"limit":2}'
echo
Expected output (abridged):
{"took":0,"timed_out":false,"hits":{"total":2,"total_relation":"eq","hits":[
{"_id":2,"_score":1356,"_source":{"title":"Wired studio headphones","brand":"Acme","price":89.5}},
{"_id":1,"_score":1356,"_source":{"title":"Wireless noise cancelling headphones","brand":"Acme","price":199.0}}]}}

Step 8 — Query over SQL and the MySQL wire protocol
The same data is reachable through SQL over HTTP and, for tools and drivers that speak the MySQL protocol, over the SQL port. Over HTTP you send SQL to /sql; over the wire protocol you connect the standard mysql client to the loopback port 9306 (SSH tunnel it from your workstation — see below).
PASS=$(sudo grep '^MANTICORE_PASSWORD=' /root/manticoresearch-credentials.txt | cut -d= -f2-)
curl -s -u "manticore:$PASS" http://127.0.0.1/sql \
-d "mode=raw&query=SELECT id, title, price FROM products WHERE MATCH('wireless')"
echo
mysql -h127.0.0.1 -P9306 -e 'SHOW TABLES; SELECT COUNT(*) AS n FROM products;'
Expected output:
[{"columns":[...],"data":[{"id":1,"title":"Wireless noise cancelling headphones","price":199}],"total":1,"error":"","warning":""}]
Table Type
products rt
n
2

Reaching the SQL wire protocol from your workstation
The SQL port 9306 is bound to loopback and is not exposed through nginx. Tunnel it over SSH, then point any MySQL client at your local end of the tunnel:
ssh -L 9306:127.0.0.1:9306 azureuser@<vm-public-ip>
# in another terminal on your workstation:
mysql -h127.0.0.1 -P9306
Step 9 — Enabling HTTPS
For any public exposure, terminate TLS in front of nginx. Point a DNS record at the VM's public IP, then use certbot to obtain and install a certificate:
sudo apt-get update
sudo apt-get install -y certbot python3-certbot-nginx
sudo certbot --nginx -d search.example.com
certbot rewrites the nginx site to listen on 443 with your certificate and sets up automatic renewal. Keep the HTTP Basic Auth in place so the credential is still required over TLS, and restrict 80/tcp and 443/tcp in the NSG to the networks that need them.
Step 10 — Maintenance
- Service management:
sudo systemctl restart manticoreandsudo systemctl restart nginx; logs viasudo journalctl -u manticore -eand/var/log/manticore/. - Data: real time tables, the binlog and on disk data live under
data_dirat/var/lib/manticore. Back it up with Manticore's own tooling (manticore-backup) or snapshot the OS disk. - Configuration:
searchdsettings live in/etc/manticoresearch/manticore.conf; the listeners are intentionally bound to127.0.0.1— keep them loopback only and reach the engine through the authenticated nginx proxy or an SSH tunnel. - Credential: rotate the basic auth password by regenerating the htpasswd entry in
/etc/nginx/.manticore_htpasswd(sudo htpasswd /etc/nginx/.manticore_htpasswd manticore) and reloading nginx. - Updates:
sudo apt-get update && sudo apt-get install --only-upgrade manticore, thensudo systemctl restart manticore. OS security updates are applied automatically by unattended-upgrades.
Conclusion
You now have Manticore Search running on Ubuntu 24.04 on Azure, with a real time table indexed and searchable over the JSON HTTP API, SQL over HTTP, and the MySQL wire protocol — all behind a per VM credential with the engine bound to loopback. Extend it by indexing your own documents, adding full text and attribute filters, and fronting it with TLS for production. Every cloudimg image includes 24/7 support.