Posted on
Artificial Intelligence

Best Vector Databases for Linux

Author
  • User
    linuxbash
    Posts by this author
    Posts by this author

Best Vector Databases for Linux: Fast, Local, and Bash-Friendly

Your embeddings are ready, your RAG pipeline is underway, and now you need a place to put millions of vectors—locally, fast, and with Linux scripting at the core. Shoving vectors into JSON files won’t cut it; you need a purpose-built vector database that runs well on Linux, plays nicely with Bash, and scales from a laptop to the lab.

This guide helps you choose and quickly stand up the best vector databases for Linux, with copy-paste installs and curl-able examples. You’ll leave with a shortlist, a working instance, and a checklist to benchmark and pick the right fit.


Why vector databases on Linux are worth your time

  • Performance and control: Local Linux gives you raw IO, predictable latency, and resource control (cgroups, NUMA pinning).

  • Privacy and cost: Keep embeddings and documents on your own hardware; no egress surprises.

  • Dev velocity: Bash + containers mean reproducible spins, teardown, and CI-friendly testing.

  • Versatility: Blend vector search with metadata filtering, hybrid BM25+vector ranking, and transactions where needed.


What “best” means here

We focus on mature, Linux-friendly options you can boot quickly and query with curl or psql:

  • Qdrant: Rust-based, blazing fast, dead-simple REST.

  • Weaviate: Schema-first, hybrid search, strong REST/GraphQL.

  • PostgreSQL + pgvector: If you already love Postgres, get vectors where your data lives.

  • OpenSearch (k-NN): If you need log/keyword + vector in one cluster.

All four are open source and run great in containers.


Prerequisites: one-time setup on Linux

Choose Podman (rootless-friendly) or Docker. We’ll use Podman in examples.

Install Podman, curl, and jq:

  • Debian/Ubuntu
sudo apt update && sudo apt install -y podman curl jq
  • Fedora/RHEL/CentOS Stream
sudo dnf install -y podman curl jq
  • openSUSE/SLE
sudo zypper refresh && sudo zypper install -y podman curl jq

Optional: install Docker instead (varies by distro)

  • Debian/Ubuntu
sudo apt update && sudo apt install -y docker.io
  • Fedora
sudo dnf install -y moby-engine
  • openSUSE/SLE
sudo zypper install -y docker

Security note: Examples bind to localhost. For remote access, secure with auth, TLS, and firewalls.


1) Qdrant: fast, simple, production-ready REST

When to pick it:

  • You want speed, a clean REST API, top-tier vector filtering, and easy persistence.

  • Great for local RAG stores, semantic search over docs, and on-box apps.

Quick start:

podman run -d --name qdrant -p 6333:6333 qdrant/qdrant:latest

Create a collection (3-D demo) and add points:

curl -s -X PUT 'http://localhost:6333/collections/demo' \
  -H 'content-type: application/json' \
  -d '{ "vectors": { "size": 3, "distance": "Cosine" } }' | jq

curl -s -X PUT 'http://localhost:6333/collections/demo/points?wait=true' \
  -H 'content-type: application/json' \
  -d '{
        "points": [
          {"id":1,"vector":[0.1,0.2,0.3],"payload":{"text":"apt cheatsheet"}},
          {"id":2,"vector":[0.2,0.1,0.0],"payload":{"text":"dnf tips"}},
          {"id":3,"vector":[0.0,0.1,0.2],"payload":{"text":"zypper guide"}}
        ]
      }' | jq

Search by vector:

curl -s -X POST 'http://localhost:6333/collections/demo/points/search' \
  -H 'content-type: application/json' \
  -d '{ "vector":[0.1,0.18,0.27], "limit": 2, "with_payload": true }' \
| jq '.result[] | {id, score, text: .payload.text}'

Persist data: mount a volume (replace $PWD with your path):

podman rm -f qdrant
podman run -d --name qdrant -p 6333:6333 \
  -v $PWD/qdrant_storage:/qdrant/storage \
  qdrant/qdrant:latest

2) Weaviate: schema-first with hybrid search options

When to pick it:

  • You prefer a schema, GraphQL, hybrid BM25+vector search, and extensibility.

Quick start (no built-in vectorizer, you supply vectors):

podman run -d --name weaviate -p 8080:8080 \
  -e AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED=true \
  -e DEFAULT_VECTORIZER_MODULE=none \
  -e CLUSTER_HOSTNAME=node1 \
  semitechnologies/weaviate:latest

Health check:

curl -s localhost:8080/v1/.well-known/ready && echo

Create a class and insert data with your own vectors:

curl -s -X POST localhost:8080/v1/schema \
  -H 'content-type: application/json' \
  -d '{
        "classes":[
          {"class":"Doc","vectorIndexType":"hnsw",
           "properties":[{"name":"text","dataType":["text"]}]}
        ]
      }' | jq

curl -s -X POST localhost:8080/v1/objects \
  -H 'content-type: application/json' \
  -d '{
        "class":"Doc",
        "properties":{"text":"Linux package managers overview"},
        "vector":[0.1,0.2,0.3]
      }' | jq

Query with nearVector (GraphQL):

curl -s -X POST localhost:8080/v1/graphql \
  -H 'content-type: application/json' \
  -d '{
        "query":"{ Get { Doc(nearVector:{vector:[0.1,0.18,0.27]}, limit:2) { text _additional { distance } } } }"
      }' | jq

Persist data:

podman rm -f weaviate
podman run -d --name weaviate -p 8080:8080 \
  -e AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED=true \
  -e DEFAULT_VECTORIZER_MODULE=none \
  -e CLUSTER_HOSTNAME=node1 \
  -v $PWD/weaviate_data:/var/lib/weaviate \
  semitechnologies/weaviate:latest

3) PostgreSQL + pgvector: vectors where your data lives

When to pick it:

  • You already rely on Postgres for transactions/joins and want vectors without a new service.

  • Ideal for smaller to mid-scale embeddings or strong relational needs.

Quick start (container with pgvector preinstalled):

podman run -d --name pgvector -e POSTGRES_PASSWORD=secret -p 5432:5432 pgvector/pgvector:pg16

Create extension, table, data, and run a search:

podman exec -i pgvector psql -U postgres -c "
CREATE EXTENSION IF NOT EXISTS vector;
CREATE TABLE items (id bigserial primary key, embedding vector(3), note text);
INSERT INTO items (embedding, note) VALUES
  ('[0.1,0.2,0.3]', 'apt cheatsheet'),
  ('[0.2,0.1,0.0]', 'dnf tips'),
  ('[0.0,0.1,0.2]', 'zypper guide');
SELECT id, note, (embedding <-> '[0.1,0.18,0.27]') AS l2
FROM items
ORDER BY embedding <-> '[0.1,0.18,0.27]' LIMIT 2;"

Optional: install a local psql client

  • Debian/Ubuntu
sudo apt install -y postgresql-client
  • Fedora/RHEL/CentOS Stream
sudo dnf install -y postgresql
  • openSUSE/SLE
sudo zypper install -y postgresql-client

Persist data:

podman rm -f pgvector
podman run -d --name pgvector -e POSTGRES_PASSWORD=secret -p 5432:5432 \
  -v $PWD/pg_data:/var/lib/postgresql/data \
  pgvector/pgvector:pg16

4) OpenSearch with k-NN: logs, keyword, and vectors together

When to pick it:

  • You already use Elasticsearch/OpenSearch for logs/text and want vector search in the same stack.

Quick start (security disabled for local testing only):

podman run -d --name opensearch -p 9200:9200 -p 9600:9600 \
  -e "discovery.type=single-node" \
  -e "plugins.security.disabled=true" \
  -e "OPENSEARCH_JAVA_OPTS=-Xms1g -Xmx1g" \
  opensearchproject/opensearch:2.11.0

