Files
AWatch-rus/ansible/deploy_proxmox_web_gateway.yml
T

403 lines
16 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: Развернуть nginx web gateway на Proxmox host
hosts: proxmox
become: true
gather_facts: true
vars:
proxmox_web_gateway_public_hostname: "detmir.example.local"
proxmox_web_gateway_root: "/var/www/proxmox-web-gateway"
proxmox_web_gateway_site_name: "proxmox-web-gateway.conf"
proxmox_web_gateway_site_path: "/etc/nginx/sites-available/{{ proxmox_web_gateway_site_name }}"
proxmox_web_gateway_site_enabled_path: "/etc/nginx/sites-enabled/{{ proxmox_web_gateway_site_name }}"
proxmox_web_gateway_tls_dir: "/etc/nginx/ssl/proxmox-web-gateway"
proxmox_web_gateway_tls_cert_path: "{{ proxmox_web_gateway_tls_dir }}/fullchain.pem"
proxmox_web_gateway_tls_key_path: "{{ proxmox_web_gateway_tls_dir }}/privkey.pem"
proxmox_web_gateway_health_path: "/healthz"
proxmox_web_gateway_auth_realm: "AWatch-rus portal 2026-06-06"
proxmox_web_gateway_auth_user: "detmir"
proxmox_web_gateway_auth_file: "/etc/nginx/proxmox-web-gateway.htpasswd"
proxmox_web_gateway_credentials_file: "/etc/detmir/proxmox-web-gateway.credentials"
proxmox_web_gateway_routes:
- slug: "proxmox-gui"
title: "Proxmox VE"
category: "Host"
description: "Основная панель управления Proxmox VE."
target_url: "https://192.0.2.2:8006/"
external_enabled: false
- slug: "file1c-brief"
title: "1C Executive Brief"
category: "Management"
description: "Сводка по предприятиям и рискам 1С."
target_url: "http://192.0.2.2:8710/manager/brief"
proxy_path: "/r/file1c/brief"
proxy_target_url: "http://192.0.2.2:8710/manager/brief"
external_enabled: true
- slug: "file1c-actions"
title: "1C Management Actions"
category: "Management"
description: "Очередь действий по предприятиям в 1С."
target_url: "http://192.0.2.2:8710/manager/actions"
proxy_path: "/r/file1c/actions"
proxy_target_url: "http://192.0.2.2:8710/manager/actions"
external_enabled: true
- slug: "file1c-finance"
title: "1C Financial Reporting"
category: "Management"
description: "Первый financial board по файловой 1С с разделением ledger/proxy."
target_url: "http://192.0.2.11:3000/d/1c-file-finance/1c-file-financial-reporting?orgId=1"
proxy_path: "/d/1c-file-finance/1c-file-financial-reporting?orgId=1"
external_enabled: true
- slug: "file1c-telemetry"
title: "1C Telemetry Board"
category: "Dashboards"
description: "Read-only telemetry экран по состоянию файловых баз, reglog и host."
target_url: "http://192.0.2.11:3000/d/1c-file-telemetry/1c-file-telemetry-board?orgId=1"
proxy_path: "/d/1c-file-telemetry/1c-file-telemetry-board?orgId=1"
external_enabled: true
- slug: "grafana-1c"
title: "Grafana 1C"
category: "Dashboards"
description: "Рабочий file-1c dashboard contour в внешней Grafana."
target_url: "http://192.0.2.11:3000/d/1c-file-mgmt/1c-file-management-board?orgId=1"
proxy_path: "/d/1c-file-mgmt/1c-file-management-board?orgId=1"
external_enabled: true
- slug: "clickhouse-http"
title: "ClickHouse HTTP"
category: "Data"
description: "HTTP endpoint ClickHouse для file-1C analytics."
target_url: "http://192.0.2.2:8123/"
external_enabled: false
- slug: "influxdb"
title: "InfluxDB"
category: "Data"
description: "InfluxDB LXC на CT 200."
target_url: "http://192.0.2.10:8086/"
external_enabled: false
- slug: "grafana-core"
title: "Grafana Core"
category: "Dashboards"
description: "Отдельный Grafana CT 201."
target_url: "http://192.0.2.11:3000/"
proxy_path: "/dashboards"
external_enabled: true
- slug: "loki-alloy"
title: "Grafana Alloy"
category: "Logs"
description: "Web UI Alloy на CT 202."
target_url: "http://192.0.2.12:12345/"
external_enabled: false
- slug: "aw-ui"
title: "AW-rus UI"
category: "Operations"
description: "Основной ActivityWatch-Russian Web UI на CT 203."
target_url: "http://192.0.2.13:5600/"
proxy_path: "/r/aw/"
external_enabled: true
- slug: "aw-worktime"
title: "AW-rus Management Report"
category: "Operations"
description: "Управленческий worktime/report API на CT 203."
target_url: "http://192.0.2.13:5610/reports/worktime/management?format=html&host=HOST-EXAMPLE"
proxy_path: "/r/aw-worktime"
proxy_target_url: "http://192.0.2.13:5610/reports/worktime/management?format=html&host=HOST-EXAMPLE"
external_enabled: true
- slug: "detmir-portal"
title: "DetMir Portal"
category: "Operations"
description: "Единый read-only портал для оператора, руководителя и владельца."
target_url: "http://127.0.0.1:8720/"
proxy_path: "/portal/"
external_enabled: true
tasks:
- name: Установить nginx
ansible.builtin.package:
name:
- nginx
- openssl
state: present
- name: Создать web root gateway
ansible.builtin.file:
path: "{{ proxmox_web_gateway_root }}"
state: directory
owner: root
group: root
mode: "0755"
- name: Создать каталог TLS gateway
ansible.builtin.file:
path: "{{ proxmox_web_gateway_tls_dir }}"
state: directory
owner: root
group: root
mode: "0700"
- name: Сгенерировать self-signed TLS сертификат gateway
ansible.builtin.command:
argv:
- openssl
- req
- -x509
- -nodes
- -newkey
- rsa:2048
- -sha256
- -days
- "3650"
- -keyout
- "{{ proxmox_web_gateway_tls_key_path }}"
- -out
- "{{ proxmox_web_gateway_tls_cert_path }}"
- -subj
- "/CN={{ proxmox_web_gateway_public_hostname }}"
- -addext
- "subjectAltName=DNS:{{ proxmox_web_gateway_public_hostname }}"
args:
creates: "{{ proxmox_web_gateway_tls_cert_path }}"
- name: Проверить наличие gateway Basic Auth файла
ansible.builtin.stat:
path: "{{ proxmox_web_gateway_auth_file }}"
register: proxmox_web_gateway_auth_stat
- name: Проверить наличие gateway credential файла
ansible.builtin.stat:
path: "{{ proxmox_web_gateway_credentials_file }}"
register: proxmox_web_gateway_credentials_stat
- name: Создать согласованные gateway Basic Auth credential
ansible.builtin.shell: |
set -eu
umask 077
password="$(openssl rand -base64 24 | tr -d '\n')"
hash="$(openssl passwd -apr1 "$password")"
printf '%s:%s\n' '{{ proxmox_web_gateway_auth_user }}' "$hash" > '{{ proxmox_web_gateway_auth_file }}'
printf 'url=https://{{ proxmox_web_gateway_public_hostname }}/\nuser={{ proxmox_web_gateway_auth_user }}\npassword=%s\n' "$password" > '{{ proxmox_web_gateway_credentials_file }}'
args:
executable: /bin/sh
no_log: true
when: >
not (proxmox_web_gateway_auth_stat.stat.exists | default(false))
or not (proxmox_web_gateway_credentials_stat.stat.exists | default(false))
- name: Зафиксировать права gateway Basic Auth файла
ansible.builtin.file:
path: "{{ proxmox_web_gateway_auth_file }}"
owner: root
group: www-data
mode: "0640"
- name: Зафиксировать права файла с gateway credential
ansible.builtin.file:
path: "{{ proxmox_web_gateway_credentials_file }}"
owner: root
group: root
mode: "0600"
- name: Прочитать gateway credential для локальной проверки
ansible.builtin.slurp:
src: "{{ proxmox_web_gateway_credentials_file }}"
register: proxmox_web_gateway_credentials_slurp
no_log: true
- name: Подготовить gateway auth password для проверок
ansible.builtin.set_fact:
proxmox_web_gateway_auth_password: "{{ (proxmox_web_gateway_credentials_slurp.content | b64decode).split('password=')[1].split('\n')[0] }}"
no_log: true
- name: Развернуть index.html gateway
ansible.builtin.template:
src: "templates/proxmox-web-gateway-index.html.j2"
dest: "{{ proxmox_web_gateway_root }}/index.html"
owner: root
group: root
mode: "0644"
- name: Развернуть nginx site gateway
ansible.builtin.template:
src: "templates/proxmox-web-gateway.conf.j2"
dest: "{{ proxmox_web_gateway_site_path }}"
owner: root
group: root
mode: "0644"
notify: Reload nginx
- name: Отключить default nginx site
ansible.builtin.file:
path: "/etc/nginx/sites-enabled/default"
state: absent
notify: Reload nginx
- name: Включить proxmox web gateway site
ansible.builtin.file:
src: "{{ proxmox_web_gateway_site_path }}"
dest: "{{ proxmox_web_gateway_site_enabled_path }}"
state: link
notify: Reload nginx
- name: Включить и запустить nginx
ansible.builtin.systemd:
name: nginx
enabled: true
state: started
- name: Применить handlers до проверок
ansible.builtin.meta: flush_handlers
- name: Проверить синтаксис nginx после выкладки site
ansible.builtin.command: "/usr/sbin/nginx -t"
register: proxmox_web_gateway_nginx_test
changed_when: false
- name: Проверить локальный HTTP redirect на HTTPS
ansible.builtin.uri:
url: "http://127.0.0.1/"
headers:
Host: "{{ proxmox_web_gateway_public_hostname }}"
follow_redirects: none
status_code: 301
register: proxmox_web_gateway_http_redirect
failed_when:
- proxmox_web_gateway_http_redirect.status != 301
- proxmox_web_gateway_http_redirect.location != "https://{{ proxmox_web_gateway_public_hostname }}/"
changed_when: false
- name: Проверить старый /go путь без auth закрыт
ansible.builtin.uri:
url: "https://127.0.0.1/go/proxmox-gui"
headers:
Host: "{{ proxmox_web_gateway_public_hostname }}"
validate_certs: false
follow_redirects: none
status_code: 401
register: proxmox_web_gateway_redirect
failed_when:
- proxmox_web_gateway_redirect.status != 401
changed_when: false
- name: Проверить index без auth закрыт
ansible.builtin.uri:
url: "https://127.0.0.1/"
headers:
Host: "{{ proxmox_web_gateway_public_hostname }}"
validate_certs: false
status_code: 401
changed_when: false
- name: Проверить index по public hostname с auth
ansible.builtin.uri:
url: "https://127.0.0.1/"
headers:
Host: "{{ proxmox_web_gateway_public_hostname }}"
url_username: "{{ proxmox_web_gateway_auth_user }}"
url_password: "{{ proxmox_web_gateway_auth_password }}"
force_basic_auth: true
return_content: true
validate_certs: false
register: proxmox_web_gateway_named_index
failed_when:
- proxmox_web_gateway_named_index.status != 200
- proxmox_web_gateway_public_hostname not in proxmox_web_gateway_named_index.content
changed_when: false
- name: Проверить reverse proxy к 1C brief с auth
ansible.builtin.uri:
url: "https://127.0.0.1/r/file1c/brief"
headers:
Host: "{{ proxmox_web_gateway_public_hostname }}"
url_username: "{{ proxmox_web_gateway_auth_user }}"
url_password: "{{ proxmox_web_gateway_auth_password }}"
force_basic_auth: true
validate_certs: false
status_code: 200
changed_when: false
- name: Проверить reverse proxy к Grafana health с auth
ansible.builtin.uri:
url: "https://127.0.0.1/r/grafana/api/health"
headers:
Host: "{{ proxmox_web_gateway_public_hostname }}"
url_username: "{{ proxmox_web_gateway_auth_user }}"
url_password: "{{ proxmox_web_gateway_auth_password }}"
force_basic_auth: true
validate_certs: false
status_code: 200
changed_when: false
- name: Проверить reverse proxy к AW info с auth
ansible.builtin.uri:
url: "https://127.0.0.1/r/aw/api/0/info"
headers:
Host: "{{ proxmox_web_gateway_public_hostname }}"
url_username: "{{ proxmox_web_gateway_auth_user }}"
url_password: "{{ proxmox_web_gateway_auth_password }}"
force_basic_auth: true
validate_certs: false
status_code: 200
changed_when: false
- name: Проверить reverse proxy к DetMir Portal health с auth
ansible.builtin.uri:
url: "https://127.0.0.1/portal/api/health"
headers:
Host: "{{ proxmox_web_gateway_public_hostname }}"
url_username: "{{ proxmox_web_gateway_auth_user }}"
url_password: "{{ proxmox_web_gateway_auth_password }}"
force_basic_auth: true
validate_certs: false
status_code: 200
return_content: true
register: proxmox_web_gateway_portal_health
failed_when:
- proxmox_web_gateway_portal_health.status != 200
- "'sources' not in proxmox_web_gateway_portal_health.content"
changed_when: false
- name: Проверить browser-origin AW API query без 403
ansible.builtin.uri:
url: "https://127.0.0.1/api/0/query/"
method: POST
headers:
Host: "{{ proxmox_web_gateway_public_hostname }}"
Origin: "https://{{ proxmox_web_gateway_public_hostname }}"
Referer: "https://{{ proxmox_web_gateway_public_hostname }}/r/aw/"
Content-Type: "application/json"
body_format: json
body:
timeperiods:
- "1970-01-01T00:00:00+00:00/1970-01-01T00:01:00+00:00"
query:
- "RETURN = [];"
url_username: "{{ proxmox_web_gateway_auth_user }}"
url_password: "{{ proxmox_web_gateway_auth_password }}"
force_basic_auth: true
validate_certs: false
status_code: 200
return_content: true
register: proxmox_web_gateway_aw_query
failed_when:
- proxmox_web_gateway_aw_query.status != 200
- proxmox_web_gateway_aw_query.content != "[[]]"
changed_when: false
- name: Проверить локальный HTTPS health endpoint gateway
ansible.builtin.uri:
url: "https://127.0.0.1{{ proxmox_web_gateway_health_path }}"
headers:
Host: "{{ proxmox_web_gateway_public_hostname }}"
return_content: true
validate_certs: false
register: proxmox_web_gateway_https_health
failed_when:
- proxmox_web_gateway_https_health.status != 200
- "'ok' not in proxmox_web_gateway_https_health.content"
changed_when: false
handlers:
- name: Reload nginx
ansible.builtin.systemd:
name: nginx
state: reloaded