Почему после переноса базы NetBox 3.6 сразу в 4.x возникает relation users_user does not exist
Восстановили бэкап 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 не исключение.
- Ошибка означает рассинхрон между кодом NetBox (4.x) и фактической структурой базы (3.6).
- Причина — пропущенный промежуточный шаг через ветку 3.7; в 4.0 появилась собственная модель User с таблицей users_user.
- Дамп и права на таблицу тут не при чём: проблема в порядке применения миграций Django.
Почему мажорную версию 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 и РЕД ОС — резкий скачок через несколько версий почти всегда обходится дороже, чем несколько спокойных шагов.
- Правило: прыжок через мажорную версию — только с последнего минорного релиза предыдущей ветки.
- Для 3.x → 4.x обязательный промежуточный шаг — ветка 3.7 (любой релиз, я беру 3.7.8).
- Правило рекурсивное: с 2.x сначала на последний 2.x, потом на 3.7.x, потом на 4.x.
- Текущий стабильный релиз на 23.09.2026 — NetBox 4.7.1.
Что технически меняется между 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.
- NetBox 3.7: Python 3.8–3.11, PostgreSQL от 12.
- NetBox 4.0–4.1: Python 3.10–3.12, PostgreSQL от 12.
- NetBox 4.7: Python 3.12–3.14, PostgreSQL от 15, Redis от 6.0.
- Плагинские ресурсы: extras.plugins → netbox.plugins (в 3.7), старый путь не работает с 4.0.
- На Docker — контейнер 3.7.x (netbox-docker 2.8.x) перед контейнером нужной версии 4.x.
Правильный порядок миграции 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), и воспроизвести это руками без ошибок практически нереально.
- Шаг 1: довести исходную базу до состояния 3.7.x (апгрейд на месте или временный инстанс).
- Шаг 2: снять дамп именно с работающей 3.7.x, не со старой 3.6.
- Шаг 3: этот дамп — и только его — загрузить в целевую установку 4.x.
- Ручные SQL-правки таблиц вместо миграций Django — не вариант.
Что делать, если ошибка уже возникла
Если 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С перед обновлением релиза: прогонять миграцию сначала на копии, а не экспериментировать сразу на боевых данных.
- Не чинить руками — снести базу целевой установки и повторить перенос правильно.
- `manage.py showmigrations` — посмотреть, что реально применилось, если исходного дампа больше нет.
- Докатывание миграций вручную — только как крайняя мера, после полного бэкапа текущего состояния.
Кейс: «ПерсоналКонсалт», 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 3.6.4, без обновлений три года.
- Промежуточный контейнер 3.7.8: восстановление дампа + прогон миграций — около 4 минут (1200 устройств, 3400 IP).
- Целевая установка 4.x поднялась с первого раза после дампа с 3.7.8.
- Один из двух плагинов требовал обновления под путь netbox.plugins.
- Полный перенос — чуть больше 2 часов, из них апгрейд схемы — меньше 10 минут.
Что я теперь проверяю перед любым апгрейдом 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. Пропускать любую из этих границ нельзя по той же причине — рассинхрон миграций схемы.
Источники
- NetBox Documentation — Upgrading to a New NetBox Release — Правило перехода через мажорную версию только с последнего минорного релиза предыдущей ветки, пример 2.11.8→3.3.2 vs 2.10.10: https://netboxlabs.com/docs/netbox/en/stable/installation/upgrading/
- GitHub — netbox-community/netbox Discussion #16060 — Точный текст ошибки relation "users_user" does not exist после переноса дампа 3.6 в 4.0, рекомендация апгрейда через 3.7.8 и вариант с временным контейнером: https://github.com/netbox-community/netbox/discussions/16060
- NetBox Labs Docs — Migrating Your Plugin to NetBox v4.0 — Перенос плагинских ресурсов из extras.plugins в netbox.plugins в 3.7 и удаление поддержки старого пути в 4.0: https://netboxlabs.com/docs/netbox/v4.4/plugins/development/migration-v4/
- NetBox Documentation — Upgrading, таблица Version History — Минимальные версии по веткам: 3.7 — Python 3.8–3.11/PostgreSQL 12; 4.0–4.1 — Python 3.10–3.12/PostgreSQL 12; 4.7 — Python 3.12–3.14/PostgreSQL 15/Redis 6.0: https://netboxlabs.com/docs/netbox/installation/upgrading/
- NetBox Labs — NetBox v4.7.1 (актуальный стабильный релиз) — Проверена дата и номер актуального стабильного релиза NetBox на 23.09.2026: https://github.com/netbox-community/netbox/releases
- NetBox v4.0 release notes — #12795 — собственные модели User и Group вместо стандартных Django; #14092 — удалена совместимость импорта из extras.plugins: https://github.com/netbox-community/netbox/blob/main/docs/release-notes/version-4.0.md



