Апгрейд Zimbra 9 → 10: на месте или на новом сервере

В июне 2025 строительная компания из Балашихи, 40 рабочих мест, попросила поднять почту с девятки на десятку. Ожидание было такое: вечер работы, перезагрузка, утром все довольны. Я сначала с этим согласился — и это была моя ошибка, которую поймал тестовый клон. Рассказываю оба пути целиком: что даёт апгрейд на месте, какие мины он оставляет и по каким признакам я выбираю новую машину даже там, где это дороже по часам.

«Это же просто обновление» — откуда берётся ожидание одного вечера

Апгрейд почтового сервера в голове у заказчика выглядит как обновление телефона. Нажал, подождал, пользуешься дальше. Логика понятная, и спорить с ней в лоб бесполезно — надо показывать.

У этого ожидания есть источник. Внутри одной ветки обновления действительно проходят так: накатить патч на девятку — это полчаса и перезапуск служб. Люди делают это раз-другой, привыкают и переносят ощущение на смену мажорной версии. А смена мажорной — другое животное.

Второй источник — совет, который гуляет по форумам и который я считаю по-настоящему вредным: «попробуйте на месте, не получится — откатитесь». Откатиться нельзя. У инсталлятора нет обратного хода: он поднимает схему базы, переписывает конфигурацию, перекладывает данные. Единственная работающая точка отката — снимок машины, сделанный до первой команды. Если снимка нет, а апгрейд не задался, вы не откатываетесь, а восстанавливаетесь из бэкапа. Это другой процесс, другие часы и другие нервы.

Выбор между двумя путями определяется не версией, с которой вы идёте, и не той, на которую идёте. Он определяется состоянием сервера. Ниже — как я это состояние измеряю.

Июнь 2025, Балашиха: 40 мест, девятка и пять лет истории

Строительная компания: генподряд, свои прорабы, объекты по области. 40 рабочих мест — сметчики, снабжение, проектный отдел, бухгалтерия. Почта своя с 2020 года, ставил тогдашний системный администратор, который до сих пор работает и меня же и позвал. Хороший грамотный парень, просто ни разу не делал мажорный переход и не хотел учиться на боевом. В 2022-м он перевёз почту на новую виртуалку с Ubuntu 20.04 и поставил девятку начисто — это та самая запись INSTALL SESSION в истории ниже.

Фактура первого часа:

$ su - zimbra -c 'zmcontrol -v'
Release 9.0.0_GA_4259.UBUNTU20_64_20220721121515 UBUNTU20_64 FOSS edition, Patch 9.0.0_P32.

$ su - zimbra -c 'zmprov -l gaa' | wc -l
47
$ du -sh /opt/zimbra/store /opt/zimbra/index /opt/zimbra/db
528G	/opt/zimbra/store
31G	/opt/zimbra/index
12G	/opt/zimbra/db

$ id zimbra
uid=1001(zimbra) gid=1001(zimbra) groups=1001(zimbra)

$ tail -3 /opt/zimbra/.install_history
07/21/2022 12:15:51: INSTALL SESSION COMPLETE
11/09/2022 22:04:19: UPGRADE 9.0.0_GA_4259 -> 9.0.0_GA_4259
03/14/2023 01:37:55: UPGRADE 9.0.0_GA_4259 -> 9.0.0_GA_4259

Сорок семь ящиков, живых сорок. 528 гигабайт — стройка есть стройка: рабочая документация, фотоотчёты с объектов, сканы актов. Последняя запись в истории установок — март 2023 года: больше двух лет к серверу не подходили вообще, отсюда и патч-уровень P32. А дыра в postjournal закрывается патчем P41 и выше, то есть отставание было и по безопасности — во что это могло встать, посчитаю в конце.

Операционная система — Ubuntu 20.04. Формально десятка на неё встаёт. Но лично мне не хочется прожить на этой ОС ещё три года, и этот довод я на встрече озвучил как своё мнение, а не как факт.

И вот строка, из-за которой первый разговор пошёл вовсе не про «на месте или на новом». В выводе стоит FOSS edition — бесплатная редакция. А бесплатной десятки не существует. Zimbra 10, она же Daffodil, выпускается только как Network Edition: инсталлятор спрашивает лицензионный ключ и без него апгрейд не начинает, а на mailbox-сервере должна подняться отдельная служба лицензирования. Ключ — строка длиной в два-три десятка символов, она передаётся инсталлятору при запуске.

