Архив лежит в бакете, листинг его показывает, размер совпадает, контрольная сумма тоже. Кажется, задача выполнена. Но настоящий вопрос про резервную копию звучит иначе: кто и при каких условиях сможет её убрать? Пока ответ «любой, у кого есть ключ приложения», копия остаётся просто файлом в удобном месте. Она переживёт поломку диска на VPS, но не переживёт ошибку в скрипте очистки, скомпрометированный токен или неудачный рефакторинг, в котором delete_old_backups() вдруг начал считать «старыми» все файлы сразу.
S3 Object Lock меняет именно это: он превращает вопрос «есть ли копия» в вопрос «чьих полномочий хватит, чтобы её удалить и до какого момента». Разберёмся, как это устроено, где легко ошибиться и как проверить защиту так, чтобы не пожертвовать реальными данными.
Сохранённый объект и объект под ограничением: две разные вещи
Обычный объект в S3-подобном хранилище защищён только правами доступа. Если у ключа есть право на удаление, объект исчезнет по первому запросу. Всё, что мы называем «защитой» на уровне приложения, — это надежда, что код не вызовет удаление по ошибке.
Object Lock добавляет к версии объекта собственное правило. Согласно документации Amazon S3, блокировка защищает именно версии объектов и работает через два механизма: срок удержания (retention period) и юридическое удержание (legal hold). Обратите внимание на слово «версии». Защита привязана не к имени файла вроде backup-2026-11-01.tar.zst, а к конкретной записанной версии под этим именем. Отсюда следует практический вывод: Object Lock в связке с версионированием, а не вместо него. Если кто-то перезапишет объект с тем же ключом, появится новая версия, а защищённая останется на месте. Но и «чистая» новая версия не унаследует защиту автоматически, её нужно получить своими параметрами записи или правилами бакета по умолчанию, если поставщик их поддерживает.
Два механизма различаются по природе:
- Срок удержания имеет дату окончания. Пока она не наступила, версию нельзя удалить или перезаписать в смысле удаления этой версии. Когда дата прошла, объект снова обычный.
- Legal hold даты окончания не имеет. Он действует, пока его кто-то явно не снимет. Это инструмент для случаев «подождите, эти данные могут понадобиться», а не для плановой ротации.
Для бэкапов VPS ежедневная работа почти всегда строится на сроке удержания: он сам заканчивается, и очистка остаётся предсказуемой. Legal hold удобен точечно: например, вы заметили, что копия от вторника содержит последнее хорошее состояние базы перед инцидентом, и хотите, чтобы плановая очистка её не коснулась, даже если срок скоро истечёт.
Совместимость с S3 — это ещё не Object Lock
Здесь легче всего споткнуться. Фраза «S3-совместимое хранилище» чаще всего означает, что клиент умеет делать PUT, GET, LIST и DELETE по знакомому протоколу. Это не доказывает, что поставщик реализовал блокировку объектов, версионирование, нужные заголовки и политики. Документация Amazon описывает поведение Amazon S3; она ничего не говорит о том, как ведёт себя чужая реализация.
Поэтому перед тем как строить на Object Lock план защиты бэкапов, у выбранного поставщика нужно выяснить по его собственной документации и настройкам:
- Поддерживается ли Object Lock вообще и нужно ли включать его при создании бакета, а не позже.
- Требуется ли включённое версионирование и можно ли его выключить после включения блокировки.
- Какие режимы удержания доступны: только один строгий или оба, включая мягкий.
- Есть ли у режима обход и каким отдельным правом он управляется.
- Как поставщик трактует срок: в днях, в точной дате, можно ли его только продлевать.
- Что происходит с блокировкой при удалении аккаунта, бакета, при неоплате.
Последний пункт неочевиден и неприятен. Блокировка защищает объект внутри хранилища, но не отменяет договорных отношений с поставщиком. Если аккаунт заблокирован за неуплату, вопрос о судьбе данных решается за пределами протокола S3. Для этого и нужна копия в другом месте, но об этом чуть ниже.
Тот же вопрос стоит и при хранении на собственном VPS: если вы поднимаете S3-совместимый сервер сами, что именно он делает при команде удаления защищённой версии, определяется его документацией и вашей проверкой, а не названием протокола.
Режимы и обход: что можно, а что нельзя вернуть
В экосистеме S3 удержание существует в двух режимах, и разница между ними определяет, насколько вы защищены от собственных ошибок и от чужих рук. В режиме governance защиту можно обойти, если у субъекта есть специальное разрешение. В режиме compliance обход не предусмотрен: до конца срока версию не удалит никто, включая владельца аккаунта. Подробности, в том числе названия разрешений, берите из описания Object Lock и сверяйте с поставщиком, если вы работаете не с Amazon.
Принципиальный момент из документации: разрешение на обход governance и разрешение на изменение параметров удержания — отдельные полномочия. Они не вытекают из права записи и права удаления. Это и есть та рычажная точка, ради которой всё затевается. Приложение, которое пишет бэкапы, должно уметь класть объекты, но не должно уметь ни обходить защиту, ни менять сроки.
| Свойство | Governance | Compliance |
|---|---|---|
| Можно ли обойти защиту специальным правом | Да, если право выдано | Нет |
| Исправление ошибки в сроке (поставили 10 лет вместо 10 дней) | Возможно через обход при наличии права | Невозможно до конца срока |
| Риск при утечке ключа с правом обхода | Защиту можно снять | Такого права не существует |
| Цена ошибки конфигурации | Обратима | Оплачивается местом в хранилище весь срок |
Выбор зависит не от «серьёзности» намерений, а от того, чего вы боитесь больше: что кто-то с лишними правами сотрёт копии или что вы сами ошибётесь в сроке и будете хранить лишнее. Для первых недель после внедрения разумнее мягкий режим, если поставщик его даёт: ошибку в параметрах можно исправить. Строгий режим имеет смысл включать, когда процесс отлажен, сроки проверены, а права обхода вообще не выданы никому из повседневных учётных записей.
Испытание: попытка удалить теми же полномочиями
Теперь к сцене из начала. Копия записана, а проверять нужно не её содержимое, а её устойчивость. Тест простой по смыслу: взять те же учётные данные, которыми пишет приложение, и попытаться удалить свежую защищённую версию.
Но здесь есть правило, которое нельзя нарушать: не ставьте необратимое удержание на production-данные ради эксперимента. Если вы проверяете строгий режим на настоящем ночном дампе базы с долгим сроком, то получите объект, который нельзя убрать, пока не истечёт срок. Для эксперимента заведите отдельный тестовый бакет (или префикс, если политика это допускает), положите туда небольшой файл с заведомо коротким сроком и проверяйте на нём.
Порядок проверки может быть таким:
- Создать тестовый бакет с включённой блокировкой объектов, как того требует поставщик.
- Записать маленький файл с коротким сроком удержания теми же ключами, что использует приложение.
- Выполнить обычное удаление объекта по имени. В версионируемом бакете это обычно создаёт маркер удаления, а не стирает данные, и это поведение стоит увидеть своими глазами.
- Выполнить удаление конкретной версии. Ожидаемый результат — отказ.
- Попробовать сократить срок удержания теми же ключами. Ожидаемый результат — тоже отказ.
- Если режим мягкий, убедиться, что без права обхода запрос на обход не проходит.
- Сохранить тексты ответов хранилища: они пригодятся для мониторинга и для инструкции.
Пункт 3 заслуживает отдельного внимания. Многие думают, что «удаление не удалось», если вызов вернул успех. А в версионируемом хранилище успешный ответ может означать лишь добавление маркера удаления: в обычном листинге объект исчез, но защищённая версия лежит на месте. Это нормально, но для приложения картина двусмысленна: оно видит, что файла нет, и может решить, что бэкап пропал. Поэтому проверка восстановления должна идти по версиям, а не по именам.
Результат испытания нужен не ради красивого отчёта. Он отвечает на вопрос, на который нельзя ответить чтением документации: делает ли выбранное хранилище то, что обещает, именно для ваших ключей и вашей политики.
Разделение полномочий: три ключа вместо одного
Object Lock бесполезен, если один и тот же набор ключей одновременно пишет, удаляет, меняет политику и обходит защиту. Такой набор у приложения на VPS лежит в переменных окружения или конфигурации, то есть в той же среде, которую вы хотите защитить. Тот, кто получил доступ к серверу, получил и всё остальное.
Разумная схема делит роли на три учётные записи с разными правами.
- Запись. Ключ на VPS. Может создавать объекты и версии. Не может удалять версии, менять параметры удержания, обходить governance и менять политику бакета.
- Восстановление. Отдельный ключ только на чтение, лежит не на производственном сервере, а там, откуда вы запускаете восстановление: на рабочем месте администратора или на отдельной машине. Если сервер недоступен, этот ключ должен быть у вас под рукой независимо от него.
- Очистка и управление политикой. Права на удаление истёкших версий и изменение конфигурации. Выдаются отдельной учётной записи, используются редко и, по возможности, интерактивно или из защищённого задания. Право обхода governance, если оно вообще нужно, лучше не выдавать никому постоянно.
Смысл разделения в том, чтобы компрометация одной роли не давала возможностей других. Если ключ записи утечёт, злоумышленник сможет создать мусорные объекты и потратить ваше место, но не сможет стереть вчерашнюю копию. Стоимость такого сценария — счёт за хранение, а не потеря данных.
Этот подход перекликается с общей идеей из материала о защите копий от того, кто уже внутри: предполагайте, что на сервере с приложением может оказаться не только ваш код. Блокировка объектов хорошо ложится на эту модель, потому что решение об удалении выносится за пределы хоста.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации Россия, США, Франция и Великобритания. Оплата картой РФ и по СБП.
Срок удержания против плана очистки
Теперь неприятная часть, о которой часто молчат. Неизменяемость стоит места. Каждая защищённая версия занимает объём до конца срока, и никакая очистка не освободит его раньше. Если вы храните ежедневные полные копии с удержанием 30 дней, то в любой момент у вас лежит около тридцати версий плюс всё, что ещё не успело истечь. Рассчитайте это заранее.
Пример с условными числами (они придуманы для наглядности, а не измерены ни на каком сервере). Допустим, дамп сжимается до 5 ГБ, копии делаются раз в сутки, срок удержания 30 дней. Минимум защищённых данных: 30 × 5 = 150 ГБ. Если дамп растёт на 2% в неделю, то к концу срока последние копии будут заметно больше первых, и сумма сместится вверх. Если вы к тому же решите делать копию дважды в день, число удвоится. А если ошибётесь и поставите 300 дней вместо 30, в строгом режиме вы заплатите десятикратным объёмом без возможности исправить.
Отсюда несколько практических выводов.
- Не путайте срок удержания и срок хранения. Удержание — минимум, до которого нельзя удалять. Хранить дольше вы вправе, просто после его окончания очистка снова возможна. Скажем, удержание 14 дней и политика хранения 60 дней — разумное сочетание: ближние копии неприкосновенны, дальние управляются обычной очисткой.
- Не выставляйте по умолчанию срок «на всякий случай» большим. Каждый лишний день умножается на число копий и на их размер.
- Используйте инкрементальные схемы осознанно. Если копии зависят друг от друга цепочкой, защищённой должна быть вся цепочка, иначе защита полной копии не спасёт от потери зависимых от неё инкрементов. Какой ряд объектов нужно держать вместе, определяет формат вашего инструмента резервного копирования.
Отдельный нюанс — программа резервного копирования, которая сама удаляет старые данные: например, сжимает цепочки или перепаковывает блоки. Если она работает ключом записи, у которого больше нет права на удаление, её операции очистки начнут завершаться ошибками. Это не поломка, а признак того, что защита работает. Но инструмент нужно настроить так, чтобы он не пытался чистить сам, а очисткой занималось отдельное задание, запускаемое с ключом очистки и только по расписанию, согласованному со сроками удержания.
Очистка, которая не борется с защитой
Хорошо спроектированная очистка выглядит скучно: раз в сутки (или неделю) выбирает версии, у которых срок удержания истёк и которые выходят за политику хранения, и удаляет их. Всё. Она не пытается обойти защиту, не работает по принципу «удалить всё старше N дней и посмотреть, что получится».
Полезно держать у себя таблицу, которую можно сверять с реальностью:
| Копия | Записана | Удержание | Удаление разрешено с |
|---|---|---|---|
| Ежедневная | 1 ноября | 14 дней | 15 ноября |
| Еженедельная | 1 ноября | 35 дней | 6 декабря |
| Месячная | 1 ноября | 180 дней | 30 апреля |
Конкретные сроки в таблице нужны только для иллюстрации принципа: каждая категория копий получает свою дату освобождения, и она известна в момент записи. Лучше сохранять её рядом с копией, например в метаданных вашего каталога резервных копий, чтобы очистка не вычисляла заново и не ошибалась на границе месяцев и часовых поясов. Сверяйтесь с тем, как поставщик задаёт и показывает дату окончания, и ориентируйтесь на значение из самого хранилища, а не на собственный расчёт.
Если вы пользуетесь legal hold, добавьте к плану простое правило: очистка пропускает версии с активным удержанием, даже если срок вышел. А тот, кто поставил hold, записывает причину и ответственного. Hold без даты окончания легко превращается в вечное хранение по забывчивости, и это та самая скрытая цена, о которой неприятно думать: копии, которые никто не помнит, продолжают занимать место и деньги.
Восстановление: проверка, о которой забывают
Неизменяемая копия, которую нельзя прочитать, не лучше удалённой. Поэтому в сценарий проверки нужно включить сам процесс восстановления, а не только защиту от стирания.
Что имеет смысл прогнать:
- Взять ключ восстановления, который не лежит на производственном VPS.
- Показать список версий нужного объекта и выбрать не последнюю, а, например, третью с конца. Так вы проверите, что умеете искать именно версии.
- Скачать её на отдельную машину и развернуть в изолированной среде.
- Убедиться, что приложение стартует на восстановленных данных, а не просто что архив распаковался.
Для такого тренировочного развёртывания удобно использовать отдельный небольшой VPS. У MAATRIX в публичном предложении есть конфигурации от Ba с 1 vCPU, 2 ГБ RAM и 40 ГБ NVMe до более крупных, а также root-доступ, так что поднять временный сервер для проверки восстановления можно без вмешательства в рабочую машину. Подходящий размер зависит от вашей базы и данных: ресурсы тарифа не служат обещанием ёмкости, поэтому сначала оцените объём распакованной копии и только потом выбирайте конфигурацию. Какие образы и локации доступны в момент заказа, показывает форма заказа.
Заодно проверьте время: сколько занимает скачивание и разворачивание. Это число определяет реальное время простоя при аварии. Защищённая копия, которую вы тянете шесть часов, — другая ситуация, чем та, что доезжает за двадцать минут, и узнать это лучше заранее.
Кто может менять политику и где лежит независимый доступ на чтение
Вся конструкция держится на предположении, что права на изменение политики бакета, на отключение блокировки или удаление самого бакета недоступны тем, кого вы защищаетесь. Если администратор хранилища — тот же человек и с теми же ключами, что и разработчик приложения, защита ограничится аккуратностью этого человека. Это не обязательно плохо для небольшого проекта, но стоит осознавать честно.
Практические вопросы, которые стоит задать себе:
- У кого есть права на изменение конфигурации блокировки и удержания? Сколько этих людей или учётных записей?
- Защищена ли учётная запись управления вторым фактором, и хранится ли её доступ отдельно от секретов приложения?
- Что случится, если ключ очистки потеряется? Есть ли запасной способ восстановить управление, и не ведёт ли он к обходу всей схемы?
- Где лежит ключ восстановления и кто, кроме вас, может им воспользоваться, если вы недоступны?
- Фиксируются ли действия по изменению политики в журнале, который не может стереть тот, кого он наблюдает?
Отдельно о доступе на чтение. Его независимость — это условие, при котором защищённая копия реально превращается в восстановленную систему. Если единственная копия ключа чтения лежит на сервере, который сгорел, вы получили сейф с ключом внутри. Храните его там, где он переживёт потерю VPS: в менеджере секретов, на отдельном носителе, у второго ответственного. Только не в репозитории приложения.
И последнее ограничение, о котором стоит помнить. Object Lock защищает версии объектов в одном хранилище одного поставщика. Он не страхует от ошибки в самих данных, если вы честно сохраняли испорченный дамп, от потери аккаунта или от решений поставщика. Это один слой, а не абсолютная защита. Для действительно важных данных добавляется вторая копия у другого поставщика или в другой форме, и вопрос о том, нужна ли она, решается по цене потери, а не из общей тревожности.
Когда объект наконец можно удалить
Остаётся вернуться к началу. Копия записана и защищена, приложение пробует её стереть и получает отказ. Но у этой истории есть вторая половина, которую неудобно оставлять без внимания: защита не должна быть бессрочной по умолчанию. У каждой копии есть дата, с которой её удаление становится не угрозой, а плановой уборкой.
Поэтому вместо совета «навсегда запретить очистку» полезнее заранее посчитать момент освобождения. Запишите в день создания: эта версия неприкосновенна до 15 ноября, после этого она подпадает под политику хранения, а следующая очистка по расписанию пройдёт в ночь на 16-е и освободит столько-то гигабайт. Тогда ограничение превращается из загадочного барьера в обычный календарный факт. В нужную ночь очистка отрабатывает своим отдельным ключом, место возвращается, а следующая партия копий уже ждёт своей даты. Именно в такой предсказуемости и состоит смысл: приложение не стирает бэкапы раньше срока, а вы не хоронитесь от собственного хранилища после него.