Как установить и настроить Firecrawl на VPS
Firecrawl превращает любую веб-страницу в чистый markdown для LLM-агентов и RAG, но облачный тариф считает каждый запрос кредитами, а бесплатная квота заканчивается быстрее, чем начинается проект. Установка Firecrawl на VPS даёт тот же движок в Docker Compose — без лимита запросов, но с собственным стеком из пяти контейнеров и своими заботами о ресурсах. Разберём путь от git clone до первого успешного скрейпа: точные команды, реальные ошибки и честная оценка того, сколько сервера стеку действительно нужно.
Содержание
- Что такое Firecrawl и зачем ставить его на свой сервер
- Требования к серверу: сколько ядер и памяти просит стек
- Установка Firecrawl: git clone, .env и docker compose up
- Проверка: health-check и первый запрос к API
- Грабли self-host: NUQ_RABBITMQ_URL, ZodError и pg_cron
- Прод-режим: домен, авторизация и обновления
- Какой сервер под Firecrawl брать в MAATRIX
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →Что такое Firecrawl и зачем ставить его на свой сервер
Firecrawl — открытый движок (лицензия AGPL-3.0) для превращения веб-страниц в данные, пригодные для LLM: вместо сырого HTML с меню, баннерами и вёрсткой он отдаёт чистый markdown, plain-текст или структурированный JSON. Проект вырос из Mendable AI, организация на GitHub переименована из mendableai в firecrawl — старые ссылки на github.com/mendableai/firecrawl ведут туда же.
У Firecrawl пять операций. /scrape забирает одну страницу. /map за секунды строит список всех ссылок сайта без скачивания контента — удобно сначала оценить объём. /crawl обходит сайт по ссылкам асинхронно и возвращает страницы пачками по мере готовности. /search ищет в вебе и по желанию скрейпит найденные результаты. /extract вытаскивает структурированные данные по JSON-схеме через LLM — нужен ключ OpenAI или совместимого провайдера.
Типичный потребитель Firecrawl — не человек, а другой сервис: RAG-пайплайн, агент в n8n, дёргающий API как HTTP-узел в сценарии, или MCP-клиент вроде Claude Desktop через официальный firecrawl-mcp-server. Поэтому установка на VPS обычно встаёт как часть более широкого AI-стека.
Главное отличие self-host от облака — не в функциях, а в двух вещах. Приятная: никаких кредитов за запрос, единственный счётчик — ресурсы сервера. Менее приятная: облако включает проприетарный слой обхода антибот-защиты (fire-engine) с ротацией прокси, а self-host по умолчанию ходит на сайты напрямую через обычный Playwright — ресурсы с Cloudflare ответят капчей или 403, и обходить это придётся своим прокси.
Требования к серверу: сколько ядер и памяти просит стек
Полный self-host стек Firecrawl — пять контейнеров: api, playwright-service, redis, rabbitmq, nuq-postgres. Есть опциональный foundationdb — альтернативный backend очереди вместо Postgres+RabbitMQ, но по умолчанию не нужен и для старта только усложняет картину.
| Контейнер | Образ / сборка | Порт наружу | Роль |
|---|---|---|---|
| api | build apps/api | 3002 | приём запросов, отдаёт результат |
| playwright-service | build apps/playwright-service-ts | только внутри сети | рендерит JS-страницы |
| redis | redis:alpine | только внутри сети | кэш и рейт-лимиты |
| rabbitmq | rabbitmq:3-management | только внутри сети | очередь задач между api и воркерами |
| nuq-postgres | build apps/nuq-postgres | только внутри сети | хранит очередь заданий и (опционально) авторизацию |
Официальный гайд честно пишет, что проверенный минимальный размер хоста для этого стека не публикуется. Но у самого docker-compose.yaml есть косвенная подсказка: он выставляет api лимит в 4 vCPU / 8 ГБ памяти, а playwright-service — 2 vCPU / 4 ГБ. Это потолок, а не гарантия работы с меньшим, но ориентир честнее случайной цифры из чужого блога.
Из требований — Docker Engine с плагином Compose v2, git, curl и свободный порт 3002. Работаем на Ubuntu 24.04 (Debian подходит без изменений). Порт 3002 в фаервол пока не открываем — решение откладываем до раздела про прод-режим:
apt update && apt upgrade -y
ufw allow 22/tcp && ufw enable
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверУстановка Firecrawl: git clone, .env и docker compose up
Ставим Docker официальным скриптом и проверяем плагин Compose:
curl -fsSL https://get.docker.com | sh
docker compose version
Клонируем репозиторий и фиксируемся на релизном теге, а не на ветке main — так вы не словите недокументированные изменения между релизами:
git clone https://github.com/firecrawl/firecrawl.git
cd firecrawl
git checkout v2.11.0 # актуальный тег смотрите на странице Releases репозитория
Ключевой момент — файл окружения. В корне репозитория нужен свой .env, который читает docker-compose.yaml — это не то же самое, что apps/api/.env.example внутри кода API, использовать его как готовый контракт для Compose не стоит. Минимальный рабочий .env без базы аутентификации:
cat > .env <<'EOF'
USE_DB_AUTHENTICATION=false
POSTGRES_USER=postgres
POSTGRES_PASSWORD=замените-на-32-случайных-символа
POSTGRES_DB=postgres
ALLOW_LOCAL_WEBHOOKS=false
BLOCK_MEDIA=false
EOF
false в последних двух строках написан явно, не оставлен пустым — пустая строка в булевом флаге роняет api при старте, разберём это в разделе про грабли. Пароль Postgres — реальная случайная строка от 32 символов, openssl rand -hex 24 подходит.
Запускаем стек и проверяем, что все контейнеры поднялись:
docker compose up --build -d
docker compose ps
Первая сборка занимает несколько минут — образ playwright-service тянет за собой Chromium. В выводе docker compose ps должно быть пять строк, причём у firecrawl-rabbitmq-1 и firecrawl-nuq-postgres-1 в статусе должно появиться (healthy) — у них есть health-check, и api начинает принимать трафик только после готовности RabbitMQ.
Проверка: health-check и первый запрос к API
Первым делом — liveness-проверка, она не требует авторизации и отвечает быстрее всего:
curl --max-time 5 http://localhost:3002/v0/health/readiness
Ответ {"status":"ok"} значит, что процесс поднялся и слушает порт. Дальше — реальный скрейп одной страницы:
curl -s -X POST http://localhost:3002/v1/scrape \
-H 'Content-Type: application/json' \
-d '{"url": "https://example.com", "formats": ["markdown"]}' | jq .
Ожидаемый ответ — JSON вида {"success": true, "data": {"markdown": "...", "metadata": {"statusCode": 200}}}. Заголовок Authorization не нужен: при USE_DB_AUTHENTICATION=false ключи не проверяются вовсе — вернёмся к этому в разделе про прод-режим. У свежих сборок рядом с /v1/scrape появился /v2/scrape с расширенным набором параметров, v1 продолжает работать.
Асинхронный обход сайта проверяется двумя запросами — сначала запускаем job, потом опрашиваем его статус:
JOB=$(curl -s -X POST http://localhost:3002/v1/crawl \
-H 'Content-Type: application/json' \
-d '{"url": "https://example.com", "limit": 5}' | jq -r .id)
curl -s http://localhost:3002/v1/crawl/$JOB | jq '{status, pages: (.data | length)}'
Сразу после запуска status будет scraping, затем completed, а pages — число забранных страниц. curl: (7) Failed to connect на первом же запросе значит, что api ещё не поднялся или не прошёл health-check зависимостей; смотрите docker compose logs -f api.
Грабли self-host: NUQ_RABBITMQ_URL, ZodError и pg_cron
Три ошибки, с которыми сталкивается почти каждый при первом запуске стека — все не про Firecrawl как продукт, а про конфигурацию контейнеров.
NUQ_RABBITMQ_URL is not configured. Контейнер api падает сразу при старте, если переменная подключения к очереди не собралась в валидный URL вида amqp://пользователь:пароль@rabbitmq:5672 — она должна ссылаться на те же RABBITMQ_USER/RABBITMQ_PASSWORD, что и сам RabbitMQ. Разошлись в одном месте и забыли синхронизировать в другом — получите эту строку в docker compose logs api.
ZodError на пустой булевой переменной. API парсит .env через схему валидации Zod, и пустая строка в поле, ожидающем true/false (типичные кандидаты — ALLOW_LOCAL_WEBHOOKS и BLOCK_MEDIA), — это не «пусто = false», а ошибка валидации, из-за которой api не стартует вовсе. Лечится как в разделе установки: писать литеральное значение, а не оставлять переменную без него.
pg_cron и exit code 3. Внутри nuq-postgres включено расширение pg_cron, а оно требует shared_preload_libraries=pg_cron и параметр cron.database_name с именем реальной базы. Разошлось с фактическим POSTGRES_DB — nuq-postgres завершается кодом выхода 3, а api следом падает с ошибкой очереди: симптом похож на проблему RabbitMQ, хотя корень в Postgres.
Отдельно — решение авторов, не баг: корневой docker-compose.yaml не объявляет постоянные тома для Postgres, Redis и RabbitMQ. Обычный docker compose down, а тем более down -v, стирает очередь и историю job'ов вместе с контейнерами. Для рабочего инструмента именованные тома и бэкапы базы — целиком ваша забота.
Последнее в разделе — не техническая деталь, а юридическая. AGPL-3.0 — лицензия с сетевым copyleft: меняете код и предлагаете изменённую версию как публичный сервис третьим лицам — обязаны открыть изменения. Для внутреннего использования на своём сервере это ограничение не касается.
Прод-режим: домен, авторизация и обновления
По умолчанию API Firecrawl слушает 0.0.0.0:3002 без авторизации — это прямо написано в документации по self-host. Держать порт открытым без защиты — плохая идея: любой в интернете сможет гонять через ваш сервер скрейпы и жечь ресурсы.
Два варианта. Для работы с того же сервера или через n8n/агента в той же docker-сети — не публиковать порт api наружу, держать ufw deny 3002/tcp и обращаться по 127.0.0.1:3002 или по имени контейнера в сети backend. Для доступа снаружи — реверс-прокси (Nginx или Caddy) с TLS перед портом, сам порт пробрасывать только на локальный адрес.
Включить настоящую авторизацию — не то же самое, что поменять флаг. USE_DB_AUTHENTICATION=true подключает выдачу API-ключей поверх Supabase: без SUPABASE_URL, SUPABASE_ANON_TOKEN, SUPABASE_SERVICE_TOKEN и миграции схемы флага недостаточно — «просто включить» не значит «получить рабочую авторизацию». Альтернатива — держать api за своим прокси с проверкой заголовка или ключа на уровне Nginx.
Отдельно защитите админку очереди: BULL_AUTH_KEY открывает панель Bull по адресу /admin/<ваш-ключ>/queues со всеми заданиями. Задайте случайную строку — без ключа UI не поднимется вовсе.
Обновление — это смена тега и пересборка:
git fetch --tags
git checkout v2.12.0
docker compose pull
docker compose up --build -d
Перед переходом на новый тег загляните в его docker-compose.yaml и заметки к релизу — список сервисов и переменных между версиями меняется, а слепой git pull на main регулярно ломает то, что вчера работало.
Стек стабилен — свяжите его с остальным AI-стеком на том же сервере: n8n с AI-агентами дёргает /v1/scrape как обычный HTTP-узел в сценарии, а markdown-результат удобно заливать в векторную базу для RAG или в рабочее пространство AnythingLLM, если он уже стоит рядом.
Какой сервер под Firecrawl брать в MAATRIX
Firecrawl в self-host — не одна программа, а пять контейнеров: очередь, база, кэш и Chromium под капотом Playwright. Экономить на памяти опаснее, чем кажется — не хватит RAM, и первым падёт не самый заметный контейнер, а Postgres или RabbitMQ, а разбираться придётся с непонятным exit code, а не с честным OOM в логах api.
| Вариант | Конфигурация | Для чего хватает |
|---|---|---|
| Минимум | 4 vCPU, 8 ГБ RAM, 40 ГБ NVMe | Личные обходы, тесты, несколько job'ов подряд — без запаса |
| Комфортный | 6–8 vCPU, 16 ГБ RAM, 80–100 ГБ NVMe | Параллельные crawl'ы, постоянные тома, бэкапы без тревоги за место |
Минимум подобран не произвольно — это потолок, который docker-compose.yaml резервирует под один контейнер api (4 vCPU / 8 ГБ). playwright-service и api формально делят те же четыре ядра, и при параллельных crawl'ах это чувствуется — первым делом стоит опустить NUM_WORKERS_PER_QUEUE с дефолтных 8 до 2–4. Комфортный вариант даёт обоим их лимиты одновременно (4+2 vCPU, 8+4 ГБ) и оставляет память под Redis, RabbitMQ, Postgres и ОС без свопа.
По локации логичнее всего Великобритания. Причина не в блокировках, а в маршруте скрейпов: львиная доля целевых сайтов — европейские и международные ресурсы, и лондонский узел даёт короткий пинг до них и меньше поводов заподозрить «нетипичную» геолокацию запроса. Та же логика для /extract с OPENAI_API_KEY — обращения к OpenAI с британского адреса идут без региональных сюрпризов, подробнее — в статье про прокси к OpenAI через сервер в Великобритании.
Firecrawl не входит в каталог apps.maatrix.io: сервер приходит чистой Ubuntu 24.04 или Debian, весь путь от git clone до docker compose up вы проходите сами. Зато в каталоге есть готовые сборки смежных вещей из того же AI-стека — n8n, Open WebUI, AnythingLLM ставятся при заказе без единой команды, а Firecrawl связываете с ними уже после, через API. Оформить сервер можно на странице аренды VPS: тариф и локация — на месте, оплата картой российского банка, по СБП, криптовалютой или токеном MAAT.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверОбсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →Частые вопросы
Нужен ли API-ключ, чтобы обращаться к self-hosted Firecrawl?
По умолчанию нет: при USE_DB_AUTHENTICATION=false запросы на порт 3002 идут без заголовка Authorization. Это нормально, пока порт закрыт файрволом; для настоящей авторизации нужен не только флаг true, но и подключённый Supabase (SUPABASE_URL, SUPABASE_ANON_TOKEN, SUPABASE_SERVICE_TOKEN).
Чем self-host хуже облачного Firecrawl?
Двумя вещами: нет антибот-слоя fire-engine с ротацией прокси (сайты за Cloudflare обходите своим PROXY_SERVER или ScrapingBee), и нет постоянных томов — без вашей настройки очередь и история job'ов не переживут docker compose down.
Сколько сервера реально нужно под self-host Firecrawl?
Официальный гайд не публикует минимум, но сам docker-compose.yaml ограничивает api 4 vCPU/8 ГБ, а playwright-service — 2 vCPU/4 ГБ. На практике 4 vCPU/8 ГБ — рабочий, но впритык минимум, 6–8 vCPU/16 ГБ — комфортный запас.
Нужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.