<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Mario Ravalli</title>
    <description>The latest articles on DEV Community by Mario Ravalli (@mrkrash).</description>
    <link>https://dev.to/mrkrash</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F396351%2F8673e640-cc0e-4fa9-8406-427db6f742d7.jpeg</url>
      <title>DEV Community: Mario Ravalli</title>
      <link>https://dev.to/mrkrash</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mrkrash"/>
    <language>en</language>
    <item>
      <title>Samba, Spotlight &amp; Manticore</title>
      <dc:creator>Mario Ravalli</dc:creator>
      <pubDate>Sun, 12 Apr 2026 22:13:41 +0000</pubDate>
      <link>https://dev.to/mrkrash/samba-spotlight-manticore-40f9</link>
      <guid>https://dev.to/mrkrash/samba-spotlight-manticore-40f9</guid>
      <description>&lt;h2&gt;
  
  
  Part 1 — The Journey
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Goal
&lt;/h3&gt;

&lt;p&gt;I have a NAS built on Proxmox with LXC containers. The idea was simple: share files via Samba and be able to search them from macOS Finder as if they were on a local disk, using Spotlight. Search for "Battiato" and find all the MP3s, PDFs, text files — everything indexed, everything reachable in a second.&lt;/p&gt;

&lt;p&gt;Samba has supported Apple's Spotlight protocol since version 4.x, with an option called &lt;code&gt;spotlight backend&lt;/code&gt; that allows delegating indexing to an external engine. Three backends are supported: &lt;code&gt;noindex&lt;/code&gt; (no search), &lt;code&gt;tracker&lt;/code&gt; (GNOME Tracker), and &lt;code&gt;elasticsearch&lt;/code&gt;. None of these was exactly what I was looking for.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Context: Proxmox, LXC, and Alpine Linux
&lt;/h3&gt;

&lt;p&gt;My setup uses Proxmox as a hypervisor with LXC containers for services. The NAS initially ran on an Alpine Linux container — lightweight, fast, perfect for a fileserver.&lt;/p&gt;

&lt;p&gt;The first obstacle came right away: I want Spotlight search, so I need to choose a backend. Tracker is out of the question on Alpine — it depends on D-Bus, the GNOME stack, systemd, none of which is practically available on Alpine with musl libc. Elasticsearch is heavy and requires a JVM. But there is an alternative.&lt;/p&gt;

&lt;h3&gt;
  
  
  Manticore Search: A Lightweight Elasticsearch
&lt;/h3&gt;

&lt;p&gt;Manticore Search is a full-text search engine compatible with the Elasticsearch REST API, written in C++. It is much lighter, requires no JVM, and has excellent support for text indexing. The idea was to use it as the Elasticsearch backend for Samba, in a separate LXC container.&lt;/p&gt;

&lt;p&gt;The two-container architecture makes sense: the search service is separate from the fileserver, they can be updated independently, and Manticore can be reached by multiple shares if needed.&lt;/p&gt;

&lt;h3&gt;
  
  
  The First Problem: &lt;code&gt;spotlight.so&lt;/code&gt; Does Not Exist on Alpine
&lt;/h3&gt;

&lt;p&gt;After configuring Samba with &lt;code&gt;spotlight backend = elasticsearch&lt;/code&gt; and adding &lt;code&gt;vfs objects = spotlight&lt;/code&gt; to the share, the result was:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Error loading module '/usr/lib/samba/vfs/spotlight.so': No such file or directory
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Samba package on Alpine does not include the VFS module for Spotlight. It is not in the repositories, there is no separate package, and compiling it from source on Alpine with musl libc is an inadvisable adventure.&lt;/p&gt;

&lt;h3&gt;
  
  
  Migrating to Debian 13
&lt;/h3&gt;

&lt;p&gt;I recreated the NAS container on Debian 13 (Bookworm). Samba 4.22 on Debian is compiled with Spotlight support — you can see this from the &lt;code&gt;smbd -b&lt;/code&gt; output which shows &lt;code&gt;WITH_SPOTLIGHT&lt;/code&gt; and &lt;code&gt;HAVE_SPOTLIGHT_BACKEND_ES&lt;/code&gt;. The module is compiled statically into &lt;code&gt;smbd&lt;/code&gt;, not as a separate &lt;code&gt;.so&lt;/code&gt;, so it does not need to be added to &lt;code&gt;vfs objects&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Technical Problems, One by One
&lt;/h3&gt;

&lt;h4&gt;
  
  
  1. The Missing Mappings File
&lt;/h4&gt;

