Qdrant на Ubuntu 24.04: пошаговая установка
В документации Qdrant установка — одна строка с docker run, и на Ubuntu 24.04 она честно отрабатывает: вместе с базой, открытой в интернет без пароля, дашбордом на 404 и хранилищем, которое исчезает при первом docker compose down -v. Ниже — установка Qdrant на Ubuntu двумя рабочими способами, бинарником под systemd и через Docker Compose, с закрытым периметром, ключом и снапшотами.
Содержание
- Что именно ставится и чем noble отличается от jammy
- Подготовка системы: пользователь, каталоги, лимиты
- Способ 1: бинарник из релиза и systemd-юнит
- Способ 2: Docker Compose и ловушка с ufw
- Первая коллекция, API-ключ и клиент на Python 3.12
- Домен, HTTPS, снапшоты и обновления
- Какой сервер под Qdrant брать в MAATRIX
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →Что именно ставится и чем noble отличается от jammy
Qdrant — векторная база на Rust: один исполняемый файл, без JVM, интерпретатора и GPU. Он держит коллекции векторов с полезной нагрузкой (payload), ищет ближайших соседей по индексу HNSW и отвечает по REST и gRPC. Портов три: 6333 — REST API и дашборд на /dashboard, 6334 — gRPC, быстрее на массовой загрузке, 6335 — обмен между узлами кластера.
Дальше главное: пакета Qdrant в репозиториях Ubuntu нет, и собственного apt-репозитория проект не держит. apt-cache policy qdrant на noble возвращает пустой кандидат, а в релизах на GitHub лежат tar-архивы, а не .deb. Рабочих путей ровно два — бинарник под systemd и контейнер.
Чем noble отличается от jammy — каждая строка ниже во что-нибудь упирается:
| Что | Ubuntu 22.04 | Ubuntu 24.04 (noble) |
|---|---|---|
| glibc | 2.35 | 2.39 |
| Python по умолчанию | 3.10 | 3.12 + PEP 668 |
| nginx в репозитории | 1.18 | 1.24.0 |
| systemd | 249 | 255 |
Compose v1 (docker-compose) | ещё есть | удалён |
| UID 1000 | свободен | занят учёткой ubuntu |
Собранный на noble бинарник не запустится на 22.04 — /lib/x86_64-linux-gnu/libc.so.6: version 'GLIBC_2.38' not found; обратное направление работает, поэтому официальный -gnu-архив ставится без вопросов. PEP 668 ломает pip install qdrant-client, отсутствие Compose v1 даёт docker-compose: command not found, а занятый UID 1000 мешает завести сервисного пользователя.
Подготовка системы: пользователь, каталоги, лимиты
Обновляемся и ставим инструменты — jq понадобится почти в каждой команде.
sudo apt update && sudo apt -y upgrade
sudo apt -y install curl jq ca-certificates
На 24.04 при каждом апгрейде вылезает синий диалог needrestart — в скрипте он вешает установку намертво. Отключается один раз:
sudo sed -i "s/^#\$nrconf{restart} = 'i';/\$nrconf{restart} = 'a';/" /etc/needrestart/needrestart.conf
Сервисному пользователю не задавайте UID 1000: в облачных образах 24.04 он занят учёткой ubuntu, и useradd -u 1000 qdrant отвечает useradd: UID 1000 is not unique.
sudo useradd --system --shell /usr/sbin/nologin \
--home-dir /var/lib/qdrant --create-home qdrant
sudo mkdir -p /var/lib/qdrant/storage /var/lib/qdrant/snapshots /etc/qdrant
sudo chown -R qdrant:qdrant /var/lib/qdrant
sudo chmod 750 /var/lib/qdrant
Разделение каталогов не косметика: снапшот, занявший место рядом с данными, даёт Service internal error: No space left on device (os error 28). Запас смотрите заранее: df -h /var/lib.
Отдельно — лимит открытых файлов. Qdrant режет коллекцию на сегменты и отображает их файлы через mmap, так что счёт дескрипторов идёт на тысячи. Дефолтные 1024 однажды дают Too many open files (os error 24), и лечится это строкой LimitNOFILE=65536 в юните (для контейнера — секцией ulimits).
И безопасность — до первого запуска, а не после. По умолчанию Qdrant слушает 0.0.0.0 и не требует авторизации. Открытый наружу 6333 — это база, из которой любой выкачивает ваши эмбеддинги, а curl -X DELETE http://ваш-ip:6333/collections/docs сносит коллекцию без подтверждений и корзины.
sudo ufw allow OpenSSH
sudo ufw enable
sudo ufw status numbered
Порт 6333 сюда не добавляйте: наружу Qdrant выходит через прокси с TLS, а серверу приложений выдаётся правило sudo ufw allow from 203.0.113.10 to any port 6333 proto tcp.
Развернуть за пару минут
Готовый образ на VPS MAATRIX: NVMe, AMD EPYC, root-доступ. Локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Развернуть QdrantСпособ 1: бинарник из релиза и systemd-юнит
Меньше слоёв и понятные логи в journalctl. Забираем архив под glibc:
VER=$(curl -s https://api.github.com/repos/qdrant/qdrant/releases/latest | jq -r .tag_name)
sudo mkdir -p /opt/qdrant
curl -sL -o /tmp/qdrant.tar.gz \
"https://github.com/qdrant/qdrant/releases/download/${VER}/qdrant-x86_64-unknown-linux-gnu.tar.gz"
sudo tar -xzf /tmp/qdrant.tar.gz -C /opt/qdrant
sudo /opt/qdrant/qdrant --version
Рядом лежит статический вариант -musl — он нужен для переезда на старый дистрибутив; для Ubuntu 24.04 берите -gnu.
Дальше конфиг и главная ловушка бинарной установки. Qdrant ищет каталог config/ относительно рабочего каталога процесса, а storage_path и snapshots_path по умолчанию тоже относительные. Без WorkingDirectory systemd стартует процесс из /, и Qdrant создаёт /storage в корне файловой системы, считая это нормой. Лечится абсолютными путями и явным --config-path в /etc/qdrant/config.yaml:
log_level: INFO
telemetry_disabled: true
storage:
storage_path: /var/lib/qdrant/storage
snapshots_path: /var/lib/qdrant/snapshots
on_disk_payload: true
service:
host: 127.0.0.1
http_port: 6333
grpc_port: 6334
enable_cors: false
Ключ в этот файл не кладите: подстановку ${VAR} Qdrant в YAML не выполняет, строка уедет в конфиг дословно. Работает переопределение через окружение — параметр задаётся переменной QDRANT__ с двойным подчёркиванием вместо вложенности: QDRANT__SERVICE__API_KEY.
printf 'QDRANT__SERVICE__API_KEY=%s\n' "$(openssl rand -hex 32)" \
| sudo tee /etc/qdrant/qdrant.env > /dev/null
sudo chown root:qdrant /etc/qdrant/qdrant.env && sudo chmod 640 /etc/qdrant/qdrant.env
Юнит /etc/systemd/system/qdrant.service:
[Unit]
Description=Qdrant vector database
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=qdrant
Group=qdrant
WorkingDirectory=/var/lib/qdrant
EnvironmentFile=/etc/qdrant/qdrant.env
ExecStart=/opt/qdrant/qdrant --config-path /etc/qdrant/config.yaml
Restart=always
RestartSec=5
LimitNOFILE=65536
NoNewPrivileges=true
PrivateTmp=true
ProtectHome=true
ProtectSystem=strict
ReadWritePaths=/var/lib/qdrant
[Install]
WantedBy=multi-user.target
ProtectSystem=strict монтирует всё только на чтение, поэтому ReadWritePaths=/var/lib/qdrant обязателен: забудете строку — сервис ляжет с Permission denied (os error 13).
sudo systemctl daemon-reload
sudo systemctl enable --now qdrant
journalctl -u qdrant -n 40 --no-pager
Успешный старт — ASCII-баннер и строки:
Version: 1.15.1, build: a1b2c3d
Access web UI at http://localhost:6333/dashboard
INFO qdrant: Qdrant HTTP listening on 6333
INFO actix_server::builder: starting 8 workers
INFO qdrant::actix: TLS disabled for REST API
INFO qdrant::tonic: Qdrant gRPC listening on 6334
Честное ограничение: в tar-архиве только исполняемый файл, статики дашборда там нет. API работает, а /dashboard отвечает 404 — это не поломка, а комплектация: веб-интерфейс докачивается отдельным архивом с той же страницы релиза и подключается через service.static_content_dir.
Способ 2: Docker Compose и ловушка с ufw
Контейнер удобнее версионированием, и дашборд уже внутри образа. Пакет docker.io из noble отстаёт от актуального Engine, поэтому подключаем официальный репозиторий — с кодовым именем noble, а не jammy:
. /etc/os-release && echo "$VERSION_CODENAME" # должно быть noble
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
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] \
https://download.docker.com/linux/ubuntu noble stable" \
| sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update && sudo apt -y install docker-ce docker-ce-cli containerd.io docker-compose-plugin
docker compose version
Команда именно docker compose, через пробел: Compose v1 из noble вырезан. Файл /opt/qdrant-docker/compose.yaml:
services:
qdrant:
image: qdrant/qdrant:v1.15.1
container_name: qdrant
restart: unless-stopped
ports:
- "127.0.0.1:6333:6333"
- "127.0.0.1:6334:6334"
environment:
QDRANT__SERVICE__API_KEY: ${QDRANT_API_KEY}
QDRANT__TELEMETRY_DISABLED: "true"
QDRANT__LOG_LEVEL: INFO
volumes:
- /var/lib/qdrant/storage:/qdrant/storage
- /var/lib/qdrant/snapshots:/qdrant/snapshots
ulimits:
nofile: 65536
Три решения здесь приняты намеренно.
- Публикация на
127.0.0.1. Docker пишет правила DNAT в цепочкуDOCKERтаблицы nat, и она обрабатывается раньше ufw:sudo ufw deny 6333не закроет порт, опубликованный как-p 6333:6333. Вы будете смотреть наufw statusс чувством выполненного долга, пока база отвечает всему интернету. Проверка —sudo iptables -t nat -L DOCKER -n. - Тег версии вместо
latest. Формат хранилища мигрирует вперёд при старте новой версии, обратной миграции нет: сlatestлюбой перезапуск может незаметно обновить движок, и вернуться на прежний тег уже не выйдет. - Монтирование в каталоги
/var/lib/qdrant. Именованный том тоже работает, ноdocker compose down -vсносит его вместе с коллекциями.
cd /opt/qdrant-docker
printf 'QDRANT_API_KEY=%s\n' "$(openssl rand -hex 32)" > .env && chmod 600 .env
docker compose up -d && docker compose logs --tail=30 qdrant
Последний нюанс — права на тома. Стандартный образ работает от root; переключитесь на тег -unprivileged или user: "1000:1000" — каталог на хосте нужно отдать этому же UID, иначе контейнер падает с Permission denied (os error 13) при создании storage/collections.
Первая коллекция, API-ключ и клиент на Python 3.12
Проверяем, что сервис жив — корневой эндпоинт отдаёт версию, /healthz годится для мониторинга.
curl -s http://127.0.0.1:6333 | jq
# {"title":"qdrant - vector search engine","version":"1.15.1","commit":"a1b2c3d"}
curl -s http://127.0.0.1:6333/healthz
Теперь проверьте, что ключ включился: запрос без заголовка обязан получить 401 с телом {"status":{"error":"Must provide an API key or an Authorization bearer token"},"time":0.0}. Пришёл список коллекций — переменная не долетела до процесса; смотрите окружение PID, а не своей сессии: sudo tr '\0' '\n' < /proc/$(systemctl show -p MainPID --value qdrant)/environ | grep QDRANT.
Создаём коллекцию. Размерность берётся из модели эмбеддингов: 384 у all-MiniLM-L6-v2, 768 у bge-base, 1536 у text-embedding-3-small.
export QDRANT_API_KEY=$(sudo grep -oP '(?<=API_KEY=).*' /etc/qdrant/qdrant.env)
curl -s -X PUT http://127.0.0.1:6333/collections/docs \
-H "api-key: $QDRANT_API_KEY" -H 'Content-Type: application/json' \
-d '{"vectors":{"size":384,"distance":"Cosine"}}' | jq
# {"result":true,"status":"ok","time":0.02}
curl -s -X PUT "http://127.0.0.1:6333/collections/docs/points?wait=true" \
-H "api-key: $QDRANT_API_KEY" -H 'Content-Type: application/json' \
-d '{"points":[{"id":1,"vector":[0.05,0.11,0.02],"payload":{"url":"/faq"}}]}' | jq
Здесь ждёт самая частая ошибка старта — несовпадение размерности: коллекция создана под 384, а приложение считает эмбеддинги моделью OpenAI на 1536.
{"status":{"error":"Wrong input: Vector dimension error: expected dim: 384, got 1536"},"time":0.0}
Честно о последствиях: размерность существующей коллекции изменить нельзя. Никакого ALTER тут нет — коллекцию удаляют, создают заново с правильным size и переиндексируют весь корпус, поэтому модель эмбеддингов выбирают до первой загрузки. Второй по частоте ответ — 404 с текстом Not found: Collection 'docs' doesn't exist! (Qdrant обрамляет имя обратными кавычками).
Клиент на Python — место, где noble бьёт по рукам сильнее всего. Системный pip install qdrant-client завершается так:
error: externally-managed-environment
× This environment is externally managed
╰─> To install Python packages system-wide, try apt install
python3-xyz, where xyz is the package you want to install.
Это PEP 668, и на боевом сервере его не обходят флагом --break-system-packages: так ломаются системные утилиты Ubuntu на том же Python 3.12. Путь — виртуальное окружение, причём пакет python3-venv в noble отдельный.
sudo apt -y install python3-venv
python3 -m venv /opt/qdrant-client && source /opt/qdrant-client/bin/activate
pip install qdrant-client
Версию библиотеки держите рядом с версией сервера: при разрыве в лог падает «Qdrant client version is incompatible with server version». А включая prefer_grpc=True, убедитесь, что порт 6334 опубликован, — иначе вместо ошибки будет таймаут.
Домен, HTTPS, снапшоты и обновления
Qdrant слушает localhost, наружу его выводит nginx. И тут особенность 24.04: в noble лежит nginx 1.24.0, а директива http2 on; появилась только в 1.25.1 — свежий конфиг из интернета даст nginx: [emerg] unknown directive "http2". Пишется старый синтаксис:
server {
listen 443 ssl http2;
server_name qdrant.example.com;
ssl_certificate /etc/letsencrypt/live/qdrant.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/qdrant.example.com/privkey.pem;
client_max_body_size 64m;
proxy_read_timeout 300s;
location / {
proxy_pass http://127.0.0.1:6333;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
client_max_body_size поднят не случайно: батч из тысячи векторов по 768 измерений — это мегабайты JSON, и на дефолтном лимите в 1 МБ загрузка встанет с 413 Request Entity Too Large. Сертификат — обычным sudo certbot --nginx -d qdrant.example.com. gRPC через этот блок не проксируется: ему нужен отдельный слушатель с grpc_pass grpc://127.0.0.1:6334; и HTTP/2.
Бэкапы делаются снапшотами, а не копированием каталога на живой базе:
curl -s -X POST -H "api-key: $QDRANT_API_KEY" \
http://127.0.0.1:6333/collections/docs/snapshots | jq
ls -lh /var/lib/qdrant/snapshots/docs/
Честное ограничение: снапшот не инкрементальный — каждый раз это полная копия коллекции, поэтому диск планируйте с двойным запасом и ставьте задачу в ночное окно через cron. Восстановление — загрузка файла на /collections/{name}/snapshots/upload, слепок всего хранилища — POST /snapshots.
Обновление одинаково для обоих способов: снять снапшот, остановить сервис, поменять версию, запустить, проверить /collections. Через минорные версии идите по порядку, а не прыгайте с 1.9 сразу на 1.15 — миграции формата рассчитаны на последовательное применение. И повторю про откат: его нет. На мониторинг повесьте /healthz и /metrics — метрики в формате Prometheus, включая число точек, сегментов и статус индексации; что делать, когда индексация не поспевает за загрузкой, разобрано в материале про частые ошибки Qdrant.
Какой сервер под Qdrant брать в MAATRIX
Сам движок скромен: пустой Qdrant занимает сотни мегабайт и почти не грузит процессор — считать нужно коллекцию. В документации есть прямая формула оценки памяти под векторы: количество векторов × размерность × 4 байта × 1,5, где множитель закрывает граф HNSW и служебные структуры.
| Коллекция | Модель эмбеддингов | Память под векторы | Конфигурация |
|---|---|---|---|
| 100 тыс. × 384 | all-MiniLM-L6-v2 | ~0,23 ГБ | 2 vCPU / 4 ГБ / 40 ГБ NVMe |
| 1 млн × 384 | all-MiniLM-L6-v2 | ~2,3 ГБ | 4 vCPU / 8 ГБ / 80 ГБ NVMe |
| 1 млн × 768 | bge-base, e5-base | ~4,6 ГБ | 4 vCPU / 16 ГБ / 160 ГБ NVMe |
| 5 млн × 1536 | text-embedding-3-small | ~46 ГБ | 8 vCPU / 64 ГБ или квантование |
Это расчёт по формуле, а не замер: потребление зависит ещё от payload и доли сегментов на диске.
Честный минимум — 2 vCPU, 4 ГБ RAM, 40 ГБ NVMe. Хватает на базу знаний до сотен тысяч фрагментов с моделью на 384 измерения. На 1 vCPU и 1–2 ГБ Qdrant запустится, но первая же массовая загрузка с построением HNSW-индекса — самая прожорливая операция за всю жизнь базы — кончится процессом, снятым по OOM: в journalctl -k | grep -i oom будет Killed process ... (qdrant), а коллекция останется недоиндексированной.
Комфортный вариант — 4 vCPU, 8–16 ГБ RAM, 80–160 ГБ NVMe. Миллион векторов на 768 измерений, переиндексация без остановки поиска, место под рост. Диск считайте с коэффициентом 2,5–3 к объёму векторов: там же payload, журнал операций и копия коллекции в момент снапшота. Упираетесь в память — квантование int8 сжимает векторы вчетверо ценой небольшой потери точности, а hnsw_config.on_disk: true оставляет граф на диске; расчёт по моделям — отдельный разговор. GPU базе не нужен: он пригодится разве что при вычислении эмбеддингов, да и там не обязателен.
Локация — Лондон (UK). Qdrant почти никогда не стоит один: рядом модель эмбеддингов, тянущая веса с huggingface.co, и оркестрация RAG. С британской площадки всё это качается напрямую, до Европы пинг в десятки миллисекунд, плюс периметр GDPR. Завязан конвейер на OpenAI или Anthropic — логичнее США (Нью-Йорк); лежат персональные данные россиян — площадка в России закрывает 152-ФЗ.
Повторять всё руками не обязательно: Qdrant есть в каталоге приложений apps.maatrix.io. Он ставится автоматически при заказе сервера, работает на Ubuntu и Debian, а доступы — адрес и ключи — появляются в личном кабинете, в разделе «Доступ». Инструкция выше остаётся картой: вы знаете, где лежит хранилище, чем задан ключ и что чинить. Оплата — картами российских банков, по СБП, криптовалютой или токеном MAAT.
Развернуть за пару минут
Готовый образ на VPS MAATRIX: NVMe, AMD EPYC, root-доступ. Локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Развернуть QdrantОбсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →Частые вопросы
Можно ли поставить Qdrant через apt install qdrant?
Нет: пакета в репозиториях 24.04 нет, apt-репозитория проект не публикует, .deb в релизах тоже отсутствует. Вариантов два — tar-архив с GitHub плюс свой systemd-юнит либо контейнер qdrant/qdrant.
/dashboard отдаёт 404, хотя API отвечает. Что сломалось?
Ничего: в tar-архиве релиза только исполняемый файл, статики веб-интерфейса нет. Докачайте архив с UI и укажите путь в service.static_content_dir — или берите Docker, там дашборд внутри образа.
Я закрыл 6333 через ufw, но Qdrant доступен снаружи. Почему?
Контейнер опубликован как -p 6333:6333, а правила Docker в таблице nat срабатывают раньше ufw. Смените публикацию на 127.0.0.1:6333:6333 и проверьте sudo iptables -t nat -L DOCKER -n.
Нужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.