From 9e53272ce92d9411ab5e17145e9a1733bee7fc83 Mon Sep 17 00:00:00 2001 From: igor04091968 Date: Sat, 25 Apr 2026 15:43:31 +0300 Subject: [PATCH] feat(ansible): add full Proxmox zero-to-service provisioning playbook --- README.md | 4 + ansible/README.md | 22 +- ansible/group_vars/proxmox.example.yml | 18 ++ ansible/inventory.example.ini | 3 + .../provision_proxmox_ct_and_deploy_aw.yml | 229 ++++++++++++++++++ docs/FULL_DEPLOYMENT_MANUAL_RU.md | 24 ++ docs/deployment.md | 9 + 7 files changed, 308 insertions(+), 1 deletion(-) create mode 100644 ansible/group_vars/proxmox.example.yml create mode 100644 ansible/provision_proxmox_ct_and_deploy_aw.yml diff --git a/README.md b/README.md index 4d4a946..5345de4 100755 --- a/README.md +++ b/README.md @@ -27,6 +27,10 @@ 8. Развернуть Windows-клиентов через `windows/deploy-ensemble.ps1`. 9. Проверить итог через `windows/validate-deployment.ps1`. +Для полного Ansible-сценария “с нуля” в Proxmox используйте: + +- `ansible/provision_proxmox_ct_and_deploy_aw.yml` + Скрипты `proxmox/create-ct.sh` и `proxmox/push-aw-artifacts.sh` по умолчанию читают: - `secrets/deploy.secrets.env` diff --git a/ansible/README.md b/ansible/README.md index f22443a..247e5da 100644 --- a/ansible/README.md +++ b/ansible/README.md @@ -1,12 +1,17 @@ # Ansible ensemble for AWatch-rus -Эта директория содержит минимальный Ansible-ensemble для повторяемого развёртывания ActivityWatch Server в Debian/LXC. +Эта директория содержит Ansible-ensemble для двух сценариев: + +- деплой на уже существующий Debian host/CT; +- полный цикл с нуля в Proxmox: создание CT + bootstrap + установка ActivityWatch + RU patch. ## Файлы - `/home/igor/tmp/AWatch-rus/ansible/deploy_aw_server.yml` — основной playbook. +- `/home/igor/tmp/AWatch-rus/ansible/provision_proxmox_ct_and_deploy_aw.yml` — full-stack playbook для Proxmox. - `/home/igor/tmp/AWatch-rus/ansible/inventory.example.ini` — шаблон inventory. - `/home/igor/tmp/AWatch-rus/ansible/group_vars/all.example.yml` — шаблон переменных. +- `/home/igor/tmp/AWatch-rus/ansible/group_vars/proxmox.example.yml` — шаблон переменных CT в Proxmox. ## Быстрый запуск @@ -21,9 +26,24 @@ cd /home/igor/tmp/AWatch-rus/ansible ansible-playbook -i inventory.ini deploy_aw_server.yml ``` +## Полный запуск с нуля в Proxmox + +1. Подготовьте inventory и vars: + - `cp /home/igor/tmp/AWatch-rus/ansible/inventory.example.ini /home/igor/tmp/AWatch-rus/ansible/inventory.ini` + - `cp /home/igor/tmp/AWatch-rus/ansible/group_vars/all.example.yml /home/igor/tmp/AWatch-rus/ansible/group_vars/all.yml` + - `cp /home/igor/tmp/AWatch-rus/ansible/group_vars/proxmox.example.yml /home/igor/tmp/AWatch-rus/ansible/group_vars/proxmox.yml` +2. Заполните `group_vars/proxmox.yml` и `group_vars/all.yml`. +3. Запустите playbook: + +```bash +cd /home/igor/tmp/AWatch-rus/ansible +ansible-playbook -i inventory.ini provision_proxmox_ct_and_deploy_aw.yml +``` + ## Результат - Установлен ActivityWatch Server. - Создан systemd-unit `activitywatch-server.service`. - Установлен RU Web UI patch. - Выполнена валидация API `http://127.0.0.1:5600/api/0/info`. +- Для full-stack сценария CT создаётся автоматически через `pct create`. diff --git a/ansible/group_vars/proxmox.example.yml b/ansible/group_vars/proxmox.example.yml new file mode 100644 index 0000000..07e6eda --- /dev/null +++ b/ansible/group_vars/proxmox.example.yml @@ -0,0 +1,18 @@ +proxmox_ct_id: "203" +proxmox_ct_hostname: "activitywatch-server" +proxmox_ct_storage: "local-lvm" +proxmox_ct_template: "local:vztmpl/debian-12-standard_12.7-1_amd64.tar.zst" +proxmox_ct_rootfs_size: "8G" +proxmox_ct_cores: "2" +proxmox_ct_memory: "2048" +proxmox_ct_swap: "512" +proxmox_ct_bridge: "vmbr10" +proxmox_ct_ip: "10.20.30.13/24" +proxmox_ct_gw: "10.20.30.1" +proxmox_ct_vlan: "" +proxmox_ct_nameserver: "1.1.1.1 8.8.8.8" +proxmox_ct_searchdomain: "example.internal" +proxmox_ct_password: "CHANGE_ME" +proxmox_ct_unprivileged: "1" +proxmox_ct_onboot: "1" +proxmox_ct_features: "nesting=1,keyctl=1" diff --git a/ansible/inventory.example.ini b/ansible/inventory.example.ini index b0c2d48..1376644 100644 --- a/ansible/inventory.example.ini +++ b/ansible/inventory.example.ini @@ -1,2 +1,5 @@ +[proxmox] +pve-main ansible_host=192.168.10.2 ansible_user=root ansible_port=22 + [aw_server] aw-ct ansible_host=10.20.30.13 ansible_user=root ansible_port=22 diff --git a/ansible/provision_proxmox_ct_and_deploy_aw.yml b/ansible/provision_proxmox_ct_and_deploy_aw.yml new file mode 100644 index 0000000..8b96c0e --- /dev/null +++ b/ansible/provision_proxmox_ct_and_deploy_aw.yml @@ -0,0 +1,229 @@ +--- +- name: Provision Proxmox CT and deploy AWatch-rus + hosts: proxmox + gather_facts: false + + vars: + proxmox_bootstrap_dir: "/tmp/aw-rus-bootstrap" + proxmox_ct_net0: >- + name=eth0,bridge={{ proxmox_ct_bridge }},ip={{ proxmox_ct_ip }},gw={{ proxmox_ct_gw }}{% if proxmox_ct_vlan | default('') | length > 0 %},tag={{ proxmox_ct_vlan }}{% endif %} + aw_bootstrap_files: + - install_aw_server.sh + - apply_webui_ru_patch.sh + - activitywatch-server.service + - aw-server.env.example + - aw-ru-patch.js + - aw-sw-cleanup.js + + tasks: + - name: Validate required Proxmox variables + ansible.builtin.assert: + that: + - proxmox_ct_id is defined + - proxmox_ct_hostname is defined + - proxmox_ct_storage is defined + - proxmox_ct_template is defined + - proxmox_ct_rootfs_size is defined + - proxmox_ct_cores is defined + - proxmox_ct_memory is defined + - proxmox_ct_swap is defined + - proxmox_ct_bridge is defined + - proxmox_ct_ip is defined + - proxmox_ct_gw is defined + - proxmox_ct_password is defined + - proxmox_ct_unprivileged is defined + - proxmox_ct_onboot is defined + - proxmox_ct_features is defined + - aw_repo_root is defined + - aw_server_version is defined + - aw_server_download_url is defined + - aw_server_bind_host is defined + - aw_server_port is defined + - aw_server_webui_dir is defined + - aw_server_data_dir is defined + - aw_server_log_dir is defined + - aw_server_user is defined + - aw_server_group is defined + fail_msg: "Missing required variables in ansible/group_vars/*.yml" + + - name: Check whether CT already exists + ansible.builtin.command: + argv: + - pct + - status + - "{{ proxmox_ct_id }}" + register: ct_status_check + failed_when: false + changed_when: false + + - name: Create CT when absent + ansible.builtin.command: + argv: + - pct + - create + - "{{ proxmox_ct_id }}" + - "{{ proxmox_ct_template }}" + - --hostname + - "{{ proxmox_ct_hostname }}" + - --cores + - "{{ proxmox_ct_cores }}" + - --memory + - "{{ proxmox_ct_memory }}" + - --swap + - "{{ proxmox_ct_swap }}" + - --rootfs + - "{{ proxmox_ct_storage }}:{{ proxmox_ct_rootfs_size }}" + - --password + - "{{ proxmox_ct_password }}" + - --unprivileged + - "{{ proxmox_ct_unprivileged }}" + - --onboot + - "{{ proxmox_ct_onboot }}" + - --features + - "{{ proxmox_ct_features }}" + - --net0 + - "{{ proxmox_ct_net0 }}" + - --nameserver + - "{{ proxmox_ct_nameserver | default('') }}" + - --searchdomain + - "{{ proxmox_ct_searchdomain | default('') }}" + - --ostype + - debian + when: ct_status_check.rc != 0 + + - name: Check current CT runtime state + ansible.builtin.command: + argv: + - pct + - status + - "{{ proxmox_ct_id }}" + register: ct_runtime_status + changed_when: false + + - name: Start CT when stopped + ansible.builtin.command: + argv: + - pct + - start + - "{{ proxmox_ct_id }}" + when: "'stopped' in ct_runtime_status.stdout" + + - name: Ensure bootstrap directory on Proxmox host + ansible.builtin.file: + path: "{{ proxmox_bootstrap_dir }}" + state: directory + mode: "0700" + + - name: Copy AW bootstrap files to Proxmox host temp + ansible.builtin.copy: + src: "{{ aw_repo_root }}/aw-server/{{ item }}" + dest: "{{ proxmox_bootstrap_dir }}/{{ item }}" + mode: "0644" + loop: "{{ aw_bootstrap_files }}" + + - name: Bootstrap CT OS dependencies + ansible.builtin.command: + argv: + - pct + - exec + - "{{ proxmox_ct_id }}" + - -- + - bash + - -lc + - | + set -euo pipefail + export DEBIAN_FRONTEND=noninteractive + apt-get update + apt-get install -y curl ca-certificates bash unzip xz-utils jq rsync openssh-server + mkdir -p /root/bootstrap /etc/activitywatch + systemctl enable ssh || true + systemctl restart ssh || true + + - name: Push bootstrap files into CT + ansible.builtin.command: + argv: + - pct + - push + - "{{ proxmox_ct_id }}" + - "{{ proxmox_bootstrap_dir }}/{{ item }}" + - "/root/bootstrap/{{ item }}" + loop: "{{ aw_bootstrap_files }}" + + - name: Write AW server env file on Proxmox host temp + ansible.builtin.copy: + dest: "{{ proxmox_bootstrap_dir }}/aw-server.env" + mode: "0600" + content: | + AW_SERVER_VERSION={{ aw_server_version }} + AW_SERVER_DOWNLOAD_URL={{ aw_server_download_url }} + AW_SERVER_BIND_HOST={{ aw_server_bind_host }} + AW_SERVER_PORT={{ aw_server_port }} + AW_SERVER_WEBUI_DIR={{ aw_server_webui_dir }} + AW_SERVER_DATA_DIR={{ aw_server_data_dir }} + AW_SERVER_LOG_DIR={{ aw_server_log_dir }} + AW_SERVER_USER={{ aw_server_user }} + AW_SERVER_GROUP={{ aw_server_group }} + + - name: Push AW server env into CT + ansible.builtin.command: + argv: + - pct + - push + - "{{ proxmox_ct_id }}" + - "{{ proxmox_bootstrap_dir }}/aw-server.env" + - /etc/activitywatch/aw-server.env + + - name: Set mode for env inside CT + ansible.builtin.command: + argv: + - pct + - exec + - "{{ proxmox_ct_id }}" + - -- + - chmod + - "0600" + - /etc/activitywatch/aw-server.env + + - name: Install server and apply RU patch inside CT + ansible.builtin.command: + argv: + - pct + - exec + - "{{ proxmox_ct_id }}" + - -- + - bash + - -lc + - | + set -euo pipefail + chmod +x /root/bootstrap/install_aw_server.sh /root/bootstrap/apply_webui_ru_patch.sh + bash /root/bootstrap/install_aw_server.sh + bash /root/bootstrap/apply_webui_ru_patch.sh + systemctl restart activitywatch-server.service + + - name: Validate AW API from inside CT + ansible.builtin.command: + argv: + - pct + - exec + - "{{ proxmox_ct_id }}" + - -- + - bash + - -lc + - "curl -fsS http://127.0.0.1:{{ aw_server_port }}/api/0/info >/dev/null" + + - name: Validate RU patch hooks in index + ansible.builtin.command: + argv: + - pct + - exec + - "{{ proxmox_ct_id }}" + - -- + - bash + - -lc + - "grep -q 'ru-patch-v5.js' {{ aw_server_webui_dir }}/index.html && grep -q 'sw-cleanup.js' {{ aw_server_webui_dir }}/index.html" + + - name: Show final endpoint + ansible.builtin.debug: + msg: + - "CT {{ proxmox_ct_id }} is provisioned and configured." + - "ActivityWatch endpoint: http://{{ proxmox_ct_ip | regex_replace('/[0-9]+$', '') }}:{{ aw_server_port }}" diff --git a/docs/FULL_DEPLOYMENT_MANUAL_RU.md b/docs/FULL_DEPLOYMENT_MANUAL_RU.md index c93d34f..262921f 100755 --- a/docs/FULL_DEPLOYMENT_MANUAL_RU.md +++ b/docs/FULL_DEPLOYMENT_MANUAL_RU.md @@ -18,6 +18,7 @@ - `/mnt/usb_hdd2/Projects/ActivityWatch-Russian/windows/validate-deployment.ps1` - `/mnt/usb_hdd2/Projects/ActivityWatch-Russian/windows/browser-domains-native-collector.ps1` - `/mnt/usb_hdd2/Projects/ActivityWatch-Russian/ansible/deploy_aw_server.yml` +- `/mnt/usb_hdd2/Projects/ActivityWatch-Russian/ansible/provision_proxmox_ct_and_deploy_aw.yml` --- @@ -51,6 +52,29 @@ cp /mnt/usb_hdd2/Projects/ActivityWatch-Russian/secrets/deploy.secrets.env.examp ## 2) Развёртывание сервера в Proxmox +### 2.0 Ansible full-stack (создание CT + установка AW) + +Подготовьте: + +- `/mnt/usb_hdd2/Projects/ActivityWatch-Russian/ansible/inventory.ini` +- `/mnt/usb_hdd2/Projects/ActivityWatch-Russian/ansible/group_vars/all.yml` +- `/mnt/usb_hdd2/Projects/ActivityWatch-Russian/ansible/group_vars/proxmox.yml` + +Запуск: + +```bash +cd /mnt/usb_hdd2/Projects/ActivityWatch-Russian/ansible +ansible-playbook -i inventory.ini provision_proxmox_ct_and_deploy_aw.yml +``` + +Этот сценарий полностью закрывает: + +- создание CT в Proxmox; +- bootstrap пакетов в CT; +- установку ActivityWatch Server; +- применение RU Web UI patch; +- проверку API. + ### 2.1 Создать LXC контейнер На узле Proxmox: diff --git a/docs/deployment.md b/docs/deployment.md index b4baf68..a069f68 100755 --- a/docs/deployment.md +++ b/docs/deployment.md @@ -1,5 +1,14 @@ # Deployment +## 0. Ansible full-stack вариант (рекомендуется) + +```sh +cd /home/igor/tmp/AWatch-rus/ansible +ansible-playbook -i inventory.ini provision_proxmox_ct_and_deploy_aw.yml +``` + +Этот playbook создаёт CT в Proxmox и полностью разворачивает ActivityWatch внутри контейнера. + ## 1. Подготовить env-файлы На рабочей машине оператора: