iac/aero/roles/sarex_stack/tasks/main.yml

202 lines
8.1 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
# --- Каталоги и файлы ----------------------------------------------------
- name: Создать каталог развёртывания
ansible.builtin.file:
path: "{{ deploy_dir }}"
state: directory
owner: root
group: root
mode: "0750"
tags: [env]
- name: Скопировать docker-compose.yaml
ansible.builtin.copy:
src: "{{ deploy_src_root }}/docker-compose.yaml"
dest: "{{ deploy_dir }}/docker-compose.yaml"
mode: "0640"
# nginx монтирует ./nginx/templates и ./nginx/certs — без шаблонов nginx не
# стартует, поэтому копируем конфигурацию рядом с compose.
- name: Скопировать шаблоны nginx
ansible.builtin.copy:
src: "{{ deploy_src_root }}/nginx/templates/"
dest: "{{ deploy_dir }}/nginx/templates/"
mode: "0644"
# backend монтирует ./backend/uwsgi.ini (http-socket + 4 воркера) и
# ./backend/production.py (классическая JWT-аутентификация)
- name: Скопировать конфиги backend (uwsgi.ini, production.py)
ansible.builtin.copy:
src: "{{ deploy_src_root }}/backend/"
dest: "{{ deploy_dir }}/backend/"
mode: "0644"
# --- Секреты: генерация с персистом на control-node (идемпотентно) --------
- name: Сгенерировать/загрузить пароли (persist в secrets_store, gitignored)
ansible.builtin.set_fact:
sarex_secrets: >-
{{ sarex_secrets | default({}) | combine({
item: lookup('password',
secrets_store ~ '/' ~ inventory_hostname ~ '/' ~ item
~ ' length=' ~ secret_length ~ ' chars=ascii_letters,digits')
}) }}
loop: "{{ sarex_secret_vars }}"
no_log: true
tags: [env]
# RSA-ключи JWT (RS512): генерируем на control-node, persist в secrets_store.
- name: Сгенерировать приватный RSA-ключ JWT
ansible.builtin.command: "openssl genrsa -out {{ jwt_private_key_path }} 4096"
args:
creates: "{{ jwt_private_key_path }}"
delegate_to: localhost
become: false
tags: [env]
- name: Извлечь публичный RSA-ключ JWT
ansible.builtin.command: "openssl rsa -in {{ jwt_private_key_path }} -pubout -out {{ jwt_public_key_path }}"
args:
creates: "{{ jwt_public_key_path }}"
delegate_to: localhost
become: false
tags: [env]
- name: Собрать словарь переопределений для .env (пароли + домены + JWT)
ansible.builtin.set_fact:
env_overrides: >-
{{ sarex_secrets | combine({
'PLATFORM_DOMAIN': platform_domain,
'ADMIN_DOMAIN': admin_domain,
'MINIO_DOMAIN': minio_domain,
'SAREX_MINIO_CONSOLE_URL': 'https://' ~ minio_domain,
'SAREX_JWT_PRIVATE_KEY': "'" ~ (lookup('file', jwt_private_key_path) | replace('\n', '\\n')) ~ "'",
'SAREX_JWT_PUBLIC_KEY': "'" ~ (lookup('file', jwt_public_key_path) | replace('\n', '\\n')) ~ "'",
}) }}
no_log: true
tags: [env]
- name: Отрендерить .env из .env.example с переопределениями
ansible.builtin.template:
src: env.j2
dest: "{{ deploy_dir }}/.env"
owner: root
group: root
mode: "0600"
no_log: true
tags: [env]
# --- Самоподписанный TLS-сертификат для трёх доменов ----------------------
- name: Создать каталог для сертификатов
ansible.builtin.file:
path: "{{ cert_dir }}"
state: directory
mode: "0750"
- name: Сгенерировать самоподписанный сертификат (SAN на все домены)
ansible.builtin.shell:
# umask 077 → приватный ключ создаётся сразу с правами 0600
cmd: >-
umask 077 && openssl req -x509 -nodes -newkey rsa:2048 -days {{ cert_days }}
-keyout {{ cert_dir }}/selfsigned.key
-out {{ cert_dir }}/selfsigned.crt
-subj "/CN={{ platform_domain }}"
-addext "subjectAltName=DNS:{{ platform_domain }},DNS:{{ admin_domain }},DNS:{{ minio_domain }}"
creates: "{{ cert_dir }}/selfsigned.crt"
# --- Логин в приватный реестр образов (json_key) --------------------------
- name: Проверить, выполнен ли вход в реестр
ansible.builtin.command: grep -q "{{ registry_host }}" /root/.docker/config.json
register: registry_login_state
changed_when: false
failed_when: false
tags: [login]
- name: Скопировать ключ реестра на хост (временно)
ansible.builtin.copy:
src: "{{ registry_key_src }}"
dest: /root/.registry-key.json
mode: "0600"
when: registry_login_state.rc != 0
no_log: true
tags: [login]
- name: docker login в приватный реестр
ansible.builtin.shell: >-
set -o pipefail && cat /root/.registry-key.json
| docker login --username {{ registry_username }} --password-stdin {{ registry_host }}
args:
executable: /bin/bash
when: registry_login_state.rc != 0
register: registry_login_result
changed_when: "'Login Succeeded' in registry_login_result.stdout"
no_log: true
tags: [login]
- name: Удалить временный ключ реестра с хоста
ansible.builtin.file:
path: /root/.registry-key.json
state: absent
tags: [login]
# --- Поднять сервисы приложения ------------------------------------------
- name: Поднять сервисы приложения (docker compose up -d)
ansible.builtin.command:
cmd: "{{ compose_cmd }} up -d {{ sarex_services | join(' ') }}"
chdir: "{{ deploy_dir }}"
when: sarex_compose_up | bool
changed_when: true
tags: [up]
# --- Django-суперпользователь: генерация логина+пароля, создание -----------
# Только по явной команде (uv run poe superuser передаёт sarex_create_superuser=true),
# чтобы обычный deploy не дёргал backend. Логин/пароль персистятся в secrets_store
# (переиспользуются при повторе — идемпотентно).
- name: Сгенерировать логин суперпользователя
ansible.builtin.set_fact:
superuser_name: "{{ lookup('password', secrets_store ~ '/' ~ inventory_hostname ~ '/SAREX_SUPERUSER_NAME chars=ascii_lowercase,digits length=10') }}"
when: sarex_create_superuser | default(false) | bool
no_log: true
tags: [superuser]
- name: Сгенерировать пароль суперпользователя
ansible.builtin.set_fact:
superuser_password: "{{ lookup('password', secrets_store ~ '/' ~ inventory_hostname ~ '/SAREX_SUPERUSER_PASSWORD chars=ascii_letters,digits length=' ~ secret_length) }}"
when: sarex_create_superuser | default(false) | bool
no_log: true
tags: [superuser]
- name: Создать/обновить Django-суперпользователя в backend
when: sarex_create_superuser | default(false) | bool
ansible.builtin.command:
argv:
- "{{ compose_cmd.split()[0] }}"
- exec
- -e
- "SU_NAME={{ superuser_name }}"
- -e
- "SU_PASS={{ superuser_password }}"
- -e
- "SU_EMAIL={{ superuser_name }}@{{ platform_domain }}"
- sarex-backend
- python
- manage.py
- shell
- -c
- >-
import os;
from django.contrib.auth import get_user_model;
U = get_user_model();
u, c = U.objects.get_or_create(username=os.environ['SU_NAME'], defaults={'email': os.environ['SU_EMAIL']});
u.is_staff = True; u.is_superuser = True; u.set_password(os.environ['SU_PASS']); u.save();
print('created' if c else 'updated')
register: superuser_result
changed_when: true
no_log: true
tags: [superuser]
- name: Показать учётные данные суперпользователя
ansible.builtin.debug:
msg: "Django superuser → login: {{ superuser_name }} password: {{ superuser_password }}"
when: sarex_create_superuser | default(false) | bool
tags: [superuser]