Compare commits

..

No commits in common. "9b726465372b50ad21b9c599909f2c193fd279bd" and "4709d4c0e77fc2e97118af52836114de3081da22" have entirely different histories.

13 changed files with 88 additions and 338 deletions

182
README.md
View File

@ -2,33 +2,28 @@
## Обзор ## Обзор
Этот репозиторий содержит проект Ansible, интегрированный с Jenkins, для автоматизации развёртывания двух веб-сайтов (`SiteA` и `SiteB`) и прокси-сервера (`Proxy`). Настройка обеспечивает балансировку нагрузки, автоматические проверки состояния (health checks) и динамическое обновление контента без ручного вмешательства. Дополнительно внедрены обработчики для перезапуска служб при изменении конфигурации и централизованное управление основным конфигурационным файлом Nginx через `group_vars`. Этот репозиторий содержит проект Ansible, интегрированный с Jenkins, для автоматизации развёртывания двух веб-сайтов (`SiteA` и `SiteB`) и прокси-сервера (`Proxy`). Настройка обеспечивает балансировку нагрузки, автоматические проверки состояния (health checks) и динамическое обновление контента без ручного вмешательства.
## Описание Компонентов ## Описание Структуры
- **group_vars/**: Содержит файлы с переменными групп хостов. В `all.yml` определены общие переменные для всех ролей и хостов, включая параметры для Nginx и контент для сайтов. - **group_vars/**: Содержит файлы с переменными групп хостов. В данном случае `all.yml` содержит общие переменные для всех ролей и хостов.
- **roles/**: Основная директория с ролями Ansible. - **roles/**: Основная директория с ролями Ansible.
- **firewall/**: Роль для настройки и конфигурирования файрвола (`firewalld`), открытия необходимых портов.
- **firewall/**: - **tasks/**: Задачи для установки и настройки `firewalld`.
- **handlers/**: Содержит обработчики для перезапуска `firewalld`.
- **tasks/**: Задачи для установки и настройки `firewalld`, открытия необходимых портов.
- **vars/**: Переменные, используемые в роли `firewall`. - **vars/**: Переменные, используемые в роли `firewall`.
- **nginx_proxy/**: - **nginx_proxy/**: Роль для установки и настройки Nginx как прокси-сервера с балансировкой нагрузки и проверкой состояния.
- **handlers/**: Содержит обработчики для перезапуска Nginx. - **tasks/**: Задачи для установки Nginx и деплоя конфигурации прокси.
- **tasks/**: Задачи для установки Nginx, создания директорий, деплоя конфигураций и тестирования конфигурации. - **templates/**: Шаблоны конфигурационных файлов Nginx для прокси-сервера.
- **templates/**: Шаблоны конфигурационных файлов Nginx для прокси-сервера и страниц ошибок.
- **nginx_site/**: - **nginx_site/**: Роль для установки и настройки Nginx на целевых сайтах (`SiteA` и `SiteB`), а также деплоя HTML контента.
- **handlers/**: Содержит обработчики для перезапуска Nginx. - **tasks/**: Задачи для установки Nginx, создания корневых директорий сайтов, деплоя конфигураций и HTML файлов.
- **tasks/**: Задачи для установки Nginx, создания корневых директорий сайтов, деплоя конфигураций и HTML файлов, а также тестирования конфигурации.
- **templates/**: Шаблоны конфигурационных файлов Nginx и HTML страниц для сайтов. - **templates/**: Шаблоны конфигурационных файлов Nginx и HTML страниц для сайтов.
- **ssl_certificate/**: - **ssl_certificate/**: Роль для генерации самоподписанных SSL сертификатов для прокси-сервера.
- **handlers/**: Содержит обработчики для перезапуска Nginx после генерации SSL сертификатов.
- **tasks/**: Задачи для установки OpenSSL, создания директории для сертификатов и генерации самоподписанных сертификатов. - **tasks/**: Задачи для установки OpenSSL, создания директории для сертификатов и генерации самоподписанных сертификатов.
- **templates/**: Шаблоны или скрипты для генерации SSL сертификатов. - **vars/**: Переменные, используемые в роли `ssl_certificate`.
- **playbook.yml**: Основной Ansible playbook, который связывает все роли и определяет порядок их выполнения на соответствующих хостах. - **playbook.yml**: Основной Ansible playbook, который связывает все роли и определяет порядок их выполнения на соответствующих хостах.
@ -36,52 +31,33 @@
- **ansible.cfg**: Конфигурационный файл Ansible, определяющий пути к ролям и другие настройки. - **ansible.cfg**: Конфигурационный файл Ansible, определяющий пути к ролям и другие настройки.
- **jenkinsfile**: Скрипт для Jenkins Pipeline, который управляет процессом деплоя, включая расшифровку SSH ключей, передачу переменных и запуск Ansible playbook. - **Jenkinsfile**: Скрипт для Jenkins Pipeline, который управляет процессом деплоя, включая расшифровку SSH ключей, передачу переменных и запуск Ansible playbook.
## Параметры и Их Назначение ## Параметры и Их Назначение
### В `group_vars/all.yml` ### В `group_vars/all.yml`
```yaml - **siteA**:
# group_vars/all.yml - `site_title`: Заголовок страницы SiteA.
ansible_python_interpreter: /usr/bin/python3.6 - `site_h1`: Основной заголовок `<h1>` на странице SiteA.
- `site_h2`: Дополнительный заголовок `<h2>` для SiteA.
- `site_p`: Параграф `<p>` контента для SiteA.
- `site_domain`: Доменное имя SiteA.
- `site_ip`: IP-адрес сервера SiteA.
# Общие переменные для Nginx - **siteB**:
nginx_worker_processes: auto - `site_title`: Заголовок страницы SiteB.
nginx_error_log: /var/log/nginx/error.log - `site_h1`: Основной заголовок `<h1>` на странице SiteB.
nginx_error_log_level: warn - `site_h2`: Дополнительный заголовок `<h2>` для SiteB.
nginx_worker_connections: 1024 - `site_p`: Параграф `<p>` контента для SiteB.
nginx_access_log: /var/log/nginx/access.log - `site_domain`: Доменное имя SiteB.
nginx_keepalive_timeout: 65 - `site_ip`: IP-адрес сервера SiteB.
nginx_types_hash_max_size: 2048
# Переменные для сайтов SiteA и SiteB - **proxy**:
siteA: - `proxy_domain`: Доменное имя прокси-сервера.
site_title: "SiteA - Добро пожаловать" - `proxy_ip`: IP-адрес прокси-сервера.
site_h1: "Добро пожаловать на SiteA"
site_h2: "Дефолтный заголовок H2 для SiteA"
site_p: "Дефолтный параграф для SiteA"
site_domain: "siteA.example.com"
site_ip: "192.168.0.61"
siteB: - **ansible_python_interpreter**: Явное указание пути к Python-интерпретатору на всех хостах.
site_title: "SiteB - Добро пожаловать"
site_h1: "Добро пожаловать на SiteB"
site_h2: "Дефолтный заголовок H2 для SiteB"
site_p: "Дефолтный параграф для SiteB"
site_domain: "siteB.example.com"
site_ip: "192.168.0.62"
proxy:
proxy_domain: "proxy.example.com"
proxy_ip: "192.168.0.63"
# SSL переменные
ssl_cert_path: "/etc/nginx/ssl"
ssl_cert_file: "proxy.crt"
ssl_key_file: "proxy.key"
ssl_subject: "/C=RU/ST=Some-State/L=Some-City/O=Your Company/CN={{ proxy.proxy_domain }}"
```
### В `Jenkinsfile` ### В `Jenkinsfile`
@ -125,98 +101,4 @@ all:
hosts: hosts:
192.168.0.63: 192.168.0.63:
ansible_user: ansible ansible_user: ansible
ansible_python_interpreter: /usr/bin/python3.6 ansible_python_interpreter: /usr/bin/python3.6
```
### Настройка Переменных
Все переменные, используемые в проектах, определены в `group_vars/all.yml`. При необходимости, вы можете переопределить их через Jenkins параметры или добавить дополнительные переменные.
### Запуск Jenkins Pipeline
1. **Дешифровка SSH ключей**: Jenkins автоматически расшифровывает SSH ключи для доступа к серверам.
2. **Выбор Цели Развертывания**: Выберите, какой сайт (`SiteA`, `SiteB`) или все (`All`) нужно развернуть.
3. **Передача Дополнительных Переменных**: Введите дополнительные параметры контента для выбранных сайтов.
4. **Запуск Ansible Playbook**: Jenkins запускает Ansible playbook с переданными параметрами, развертывая конфигурации и контент на целевых хостах.
## Проверка и Отладка
Если при развертывании возникают ошибки:
1. **Просмотрите Логи Jenkins**: Получите подробную информацию об ошибках.
2. **Подключитесь к Целевым Серверам**: Проверьте статус служб и конфигурационных файлов.
```bash
systemctl status nginx
systemctl status firewalld
```
3. **Проверьте Конфигурацию Nginx**: Убедитесь, что конфигурационные файлы корректны.
```bash
nginx -t
```
4. **Просмотрите Логи Nginx**:
```bash
sudo journalctl -xeu nginx.service
sudo tail -n 100 /var/log/nginx/error.log
```
### Пример Запуска Playbook Локально
Для локального тестирования или отладки вы можете запустить playbook вручную:
```bash
ansible-playbook playbook.yml
```
## Дополнительные Возможности
- **Автоматическое Тестирование Конфигураций**: Playbook включает задачи для тестирования конфигурации Nginx перед запуском службы, предотвращая запуск с ошибками.
- **Обработчики (Handlers)**: Автоматический перезапуск служб `nginx` и `firewalld` при изменении конфигурационных файлов.
- **Централизованное Управление Конфигурацией**: Основной конфигурационный файл Nginx управляется через шаблоны и переменные в `group_vars/all.yml`.
## Рекомендации и Лучшие Практики
1. **Безопасность**:
- Используйте Ansible Vault для защиты чувствительных данных.
- Убедитесь, что SSH ключи и другие секреты не попадают в систему контроля версий.
2. **Документация**:
- Поддерживайте актуальную документацию, описывающую структуру проекта и инструкции по развертыванию.
3. **Тестирование**:
- Используйте инструменты вроде [Molecule](https://molecule.readthedocs.io/en/latest/) для тестирования Ansible ролей.
- Внедрите проверку конфигураций перед применением изменений.
4. **Управление Конфигурациями**:
- Централизуйте общие конфигурационные файлы для облегчения управления и уменьшения дублирования.
- Используйте обработчики для автоматического применения изменений.
5. **Мониторинг и Логирование**:
- Внедрите системы мониторинга для отслеживания состояния сервисов.
- Анализируйте логи для своевременного обнаружения и устранения проблем.
## Заключение
Этот проект демонстрирует эффективное использование Ansible и Jenkins для автоматизации развёртывания веб-сайтов и прокси-сервера с учётом безопасности, надёжности и удобства управления. Следуя приведённым инструкциям и рекомендациям, вы сможете быстро адаптировать и расширять данное решение под свои нужды.
Если у вас возникнут дополнительные вопросы или потребуется помощь с настройкой, не стесняйтесь обращаться!
---
**Примечания:**
- Убедитесь, что все переменные правильно определены и соответствуют вашим требованиям.
- При необходимости, обновите пути и имена файлов в соответствии с вашей инфраструктурой.
- Для улучшения безопасности рассмотрите использование Ansible Vault для хранения чувствительных данных, таких как SSH ключи и пароли.
Если возникнут дополнительные вопросы или потребуется помощь с настройкой, не стесняйтесь обращаться!

57
ansible/Jenkinsfile vendored
View File

@ -13,27 +13,22 @@ pipeline {
parameters { parameters {
choice( choice(
name: 'DEPLOY_TARGET', name: 'DEPLOY_TARGET',
choices: ['SiteA', 'SiteB', 'proxy', 'SiteA&proxy', 'SiteB&proxy', 'All'], choices: ['SiteA', 'SiteB', 'All'],
description: 'Выберите цели для развертывания' description: 'Выберите сайты для развертывания'
) )
string( string(name: 'ADDITIONAL_CONTENT_SITEA_H2', defaultValue: 'Новое сообщение для SiteA', description: 'Дополнительный <h2> контент для SiteA')
name: 'ADDITIONAL_CONTENT_H2', string(name: 'ADDITIONAL_CONTENT_SITEA_P', defaultValue: 'Дополнительный параграф для SiteA', description: 'Дополнительный <p> контент для SiteA')
defaultValue: 'Новое сообщение',
description: 'Дополнительный <h2> контент' string(name: 'ADDITIONAL_CONTENT_SITEB_H2', defaultValue: 'Новое сообщение для SiteB', description: 'Дополнительный <h2> контент для SiteB')
) string(name: 'ADDITIONAL_CONTENT_SITEB_P', defaultValue: 'Дополнительный параграф для SiteB', description: 'Дополнительный <p> контент для SiteB')
string(
name: 'ADDITIONAL_CONTENT_P',
defaultValue: 'Дополнительный параграф',
description: 'Дополнительный <p> контент'
)
} }
stages { stages {
stage('Decrypt SSH Key') { stage('Decrypt SSH Key') {
steps { steps {
script { script {
def tempDir = "/tmp/${UUID.randomUUID().toString()}" def tempDir = '/tmp/' + UUID.randomUUID().toString()
env.TEMP_DIR = tempDir env.TEMP_DIR = tempDir
sh "mkdir -p ${tempDir}" sh "mkdir -p ${tempDir}"
@ -43,7 +38,7 @@ pipeline {
writeFile file: vaultPassFile, text: VAULT_PASSWORD writeFile file: vaultPassFile, text: VAULT_PASSWORD
sh """ sh """
ansible-vault decrypt ./ansible/id_ed25519_vault --output=${decryptedKeyFile} --vault-password-file=${vaultPassFile} ansible-vault decrypt ./ansible/id_ed25519_vault --output=${decryptedKeyFile} --vault-password-file=${vaultPassFile}
""" """
env.DECYPTED_KEY_FILE = decryptedKeyFile env.DECYPTED_KEY_FILE = decryptedKeyFile
@ -61,34 +56,21 @@ pipeline {
switch(params.DEPLOY_TARGET) { switch(params.DEPLOY_TARGET) {
case 'SiteA': case 'SiteA':
selectedHosts = 'SiteA' selectedHosts = 'SiteA,proxy'
extraVars.siteA_h2 = params.ADDITIONAL_CONTENT_H2 extraVars.siteA_h2 = params.ADDITIONAL_CONTENT_SITEA_H2
extraVars.siteA_p = params.ADDITIONAL_CONTENT_P extraVars.siteA_p = params.ADDITIONAL_CONTENT_SITEA_P
break break
case 'SiteB': case 'SiteB':
selectedHosts = 'SiteB'
extraVars.siteB_h2 = params.ADDITIONAL_CONTENT_H2
extraVars.siteB_p = params.ADDITIONAL_CONTENT_P
break
case 'proxy':
selectedHosts = 'proxy'
break
case 'SiteA&proxy':
selectedHosts = 'SiteA,proxy'
extraVars.siteA_h2 = params.ADDITIONAL_CONTENT_H2
extraVars.siteA_p = params.ADDITIONAL_CONTENT_P
break
case 'SiteB&proxy':
selectedHosts = 'SiteB,proxy' selectedHosts = 'SiteB,proxy'
extraVars.siteB_h2 = params.ADDITIONAL_CONTENT_H2 extraVars.siteB_h2 = params.ADDITIONAL_CONTENT_SITEB_H2
extraVars.siteB_p = params.ADDITIONAL_CONTENT_P extraVars.siteB_p = params.ADDITIONAL_CONTENT_SITEB_P
break break
case 'All': case 'All':
selectedHosts = 'SiteA,SiteB,proxy' selectedHosts = 'SiteA,SiteB,proxy'
extraVars.siteA_h2 = params.ADDITIONAL_CONTENT_H2 extraVars.siteA_h2 = params.ADDITIONAL_CONTENT_SITEA_H2
extraVars.siteA_p = params.ADDITIONAL_CONTENT_P extraVars.siteA_p = params.ADDITIONAL_CONTENT_SITEA_P
extraVars.siteB_h2 = params.ADDITIONAL_CONTENT_H2 extraVars.siteB_h2 = params.ADDITIONAL_CONTENT_SITEB_H2
extraVars.siteB_p = params.ADDITIONAL_CONTENT_P extraVars.siteB_p = params.ADDITIONAL_CONTENT_SITEB_P
break break
default: default:
error "Неизвестный DEPLOY_TARGET: ${params.DEPLOY_TARGET}" error "Неизвестный DEPLOY_TARGET: ${params.DEPLOY_TARGET}"
@ -98,8 +80,7 @@ pipeline {
playbook: 'ansible/playbook.yml', playbook: 'ansible/playbook.yml',
inventory: "ansible/inventory.yml", inventory: "ansible/inventory.yml",
extraVars: extraVars, extraVars: extraVars,
limit: selectedHosts, limit: selectedHosts
colorized: true
) )
} }
} }

View File

@ -1,12 +1,9 @@
ansible_python_interpreter: /usr/bin/python3.6 ansible_python_interpreter: /usr/bin/python3.6
nginx_worker_processes: auto siteA_h2: "Дефолтный заголовок H2 для SiteA"
nginx_error_log: /var/log/nginx/error.log siteA_p: "Дефолтный параграф для SiteA"
nginx_error_log_level: warn siteB_h2: "Дефолтный заголовок H2 для SiteB"
nginx_worker_connections: 1024 siteB_p: "Дефолтный параграф для SiteB"
nginx_access_log: /var/log/nginx/access.log
nginx_keepalive_timeout: 65
nginx_types_hash_max_size: 2048
siteA: siteA:
site_title: "SiteA - Добро пожаловать" site_title: "SiteA - Добро пожаловать"
@ -26,9 +23,4 @@ siteB:
proxy: proxy:
proxy_domain: "proxy.example.com" proxy_domain: "proxy.example.com"
proxy_ip: "192.168.0.63" proxy_ip: "192.168.0.63"
siteA_h2: "Новое сообщение для SiteA"
siteA_p: "Дополнительный параграф для SiteA"
siteB_h2: "Новое сообщение для SiteB"
siteB_p: "Дополнительный параграф для SiteB"

View File

@ -1,4 +0,0 @@
- name: Restart firewalld
systemd:
name: firewalld
state: restarted

View File

@ -2,16 +2,12 @@
zypper: zypper:
name: firewalld name: firewalld
state: present state: present
notify:
- Restart firewalld
- name: Ensure firewalld is enabled and started - name: Ensure firewalld is enabled and started
systemd: systemd:
name: firewalld name: firewalld
enabled: yes enabled: yes
state: started state: started
notify:
- Restart firewalld
- name: Open specified firewall ports - name: Open specified firewall ports
firewalld: firewalld:
@ -19,6 +15,4 @@
permanent: yes permanent: yes
state: enabled state: enabled
immediate: yes immediate: yes
loop: "{{ firewall_ports }}" loop: "{{ firewall_ports }}"
notify:
- Restart firewalld

View File

@ -1,4 +0,0 @@
- name: Restart Nginx
systemd:
name: nginx
state: restarted

View File

@ -2,8 +2,12 @@
zypper: zypper:
name: nginx name: nginx
state: present state: present
notify:
- Restart Nginx - name: Ensure Nginx is enabled and started
systemd:
name: nginx
enabled: yes
state: started
- name: Create directory for error pages - name: Create directory for error pages
file: file:
@ -12,36 +16,19 @@
owner: nginx owner: nginx
group: nginx group: nginx
mode: '0755' mode: '0755'
notify:
- Restart Nginx
- name: Deploy custom error page - name: Deploy custom error page
template: template:
src: site_down.html.j2 src: site_down.html.j2
dest: /var/www/errors/site_down.html dest: /var/www/errors/site_down.html
mode: '0644' mode: '0644'
notify:
- Restart Nginx
- name: Deploy Proxy Configuration - name: Deploy Proxy Configuration
template: template:
src: proxy.conf.j2 src: proxy.conf.j2
dest: /etc/nginx/conf.d/proxy.conf dest: /etc/nginx/conf.d/proxy.conf
notify:
- Restart Nginx
- name: Deploy Main Nginx Configuration - name: Reload Nginx
template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
mode: '0644'
notify:
- Restart Nginx
- name: Ensure Nginx is enabled and started
systemd: systemd:
name: nginx name: nginx
enabled: yes state: reloaded
state: started
notify:
- Restart Nginx

View File

@ -1,27 +0,0 @@
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
include /etc/nginx/conf.d/*.conf;
}

View File

@ -9,11 +9,6 @@ upstream backend {
server { server {
listen 80; listen 80;
server_name {{ proxy.proxy_domain }};
return 301 https://$host$request_uri;
}
server {
listen 443 ssl; listen 443 ssl;
server_name {{ proxy.proxy_domain }}; server_name {{ proxy.proxy_domain }};

View File

@ -1,4 +0,0 @@
- name: Restart Nginx
systemd:
name: nginx
state: restarted

View File

@ -2,32 +2,12 @@
zypper: zypper:
name: nginx name: nginx
state: present state: present
notify:
- Restart Nginx
- name: Deploy Main Nginx Configuration - name: Ensure Nginx is enabled and started
template: systemd:
src: nginx.conf.j2 name: nginx
dest: /etc/nginx/nginx.conf enabled: yes
mode: '0644' state: started
notify:
- Restart Nginx
- name: Deploy SiteA Configuration
template:
src: siteA.conf.j2
dest: /etc/nginx/conf.d/siteA.conf
when: "'SiteA' in group_names"
notify:
- Restart Nginx
- name: Deploy SiteB Configuration
template:
src: siteB.conf.j2
dest: /etc/nginx/conf.d/siteB.conf
when: "'SiteB' in group_names"
notify:
- Restart Nginx
- name: Create web root for SiteA - name: Create web root for SiteA
file: file:
@ -37,8 +17,6 @@
group: nginx group: nginx
mode: '0755' mode: '0755'
when: "'SiteA' in group_names" when: "'SiteA' in group_names"
notify:
- Restart Nginx
- name: Create web root for SiteB - name: Create web root for SiteB
file: file:
@ -48,8 +26,18 @@
group: nginx group: nginx
mode: '0755' mode: '0755'
when: "'SiteB' in group_names" when: "'SiteB' in group_names"
notify:
- Restart Nginx - name: Deploy SiteA Configuration
template:
src: siteA.conf.j2
dest: /etc/nginx/conf.d/siteA.conf
when: "'SiteA' in group_names"
- name: Deploy SiteB Configuration
template:
src: siteB.conf.j2
dest: /etc/nginx/conf.d/siteB.conf
when: "'SiteB' in group_names"
- name: Deploy SiteA HTML - name: Deploy SiteA HTML
template: template:
@ -61,8 +49,6 @@
site_h2: "{{ siteA.site_h2 }}" site_h2: "{{ siteA.site_h2 }}"
site_p: "{{ siteA.site_p }}" site_p: "{{ siteA.site_p }}"
when: "'SiteA' in group_names" when: "'SiteA' in group_names"
notify:
- Restart Nginx
- name: Deploy SiteB HTML - name: Deploy SiteB HTML
template: template:
@ -74,13 +60,8 @@
site_h2: "{{ siteB.site_h2 }}" site_h2: "{{ siteB.site_h2 }}"
site_p: "{{ siteB.site_p }}" site_p: "{{ siteB.site_p }}"
when: "'SiteB' in group_names" when: "'SiteB' in group_names"
notify:
- Restart Nginx
- name: Ensure Nginx is enabled and started - name: Reload Nginx
systemd: systemd:
name: nginx name: nginx
enabled: yes state: reloaded
state: started
notify:
- Restart Nginx

View File

@ -1,27 +0,0 @@
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
include /etc/nginx/conf.d/*.conf;
}

View File

@ -0,0 +1,4 @@
siteA_h2: "Дефолтный заголовок H2 для SiteA"
siteA_p: "Дефолтный параграф для SiteA"
siteB_h2: "Дефолтный заголовок H2 для SiteB"
siteB_p: "Дефолтный параграф для SiteB"