Mastodon’s default search only finds exact usernames and hashtags. This limitation frustrates power users and community managers who need to locate posts by keywords or phrases across the federated timeline. The cause is that Mastodon stores posts in a PostgreSQL database without a full-text index by default. This article explains how to install and configure Elasticsearch on your Mastodon server to enable full-text search for posts, including private and unlisted posts visible to the searcher.
Key Takeaways: Enabling Full-Text Search on Mastodon
- Elasticsearch 7.x installation: Version 7 is required because Mastodon’s search engine is not compatible with Elasticsearch 8.x as of the current stable release.
- docker-compose.yml edits: You must add the Elasticsearch service and environment variables to the Mastodon Docker stack for the backend to connect.
- Mastodon Sidekiq queue restart: After enabling search, restart the Sidekiq process so the search index is built and updated with new posts.
What Full-Text Search Does and What You Need Before Starting
Full-text search in Mastodon indexes the text content of statuses, including public, unlisted, and private posts that the searching user can see. It also indexes usernames, display names, and hashtags. When a user types a query in the search bar, Mastodon sends the request to Elasticsearch instead of scanning the PostgreSQL database. This returns results in under a second even on instances with millions of posts.
Before you begin, you need the following prerequisites:
- A Mastodon instance running on a Linux server with Docker and Docker Compose installed.
- Root or sudo access to the server.
- At least 2 GB of free RAM on the server. Elasticsearch requires a minimum of 1 GB heap memory.
- Elasticsearch 7.17.x. Do not use version 8.x — Mastodon does not support it.
Steps to Install and Configure Elasticsearch for Mastodon
These steps assume you are using the official Mastodon Docker setup. If you run Mastodon without Docker, adjust the paths and service names accordingly.
Step 1: Add Elasticsearch Service to Docker Compose
- Open your
docker-compose.ymlfile
Navigate to your Mastodon directory and opendocker-compose.ymlin a text editor with root privileges. - Add the Elasticsearch service block
Under theservices:section, add the following block:es: image: docker.elastic.co/elasticsearch/elasticsearch:7.17.24 environment: - "ES_JAVA_OPTS=-Xms512m -Xmx512m" - "discovery.type=single-node" - "xpack.security.enabled=false" volumes: - ./elasticsearch:/usr/share/elasticsearch/data ports: - "127.0.0.1:9200:9200"Adjust the memory values in
ES_JAVA_OPTSbased on your server capacity. The example uses 512 MB heap. - Add Elasticsearch volume to the volumes section
At the bottom of the file, undervolumes:, add:elasticsearch:
- Add environment variables to the web service
In thewebservice block, underenvironment:, add these lines:ES_ENABLED=true ES_HOST=es ES_PORT=9200 - Add the same environment variables to the sidekiq service
Repeat the previous step for thesidekiqservice block. - Save and close the file
Write the changes and exit the editor.
Step 2: Start Elasticsearch and Rebuild Mastodon Containers
- Create the Elasticsearch data directory
Runmkdir -p ./elasticsearchin your Mastodon directory to store index data persistently. - Set proper permissions for the data directory
Runchown -R 1000:1000 ./elasticsearchto match the Elasticsearch container user ID. - Recreate the Mastodon containers
Rundocker-compose up -dto start the new Elasticsearch container and restart the existing services with the new environment variables. - Verify Elasticsearch is running
Runcurl http://localhost:9200. You should see a JSON response containing"name" : "es"and"version" : {"number" : "7.17.24"}.
Step 3: Create the Search Index in Mastodon
- Run the search indexing task
Execute the following command inside the Mastodon web container:docker-compose run --rm web rails mastodon:search:deploy
This creates the Elasticsearch index and populates it with existing posts. The process may take several minutes depending on your database size. - Restart Sidekiq to apply the new index
Rundocker-compose restart sidekiqso that background jobs start pushing new posts to the index. - Test the search
Open your Mastodon instance in a browser. Log in with any account. Type a word from a known post into the search bar. You should see matching results below the user and hashtag results.
Common Issues After Enabling Full-Text Search
Search Returns No Results for Known Posts
If you search for a word that exists in a public post but nothing appears, the index may not have been built yet. Wait a few minutes for Sidekiq to process the indexing queue. You can check the Sidekiq dashboard at /sidekiq on your instance for the number of pending jobs in the default queue. If the queue remains stuck, restart Sidekiq again with docker-compose restart sidekiq.
Elasticsearch Container Fails to Start With Memory Error
If the container exits with an error about memory locking or insufficient heap, increase the ES_JAVA_OPTS values in docker-compose.yml. For a server with 4 GB RAM, set -Xms1g -Xmx1g. Also ensure that vm.max_map_count is set to at least 262144 on the host. Run sysctl -w vm.max_map_count=262144 and make the change permanent by adding vm.max_map_count=262144 to /etc/sysctl.conf.
Search Works but Private Posts Are Missing From Results
This is expected behavior. Mastodon only indexes private and direct posts for the author of those posts. Other users cannot search for content in private or direct posts. If you are an admin and need to search all posts, you must use the database directly via psql or the Mastodon admin dashboard. There is no Elasticsearch setting to override this permission boundary.
| Item | Elasticsearch 7.17.x | PostgreSQL Full-Text Search |
|---|---|---|
| Search speed for large instances | Under 1 second for millions of posts | Several seconds to minutes |
| Index update latency | Near real-time (seconds) | Requires manual VACUUM ANALYZE |
| Supported content types | Text, usernames, display names, hashtags | Text only with limited stemming |
| Memory requirement | 1 GB heap minimum | None beyond PostgreSQL |
| Mastodon compatibility | Official and stable | Not supported |
After enabling Elasticsearch, your Mastodon instance now returns keyword-based search results in real time. Users can find posts by topic, phrase, or username without relying on hashtags alone. As a next step, review the Mastodon admin settings under Preferences > Administration > Server Settings > Discovery to adjust search visibility for unlisted posts. For advanced tuning, set the ES_JAVA_OPTS heap size to 50 percent of your server RAM but never exceed 31 GB due to Elasticsearch’s compressed object pointer limit.