&lt;p&gt;The first error after the migration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mdssvc_es_init: Opening mapping file [/usr/share/samba/mdssvc/elasticsearch_mappings.json] failed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Samba looks for a JSON file that maps Spotlight attributes (such as &lt;code&gt;kMDItemFSName&lt;/code&gt;, &lt;code&gt;kMDItemTitle&lt;/code&gt;) to Elasticsearch fields. The file was not included in the Debian package. Solution: download it from the official Samba repository and place it at the correct path.&lt;/p&gt;

&lt;h4&gt;
  
  
  2. Manticore Does Not Support Field Names With Dots
&lt;/h4&gt;

&lt;p&gt;Samba sends queries with fields like &lt;code&gt;path.real&lt;/code&gt;, &lt;code&gt;file.filename&lt;/code&gt;, &lt;code&gt;meta.title&lt;/code&gt;. Manticore does not accept field names containing dots — not as SQL, not with backticks, in no way.&lt;/p&gt;

&lt;p&gt;Solution: rename the fields in the index (&lt;code&gt;path_real&lt;/code&gt;, &lt;code&gt;file_filename&lt;/code&gt;, etc.) and create an HTTP proxy that translates the names in both requests and responses.&lt;/p&gt;

&lt;h4&gt;
  
  
  3. The &lt;code&gt;prefix&lt;/code&gt; Query Is Not Supported on Full-Text Fields
&lt;/h4&gt;

&lt;p&gt;Samba filters results by share using a &lt;code&gt;prefix&lt;/code&gt; query on the &lt;code&gt;path.real&lt;/code&gt; field. Manticore does not support this type of query on full-text fields. The proxy must intercept and remove this filter.&lt;/p&gt;

&lt;h4&gt;
  
  
  4. Elasticsearch's &lt;code&gt;query_string&lt;/code&gt; Syntax Is Not Compatible
&lt;/h4&gt;

&lt;p&gt;Samba sends queries like &lt;code&gt;"query": "Fran* OR content:Fran*"&lt;/code&gt; with &lt;code&gt;"fields": ["file.filename", "content"]&lt;/code&gt;. Manticore does not understand the &lt;code&gt;content:Fran*&lt;/code&gt; syntax inside a &lt;code&gt;query_string&lt;/code&gt;. The proxy must rewrite the query into Manticore's format: &lt;code&gt;@file_filename Fran* | @content Fran*&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  5. &lt;code&gt;json_loadb failed&lt;/code&gt;: the Content-Length
&lt;/h4&gt;

&lt;p&gt;Even with a correct JSON response, Samba kept throwing &lt;code&gt;json_loadb failed&lt;/code&gt;. The problem was that the proxy was not including the &lt;code&gt;Content-Length&lt;/code&gt; header in the response. Samba reads exactly N declared bytes — without Content-Length, parsing fails.&lt;/p&gt;

&lt;h4&gt;
  
  
  6. Accented Characters and &lt;code&gt;ensure_ascii&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;Python by default serializes non-ASCII characters as Unicode sequences (&lt;code&gt;È&lt;/code&gt; → &lt;code&gt;E\u0300&lt;/code&gt;). Samba does not handle NFD (decomposed) form correctly. Solution: &lt;code&gt;json.dumps(data, ensure_ascii=False)&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  7. The Nested Structure of &lt;code&gt;path.real&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;The final error: &lt;code&gt;Missing path.real in JSON result&lt;/code&gt;. Looking at the Samba source code reveals that the parser expects:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"_source"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"path"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"real"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/share/music/..."&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Not the flat key &lt;code&gt;"path.real"&lt;/code&gt;. The proxy must therefore transform &lt;code&gt;path_real&lt;/code&gt; into the nested object &lt;code&gt;{"path": {"real": "..."}}&lt;/code&gt; in the response.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Python Proxy: The Solution
&lt;/h3&gt;

&lt;p&gt;A small HTTP proxy written in Python, listening on port 9200, which intercepts Samba's requests and translates them for Manticore, then translates the responses back into the format Samba expects. About 80 lines of standard library code, no external dependencies.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Result
&lt;/h3&gt;

&lt;p&gt;Searching for "Battiato" from Finder shows Franco Battiato's MP3 files. Searching for "Robot" finds Ufo Robot songs and Asimov's Robot novels. Search works on filenames, ID3 titles, PDF and text file contents, and PHP and JavaScript source code.&lt;/p&gt;




