- PVSM.RU - https://www.pvsm.ru -

Я устал деплоить проекты вручную и автоматизировал этот процесс

Проблема

Мне, как backend‑разработчику, приходится работать с деплоем своих проектов. Каждый раз одна и та же рутина: настройка сервера, Nginx, SSL, безопасность сервера(fail2ban, отдельный пользователь), CD и многое другое. Это забирает много времени.

Что сделал

После десятков задеплоенных проектов я понял, что все эти действия можно автоматизировать, и решил написать скрипт. Работает так: я запускаю скрипт и ввожу свои данные, которые уникальны у каждого проекта: домен, сервер, Docker, .env. Код этих bash‑скриптов я выложил в открытый репозиторий на GitHub, так что каждый может посмотреть, что выполняется на сервере, куда осуществляется деплой.

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

mkdir -p /etc/docker cat > /etc/docker/daemon.json <<‘JSON’ { “registry-mirrors”: [“https://mirror.gcr.io”, “https://dockerhub.timeweb.cloud”], “userland-proxy”: false, “dns”: [“8.8.8.8”, “1.1.1.1”] } JSON systemctl restart docker || true

С каждым разом я искал возможность автоматизации, потому что где‑то нужен мониторинг системы — Grafana + Prometeus. Их я решил поднимать в отдельном Docker Compose‑файле и запускать вместе с основным. Где‑то нужны защищённые роуты, в качестве VPN выбрал AmneziaWG, он простой в настройке и, как показывает практика, не блокируется. Поднимаем VPN, а в Caddyfile проверяем IP‑адрес запроса, если запрос из нашей сети — пропускаем, если нет — отдаём 404:

@protected {
path /путь /путь/ /путь/*
not remote_ip 10.8.0.0/24
}

respond @protected “404 Not Found” 404

Тут же расскажу про Caddy и почему я выбрал его, а не Nginx. Одно из преимуществ Caddy — автоматический SSL: про ручную настройку сертификатов можно практически забыть, и лёгкость конфигурации. В будущем, конечно, планирую перейти на Nginx: всё‑таки он проверен годами, да и при больших нагрузках может быть быстрее. Caddy поднимаю глобально на весь VPS [1], раньше он запускался в отдельном Docker‑контейнере. Это решение — вынести Caddy глобально — добавило возможность гибко им управлять при добавлении/удалении/обновлении проектов на 1 VPS [1]. Caddyfile дефолтный, можно отметить наличие security‑заголовков:

header {
Strict-Transport-Security "max-age=31536000;"
X-Content-Type-Options "nosniff"
X-Frame-Options "SAMEORIGIN"
-Server
}

и подстановку реального IP и попытки достучаться до приложения, чтобы не отдавать пользователю 502:

reverse_proxy app-проект:порт {
header_up X-Real-IP {http.request.remote.host}
lb_try_duration 30s
lb_try_interval 250ms
}

Почему я сделал сервис, ведь уже есть готовые скрипты?

Эти bash‑команды либо писать вручную на VPS [1], либо писать программу, которая будет выполнять всё это на сервере, поэтому я, как веб‑разработчик, сделал UI для себя, где от меня требуется только заполнить форму и нажать кнопки, скрипт выполняется на сервере, где размещается проект(который мы ставим на хостинг [1]). Помимо автоматизации, чтобы сервис не сидел без дела, пока работает проект, я постарался увеличить его КПД. Пусть пингует мой сервер каждые 20 секунд и выдаёт уведомление, если сервер не отвечает или отдаёт 500. А когда сервер восстановится (после обнаружения ошибки проверка идёт раз в 5 секунд), пусть тоже напишет. Также приходилось разрабатывать проекты командой и тут мой сервис был не готов конечно — все у одного человека. Пришлось добавить команды, где проекты общие — все участники видят лог: кто что нажал, когда CD отработал, когда был отключён и тому подобное

Про безопасность

Так как сервис работает с чужими серверами, я не хотел делать магию в стиле «просто доверься». Здесь есть несколько важных моментов.

Во‑первых, все запросы к самому сервису идут по HTTPS. Это закрывает передачу данных между браузером и сервисом, но понятно, что одного HTTPS недостаточно, потому что дальше остаются вопросы хранения данных, SSH‑доступ и выполнение команд на сервере.

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

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

Доступ к GitHub нужен только на время получения кода для деплоя. Здесь тоже важно не записывать токены в логи и не хранить их в открытом виде. Из того, что всё‑таки нужно хранить постоянно: метаданные проекта, домен, репозиторий, настройки деплоя и зашифрованный приватный ключ для CD/откатов. Приватный ключ хранится не в чистом виде, а в зашифрованном виде через AES‑GCM. Это не делает систему неуязвимой, но защищает от самого тупого сценария, если кто‑то получит дамп базы, он не увидит ключи в открытом виде.

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

Что насчёт Dokku, Heroku, Railway и Render?

Эти инструменты отлично решают проблему деплоя, но всё равно это не то, что я хотел. Dokku хорош тем, что всё остаётся на твоём сервере. Но у меня всё равно оставалось ощущение, что я опять живу в терминале и вручную сопровождаю инфраструктуру. Heroku, Railway, Render и похожие сервисы удобны, но это уже их инфраструктура, ограничения и ценник. А мне хотелось немного другого: оставить проект на своём VPS [1], но сделать деплой таким же простым, как на PaaS‑платформах.

Кому интересен код, сервис:
Гитхаб с bash‑скриптами: https://github.com/slime4ik/djaploy‑scripts [2]
Веб‑интерфейс, который вырос: https://djaploy.dev [3]

Автор: Slime4ik

Источник [4]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/python/454319

Ссылки в тексте:

[1] VPS: https://www.reg.ru/?rlink=reflink-717

[2] https://github.com/slime4ik/djaploy‑scripts: https://github.com/slime4ik/djaploy-scripts

[3] https://djaploy.dev: https://djaploy.dev

[4] Источник: https://habr.com/ru/articles/1054822/?utm_source=habrahabr&utm_medium=rss&utm_campaign=1054822