Я сказал это на первой встрече, до всякой сметы, потому что без ответа на этот вопрос дальше идти некуда. Развилка на столе выглядела так:

  • остаться на девятке, догнать патч-уровень до последнего и дожить на ней до конца её жизненного цикла — бесплатно, но с известным сроком;
  • купить лицензию и идти на десятку — работы плюс ежегодный платёж по числу ящиков, причём покупка российским юрлицом с 2022 года сама по себе процедура: договор, платёж и вопрос «а что будет через год при продлении»;
  • уйти на Carbonio CE и не платить вовсе — но это уже не апгрейд, а смена платформы, другой проект и другой разговор.

Выбрали второе, и по вполне конкретной причине: прорабам на объектах нужны были календарь и общая адресная книга на телефонах, а это ActiveSync, то есть коммерческая ветка в любом случае. Лицензию на 40 ящиков компания оплатила отдельным договором за три недели до начала работ. В мою смету она не входила, и в цифрах ниже её нет — держите это в голове, когда будете примерять мои суммы на свой бюджет: у вас к ним прибавится строка, которой на бесплатной девятке не было ни разу.

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

Тестовый клон и версия, которая не подтвердилась

Правило, от которого я не отступаю: мажорный апгрейд сначала проходит на клоне, потом на бою. Клон — это копия виртуалки, поднятая в изолированной сети с отключённым исходящим SMTP. Час работы, снимает большую часть сюрпризов. Клон я поднимал уже с купленным ключом: без него инсталлятор десятки не начинает работу даже в изолированной сети, так что схема «прорепетируем, а лицензию решим потом» тут не работает.

Моя версия была: сервер здоров, апгрейд на месте пройдёт за вечер, зовём людей на субботу и закрываем тему. Клон эту версию разобрал на части.

Сам подъём версии прошёл. Инсталлятор отработал, службы поднялись. А дальше начали вылезать вещи, которые на живом сервере не видны, потому что не мешают.

# на клоне, после подъёма версии
$ su - zimbra -c 'zmvolume -l'
   Volume id: 1
         name: message1
 path: /opt/zimbra/store

   Volume id: 2
         name: index1
 path: /opt/zimbra/index

   Volume id: 4
         name: arch2021
 path: /mnt/old-arch/store

   Volume id: 5
         name: msg-tmp
 path: /mnt/store2/store

$ ls /mnt/old-arch/store
ls: невозможно получить доступ к '/mnt/old-arch/store': Нет такого файла или каталога

$ cat /opt/zimbra/log/mailbox.log* | grep -c 'Possibly corrupt index'
1184

$ ls /opt/zimbra/zimlets-deployed/ | wc -l
39

Разбираю по строкам. Том с идентификатором 4 указывал на каталог, которого нет: в 2021 году архив выносили на отдельный диск, потом диск сняли, а запись в списке томов осталась. Том 5 создали и не заполнили. Оба переехали на десятку в целости, потому что апгрейд на месте не задаёт вопросов — он переносит конфигурацию как есть.

1184 упоминания повреждённого индекса в логах — это не про десятку, это накопленное за пять лет. Апгрейд их не лечит и не замечает.

Тридцать девять развёрнутых зимлетов при том, что штатных в поставке заметно меньше. Часть ставили руками в 2020–2021 годах, авторы половины из них с тех пор пропали. На десятке два из них не запустились и молча писали в лог исключение при каждом открытии веб-клиента.

Вот тут моя первоначальная версия и умерла. Сервер был не здоров — он был бессимптомен. Разница принципиальная.

Что апгрейд на месте тащит за собой

