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 на Вашу електронну пошту:
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
Ця роль відповідає за базове налаштування сервера: оновлення пакетів, встановлення необхідних утиліт та налаштування мережевої безпеки. Вона створює надійну основу для наступних кроків автоматизації.
Оновлення системи, встановлення залежностей та налаштування фаєрвола:
# - оновлюємо кеш пакетів 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 перед запуском на робочих серверах, щоб уникнути непередбачених змін:
Для отримання додаткової інформації зверніться до офіційних джерел: