---
- name: Развернуть сервер AWatch-rus
hosts: aw_server
become: true
gather_facts: true
vars:
aw_release_root: "/opt/activitywatch/releases"
aw_release_dir: "{{ aw_release_root }}/{{ aw_server_version }}"
aw_archive_path: "/tmp/activitywatch-{{ aw_server_version }}.zip"
aw_bootstrap_dir: "/tmp/aw-rus-bootstrap"
aw_release_install_dir: "{{ aw_release_root }}/aw-server-rust-{{ aw_server_version }}"
aw_ru_patch_cache_bust: "{{ lookup('file', aw_repo_root + '/aw-server/aw-ru-patch.js') | hash('sha1') | truncate(12, true, '') }}"
aw_sw_cleanup_cache_bust: "{{ lookup('file', aw_repo_root + '/aw-server/aw-sw-cleanup.js') | hash('sha1') | truncate(12, true, '') }}"
aw_worktime_classes: "{{ lookup('file', aw_repo_root + '/aw-server/settings/classes-worktime.json') | from_json }}"
aw_default_views: "{{ lookup('file', aw_repo_root + '/aw-server/settings/views-default.json') | from_json }}"
tasks:
- name: Установить базовые пакеты
ansible.builtin.apt:
name:
- curl
- python3-venv
- python3-pip
- rsync
- tesseract-ocr
- tesseract-ocr-rus
- unzip
state: present
update_cache: true
- name: Создать системную группу сервиса
ansible.builtin.group:
name: "{{ aw_server_group }}"
system: true
state: present
- name: Создать системную учётную запись сервиса
ansible.builtin.user:
name: "{{ aw_server_user }}"
group: "{{ aw_server_group }}"
home: "{{ aw_server_data_dir }}"
shell: /usr/sbin/nologin
system: true
create_home: false
- name: Создать обязательные каталоги
ansible.builtin.file:
path: "{{ item }}"
state: directory
mode: "0755"
loop:
- "{{ aw_release_root }}"
- "{{ aw_release_dir }}"
- "{{ aw_release_install_dir }}"
- /opt/activitywatch
- /opt/activitywatch/bin
- "{{ aw_server_webui_dir }}"
- "{{ aw_server_webui_dir }}/js"
- "{{ aw_server_data_dir }}"
- "{{ aw_server_db_path | dirname }}"
- "{{ aw_server_data_dir }}/.config"
- "{{ aw_server_data_dir }}/.config/activitywatch"
- "{{ aw_server_data_dir }}/.config/activitywatch/aw-server-rust"
- "{{ aw_server_data_dir }}/backups"
- "{{ aw_rus_health_state_dir }}"
- "{{ aw_rus_health_validation_dir }}"
- "{{ aw_server_log_dir }}"
- /etc/activitywatch
- "{{ aw_bootstrap_dir }}"
- name: Настроить каталоги ActivityWatch с владельцем сервиса
ansible.builtin.file:
path: "{{ item }}"
state: directory
owner: "{{ aw_server_user }}"
group: "{{ aw_server_group }}"
mode: "0755"
loop:
- /opt/activitywatch
- /opt/activitywatch/bin
- "{{ aw_release_root }}"
- "{{ aw_release_dir }}"
- "{{ aw_release_install_dir }}"
- "{{ aw_server_webui_dir }}"
- "{{ aw_server_webui_dir }}/js"
- "{{ aw_server_data_dir }}"
- "{{ aw_server_db_path | dirname }}"
- "{{ aw_server_data_dir }}/.config"
- "{{ aw_server_data_dir }}/.config/activitywatch"
- "{{ aw_server_data_dir }}/.config/activitywatch/aw-server-rust"
- "{{ aw_server_data_dir }}/backups"
- "{{ aw_rus_health_state_dir }}"
- "{{ aw_rus_health_validation_dir }}"
- "{{ aw_server_log_dir }}"
- name: (Check mode) Пропустить установку релиза ActivityWatch
ansible.builtin.debug:
msg: "ansible_check_mode=true: download/unarchive/install of ActivityWatch release is skipped."
when: ansible_check_mode
- name: Установить релиз ActivityWatch (download/unarchive/install)
when: not ansible_check_mode
block:
- name: Скачать архив релиза ActivityWatch
ansible.builtin.get_url:
url: "{{ aw_server_download_url }}"
dest: "{{ aw_archive_path }}"
mode: "0644"
- name: Распаковать релиз ActivityWatch
ansible.builtin.unarchive:
src: "{{ aw_archive_path }}"
dest: "{{ aw_release_dir }}"
remote_src: true
extra_opts: ["-o"]
- name: Найти распакованный каталог ActivityWatch
ansible.builtin.find:
paths: "{{ aw_release_dir }}"
recurse: true
file_type: directory
patterns: "activitywatch*"
register: aw_release_find
- name: Найти бинарный файл AW server
ansible.builtin.find:
paths: "{{ aw_release_dir }}"
recurse: true
file_type: file
patterns:
- aw-server-rust
- aw-server
register: aw_server_binary_find
- name: Найти index.html WebUI
ansible.builtin.find:
paths: "{{ aw_release_dir }}"
recurse: true
file_type: file
patterns:
- index.html
register: aw_webui_index_find
- name: Сохранить пути распакованного релиза (binary + webui index)
ansible.builtin.set_fact:
aw_release_extracted: "{{ (aw_release_find.files | default([]) | sort(attribute='path') | map(attribute='path') | list | first) | default('') }}"
aw_server_binary_path: >-
{{
(
(
(aw_server_binary_find.files | default([]) | sort(attribute='path') | map(attribute='path') | list)
| select('match', '.*/aw-server-rust$') | list | first
)
| default(
(
(aw_server_binary_find.files | default([]) | sort(attribute='path') | map(attribute='path') | list | first)
),
true
)
) | default('')
}}
aw_webui_index_path: >-
{{
(
(
(aw_webui_index_find.files | default([]) | sort(attribute='path') | map(attribute='path') | list)
| select('search', '/static/index\\.html$') | list | first
)
| default(
(
(aw_webui_index_find.files | default([]) | sort(attribute='path') | map(attribute='path') | list | first)
),
true
)
) | default('')
}}
- name: Сохранить каталог WebUI (dirname index.html)
ansible.builtin.set_fact:
aw_webui_source_path: "{{ aw_webui_index_path | dirname }}"
- name: Проверить, что компоненты релиза найдены
ansible.builtin.assert:
that:
- aw_release_extracted is defined
- aw_release_extracted | length > 0
- aw_server_binary_path is defined
- aw_server_binary_path | length > 0
- aw_webui_source_path is defined
- aw_webui_source_path | length > 0
fail_msg: "Не удалось найти бинарный файл или WebUI в распакованном релизе ActivityWatch."
- name: Создать каталог установленного релиза
ansible.builtin.file:
path: "{{ aw_release_install_dir }}"
state: directory
owner: "{{ aw_server_user }}"
group: "{{ aw_server_group }}"
mode: "0755"
- name: Установить бинарный файл AW server
ansible.builtin.copy:
remote_src: true
src: "{{ aw_server_binary_path }}"
dest: "{{ aw_release_install_dir }}/aw-server-rust"
owner: "{{ aw_server_user }}"
group: "{{ aw_server_group }}"
mode: "0755"
- name: Создать ссылку на активный бинарный файл AW server
ansible.builtin.file:
src: "{{ aw_release_install_dir }}/aw-server-rust"
dest: /opt/activitywatch/bin/aw-server-rust
owner: "{{ aw_server_user }}"
group: "{{ aw_server_group }}"
state: link
force: true
- name: Синхронизировать WebUI в RU каталог
ansible.builtin.command:
cmd: "rsync -a {{ aw_webui_source_path }}/ {{ aw_server_webui_dir }}/"
- name: Настроить владельца файлов /opt/activitywatch
ansible.builtin.file:
path: /opt/activitywatch
state: directory
owner: "{{ aw_server_user }}"
group: "{{ aw_server_group }}"
recurse: true
- name: Установить systemd service из шаблона репозитория
ansible.builtin.copy:
dest: /etc/systemd/system/activitywatch-server.service
mode: "0644"
content: >-
{{
lookup('file', aw_repo_root + '/aw-server/activitywatch-server.service')
| replace('__AW_SERVER_USER__', aw_server_user)
| replace('__AW_SERVER_GROUP__', aw_server_group)
| replace('__AW_SERVER_DATA_DIR__', aw_server_data_dir)
}}
notify:
- Перезагрузить systemd
- Перезапустить activitywatch
- name: (Check mode) Пропустить WebUI patch и запуск сервиса
ansible.builtin.debug:
msg: "ansible_check_mode=true: WebUI patch + service start + API checks are skipped."
when: ansible_check_mode
- name: Применить WebUI RU patch и запустить сервис
when: not ansible_check_mode
block:
- name: Скопировать RU patch файлы WebUI из репозитория
ansible.builtin.copy:
src: "{{ item.src }}"
dest: "{{ item.dest }}"
mode: "{{ item.mode }}"
owner: "{{ aw_server_user }}"
group: "{{ aw_server_group }}"
loop:
- { src: "{{ aw_repo_root }}/aw-server/aw-ru-patch.js", dest: "{{ aw_server_webui_dir }}/js/ru-patch-v5.js", mode: "0644" }
- { src: "{{ aw_repo_root }}/aw-server/aw-sw-cleanup.js", dest: "{{ aw_server_webui_dir }}/js/sw-cleanup.js", mode: "0644" }
- { src: "{{ aw_repo_root }}/aw-server/aw-worktime-panel.js", dest: "{{ aw_server_webui_dir }}/js/aw-worktime-panel.js", mode: "0644" }
- { src: "{{ aw_repo_root }}/aw-server/aw-host-groups.json", dest: "{{ aw_server_webui_dir }}/js/aw-host-groups.json", mode: "0644" }
- name: Создать каталог /root/bootstrap для apply_webui_ru_patch.sh
ansible.builtin.file:
path: /root/bootstrap
state: directory
mode: "0755"
- name: Скопировать RU patch файлы для apply_webui_ru_patch.sh (хотфиксы compiled JS чанков)
ansible.builtin.copy:
src: "{{ item.src }}"
dest: "{{ item.dest }}"
mode: "{{ item.mode }}"
loop:
- { src: "{{ aw_repo_root }}/aw-server/aw-ru-patch.js", dest: "/root/bootstrap/aw-ru-patch.js", mode: "0644" }
- { src: "{{ aw_repo_root }}/aw-server/aw-sw-cleanup.js", dest: "/root/bootstrap/aw-sw-cleanup.js", mode: "0644" }
- { src: "{{ aw_repo_root }}/aw-server/aw-worktime-panel.js", dest: "/root/bootstrap/aw-worktime-panel.js", mode: "0644" }
- { src: "{{ aw_repo_root }}/aw-server/aw-host-groups.json", dest: "/root/bootstrap/aw-host-groups.json", mode: "0644" }
- name: Скопировать apply_webui_ru_patch.sh скрипт
ansible.builtin.copy:
src: "{{ aw_repo_root }}/aw-server/apply_webui_ru_patch.sh"
dest: /opt/activitywatch/aw-server/apply_webui_ru_patch.sh
mode: "0755"
- name: Записать /etc/activitywatch/aw-server.env перед хотфиксами
ansible.builtin.copy:
dest: /etc/activitywatch/aw-server.env
mode: "0640"
owner: root
group: root
content: |
AW_SERVER_BIND_HOST={{ aw_server_bind_host }}
AW_SERVER_PORT={{ aw_server_port }}
AW_SERVER_DATA_DIR={{ aw_server_data_dir }}
AW_SERVER_DB_PATH={{ aw_server_db_path }}
AW_SERVER_LOG_DIR={{ aw_server_log_dir }}
AW_SERVER_WEBUI_DIR={{ aw_server_webui_dir }}
AW_SERVER_USER={{ aw_server_user }}
AW_SERVER_GROUP={{ aw_server_group }}
AW_WORKTIME_REPORT_BASE={{ aw_worktime_report_base }}
AW_WORKTIME_TZ={{ aw_worktime_timezone }}
AW_DLP_IOC_DIR={{ aw_dlp_ioc_workdir }}/output
AW_DLP_POLICY_ENGINE_BIND_HOST={{ aw_dlp_policy_engine_bind_host }}
AW_DLP_POLICY_ENGINE_PORT={{ aw_dlp_policy_engine_port }}
AW_DLP_POLICY_ENGINE_DB_PATH={{ aw_dlp_policy_engine_db_path }}
AW_DLP_CASE_BIND_HOST={{ aw_dlp_case_bind_host }}
AW_DLP_CASE_PORT={{ aw_dlp_case_port }}
AW_DLP_CASE_DB_PATH={{ aw_dlp_case_db_path }}
AW_DLP_COMPLIANCE_REPORT_DIR={{ aw_dlp_compliance_report_dir }}
AW_DLP_COMPLIANCE_TEMPLATE={{ aw_dlp_compliance_template_path }}
AW_SERVER_URL=http://127.0.0.1:5600
XDG_DATA_HOME={{ aw_server_data_dir }}/.local/share
XDG_CONFIG_HOME={{ aw_server_data_dir }}/.config
AW_WORKTIME_INFLUX_ENABLED={{ 'true' if (aw_worktime_influx_enabled | default(false) | bool) else 'false' }}
AW_WORKTIME_INFLUX_URL={{ aw_worktime_influx_url | default('') }}
AW_WORKTIME_INFLUX_ORG={{ aw_worktime_influx_org | default('proxmox') }}
AW_WORKTIME_INFLUX_BUCKET={{ aw_worktime_influx_bucket | default('aw_metrics') }}
AW_WORKTIME_INFLUX_HOSTS={{ aw_worktime_influx_hosts | default('SHARKON2025') }}
AW_WORKTIME_INFLUX_DAYS={{ aw_worktime_influx_days | default('today,yesterday') }}
AW_WORKTIME_INFLUX_TOKEN={{ aw_worktime_influx_token | default('') }}
AW_DLP_INFLUX_ENABLED={{ 'true' if (aw_dlp_influx_enabled | default(false) | bool) else 'false' }}
AW_DLP_INFLUX_URL={{ aw_dlp_influx_url | default('') }}
AW_DLP_INFLUX_ORG={{ aw_dlp_influx_org | default('proxmox') }}
AW_DLP_INFLUX_BUCKET={{ aw_dlp_influx_bucket | default('aw_metrics') }}
AW_DLP_INFLUX_HOSTS={{ aw_dlp_influx_hosts | default('SHARKON2025') }}
AW_DLP_INFLUX_LOOKBACK_DAYS={{ aw_dlp_influx_lookback_days | default(30) }}
AW_DLP_INFLUX_EVENT_LIMIT={{ aw_dlp_influx_event_limit | default(2000) }}
AW_DLP_INFLUX_TOKEN={{ aw_dlp_influx_token | default('') }}
AW_DLP_AW_API_BASE=http://127.0.0.1:5600/api/0
AW_DLP_CASE_API_BASE=http://127.0.0.1:5602/api/0/dlp/cases
AW_EXPECT_START_OF_DAY={{ aw_worktime_start_of_day | default('') }}
AW_EXPECT_ALWAYS_ACTIVE_PATTERN={{ aw_server_always_active_pattern | default('') }}
AW_EXPECT_LANDINGPAGE={{ aw_server_landingpage | default('') }}
AW_HEALTH_STRICT_FILEOPS={{ aw_health_strict_fileops | default(0) }}
AW_MONITORED_WINDOWS_HOST={{ aw_monitored_windows_host }}
AW_MONITORED_WINDOWS_HOSTNAME={{ aw_monitored_windows_hostname }}
AW_RUS_HEALTH_WORKTIME_API={{ aw_rus_health_worktime_api_base | default('http://127.0.0.1:5610') }}
AW_RUS_HEALTH_STATE_DIR={{ aw_rus_health_state_dir }}
AW_RUS_HEALTH_VALIDATION_DIR={{ aw_rus_health_validation_dir }}
AW_RUS_HEALTH_SESSION_EVENTS_MAX_AGE_SECONDS={{ aw_rus_health_session_events_max_age_seconds | default(86400) }}
AW_HAYABUSA_AUTO_CASE_ENABLED={{ 'true' if (aw_hayabusa_auto_case_enabled | default(true) | bool) else 'false' }}
AW_HAYABUSA_AUTO_CASE_MIN_SEVERITY={{ aw_hayabusa_auto_case_min_severity | default('medium') }}
AW_HAYABUSA_TELEGRAM_ENABLED={{ 'true' if (aw_hayabusa_telegram_enabled | default(false) | bool) else 'false' }}
AW_HAYABUSA_TELEGRAM_MIN_SEVERITY={{ aw_hayabusa_telegram_min_severity | default('high') }}
AW_HAYABUSA_TELEGRAM_BOT_TOKEN={{ aw_hayabusa_telegram_bot_token | default('') }}
AW_HAYABUSA_TELEGRAM_CHAT_IDS={{ aw_hayabusa_telegram_chat_ids | default('') }}
- name: Создать каталог DLP policy engine
ansible.builtin.file:
path: /opt/activitywatch/dlp-policy-engine
state: directory
owner: "{{ aw_server_user }}"
group: "{{ aw_server_group }}"
mode: "0755"
when: aw_dlp_policy_engine_enabled | default(false) | bool
- name: Скопировать файлы DLP policy engine
ansible.builtin.copy:
src: "{{ aw_repo_root }}/aw-server/dlp-policy-engine/{{ item }}"
dest: "/opt/activitywatch/dlp-policy-engine/{{ item }}"
owner: "{{ aw_server_user }}"
group: "{{ aw_server_group }}"
mode: "0644"
loop:
- policy_service.py
- policy_schema.py
- policy_storage.py
- policy_distributor.py
- requirements.txt
when: aw_dlp_policy_engine_enabled | default(false) | bool
- name: Создать virtualenv DLP policy engine
ansible.builtin.command:
cmd: python3 -m venv /opt/activitywatch/dlp-policy-engine/.venv
args:
creates: /opt/activitywatch/dlp-policy-engine/.venv/bin/python
when: aw_dlp_policy_engine_enabled | default(false) | bool
- name: Установить зависимости DLP policy engine
ansible.builtin.pip:
requirements: /opt/activitywatch/dlp-policy-engine/requirements.txt
virtualenv: /opt/activitywatch/dlp-policy-engine/.venv
when: aw_dlp_policy_engine_enabled | default(false) | bool
- name: Установить systemd unit DLP policy engine
ansible.builtin.copy:
src: "{{ aw_repo_root }}/aw-server/dlp-policy-engine/dlp-policy-engine.service"
dest: /etc/systemd/system/aw-dlp-policy-engine.service
owner: root
group: root
mode: "0644"
when: aw_dlp_policy_engine_enabled | default(false) | bool
- name: Создать каталог DLP content analysis
ansible.builtin.file:
path: /opt/activitywatch/dlp-content-analysis
state: directory
owner: "{{ aw_server_user }}"
group: "{{ aw_server_group }}"
mode: "0755"
when: aw_dlp_content_analysis_enabled | default(true) | bool
- name: Скопировать файлы DLP content analysis
ansible.builtin.copy:
src: "{{ aw_repo_root }}/aw-server/dlp-content-analysis/"
dest: /opt/activitywatch/dlp-content-analysis/
owner: "{{ aw_server_user }}"
group: "{{ aw_server_group }}"
mode: "0644"
when: aw_dlp_content_analysis_enabled | default(true) | bool
- name: Установить wrapper запуска DLP content analysis через virtualenv
ansible.builtin.copy:
src: "{{ aw_repo_root }}/aw-server/dlp-content-analysis/aw-dlp-content-analyzer.sh"
dest: /usr/local/bin/aw-dlp-content-analyzer
owner: root
group: root
mode: "0755"
when: aw_dlp_content_analysis_enabled | default(true) | bool
- name: Создать virtualenv DLP content analysis
ansible.builtin.command:
cmd: python3 -m venv /opt/activitywatch/dlp-content-analysis/.venv
args:
creates: /opt/activitywatch/dlp-content-analysis/.venv/bin/python
when: aw_dlp_content_analysis_enabled | default(true) | bool
- name: Установить зависимости DLP content analysis
ansible.builtin.pip:
requirements: /opt/activitywatch/dlp-content-analysis/requirements.txt
virtualenv: /opt/activitywatch/dlp-content-analysis/.venv
when: aw_dlp_content_analysis_enabled | default(true) | bool
- name: Создать каталог DLP integrations
ansible.builtin.file:
path: /opt/activitywatch/dlp-integrations
state: directory
owner: "{{ aw_server_user }}"
group: "{{ aw_server_group }}"
mode: "0755"
when: aw_dlp_integrations_enabled | default(true) | bool
- name: Скопировать файлы DLP integrations
ansible.builtin.copy:
src: "{{ aw_repo_root }}/aw-server/dlp-integrations/{{ item }}"
dest: "/opt/activitywatch/dlp-integrations/{{ item }}"
owner: "{{ aw_server_user }}"
group: "{{ aw_server_group }}"
mode: "0644"
loop:
- cef_exporter.py
- syslog_forwarder.py
- webhook_sender.py
- cef-config.yaml
- syslog-forwarder-config.yaml
- webhook-config.yaml
- requirements.txt
when: aw_dlp_integrations_enabled | default(true) | bool
- name: Выставить executable для python scripts DLP integrations
ansible.builtin.file:
path: "/opt/activitywatch/dlp-integrations/{{ item }}"
owner: "{{ aw_server_user }}"
group: "{{ aw_server_group }}"
mode: "0755"
loop:
- cef_exporter.py
- syslog_forwarder.py
- webhook_sender.py
when: aw_dlp_integrations_enabled | default(true) | bool
- name: Создать virtualenv DLP integrations
ansible.builtin.command:
cmd: python3 -m venv /opt/activitywatch/dlp-integrations/.venv
args:
creates: /opt/activitywatch/dlp-integrations/.venv/bin/python
when: aw_dlp_integrations_enabled | default(true) | bool
- name: Установить зависимости DLP integrations
ansible.builtin.pip:
requirements: /opt/activitywatch/dlp-integrations/requirements.txt
virtualenv: /opt/activitywatch/dlp-integrations/.venv
when: aw_dlp_integrations_enabled | default(true) | bool
- name: Создать state каталог DLP integrations
ansible.builtin.file:
path: /var/lib/activitywatch/dlp-integrations
state: directory
owner: "{{ aw_server_user }}"
group: "{{ aw_server_group }}"
mode: "0755"
when: aw_dlp_integrations_enabled | default(true) | bool
- name: Установить systemd unit CEF exporter
ansible.builtin.copy:
src: "{{ aw_repo_root }}/aw-server/dlp-integrations/cef-exporter.service"
dest: /etc/systemd/system/aw-dlp-cef-exporter.service
owner: root
group: root
mode: "0644"
when: aw_dlp_integrations_enabled | default(true) | bool
- name: Установить systemd timer CEF exporter
ansible.builtin.copy:
src: "{{ aw_repo_root }}/aw-server/dlp-integrations/cef-exporter.timer"
dest: /etc/systemd/system/aw-dlp-cef-exporter.timer
owner: root
group: root
mode: "0644"
when: aw_dlp_integrations_enabled | default(true) | bool
- name: Установить systemd unit syslog forwarder
ansible.builtin.copy:
src: "{{ aw_repo_root }}/aw-server/dlp-integrations/syslog-forwarder.service"
dest: /etc/systemd/system/aw-dlp-syslog-forwarder.service
owner: root
group: root
mode: "0644"
when: aw_dlp_integrations_enabled | default(true) | bool
- name: Установить systemd timer syslog forwarder
ansible.builtin.copy:
src: "{{ aw_repo_root }}/aw-server/dlp-integrations/syslog-forwarder.timer"
dest: /etc/systemd/system/aw-dlp-syslog-forwarder.timer
owner: root
group: root
mode: "0644"
when: aw_dlp_integrations_enabled | default(true) | bool
- name: Установить systemd unit webhook sender
ansible.builtin.copy:
src: "{{ aw_repo_root }}/aw-server/dlp-integrations/webhook-sender.service"
dest: /etc/systemd/system/aw-dlp-webhook-sender.service
owner: root
group: root
mode: "0644"
when: aw_dlp_integrations_enabled | default(true) | bool
- name: Установить systemd timer webhook sender
ansible.builtin.copy:
src: "{{ aw_repo_root }}/aw-server/dlp-integrations/webhook-sender.timer"
dest: /etc/systemd/system/aw-dlp-webhook-sender.timer
owner: root
group: root
mode: "0644"
when: aw_dlp_integrations_enabled | default(true) | bool
- name: Создать каталог DLP case management
ansible.builtin.file:
path: /opt/activitywatch/dlp-case-management
state: directory
owner: "{{ aw_server_user }}"
group: "{{ aw_server_group }}"
mode: "0755"
when: aw_dlp_case_management_enabled | default(true) | bool
- name: Скопировать файлы DLP case management
ansible.builtin.copy:
src: "{{ aw_repo_root }}/aw-server/dlp-case-management/{{ item }}"
dest: "/opt/activitywatch/dlp-case-management/{{ item }}"
owner: "{{ aw_server_user }}"
group: "{{ aw_server_group }}"
mode: "0644"
loop:
- case_service.py
- case_rules.py
- case_schema.py
- case_storage.py
- evidence_chain.py
- requirements.txt
when: aw_dlp_case_management_enabled | default(true) | bool
- name: Выставить executable для case_service
ansible.builtin.file:
path: /opt/activitywatch/dlp-case-management/case_service.py
owner: "{{ aw_server_user }}"
group: "{{ aw_server_group }}"
mode: "0755"
when: aw_dlp_case_management_enabled | default(true) | bool
- name: Создать virtualenv DLP case management
ansible.builtin.command:
cmd: python3 -m venv /opt/activitywatch/dlp-case-management/.venv
args:
creates: /opt/activitywatch/dlp-case-management/.venv/bin/python
when: aw_dlp_case_management_enabled | default(true) | bool
- name: Установить зависимости DLP case management
ansible.builtin.pip:
requirements: /opt/activitywatch/dlp-case-management/requirements.txt
virtualenv: /opt/activitywatch/dlp-case-management/.venv
when: aw_dlp_case_management_enabled | default(true) | bool
- name: Установить systemd unit DLP case management
ansible.builtin.copy:
src: "{{ aw_repo_root }}/aw-server/dlp-case-management/case-service.service"
dest: /etc/systemd/system/aw-dlp-case-management.service
owner: root
group: root
mode: "0644"
when: aw_dlp_case_management_enabled | default(true) | bool
- name: Создать каталоги DLP compliance
ansible.builtin.file:
path: "{{ item }}"
state: directory
owner: "{{ aw_server_user }}"
group: "{{ aw_server_group }}"
mode: "0755"
loop:
- /opt/activitywatch/dlp-compliance
- /opt/activitywatch/dlp-compliance/templates
- "{{ aw_dlp_compliance_report_dir }}"
when: aw_dlp_compliance_enabled | default(true) | bool
- name: Скопировать файлы DLP compliance
ansible.builtin.copy:
src: "{{ aw_repo_root }}/aw-server/dlp-compliance/{{ item.src }}"
dest: "{{ item.dest }}"
owner: "{{ aw_server_user }}"
group: "{{ aw_server_group }}"
mode: "{{ item.mode }}"
loop:
- { src: "report_generator.py", dest: "/opt/activitywatch/dlp-compliance/report_generator.py", mode: "0755" }
- { src: "compliance_scheduler.py", dest: "/opt/activitywatch/dlp-compliance/compliance_scheduler.py", mode: "0755" }
- { src: "requirements.txt", dest: "/opt/activitywatch/dlp-compliance/requirements.txt", mode: "0644" }
- { src: "templates/152-fz-report.html", dest: "/opt/activitywatch/dlp-compliance/templates/152-fz-report.html", mode: "0644" }
- { src: "templates/pci-dss-report.html", dest: "/opt/activitywatch/dlp-compliance/templates/pci-dss-report.html", mode: "0644" }
- { src: "report-scheduler.service", dest: "/etc/systemd/system/aw-dlp-report-scheduler.service", mode: "0644" }
- { src: "report-scheduler.timer", dest: "/etc/systemd/system/aw-dlp-report-scheduler.timer", mode: "0644" }
when: aw_dlp_compliance_enabled | default(true) | bool
- name: Создать virtualenv DLP compliance
ansible.builtin.command:
cmd: python3 -m venv /opt/activitywatch/dlp-compliance/.venv
args:
creates: /opt/activitywatch/dlp-compliance/.venv/bin/python
when: aw_dlp_compliance_enabled | default(true) | bool
- name: Установить зависимости DLP compliance
ansible.builtin.pip:
requirements: /opt/activitywatch/dlp-compliance/requirements.txt
virtualenv: /opt/activitywatch/dlp-compliance/.venv
when: aw_dlp_compliance_enabled | default(true) | bool
- name: Установить dlp-admin-cli
ansible.builtin.copy:
src: "{{ aw_repo_root }}/scripts/dlp-admin-cli.py"
dest: /usr/local/bin/dlp-admin-cli.py
owner: root
group: root
mode: "0755"
- name: Установить скрипт AW worktime API
ansible.builtin.copy:
src: "{{ aw_repo_root }}/aw-server/aw-worktime-api.py"
dest: /usr/local/bin/aw-worktime-api.py
owner: root
group: root
mode: "0755"
- name: Установить systemd unit AW worktime API
ansible.builtin.copy:
src: "{{ aw_repo_root }}/aw-server/aw-worktime-api.service"
dest: /etc/systemd/system/aw-worktime-api.service
owner: root
group: root
mode: "0644"
- name: Установить скрипт AW worktime UI bridge
ansible.builtin.copy:
src: "{{ aw_repo_root }}/aw-server/aw-worktime-ui-bridge.py"
dest: /usr/local/bin/aw-worktime-ui-bridge.py
owner: root
group: root
mode: "0755"
- name: Установить скрипт AW worktime autoheal
ansible.builtin.copy:
src: "{{ aw_repo_root }}/aw-server/aw-worktime-autoheal.sh"
dest: /usr/local/bin/aw-worktime-autoheal.sh
owner: root
group: root
mode: "0755"
- name: Установить скрипт AW worktime Influx exporter
ansible.builtin.copy:
src: "{{ aw_repo_root }}/aw-server/aw-worktime-influx-exporter.py"
dest: /usr/local/bin/aw-worktime-influx-exporter.py
owner: root
group: root
mode: "0755"
when: aw_worktime_influx_enabled | default(false) | bool
- name: Установить скрипт AW DLP Influx exporter
ansible.builtin.copy:
src: "{{ aw_repo_root }}/aw-server/aw-dlp-influx-exporter.py"
dest: /usr/local/bin/aw-dlp-influx-exporter.py
owner: root
group: root
mode: "0755"
when: aw_dlp_influx_enabled | default(false) | bool
- name: Установить скрипт aw-health-check
ansible.builtin.copy:
src: "{{ aw_repo_root }}/aw-server/health-check.sh"
dest: /usr/local/bin/aw-health-check
owner: root
group: root
mode: "0755"
- name: Установить скрипт dlp-health-check
ansible.builtin.copy:
src: "{{ aw_repo_root }}/scripts/dlp-health-check.py"
dest: /usr/local/bin/dlp-health-check
owner: root
group: root
mode: "0755"
- name: Установить скрипт aw-rus-healthd
ansible.builtin.copy:
src: "{{ aw_repo_root }}/aw-server/aw-rus-healthd.py"
dest: /usr/local/bin/aw-rus-healthd.py
owner: root
group: root
mode: "0755"
- name: Установить systemd unit AW worktime UI bridge
ansible.builtin.copy:
src: "{{ aw_repo_root }}/aw-server/aw-worktime-ui-bridge.service"
dest: /etc/systemd/system/aw-worktime-ui-bridge.service
owner: root
group: root
mode: "0644"
- name: Установить systemd timer AW worktime UI bridge
ansible.builtin.copy:
src: "{{ aw_repo_root }}/aw-server/aw-worktime-ui-bridge.timer"
dest: /etc/systemd/system/aw-worktime-ui-bridge.timer
owner: root
group: root
mode: "0644"
- name: Установить systemd unit AW worktime autoheal
ansible.builtin.copy:
src: "{{ aw_repo_root }}/aw-server/aw-worktime-autoheal.service"
dest: /etc/systemd/system/aw-worktime-autoheal.service
owner: root
group: root
mode: "0644"
- name: Установить systemd timer AW worktime autoheal
ansible.builtin.copy:
src: "{{ aw_repo_root }}/aw-server/aw-worktime-autoheal.timer"
dest: /etc/systemd/system/aw-worktime-autoheal.timer
owner: root
group: root
mode: "0644"
- name: Установить systemd unit AW-RUS healthd
ansible.builtin.copy:
src: "{{ aw_repo_root }}/aw-server/aw-rus-healthd.service"
dest: /etc/systemd/system/aw-rus-healthd.service
owner: root
group: root
mode: "0644"
- name: Установить systemd timer AW-RUS healthd
ansible.builtin.copy:
src: "{{ aw_repo_root }}/aw-server/aw-rus-healthd.timer"
dest: /etc/systemd/system/aw-rus-healthd.timer
owner: root
group: root
mode: "0644"
- name: Установить systemd unit AW worktime Influx exporter
ansible.builtin.copy:
src: "{{ aw_repo_root }}/aw-server/aw-worktime-influx-exporter.service"
dest: /etc/systemd/system/aw-worktime-influx-exporter.service
owner: root
group: root
mode: "0644"
when: aw_worktime_influx_enabled | default(false) | bool
- name: Установить systemd timer AW worktime Influx exporter
ansible.builtin.copy:
src: "{{ aw_repo_root }}/aw-server/aw-worktime-influx-exporter.timer"
dest: /etc/systemd/system/aw-worktime-influx-exporter.timer
owner: root
group: root
mode: "0644"
when: aw_worktime_influx_enabled | default(false) | bool
- name: Установить systemd unit AW DLP Influx exporter
ansible.builtin.copy:
src: "{{ aw_repo_root }}/aw-server/aw-dlp-influx-exporter.service"
dest: /etc/systemd/system/aw-dlp-influx-exporter.service
owner: root
group: root
mode: "0644"
when: aw_dlp_influx_enabled | default(false) | bool
- name: Установить systemd timer AW DLP Influx exporter
ansible.builtin.copy:
src: "{{ aw_repo_root }}/aw-server/aw-dlp-influx-exporter.timer"
dest: /etc/systemd/system/aw-dlp-influx-exporter.timer
owner: root
group: root
mode: "0644"
when: aw_dlp_influx_enabled | default(false) | bool
- name: Перезагрузить systemd после установки AW worktime API
ansible.builtin.systemd:
daemon_reload: true
- name: Включить таймер AW-RUS healthd
ansible.builtin.systemd:
name: aw-rus-healthd.timer
enabled: true
state: started
- name: Включить и перезапустить DLP policy engine
ansible.builtin.systemd:
name: aw-dlp-policy-engine.service
enabled: true
state: restarted
when: aw_dlp_policy_engine_enabled | default(false) | bool
- name: Включить и перезапустить timer CEF exporter
ansible.builtin.systemd:
name: aw-dlp-cef-exporter.timer
enabled: true
state: restarted
when: aw_dlp_integrations_enabled | default(true) | bool
- name: Включить и перезапустить timer syslog forwarder
ansible.builtin.systemd:
name: aw-dlp-syslog-forwarder.timer
enabled: true
state: restarted
when: aw_dlp_integrations_enabled | default(true) | bool
- name: Включить и перезапустить timer webhook sender
ansible.builtin.systemd:
name: aw-dlp-webhook-sender.timer
enabled: true
state: restarted
when: aw_dlp_integrations_enabled | default(true) | bool
- name: Включить и перезапустить DLP case management
ansible.builtin.systemd:
name: aw-dlp-case-management.service
enabled: true
state: restarted
when: aw_dlp_case_management_enabled | default(true) | bool
- name: Включить и перезапустить timer DLP compliance report
ansible.builtin.systemd:
name: aw-dlp-report-scheduler.timer
enabled: true
state: restarted
when: aw_dlp_compliance_enabled | default(true) | bool
- name: Выполнить разовый прогон DLP compliance report
ansible.builtin.systemd:
name: aw-dlp-report-scheduler.service
state: started
failed_when: false
when: aw_dlp_compliance_enabled | default(true) | bool
- name: Включить и перезапустить AW worktime API
ansible.builtin.systemd:
name: aw-worktime-api.service
enabled: true
state: restarted
- name: Отключить legacy timer aw-worktime-afk-bridge (если есть)
ansible.builtin.systemd:
name: aw-worktime-afk-bridge.timer
enabled: false
state: stopped
failed_when: false
- name: Включить и перезапустить AW worktime UI bridge timer
ansible.builtin.systemd:
name: aw-worktime-ui-bridge.timer
enabled: true
state: restarted
- name: Выполнить разовый прогон AW worktime UI bridge
ansible.builtin.systemd:
name: aw-worktime-ui-bridge.service
state: started
failed_when: false
- name: Включить и перезапустить AW worktime autoheal timer
ansible.builtin.systemd:
name: aw-worktime-autoheal.timer
enabled: true
state: restarted
- name: Выполнить разовый прогон AW worktime autoheal
ansible.builtin.systemd:
name: aw-worktime-autoheal.service
state: started
failed_when: false
- name: Включить и перезапустить AW worktime Influx exporter timer
ansible.builtin.systemd:
name: aw-worktime-influx-exporter.timer
enabled: true
state: restarted
when: aw_worktime_influx_enabled | default(false) | bool
- name: Выполнить разовый прогон AW worktime Influx exporter
ansible.builtin.systemd:
name: aw-worktime-influx-exporter.service
state: started
failed_when: false
when: aw_worktime_influx_enabled | default(false) | bool
- name: Включить и перезапустить AW DLP Influx exporter timer
ansible.builtin.systemd:
name: aw-dlp-influx-exporter.timer
enabled: true
state: restarted
when: aw_dlp_influx_enabled | default(false) | bool
- name: Выполнить разовый прогон AW DLP Influx exporter
ansible.builtin.systemd:
name: aw-dlp-influx-exporter.service
state: started
failed_when: false
when: aw_dlp_influx_enabled | default(false) | bool
- name: Применить хотфиксы compiled JS чанков (Trends, Timespiral, Category helper)
ansible.builtin.command:
cmd: "/opt/activitywatch/aw-server/apply_webui_ru_patch.sh"
register: apply_ru_patch_result
failed_when: false
- name: Вывести результат применения хотфиксов
ansible.builtin.debug:
msg: "apply_webui_ru_patch.sh: {{ apply_ru_patch_result.stdout }}"
- name: Проверить наличие index.html после копирования
ansible.builtin.stat:
path: "{{ aw_server_webui_dir }}/index.html"
register: aw_webui_ru_index
- name: Проверить, что index.html доступен для RU patch
ansible.builtin.assert:
that:
- aw_webui_ru_index.stat.exists
- (aw_webui_ru_index.stat.size | default(0) | int) > 0
fail_msg: "Не найден index.html WebUI для применения RU patch."
- name: Проверить, что index.html не опустел после применения RU patch
ansible.builtin.stat:
path: "{{ aw_server_webui_dir }}/index.html"
register: aw_webui_ru_index_after_patch
- name: Подтвердить, что index.html остался непустым
ansible.builtin.assert:
that:
- aw_webui_ru_index_after_patch.stat.exists
- (aw_webui_ru_index_after_patch.stat.size | default(0) | int) > 0
fail_msg: "index.html WebUI пуст после RU patch."
- name: Удалить старые теги RU patch из index.html
ansible.builtin.replace:
path: "{{ aw_server_webui_dir }}/index.html"
regexp: ''
replace: ''
- name: Добавить cleanup script RU patch в index.html
ansible.builtin.replace:
path: "{{ aw_server_webui_dir }}/index.html"
regexp: ''
replace: ''
- name: Добавить загрузчик RU patch перед закрытием body
ansible.builtin.replace:
path: "{{ aw_server_webui_dir }}/index.html"
regexp: '