Список того, что переезжает вперёд без вопросов. Проверяйте по нему свой сервер, он короткий.

  • Записи о томах, включая указывающие на несуществующие пути. Пока никто не пробует туда писать — тишина. Когда пробует — ошибки доступа к письмам;
  • Повреждённые индексы ящиков. Поиск у пользователя не находит писем, которые точно есть. Лечится переиндексацией, но её надо назначить, а апгрейд об этом не сообщит;
  • Зимлеты, поставленные руками. Совместимость с новой версией никто не гарантировал, а отвалившийся зимлет часто выглядит как «веб-почта стала тормозить»;
  • Правки конфигурации, сделанные напрямую в сгенерированных файлах. Их затирает при перегенерации из шаблонов, и вы узнаёте об этом не сразу;
  • Учётки, которые давно пора было удалить — уволенные, тестовые, забытые общие ящики. Каждая занимает место и остаётся точкой входа;
  • Локальные настройки, накрученные предыдущим админом без документации. После апгрейда часть из них применяется иначе, и разбираться приходится по факту сбоя.

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

Считается это просто. Я закладываю по два часа на каждый нетривиальный унаследованный объект — мёртвый том, чужой зимлет, ручную правку конфигурации. Если сумма перевалила за двадцать часов, дешевле собрать новую машину и перенести только данные.

У строителей сумма получилась двадцать шесть.

Проверьте у себя за две минуты

Шесть команд. Они не меняют ничего и выполняются на живом сервере в рабочее время.

su - zimbra -c 'zmcontrol -v'
su - zimbra -c 'zmvolume -l'
su - zimbra -c 'zmprov -l gaa' | wc -l
ls /opt/zimbra/zimlets-deployed/ | wc -l
cat /opt/zimbra/log/mailbox.log* | grep -c 'Possibly corrupt index'
id zimbra; tail -5 /opt/zimbra/.install_history

Складывайте баллы по таблице:

Что видитеТянет к апгрейду на местеТянет к новому серверу
Список томовОдин-два штатных тома, все пути существуютТри и больше, есть пути в никуда
ЗимлетыТолько штатные из поставкиДесятки, происхождение части неизвестно
Записи о повреждённых индексахЕдиницы или нольСотни и тысячи
История установкиРовная цепочка апгрейдовПропуски, ручные вмешательства, чужие следы
Операционная системаСвежая, входит в поддерживаемые для целевой версииНа исходе поддержки или уже вне её
Кто вёл серверТот же человек, он на местеСменилось двое, документации нет

Три и больше отметок в правой колонке — берите новую машину. Не потому, что на месте не получится: потому что разбор наследия съест разницу в часах и добавит риск в самое неудачное время, ночью и под окном простоя.

Ещё одна строка в этот счёт не входит, потому что она не про «на месте или на новом», а про то, состоится ли проект вообще. Посмотрите в выводе zmcontrol -v, что стоит перед словом edition. Если FOSS — прибавьте к любой из двух смет лицензию Network Edition: на десятку без ключа не пускает инсталлятор, а не администратор, и платёж этот годовой. Если NETWORK — проверьте срок действия и заранее выясните, кто и как будет продлевать.

Отдельно про id zimbra. Эту строчку запишите прямо сейчас, куда-нибудь в заметку. Она понадобится, и объясню в разделе про мои грабли, почему.

Как я делаю апгрейд на месте, когда он оправдан

Оправдан он часто — примерно в половине случаев. Порядок такой.

  1. Снимок виртуальной машины. До всего. Это единственная точка отката, других нет;
  2. Догнать исходную версию до последнего доступного патча. Инсталлятор новой мажорной ветки капризен к состоянию исходной системы, и подъём с актуального патч-уровня проходит заметно спокойнее;
  3. Проверить свободное место. Мало места — установка падает на середине, и это худший из возможных моментов;
  4. Остановить службы командой zmcontrol stop и убедиться, что они действительно остановились, а не сделали вид;
  5. Запустить инсталлятор новой версии из распакованного дистрибутива, передав ему лицензионный ключ. Он определит установленную систему и предложит обновление — соглашаемся. Без ключа он до этого вопроса не дойдёт;
  6. Дождаться до конца, не трогая консоль. Всё длинное — в screen;
  7. Поднять службы, проверить статус, проверить историю установки и заодно убедиться, что служба лицензирования запустилась вместе со всеми.
# перед стартом
$ df -h /opt
$ su - zimbra -c '/opt/zimbra/bin/zmcontrol stop'
$ su - zimbra -c 'zmcontrol status'

