MAATRIX / Блог / MVP собрали за выходные: что чинить на сервере в первый рабочий понедельник

MVP собрали за выходные: что чинить на сервере в первый рабочий понедельник

MAATRIX

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

Почему это не про «плохой код», а про два разных режима работы

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

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

Дальше — пять типов долга, которые чаще всего накапливаются за спринт выходных, в порядке убывания цены ошибки, если их не закрыть.

Секреты в коде — чинить в первую очередь

Это самый частый и самый опасный долг хакатон-скорости: пароль от базы, ключ API OpenAI или Stripe, токен бота — всё это оказывается прямо в исходниках, потому что переменные окружения — это на 10 минут дольше, а дедлайн — сейчас. Приватность репозитория — не гарантия: доступ к нему может получить внешний подрядчик, случайный коллаборатор, а сам репозиторий может однажды стать публичным одним неверным кликом в настройках GitHub.

Хуже того — секрет, один раз попавший в git-историю, остаётся там даже после того, как вы удалите строку в следующем коммите. Он лежит в .git, доступен через git log -p и через любой клон репозитория.

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

  1. Найдите все секреты в коде. Быстрый способ — grep по репозиторию:
grep -rniE "(password|passwd|secret|api[_-]?key|token)\s*=\s*['\"][^'\"]{8,}" --include="*.py" --include="*.js" --include="*.env.example" .

Плюс отдельно проверьте docker-compose.yml и любые конфиги — там пароли к базам часто прописаны буквально в environment:.

  1. Вынесите их в .env и переменные окружения. Для Node.js — пакет dotenv, для Python — python-dotenv или pydantic-settings. Файл .env сразу добавьте в .gitignore, а рядом положите .env.example с именами переменных без значений — это документация для будущего вас и для остальных участников команды.
  1. Ротируйте всё, что уже успело попасть в git, даже если репозиторий приватный. Смена пароля к базе, перевыпуск API-ключа в панели провайдера — дешевле, чем потом разбираться, кто и когда мог видеть старый секрет. Скомпрометированный ключ, который вы просто удалили из кода, но не отозвали, — это всё ещё рабочий ключ в чужих руках.
  1. Если секрет уже утёк в публичный репозиторий — считайте его скомпрометированным без вариантов, даже если вы уверены, что «никто не успел посмотреть». Перевыпускайте немедленно, потом уже разбирайтесь с историей git (git filter-repo или BFG Repo-Cleaner для полной зачистки).

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

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

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

Арендовать VPS

Резервное копирование — пока не поздно

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

Минимальный рабочий бэкап на понедельник — не идеальный, а просто существующий:

# для PostgreSQL — дамп базы раз в сутки с ротацией на 7 дней
mkdir -p /opt/backups/db
cat > /opt/backups/backup.sh << 'EOF'
#!/bin/bash
DATE=$(date +%Y-%m-%d)
pg_dump -U myapp_user myapp_db | gzip > /opt/backups/db/myapp_$DATE.sql.gz
find /opt/backups/db -name "*.sql.gz" -mtime +7 -delete
EOF
chmod +x /opt/backups/backup.sh
(crontab -l 2>/dev/null; echo "0 3 * * * /opt/backups/backup.sh") | crontab -

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

Здесь стоит сразу закрыть три типичные ошибки самодельного бэкапа на старте:

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

Подробный разбор общего принципа резервного копирования — в статье про правило 3-2-1 для бэкапов: для MVP на старте достаточно версии «попроще», но сам принцип — несколько копий в разных местах — стоит держать в голове с первого дня.

Открытые "для теста" порты и панели без пароля

Во время спринта почти всегда появляются временные точки входа: админка Grafana с логином admin/admin, панель базы данных, открытая наружу для удобства отладки, debug-эндпоинт вроде /debug, /api/internal или /.env, который случайно отвечает 200 вместо 404. В пятницу вечером это удобно — можно быстро зайти и посмотреть логи прямо из браузера. В понедельник, когда у продукта появился реальный трафик, это ровно то, что сканируют боты в первую же минуту после того, как порт стал доступен из интернета.

Проверьте, что реально видно снаружи, а не что вы думаете, что открыли:

# с самого сервера — какие порты слушают и на каком интерфейсе
ss -tulnp

# извне — что реально доступно (замените IP на свой)
nmap -Pn 203.0.113.10

Если ss показывает 0.0.0.0:5432 для базы данных или 0.0.0.0:3000 для админки — это порт, открытый всему интернету, а не только вам. Дальше по каждому найденному сервису — три варианта:

  • Закрыть совсем, если снаружи он и не должен быть виден: база данных, Redis, внутренние API — им нужен только доступ с самого сервера или из докер-сети, 127.0.0.1 вместо 0.0.0.0 в конфиге сервиса, плюс правило firewall.
  • Спрятать за VPN или SSH-туннель, если доступ нужен вам, но не всему миру — ssh -L 3000:localhost:3000 user@server для разового захода в админку без постоянно открытого порта.
  • Поставить аутентификацию, если сервис действительно должен быть публичным — минимум basic auth через nginx перед панелью:
location /admin/ {
    auth_basic "Restricted";
    auth_basic_user_file /etc/nginx/.htpasswd;
    proxy_pass http://127.0.0.1:3000/;
}

Заодно проверьте фаервол на уровне ОС — ufw status verbose или iptables -L -n. Правило «разрешить всё, потом разберёмся» — частый спутник спринта выходных, и его стоит заменить на «запрещено всё, кроме явно нужного» уже в первую рабочую неделю. Подробный разбор — в статье о том, как проверить и закрыть открытые порты на сервере.

Мониторинг и алерты — узнавать первым, а не последним

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

Минимальный рабочий мониторинг разворачивается быстрее, чем кажется. Uptime Kuma — самый быстрый вариант для старта, поднимается одним контейнером:

services:
  uptime-kuma:
    image: louislam/uptime-kuma:1
    volumes:
      - uptime-kuma-data:/app/data
    ports:
      - "3001:3001"
    restart: unless-stopped
volumes:
  uptime-kuma-data:

После запуска — добавить пару проверок: HTTP-пинг главной страницы раз в минуту, проверку что API отвечает 200, и подключить уведомление в Telegram или почту. На старте не нужно 20 метрик и дашборд с графиками — нужны буквально два алерта: «сайт не отвечает» и «диск почти заполнен» (df -h вручную первую неделю тоже сойдёт, если руки пока не дошли до автоматики). Это на порядок дешевле по времени, чем разворачивать полноценный Prometheus + Grafana в первый же понедельник — тот стек стоит подключать позже, когда появится, что именно измерять.

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

Права доступа и root — навести порядок без спешки

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

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

Что стоит поправить в первую неделю без спешки:

  • Сервисы — не от root. Создайте отдельного пользователя под приложение и запускайте процесс от него:
useradd -r -s /bin/false myapp
chown -R myapp:myapp /opt/myapp
# в systemd-юните
[Service]
User=myapp
Group=myapp
  • SSH — по ключу, не по паролю. Если сейчас вход всё ещё по паролю — это стоит закрыть в числе первых пунктов, а не только в конце списка; это тоже точка входа снаружи, как и открытые порты.
  • Firewall — по умолчанию deny, явные разрешения по необходимости. ufw default deny incoming, а дальше открывать только реально нужные порты (80, 443, SSH на нестандартном порту, если используете такой подход).
  • Сотрудники и подрядчики — без общего root-доступа. Если к серверу за выходные успел подключиться кто-то ещё, стоит сразу же завести отдельные учётки вместо одного общего пароля — это упрощает и отзыв доступа, если человек уйдёт из проекта.

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

Как расставить приоритеты, не пытаясь исправить всё сразу

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

ПриоритетЧто чинитьПочему именно сейчасОриентировочное время
1 (сегодня)Секреты из кода в переменные окружения, ротация утёкших ключейОткрытая дверь в базу или к платному API прямо сейчас1-2 часа
2 (сегодня-завтра)Минимальный бэкап данных с копией не на этом же сервереПервые пользователи = первые невосстановимые данные2-3 часа
3 (эта неделя)Закрыть или спрятать за VPN тестовые порты и админкиБоты сканируют новые IP в первые часы после появления в сети2-4 часа
4 (эта неделя)Базовый мониторинг с алертом в Telegram на падение сайтаДешевле узнать от системы, чем от пользователя1-2 часа
5 (следующие 1-2 недели)Сервис не от root, ключи вместо паролей, firewall default denyСнижает ущерб при взломе, но не первопричина рискапо частям

Обратите внимание, что порядок — не «от простого к сложному», а от «может привести к невосстановимой потере или прямому взлому» к «снижает последствия, если что-то всё же случится». Косметика вроде красивых имён веток, рефакторинга наспех написанных функций или наведения порядка в issue-трекере может подождать сколько угодно — она не увеличивает риск для пользователей и данных, только неудобство для вас самих.

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

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

Арендовать VPS

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

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

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

У меня нет времени закрыть всё за один день — с чего начать, если есть только час?

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

Обязательно ли сразу переезжать с ноутбука или временного VPS на нормальный сервер, если MVP уже работает?

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

Можно ли просто поставить облачный сервис мониторинга и бэкапов вместо ручной настройки?

Можно и часто разумно на этом этапе — платный сервис вроде managed-бэкапа или SaaS-мониторинга экономит время, которого у команды на старте и так мало. Компромисс — вы платите за скорость и меньше контролируете детали; для MVP это обычно оправданный обмен.

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

Нет смысла — это нормальная цена скорости хакатон-спринта, а не провал. Полезнее превратить чек-лист в конкретные задачи с оценкой времени и закрыть их в течение недели, чем разбирать, кто виноват.

Как понять, что порт или сервис действительно нужно закрыть, а не просто он выглядит подозрительно?

Задайте вопрос: «должен ли к этому иметь доступ кто-то за пределами моего сервера или моей команды?» Если ответ нет — закрывайте или прячьте за VPN. Если да — оставляйте, но добавляйте аутентификацию и логирование обращений.

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

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

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