MAATRIX / Блог / Регламент архивации завершённых проектов: как убрать их с боевого сервера

Регламент архивации завершённых проектов: как убрать их с боевого сервера

MAATRIX

На боевом сервере обычно живёт не только то, что приносит деньги сейчас. Там же тихо стоят три контейнера от пилота, свёрнутого полгода назад, база клиента, ушедшего в прошлом квартале, и сервис для эксперимента, который «пока не будем удалять, вдруг вернёмся». Каждый такой проект продолжает есть RAM и диск, тянуть на себе неснятую версию фреймворка с известными дырами и оставаться точкой входа, о которой никто уже не помнит. Ниже — рабочий регламент, который переводит такие проекты из состояния «висит непонятно зачем» в состояние «заархивирован, задокументирован, поднимается за час при необходимости».

Почему «пусть повисит» — это не нейтральный выбор

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

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

Второй — поверхность атаки. Проект, который не развивают, не получает обновлений безопасности. PHP 7.4 без патчей, заброшенный WordPress-плагин — всё это открытые порты и уязвимый код, доступный из интернета, за которым никто не следит. Сканеры уязвимостей находят такие цели быстрее, чем действующие сервисы, потому что на них никто не реагирует на алерты.

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

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

Что считать завершённым проектом и кто это решает

Прежде чем архивировать, нужен явный критерий «этот проект пора убирать с продакшена». Без него архивация происходит либо никогда (жалко, вдруг понадобится), либо хаотично (кто-то один решил и снёс).

Рабочие признаки того, что проект — кандидат на архивацию:

  • Нет коммитов в репозиторий и тикетов по проекту за последние 60–90 дней.
  • Договор с клиентом расторгнут либо продукт официально закрыт для новых пользователей.
  • Трафик на прод стремится к нулю по логам за последний месяц (без учёта ботов и сканеров).
  • Проект «на паузе» дольше квартала без плана возобновления — с точки зрения инфраструктуры такая пауза ничем не отличается от закрытия: платить и держать поверхность атаки приходится всё это время.

Важно закрепить, кто принимает решение об архивации — обычно тимлид или владелец продукта, а не дежурный DevOps-инженер по собственной инициативе. У архивации есть последствия для юридической стороны (сроки хранения данных клиентов, договорные обязательства), которые не всегда видны из инфраструктуры. Решение фиксируется письменно — тикетом или записью в трекере — с датой и именем того, кто его принял. Через год именно эта запись объяснит, почему проект вообще тронули.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Шаг 1. Полный бэкап перед выводом с продакшена

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

Что входит в архивный бэкап, помимо базы данных:

  • Код и история — не только текущая ветка, а полный git-репозиторий со всеми ветками и тегами: git bundle create project.bundle --all. Если код лежит только на самостоятельно хостящемся GitLab/Gitea — экспортируйте архив проекта через API, не полагайтесь, что репозиторий переживёт архивацию самого GitLab.
  • База данных — полный дамп, а не инкремент. Для PostgreSQL: pg_dump -Fc dbname > dbname.dump, для MySQL — mysqldump --single-transaction --routines --triggers dbname > dbname.sql. Логический дамп переживает смену версии СУБД лучше, чем бинарный снапшот диска.
  • Файлы приложения — загруженные пользователями файлы, сгенерированные отчёты, логи за последние несколько месяцев для расследований задним числом.
  • Конфигурация и секреты.env, конфиги nginx/traefik, docker-compose.yml, systemd unit-файлы. Секреты стоит вынести отдельно и зашифровать своим ключом — они не должны валяться в общем архиве открытым текстом годами.
  • Docker-образы, если проект собирался в кастомный образ: docker save myapp:latest | gzip > myapp-image.tar.gz. Через два года конкретная версия base-image может уже не собраться из Dockerfile — зависимости из репозиториев исчезают или ломают совместимость.
  • DNS-записи и внешние интеграции — список доменов, поддоменов, вебхуков, API-ключей у платёжных систем. Это то, что физически не лежит на сервере, но обязательно для восстановления.

Практический момент: соберите всё в один архив с понятной структурой и проверьте его целостность до того, как трогать продакшен:

