AI

Install Qdrant on Ubuntu 26.04 / 24.04 / 22.04

Qdrant is the open source vector database that powers retrieval at scale for AI applications. This guide walks through installing Qdrant on Ubuntu LTS, covering both the Docker path most teams use and the native .deb path when you need a system service without Docker. The same steps apply to Ubuntu 26.04, 24.04, and 22.04, with version-aware commands for each.

Original content from computingforgeeks.com - post 167996

By the end you will have Qdrant running, the REST API responding, the built in Web UI loaded in a browser, and a first collection holding a few vectors so you can confirm search works. We tested every command in this guide on a fresh Ubuntu 24.04 LTS VM. Companion code lives at c4geeks/qdrant/install-ubuntu, and the canonical reference for any flag in this article is the official Qdrant documentation.

If you are new to vector databases as a category, our vector search vs traditional search explainer walks through why dense retrieval beats keyword matching for fuzzy intent queries. If you are weighing Qdrant against a Postgres extension, the install pgvector on PostgreSQL walkthrough sets up the other end of the self host spectrum.

Before you begin

You will need the following:

  • Ubuntu 26.04, 24.04, or 22.04 LTS server with at least 2 GB of RAM. The official Docker image runs on amd64 and arm64.
  • A user account with sudo rights.
  • Network access to github.com (release downloads) and download.docker.com (Docker repo).
  • Two free TCP ports: 6333 (REST and Web UI) and 6334 (gRPC).
  • Roughly 1 GB of disk for the image plus whatever your dataset needs in /var/lib/qdrant/storage.

Refresh the package index so the rest of the steps run cleanly:

sudo apt update
sudo apt install -y ca-certificates curl jq

Method 1: Install Qdrant with Docker

Docker is the recommended install path for almost every Qdrant deployment. The image is the same one the maintainers ship to production, so what runs on your laptop is what runs in the cluster.

Step 1: Install the Docker engine

Add the Docker apt repository and install the engine plus the Compose plugin:

sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg \
  -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc

. /etc/os-release
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] \
  https://download.docker.com/linux/ubuntu ${VERSION_CODENAME} stable" \
  | sudo tee /etc/apt/sources.list.d/docker.list >/dev/null

sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io \
  docker-buildx-plugin docker-compose-plugin

Add your user to the docker group so you do not need sudo for routine commands. Log out and back in for the group change to take effect:

sudo usermod -aG docker $USER
docker --version
docker compose version

Step 2: Detect the latest Qdrant release and pull the image

Pull a specific Qdrant tag so your environment is reproducible. Capture the latest release tag into a shell variable, then use it everywhere:

export QDRANT_VERSION=$(curl -s https://api.github.com/repos/qdrant/qdrant/releases/latest | jq -r .tag_name)
echo $QDRANT_VERSION

docker pull qdrant/qdrant:${QDRANT_VERSION}  # https://github.com/qdrant/qdrant/releases

Step 3: Run Qdrant with persistent storage

Create a host directory for the vector data, bind it into the container at the canonical /qdrant/storage path, and start the service:

sudo mkdir -p /var/lib/qdrant/storage

docker run -d \
  --name qdrant \
  --restart unless-stopped \
  -p 6333:6333 -p 6334:6334 \
  -v /var/lib/qdrant/storage:/qdrant/storage:z \
  qdrant/qdrant:${QDRANT_VERSION}

Confirm the container is running and the ports are bound:

docker ps --filter name=qdrant --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"

The output should show the container in the Up state with both REST and gRPC ports mapped to the host:

Terminal showing Qdrant Docker pull and run commands

Step 4: Verify the install

Qdrant exposes three quick endpoints to confirm the service is alive, ready to serve queries, and on the expected version:

curl -sf http://localhost:6333/healthz
curl -s http://localhost:6333/ | jq .
curl -s http://localhost:6333/readyz

You should see the health probe pass, the version response confirm the running tag, and readiness report that the shards are loaded:

Terminal output of Qdrant healthz and version endpoints

Step 5: Create your first collection and search

A collection holds points (your vectors plus their metadata). Create one called demo with four dimensional vectors and cosine distance, then upsert three sample points:

curl -s -X PUT http://localhost:6333/collections/demo \
  -H "Content-Type: application/json" \
  -d '{"vectors":{"size":4,"distance":"Cosine"}}'

curl -s -X PUT http://localhost:6333/collections/demo/points \
  -H "Content-Type: application/json" \
  -d '{
    "points": [
      {"id":1, "vector":[0.1,0.2,0.3,0.4], "payload":{"city":"Nairobi"}},
      {"id":2, "vector":[0.2,0.3,0.4,0.5], "payload":{"city":"Berlin"}},
      {"id":3, "vector":[0.9,0.8,0.7,0.6], "payload":{"city":"Tokyo"}}
    ]
  }'

