feat(ansible): add full Proxmox zero-to-service provisioning playbook

This commit is contained in:
igor04091968
2026-04-25 15:43:31 +03:00
parent 92eaa0635c
commit 9e53272ce9
7 changed files with 308 additions and 1 deletions
+21 -1
View File
@@ -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`.
+18
View File
@@ -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"
+3
View File
@@ -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
@@ -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 }}"