NetBox 3.6 в 4.x: откуда users_user does not exist
АйТи Фреш
Linux, Docker и DevOps

Почему после переноса базы NetBox 3.6 сразу в 4.x возникает relation users_user does not exist

Автор: , директор ООО «АйТи-Фреш» · · ~17 мин чтения
Перенос базы NetBox с версии 3.6 сразу на 4.x с пропуском промежуточной ветки 3.7 приводит к ошибке
Мажорную версию NetBox нельзя перепрыгивать — только через последний релиз предыдущей ветки.

Восстановили бэкап NetBox 3.6 на новом сервере с уже установленным 4.x — и первый же запрос падает с relation "users_user" does not exist. Причина не в повреждённом дампе: мажорные апгрейды NetBox нельзя перепрыгивать, а 3.6 → 4.x без промежуточной ветки 3.7 — ровно такой прыжок. Показываю правильный порядок и что делать, если ошибка уже словлена.

Что означает ошибка relation "users_user" does not exist

Сценарий, с которым сталкивались клиенты уже дважды: разворачиваем свежий сервер, ставим актуальный NetBox 4.x, накатываем pg_dump со старого сервера на 3.6 — и вместо рабочего интерфейса получаем 500-ю с текстом вида relation "users_user" does not exist LINE 1: ...ser"."is_active", "users_user"."date_joined" FROM "users_use.... Ровно такой текст ошибки разбирали в обсуждении #16060 на GitHub NetBox: пользователь восстановил дамп с 3.6 в свежую установку 4.0 и получил тот же результат.

Дело не в дампе и не в правах на таблицу. В NetBox 4.0 появились собственные модели User и Group вместо стандартных моделей Django (изменение #12795 в release notes 4.0) — отсюда и таблица users_user, которой в базе 3.6 просто нет. Код 4.0 обращается к ней сразу, в том числе на странице входа, а переход к новой структуре рассчитан на базу, прошедшую миграции ветки 3.7. Документация прямо объясняет, зачем нужен промежуточный шаг: при смене мажорной версии миграции схемы консолидируются, и новый код умеет продолжать только с того места, где закончила последняя минорная ветка предыдущей линейки. База, которая никогда не «видела» код 3.7, оказывается вне этой цепочки — и NetBox 4.x работает с ней в предположении, что путь миграций пройден полностью, хотя по факту структура на несколько шагов позади.

Тот же принцип последовательного применения миграций схемы актуален не только для NetBox, но для любой Django/ORM-системы, где структура базы жёстко привязана к версии кода — с этим мы регулярно сталкиваемся и в проектах внедрения NetBox. Пропуск промежуточного шага почти никогда не работает по накатанной, и NetBox не исключение.

relation "users_user" does not exist в NetBox почти всегда значит одно: базу перенесли через мажорную версию, минуя последний минорный релиз предыдущей ветки.

Почему мажорную версию NetBox нельзя перепрыгивать

Официальная документация формулирует правило дословно: NetBox можно обновлять сразу на любой более новый релиз без промежуточных шагов, за одним исключением — переход на следующую мажорную версию возможен только с последнего минорного релиза текущей мажорной ветки. Пример из документации: NetBox 2.11.8 можно обновить сразу до 3.3.2, а вот развёртывание 2.10.10 или более раннее сначала нужно довести до любого релиза 2.11, и только потом переходить на 3.x.

Для перехода 3.x → 4.x это означает: последняя минорная ветка третьей линейки — 3.7, и именно на неё нужно попасть перед 4.0 и выше. Причём подходит любой релиз в пределах 3.7.x, документация не требует непременно самого свежего патча — но я всегда беру самый свежий доступный (это 3.7.8 — именно её советовали в обсуждении #16060), потому что в патчах ветки чаще всего закрыты как раз баги миграций схемы.

Важный нюанс: если ваша база вообще старше 3.6 — например, всё ещё на 2.x — правило действует рекурсивно. Сначала до последнего релиза 2.x, потом до 3.7.x, и только потом до нужной вам версии 4.x или актуальной 4.7.x (последний стабильный релиз на 23.09.2026 — 4.7.1). Пропустить промежуточные мажорные ветки нельзя, даже если кажется, что «дамп же нормально открывается». Похожий принцип поэтапного перехода без пропуска ступеней я закладываю и в проекты перехода с Astra Linux и РЕД ОС — резкий скачок через несколько версий почти всегда обходится дороже, чем несколько спокойных шагов.

Схема правильного пути апгрейда NetBox с 3.6 до 4.x через промежуточную ветку 3.7
Прямой прыжок с 3.6 на 4.x даёт relation users_user does not exist — обязателен промежуточный шаг через 3.7.

Что технически меняется между 3.7 и 4.0 — и почему это важно не только для схемы БД

Кроме миграций схемы базы, между 3.7 и 4.x меняются требования к окружению, и здесь важно смотреть на целевую версию, а не на «4.0 вообще». NetBox 3.7 работает на Python 3.8–3.11 и PostgreSQL от 12. NetBox 4.0 и 4.1 требуют Python 3.10–3.12, PostgreSQL по-прежнему от 12. Дальше планка растёт: 4.2 требует PostgreSQL 13+, 4.3 — 14+, с 4.5 нужен Python 3.12–3.14, а актуальная 4.7 требует PostgreSQL 15 или новее и Redis 6.0+ — её upgrade.sh просто прервётся на более старой СУБД. Так что если цель — сразу 4.7.1, апгрейд PostgreSQL и Python почти наверняка входит в план. На venv-установке со старым Python (3.8 или 3.9) при переходе на 4.x сначала поднимаю интерпретатор, иначе upgrade.sh не соберёт зависимости.

Второе изменение — расположение плагинских ресурсов. В 3.7 все Python-ресурсы плагинов перенесли из extras.plugins в netbox.plugins, а начиная с 4.0 поддержка импорта по старому пути полностью убрана. Если у вас установлены сторонние плагины NetBox, при переходе на 4.x стоит заранее свериться с их README на предмет актуальной версии под 4.x — без этого плагин может просто не загрузиться после апгрейда, и вы получите отдельную ошибку импорта поверх уже решённой проблемы со схемой.

Для установок на Docker те же принципы действуют иначе технически, но не по сути: переход через мажорную границу означает последовательный запуск сначала образа NetBox 3.7.x (чтобы применились миграции), а потом уже образа нужной версии 4.x. Учтите совместимость самого netbox-docker: релиз 2.8.0 рассчитан на NetBox 3.7.x, а начиная с 2.9.0 проект поддерживает только NetBox 4.0 и новее, так что для промежуточного инстанса берите compose-файлы ветки 2.8.x. Для NetBox 4.7 нужен уже netbox-docker 5.1.x — со своим переходом на PostgreSQL 18.

Правильный порядок миграции 3.6 → 4.x без ошибок

Есть два рабочих варианта, оба опираются на рекомендацию из обсуждения #16060: сначала довести схему до состояния 3.7, потом уже переходить на 4.x. Первый — апгрейд на месте, на исходном сервере, до переноса на новую машину. Для venv-установки это штатный upgrade.sh из релиза 3.7.8: скачиваете архив, разворачиваете, копируете configuration.py, local_requirements.txt, а также media, пользовательские scripts и reports (если есть) от текущей установки, запускаете скрипт от root — он пересоберёт виртуальное окружение, применит миграции и соберёт статику.

NEWVER=3.7.8
wget https://github.com/netbox-community/netbox/archive/v$NEWVER.tar.gz
sudo tar -xzf v$NEWVER.tar.gz -C /opt
sudo ln -sfn /opt/netbox-$NEWVER/ /opt/netbox
sudo cp /opt/netbox-3.6.*/local_requirements.txt /opt/netbox/
sudo cp /opt/netbox-3.6.*/netbox/netbox/configuration.py /opt/netbox/netbox/netbox/
cd /opt/netbox
sudo ./upgrade.sh
sudo systemctl restart netbox netbox-rq

После того как 3.7.8 поднялась и работает штатно, снимаете дамп именно с неё (а не со старой 3.6) и уже его переносите на новый сервер с установленным 4.x. Второй вариант — временный контейнер: если под рукой нет возможности апгрейдить исходную инсталляцию, поднимаете отдельный контейнер или venv-инстанс NetBox 3.7.x, накатываете туда дамп с 3.6, даёте ему применить миграции при старте, снимаете свежий дамп уже после этого — и только этот дамп грузите в целевую установку 4.x.

# временный инстанс 3.7.x: сначала поднимаем только базу
docker compose up -d postgres
# восстанавливаем в неё дамп 3.6
gunzip -c netbox36_dump.sql.gz | docker compose exec -T postgres sh -c 'psql -U $POSTGRES_USER $POSTGRES_DB'
# NetBox 3.7.x применит миграции схемы при старте контейнера
docker compose up -d
# затем — новый дамп уже из этого инстанса, он идёт в целевую установку 4.x
docker compose exec -T postgres sh -c 'pg_dump -cU $POSTGRES_USER $POSTGRES_DB' | gzip > netbox37_dump.sql.gz

В обоих случаях ключевая мысль одна: миграции схемы должен прогнать сам NetBox нужной промежуточной версии, а не вы вручную SQL-запросами. Ручное «долепить» недостающие таблицы через CREATE TABLE users_user (...) я категорически не рекомендую — структура таблицы завязана на модели Django, индексы, constraints и связанные таблицы (permissions, group membership), и воспроизвести это руками без ошибок практически нереально.

Сравнение двух способов довести базу NetBox до версии 3.7 перед переходом на 4.x
Оба варианта ведут к одному: NetBox 3.7.x сам должен прогнать миграции, прежде чем снимать финальный дамп.

Что делать, если ошибка уже возникла

Если 4.0 (или любая версия 4.x) уже запущена поверх дампа 3.6 и упала с этой ошибкой — не пытайтесь чинить текущую базу руками. Самый надёжный путь: остановить контейнер/сервис NetBox, полностью снести базу данных этой установки (DROP DATABASE netbox; либо удалить том базы для Docker — в netbox-docker это netbox-postgres-data с префиксом проекта compose), и повторить перенос по правильной цепочке из раздела выше, начиная с исходного дампа 3.6.

Если исходной базы 3.6 под рукой уже нет и есть только тот самый повреждённый на середине пути инстанс 4.x — ситуация хуже, но не безнадёжна: смотрите, применились ли миграции хотя бы частично (python3 manage.py showmigrations в контексте установленного NetBox покажет, какие миграции отмечены как применённые). Иногда можно докатить недостающие миграции вручную командой manage.py migrate, но я делаю это только как крайний случай и только после полного бэкапа текущего состояния — если что-то пойдёт не так, откатываться будет некуда.

В моей практике почти всегда быстрее и безопаснее восстановиться из исходного дампа 3.6 по правильной цепочке, чем чинить наполовину смигрированную 4.x-базу. Это буквально час-полтора работы против непредсказуемого времени на разбор частично применённых миграций. Тот же принцип я применяю и при подготовке тестовой копии базы 1С перед обновлением релиза: прогонять миграцию сначала на копии, а не экспериментировать сразу на боевых данных.

Восстановление по правильной цепочке из исходного дампа 3.6 почти всегда быстрее, чем разбор частично смигрированной базы 4.x.
Цифры кейса ПерсоналКонсалт: перенос базы NetBox с версии 3.6 на 4.x через промежуточную 3.7.8
Промежуточный шаг через 3.7 занял 4 минуты — а сэкономил часы на разборе битой базы.

Кейс: «ПерсоналКонсалт», 43 рабочих места — миграция с трёхлетней инсталляции 3.6

У кадрового консалтинга «ПерсоналКонсалт» (43 рабочих места) NetBox стоял с 2023 года и с тех пор ни разу не обновлялся — типичная ситуация для системы, которая «просто работает» и её не трогают. Когда клиент решил перенести инфраструктуру на новый сервер и заодно поставить актуальную версию, их инженер развернул свежий NetBox 4.x из netbox-docker, накатил pg_dump со старого сервера и сразу получил relation "users_user" does not exist. Решили, что дамп битый, сняли ещё раз — та же ошибка.

Когда подключились мы, первым делом посмотрели версию исходной установки — оказалась 3.6.4, три года без обновлений. Подняли временный контейнер netbox-docker с образом 3.7.8, восстановили в него исходный дамп 3.6, дали контейнеру запуститься и применить миграции — заняло около четырёх минут на их объёме данных (порядка 1200 устройств, 3400 IP-адресов). Проверили, что интерфейс 3.7 открывается и данные на месте, сняли новый дамп уже с этого инстанса.

Этот дамп загрузили в целевую установку 4.x — поднялась без единой ошибки с первого раза. Дополнительно проверили два установленных у клиента плагина: один оказался не обновлён под 4.x и использовал старый путь extras.plugins — заменили на актуальную версию с GitHub. Полный перенос с учётом проверки плагинов занял чуть больше двух часов, из которых собственно промежуточный апгрейд схемы — меньше десяти минут.

После этого случая мы завели клиенту простое правило: NetBox теперь обновляется не реже раза в год, небольшими минорными шагами, а не «раз в три года одним рывком через две мажорные версии».

Что я теперь проверяю перед любым апгрейдом NetBox по умолчанию

Первое — версия источника и версия цели, и явная проверка: не пересекает ли путь между ними границу мажорной версии. Если пересекает — сразу планирую промежуточный шаг, а не надеюсь, что «наверное, само смигрируется». Документация NetBox формулирует это правило однозначно, и оно не менялось на всём протяжении версий 2.x–4.x.

Второе — регулярность. Инсталляция, которую обновляют раз в квартал минорными релизами, почти никогда не упирается в проблему мажорного перепрыгивания: к моменту следующей мажорной версии она и так стоит на последнем миноре предыдущей ветки. Проблема возникает именно там, где систему годами не трогали.

Третье — перед любым переносом на новый сервер с одновременным апгрейдом версии я разделяю эти два действия: сначала довожу версию до нужной точки на исходном сервере (или в промежуточном контейнере), потом переношу дамп уже финальной версии на новое железо. Совмещать «перенос на новый сервер» и «прыжок через две мажорные версии» в одной операции — то, что почти гарантированно даёт именно эту ошибку. Аналогичная логика «не пропускать промежуточный шаг» стоит и за апгрейдом Veeam с Windows на Linux-апплаенс перед версией 13.1 — там пропуск подготовительного этапа тоже закрывает путь назад.

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

Можно ли обновить NetBox сразу с 3.6 на актуальный 4.7.1, минуя все промежуточные релизы 4.x?

Промежуточные релизы внутри одной мажорной ветки пропускать можно — правило касается только перехода между мажорными версиями. Единственный обязательный промежуточный шаг для 3.6 — любой релиз ветки 3.7 (я беру 3.7.8), после него можно идти сразу на 4.7.1, но учтите: 4.7 требует PostgreSQL 15+ и Python 3.12+.

Что означает точный текст ошибки relation "users_user" does not exist?

PostgreSQL сообщает, что таблицы users_user нет в базе. Она появилась в NetBox 4.0 вместе с собственной моделью User вместо стандартной модели Django, а база 3.6 не прошла цепочку миграций через 3.7, на которую рассчитан переход.

Достаточно ли просто установить пакет NetBox 3.7, не подключая к нему базу?

Нет. Миграции должен реально применить NetBox 3.7.x к этой базе: в venv-установке это делает upgrade.sh (manage.py migrate), в netbox-docker — контейнер при старте. Только после этого снимайте новый дамп.

У нас установлены сторонние плагины NetBox — на что обратить внимание при переходе 3.x → 4.x?

Проверьте, обновлён ли плагин под 4.x: ресурсы Python перенесены из extras.plugins в netbox.plugins в 3.7, а с 4.0 старый путь импорта не поддерживается вовсе. Устаревший плагин просто не загрузится.

Нужно ли отдельно обновлять PostgreSQL при переходе с 3.7 на 4.x?

Для 4.0–4.1 нет — им хватает PostgreSQL 12. Но 4.2 требует 13+, 4.3 — 14+, а актуальная 4.7 — PostgreSQL 15 или новее, и её upgrade.sh прервётся на старой СУБД.

А если у нас NetBox ещё старше — например, 2.x?

Правило рекурсивное: сначала довести до последнего релиза 2.x, затем до 3.7.x, и только потом переходить на 4.x. Пропускать любую из этих границ нельзя по той же причине — рассинхрон миграций схемы.

Столкнулись с похожей задачей? Обращайтесь — решим

Если у вас происходит что-то из описанного в этой статье — или любая другая проблема с ИТ-инфраструктурой, — обращайтесь в любое время. Мои специалисты и я лично разберём ситуацию, найдём настоящую причину и доведём до решения.

Возьмёмся и за разовую задачу, и за постоянное обслуживание. Первичная консультация — бесплатно и без обязательств.

📞 +7 903 729-62-41 ✈ Telegram @ITfresh_Boss

С уважением, Семёнов Евгений Сергеевич, директор «АйТи Фреш» — IT-аутсорсинг для компаний до 50 рабочих мест, 15+ лет практики

Источники

© ООО «АйТи-Фреш» · Москва · Все статьи