mkdir -p /archive-staging/project-name/{db,code,files,config,secrets}
pg_dump -Fc project_db > /archive-staging/project-name/db/project_db.dump
git bundle create /archive-staging/project-name/code/repo.bundle --all
tar czf /archive-staging/project-name/files/uploads.tar.gz /var/www/project/uploads
cp docker-compose.yml nginx.conf /archive-staging/project-name/config/
tar czf project-name-archive-$(date +%F).tar.gz -C /archive-staging project-name
sha256sum project-name-archive-*.tar.gz > project-name-archive.sha256

Хэш-сумма — не формальность: она даёт способ через год проверить, что архив не побился при копировании между хранилищами. Регламент не завязан на конкретный инструмент бэкапа — подходит и borgbackup, и restic, и обычный tar.

Шаг 2. Безопасное отключение с периодом наблюдения

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

  1. Read-only режим. Если это возможно на уровне приложения — переведите его в режим только для чтения на несколько дней. Это ловит ситуации, когда «завершённый» проект на деле кому-то ещё нужен для записи данных.
  2. Отдать 503 вместо реального ответа, оставив сервис технически поднятым. На nginx это делается без остановки самого приложения:
location / {
    return 503;
}
error_page 503 /maintenance.html;

Так фиксируется, кто и как часто ещё пытается достучаться до проекта — по логам 503-ответов видно живых клиентов, забытые cron-джобы с других серверов, вебхуки от внешних систем.

  1. Период наблюдения — от 7 до 30 дней в зависимости от критичности проекта: для внутреннего пет-проекта достаточно недели, для бывшего платящего клиента разумно выдержать полный месяц, чтобы захватить конец отчётного периода. Логика такая же, как в статье про то, как правильно выключать старый сервер, выждав 30 дней: наблюдение стоит на порядок дешевле, чем экстренное восстановление удалённого проекта по требованию клиента, который «просто забыл предупредить».
  2. Остановить фоновые процессы — cron-задачи, очереди (Celery, Sidekiq, RabbitMQ consumers), scheduled-задачи в Kubernetes. Именно они чаще всего продолжают дёргать внешние API даже тогда, когда веб-часть уже не отвечает.
  3. Только после этого — остановка и снятие сервисов. docker compose down, снятие systemd unit'ов, отзыв SSL-сертификатов через ACME-клиент. Сервер как физическая или виртуальная единица на этом этапе ещё может продолжать существовать под другими проектами — вы просто убираете конкретный сервис с него.

Шаг 3. Перенос архива в дешёвое долгосрочное хранение

Хранить архив на том же NVMe, где крутится прод — самая частая переплата в этой цепочке: быстрый диск стоит в разы дороже холодного хранилища, а архиву скорость доступа не нужна почти никогда.

Практические варианты, куда переносить готовый архив:

ВариантКогда уместенОсобенности
Свой S3-бакет (MinIO на сервере с HDD)Несколько архивов, своя инфраструктураПолный контроль, но нужно следить за диском и бэкапом самого хранилища
Архивный тариф облачного объектного хранилищаРазовые архивы, не хочется администрировать железоХранение дешёвое, но скачивание и досрочное удаление часто отдельная платная строка
Отдельный дешёвый сервер с HDD под архивыМного проектов на архивации, нужен единый «архивный узел»Дешевле, чем держать SSD под мёртвые проекты; годится и под бэкапы живых
Офлайн-диск с двумя копиямиОсобо чувствительные и юридические архивыНе тарифицируется постоянно, но нужна ручная ротация и проверка читаемости раз в год-два

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

Обязательно шифруйте архив перед переносом в стороннее хранилище, особенно если внутри — персональные данные пользователей или платёжные реквизиты:

gpg --symmetric --cipher-algo AES256 project-name-archive-2026-08-25.tar.gz

Ключ шифрования храните отдельно от самого архива — в менеджере паролей команды, а не в текстовом файле рядом с бэкапом.

Шаг 4. Документирование — реестр архивов

Самая частая причина, по которой архивация «не работает» даже при наличии бэкапа — никто через два года не помнит, что именно заархивировано, где оно лежит и как это поднять обратно. Бэкап без описания — просто файл неизвестного содержания.

