How to Self-Host Sonic with Docker Compose

What Is Sonic?

Sonic is a lightweight, schema-less search backend designed to replace heavy search engines like Elasticsearch when you need basic full-text search with minimal resource usage. Written in Rust, Sonic uses less than 20 MB of RAM while providing fast search with auto-complete suggestions. It’s not a database — it stores search indexes only and returns document IDs that you look up in your actual database.

Prerequisites

  • A Linux server (Ubuntu 22.04+ recommended)
  • Docker and Docker Compose installed (guide)
  • 64 MB+ RAM (Sonic is extremely lightweight)
  • 1 GB free disk space
  • No GPU required

Docker Compose Configuration

Create a docker-compose.yml file:

services:
  sonic:
    image: valeriansaliou/sonic:v1.4.9
    container_name: sonic
    ports:
      - "1491:1491"
    volumes:
      - sonic_data:/var/lib/sonic/store
      - ./sonic.cfg:/etc/sonic.cfg:ro
    restart: unless-stopped

volumes:
  sonic_data:

Create a sonic.cfg configuration file:

[server]
log_level = "info"

[channel]
inet = "0.0.0.0:1491"
tcp_timeout = 300

[channel.search]
query_limit_default = 10
query_limit_maximum = 100
query_alternates_try = 4
suggest_limit_default = 5
suggest_limit_maximum = 20

[store]

[store.kv]
path = "/var/lib/sonic/store/kv/"
retain_word_objects = 1000

[store.kv.pool]
inactive_after = 1800

[store.kv.database]
flush_after = 900
compress = true

[store.fst]
path = "/var/lib/sonic/store/fst/"

[store.fst.pool]
inactive_after = 300

[store.fst.graph]
consolidate_after = 180
max_size = 2048
max_words = 250000

Start the stack:

docker compose up -d

Initial Setup

Sonic uses a custom text protocol over TCP (not HTTP). Use a Sonic client library or telnet:

telnet localhost 1491

Connect and Push Data

START search SecretPassword
# Connected to Sonic

# Push text into the index
PUSH messages user:1 conv:1 "Hello, how are you today?"
PUSH messages user:1 conv:2 "Let's talk about self-hosting"

# Search
QUERY messages user:1 "self-hosting"
# Returns: conv:2

# Auto-suggest
SUGGEST messages user:1 "sel"
# Returns: self-hosting

QUIT

Using Client Libraries

Sonic has official and community client libraries for most languages:

  • Node.js: sonic-channel
  • Python: sonic-client
  • Go: go-sonic
  • Ruby: sonic-ruby
  • PHP: php-sonic

Example with Node.js:

const Sonic = require("sonic-channel");

const search = new Sonic.Search({ host: "localhost", port: 1491, auth: "SecretPassword" });
await search.connect();
const results = await search.query("messages", "user:1", "self-hosting");
// results = ["conv:2"]

Configuration

Key Config Options

SectionSettingDefaultDescription
channel.inet0.0.0.0:1491Listen address and port
channel.search.query_limit_default10Default results per query
channel.search.query_alternates_try4Typo correction alternatives
channel.search.suggest_limit_default5Default suggestions count
store.kv.retain_word_objects1000Word objects kept in memory
store.fst.graph.max_words250000Max words in suggestion graph

Authentication

Set a password in sonic.cfg:

[channel]
auth_password = "YourSecretPassword"

All client connections must authenticate with START [mode] [password].

Reverse Proxy

Sonic uses a TCP protocol, not HTTP. You cannot put it behind a standard HTTP reverse proxy. Access it directly via port 1491 from your application servers. Restrict access via firewall rules. See Reverse Proxy Setup.

Backup

Back up the Sonic data volume:

docker run --rm -v sonic_data:/data -v $(pwd):/backup alpine \
  tar czf /backup/sonic-backup.tar.gz /data

Sonic stores search indexes only. If you lose the data, you can re-index from your source database. See Backup Strategy.

Troubleshooting

Connection Refused

Symptom: Can’t connect on port 1491. Fix: Verify channel.inet in sonic.cfg is set to 0.0.0.0:1491. Check Docker port mapping. Ensure the config file is mounted correctly.

No Search Results

Symptom: QUERY returns empty results. Fix: Verify data was pushed with PUSH. The collection and bucket names must match exactly. Sonic indexes text — it returns document IDs, which you look up in your database.

High Memory Usage

Symptom: Sonic using more RAM than expected. Fix: Reduce retain_word_objects in config. Reduce max_words in FST graph settings. Sonic is designed to use minimal RAM, so high usage usually indicates a very large index.

Resource Requirements

  • RAM: 10-50 MB (extremely lightweight)
  • CPU: Very low
  • Disk: Index size is typically 10-20% of indexed text

Verdict

Sonic is the lightest search engine you can self-host. If you need basic full-text search and auto-suggest for an application and don’t want the overhead of Elasticsearch or even Meilisearch, Sonic does the job in 20 MB of RAM. The trade-off is a limited feature set — no faceting, no aggregations, no HTTP API.

Choose Sonic for minimal search on resource-constrained servers (Raspberry Pi, cheap VPS). Choose Meilisearch for a more complete search engine with an HTTP API. Choose Elasticsearch for full-featured search and analytics.

Frequently Asked Questions

How does Sonic compare to Meilisearch?

Sonic is a search index that returns document IDs — it doesn’t store or serve documents. Meilisearch is a full search engine with an HTTP API, faceting, filtering, and document storage. Sonic uses 10-50 MB of RAM; Meilisearch uses 500+ MB. Choose Sonic for minimal search on constrained hardware; Meilisearch for a complete search solution.

Does Sonic have an HTTP API?

No. Sonic uses a custom TCP-based text protocol, not REST/HTTP. You need a Sonic client library (available for Node.js, Python, Go, Ruby, PHP) to integrate with your application. This is simpler to implement but less standard than HTTP APIs.

Can Sonic handle typos and fuzzy matching?

Yes. Sonic includes built-in typo correction via the query_alternates_try setting. It also supports auto-suggest through the SUGGEST command, which provides word completions as users type.

Does Sonic replace my database?

No. Sonic is a search index only — it stores search terms mapped to document IDs. When you search, Sonic returns IDs that you look up in your actual database (PostgreSQL, MySQL, MongoDB, etc.). It’s a complement to your database, not a replacement.

Can Sonic run on a Raspberry Pi?

Yes. Sonic is one of the few search engines that runs well on ARM hardware with as little as 64 MB of RAM. The Rust binary is efficient on low-power devices, making it ideal for homelab search functionality.

How do I add data to Sonic?

Use the PUSH command via a client library or TCP connection. For each document, push the text content along with a collection name, bucket name, and unique object ID. Sonic indexes the text and returns the object ID when searches match.

Comments