# сам апгрейд — обязательно в screen
# screen -S zcs-upgrade
# ./install.sh --licensekey <ключ Network Edition>

# после
$ su - zimbra -c 'zmcontrol status'
$ su - zimbra -c 'zmcontrol -v'
$ tail -3 /opt/zimbra/.install_history
$ su - zimbra -c 'zmprov gs $(zmhostname) zimbraServiceEnabled'

Про screen без иронии. Обрыв сессии посреди длинной операции над данными способен оставить базу в несогласованном состоянии, и это не страшилка из документации — это то, за чем потом едут разбираться. Про то, как я на этом попался, ниже.

Типовое окно для сервера на 40–50 ящиков и полтерабайта: три-четыре часа, если наследия нет. Плюс утро следующего дня на разбор мелочей, которые вылезут при живых пользователях.

Как я делаю на новом сервере

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

Ключевое правило переноса: на целевой машине ставится та же версия и та же операционная система, что на исходной. Апгрейд делается уже после переезда, отдельным шагом. Попытка совместить смену машины со сменой мажорной версии — самый надёжный способ получить сутки разбора вместо ночи работ.

# 1. на новой машине: та же ОС, тот же hostname
# 2. сверить UID/GID ДО установки
$ id zimbra

# 3. установка без мастера конфигурации
# ./install.sh -s

# 4. остановить исходный сервер
$ su - zimbra -c '/opt/zimbra/bin/zmcontrol stop'

# 5. перенос данных с сохранением числовых владельцев
# rsync -avr --numeric-ids /mnt/migration/zimbra /opt

# 6. права — обязательно, от root
# /opt/zimbra/libexec/zmfixperms

# 7. переустановка поверх перенесённых данных, инсталлятор предложит upgrade
# 8. и только теперь — подъём мажорной версии

Что здесь даёт новая машина, чего не даёт апгрейд на месте:

  • Старый сервер остаётся живым и нетронутым. Это точка отката получше любого снимка — можно просто вернуть DNS обратно;
  • Наследие вы переносите выборочно, а не целиком: тома создаёте заново, зимлеты ставите только нужные, мёртвые учётки не едут;
  • Операционная система меняется бесплатно, в рамках той же работы;
  • Окно простоя короче: копирование можно прогнать заранее и в окне догнать только дельту.

Что не даёт: экономии. По часам новый сервер почти всегда дороже. Разница окупается тогда, когда наследия много — а когда его много, вы это уже увидели по таблице выше.

Где я ошибся: два числа и одна оборванная сессия

Первое. Я сверил id zimbra на исходном сервере, записал 1001 — и не сверил на целевом после установки. Там инсталлятор выдал 999. После rsync получился каталог на полтерабайта, где файлы принадлежат числовому владельцу, которого в системе нет.

Спасло то, что копировал с флагом --numeric-ids: числа сохранились ровно как были, и картина оказалась однозначной, а не кашей из полу-верных владельцев. Лечится это запуском zmfixperms от root, но на 528 гигабайтах он думал час пятьдесят. Час пятьдесят посреди ночного окна — ощутимо.

Второе, и обиднее. Импорт я запустил из обычной ssh-сессии, потому что «ну это же быстро, минут двадцать». Через сорок минут вайфай в бытовке на объекте, откуда я подключался, моргнул. Сессия отвалилась, процесс умер посередине.

Дальше час я потратил на проверку, не осталась ли база в несогласованном состоянии. Обошлось: операция была из тех, что переживают обрыв. Но узнал я это только после проверки, и этот час был неприятным. С тех пор у меня в чек-листе первым пунктом стоит screen -S, и я запускаю его даже под операцию на три минуты — потому что решение «эта быстрая, можно без» принимается ровно тогда, когда его принимать не надо.

Третье, помельче, но упомяну. При переносе я захватил вместе со всеми и служебные ящики. На той схеме, где данные едут целым каталогом, это нормально и даже правильно. А вот при переносе через выгрузку ящиков по одному служебные учётки трогать нельзя — платформа создаёт их сама, и залитое поверх содержимое ломает обучение антиспама. Я эти две схемы однажды перепутал в голове, поймал на этапе плана. Записал себе.

Сколько вышло и как выбирать у себя