Заведите единый реестр архивов — таблицу в Google Sheets, Notion или файл в репозитории с внутренней документацией — с обязательными полями:

  • Название проекта и дата архивации.
  • Причина архивации и кто принял решение (ссылка на тикет).
  • Где физически лежит архив — конкретный путь, бакет, имя диска.
  • Контрольная сумма (sha256) для проверки целостности.
  • Срок хранения и дата, после которой архив можно удалить окончательно.
  • Краткий runbook восстановления — 5–10 команд, которые физически поднимут проект обратно, а не «спроси у Пети, он знает».

Runbook стоит написать так, будто читать его будет не автор, а другой человек через год без контекста:

# Восстановление project-name из архива

1. Скачать архив: project-name-archive-2026-08-25.tar.gz из /backup-archive/project-name/
2. Проверить целостность: sha256sum -c project-name-archive.sha256
3. Расшифровать: gpg --decrypt project-name-archive-2026-08-25.tar.gz.gpg > archive.tar.gz
4. Распаковать: tar xzf archive.tar.gz
5. Поднять БД: pg_restore -d project_db_restored db/project_db.dump
6. Восстановить код: git clone code/repo.bundle project-name
7. Поднять контейнеры: docker compose -f config/docker-compose.yml up -d
8. Настроить DNS обратно на новый IP (записи см. в config/dns-records.txt)

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

Баланс между «удалить навсегда» и «держать вечно просто так»

Оба крайних варианта — ошибка. Немедленное удаление после отключения экономит копейки на хранении, но лишает возможности вернуться к проекту и часто нарушает обязательства по хранению данных (у бухгалтерских документов и персональных данных пользователей — разные законодательно закреплённые сроки). Вечное хранение на боевом сервере, в свою очередь, оплачивается по цене продакшена за то, что давно не приносит пользы.

Рабочий компромисс — трёхуровневая политика сроков:

  1. 0–30 дней — период наблюдения, сервис ещё технически доступен, легко откатить решение полностью.
  2. 30 дней – 1–3 года (конкретный срок зависит от типа данных и юрисдикции — стоит свериться с юристом или бухгалтером, а не решать инженерным чутьём) — архив лежит в холодном хранилище, недоступен публично, но восстановим за часы по runbook.
  3. После истечения срока — окончательное удаление с подтверждением: ответственный из реестра архивов проверяет, что срок истёк и юридических причин хранить дальше нет, и только после этого стирает архив безвозвратно, включая резервные копии самого архивного хранилища.

Хранение в холодном хранилище на порядок дешевле, чем на активном сервере, но не бесплатно — если проектов десятки, а сроки растягиваются на годы, объём архивов тоже растёт, и его стоит периодически ревизовать, а не забывать насовсем. Регламент архивации превращает разовое «надо бы прибрать» в процесс с датами, ответственными и понятным концом.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.

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

Обязательно ли ждать 30 дней перед отключением, если проект точно больше не нужен?

Нет, срок наблюдения — не догма, а инструмент под конкретный риск. Для внутреннего эксперимента без внешних пользователей хватит нескольких дней read-only режима. Длинное окно нужно там, где есть внешние клиенты или интеграции, о которых легко забыть.

Что делать, если после архивации выяснилось, что бэкап собрали не полностью?

Это и есть причина держать сервер живым в период наблюдения, а не сносить сразу после снятия дампа. Если сервер уже выключен — восстановление возможно только из того, что реально попало в архив, отсюда и важность чек-листа на шаге 1.

Нужно ли архивировать проекты, где не было персональных данных пользователей?

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

Можно ли автоматизировать весь регламент скриптом?

Шаги 1 и 3 (сбор бэкапа и перенос в холодное хранилище) автоматизируются полностью — обычный cron-скрипт с проверкой контрольных сумм. Шаг 2 (решение об отключении) и часть шага 4 (причина архивации, юридическая оценка сроков) требуют человека — автоматизировать стоит механику, а не решение.

Куда девать реестр архивов, если компания использует несколько разных хранилищ?

Реестр должен быть один и централизованный независимо от числа физических мест хранения — иначе теряется смысл документирования. Формат неважен: таблица, вики-страница, README в репозитории — важно, чтобы у него был один известный команде адрес.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →