MAATRIX / Блог / Меняем пароли и ключи на живом сервере: порядок, при котором ничего не отвалится

Меняем пароли и ключи на живом сервере: порядок, при котором ничего не отвалится

MAATRIX

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

Почему нельзя просто взять и сменить всё за вечер

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

Пароль или ключ на сервере редко живёт в одном месте. Пароль от базы данных обычно прописан минимум в трёх местах одновременно: в самой СУБД, в .env или конфиге приложения, и часто ещё в скрипте бэкапа. Смените его в PostgreSQL — и через минуту упадёт приложение, которое продолжает стучаться со старым паролем, а следом отвалится ночной бэкап, потому что никто не вспомнил про cron-скрипт с захардкоженной строкой подключения.

SSH-ключ ещё коварнее: если вы одним движением заменяете authorized_keys, а у части команды в ~/.ssh/config до сих пор указан старый ключ, эти люди мгновенно теряют доступ — и если это единственный сервер с root, отыграть назад можно только через консоль хостинга (если она вообще настроена и если у вас есть к ней доступ).

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

Составляем карту: что менять и где это используется

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

# ищем явные пароли и ключи в конфигах — черновой список, не финальный
grep -rniE "(password|passwd|secret|api_key|token)\s*[:=]" \
  /etc /opt /var/www /home --include="*.env" --include="*.yml" \
  --include="*.yaml" --include="*.conf" --include="*.ini" 2>/dev/null \
  | grep -v "^Binary"

# отдельно смотрим docker-compose и docker secrets
grep -rn "environment:" -A5 /opt/*/docker-compose.yml 2>/dev/null

# ищем захардкоженные строки подключения в cron
crontab -l
for u in $(cut -d: -f1 /etc/passwd); do sudo crontab -l -u "$u" 2>/dev/null | grep -i "pass\|token"; done

Отдельная больная тема — пароли, зашитые в переменные окружения docker-compose.yml напрямую, а не через .env или Docker secrets: если у вас есть такие сервисы, при инвентаризации сразу отмечайте их как места повышенного риска (подробнее о том, почему это утечка даже после удаления строки, — в разборе антипаттерна с паролями в docker-compose).

По итогу инвентаризации у вас должен получиться примерно такой список:

СекретГде хранитсяКто используетКритичность
root SSH-ключauthorized_keys rootвся команда, деплой-скрипткритично
пароль PostgreSQLБД, .env приложения, скрипт бэкапаприложение, cron, мониторкритично
пароль панели хостингаголова1-2 человекасредне
пароль SMTP-релея.env, конфиг рассылкиприложениесредне
API-ключ платёжного шлюза-песочницы.env тестового стендатолько тестнизкая
пароль FTP для старого архиваконфиг FTP-клиентаникто активнонизкая

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

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

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

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

Порядок: сначала некритичное, потом критичное

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

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

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

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

Практический план очерёдности:

  1. Мёртвые и тестовые доступы — то, что реально не используется в проде: старые FTP, тестовые API-ключи, доступы уволившихся исполнителей, о которых все и так знали, что их пора выключить. Здесь же — хорошее время эти доступы вообще упразднить, если они не нужны, а не просто сменить пароль.
  2. Вспомогательные сервисы со средней критичностью — мониторинг, SMTP-релей, панель хостинга, дашборды. Простой на несколько минут здесь неприятен, но не катастрофичен.
  3. Пароли приложений и баз данных — здесь уже нужна синхронная замена (следующий раздел) и заранее выбранное окно с минимальной нагрузкой.
  4. SSH-ключи и root-доступ — самое последнее и самое аккуратное звено: делается по схеме с переходным периодом, а не одномоментной заменой (см. ниже).
  5. Плановая ротация на будущее — когда всё унаследованное заменено, переводите обновлённые секреты на регулярный график, а не оставляете их менять «когда вспомним» (ориентиры по частоте и распределению по календарю — в разборе смены паролей на сервере по расписанию).

Синхронная замена: почему нельзя менять по частям

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

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

# 1. Генерируем новое значение заранее, до начала окна замены
NEW_PASS=$(openssl rand -base64 24)
echo "Новый пароль сгенерирован, сохраняем в черновик менеджера паролей"

# 2. Готовим все конфиги ЗАРАНЕЕ, но не применяем —
#    правим .env приложения, скрипт бэкапа, конфиг мониторинга
#    в отдельных файлах-черновиках рядом с боевыми
cp /opt/app/.env /opt/app/.env.new
sed -i "s/DB_PASSWORD=.*/DB_PASSWORD=${NEW_PASS}/" /opt/app/.env.new

# 3. В короткое окно — меняем пароль в СУБД и тут же
#    подменяем боевые конфиги заготовленными
sudo -u postgres psql -c "ALTER USER app_user WITH PASSWORD '${NEW_PASS}';"
mv /opt/app/.env.new /opt/app/.env
systemctl restart app.service

# 4. Сразу проверяем, что приложение поднялось и работает с новым паролем
systemctl status app.service --no-pager
curl -sf http://127.0.0.1:8080/health || echo "ПРОВЕРКА НЕ ПРОШЛА"

Ключевая идея — минимизировать окно между сменой пароля в источнике (СУБД, панель, сервис аутентификации) и обновлением во всех потребителях. Черновики конфигов готовятся заранее, само переключение занимает секунды, а не минуты на редактирование файлов вручную под давлением «уже не работает».