Now run a similarity search. The vector closest to the query gets the highest score:

curl -s -X POST http://localhost:6333/collections/demo/points/search \
  -H "Content-Type: application/json" \
  -d '{"vector":[0.15,0.25,0.35,0.45],"limit":3,"with_payload":true}' \
  | jq .

Berlin lands first, Nairobi second, Tokyo last because its vector points the other way. This is your end to end sanity check that ingest, index, and query all work:

Terminal output of first vector search returning Berlin Nairobi Tokyo

Step 6: Open the built in Web UI

Every Qdrant container ships with a browser based UI at /dashboard. Open http://<server-ip>:6333/dashboard in a browser. The Collections panel lists the demo collection you just created, with status, point count, and vector config:

Qdrant Web UI showing demo collection with 3 points and GREEN status

Click Console in the sidebar to run REST calls directly from the browser. Useful for quick experiments and onboarding teammates who do not have curl in their muscle memory:

Qdrant Web UI Console panel showing REST API examples

Docker Compose alternative

If you prefer Compose, the equivalent setup with an API key and a memory limit fits in one file. Save this as docker-compose.yml next to a .env that defines QDRANT_VERSION and QDRANT_API_KEY:

services:
  qdrant:
    image: qdrant/qdrant:${QDRANT_VERSION}  # https://github.com/qdrant/qdrant/releases
    container_name: qdrant
    restart: unless-stopped
    ports:
      - "6333:6333"
      - "6334:6334"
    volumes:
      - ./qdrant_storage:/qdrant/storage:z
      - ./qdrant_snapshots:/qdrant/snapshots:z
    environment:
      QDRANT__SERVICE__API_KEY: ${QDRANT_API_KEY}
      QDRANT__TELEMETRY_DISABLED: "true"
    deploy:
      resources:
        limits:
          memory: 4G

Generate a strong API key and bring the stack up:

echo "QDRANT_VERSION=${QDRANT_VERSION}" > .env
echo "QDRANT_API_KEY=$(openssl rand -base64 32)" >> .env

docker compose up -d
docker compose logs -f --tail=20 qdrant

Every subsequent curl now needs the api-key header:

curl -s http://localhost:6333/collections \
  -H "api-key: $(grep QDRANT_API_KEY .env | cut -d= -f2)"

Method 2: Native .deb install with systemd

The native path drops the Docker layer and lets systemd manage Qdrant directly. Use this when your host policy forbids Docker, when you need tighter integration with journalctl, or when the rest of your stack uses native packages.

Download the official .deb for the latest release. The release page publishes amd64 and arm64 packages:

QDRANT_PKG_VERSION="${QDRANT_VERSION#v}"
cd /tmp
curl -fL --retry 3 -o "qdrant_${QDRANT_PKG_VERSION}-1_amd64.deb" \
  "https://github.com/qdrant/qdrant/releases/download/${QDRANT_VERSION}/qdrant_${QDRANT_PKG_VERSION}-1_amd64.deb"  # https://github.com/qdrant/qdrant/releases

sudo apt install -y "./qdrant_${QDRANT_PKG_VERSION}-1_amd64.deb"

Create a dedicated system user and storage directory, then drop a systemd unit:

