Databases Azure

Manticore Search on Ubuntu 24.04 on Azure User Guide

| Product: Manticore Search on Ubuntu 24.04 LTS on Azure

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 searchd daemon, installed from the official apt repository, run by an unprivileged manticore account
  • All three searchd interfaces bound to loopback only: SQL 127.0.0.1:9306 (MySQL protocol), HTTP 127.0.0.1:9308 (JSON API), and binary 127.0.0.1:9312
  • nginx reverse proxy on :80 in 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.service as 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

Manticore Search service health on the cloudimg Azure image: manticore.service and nginx active, the SQL 9306, HTTP 9308 and binary 9312 searchd listeners all bound to loopback, the searchd version, and the /health endpoint returning 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

The per VM Manticore basic auth credential in its root only file with the password masked, a request to the SQL endpoint returning HTTP 401 without the credential and HTTP 200 with the manticore user credential, confirming searchd is loopback only and nginx is the sole authenticated door

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}}]}}

Creating a real time products table over SQL-over-HTTP, indexing two documents through the JSON insert endpoint with both returning created status 201, and a full text search for headphones returning both matching documents with relevance scores

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

A SQL-over-HTTP query selecting the wireless headphones row by full text match, and the MySQL wire protocol on 127.0.0.1:9306 listing the real time products table and counting its two rows, showing Manticore serving the same data over both SQL and HTTP

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 manticore and sudo systemctl restart nginx; logs via sudo journalctl -u manticore -e and /var/log/manticore/.
  • Data: real time tables, the binlog and on disk data live under data_dir at /var/lib/manticore. Back it up with Manticore's own tooling (manticore-backup) or snapshot the OS disk.
  • Configuration: searchd settings live in /etc/manticoresearch/manticore.conf; the listeners are intentionally bound to 127.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, then sudo 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.