MAATRIX / Блог / NodeBB на сервере: частые ошибки и решения

NodeBB на сервере: частые ошибки и решения

MAATRIX

NodeBB — форум на Node.js, который держит реалтайм-уведомления, чат и обновление ленты через WebSocket, а не через перезагрузку страницы. Именно эта особенность и рождает большинство проблем на сервере: обычная nginx-конфигурация, которая отлично работает для сайта на PHP, глушит WebSocket у NodeBB и ломает realtime. Ниже — разбор ошибок, с которыми чаще всего сталкиваются при установке и эксплуатации: занятый порт, сломанная сборка после апгрейда, обрыв соединений за прокси, отказ базы данных и падения процесса под нагрузкой.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →

Порт уже занят: EADDRINUSE

При старте ./nodebb start в логе может появиться:

Error: listen EADDRINUSE: address already in use :::4567

Это значит, что порт, на котором должен слушать NodeBB (по умолчанию 4567), уже занят другим процессом — часто предыдущим экземпляром NodeBB, который не завершился корректно. Проверьте, что реально слушает порт:

sudo ss -ltnp | grep 4567

Если там уже висит node-процесс — остановите форум штатно, а не через kill -9:

./nodebb stop
./nodebb start

Если ./nodebb stop не помогает (процесс завис), найдите PID из вывода ss и завершите его через kill, затем убедитесь, что в каталоге NodeBB не осталось файла pidfile со старым идентификатором — иначе следующий старт снова может решить, что процесс уже запущен, и повести себя непредсказуемо. Второй частый вариант — порт 4567 действительно занят другим сервисом (например, вы разворачиваете второй форум на том же сервере). Тогда меняют порт в config.json (поле port) и сверяют, что тот же порт указан в конфиге nginx, который проксирует запросы на NodeBB.

После git pull или upgrade форум не стартует

Частая ситуация: обновили код через git pull или ./nodebb upgrade, перезапустили — и получили Error: Cannot find module или форум отдаёт старые шаблоны и битые стили. NodeBB не пересобирает клиентские ассеты и не подтягивает новые npm-зависимости автоматически при простом git pull — это отдельный шаг.

Правильная последовательность после обновления кода плагина, темы или самого ядра:

cd /путь/к/nodebb
./nodebb stop
git pull
./nodebb upgrade
./nodebb start

Команда ./nodebb upgrade сама выполняет npm install для актуализации зависимостей, прогоняет миграции схемы базы данных и пересобирает ассеты (JS-бандлы, LESS/SCSS в CSS, минификацию). Если ошибка Cannot find module вылезла после ручного редактирования package.json или после переноса каталога на другой сервер без копирования node_modules, помогает точечный npm install в корне NodeBB перед ./nodebb build.

Отдельно стоит ./nodebb build — если после установки нового плагина или темы страница выглядит так, будто изменения не применились, почти всегда дело в том, что сборка не запускалась заново. Пересоберите ассеты и перезапустите:

./nodebb build
./nodebb start

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Реалтайм не работает за nginx: обрывается WebSocket

Это самая специфичная для NodeBB проблема, и типовой конфиг nginx для реверс-прокси её не решает. NodeBB держит соединение с браузером через socket.io: уведомления, счётчик непрочитанных, чат и live-обновление постов идут именно по нему. Если проксирующий сервер не пробрасывает заголовки апгрейда протокола, socket.io откатывается на long polling или вовсе рвётся, а в консоли браузера видно постоянные переподключения и задержки в интерфейсе.

Минимальный рабочий блок nginx для NodeBB:

server {
    listen 443 ssl http2;
    server_name forum.example.com;

    location / {
        proxy_pass http://127.0.0.1:4567;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_read_timeout 60s;
    }
}

Ключевые строки — proxy_http_version 1.1 и пара Upgrade/Connection "upgrade": без них nginx не даст протоколу переключиться с HTTP на WebSocket, и браузер получит обычный HTTP-ответ там, где ждал апгрейд. Второй момент — proxy_read_timeout. Значение по умолчанию у nginx рассчитано на короткие HTTP-запросы, а WebSocket-соединение живёт долго; если таймаут слишком мал, простаивающие вкладки будут переподключаться каждые несколько секунд, что выглядит как «форум лагает». Общий подход к настройке реверс-прокси и типовые грабли разобраны в статье про nginx как реверс-прокси — те же принципы применимы и здесь, только с обязательным условием апгрейда протокола.

Проверить, что WebSocket реально держится, можно во вкладке Network инструментов разработчика браузера — там должно быть активное соединение с кодом ответа 101 Switching Protocols, а не бесконечная серия коротких XHR-запросов к /socket.io/.

Ошибка подключения к базе данных

NodeBB хранит данные в MongoDB, Redis или PostgreSQL — какую базу выбрали при установке, та и указана в config.json. Если база недоступна, при старте появляется что-то вроде:

Error: connect ECONNREFUSED 127.0.0.1:27017

или для Redis:

Redis connection to 127.0.0.1:6379 failed: connect ECONNREFUSED

Сначала проверьте, что служба базы вообще запущена:

sudo systemctl status mongod
sudo systemctl status redis-server

Если служба не активна — смотрите её собственный журнал (journalctl -u mongod -n 50), причина падения обычно там. Если служба работает, но подключение всё равно отклоняется — сверьте адрес и порт в config.json с тем, где реально слушает база: sudo ss -ltnp | grep 27017 или grep 6379. Отдельная категория ошибок — база и NodeBB на разных серверах: тогда добавляется проверка фаервола между машинами и параметра bind у самой базы, которая по умолчанию слушает только 127.0.0.1 и не примет внешнее подключение без явной настройки. Подробный разбор типичных ошибок каждой базы — в статьях про MongoDB на сервере и Redis на сервере: там про авторизацию, лимиты памяти и потерю данных при рестарте — те же принципы актуальны и для базы под NodeBB.

