There are things most CMS tools are great at, and then there are things they suck at. Universally? They all suck at search when you get to scale.
This is not really true fault of the CMS (be it WordPress, Drupal, Hugo, etc). The problem is search is difficult to build! If it was easy, everyone would do it. The whole reason Google rose to dominance was that it made search easy and reliable. And that’s great, but not everyone is okay with relying on 3rd party services.
I’ve used ElasticSearch (too clunky to run, a pain to customize), Lunr (decent for static sites), and even integrated Yahoo and Google searches. They all have issues.
Recently I was building out a search tool for a private (read: internal, no access if you’re not ‘us’) service, and I was asked to do it with MeiliSearch. It was new to me. As I installed and configured it, I thought … “This could be a nice solution.”
Build Your Instance
When you read the directions, you’ll notice they want to install the app as root, meaning it would be one install. And that sounds okay until you start thinking about multiple servers using one instance (for example, WordPress Multisite) where you don’t want to cross contaminate your results. Wouldn’t want posts from Ipstenu.org and Woody.com showing up on HalfElf, and all.
There are a couple of ways around that, Multi-Tenancy and multiple Indexes. I went with the indexes for now, but I’m sure I’ll want tenancy later.
I’m doing all this on DreamHost, because I love those weirdos, but there are pre-built images on DigitalOcean if that floats your goat:
- Make a dedicated server or a DreamCompute (I used the latter) – you need root access
- Set the server to Nginx with the latest PHP – this will allow you to make a proxy later
- Add your ssh key from
~/.ssh/id_rsa.pub
to your SSH keys – this will let you log in root (or an account with root access)
Did that? Great! The actual installation is pretty easy, you can just follow the directions down the line.
Integration with WordPress
The first one I integrated with was WordPress and for that I used Yuto.
It’s incredibly straightforward to set up. Get your URL and your Master Key. Plunk them in. Save. Congratulations!
On the Indices page I originally set my UIDs to ipstenu_posts
and ipstenu_pages
– to prevent collisions. But then I realized… I wanted the whole site on there, so I made them both ipstenu_org

I would like to change the “Ipstenu_org” flag, like ‘If there’s only one Index, don’t show the name’ and then a way to customize it.
I will note, there’s a ‘bug’ in Yuto – it has to load all your posts into a cache before it will index them, and that’s problematic if you have a massive amount of posts, or if you have anti-abuse tools that block long actions like that. I made a quick WP-CLI command.
WP-CLI Command
The command I made is incredibly simple: wp ipstenu yuto build-index posts
The code is fast, too. It took under a minute for over 1000 posts.
After I made it, I shared it with the creators of Yuto, and their next release includes a version of it.
Multiple Indexes and Tenants
You’ll notice that I have two indexes. This is due to how the plugin works, making an index per post type. In so far as my ipstenu.org sites go, I don’t mind having them all share a tenant. After all, they’re all on a server together.
However… This server will also house a Hugo site and my other WP site. What to do?
The first thing I did was I made a couple more API keys! They have read-write access to a specific index (the Key for “Ipstenu” has access to my ipstenu_org
index and so on). That lets me manage things a lot more easily and securely.
While Yuto will make the index, it cannot make custom keys, so I used the API:
curl \
-X POST 'https://example.com/keys' \
-H 'Authorization: Bearer BEARERKEY' \
-H 'Content-Type: application/json' \
--data-binary '{
"description": "Ipstenu.org",
"actions": ["*"],
"indexes": ["ipstenu_org"],
"expiresAt": null
}'
That returns a JSON string with (among other things) a key that you can use in WordPress.
Will I look into Tenancy? Maybe. Haven’t decided yet. For now, separate indexes works for me.