Отдельно держите в голове неочевидных потребителей: интеграции мониторинга (Zabbix, Prometheus exporter с паролем к БД), скрипты миграций, CI/CD-пайплайны, которые деплоят на сервер и где пароль может лежать в переменных окружения раннера. Если один из них пропущен, ошибка вылезет не сразу, а в следующий раз, когда скрипт запустится по расписанию — часто ночью, когда её сложнее поймать быстро.

SSH-ключи и root: без окна простоя вообще

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

# 1. Добавляем НОВЫЙ ключ, не трогая старый
cat new_key.pub >> ~/.ssh/authorized_keys

# 2. Проверяем вход по новому ключу В ОТДЕЛЬНОЙ сессии,
#    не закрывая текущую — это страховка на случай опечатки
ssh -i ~/.ssh/new_key user@server "echo OK, новый ключ работает"

# 3. Только после успешной проверки — предупреждаем всех, у кого
#    есть старый ключ, о сроке перехода, и удаляем старую строку
sed -i '/старый-ключ-комментарий/d' ~/.ssh/authorized_keys

Если унаследованных ключей много и вы не уверены, кто именно ими пользуется — частый случай на чужом сервере, — не удаляйте молча: дайте видимый срок (несколько дней) и наблюдайте по логам auth.log, кто реально заходит новым ключом, а кто ещё нет. Подробный регламент с переходным периодом разобран в статье про ротацию SSH-ключей раз в полгода — там же порядок для повторяющегося цикла, а не разовой унаследованной чистки.

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

Тестируем каждый шаг, а не всю партию в конце

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

Минимальный набор проверок после каждой смены:

  • Сервис поднялсяsystemctl status, ответ жив, процесс не в цикле рестарта (systemctl status покажет счётчик перезапусков).
  • Функциональная проверка — не просто «порт слушает», а реальный запрос: логин в приложение, тестовая транзакция, health-check эндпоинт, если он есть.
  • Логи чистые в первые минутыjournalctl -u app.service -f или tail -f по логу приложения сразу после рестарта, минуту-две вживую, не постфактум.
  • Соседние сервисы не задеты — если меняли пароль от БД, проверьте не только основное приложение, но и всё, что к той же базе стучится: админку, аналитику, экспорт отчётов.
# короткий скрипт-проверка после каждого шага смены
SERVICE=app.service
systemctl is-active --quiet "$SERVICE" && echo "$SERVICE: активен" || echo "$SERVICE: НЕ АКТИВЕН"
journalctl -u "$SERVICE" --since "2 minutes ago" | grep -i "error\|fail\|denied" && echo "Есть подозрительные строки в логе" || echo "Логи чистые"

Фиксируйте каждый успешный шаг в журнале, который вы завели при первичном разборе сервера: дата, что поменяли, где обновили, что проверили. Это единственный способ через месяц ответить на вопрос «мы точно везде поменяли пароль от той базы» без повторной инвентаризации с нуля.

Откат и куда положить новые пароли после смены

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

Базовые правила отката:

  • Не удаляйте старое значение, пока не подтверждена работоспособность нового. Для SSH — не трогать старую запись в authorized_keys, пока новый ключ не проверен рабочей сессией. Для паролей — держать прежнее значение под рукой (в защищённом виде) до конца окна замены.
  • Делайте снимок конфигов перед правкой. cp .env .env.bak.$(date +%s) перед каждой правкой — секунда времени, которая экономит десятки минут на восстановление, если откат понадобится.
  • Для баз данных — короткое окно, где старый и новый пароль оба валидны, если СУБД это позволяет. В PostgreSQL можно временно завести второго технического пользователя с тем же уровнем прав на новом пароле, переключить на него приложение и только потом убрать старого — дороже по времени, но снимает риск полного простоя.
  • Держите альтернативный канал доступа, пока идёт смена root-ключа или единственного sudo-пользователя: консоль провайдера (VNC/serial-console через панель хостинга) — аварийный выход, если SSH-доступ вдруг оказался потерян. Проверьте, что знаете, как в неё попасть, ещё до начала смены.

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

Смена паролей без изменения того, как они хранятся дальше, — половина работы: если новые значения снова осядут в переписке или в незашифрованном файле на рабочем столе, вы через полгода окажетесь в той же ситуации, что заставила вас читать эту статью. Заведите единое место хранения для команды — менеджер паролей с общими сейфами по проектам, а не пересылку в чат при каждой необходимости. Для секретов, которые использует само приложение (не люди), — Docker secrets или файлы с ограниченными правами вне репозитория, а не переменные окружения в открытом виде в docker-compose.yml.

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

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

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

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

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

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

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

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

Можно ли менять все пароли параллельно, если работает несколько человек?

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

Что делать, если неизвестно, кто ещё пользуется конкретным SSH-ключом?

Не удаляйте его сразу. Дайте видимый срок перехода (несколько дней), в объявлении команде укажите крайний срок, и следите по auth.log, какие ключи реально используются в этот период — по факту входа, а не по памяти.

Нужно ли менять пароли, если сервер и так скоро планируется переносить на новую инфраструктуру?

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

Как быть с паролями, которые прописаны в коде приложения, а не в конфиге?

Это отдельная и более трудоёмкая задача — вынести секрет из кода в переменные окружения или менеджер секретов потребует правки и деплоя приложения, а не только смены значения. Планируйте на это отдельное время и отдельный релиз, не пытайтесь совместить с общей волной смены паролей.

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

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

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