Смета была такая: апгрейд на месте — 16 часов и 64 000 ₽ по ставке 4 000 ₽ в час. Новый сервер — 44 часа и 176 000 ₽. После клона мы пошли по второму пути, и фактически получилось 51 час и 204 000 ₽: семь часов сверху дали права после rsync, оборванная сессия и разбор двух зимлетов, которые всё-таки понадобились и которые пришлось искать в живых версиях.

Отдельной строкой, до всех работ — лицензия Network Edition на 40 ящиков на год. Её клиент оплачивал напрямую, в мои часы она не входит, но в бюджет проекта входит и повторяется каждый год. Если вам называют цену апгрейда с девятки на десятку без этой строки — вам называют неполную цену.

Что получили на выходе: чистая машина на свежей ОС, два тома вместо четырёх, четырнадцать зимлетов вместо тридцати девяти, 40 живых ящиков вместо 47. Переиндексация всех ящиков прошла отдельным заходом в выходные — 1184 записи о повреждённых индексах ушли в ноль. 528 гигабайт после чистки мёртвых учёток и пустого тома превратились в 471.

Простой пользователей — с 22:40 пятницы до 6:15 субботы, из них по-настоящему без почты они были около пяти часов.

Отдельно про целевую версию, и это правка на момент, когда я пишу текст, а не на июнь 2025. Сегодня я бы не советовал целиться ниже 10.0.18 в старшей ветке или 10.1.13 в младшей: более ранние версии затронуты хранимым XSS через содержимое письма. И держите в голове неприятную деталь линейки 10.1: между 10.1.7 и 10.1.8 появился регресс, при котором архивная выгрузка ящика целиком буферизуется в памяти java-процесса, и на крупных ящиках zmmailbox падает по нехватке heap. Бэкпортом это уехало и в 10.0.16 с 10.0.18. То есть на свежей ветке вас ждёт не отсутствие проблем, а другой их набор — планируйте выгрузку больших ящиков кусками.

И про то, во что обошлось бы не делать ничего — этот счёт я показал директору до сметы. Первая колонка: P32 не закрывает дыру в postjournal, а её начали массово эксплуатировать с конца сентября 2024 года, и сервер строителей смотрел наружу. Разбор одного взлома Zimbra у нас занимает 60–90 часов, то есть 240 000–360 000 ₽ только за работы — без простоя и без объяснений заказчикам, что лежало в переписке. Вторая колонка: генподряд живёт почтой, через неё ходят сметы, акты и КС-2. Сутки без почты по их же фонду оплаты — 40 человек, 8 часов, 700 ₽ на человеко-час — это 224 000 ₽, и это до того, как кто-то посчитает сдвинутое подписание акта. Переезд за 204 тысячи оказался дешевле любой из двух колонок, и это единственный аргумент, который в таком разговоре действительно работает.

Как выбирать у себя, коротко. Прогоните шесть команд из блока проверки, посчитайте отметки в правой колонке таблицы. Три и больше — новая машина. Меньше — на месте, но со снимком и с клоном, на котором вы это сначала прорепетируете. Клон стоит час, а стоимость непроверенного апгрейда я вам не назову, потому что она каждый раз разная и всегда больше ожидаемой.

Хотите, чтобы я посмотрел? Пришлите вывод этих шести команд и напишите, сколько у вас людей и какая ОС под сервером. За день отвечу, какой путь ваш, сколько часов он займёт и какие конкретно унаследованные объекты у вас придётся разбирать. Это бесплатно и ни к чему вас не обязывает.

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

Можно ли откатить апгрейд, если что-то пошло не так?

Инсталлятором — нет. Обратного хода у него не предусмотрено: он поднимает схему базы, переписывает конфигурацию и перекладывает данные, и повторный запуск старой версии поверх этого не вернёт систему назад. Единственная работающая точка отката — снимок виртуальной машины, сделанный до первой команды. Если сервер физический, точкой отката становится полная холодная копия каталога /opt/zimbra при остановленных службах, снятая туда, откуда её реально можно вернуть. Совет «попробуем, не выйдет — откатимся» без одного из этих двух вариантов означает «попробуем, не выйдет — будем восстанавливаться из бэкапа несколько часов».

