Что проверить в PostgreSQL перед апгрейдом NetBox 4.7 и почему обновлению нужно длинное окно простоя
Если вы планируете обновить NetBox до 4.7 тем же коротким окном, что и обычно, — не планируйте: релиз требует PostgreSQL 15 и расширение ltree, а миграция, которая заменяет django-mptt на ltree, держит блокировку ACCESS EXCLUSIVE на иерархических таблицах и не откатывается по-настоящему. Разбираю, что проверить в PostgreSQL заранее, чтобы обновление не встало посреди рабочего дня.
Что именно меняется в 4.7 и почему это не рядовой минорный апгрейд
NetBox 4.7.0 вышел 2 сентября 2026 года, и в списке breaking changes есть два пункта, которые касаются напрямую PostgreSQL, а не только кода приложения. Первый: «PostgreSQL 14 is no longer supported. NetBox now requires PostgreSQL 15 or later: The upgrade script will abort when connected to an earlier release». Это отличие от предыдущего релиза — в 4.6 то же самое несоответствие версии просто выводило предупреждение, апгрейд с PostgreSQL 14 хоть и не рекомендовался, но проходил. В 4.7 скрипт обновления прерывается сразу, если база на 14-й версии или старше.
Второй пункт — совсем новое требование, которое в документации по обновлению сформулировано так: «NetBox v4.7 and later require the PostgreSQL ltree extension». Это модуль иерархических данных из стандартного набора contrib-модулей PostgreSQL, который должен быть включён в конкретной базе данных. В пакетах Debian/Ubuntu он входит в основной пакет сервера, а на RHEL-подобных системах с пакетами PGDG живёт в отдельном postgresqlNN-contrib — если его нет, CREATE EXTENSION упадёт с ошибкой об отсутствии control-файла. До 4.7 NetBox хранил иерархии (регионы, группы сайтов, локации, роли устройств и ещё несколько моделей) через django-mptt — стороннюю Python-библиотеку. В 4.7 это заменено на нативный тип PostgreSQL ltree, и без включённого расширения миграция просто не сможет создать нужные колонки. Подготовку базы под такие релизы я обычно закладываю заранее в план внедрения NetBox — версия СУБД и её расширения реже всего попадают в чек-лист, который сам администратор составляет по памяти.
Третье, менее заметное в заголовках, но не менее важное изменение — минимальная версия Redis поднята до 6.0, релиз 5.x больше не поддерживается. Если вы годами не трогали инфраструктуру вокруг NetBox (сам PostgreSQL, Redis), апгрейд до 4.7 — тот случай, когда обновление приложения тянет за собой ревизию всего стека, а не только pip install новой версии кода.
Расширение ltree: что это и кто должен его включить
ltree — доверенный (trusted) модуль PostgreSQL для хранения и запроса иерархических меток вида 1.2.3. Он входит в стандартную поставку PostgreSQL и, будучи модулем trusted, не требует прав суперпользователя для активации — это прямо отмечено в предупреждении релиз-нот: «This trusted module ships with PostgreSQL and does not require superuser permission to activate». Формально включить его может обычный владелец базы данных, если у него есть привилегия CREATE на этой базе.
NetBox постарается сделать это сам: «NetBox will install it automatically during the upgrade if it is not already present. This requires the NetBox database user to hold the CREATE privilege on the database». То есть в большинстве случаев ничего вручную делать не придётся — миграция сама выполнит CREATE EXTENSION ltree, если у пользователя, от имени которого подключается NetBox, есть на это право. Официальная документация по установке PostgreSQL для NetBox изначально делает пользователя NetBox владельцем базы данных, а владелец базы по умолчанию обладает правом CREATE — так что для инсталляций, разворачивавшихся по стандартной инструкции, отдельно ничего готовить не нужно.
Проблема возникает там, где базу разворачивали не по этой инструкции: например, DBA завёл отдельную учётную запись для NetBox без роли владельца, или база живёт в управляемом облачном PostgreSQL (RDS, Cloud SQL и аналоги), где владение базой и права на расширения разграничены отдельно от прав на данные. В этих сценариях апгрейд может упасть на этапе миграции с ошибкой прав, и разбираться с этим в разгар обслуживания — заведомо хуже, чем проверить права до начала работ. У меня похожая история с правами регулярно всплывает и на серверах 1С на Linux с PostgreSQL: роль базы отдельно от роли владельца — удобно с точки зрения ИБ, но требует отдельного шага перед любым апгрейдом, который меняет схему.
Как проверить и выдать право CREATE заранее
Официальная документация по обновлению отдельным разделом «Verify Database Permissions» описывает, что делать, если расширение не установлено, а прав недостаточно. Заходите в psql от системного пользователя postgres:
sudo -u postgres psqlи выполняете команду, подставив имя своей базы и пользователя NetBox:
GRANT CREATE ON DATABASE netbox TO netbox;После этого при следующем запуске миграций NetBox 4.7 сможет создать расширение самостоятельно.
Альтернативный путь — не давать NetBox это право вообще, а поставить расширение заранее силами администратора базы данных:
CREATE EXTENSION IF NOT EXISTS ltree;Эту команду выполняет пользователь с более широкими правами (например, суперпользователь или владелец базы), подключившись именно к базе NetBox (sudo -u postgres psql -d netbox) — расширение ставится в конкретную базу, а не на весь сервер. Один раз, заранее — до дня апгрейда. Я предпочитаю именно этот вариант для клиентов с управляемым PostgreSQL или строгой моделью прав: расширение появляется в базе спокойно, без спешки в окне обслуживания, и сама миграция NetBox уже просто находит его на месте и ничего не создаёт.
Проверить, установлено ли расширение уже сейчас, можно одной командой на самой базе:
SELECT extname, extversion FROM pg_extension WHERE extname = 'ltree';Если запрос вернул строку — расширение уже активно, и этот пункт подготовки можно вычеркнуть. Если пусто — самое время решить, кто и когда выдаёт право CREATE или ставит расширение вручную, до, а не во время апгрейда.
Почему миграция держит блокировку и сколько это реально длится
В релиз-нотах этому посвящено отдельное предупреждение «Extended Upgrade Duration», и формулировка там жёсткая: «Two steps in this upgrade scale with the size of the database, and may take considerably longer than a typical NetBox upgrade». Первый шаг — сама замена django-mptt на ltree: миграция добавляет и изменяет колонки на каждой иерархической таблице, а затем заполняет таблицу одним оператором («adds and alters columns on each hierarchical table before backfilling it in a single statement»). Изменение схемы держит блокировку ACCESS EXCLUSIVE, которая блокирует не только запись, но и чтение на затронутых таблицах на всё время своей работы; последующий backfill блокирует уже конкретные строки, которые обновляет, до своего коммита. Оценка в релиз-нотах — «on a large deployment this can last several minutes»: минуты, а не часы, но именно на крупной базе.
Список моделей, которые это затрагивает, в релиз-нотах прямой (с пометкой «etc.» для групп): Region, SiteGroup, Location, DeviceRole, Platform, TenantGroup, ContactGroup, WirelessLANGroup, а также ModuleBay, InventoryItem и InventoryItemTemplate. Если у вас скромная база — десятки регионов, сотни локаций — миграция пройдёт незаметно. Если счёт идёт на многие тысячи объектов инвентаря (InventoryItem — обычно самая объёмная из этого списка модель, туда попадают все компоненты внутри устройств), блокировка на чтение всей таблицы на несколько минут — это уже ощутимый простой для любого сервиса, который читает NetBox через API в реальном времени (генераторы конфигов, дашборды, интеграции с системами мониторинга).
Второй шаг — отдельная команда rebuild_config_context_cache, которая исполняется прямо в скрипте апгрейда и делает по одному UPDATE на каждое устройство и каждую виртуальную машину в базе. У инфраструктуры с несколькими тысячами устройств это тысячи отдельных операций записи — не одна тяжёлая транзакция, как в случае с ltree, но по совокупному времени тоже заметно длиннее, чем обычные миграции NetBox, к которым все привыкли за прошлые релизы. Хорошая новость из тех же релиз-нот: команда пропускает объекты с уже заполненным кешем, её безопасно прервать и перезапустить, а при нехватке окна — отложить до момента, когда NetBox уже снова в строю (объект с пустым кешем просто рендерит config context на лету). Похожий эффект «много мелких операций дают долгий общий апгрейд» я разбирал на примере обновления конфигураций 1С без аварий — регламент там тоже строится вокруг оценки реального объёма данных, а не вокруг привычной длительности из прошлого раза.
Необратимость: почему «просто откатить» не сработает
Последняя строка предупреждения в релиз-нотах особенно важна для планирования: «these migrations are not reversible in practice: Reversing them restores the MPTT columns but does not repopulate them». Формально команда отката существует — Django-миграции всегда можно откатить командой migrate на более раннюю ревизию, и технически колонки lft, rght, tree_id, level, которые использовал django-mptt, снова появятся в схеме. Но данные в них никто не восстановит: обратная миграция создаёт пустые колонки, а не пересчитывает дерево заново.
На практике это означает, что после успешного перехода на ltree откат версии NetBox назад — это не «нажать одну кнопку», а фактически восстановление базы данных из бэкапа, снятого до апгрейда. Официальная документация по обновлению отдельным предупреждением требует бэкап перед любым апгрейдом: «Always be sure to save a backup of your current NetBox deployment prior to starting the upgrade process» — это общая рекомендация для любой версии, но для перехода на 4.7 она перестаёт быть формальностью и становится единственным реальным планом отхода, если что-то пойдёт не так в процессе или сразу после обновления. Тот же принцип «бэкап — это не формальность, а единственный реальный план Б» я закладываю в любую стратегию резервного копирования баз, которую строю клиентам, независимо от конкретной СУБД под капотом.
Отдельно стоит учитывать, что level — поле, которое раньше можно было использовать в фильтрах и order_by() при работе с иерархией через API или скрипты — после миграции остаётся доступным только как Python-свойство и больше не участвует в запросах к базе. Туда же — методы MPTT, которые NetBox не перенёс: реализация на ltree покрывает только get_ancestors(), get_descendants(), get_children() и add_related_count(), а get_root(), get_family(), is_leaf_node(), move_to() и insert_at() больше недоступны. Если у вас есть кастомные скрипты, репорты, плагины или интеграции, которые сортируют или фильтруют объекты по level или зовут эти методы, они перестанут работать именно в момент этого апгрейда — стоит поискать такие места в коде заранее, а не находить постфактум по упавшей интеграции.
Чек-лист подготовки к окну обслуживания
Порядок действий, который я использую при подготовке клиентов к переходу на 4.7. Сначала — оценка объёма: количество строк в таблицах Region, Location, DeviceRole, Platform и особенно InventoryItem (обычно самая большая), чтобы понять, о каких минутах блокировки реально идёт речь именно на вашей базе, а не полагаться на общую формулировку «may take considerably longer». Затем — версии зависимостей: SELECT version(); в psql на предмет PostgreSQL 15+, и версия Redis-сервера — обе должны быть подняты заранее, отдельным этапом, ещё до попытки апгрейда самого NetBox.
Дальше — права и расширение: проверка pg_extension на ltree, и если его нет — либо выдача GRANT CREATE, либо ручная установка CREATE EXTENSION силами DBA, оба варианта разобраны выше. Отдельным пунктом — полный бэкап базы данных (pg_dump или снапшот тома, в зависимости от вашей инфраструктуры) прямо перед началом работ, и проверка, что все установленные плагины заявляют совместимость с 4.7 — документация по обновлению прямо требует свериться с этим перед апгрейдом любой версии. Ещё два пункта именно из 4.7: дать фоновым очередям RQ опустеть перед остановкой воркеров (вебхуки, поставленные в очередь старой версией, после рестарта упадут с TypeError), а если у вас SSO — проверить вход на тестовом стенде, потому что social-auth-app-django и social-auth-core обновлены до новых мажорных версий.
Последний пункт — коммуникация с командой, которая пользуется интеграциями поверх NetBox. Если у вас есть скрипты, дёргающие REST API или GraphQL в момент планового окна, предупредите их авторов: сама миграция держит ACCESS EXCLUSIVE на части таблиц, поэтому даже чтение через API в эти минуты будет получать таймауты, а не просто медленный ответ. Планируйте окно не на «пару минут по привычке», а на реалистичную оценку по объёму вашей базы плюс запас.
Кейс: инкубатор стартапов «Бизнес-трамплин», 21 рабочее место
У клиента NetBox используется два года для учёта сетевой инфраструктуры коворкинга — стойки, свитчи, точки доступа по этажам, плюс детальный инвентарь компонентов серверных стоек резидентов (карты расширения, диски, модули памяти заведены как InventoryItem, потому что оборудование резидентов меняется часто и клиенту важно видеть историю). За два года таблица InventoryItem накопила около 6 тысяч записей — немного по меркам крупного дата-центра, но заметно больше, чем в среднем малом офисе.
Перед обновлением до 4.7 мы сначала проверили версию PostgreSQL — на сервере клиента стояла 14-я ветка, унаследованная ещё с первоначальной установки NetBox 4.1 два года назад, апгрейды PostgreSQL параллельно с NetBox всё это время не делали. Пришлось сначала поднять PostgreSQL до 15-й ветки отдельным этапом (со своим планом бэкапа и проверкой совместимости), и только после этого — обновлять сам NetBox. Расширение ltree на новой версии PostgreSQL включили заранее вручную, командой CREATE EXTENSION IF NOT EXISTS ltree, от имени администратора базы, не полагаясь на автоматическое создание в момент миграции.
Окно под само обновление NetBox мы заложили в 40 минут — против обычных 5–10 минут для минорных апгрейдов у этого же клиента в прошлом — и заранее предупредили резидентов коворкинга о плановой недоступности панели самообслуживания, которая читает NetBox через API. Фактически на базе такого размера шаг django-mptt → ltree вместе с блокировкой занял меньше минуты, rebuild_config_context_cache по примерно 150 устройствам и ВМ — около минуты, а весь upgrade.sh с пересборкой виртуального окружения и collectstatic — около 12 минут; остальное время ушло на свежий pg_dump, проверку интерфейса и прогон интеграций. Запас оказался с избытком, и я считаю это правильным исходом: оценку надо делать по своей базе, а «several minutes» из релиз-нот — это про инсталляции с сотнями тысяч объектов, а не про 6 тысяч.
Частые вопросы
Обязательно ли поднимать PostgreSQL до 15 перед апгрейдом NetBox до 4.7?
Да, это жёсткое требование. Скрипт обновления NetBox 4.7 прерывается при подключении к PostgreSQL 14 или старше — в отличие от версии 4.6, которая только предупреждала. PostgreSQL нужно обновить отдельным этапом до апгрейда самого NetBox.
Нужно ли устанавливать расширение ltree вручную?
Не обязательно — NetBox создаст его сам во время миграции, если у пользователя базы есть право CREATE (при стандартной установке пользователь NetBox — владелец базы, и право уже есть). Если у вас управляемый PostgreSQL или строгая модель прав, надёжнее заранее выполнить CREATE EXTENSION IF NOT EXISTS ltree в базе NetBox силами администратора СУБД.
Сколько реально длится блокировка при миграции на ltree?
Зависит от объёма иерархических таблиц — прежде всего InventoryItem, Location, ModuleBay и похожих моделей. Релиз-ноты говорят о нескольких минутах на крупной инсталляции; на базе с ~6 тысячами InventoryItem этот шаг проходит меньше чем за минуту. Оценивайте по числу строк в своих таблицах и закладывайте запас.
Можно ли откатить NetBox с 4.7 назад после обновления?
Технически откат миграции восстанавливает старые колонки django-mptt, но данные в них не заполняются заново — по факту функциональность иерархии будет сломана. Единственный надёжный план отката — восстановление из бэкапа базы данных, снятого перед апгрейдом.
Что делать, если в моих скриптах есть сортировка по полю level?
После миграции на ltree поле level остаётся доступным только как Python-свойство и больше не работает в фильтрах или order_by() на уровне базы данных. Такие места в коде нужно найти и переписать до обновления, иначе они начнут падать сразу после апгрейда.
Требования по Redis тоже обязательны?
Да, NetBox 4.7 прекращает поддержку Redis 5.x и требует версию 6.0 или новее. Проверьте версию Redis вместе с PostgreSQL в рамках той же подготовки, до начала апгрейда.
Источники
- NetBox v4.7.0 Release Notes — Дата релиза 2026-09-02, требования PostgreSQL 15+/ltree/Redis 6.0+, предупреждение Extended Upgrade Duration, список затронутых моделей, необратимость миграции django-mptt → ltree: https://github.com/netbox-community/netbox/blob/v4.7.0/docs/release-notes/version-4.7.md
- NetBox Labs Docs — Upgrading to a New NetBox Release, раздел Verify Database Permissions — Раздел Verify Database Permissions (sudo -u postgres psql, GRANT CREATE ON DATABASE netbox TO netbox, CREATE EXTENSION IF NOT EXISTS ltree), таблица версий (4.7: PostgreSQL 15, Redis 6.0; 4.5/4.6: 14 и 5.0), требование бэкапа и проверки совместимости плагинов: https://github.com/netbox-community/netbox/blob/v4.7.0/docs/installation/upgrading.md
- GitHub netbox-community/netbox, issue #21418 — Replace django-mptt with Postgresql ltree — Мотивация замены (django-mptt не поддерживается), статус 'accepted for v4.7.0' с пометкой высокой сложности реализации: https://github.com/netbox-community/netbox/issues/21418
- PostgreSQL Documentation — ltree — Официальное описание модуля ltree как доверенного расширения ядра PostgreSQL для иерархических меток: https://www.postgresql.org/docs/current/ltree.html