Create a k-NN index and load data:

curl -s -X PUT localhost:9200/vectors \
  -H 'content-type: application/json' \
  -d '{
        "settings": {"index.knn": true},
        "mappings": {"properties": {
          "my_vector": {
            "type":"knn_vector",
            "dimension":3,
            "method":{"name":"hnsw","space_type":"cosinesimil","engine":"nmslib"}
          },
          "text": {"type":"text"}
        }}
      }' | jq

curl -s -X POST 'localhost:9200/vectors/_doc/1?refresh=true' \
  -H 'content-type: application/json' \
  -d '{"text":"apt cheatsheet","my_vector":[0.1,0.2,0.3]}'

curl -s -X POST 'localhost:9200/vectors/_doc/2?refresh=true' \
  -H 'content-type: application/json' \
  -d '{"text":"dnf tips","my_vector":[0.2,0.1,0.0]}'

curl -s -X POST 'localhost:9200/vectors/_doc/3?refresh=true' \
  -H 'content-type: application/json' \
  -d '{"text":"zypper guide","my_vector":[0.0,0.1,0.2]}'

k-NN search:

curl -s -X POST 'localhost:9200/vectors/_search' \
  -H 'content-type: application/json' \
  -d '{
        "size":2,
        "knn": {"field":"my_vector","query_vector":[0.1,0.18,0.27],"k":2,"num_candidates":3},
        "_source":["text"]
      }' | jq '.hits.hits[] | {id: ._id, score, text: ._source.text}'

Persist data (mount a volume) and enable security for non-local deployments.


Real-world Linux example: make your notes searchable by meaning

  • Generate embeddings for your Markdown files with your favorite model (e.g., sentence-transformers).

  • Store vectors and filenames in Qdrant or Postgres.

  • Use a Bash function to submit a query vector and open the top hit in $EDITOR.

Sketch:

embed="[0.11,0.19,0.27]"  # your query embedding
curl -s -X POST 'http://localhost:6333/collections/notes/points/search' \
  -H 'content-type: application/json' \
  -d "{ \"vector\": $embed, \"limit\": 5, \"with_payload\": true }" \
| jq -r '.result[].payload.path' | head -1 | xargs -r ${EDITOR:-vim}

Actionable checklist before you decide

1) Match the workload

  • High QPS with filters? Qdrant/Weaviate.

  • Strong relational joins/transactions? Postgres + pgvector.

  • Unified logs + vector? OpenSearch.

2) Choose the right metric

  • Cosine for normalized embeddings.

  • Dot/inner product for learned similarity.

  • L2 for some vision/audio models. Keep it consistent in both DB and model.

3) Tune the index

  • HNSW M/efConstruction for build speed vs recall.

  • efSearch/num_candidates for query-time quality/perf.

  • Use small, representative benchmarks with your vectors.

4) Keep metadata and enable hybrid

  • Store text, tags, and timestamps for filtering and ranking.

  • Consider hybrid BM25 + vector rerank in Weaviate/OpenSearch.

5) Test durability and ops

  • Mount volumes, take snapshots/backups.

  • Measure memory usage; most vector indexes are RAM-hungry.

  • Add resource limits (cgroups) and watch IO with iostat/vmstat.


Cleanup

Stop and remove test containers and volumes:

podman rm -f qdrant weaviate pgvector opensearch
rm -rf ./qdrant_storage ./weaviate_data ./pg_data

Conclusion and next step

Pick one and run a one-hour spike:

  • If you want the simplest and fastest local store, start with Qdrant.

  • If you like schemas and hybrid search, try Weaviate.

  • If your data already lives in Postgres, add pgvector.

  • If you’re centralizing logs and text search, enable OpenSearch k-NN.

Next: wire your embedding generator, import a few thousand vectors, and benchmark with your actual queries. When you’ve got numbers, you’ll have clarity. If you want a follow-up with a Bash-first ingestion and benchmarking script for your chosen database, ask and I’ll share a ready-made template.