Обязательно ли гонять апгрейд на тестовом клоне?

Формально нет, практически я не отступаю от этого правила. Клон — это копия виртуалки, поднятая в изолированной сети с отключённым исходящим SMTP, и на его создание уходит около часа. За этот час вы узнаёте то, чего живой сервер вам не покажет, потому что оно ему не мешает: мёртвые записи о томах, отвалившиеся зимлеты, накопленные повреждения индексов. У строителей клон развернул мою первоначальную оценку на сто восемьдесят градусов — вместо шестнадцати часов на месте мы пошли на новую машину. Час репетиции против ночи разбора вслепую.

Почему после переноса на новый сервер права на файлы оказались неверными?

Почти всегда причина одна: числовые идентификаторы пользователя zimbra на исходной и целевой машине разные. Инсталлятор выдаёт их по свободным номерам в системе, и совпадение — вопрос везения. У меня было 1001 на старом сервере и 999 на новом. Проверять надо командой id zimbra на обеих машинах до копирования, а копировать с флагом --numeric-ids, чтобы числа сохранились как есть и картина осталась однозначной. Лечится запуском /opt/zimbra/libexec/zmfixperms от root, но время он берёт по объёму: на 528 гигабайтах у меня ушло почти два часа. В ночное окно это заметно, поэтому лучше сверить заранее.

Сколько времени займёт переход и сколько почта будет недоступна?

Это два разных числа. Общая трудоёмкость на 47 ящиках и 528 гигабайтах у нас вышла 51 час, растянутых на две недели: подготовка приёмной машины делается заранее и в рабочее время. Собственно простой пользователей — с 22:40 пятницы до 6:15 субботы, из них без почты по-настоящему около пяти часов. Апгрейд на месте по окну короче, три-четыре часа, но он не даёт запасного аэродрома: если что-то не задалось, вы разбираетесь прямо в этом же окне. При переносе на новую машину старый сервер остаётся живым, и в худшем случае вы просто возвращаете DNS обратно.

Мы на бесплатной девятке. Что нужно, кроме работ, и на какую версию десятки целиться?

Сначала не про версию, а про то, что её опережает. Десятка выпускается только как Network Edition, свободной редакции у неё нет. Лицензионный ключ нужен до запуска инсталлятора: без него апгрейд не начинается ни на бою, ни на тестовом клоне. Лицензия годовая и считается по числу ящиков, а покупка её российским юрлицом — отдельная процедура, которую лучше начать раньше работ. Если у вас в zmcontrol -v стоит FOSS edition, это первая строка вашей сметы, и она повторится через год. Теперь про версию. На момент, когда я это пишу, не ниже 10.0.18 в старшей ветке или 10.1.13 в младшей — более ранние версии затронуты хранимым XSS через содержимое письма, который срабатывает при простом просмотре. Дополнительно держите в голове особенность линейки 10.1: между версиями 10.1.7 и 10.1.8 появился регресс, при котором выгрузка ящика в архив целиком буферизуется в памяти java-процесса. На крупных ящиках zmmailbox из-за этого падает по нехватке heap, и бэкпортом та же логика уехала в 10.0.16 и 10.0.18. Практический вывод: планируйте выгрузку больших ящиков кусками по датам, а не одним заходом.

Нужна помощь с проектом?

Специалисты АйТи Фреш помогут с архитектурой, DevOps, безопасностью и разработкой — 15+ лет опыта

📞 Связаться с нами
#Zimbra#апгрейд#миграция#10.1#серверы
Комментарии 0

Оставить комментарий

загрузка...

Подпишитесь на рассылку ITfresh

Раз в неделю — практические гайды для руководителя IT и сисадмина: безопасность, 1С, миграции, резервные копии, лайфхаки из реальных проектов.

Реквизиты оператора персональных данных

ООО «АЙТИ-ФРЕШ», ИНН 7719418495, КПП 771901001. Юридический адрес: 105523, г. Москва, Щёлковское шоссе, д. 92, корп. 7. Контакт: info@itfresh.ru, +7 903 729-62-41. Оператор обрабатывает e-mail подписчика в целях рассылки информационных и рекламных материалов до момента отзыва согласия.