sudo useradd -r -s /sbin/nologin qdrant
sudo mkdir -p /var/lib/qdrant/storage /etc/qdrant
sudo chown -R qdrant:qdrant /var/lib/qdrant

Write the unit file at /etc/systemd/system/qdrant.service:

[Unit]
Description=Qdrant Vector Database
After=network.target

[Service]
Type=simple
User=qdrant
Group=qdrant
WorkingDirectory=/var/lib/qdrant
ExecStart=/usr/bin/qdrant
Restart=on-failure
RestartSec=5
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target

Reload systemd, enable, and start the service:

sudo systemctl daemon-reload
sudo systemctl enable --now qdrant
sudo systemctl status qdrant --no-pager
journalctl -u qdrant -n 20 --no-pager

The same health endpoint works against the native install:

curl -sf http://localhost:6333/healthz

Open the firewall safely

Never expose Qdrant on a public interface without authentication. The default Docker run is open, which is fine on a laptop and dangerous on a VPS. If UFW is enabled, allow REST and gRPC from a trusted CIDR only:

TRUSTED_CIDR="10.0.0.0/8"   # adjust to your office or VPN range

sudo ufw allow from $TRUSTED_CIDR to any port 6333 proto tcp
sudo ufw allow from $TRUSTED_CIDR to any port 6334 proto tcp
sudo ufw reload
sudo ufw status numbered

For internet facing deployments, bind Qdrant to 127.0.0.1 and put Nginx with TLS plus an API key in front. The full hardening walkthrough is the next article in this series.

Upgrade Qdrant

Upgrades are usually a tag swap. With Docker, stop the container, re-detect the latest tag, and recreate. The storage volume persists across the swap:

export QDRANT_VERSION=$(curl -s https://api.github.com/repos/qdrant/qdrant/releases/latest | jq -r .tag_name)
docker pull qdrant/qdrant:${QDRANT_VERSION}  # https://github.com/qdrant/qdrant/releases
docker stop qdrant && docker rm qdrant
docker run -d --name qdrant --restart unless-stopped \
  -p 6333:6333 -p 6334:6334 \
  -v /var/lib/qdrant/storage:/qdrant/storage:z \
  qdrant/qdrant:${QDRANT_VERSION}

With Docker Compose, edit QDRANT_VERSION in .env and run docker compose pull && docker compose up -d. With the native install, download the new .deb and let apt install upgrade in place, then restart the service.

Troubleshooting common issues

Port 6333 already in use

If docker run fails with bind: address already in use, find what is holding the port and either stop it or remap the Qdrant ports:

sudo ss -ltnp | grep -E ':(6333|6334)\b'

# Remap if you cannot free the port
docker run -d --name qdrant -p 16333:6333 -p 16334:6334 \
  -v /var/lib/qdrant/storage:/qdrant/storage:z \
  qdrant/qdrant:${QDRANT_VERSION}

Container restarts in a loop

Look at the logs first. The most common culprit is a permission error on the bind mount when SELinux or AppArmor labels conflict:

docker logs --tail=50 qdrant
sudo chown -R 1000:1000 /var/lib/qdrant/storage

Web UI loads but Collections list is empty

The Web UI ships empty on a fresh install. Create your first collection through the Console panel or via curl, then click the refresh icon next to the Collections heading.

Where to next

You now have a working Qdrant on Ubuntu, a sample collection, and the Web UI for quick experiments. The series builds outward from here: secure Qdrant with API key, TLS, and Nginx is the next stop for any host reachable beyond localhost, and the Qdrant Web UI tour covers every panel in the dashboard. To wire Qdrant into a local LLM pipeline, our self hosted RAG with Ollama guide pairs naturally with Qdrant as a drop in for the vector store, and the Ollama commands cheat sheet covers the embedding side.

Related Articles

Databases How To Install PostgreSQL 11 on Fedora 39/38/37/36/35 Backup LVM Snapshots for Consistent Server Backups on Linux Containers How To Deploy Ubuntu Pod in Kubernetes|OpenShift Databases Install Single Node TiDB database Cluster on CentOS 8

Leave a Comment

Press ESC to close