&lt;h2&gt;
  
  
  Part 2 — Practical Guide
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Proxmox with two LXC containers&lt;/li&gt;
&lt;li&gt;Samba CT: Debian 13, at least 512MB RAM&lt;/li&gt;
&lt;li&gt;Manticore CT: Debian/Ubuntu, at least 1GB RAM&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Architecture
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;macOS Finder (Spotlight)
        │  SMB + Spotlight RPC
        ▼
CT Debian — smbd + rpcd_mdssvc
        │  HTTP :9200
        ▼
CT Debian — ms-proxy.py
        │  HTTP :9308
        ▼
CT Manticore — Manticore Search
        ▲
CT Debian — spotlight-indexer.sh
        │  inotify + ffprobe/pdftotext/catdoc
        ▼
    /share (filesystem)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  CT Manticore — Installation
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Recommended distro:&lt;/strong&gt; Debian 12 or Ubuntu 22.04&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;wget https://repo.manticoresearch.com/manticore-repo.noarch.deb
dpkg &lt;span class="nt"&gt;-i&lt;/span&gt; manticore-repo.noarch.deb
apt update
apt &lt;span class="nb"&gt;install &lt;/span&gt;manticore manticore-extra
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Download the Manticore configuration file:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;wget https://raw.githubusercontent.com/senzidee/samba-spotlight-manticore/refs/heads/main/manticore.conf
&lt;span class="nb"&gt;mv &lt;/span&gt;manticore.conf /etc/manticoresearch/manticore.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Start the service:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;systemctl &lt;span class="nb"&gt;enable &lt;/span&gt;manticore
systemctl start manticore
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  CT Samba/Debian — Installation
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;samba samba-vfs-modules &lt;span class="se"&gt;\&lt;/span&gt;
    inotify-tools curl ffmpeg &lt;span class="se"&gt;\&lt;/span&gt;
    poppler-utils catdoc &lt;span class="se"&gt;\&lt;/span&gt;
    python3 jq
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Spotlight mappings file:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /usr/share/samba/mdssvc
curl &lt;span class="nt"&gt;-s&lt;/span&gt; https://raw.githubusercontent.com/samba-team/samba/master/source3/rpc_server/mdssvc/elasticsearch_mappings.json &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-o&lt;/span&gt; /usr/share/samba/mdssvc/elasticsearch_mappings.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Download the required files:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;wget https://raw.githubusercontent.com/senzidee/samba-spotlight-manticore/refs/heads/main/msctl
wget https://raw.githubusercontent.com/senzidee/samba-spotlight-manticore/refs/heads/main/ms-proxy.py
wget https://raw.githubusercontent.com/senzidee/samba-spotlight-manticore/refs/heads/main/ms-proxy.service
wget https://raw.githubusercontent.com/senzidee/samba-spotlight-manticore/refs/heads/main/smb.conf
wget https://raw.githubusercontent.com/senzidee/samba-spotlight-manticore/refs/heads/main/spotlight-indexer.service
wget https://raw.githubusercontent.com/senzidee/samba-spotlight-manticore/refs/heads/main/spotlight-indexer.sh

&lt;span class="nb"&gt;mv &lt;/span&gt;msctl /usr/bin/
&lt;span class="nb"&gt;mv &lt;/span&gt;ms-proxy.py /usr/local/bin/
&lt;span class="nb"&gt;mv &lt;/span&gt;ms-proxy.service /etc/systemd/system/
&lt;span class="nb"&gt;mv &lt;/span&gt;smb.conf /etc/samba/
&lt;span class="nb"&gt;mv &lt;/span&gt;spotlight-indexer.service /etc/systemd/system/
&lt;span class="nb"&gt;mv &lt;/span&gt;spotlight-indexer.sh /usr/local/bin/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Start the services:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;systemctl daemon-reload
systemctl &lt;span class="nb"&gt;enable &lt;/span&gt;ms-proxy spotlight-indexer
systemctl start ms-proxy spotlight-indexer
systemctl restart smbd
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Final Verification
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Check that services are running&lt;/span&gt;
systemctl status ms-proxy spotlight-indexer smbd

&lt;span class="c"&gt;# Count documents in the index&lt;/span&gt;
msctl count

&lt;span class="c"&gt;# Search for a file&lt;/span&gt;
msctl search README.md

&lt;span class="c"&gt;# Real-time logs during a search from the Mac&lt;/span&gt;
journalctl &lt;span class="nt"&gt;-u&lt;/span&gt; smbd &lt;span class="nt"&gt;-f&lt;/span&gt;
journalctl &lt;span class="nt"&gt;-u&lt;/span&gt; ms-proxy &lt;span class="nt"&gt;-f&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>tutorial</category>
      <category>linux</category>
    </item>
  </channel>
</rss>