Если логин и пароль в config.json не совпадают с реальными учётными данными базы (например, поменяли пароль напрямую в MongoDB, забыв обновить конфиг NodeBB), получите ошибку авторизации, а не ECONNREFUSED — их легко перепутать по формулировке, но лечатся они по-разному: одна про сеть, вторая про доступ.

Сессии слетают или пропадает вход после переезда на HTTPS

Если форум работает без реалтайма (WebSocket проброшен верно), но пользователи то и дело вылетают из аккаунта, а на попытке войти получают ошибку CSRF-токена — почти всегда причина в несовпадении поля url в config.json с тем адресом, по которому реально открывают форум. NodeBB строит куки сессии и проверки CSRF, отталкиваясь именно от этого значения, включая протокол (http или https) — расхождение даже в одном символе схемы способно сломать сохранение сессии.

Проверить и поправить значение можно через ./nodebb setup в интерактивном режиме, либо прямой правкой config.json с последующим перезапуском:

./nodebb stop
# отредактировать "url": "https://forum.example.com" в config.json
./nodebb build
./nodebb start

Второй частый сценарий — форум переехал за nginx с завершением SSL на прокси (сам Node-процесс продолжает слушать по обычному HTTP на 127.0.0.1). Если прокси не передаёт заголовок X-Forwarded-Proto, NodeBB может решить, что соединение небезопасное, и вести себя с cookie сессии не так, как ожидается на HTTPS-домене — строка proxy_set_header X-Forwarded-Proto $scheme; из конфига выше как раз закрывает эту проблему. После любой правки url или структуры прокси обязательно пересобирайте ассеты (./nodebb build) — часть конфигурации, включая базовый адрес, встраивается в собранные клиентские файлы.

Сборка зависает или падает — нехватка памяти

./nodebb build компилирует и минифицирует JS-бандлы, LESS/SCSS в CSS и собирает шаблоны — процесс заметно прожорливее по памяти, чем обычная работа форума. На VPS с 1 ГБ RAM и без свопа сборка нередко просто обрывается без внятной ошибки в логе NodeBB, а в dmesg находится запись про OOM killer, убивший node-процесс:

dmesg | tail -30

Если видите там Out of memory: Killed process рядом с node — дело именно в нехватке памяти на момент сборки, а не в поломке кода. Быстрый обходной путь — временный своп-файл на время сборки:

sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
./nodebb build

Своп спасает разово, но постоянная работа форума со свопом вместо оперативной памяти — это уже симптом того, что серверу тесно. Для форума с активным сообществом, где сборка проходит регулярно при апдейтах тем и плагинов, разумнее сразу закладывать 2 ГБ RAM и больше, а не бороться с OOM при каждом обновлении. В MAATRIX можно арендовать VPS в России, США или Великобритании с нужным объёмом памяти под NodeBB и перенести форум без спешки — оплата картой РФ, по СБП, криптовалютой или токеном MAAT, без привязки к иностранной карте.

Процесс NodeBB падает и не поднимается сам

./nodebb start запускает форум в фоне и пишет вывод в logs/output.log, но сам по себе не перезапускает процесс после падения или перезагрузки сервера — это просто демонизация, а не менеджер отказоустойчивости. Если после креша форум просто лежит, пока кто-то не зайдёт и не наберёт ./nodebb start руками, нужен внешний супервизор.

Проще всего — systemd-юнит, который перезапускает NodeBB при падении и поднимает его после ребута сервера:

[Unit]
Description=NodeBB forum
After=network.target mongod.service

[Service]
Type=simple
User=nodebb
WorkingDirectory=/home/nodebb/nodebb
ExecStart=/usr/bin/node loader.js
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target

После sudo systemctl daemon-reload и sudo systemctl enable --now nodebb форум станет управляемой службой: systemctl status nodebb покажет состояние, а journalctl -u nodebb -f — живой лог вместо ручного чтения logs/output.log. Обратите внимание на After=mongod.service (или redis-server.service, смотря какая у вас база) — без этой строки systemd может попытаться запустить NodeBB раньше, чем поднимется база данных, и получить те самые ошибки ECONNREFUSED из раздела выше уже на этапе загрузки сервера.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.

Частые вопросы

Почему после обновления темы или плагина ничего не изменилось на сайте?

Нужно пересобрать ассеты: ./nodebb build, затем ./nodebb start. Простой перезапуск без сборки не подхватывает новые стили и шаблоны.

Почему отваливаются уведомления и чат, хотя сайт открывается?

Реверс-прокси не пробрасывает WebSocket. Добавьте в nginx proxy_http_version 1.1, proxy_set_header Upgrade $http_upgrade; и proxy_set_header Connection "upgrade";, увеличьте proxy_read_timeout.

NodeBB пишет ECONNREFUSED к базе — с чего начать?

Проверьте, запущена ли служба базы (systemctl status mongod или redis-server), затем сверьте адрес, порт и пароль в config.json с реальными параметрами базы.

Пользователи постоянно вылетают из аккаунта после перехода на HTTPS?

Проверьте поле url в config.json — оно должно точно совпадать с адресом сайта, включая схему https. После правки пересоберите ассеты командой ./nodebb build.

Можно ли просто перезапустить NodeBB командой kill -9, если он завис?

Лучше избегать: сначала пробуйте ./nodebb stop, а kill -9 использовать как крайний случай, потом проверяя, не остался ли устаревший pidfile, мешающий следующему старту.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →