Если у тебя всего один сайт и один сервер, всё выглядит элементарно: подключился по SSH, поставил nginx, PHP, подправил конфиги - и готово.
Но как только проектов становится больше, эта рутина начинает съедать время и порождать ошибки.
Я постоянно ловил себя на том, что повторяю одни и те же шаги:
ставлю nginx из официального репозитория (а не из пакетов дистрибутива, чтобы всегда иметь свежую версию)
создаю отдельный PHP-FPM пул под каждый сайт с собственным Unix-сокетом
настраиваю OPcache, лимиты, таймауты
прописываю виртуальные хосты nginx с корректными заголовками безопасности
ставлю Composer, Node.js, Yarn
создаю структуру директорий под Laravel
добавляю cron для artisan schedule:run
И всё это - вручную. Каждый раз. И каждый раз есть шанс что-то забыть или сделать иначе, чем на предыдущем сервере.
Почему Ansible, а не Docker?
Вопрос логичный. Docker действительно удобен, когда нужна изоляция и переносимость.
Но в реальности часто встречаются ситуации, когда контейнеры - лишняя сложность:
VDS с ограниченными ресурсами
хостинг без поддержки Docker
проекты, где нужен прямой доступ к системе
обслуживание legacy-серверов
Ansible же работает с любым Linux-сервером через SSH. Никаких агентов, никакой дополнительной инфраструктуры - только Python на целевой машине.
Что получилось в итоге
Я собрал роль nginx_laravel, которая разворачивает полноценную среду для Laravel одной командой:
ansible-playbook site.ymlЧто делает роль:
устанавливает nginx из официального репозитория nginx.org
автоматически определяет последнюю стабильную ветку (1.26.x, 1.28.x и т.д.)
ставит PHP 8.4 (или любую >= 8.2) из ondrej/php или Remi
создаёт отдельный PHP-FPM пул для каждого сайта
поддерживает список сайтов - роль сама создаёт нужные конфиги
добавляет сайт по умолчанию (catch-all) с информацией о сервере
включает базовые заголовки безопасности
защищает .env, .git, vendor
интегрируется с GitLab CI/CD
CI/CD: автоматизация, которая экономит время
Я хотел добиться простого принципа: любое изменение в репозитории должно быть проверено автоматически, а деплой выполняется только если всё прошло успешно.
Пайплайн состоит из трёх стадий: validate → deploy → verify.
validate ──────────────────────────────────────────────────────┐
yaml-lint ──┐ │
lint ├── все три параллельно │
syntax-check ─┘ │
▼
deploy ────────────────────────────────────────────────────────┐
deploy:production (только если validate прошёл) │
▼
verify ────────────────────────────────────────────────────────┘
verify:sites (только если deploy прошёл)Validate
Запускается на каждый push и merge request.
Состоит из трёх параллельных задач:
yaml-lint - проверяет синтаксис YAML
ansible-lint - анализирует плейбуки на ошибки и антипаттерны
syntax-check - проверяет структуру плейбука без подключения к серверу
yamllint --config-file .yamllint.yml --format colored $(find . -name '*.yml' -o -name '*.yaml')
ansible-playbook site.yml --syntax-check --inventory inventory/hosts.ymlDeploy
Запускается только при пуше в main.
Использует resource_group: production, чтобы не было параллельных деплоев.
Что происходит:
Поднимается ssh-agent, загружается ключ
При необходимости расшифровываются секреты ansible-vault
Запускается плейбук с флагом --diff, чтобы в логах CI было видно изменения
Verify
После деплоя запускается проверка всех сайтов:
проверяется дефолтный сайт
проверяются именованные сайты через Host-заголовок
для HTTPS используется отключённая проверка сертификата (поддержка self-signed)
Если хоть один сайт не отвечает или возвращает 4xx/5xx - пайплайн падает.
Почему это важно
До внедрения пайплайна типичная ситуация выглядела так:
сделал изменение
запушил
через 10 минут проверяешь - сайт лежит
Теперь:
syntax-check ловит ошибки до деплоя
verify ловит проблемы сразу после деплоя
весь цикл занимает 3-4 минуты
Что мне кажется важным в дизайне
Конфигурация как данные, а не код. Вся конфигурация сайтов — это просто YAML в инвентаре:
laravel_sites:
- domain: "myapp.ru www.myapp.ru"
root: "/var/www/myapp"
ssl_enabled: true
ssl_email: "admin@myapp.ru"
env: productionДобавить сайт - просто добавить элемент в список.
Идемпотентность
Роль можно запускать сколько угодно раз - она не ломает уже настроенный сервер.
Несколько доменов на один сайт
Первый домен используется для сокета, логов и сертификата, остальные обслуживаются nginx.
Кроссплатформенность
Изначально роль была только под Debian/Ubuntu. Потом добавил поддержку AlmaLinux - достаточно было вынести OS-специфичные переменные в vars/.
Что ещё предстоит сделать
автоматический HTTPS через Let's Encrypt
опциональная установка PostgreSQL/MySQL
мониторинг через php-fpm status
автоматический деплой кода из репозитория (возможно через webhook)
Итог
Эта роль не заменяет понимание nginx и PHP-FPM, но отлично снимает рутину и делает настройку серверов предсказуемой и воспроизводимой.
Если у тебя несколько Laravel-проектов на VDS и ты всё ещё настраиваешь серверы вручную - попробуй. В худшем случае просто посмотри код - уверен, найдёшь что-то полезное.
Исходники: GitOps / ansible-web-server · GitLab




Станьте первым, кто прокомментирует эту запись