8.2.4 Автоматизация развертывания сайта с помощью Ansible на VPS
Автоматизация процесса деплоя позволяет ускорить и упростить обновление приложений, особенно когда речь идёт о продакшн-сервере. В этом руководстве мы подробно рассмотрим, как с помощью Ansible развернуть Next.js-приложение на Ubuntu-сервере, используя роли, шаблоны, переменные.
Ansible — инструмент управления конфигурацией и автоматизации, который не требует установки агентов на целевых серверах. Он идеально подходит для развёртывания Node.js-приложений, таких как Next.js, в Linux-окружении.
Требования
- Услуга Виртуального сервера или Выделенного сервера;
- Ubuntu-сервер с SSH-доступом;
- Установленный Ansible на локальной машине;
- SSH-ключ для подключения к серверу.
Генерация SSH-ключа
Перед подключением Ansible к серверу по SSH необходимо создать пару ключей, если она ещё не создана. Это обеспечит безопасное и автоматизированное подключение к удалённому серверу.
Выполните команду заменив your_email@example.com на Ваш email:
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
Затем добавьте публичный ключ в файл ~/.ssh/authorized_keys на вашем сервере :
# замените user на имя Вашего пользователя на сервере и IP на ip Вашего сервера
ssh-copy-id -i ~/.ssh/id_rsa.pub user@IP
После этого Ansible сможет подключаться к серверу без ввода пароля.
Локальная установка Ansible
Ansible устанавливается на локальной машине разработчика или администратора, а не на целевой сервер. Он управляет удалёнными серверами через SSH, поэтому нет необходимости устанавливать Ansible на каждую машину, на которую вы хотите развернуть приложение.
sudo apt update
sudo apt install software-properties-common
sudo add-apt-repository --yes --update ppa:ansible/ansible
sudo apt install ansible
Эти команды нужно выполнить на вашей локальной машине, откуда будет запускаться Ansible.
Структура проекта Ansible
nextjs-deploy/
├── ansible.cfg # Основной конфигурационный файл Ansible
├── inventory.ini # Инвентарь с IP-адресами и данными для подключения к серверам
├── playbook.yml # Главный сценарий, описывающий порядок выполнения ролей
└── roles/ # Каталог с ролями, каждая из которых выполняет отдельную часть автоматизации
├── common/ # Роль, выполняющая базовую подготовку сервера
│ ├── handlers/ # Обработчики событий (например, рестарт служб)
│ └── tasks/ # Основные задачи: установка пакетов, настройка фаервола и т.д.
├── nodejs/ # Роль для установки Node.js и PM2
│ └── tasks/ # Задачи по установке Node.js и вспомогательных инструментов
└── nextjs/ # Роль, управляющая деплоем самого Next.js-приложения
├── handlers/ # Обработчики (например, перезапуск PM2)
└── tasks/ # Задачи: клонирование репозитория, установка зависимостей, сборка и конфигурация
Настройка инвентаря
Инвентарь в Ansible — это файл, в котором описаны адреса серверов и параметры подключения к ним. Он необходим для указания целевых машин, на которые будут выполняться автоматизированные действия. Здесь мы опишем IP-адрес сервера, пользователя и путь к приватному SSH-ключу.
# Необходимо заменить IP, user, id_rsa_path на ip адрес Вашего сервера, имя пользователя и путь до файла с ssh-ключем.
[web_servers]
web1 ansible_host=IP_СЕРВЕРА ansible_user=user ansible_ssh_private_key_file=id_rsa_path
[all:vars]
ansible_python_interpreter=/usr/bin/python3
Основной playbook
Playbook — это основной сценарий, в котором Ansible описывает, какие действия нужно выполнить на целевых серверах. В данном случае он управляет последовательностью ролей, необходимых для полного развертывания Next.js-приложения.
- name: Deploy NextJS application to Ubuntu server
hosts: web_servers
become: yes
roles:
- common
- nodejs
- nextjs
Роли Ansible
В Ansible роли используются для структурирования кода автоматизации. Каждая роль содержит в себе конкретную задачу, такую как установка Node.js, настройка nginx или клонирование приложения. Это помогает сделать playbook модульным, легко читаемым и повторно используемым.
Роль common
Эта роль отвечает за базовую настройку сервера: обновление пакетов, установку необходимых утилит и настройку сетевой безопасности. Она создаёт надёжную основу для последующих шагов автоматизации.
Обновление системы, установка зависимостей и настройка firewall:
# - обновляем кэш пакетов apt
- name: Update apt cache
apt: update_cache: yes
# - устанавливаем полезные утилиты, такие как git, curl, nginx и другие системные зависимости
- name: Install packages
apt:
name:
- git
- curl
- build-essential
- nginx
- ufw
state: present
# - настраиваем фаервол UFW, открывая доступ только для SSH и HTTP/HTTPS
- name: Enable UFW and allow Nginx/SSH
ufw:
rule: allow
name: "{{ item }}"
loop:
- OpenSSH
- "Nginx Full"
# - включаем фаервол с политикой запрета всех неразрешённых соединений по умолчанию
- name: Enable firewall
ufw:
state: enabled
policy: deny
Роль nodejs
Установка Node.js и PM2:
# - подключаем внешний репозиторий NodeSource для установки актуальной версии Node.js;
- name: Add NodeSource repository
shell: curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
# - устанавливаем сам Node.js из репозитория;
- name: Install Node.js
apt:
name: nodejs
state: present
# - устанавливаем PM2 — процесс-менеджер, необходимый для управления и перезапуска Next.js-приложения в продакшене.
- name: Install PM2
npm:
name: pm2
global: yes
Роль nextjs
Скачивание, установка, сборка, запуск:
# - клонируем репозиторий Next.js-приложения из Git;
- name: Clone repo
git:
repo: "{{ nextjs_repo_url }}"
dest: "{{ nextjs_app_path }}"
version: "{{ nextjs_repo_branch }}"
notify: restart nextjs application
# - устанавливаем все зависимости с помощью npm;
- name: Install dependencies
npm:
path: "{{ nextjs_app_path }}"
state: present
# - выполняем сборку production-версии приложения;
- name: Build NextJS
shell: cd {{ nextjs_app_path }} && npm run build
# - создаём конфигурационный файл PM2, описывающий, как запускать приложение;
- name: Create PM2 config
template:
src: pm2-config.json.j2
dest: "{{ nextjs_app_path }}/pm2-config.json"
# - настраиваем nginx как обратный прокси для доступа к приложению по домену;
- name: Configure Nginx
template:
src: nginx-site.conf.j2
dest: /etc/nginx/sites-available/{{ nextjs_app_name }}
# - активируем конфигурацию nginx, добавив символическую ссылку в каталог `sites-enabled`.
- name: Enable Nginx site
file:
src: /etc/nginx/sites-available/{{ nextjs_app_name }}
dest: /etc/nginx/sites-enabled/{{ nextjs_app_name }}
state: link
Переменные приложения
nextjs_app_name: my-nextjs-app # Название Next.js-приложения, которое будет использоваться в PM2 и nginx
nextjs_app_path: ~/www/my-nextjs-app # Путь на сервере, где будет размещено приложение
nextjs_app_port: 3000 # Порт, на котором будет работать приложение внутри контейнера/на сервере
nextjs_repo_url: https://github.com/youruser/repo.git # Ссылка на репозиторий с кодом приложения
nextjs_repo_branch: main # Ветка Git, из которой будет клонироваться приложение
nextjs_domain_name: example.com # Домен, по которому будет доступно приложение через Nginx
Шаблоны (templates)
Шаблоны в Ansible используются для генерации конфигурационных файлов с переменными, подставляемыми во время выполнения. Это позволяет гибко адаптировать конфигурации под разные окружения и упрощает развёртывание. В данном проекте мы используем шаблоны для настройки PM2 и Nginx.
Этот шаблон создаёт конфигурационный файл для PM2 — процесс-менеджера, который будет управлять запуском Next.js-приложения в продакшене.
{
"apps": [{
"name": "{{ nextjs_app_name }}",
"script": "npm",
"args": "start",
"cwd": "{{ nextjs_app_path }}",
"instances": "max",
"exec_mode": "cluster",
"env": {
"NODE_ENV": "production",
"PORT": "{{ nextjs_app_port }}"
}
}]
}
Шаблон описывает конфигурацию виртуального хоста Nginx, который будет выполнять роль обратного прокси для Next.js-приложения.
server {
listen 80;
server_name {{ nextjs_domain_name }};
location / {
proxy_pass http://localhost:{{ nextjs_app_port }};
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
Выполните следующую команду для проверки playbook и развёртывания приложения.
ansible-playbook -i inventory.ini playbook.yml --check
Совет: Всегда проверяйте свои плейбуки с флагом –check перед запуском на рабочих серверах, чтобы избежать непредвиденных изменений:
Для получения дополнительной информации обратитесь к оффициальным источникам: