From d1ca83186548c60c12ceb0de07afbc9fd7e63fc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A1=D0=BE=D0=BB=D0=BE=D0=B2=D1=8C=D0=B5=D0=B2=20=D0=A0?= =?UTF-8?q?=D1=83=D1=81=D0=BB=D0=B0=D0=BD?= Date: Mon, 17 Aug 2026 03:06:32 +0300 Subject: [PATCH] =?UTF-8?q?feat:=20=D0=92=D1=8B=D0=BF=D0=BE=D0=BB=D0=BD?= =?UTF-8?q?=D0=B8=D0=BB=20=D0=BF=D1=80=D0=B0=D0=BA=D1=82=D0=B8=D1=87=D0=B5?= =?UTF-8?q?=D1=81=D0=BA=D0=BE=D0=B5=20=D0=B7=D0=B0=D0=B4=D0=B0=D0=BD=D0=B8?= =?UTF-8?q?=D0=B5=20=D0=BF=D0=BE=20DevOps?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 159 ++++++++++++++++++++++++++ ansible-playbook-repeat.log | 99 ++++++++++++++++ ansible-playbook.log | 99 ++++++++++++++++ hosts.yaml | 5 + playbook.yaml | 28 +++++ roles/nginx/files/.dockerignore | 10 ++ roles/nginx/files/Dockerfile | 12 ++ roles/nginx/files/backup.sh | 16 +++ roles/nginx/files/docker-compose.yaml | 13 +++ roles/nginx/files/index.html | 20 ++++ roles/nginx/files/nginx.conf | 24 ++++ roles/nginx/tasks/main.yaml | 103 +++++++++++++++++ roles/prepare-docker/tasks/main.yaml | 30 +++++ roles/prepare-key/tasks/main.yaml | 5 + roles/prepare-vm/tasks/main.yaml | 64 +++++++++++ secrets.yaml | 2 + 16 files changed, 689 insertions(+) create mode 100644 README.md create mode 100644 ansible-playbook-repeat.log create mode 100644 ansible-playbook.log create mode 100644 hosts.yaml create mode 100644 playbook.yaml create mode 100644 roles/nginx/files/.dockerignore create mode 100644 roles/nginx/files/Dockerfile create mode 100644 roles/nginx/files/backup.sh create mode 100644 roles/nginx/files/docker-compose.yaml create mode 100644 roles/nginx/files/index.html create mode 100644 roles/nginx/files/nginx.conf create mode 100644 roles/nginx/tasks/main.yaml create mode 100644 roles/prepare-docker/tasks/main.yaml create mode 100644 roles/prepare-key/tasks/main.yaml create mode 100644 roles/prepare-vm/tasks/main.yaml create mode 100644 secrets.yaml diff --git a/README.md b/README.md new file mode 100644 index 0000000..f0fa30a --- /dev/null +++ b/README.md @@ -0,0 +1,159 @@ + +# Тестовое задание SimbirSoft DevOps + +>[!NOTE] +>Соловьев Руслан +> +>Резюме - [HH](https://krasnodar.hh.ru/resume/b105319cff0f77ed050039ed1f5a4a4a733148) +> +>Узнать поднобнее - https://ruslansoloviev.ru + + +## Почему хочу девопсить + +Мне нравится DevOps за сочетание разработки и системного администрирования. Мне интересно не только написать приложение, но и разобраться, как оно будет развёрнуто, как автоматизировать этот процесс, обеспечить его стабильную работу и понять, что происходит с сервисом после его запуска. + +Именно поэтому со временем я стал больше заниматься инфраструктурной частью своих проектов: Docker, CI/CD, Kubernetes, мониторингом, сетями и автоматизацией. Особенно нравится автоматизировать повторяющиеся процессы и превращать ручную настройку в воспроизводимую конфигурацию. + +В дальнейшем я хочу развиваться именно как DevOps-инженер, работать с более крупной инфраструктурой и задачами, где требования к надёжности, автоматизации и наблюдаемости значительно выше, чем в моих текущих проектах. + +## Теоретическая часть + +1) Нужно обеспечить высокую доступность сервиса, как бы ее реализовал? +
+- Так как у нас технически в данном задании nginx раздает только статику я бы вообще убрал сервер как точку отказа и вынес статическую страницу в объектное хранилище S3 и подключил CDN, таким образом высокая доступность будет обеспечена силами облачного провайдера, а CDN ускорит доставку контента до пользователей и сократит затраты на GET операции в хранилище. +- Если же необходимо реализовать высокую доступность именно посредством серверов, то я бы поднял как минимум 2 экземпляра на разных ВМ в разных зонах доступности и повесил на них балансировщик с хелс чеками доступности каждой из ВМ что бы не слать трафик на заведомо мертвую ВМ, 2 AZ поскольку этого будет достаточно в большинстве случаем да и самому nginx не нужен кворум для работы +
+ +2) Тебе надо создать и настроить 5 таких серверов, как бы это реализовал? +
+ +- Так как я описал необходимое состояние ВМ в ansible плейбук то для настройки будет достаточно указать все ВМ в инвентаре плейбука, а для заказа смотря как управляется текущая инфраструктура - если там терраформ или что то похожее то в конфигурации описал бы необходимые 5 экземпляров, если ручками то заказываю в гипервизоре или панели клауд провайдера + +## Практическая часть + +В данном тестовом задании я использовал Ansible и для его воспроизводимости понадобятся сам Ansible и некоторые его коллекции, установить которые можно следующими командами: +
+ +**Debian/Ubuntu** +```sh +sudo apt update && sudo apt install -y ansible +``` + +**macOS** +```sh +brew install ansible +``` + +**Через pip** +```sh +python3 -m pip install ansible +``` + +```sh +ansible-galaxy collection install community.general +ansible-galaxy collection install community.crypto +ansible-galaxy collection install community.docker +``` + +В файле *hosts.yaml* необходимо указать адрес ВМ и пользователя, например + +```yaml +all: + hosts: + nginx: + ansible_host: 192.168.20.217 + ansible_user: rouxinol +``` + +Далее в файле *secrets.yaml* необходимо указать пароль для указаного ранее пользователя, а так же пароль для *sudo* для указаного пользователя, например: + +```yaml +ansible_password: "superpass123" +ansible_become_password: "superpass123" +``` + +Далее можно зашифровать этот файл: + +```sh +ansible-vault encrypt secrets.yaml +``` + +После всех действий можно запустить плейбук: + +```sh +ansible-playbook -i hosts.yaml playbook.yaml +``` + +> [!WARNING] +> Если был зашифрован secrets.yaml то необходимо так же добавить флаг ```--ask-vault-pass``` + +--- + +В качестве лабораторной работы я заказал ВМ с Ubuntu Server 24.04 с пользователем *rouxinol* в Proxmox VE, IP ВМ в локальной сети - 192.168.20.217 + +Логи выполнения плейбука можно посмотреть в [логе выполнения Ansible](./ansible-playbook.log) + +Логи повторного выполнения плейбука можно посмотреть в [логе повторного выполнения Ansible](./ansible-playbook-repeat.log) + +## Ремарки к практическим заданиям + +3) Продемонстрировать блокировку портов + +
+ +**Конечная конфирукция ufw с ВМ** +```log +rouxinol@rouxinol-testserver:/opt/nginx$ sudo ufw status verbose +Status: active +Logging: on (low) +Default: deny (incoming), allow (outgoing), deny (routed) +New profiles: skip + +To Action From +-- ------ ---- +22/tcp (OpenSSH) ALLOW IN Anywhere +80/tcp ALLOW IN Anywhere +443/tcp ALLOW IN Anywhere +22/tcp (OpenSSH (v6)) ALLOW IN Anywhere (v6) +80/tcp (v6) ALLOW IN Anywhere (v6) +443/tcp (v6) ALLOW IN Anywhere (v6) +``` + +**Nmap по привелигированным портам** + +```log +❯ nmap 192.168.20.217 +Starting Nmap 7.98 ( https://nmap.org ) at 2026-08-17 01:54 +0300 +Nmap scan report for 192.168.20.217 +Host is up (0.0029s latency). +Not shown: 997 filtered tcp ports (no-response) +PORT STATE SERVICE +22/tcp open ssh +80/tcp open http +443/tcp open https + +Nmap done: 1 IP address (1 host up) scanned in 43.31 seconds +``` + +6) Бекап каждый понедельник + +```log +root@rouxinol-testserver:/opt/nginx# crontab -l +CRON_TZ="UTC" +#Ansible: nginx configuration backup +0 1 * * 1 /opt/nginx/backup.sh +root@rouxinol-testserver:/opt/nginx# ./backup.sh +Successfully copied 25.1kB to /tmp/tmp.9hPGthi4R2/nginx +root@rouxinol-testserver:/opt/nginx# ls backups/ +nginx_2026-08-16_23-01-36.tar.gz nginx_2026-08-16_23-02-10.tar.gz +``` + +7) В Dockerfile указано запускать master-процесс от пользователя nginx, а так же в nginx,conf указано запускать worker-процессы так же от nginx, однако для этого были выбраны непривелигированные порты 8080 и 8443, однако можно было использовать образ nginxinc/nginx-unprivileged и не указывать ничего из этого и в Dockerfile есть закомментированный FROM этого образа - однако он не был выбран так как в Docker Hub нет нужной 1.29.6 версии - я подобрал ближайшую + +8) При запуске плейбука в его корне автоматически создается ssh ed25519 ключ без фразы пароля, для подключения к ВМ будет достаточно именно для моего тестового окружения следующей команды: +```sh +ssh -i ./id_ed25519_simbirkey rouxinol@192.168.20.217 +``` + +9) [Dockerfile тут](./roles/nginx/files/Dockerfile) diff --git a/ansible-playbook-repeat.log b/ansible-playbook-repeat.log new file mode 100644 index 0000000..cdd883c --- /dev/null +++ b/ansible-playbook-repeat.log @@ -0,0 +1,99 @@ +❯ ansible-playbook -i hosts.yaml playbook.yaml --ask-vault-pass +Vault password: + +PLAY [Настройка VM для раздачи статического файла через nginx] ************************************************************************************************************************************************************************************************************************************************************************************************************************************************* + +TASK [Получение SSH отпечатка] ********************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************* +ok: [nginx -> localhost] + +TASK [Добавление SSH отпечатка в known_hosts] ****************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** +changed: [nginx -> localhost] + +TASK [Сбор фактов] ********************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************* +[WARNING]: Host 'nginx' is using the discovered Python interpreter at '/usr/bin/python3.12', but future installation of another Python interpreter could cause a different interpreter to be discovered. See https://docs.ansible.com/ansible-core/2.20/reference_appendices/interpreter_discovery.html for more information. +ok: [nginx] + +TASK [prepare-key : Генерация SSH ключа] *********************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** +ok: [nginx -> localhost] + +TASK [prepare-vm : Добавление SSH ключа] *********************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** +[WARNING]: Deprecation warnings can be disabled by setting `deprecation_warnings=False` in ansible.cfg. +[DEPRECATION WARNING]: Importing 'to_native' from 'ansible.module_utils._text' is deprecated. This feature will be removed from ansible-core version 2.24. Use ansible.module_utils.common.text.converters instead. +ok: [nginx] + +TASK [prepare-vm : Установка необходимых пакетов] ************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** +ok: [nginx] + +TASK [prepare-vm : Разрешить SSH] ****************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** +ok: [nginx] + +TASK [prepare-vm : Разрешить HTTP и HTTPS] ********************************************************************************************************************************************************************************************************************************************************************************************************************************************************************* +ok: [nginx] => (item=80) +ok: [nginx] => (item=443) + +TASK [prepare-vm : Включение и запуск файрволла] *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** +ok: [nginx] + +TASK [prepare-vm : Перезагрузка файрволла] ********************************************************************************************************************************************************************************************************************************************************************************************************************************************************************* +changed: [nginx] + +TASK [prepare-vm : Включение и запуск SSH] ********************************************************************************************************************************************************************************************************************************************************************************************************************************************************************* +ok: [nginx] + +TASK [prepare-vm : Включение и запуск cron] ******************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** +ok: [nginx] + +TASK [prepare-vm : Установка UTC для cron] ********************************************************************************************************************************************************************************************************************************************************************************************************************************************************************* +ok: [nginx] + +TASK [prepare-docker : Проверка наличия докера] **************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** +ok: [nginx] + +TASK [prepare-docker : Скачивание скрипта установки докера] **************************************************************************************************************************************************************************************************************************************************************************************************************************************************** +skipping: [nginx] + +TASK [prepare-docker : Установка докера] *********************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** +skipping: [nginx] + +TASK [prepare-docker : Активация докер сервиса] **************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** +ok: [nginx] + +TASK [nginx : Подготовка директории] *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** +ok: [nginx] + +TASK [nginx : Проверка наличия сертификата] ******************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** +ok: [nginx] + +TASK [nginx : Проверка наличия приватного ключа] *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** +ok: [nginx] + +TASK [nginx : Создание директории для сертификатов] ************************************************************************************************************************************************************************************************************************************************************************************************************************************************************ +skipping: [nginx] + +TASK [nginx : Генерация приватного ключа] ********************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** +skipping: [nginx] + +TASK [nginx : Генерация CSR] *********************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** +skipping: [nginx] + +TASK [nginx : Генерация самоподписанного сертификата] ********************************************************************************************************************************************************************************************************************************************************************************************************************************************************** +skipping: [nginx] + +TASK [nginx : Копирование файлов конфигурации] ***************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** +ok: [nginx] => (item=nginx.conf) +ok: [nginx] => (item=Dockerfile) +ok: [nginx] => (item=index.html) +ok: [nginx] => (item=docker-compose.yaml) +ok: [nginx] => (item=backup.sh) + +TASK [nginx : Подготовка директории бекапов] ******************************************************************************************************************************************************************************************************************************************************************************************************************************************************************* +ok: [nginx] + +TASK [nginx : Настройка еженедельного резервного копирования Nginx] ******************************************************************************************************************************************************************************************************************************************************************************************************************************************** +ok: [nginx] + +TASK [nginx : Сборка и запуск Docker Compose] ****************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** +changed: [nginx] + +PLAY RECAP ***************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** +nginx : ok=22 changed=3 unreachable=0 failed=0 skipped=6 rescued=0 ignored=0 diff --git a/ansible-playbook.log b/ansible-playbook.log new file mode 100644 index 0000000..9d65a87 --- /dev/null +++ b/ansible-playbook.log @@ -0,0 +1,99 @@ +❯ ansible-playbook -i hosts.yaml playbook.yaml --ask-vault-pass +Vault password: + +PLAY [Настройка VM для раздачи статического файла через nginx] ************************************************************************************************************************************************************************************************************************************************************************************************************************************************* + +TASK [Получение SSH отпечатка] ********************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************* +ok: [nginx -> localhost] + +TASK [Добавление SSH отпечатка в known_hosts] ****************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** +changed: [nginx -> localhost] + +TASK [Сбор фактов] ********************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************* +[WARNING]: Host 'nginx' is using the discovered Python interpreter at '/usr/bin/python3.12', but future installation of another Python interpreter could cause a different interpreter to be discovered. See https://docs.ansible.com/ansible-core/2.20/reference_appendices/interpreter_discovery.html for more information. +ok: [nginx] + +TASK [prepare-key : Генерация SSH ключа] *********************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** +ok: [nginx -> localhost] + +TASK [prepare-vm : Добавление SSH ключа] *********************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** +[WARNING]: Deprecation warnings can be disabled by setting `deprecation_warnings=False` in ansible.cfg. +[DEPRECATION WARNING]: Importing 'to_native' from 'ansible.module_utils._text' is deprecated. This feature will be removed from ansible-core version 2.24. Use ansible.module_utils.common.text.converters instead. +changed: [nginx] + +TASK [prepare-vm : Установка необходимых пакетов] ************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** +changed: [nginx] + +TASK [prepare-vm : Разрешить SSH] ****************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** +changed: [nginx] + +TASK [prepare-vm : Разрешить HTTP и HTTPS] ********************************************************************************************************************************************************************************************************************************************************************************************************************************************************************* +changed: [nginx] => (item=80) +changed: [nginx] => (item=443) + +TASK [prepare-vm : Включение и запуск файрволла] *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** +changed: [nginx] + +TASK [prepare-vm : Перезагрузка файрволла] ********************************************************************************************************************************************************************************************************************************************************************************************************************************************************************* +changed: [nginx] + +TASK [prepare-vm : Включение и запуск SSH] ********************************************************************************************************************************************************************************************************************************************************************************************************************************************************************* +changed: [nginx] + +TASK [prepare-vm : Включение и запуск cron] ******************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** +ok: [nginx] + +TASK [prepare-vm : Установка UTC для cron] ********************************************************************************************************************************************************************************************************************************************************************************************************************************************************************* +changed: [nginx] + +TASK [prepare-docker : Проверка наличия докера] **************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** +ok: [nginx] + +TASK [prepare-docker : Скачивание скрипта установки докера] **************************************************************************************************************************************************************************************************************************************************************************************************************************************************** +changed: [nginx] + +TASK [prepare-docker : Установка докера] *********************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** +changed: [nginx] + +TASK [prepare-docker : Активация докер сервиса] **************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** +ok: [nginx] + +TASK [nginx : Подготовка директории] *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** +changed: [nginx] + +TASK [nginx : Проверка наличия сертификата] ******************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** +ok: [nginx] + +TASK [nginx : Проверка наличия приватного ключа] *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** +ok: [nginx] + +TASK [nginx : Создание директории для сертификатов] ************************************************************************************************************************************************************************************************************************************************************************************************************************************************************ +changed: [nginx] + +TASK [nginx : Генерация приватного ключа] ********************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** +changed: [nginx] + +TASK [nginx : Генерация CSR] *********************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** +changed: [nginx] + +TASK [nginx : Генерация самоподписанного сертификата] ********************************************************************************************************************************************************************************************************************************************************************************************************************************************************** +changed: [nginx] + +TASK [nginx : Копирование файлов конфигурации] ***************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** +changed: [nginx] => (item=nginx.conf) +changed: [nginx] => (item=Dockerfile) +changed: [nginx] => (item=index.html) +changed: [nginx] => (item=docker-compose.yaml) +changed: [nginx] => (item=backup.sh) + +TASK [nginx : Подготовка директории бекапов] ******************************************************************************************************************************************************************************************************************************************************************************************************************************************************************* +changed: [nginx] + +TASK [nginx : Настройка еженедельного резервного копирования Nginx] ******************************************************************************************************************************************************************************************************************************************************************************************************************************************** +changed: [nginx] + +TASK [nginx : Сборка и запуск Docker Compose] ****************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** +changed: [nginx] + +PLAY RECAP ***************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** +nginx : ok=28 changed=20 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 diff --git a/hosts.yaml b/hosts.yaml new file mode 100644 index 0000000..a3f14d9 --- /dev/null +++ b/hosts.yaml @@ -0,0 +1,5 @@ +all: + hosts: + nginx: + ansible_host: 192.168.20.217 + ansible_user: rouxinol diff --git a/playbook.yaml b/playbook.yaml new file mode 100644 index 0000000..f52434e --- /dev/null +++ b/playbook.yaml @@ -0,0 +1,28 @@ +- name: "Настройка VM для раздачи статического файла через nginx" + hosts: all + gather_facts: false + vars_files: + - secrets.yaml + pre_tasks: + - name: Получение SSH отпечатка + ansible.builtin.command: + cmd: "ssh-keyscan -H {{ ansible_host }}" + register: ssh_host_key + changed_when: false + delegate_to: localhost + + - name: Добавление SSH отпечатка в known_hosts + ansible.builtin.known_hosts: + name: "{{ ansible_host }}" + key: "{{ ssh_host_key.stdout }}" + path: "{{ lookup('env', 'HOME') }}/.ssh/known_hosts" + state: present + delegate_to: localhost + + - name: Сбор фактов + ansible.builtin.setup: + roles: + - prepare-key + - prepare-vm + - prepare-docker + - nginx diff --git a/roles/nginx/files/.dockerignore b/roles/nginx/files/.dockerignore new file mode 100644 index 0000000..0d21d98 --- /dev/null +++ b/roles/nginx/files/.dockerignore @@ -0,0 +1,10 @@ +backup.sh +docker-compose.yaml +ssl/ +*.key +*.pem +*.crt +backups/ +*.tar +*.tar.gz +*.tgz diff --git a/roles/nginx/files/Dockerfile b/roles/nginx/files/Dockerfile new file mode 100644 index 0000000..60b2725 --- /dev/null +++ b/roles/nginx/files/Dockerfile @@ -0,0 +1,12 @@ +# FROM nginxinc/nginx-unprivileged:1.29.8-alpine3.23-slim@sha256:59678856b05324b7f6371f26eb1520be7fcd8bdc8ab380fc4913db8503e5a842 +FROM nginx:1.29.6-alpine3.23-slim@sha256:c8eb3bb3009bb98c04480e11405f5b4d38adbd0bf6df5f5e6ff552b236576331 + +COPY --chown=nginx:nginx nginx.conf /etc/nginx/nginx.conf +COPY --chown=nginx:nginx index.html /usr/share/nginx/html/index.html + +EXPOSE 80 443 + +HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ + CMD wget -q --spider http://127.0.0.1:8080 || exit 1 + +USER nginx diff --git a/roles/nginx/files/backup.sh b/roles/nginx/files/backup.sh new file mode 100644 index 0000000..0297f5c --- /dev/null +++ b/roles/nginx/files/backup.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +BACKUP_DIR="/opt/nginx/backups" +CONTAINER="nginx" +DATE=$(date -u +"%Y-%m-%d_%H-%M-%S") + +mkdir -p "$BACKUP_DIR" + +TMP_DIR=$(mktemp -d) + +docker cp "${CONTAINER}:/etc/nginx" "$TMP_DIR/nginx" + +tar -czf "${BACKUP_DIR}/nginx_${DATE}.tar.gz" \ + -C "$TMP_DIR" nginx + +rm -rf "$TMP_DIR" diff --git a/roles/nginx/files/docker-compose.yaml b/roles/nginx/files/docker-compose.yaml new file mode 100644 index 0000000..a9e7149 --- /dev/null +++ b/roles/nginx/files/docker-compose.yaml @@ -0,0 +1,13 @@ +services: + nginx: + image: simbir-nginx:1.29.6 + build: + context: . + dockerfile: Dockerfile + ports: + - "80:8080" + - "443:8443" + restart: "unless-stopped" + container_name: nginx + volumes: + - /opt/nginx/ssl:/etc/nginx/ssl:ro diff --git a/roles/nginx/files/index.html b/roles/nginx/files/index.html new file mode 100644 index 0000000..e8a9921 --- /dev/null +++ b/roles/nginx/files/index.html @@ -0,0 +1,20 @@ + + + +Hello DevOps world! + + + +

Hello DevOps world!


+

+ + diff --git a/roles/nginx/files/nginx.conf b/roles/nginx/files/nginx.conf new file mode 100644 index 0000000..0e0ada5 --- /dev/null +++ b/roles/nginx/files/nginx.conf @@ -0,0 +1,24 @@ +pid /tmp/nginx.pid; +user nginx; +events {} + +http { + client_body_temp_path /tmp/client_temp; + proxy_temp_path /tmp/proxy_temp; + fastcgi_temp_path /tmp/fastcgi_temp; + uwsgi_temp_path /tmp/uwsgi_temp; + scgi_temp_path /tmp/scgi_temp; + + server { + listen 8080; + root /usr/share/nginx/html; + } + + server { + listen 8443 ssl; + root /usr/share/nginx/html; + + ssl_certificate /etc/nginx/ssl/cert.pem; + ssl_certificate_key /etc/nginx/ssl/key.pem; + } +} diff --git a/roles/nginx/tasks/main.yaml b/roles/nginx/tasks/main.yaml new file mode 100644 index 0000000..aefc3f3 --- /dev/null +++ b/roles/nginx/tasks/main.yaml @@ -0,0 +1,103 @@ +- name: Подготовка директории + become: true + ansible.builtin.file: + state: directory + path: /opt/nginx + mode: "0755" + +- name: Проверка наличия сертификата + ansible.builtin.stat: + path: /opt/nginx/ssl/cert.pem + register: cert_file + +- name: Проверка наличия приватного ключа + ansible.builtin.stat: + path: /opt/nginx/ssl/key.pem + register: key_file + +- name: Создание директории для сертификатов + become: true + ansible.builtin.file: + path: /opt/nginx/ssl + state: directory + owner: root + group: root + mode: '0755' + when: not cert_file.stat.exists or not key_file.stat.exists + +- name: Генерация приватного ключа + become: true + community.crypto.openssl_privatekey: + path: /opt/nginx/ssl/key.pem + size: 2048 + owner: root + group: 101 + mode: '0640' + when: not cert_file.stat.exists or not key_file.stat.exists + +- name: Генерация CSR + become: true + community.crypto.openssl_csr: + path: /opt/nginx/ssl/nginx.csr + privatekey_path: /opt/nginx/ssl/key.pem + common_name: nginx.local + subject_alt_name: + - "DNS:nginx.local" + - "DNS:localhost" + - "IP:{{ansible_facts['default_ipv4']['address']}}" + when: not cert_file.stat.exists or not key_file.stat.exists + +- name: Генерация самоподписанного сертификата + become: true + community.crypto.x509_certificate: + path: /opt/nginx/ssl/cert.pem + privatekey_path: /opt/nginx/ssl/key.pem + csr_path: /opt/nginx/ssl/nginx.csr + provider: selfsigned + selfsigned_not_after: "+3650d" + when: not cert_file.stat.exists or not key_file.stat.exists + +- name: Изменение прав на сертификат + become: true + ansible.builtin.file: + path: /opt/nginx/ssl/cert.pem + owner: root + group: "101" + mode: "0644" + +- name: Копирование файлов конфигурации + become: true + ansible.builtin.copy: + src: "{{item}}" + dest: "/opt/nginx/{{item}}" + mode: "0755" + loop: + - nginx.conf + - Dockerfile + - index.html + - docker-compose.yaml + - backup.sh + +- name: Подготовка директории бекапов + become: true + ansible.builtin.file: + state: directory + path: /opt/nginx/backups + mode: "0755" + +- name: Настройка еженедельного резервного копирования Nginx + become: true + ansible.builtin.cron: + name: "nginx configuration backup" + minute: "0" + hour: "1" + weekday: "1" + job: "/opt/nginx/backup.sh" + env: false + +- name: Сборка и запуск Docker Compose + community.docker.docker_compose_v2: + project_src: /opt/nginx + state: present + build: always + become: true diff --git a/roles/prepare-docker/tasks/main.yaml b/roles/prepare-docker/tasks/main.yaml new file mode 100644 index 0000000..3fa77ef --- /dev/null +++ b/roles/prepare-docker/tasks/main.yaml @@ -0,0 +1,30 @@ +- name: Проверка наличия докера + ansible.builtin.command: + cmd: docker --version + register: docker_version + changed_when: false + failed_when: false + +- name: Скачивание скрипта установки докера + become: true + ansible.builtin.get_url: + url: https://get.docker.com + dest: /tmp/get-docker.sh + owner: root + group: root + mode: "0755" + when: docker_version.rc != 0 + +- name: Установка докера + become: true + ansible.builtin.command: + cmd: sh /tmp/get-docker.sh + creates: /usr/bin/docker + when: docker_version.rc != 0 + +- name: Активация докер сервиса + become: true + ansible.builtin.service: + name: docker + enabled: true + state: started diff --git a/roles/prepare-key/tasks/main.yaml b/roles/prepare-key/tasks/main.yaml new file mode 100644 index 0000000..bfc2d00 --- /dev/null +++ b/roles/prepare-key/tasks/main.yaml @@ -0,0 +1,5 @@ +- name: Генерация SSH ключа + ansible.builtin.command: + cmd: "ssh-keygen -t ed25519 -f {{playbook_dir}}/id_ed25519_simbirkey -N '' -C ''" + creates: "{{playbook_dir}}/id_ed25519_simbirkey" + delegate_to: localhost diff --git a/roles/prepare-vm/tasks/main.yaml b/roles/prepare-vm/tasks/main.yaml new file mode 100644 index 0000000..b72c0cd --- /dev/null +++ b/roles/prepare-vm/tasks/main.yaml @@ -0,0 +1,64 @@ +- name: Добавление SSH ключа + ansible.posix.authorized_key: + user: "{{ansible_user}}" + key: "{{ lookup('file', playbook_dir + '/id_ed25519_simbirkey.pub') }}" + state: present + +- name: Установка необходимых пакетов + ansible.builtin.apt: + name: + - ufw + - openssl + - openssh-server + - tar + - cron + state: present + update_cache: true + become: true + +- name: Разрешить SSH + community.general.ufw: + rule: allow + name: openssh + become: true + +- name: Разрешить HTTP и HTTPS + community.general.ufw: + rule: allow + port: "{{ item }}" + proto: tcp + become: true + loop: + - "80" + - "443" + +- name: Включение и запуск файрволла + community.general.ufw: + state: enabled + default: deny + become: true + +- name: Перезагрузка файрволла + ansible.builtin.command: ufw reload + become: true + +- name: Включение и запуск SSH + ansible.builtin.systemd_service: + name: ssh + enabled: true + state: started + become: true + +- name: Включение и запуск cron + ansible.builtin.systemd_service: + name: cron + state: started + enabled: true + become: true + +- name: Установка UTC для cron + ansible.builtin.cron: + name: CRON_TZ + env: true + job: UTC + become: true diff --git a/secrets.yaml b/secrets.yaml new file mode 100644 index 0000000..01f7564 --- /dev/null +++ b/secrets.yaml @@ -0,0 +1,2 @@ +ansible_password: "superpass123" +ansible_become_password: "superpass123"