chore(install): sync playbooks and installers with pve audit
This commit is contained in:
@@ -12,6 +12,9 @@
|
||||
- aw-server.env.example
|
||||
- aw-ru-patch.js
|
||||
- aw-sw-cleanup.js
|
||||
- aw-host-groups.json
|
||||
- settings/classes-worktime.json
|
||||
- settings/views-default.json
|
||||
|
||||
tasks:
|
||||
- name: Execute single-CT provisioning workflow
|
||||
|
||||
@@ -12,6 +12,9 @@
|
||||
- aw-server.env.example
|
||||
- aw-ru-patch.js
|
||||
- aw-sw-cleanup.js
|
||||
- aw-host-groups.json
|
||||
- settings/classes-worktime.json
|
||||
- settings/views-default.json
|
||||
|
||||
tasks:
|
||||
- name: Validate CT matrix is provided
|
||||
|
||||
@@ -9,13 +9,16 @@ fi
|
||||
|
||||
source "$ENV_FILE"
|
||||
|
||||
WEBUI_DIR="${AW_SERVER_WEBUI_DIR:-/opt/activitywatch/webui-ru}"
|
||||
WEBUI_DIR="${AW_SERVER_WEBUI_DIR:-${AW_WEBUI_DIR:-/opt/activitywatch/webui-ru}}"
|
||||
PATCH_JS_SRC="/root/bootstrap/aw-ru-patch.js"
|
||||
SW_CLEANUP_SRC="/root/bootstrap/aw-sw-cleanup.js"
|
||||
HOST_GROUPS_SRC="/root/bootstrap/aw-host-groups.json"
|
||||
INDEX_HTML="$WEBUI_DIR/index.html"
|
||||
SERVICE_WORKER="$WEBUI_DIR/service-worker.js"
|
||||
TS=$(date +%Y%m%d%H%M%S)
|
||||
PATCH_TARGET="$WEBUI_DIR/js/ru-patch-v5.js"
|
||||
SW_TARGET="$WEBUI_DIR/js/sw-cleanup.js"
|
||||
HOST_GROUPS_TARGET="$WEBUI_DIR/js/aw-host-groups.json"
|
||||
TRENDS_NEEDLE='this.activityStore.query_category_time_by_period(r)'
|
||||
TRENDS_REPLACEMENT='this.activityStore.ensure_loaded(r)'
|
||||
TIMESPIRAL_NEEDLE='start:new Date("2022-08-08")'
|
||||
@@ -27,14 +30,17 @@ TIMESPIRAL_REPLACEMENT='start:new Date(Date.now()-12*36e5)'
|
||||
[[ -f "$INDEX_HTML" ]] || { echo "missing $INDEX_HTML" >&2; exit 1; }
|
||||
|
||||
install -d "$WEBUI_DIR/js"
|
||||
install -m 0644 "$PATCH_JS_SRC" "$WEBUI_DIR/js/aw-ru-patch.js"
|
||||
install -m 0644 "$SW_CLEANUP_SRC" "$WEBUI_DIR/js/aw-sw-cleanup.js"
|
||||
install -m 0644 "$HOST_GROUPS_SRC" "$WEBUI_DIR/js/aw-host-groups.json"
|
||||
install -m 0644 "$PATCH_JS_SRC" "$PATCH_TARGET"
|
||||
install -m 0644 "$SW_CLEANUP_SRC" "$SW_TARGET"
|
||||
install -m 0644 "$HOST_GROUPS_SRC" "$HOST_GROUPS_TARGET"
|
||||
cp "$INDEX_HTML" "$INDEX_HTML.bak.$TS"
|
||||
|
||||
sed -i '/aw-ru-patch.js/d;/aw-sw-cleanup.js/d' "$INDEX_HTML"
|
||||
sed -i 's#</head>#<script src="/js/aw-sw-cleanup.js"></script></head>#' "$INDEX_HTML"
|
||||
sed -i 's#</body>#<script defer="defer" src="/js/aw-ru-patch.js"></script></body>#' "$INDEX_HTML"
|
||||
patch_hash="$(sha1sum "$PATCH_TARGET" | awk '{print substr($1,1,12)}')"
|
||||
sw_hash="$(sha1sum "$SW_TARGET" | awk '{print substr($1,1,12)}')"
|
||||
|
||||
sed -i '/ru-patch-v5.js/d;/sw-cleanup.js/d;/aw-ru-patch.js/d;/aw-sw-cleanup.js/d' "$INDEX_HTML"
|
||||
sed -i "s#</head>#<script src=\"/js/sw-cleanup.js?v=$sw_hash\"></script></head>#" "$INDEX_HTML"
|
||||
sed -i "s#</body>#<script defer=\"defer\" src=\"/js/ru-patch-v5.js?v=$patch_hash\"></script></body>#" "$INDEX_HTML"
|
||||
cp "$SW_CLEANUP_SRC" "$SERVICE_WORKER"
|
||||
|
||||
trends_chunk="$(grep -Rsl "$TRENDS_NEEDLE" "$WEBUI_DIR/js"/*.js 2>/dev/null | head -n 1 || true)"
|
||||
@@ -79,4 +85,4 @@ else
|
||||
echo "Timespiral hotfix skipped: chunk not found"
|
||||
fi
|
||||
|
||||
echo "RU patch applied to $WEBUI_DIR"
|
||||
echo "RU patch applied to $WEBUI_DIR (ru-patch-v5.js?v=$patch_hash)"
|
||||
|
||||
@@ -21,6 +21,10 @@ required_vars=(
|
||||
AW_SERVER_GROUP
|
||||
)
|
||||
|
||||
BOOTSTRAP_DIR="/root/bootstrap"
|
||||
VIEWS_JSON="$BOOTSTRAP_DIR/settings/views-default.json"
|
||||
CLASSES_JSON="$BOOTSTRAP_DIR/settings/classes-worktime.json"
|
||||
|
||||
for var_name in "${required_vars[@]}"; do
|
||||
if [[ -z "${!var_name:-}" ]]; then
|
||||
echo "missing required variable: $var_name" >&2
|
||||
@@ -84,3 +88,30 @@ systemctl daemon-reload
|
||||
systemctl enable activitywatch-server.service
|
||||
systemctl restart activitywatch-server.service
|
||||
systemctl --no-pager --full status activitywatch-server.service || true
|
||||
|
||||
for _ in $(seq 1 20); do
|
||||
if curl -fsS "http://127.0.0.1:${AW_SERVER_PORT}/api/0/info" >/dev/null 2>&1; then
|
||||
break
|
||||
fi
|
||||
sleep 2
|
||||
done
|
||||
|
||||
if [[ -f "$CLASSES_JSON" ]]; then
|
||||
curl -fsS -X POST \
|
||||
-H 'Content-Type: application/json' \
|
||||
--data-binary @"$CLASSES_JSON" \
|
||||
"http://127.0.0.1:${AW_SERVER_PORT}/api/0/settings/classes" >/dev/null
|
||||
echo "Applied worktime classes from $CLASSES_JSON"
|
||||
else
|
||||
echo "Worktime classes bootstrap not found, skipped: $CLASSES_JSON"
|
||||
fi
|
||||
|
||||
if [[ -f "$VIEWS_JSON" ]]; then
|
||||
curl -fsS -X POST \
|
||||
-H 'Content-Type: application/json' \
|
||||
--data-binary @"$VIEWS_JSON" \
|
||||
"http://127.0.0.1:${AW_SERVER_PORT}/api/0/settings/views" >/dev/null
|
||||
echo "Applied baseline views from $VIEWS_JSON"
|
||||
else
|
||||
echo "Views bootstrap not found, skipped: $VIEWS_JSON"
|
||||
fi
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -1,28 +1,37 @@
|
||||
KIT_DIR=install-kit-awindows-20260427-211240
|
||||
CREATED_AT=2026-04-27T21:14:11+03:00
|
||||
|
||||
FILES:
|
||||
/home/igor/tmp/AWatch-rus/install-kit-awindows-20260427-211240/MANIFEST.txt
|
||||
/home/igor/tmp/AWatch-rus/install-kit-awindows-20260427-211240/README-INSTALL-KIT.txt
|
||||
/home/igor/tmp/AWatch-rus/install-kit-awindows-20260427-211240/ansible/README.md
|
||||
/home/igor/tmp/AWatch-rus/install-kit-awindows-20260427-211240/ansible/deploy_aw_windows_phase2.yml
|
||||
/home/igor/tmp/AWatch-rus/install-kit-awindows-20260427-211240/ansible/windows.example.yml
|
||||
/home/igor/tmp/AWatch-rus/install-kit-awindows-20260427-211240/server-configs-192.168.100.21/phase2-admin.deployment-config.json
|
||||
/home/igor/tmp/AWatch-rus/install-kit-awindows-20260427-211240/server-configs-192.168.100.21/phase2-u2u5.deployment-config.json
|
||||
/home/igor/tmp/AWatch-rus/install-kit-awindows-20260427-211240/server-configs-192.168.100.21/phase2-user1.deployment-config.json
|
||||
/home/igor/tmp/AWatch-rus/install-kit-awindows-20260427-211240/windows/ActivityWatch.Windows.Common.psd1
|
||||
/home/igor/tmp/AWatch-rus/install-kit-awindows-20260427-211240/windows/ActivityWatch.Windows.Common.psm1
|
||||
/home/igor/tmp/AWatch-rus/install-kit-awindows-20260427-211240/windows/browser-domains-native-collector.ps1
|
||||
/home/igor/tmp/AWatch-rus/install-kit-awindows-20260427-211240/windows/deploy-domain-users.ps1
|
||||
/home/igor/tmp/AWatch-rus/install-kit-awindows-20260427-211240/windows/deploy-ensemble.ps1
|
||||
/home/igor/tmp/AWatch-rus/install-kit-awindows-20260427-211240/windows/deploy-single-user.ps1
|
||||
/home/igor/tmp/AWatch-rus/install-kit-awindows-20260427-211240/windows/dlp-endpoint-signals-collector.ps1
|
||||
/home/igor/tmp/AWatch-rus/install-kit-awindows-20260427-211240/windows/dlp-policy.example.json
|
||||
/home/igor/tmp/AWatch-rus/install-kit-awindows-20260427-211240/windows/hardening-recovery.ps1
|
||||
/home/igor/tmp/AWatch-rus/install-kit-awindows-20260427-211240/windows/validate-deployment.ps1
|
||||
/home/igor/tmp/AWatch-rus/install-kit-awindows-20260427-211240/windows/web-category-rules.example.json
|
||||
|
||||
|
||||
SHA256:
|
||||
40bdf651a876f1f545c06c9191ff5d9ec3ca1ce75d3edf1d647e3e2fbafece52 /home/igor/tmp/AWatch-rus/install-kit-awindows-20260427-211240.tar.gz
|
||||
e7e020bff342070d55d2489d9a5e40822543a518863a97cd46865ccf00f64399 /home/igor/tmp/AWatch-rus/install-kit-awindows-20260427-211240.zip
|
||||
6e1f304f468d77f12df67face6afaaca5bbcfb1496f43df4e4fa0557cf847829 install-kit-awindows-20260427-211240/README-INSTALL-KIT.txt
|
||||
a11f41827769be915f73d0de2c5503b05f61ccf56f70a50845771bcb79c5ebb7 install-kit-awindows-20260427-211240/ansible/README.md
|
||||
02ca96f5ecc6abf89ab3271bd08add5795dbba2281168f158d96166f557e33f0 install-kit-awindows-20260427-211240/ansible/deploy_aw_pfsense_poller.yml
|
||||
7c1ad9363412e802f4272f2e91a1d9f26be722eaf22e654c0a2512b0cebbbfd0 install-kit-awindows-20260427-211240/ansible/deploy_aw_server.yml
|
||||
d5c42e6fe49c14a0769517ff28184139e467d40f22d4a632630c42ed1ff34ce5 install-kit-awindows-20260427-211240/ansible/deploy_aw_windows_phase2.yml
|
||||
bc791462b9c00adc8c68ed81e2a7697c560bdbc46f156b4840c7bca1dee2157d install-kit-awindows-20260427-211240/ansible/group_vars/all.example.yml
|
||||
95696c243ab331f06e77a40a9800c4b6668de77675ebbdf2ef54ae49e1b18874 install-kit-awindows-20260427-211240/ansible/group_vars/pfsense-poller.example.yml
|
||||
c5cab36645065815571c99f6d360f910dcccbb54b780c8bfd526a6cdc3684e19 install-kit-awindows-20260427-211240/ansible/group_vars/proxmox-matrix.example.yml
|
||||
35a33c8a1c75ded5e85c6b79e0b3efde07959ff61ee5f66d83b7e0c2abe87fc5 install-kit-awindows-20260427-211240/ansible/group_vars/proxmox.example.yml
|
||||
69368b7adb7711fa81304866373e61ed464bcc23a08e4509fa54655b05f95790 install-kit-awindows-20260427-211240/ansible/group_vars/windows.example.yml
|
||||
00064ce5187569fb3221ddd45c2ad7eb37cd50b2a0a832ddf7843e4ff461849a install-kit-awindows-20260427-211240/ansible/inventory.example.ini
|
||||
bbef175cb77dd53aa07452dbb2fe8797f38b58f42372005c3404c8dc9d6f8e13 install-kit-awindows-20260427-211240/ansible/provision_proxmox_ct_and_deploy_aw.yml
|
||||
b8f8b6bc504a51cd87db3f46c35a27295b395ea516533068f96af35f8b720434 install-kit-awindows-20260427-211240/ansible/provision_proxmox_ct_matrix_and_deploy_aw.yml
|
||||
d35bc97b6de18f0006cbbad4adf8a8a5db8ed912997d8fc47c7f11fa9247e907 install-kit-awindows-20260427-211240/ansible/tasks/provision_ct_and_deploy_aw.yml
|
||||
a50dbadbf619342c2178e255b68f69a36503756daf80eedd9170311c63964f2e install-kit-awindows-20260427-211240/aw-server/activitywatch-server.service
|
||||
1ef77d865937a8fac15e47fd95b046fc713306f7e0b5a386a9dadd1d4c6ad0be install-kit-awindows-20260427-211240/aw-server/apply_webui_ru_patch.sh
|
||||
07d4e583f6e9757a11f01558e1f15cfd73c4d82695f1768204f2f50621712168 install-kit-awindows-20260427-211240/aw-server/aw-host-groups.json
|
||||
76d9d3f3b1984fb2d668bc3bab6bb2a6300c0e5e2cae1b123da7237ca13484e3 install-kit-awindows-20260427-211240/aw-server/aw-ru-patch.js
|
||||
7c5952f8f0a8590e849ea8381bfcd7059b138250bca8551bd5625f395eb66cd8 install-kit-awindows-20260427-211240/aw-server/aw-server.env.example
|
||||
98c0bed353bbda0fa7a69df23f3b008cb0e8e70cdff6cc63330d4caf79fd3280 install-kit-awindows-20260427-211240/aw-server/aw-sw-cleanup.js
|
||||
dce731fdfdcfd773c154d12dbd6b9e621a0bff17ced5a05a65f0fdcb1adcb70f install-kit-awindows-20260427-211240/aw-server/install_aw_server.sh
|
||||
1856e9f44636030b0cb9ece37ba2a0618eb5187fa82c7969976c1bb5f10fc622 install-kit-awindows-20260427-211240/aw-server/settings/classes-worktime.json
|
||||
ff07b90cb6a7f09b27d522307cf55b0359e136a2e695190b8564e859f14f9204 install-kit-awindows-20260427-211240/aw-server/settings/views-default.json
|
||||
59307d284caa74eb3dc129765f9db93b6e8dfd5b1d960b98f347a332b23f82dc install-kit-awindows-20260427-211240/server-configs-192.168.100.21/phase2-admin.deployment-config.json
|
||||
f2cee1872bf274f15dcfb8fb595fb20a11d228a4bae0930dc6cb918a6f800756 install-kit-awindows-20260427-211240/server-configs-192.168.100.21/phase2-u2u5.deployment-config.json
|
||||
6aefedcdac8c1d3823c9f4065b051a67a221a3e9424c913a673667b2a23ea1e7 install-kit-awindows-20260427-211240/server-configs-192.168.100.21/phase2-user1.deployment-config.json
|
||||
33aa34b89246d6c079ef9afe2f5cd153bd9d5946b69a175ff6fd678c77f61da5 install-kit-awindows-20260427-211240/windows/ActivityWatch.Windows.Common.psd1
|
||||
d506614168227fa01fa481289079b432b6d8846d5ee8961cff8c21fd0bf7ea8f install-kit-awindows-20260427-211240/windows/ActivityWatch.Windows.Common.psm1
|
||||
2a0b94ddad43a6bc684037243e636a54c168d8d4ad25b29778c4d78180da2532 install-kit-awindows-20260427-211240/windows/browser-domains-native-collector.ps1
|
||||
98bfcf5dca972f1ba1845bbca546133c192824ec40dd2e55f4e6d59c24a834d1 install-kit-awindows-20260427-211240/windows/deploy-domain-users.ps1
|
||||
a19c2a98e6483eb921457f472d1cf62a76e344f2ef3621f04fafa3d7dc2df353 install-kit-awindows-20260427-211240/windows/deploy-ensemble.ps1
|
||||
2542425e02acd8a8b02ed701ca2382cf7ae612be28441d1a10a40e48c6a13ad0 install-kit-awindows-20260427-211240/windows/deploy-single-user.ps1
|
||||
a2f963927c8b263a21aaffc0a926a058dcec65a04a5fa57c271d3dbe59f9347c install-kit-awindows-20260427-211240/windows/dlp-endpoint-signals-collector.ps1
|
||||
aef0032edd9b1e0c54f7b575664ed511dfc6cb53364e7496cbc95e137678e11a install-kit-awindows-20260427-211240/windows/dlp-policy.example.json
|
||||
ade74a55ce00d9295f2efa0fd72f987688154c93f1142ce0eb6e982f07271be7 install-kit-awindows-20260427-211240/windows/hardening-recovery.ps1
|
||||
88ffe06093ef5f7247bd2b990b0c8f801c706a26dc87725bb1194504fab7e306 install-kit-awindows-20260427-211240/windows/validate-deployment.ps1
|
||||
731098681d89b9af6f3872abd586ac3b1faba2d7f9340211e503f52ad0243b3f install-kit-awindows-20260427-211240/windows/web-category-rules.example.json
|
||||
|
||||
@@ -2,9 +2,9 @@ ActivityWatch DetMir Windows Install Kit
|
||||
|
||||
Includes:
|
||||
- windows/* (deploy scripts, collectors, common module, configs/examples)
|
||||
- ansible/deploy_aw_windows_phase2.yml
|
||||
- ansible/group_vars/windows.example.yml
|
||||
- ansible/README.md
|
||||
- ansible/* (Windows and AW server playbooks, examples, inventory, tasks)
|
||||
- aw-server/* (server installer, RU patch loader, host groups, default settings)
|
||||
- server-configs-192.168.100.21/* (working Windows Phase2 config snapshots)
|
||||
|
||||
Source:
|
||||
- Local project snapshot at build time.
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
---
|
||||
- name: Deploy pfSense ActivityWatch poller
|
||||
hosts: aw_pfsense_pollers
|
||||
become: true
|
||||
gather_facts: true
|
||||
|
||||
vars:
|
||||
aw_pfsense_install_root: "/opt/aw-pfsense"
|
||||
aw_pfsense_config_dir: "/etc/aw-pfsense"
|
||||
aw_pfsense_service_name: "aw-pfsense-poller.service"
|
||||
|
||||
tasks:
|
||||
- name: Install required packages
|
||||
ansible.builtin.apt:
|
||||
name:
|
||||
- python3
|
||||
state: present
|
||||
update_cache: true
|
||||
|
||||
- name: Ensure directories exist
|
||||
ansible.builtin.file:
|
||||
path: "{{ item }}"
|
||||
state: directory
|
||||
mode: "0755"
|
||||
loop:
|
||||
- "{{ aw_pfsense_install_root }}"
|
||||
- "{{ aw_pfsense_config_dir }}"
|
||||
|
||||
- name: Install pfSense poller script
|
||||
ansible.builtin.copy:
|
||||
src: "{{ aw_repo_root }}/pfsense/pfsense-aw-poller.py"
|
||||
dest: "{{ aw_pfsense_install_root }}/pfsense-aw-poller.py"
|
||||
mode: "0755"
|
||||
|
||||
- name: Install systemd service
|
||||
ansible.builtin.copy:
|
||||
src: "{{ aw_repo_root }}/pfsense/pfsense-aw-poller.service"
|
||||
dest: "/etc/systemd/system/{{ aw_pfsense_service_name }}"
|
||||
mode: "0644"
|
||||
notify:
|
||||
- Reload systemd
|
||||
|
||||
- name: Write pfSense poller config
|
||||
ansible.builtin.copy:
|
||||
dest: "{{ aw_pfsense_config_dir }}/poller.json"
|
||||
mode: "0600"
|
||||
content: "{{ aw_pfsense_poller_config | to_nice_json }}"
|
||||
notify:
|
||||
- Restart pfSense poller
|
||||
|
||||
- name: Enable and start pfSense poller
|
||||
ansible.builtin.systemd:
|
||||
name: "{{ aw_pfsense_service_name }}"
|
||||
enabled: true
|
||||
state: restarted
|
||||
daemon_reload: true
|
||||
|
||||
handlers:
|
||||
- name: Reload systemd
|
||||
ansible.builtin.systemd:
|
||||
daemon_reload: true
|
||||
|
||||
- name: Restart pfSense poller
|
||||
ansible.builtin.systemd:
|
||||
name: "{{ aw_pfsense_service_name }}"
|
||||
state: restarted
|
||||
@@ -0,0 +1,229 @@
|
||||
---
|
||||
- name: Deploy AWatch-rus server
|
||||
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_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_host_groups_cache_bust: "{{ lookup('file', aw_repo_root + '/aw-server/aw-host-groups.json') | 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: Install base packages
|
||||
ansible.builtin.apt:
|
||||
name:
|
||||
- curl
|
||||
- unzip
|
||||
state: present
|
||||
update_cache: true
|
||||
|
||||
- name: Ensure service account exists
|
||||
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: Ensure required directories
|
||||
ansible.builtin.file:
|
||||
path: "{{ item }}"
|
||||
state: directory
|
||||
owner: "{{ aw_server_user }}"
|
||||
group: "{{ aw_server_group }}"
|
||||
mode: "0755"
|
||||
loop:
|
||||
- "{{ aw_release_root }}"
|
||||
- "{{ aw_release_dir }}"
|
||||
- "{{ aw_server_webui_dir }}"
|
||||
- "{{ aw_server_data_dir }}"
|
||||
- "{{ aw_server_log_dir }}"
|
||||
- /etc/activitywatch
|
||||
- "{{ aw_bootstrap_dir }}"
|
||||
|
||||
- name: Download ActivityWatch release archive
|
||||
ansible.builtin.get_url:
|
||||
url: "{{ aw_server_download_url }}"
|
||||
dest: "{{ aw_archive_path }}"
|
||||
mode: "0644"
|
||||
|
||||
- name: Unpack ActivityWatch release
|
||||
ansible.builtin.unarchive:
|
||||
src: "{{ aw_archive_path }}"
|
||||
dest: "{{ aw_release_dir }}"
|
||||
remote_src: true
|
||||
extra_opts: ["-o"]
|
||||
|
||||
- name: Discover extracted AW directory
|
||||
ansible.builtin.find:
|
||||
paths: "{{ aw_release_dir }}"
|
||||
file_type: directory
|
||||
patterns: "activitywatch*"
|
||||
register: aw_release_find
|
||||
|
||||
- name: Set release extracted path
|
||||
ansible.builtin.set_fact:
|
||||
aw_release_extracted: "{{ (aw_release_find.files | sort(attribute='path') | map(attribute='path') | list | first) }}"
|
||||
|
||||
- name: Verify extracted directory exists
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- aw_release_extracted is defined
|
||||
- aw_release_extracted | length > 0
|
||||
fail_msg: "Cannot locate extracted ActivityWatch release directory."
|
||||
|
||||
- name: Sync release content to /opt/activitywatch
|
||||
ansible.builtin.command:
|
||||
cmd: "rsync -a --delete {{ aw_release_extracted }}/ /opt/activitywatch/"
|
||||
|
||||
- name: Copy bootstrap files from repository
|
||||
ansible.builtin.copy:
|
||||
src: "{{ item.src }}"
|
||||
dest: "{{ item.dest }}"
|
||||
mode: "{{ item.mode }}"
|
||||
loop:
|
||||
- { src: "{{ aw_repo_root }}/aw-server/activitywatch-server.service", dest: "/etc/systemd/system/activitywatch-server.service", mode: "0644" }
|
||||
- { 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-host-groups.json", dest: "{{ aw_server_webui_dir }}/js/aw-host-groups.json", mode: "0644" }
|
||||
notify:
|
||||
- Reload systemd
|
||||
- Restart activitywatch
|
||||
|
||||
- name: Copy WebUI index template from installed distribution
|
||||
ansible.builtin.copy:
|
||||
remote_src: true
|
||||
src: "/opt/activitywatch/aw-webui/index.html"
|
||||
dest: "{{ aw_server_webui_dir }}/index.html"
|
||||
mode: "0644"
|
||||
|
||||
- name: Insert RU patch scripts into index.html
|
||||
ansible.builtin.replace:
|
||||
path: "{{ aw_server_webui_dir }}/index.html"
|
||||
regexp: '</head>'
|
||||
replace: '<script src="/js/sw-cleanup.js?v={{ aw_sw_cleanup_cache_bust }}"></script></head>'
|
||||
|
||||
- name: Insert RU patch loader before body end
|
||||
ansible.builtin.replace:
|
||||
path: "{{ aw_server_webui_dir }}/index.html"
|
||||
regexp: '</body>'
|
||||
replace: '<script defer="defer" src="/js/ru-patch-v5.js?v={{ aw_ru_patch_cache_bust }}"></script></body>'
|
||||
|
||||
- name: Write /etc/activitywatch/aw-server.env
|
||||
ansible.builtin.copy:
|
||||
dest: /etc/activitywatch/aw-server.env
|
||||
mode: "0640"
|
||||
content: |
|
||||
AW_SERVER_HOST={{ aw_server_bind_host }}
|
||||
AW_SERVER_PORT={{ aw_server_port }}
|
||||
AW_DATA_DIR={{ aw_server_data_dir }}
|
||||
AW_LOG_DIR={{ aw_server_log_dir }}
|
||||
AW_WEBUI_DIR={{ aw_server_webui_dir }}
|
||||
AW_SERVER_USER={{ aw_server_user }}
|
||||
AW_SERVER_GROUP={{ aw_server_group }}
|
||||
|
||||
- name: Enable and start service
|
||||
ansible.builtin.systemd:
|
||||
name: activitywatch-server.service
|
||||
enabled: true
|
||||
state: restarted
|
||||
daemon_reload: true
|
||||
|
||||
- name: Wait for API
|
||||
ansible.builtin.uri:
|
||||
url: "http://127.0.0.1:{{ aw_server_port }}/api/0/info"
|
||||
method: GET
|
||||
status_code: 200
|
||||
register: aw_api
|
||||
retries: 10
|
||||
delay: 3
|
||||
until: aw_api.status == 200
|
||||
|
||||
- name: Apply baseline worktime settings (classes)
|
||||
ansible.builtin.uri:
|
||||
url: "http://127.0.0.1:{{ aw_server_port }}/api/0/settings/classes"
|
||||
method: POST
|
||||
body: "{{ aw_worktime_classes }}"
|
||||
body_format: json
|
||||
status_code: 201
|
||||
when: aw_apply_worktime_settings | default(false) | bool
|
||||
|
||||
- name: Apply baseline views (include DLP and worktime)
|
||||
ansible.builtin.uri:
|
||||
url: "http://127.0.0.1:{{ aw_server_port }}/api/0/settings/views"
|
||||
method: POST
|
||||
body: "{{ aw_default_views }}"
|
||||
body_format: json
|
||||
status_code: 201
|
||||
when: aw_apply_worktime_settings | default(false) | bool
|
||||
|
||||
- name: Derive worktime durationDefault from aw_worktime_from/to
|
||||
ansible.builtin.set_fact:
|
||||
aw_worktime_from_h: "{{ (aw_worktime_from | default('08:00')).split(':')[0] | int }}"
|
||||
aw_worktime_from_m: "{{ (aw_worktime_from | default('08:00')).split(':')[1] | int }}"
|
||||
aw_worktime_to_h: "{{ (aw_worktime_to | default('17:00')).split(':')[0] | int }}"
|
||||
aw_worktime_to_m: "{{ (aw_worktime_to | default('17:00')).split(':')[1] | int }}"
|
||||
aw_worktime_duration_default_derived: >-
|
||||
{{
|
||||
(
|
||||
(
|
||||
((aw_worktime_to_h | int) * 60 + (aw_worktime_to_m | int)) -
|
||||
((aw_worktime_from_h | int) * 60 + (aw_worktime_from_m | int))
|
||||
) * 60
|
||||
)
|
||||
}}
|
||||
when: aw_apply_worktime_settings | default(false) | bool
|
||||
|
||||
- name: Normalize derived durationDefault for overnight shifts
|
||||
ansible.builtin.set_fact:
|
||||
aw_worktime_duration_default_effective: >-
|
||||
{{
|
||||
(aw_worktime_duration_default_derived | int)
|
||||
if (aw_worktime_duration_default_derived | int) > 0
|
||||
else ((aw_worktime_duration_default_derived | int) + 86400)
|
||||
}}
|
||||
when: aw_apply_worktime_settings | default(false) | bool
|
||||
|
||||
- name: Validate derived durationDefault is sane
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- aw_worktime_duration_default_effective | int > 0
|
||||
- aw_worktime_duration_default_effective | int <= 86400
|
||||
fail_msg: "Invalid worktime window: {{ aw_worktime_from }}..{{ aw_worktime_to }}"
|
||||
when: aw_apply_worktime_settings | default(false) | bool
|
||||
|
||||
- name: Apply baseline worktime period (startOfDay)
|
||||
ansible.builtin.uri:
|
||||
url: "http://127.0.0.1:{{ aw_server_port }}/api/0/settings/startOfDay"
|
||||
method: POST
|
||||
body: "{{ aw_worktime_start_of_day }}"
|
||||
body_format: json
|
||||
status_code: 200
|
||||
when: aw_apply_worktime_settings | default(false) | bool
|
||||
|
||||
- name: Apply baseline worktime period (durationDefault seconds)
|
||||
ansible.builtin.uri:
|
||||
url: "http://127.0.0.1:{{ aw_server_port }}/api/0/settings/durationDefault"
|
||||
method: POST
|
||||
body: "{{ aw_worktime_duration_default_effective }}"
|
||||
body_format: json
|
||||
status_code: 200
|
||||
when: aw_apply_worktime_settings | default(false) | bool
|
||||
|
||||
handlers:
|
||||
- name: Reload systemd
|
||||
ansible.builtin.systemd:
|
||||
daemon_reload: true
|
||||
|
||||
- name: Restart activitywatch
|
||||
ansible.builtin.systemd:
|
||||
name: activitywatch-server.service
|
||||
state: restarted
|
||||
@@ -0,0 +1,24 @@
|
||||
aw_server_version: "v0.13.2"
|
||||
aw_server_download_url: "https://github.com/ActivityWatch/activitywatch/releases/download/v0.13.2/activitywatch-v0.13.2-linux-x86_64.zip"
|
||||
aw_server_bind_host: "0.0.0.0"
|
||||
aw_server_port: 5600
|
||||
aw_server_webui_dir: "/opt/activitywatch/webui-ru"
|
||||
aw_server_data_dir: "/var/lib/activitywatch"
|
||||
aw_server_log_dir: "/var/log/activitywatch"
|
||||
aw_server_user: "activitywatch"
|
||||
aw_server_group: "activitywatch"
|
||||
|
||||
aw_repo_root: "/home/igor/tmp/AWatch-rus"
|
||||
|
||||
# Optional: apply a baseline worktime-focused categorization and views via AW settings API.
|
||||
# WARNING: this overwrites existing server-side settings/classes/views.
|
||||
aw_apply_worktime_settings: false
|
||||
|
||||
# Optional defaults for the worktime period in Web UI.
|
||||
# startOfDay controls day-boundary and default report window start.
|
||||
# durationDefault controls default time range (seconds) shown in UI.
|
||||
#
|
||||
# Recommended: set worktime window explicitly and let the playbook derive duration.
|
||||
aw_worktime_from: "08:00"
|
||||
aw_worktime_to: "17:00"
|
||||
aw_worktime_start_of_day: "{{ aw_worktime_from }}"
|
||||
@@ -0,0 +1,30 @@
|
||||
aw_pfsense_poller_config:
|
||||
poll_interval_seconds: 60
|
||||
aw:
|
||||
server_host: "10.10.10.13"
|
||||
server_port: 5600
|
||||
hostname: "PFSENSE-EDGE01"
|
||||
pulse_time_seconds: 120
|
||||
timeout_seconds: 15
|
||||
pfsense:
|
||||
name: "pfSense Edge 01"
|
||||
host: "10.10.10.1"
|
||||
scheme: "https"
|
||||
verify_tls: false
|
||||
timeout_seconds: 15
|
||||
headers:
|
||||
X-API-Key: "replace-me"
|
||||
X-API-Secret: "replace-me"
|
||||
endpoints:
|
||||
- name: "system-status"
|
||||
path: "/api/v2/status/system"
|
||||
bucket_prefix: "aw-pfsense-health"
|
||||
bucket_type: "aw.pfsense.health"
|
||||
- name: "interfaces"
|
||||
path: "/api/v2/interface"
|
||||
bucket_prefix: "aw-pfsense-interfaces"
|
||||
bucket_type: "aw.pfsense.interfaces"
|
||||
- name: "gateways"
|
||||
path: "/api/v2/status/gateways"
|
||||
bucket_prefix: "aw-pfsense-gateways"
|
||||
bucket_type: "aw.pfsense.gateways"
|
||||
@@ -0,0 +1,38 @@
|
||||
proxmox_ct_matrix:
|
||||
- id: "203"
|
||||
hostname: "activitywatch-user1"
|
||||
storage: "local-lvm"
|
||||
template: "local:vztmpl/debian-12-standard_12.7-1_amd64.tar.zst"
|
||||
rootfs_size: "8G"
|
||||
cores: "2"
|
||||
memory: "2048"
|
||||
swap: "512"
|
||||
bridge: "vmbr10"
|
||||
ip: "10.20.30.13/24"
|
||||
gw: "10.20.30.1"
|
||||
vlan: ""
|
||||
nameserver: "1.1.1.1 8.8.8.8"
|
||||
searchdomain: "example.internal"
|
||||
password: "CHANGE_ME"
|
||||
unprivileged: "1"
|
||||
onboot: "1"
|
||||
features: "nesting=1,keyctl=1"
|
||||
|
||||
- id: "204"
|
||||
hostname: "activitywatch-user2"
|
||||
storage: "local-lvm"
|
||||
template: "local:vztmpl/debian-12-standard_12.7-1_amd64.tar.zst"
|
||||
rootfs_size: "8G"
|
||||
cores: "2"
|
||||
memory: "2048"
|
||||
swap: "512"
|
||||
bridge: "vmbr10"
|
||||
ip: "10.20.30.14/24"
|
||||
gw: "10.20.30.1"
|
||||
vlan: ""
|
||||
nameserver: "1.1.1.1 8.8.8.8"
|
||||
searchdomain: "example.internal"
|
||||
password: "CHANGE_ME"
|
||||
unprivileged: "1"
|
||||
onboot: "1"
|
||||
features: "nesting=1,keyctl=1"
|
||||
@@ -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"
|
||||
@@ -0,0 +1,8 @@
|
||||
[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
|
||||
|
||||
[aw_windows]
|
||||
win-node1 ansible_host=192.168.100.21 ansible_user=Administrator ansible_password=CHANGE_ME ansible_connection=winrm ansible_winrm_transport=ntlm ansible_port=5985 ansible_winrm_server_cert_validation=ignore
|
||||
@@ -0,0 +1,40 @@
|
||||
---
|
||||
- name: Provision single Proxmox CT and deploy AWatch-rus
|
||||
hosts: proxmox
|
||||
gather_facts: false
|
||||
|
||||
vars:
|
||||
proxmox_bootstrap_dir: "/tmp/aw-rus-bootstrap"
|
||||
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
|
||||
- aw-host-groups.json
|
||||
- settings/classes-worktime.json
|
||||
- settings/views-default.json
|
||||
|
||||
tasks:
|
||||
- name: Execute single-CT provisioning workflow
|
||||
ansible.builtin.include_tasks: tasks/provision_ct_and_deploy_aw.yml
|
||||
vars:
|
||||
ct_id: "{{ proxmox_ct_id }}"
|
||||
ct_hostname: "{{ proxmox_ct_hostname }}"
|
||||
ct_storage: "{{ proxmox_ct_storage }}"
|
||||
ct_template: "{{ proxmox_ct_template }}"
|
||||
ct_rootfs_size: "{{ proxmox_ct_rootfs_size }}"
|
||||
ct_cores: "{{ proxmox_ct_cores }}"
|
||||
ct_memory: "{{ proxmox_ct_memory }}"
|
||||
ct_swap: "{{ proxmox_ct_swap }}"
|
||||
ct_bridge: "{{ proxmox_ct_bridge }}"
|
||||
ct_ip: "{{ proxmox_ct_ip }}"
|
||||
ct_gw: "{{ proxmox_ct_gw }}"
|
||||
ct_vlan: "{{ proxmox_ct_vlan | default('') }}"
|
||||
ct_nameserver: "{{ proxmox_ct_nameserver | default('') }}"
|
||||
ct_searchdomain: "{{ proxmox_ct_searchdomain | default('') }}"
|
||||
ct_password: "{{ proxmox_ct_password }}"
|
||||
ct_unprivileged: "{{ proxmox_ct_unprivileged }}"
|
||||
ct_onboot: "{{ proxmox_ct_onboot }}"
|
||||
ct_features: "{{ proxmox_ct_features }}"
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
---
|
||||
- name: Provision Proxmox CT matrix and deploy AWatch-rus with RU patch
|
||||
hosts: proxmox
|
||||
gather_facts: false
|
||||
|
||||
vars:
|
||||
proxmox_bootstrap_dir: "/tmp/aw-rus-bootstrap"
|
||||
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
|
||||
- aw-host-groups.json
|
||||
- settings/classes-worktime.json
|
||||
- settings/views-default.json
|
||||
|
||||
tasks:
|
||||
- name: Validate CT matrix is provided
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- proxmox_ct_matrix is defined
|
||||
- proxmox_ct_matrix | length > 0
|
||||
fail_msg: "Define proxmox_ct_matrix in group_vars/proxmox-matrix.yml"
|
||||
|
||||
- name: Execute provisioning workflow for each CT
|
||||
ansible.builtin.include_tasks: tasks/provision_ct_and_deploy_aw.yml
|
||||
vars:
|
||||
ct_id: "{{ item.id }}"
|
||||
ct_hostname: "{{ item.hostname }}"
|
||||
ct_storage: "{{ item.storage }}"
|
||||
ct_template: "{{ item.template }}"
|
||||
ct_rootfs_size: "{{ item.rootfs_size }}"
|
||||
ct_cores: "{{ item.cores }}"
|
||||
ct_memory: "{{ item.memory }}"
|
||||
ct_swap: "{{ item.swap }}"
|
||||
ct_bridge: "{{ item.bridge }}"
|
||||
ct_ip: "{{ item.ip }}"
|
||||
ct_gw: "{{ item.gw }}"
|
||||
ct_vlan: "{{ item.vlan | default('') }}"
|
||||
ct_nameserver: "{{ item.nameserver | default('') }}"
|
||||
ct_searchdomain: "{{ item.searchdomain | default('') }}"
|
||||
ct_password: "{{ item.password }}"
|
||||
ct_unprivileged: "{{ item.unprivileged }}"
|
||||
ct_onboot: "{{ item.onboot }}"
|
||||
ct_features: "{{ item.features }}"
|
||||
loop: "{{ proxmox_ct_matrix }}"
|
||||
loop_control:
|
||||
label: "ct={{ item.id }} host={{ item.hostname }} ip={{ item.ip }}"
|
||||
@@ -0,0 +1,217 @@
|
||||
---
|
||||
- name: Validate required per-CT variables
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- ct_id is defined
|
||||
- ct_hostname is defined
|
||||
- ct_storage is defined
|
||||
- ct_template is defined
|
||||
- ct_rootfs_size is defined
|
||||
- ct_cores is defined
|
||||
- ct_memory is defined
|
||||
- ct_swap is defined
|
||||
- ct_bridge is defined
|
||||
- ct_ip is defined
|
||||
- ct_gw is defined
|
||||
- ct_password is defined
|
||||
- ct_unprivileged is defined
|
||||
- ct_onboot is defined
|
||||
- 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 for CT provisioning/deploy."
|
||||
|
||||
- name: Build CT network string
|
||||
ansible.builtin.set_fact:
|
||||
ct_net0: >-
|
||||
name=eth0,bridge={{ ct_bridge }},ip={{ ct_ip }},gw={{ ct_gw }}{% if (ct_vlan | default('') | string | length) > 0 %},tag={{ ct_vlan }}{% endif %}
|
||||
|
||||
- name: Check whether CT already exists
|
||||
ansible.builtin.command:
|
||||
argv:
|
||||
- pct
|
||||
- status
|
||||
- "{{ ct_id }}"
|
||||
register: ct_status_check
|
||||
failed_when: false
|
||||
changed_when: false
|
||||
|
||||
- name: Create CT when absent
|
||||
ansible.builtin.command:
|
||||
argv:
|
||||
- pct
|
||||
- create
|
||||
- "{{ ct_id }}"
|
||||
- "{{ ct_template }}"
|
||||
- --hostname
|
||||
- "{{ ct_hostname }}"
|
||||
- --cores
|
||||
- "{{ ct_cores }}"
|
||||
- --memory
|
||||
- "{{ ct_memory }}"
|
||||
- --swap
|
||||
- "{{ ct_swap }}"
|
||||
- --rootfs
|
||||
- "{{ ct_storage }}:{{ ct_rootfs_size }}"
|
||||
- --password
|
||||
- "{{ ct_password }}"
|
||||
- --unprivileged
|
||||
- "{{ ct_unprivileged }}"
|
||||
- --onboot
|
||||
- "{{ ct_onboot }}"
|
||||
- --features
|
||||
- "{{ ct_features }}"
|
||||
- --net0
|
||||
- "{{ ct_net0 }}"
|
||||
- --nameserver
|
||||
- "{{ ct_nameserver | default('') }}"
|
||||
- --searchdomain
|
||||
- "{{ ct_searchdomain | default('') }}"
|
||||
- --ostype
|
||||
- debian
|
||||
when: ct_status_check.rc != 0
|
||||
|
||||
- name: Check current CT runtime state
|
||||
ansible.builtin.command:
|
||||
argv:
|
||||
- pct
|
||||
- status
|
||||
- "{{ ct_id }}"
|
||||
register: ct_runtime_status
|
||||
changed_when: false
|
||||
|
||||
- name: Start CT when stopped
|
||||
ansible.builtin.command:
|
||||
argv:
|
||||
- pct
|
||||
- start
|
||||
- "{{ 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
|
||||
- "{{ 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
|
||||
- "{{ 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
|
||||
- "{{ 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
|
||||
- "{{ ct_id }}"
|
||||
- --
|
||||
- chmod
|
||||
- "0600"
|
||||
- /etc/activitywatch/aw-server.env
|
||||
|
||||
- name: Install server and apply RU patch inside CT
|
||||
ansible.builtin.command:
|
||||
argv:
|
||||
- pct
|
||||
- exec
|
||||
- "{{ 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
|
||||
- "{{ 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
|
||||
- "{{ 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 {{ ct_id }} is provisioned and configured."
|
||||
- "ActivityWatch endpoint: http://{{ ct_ip | regex_replace('/[0-9]+$', '') }}:{{ aw_server_port }}"
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
[Unit]
|
||||
Description=ActivityWatch Server (Rust)
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
EnvironmentFile=/etc/activitywatch/aw-server.env
|
||||
User=__AW_SERVER_USER__
|
||||
Group=__AW_SERVER_GROUP__
|
||||
WorkingDirectory=__AW_SERVER_DATA_DIR__
|
||||
ExecStart=/bin/sh -lc 'exec /opt/activitywatch/bin/aw-server-rust --host "$AW_SERVER_BIND_HOST" --port "$AW_SERVER_PORT"'
|
||||
Restart=on-failure
|
||||
RestartSec=5s
|
||||
StateDirectory=activitywatch
|
||||
LogsDirectory=activitywatch
|
||||
NoNewPrivileges=true
|
||||
PrivateTmp=true
|
||||
ProtectSystem=full
|
||||
ProtectHome=true
|
||||
LimitNOFILE=65535
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@@ -0,0 +1,88 @@
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
ENV_FILE="/etc/activitywatch/aw-server.env"
|
||||
if [[ ! -f "$ENV_FILE" ]]; then
|
||||
echo "missing env file: $ENV_FILE" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
source "$ENV_FILE"
|
||||
|
||||
WEBUI_DIR="${AW_SERVER_WEBUI_DIR:-${AW_WEBUI_DIR:-/opt/activitywatch/webui-ru}}"
|
||||
PATCH_JS_SRC="/root/bootstrap/aw-ru-patch.js"
|
||||
SW_CLEANUP_SRC="/root/bootstrap/aw-sw-cleanup.js"
|
||||
HOST_GROUPS_SRC="/root/bootstrap/aw-host-groups.json"
|
||||
INDEX_HTML="$WEBUI_DIR/index.html"
|
||||
SERVICE_WORKER="$WEBUI_DIR/service-worker.js"
|
||||
TS=$(date +%Y%m%d%H%M%S)
|
||||
PATCH_TARGET="$WEBUI_DIR/js/ru-patch-v5.js"
|
||||
SW_TARGET="$WEBUI_DIR/js/sw-cleanup.js"
|
||||
HOST_GROUPS_TARGET="$WEBUI_DIR/js/aw-host-groups.json"
|
||||
TRENDS_NEEDLE='this.activityStore.query_category_time_by_period(r)'
|
||||
TRENDS_REPLACEMENT='this.activityStore.ensure_loaded(r)'
|
||||
TIMESPIRAL_NEEDLE='start:new Date("2022-08-08")'
|
||||
TIMESPIRAL_REPLACEMENT='start:new Date(Date.now()-12*36e5)'
|
||||
|
||||
[[ -f "$PATCH_JS_SRC" ]] || { echo "missing $PATCH_JS_SRC" >&2; exit 1; }
|
||||
[[ -f "$SW_CLEANUP_SRC" ]] || { echo "missing $SW_CLEANUP_SRC" >&2; exit 1; }
|
||||
[[ -f "$HOST_GROUPS_SRC" ]] || { echo "missing $HOST_GROUPS_SRC" >&2; exit 1; }
|
||||
[[ -f "$INDEX_HTML" ]] || { echo "missing $INDEX_HTML" >&2; exit 1; }
|
||||
|
||||
install -d "$WEBUI_DIR/js"
|
||||
install -m 0644 "$PATCH_JS_SRC" "$PATCH_TARGET"
|
||||
install -m 0644 "$SW_CLEANUP_SRC" "$SW_TARGET"
|
||||
install -m 0644 "$HOST_GROUPS_SRC" "$HOST_GROUPS_TARGET"
|
||||
cp "$INDEX_HTML" "$INDEX_HTML.bak.$TS"
|
||||
|
||||
patch_hash="$(sha1sum "$PATCH_TARGET" | awk '{print substr($1,1,12)}')"
|
||||
sw_hash="$(sha1sum "$SW_TARGET" | awk '{print substr($1,1,12)}')"
|
||||
|
||||
sed -i '/ru-patch-v5.js/d;/sw-cleanup.js/d;/aw-ru-patch.js/d;/aw-sw-cleanup.js/d' "$INDEX_HTML"
|
||||
sed -i "s#</head>#<script src=\"/js/sw-cleanup.js?v=$sw_hash\"></script></head>#" "$INDEX_HTML"
|
||||
sed -i "s#</body>#<script defer=\"defer\" src=\"/js/ru-patch-v5.js?v=$patch_hash\"></script></body>#" "$INDEX_HTML"
|
||||
cp "$SW_CLEANUP_SRC" "$SERVICE_WORKER"
|
||||
|
||||
trends_chunk="$(grep -Rsl "$TRENDS_NEEDLE" "$WEBUI_DIR/js"/*.js 2>/dev/null | head -n 1 || true)"
|
||||
if [[ -n "$trends_chunk" ]]; then
|
||||
cp "$trends_chunk" "$trends_chunk.bak.$TS"
|
||||
python3 - "$trends_chunk" "$TRENDS_NEEDLE" "$TRENDS_REPLACEMENT" <<'PY'
|
||||
from pathlib import Path
|
||||
import sys
|
||||
|
||||
path = Path(sys.argv[1])
|
||||
old = sys.argv[2]
|
||||
new = sys.argv[3]
|
||||
content = path.read_text()
|
||||
if old in content:
|
||||
path.write_text(content.replace(old, new, 1))
|
||||
print(f"Trends hotfix applied to {path}")
|
||||
else:
|
||||
print(f"Trends hotfix already present in {path}")
|
||||
PY
|
||||
else
|
||||
echo "Trends hotfix skipped: chunk not found"
|
||||
fi
|
||||
|
||||
timespiral_chunk="$(grep -Rsl "$TIMESPIRAL_NEEDLE" "$WEBUI_DIR/js"/*.js 2>/dev/null | head -n 1 || true)"
|
||||
if [[ -n "$timespiral_chunk" ]]; then
|
||||
cp "$timespiral_chunk" "$timespiral_chunk.bak.$TS"
|
||||
python3 - "$timespiral_chunk" "$TIMESPIRAL_NEEDLE" "$TIMESPIRAL_REPLACEMENT" <<'PY'
|
||||
from pathlib import Path
|
||||
import sys
|
||||
|
||||
path = Path(sys.argv[1])
|
||||
old = sys.argv[2]
|
||||
new = sys.argv[3]
|
||||
content = path.read_text()
|
||||
if old in content:
|
||||
path.write_text(content.replace(old, new, 1))
|
||||
print(f"Timespiral hotfix applied to {path}")
|
||||
else:
|
||||
print(f"Timespiral hotfix already present in {path}")
|
||||
PY
|
||||
else
|
||||
echo "Timespiral hotfix skipped: chunk not found"
|
||||
fi
|
||||
|
||||
echo "RU patch applied to $WEBUI_DIR (ru-patch-v5.js?v=$patch_hash)"
|
||||
@@ -0,0 +1,47 @@
|
||||
{
|
||||
"groups": [
|
||||
{
|
||||
"id": "pve-detmir",
|
||||
"name": "pve-detmir",
|
||||
"description": "Выделенный клиент DetMir в разделе Активность.",
|
||||
"patterns": [
|
||||
"^pve-detmir$"
|
||||
],
|
||||
"links": [
|
||||
{ "label": "Активность", "type": "activity", "view": "pve_audit" },
|
||||
{ "label": "Web-admin аудит", "type": "bucket", "bucket_prefix": "aw-pve-webadmin-events_" },
|
||||
{ "label": "PVE tasks", "type": "bucket", "bucket_prefix": "aw-pve-task-events_" },
|
||||
{ "label": "SSH сессии", "type": "bucket", "bucket_prefix": "aw-ssh-sessions_" },
|
||||
{ "label": "Команды shell", "type": "bucket", "bucket_prefix": "aw-console-commands_" },
|
||||
{ "label": "Web категории", "type": "bucket", "bucket_prefix": "aw-detmir-web-category_" },
|
||||
{ "label": "Все бакеты", "type": "buckets" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "windows-rdp",
|
||||
"name": "Windows RDP",
|
||||
"description": "Пользовательские Windows/RDP хосты с активностью, DLP и рабочим временем.",
|
||||
"patterns": [
|
||||
"^(SHARKON|WIN|RDP|TERM|TS-|WS-)"
|
||||
],
|
||||
"links": [
|
||||
{ "label": "Активность", "type": "activity" },
|
||||
{ "label": "DLP", "type": "bucket", "bucket_prefix": "aw-dlp-endpoint-signals_" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "virtual-infra",
|
||||
"name": "Virtual servers + Proxmox",
|
||||
"description": "Инфраструктурные VM и сетевые узлы. Здесь должны лежать Proxmox, pfSense, Debian и Ubuntu серверы.",
|
||||
"patterns": [
|
||||
"^(PFSENSE|PVE|PROXMOX|DEBIAN|UBUNTU|LINUX|VM-|SRV-|INFRA-)"
|
||||
],
|
||||
"links": [
|
||||
{ "label": "pfSense health", "type": "bucket", "bucket_prefix": "aw-pfsense-health_" },
|
||||
{ "label": "pfSense gateways", "type": "bucket", "bucket_prefix": "aw-pfsense-gateways_" },
|
||||
{ "label": "Все бакеты", "type": "buckets" }
|
||||
]
|
||||
}
|
||||
],
|
||||
"ungrouped_name": "Прочие хосты"
|
||||
}
|
||||
+1518
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,11 @@
|
||||
# Copy to /etc/activitywatch/aw-server.env and fill with real values.
|
||||
|
||||
AW_SERVER_VERSION=0.13.2
|
||||
AW_SERVER_DOWNLOAD_URL=https://github.com/ActivityWatch/aw-server-rust/releases/download/v0.13.2/aw-server-rust-linux-x86_64.zip
|
||||
AW_SERVER_BIND_HOST=0.0.0.0
|
||||
AW_SERVER_PORT=5600
|
||||
AW_SERVER_WEBUI_DIR=/opt/activitywatch/webui-ru
|
||||
AW_SERVER_DATA_DIR=/var/lib/activitywatch
|
||||
AW_SERVER_LOG_DIR=/var/log/activitywatch
|
||||
AW_SERVER_USER=activitywatch
|
||||
AW_SERVER_GROUP=activitywatch
|
||||
@@ -0,0 +1,18 @@
|
||||
self.addEventListener("install", function (event) {
|
||||
self.skipWaiting();
|
||||
event.waitUntil((async function () {
|
||||
const keys = await caches.keys();
|
||||
await Promise.all(keys.map(function (key) { return caches.delete(key); }));
|
||||
})());
|
||||
});
|
||||
|
||||
self.addEventListener("activate", function (event) {
|
||||
event.waitUntil((async function () {
|
||||
const keys = await caches.keys();
|
||||
await Promise.all(keys.map(function (key) { return caches.delete(key); }));
|
||||
await self.clients.claim();
|
||||
await self.registration.unregister();
|
||||
})());
|
||||
});
|
||||
|
||||
self.addEventListener("fetch", function () {});
|
||||
@@ -0,0 +1,117 @@
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
ENV_FILE="/etc/activitywatch/aw-server.env"
|
||||
if [[ ! -f "$ENV_FILE" ]]; then
|
||||
echo "missing env file: $ENV_FILE" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
source "$ENV_FILE"
|
||||
|
||||
required_vars=(
|
||||
AW_SERVER_VERSION
|
||||
AW_SERVER_DOWNLOAD_URL
|
||||
AW_SERVER_BIND_HOST
|
||||
AW_SERVER_PORT
|
||||
AW_SERVER_WEBUI_DIR
|
||||
AW_SERVER_DATA_DIR
|
||||
AW_SERVER_LOG_DIR
|
||||
AW_SERVER_USER
|
||||
AW_SERVER_GROUP
|
||||
)
|
||||
|
||||
BOOTSTRAP_DIR="/root/bootstrap"
|
||||
VIEWS_JSON="$BOOTSTRAP_DIR/settings/views-default.json"
|
||||
CLASSES_JSON="$BOOTSTRAP_DIR/settings/classes-worktime.json"
|
||||
|
||||
for var_name in "${required_vars[@]}"; do
|
||||
if [[ -z "${!var_name:-}" ]]; then
|
||||
echo "missing required variable: $var_name" >&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
apt-get update
|
||||
apt-get install -y curl ca-certificates unzip jq
|
||||
|
||||
if ! getent group "$AW_SERVER_GROUP" >/dev/null; then
|
||||
groupadd --system "$AW_SERVER_GROUP"
|
||||
fi
|
||||
|
||||
if ! id "$AW_SERVER_USER" >/dev/null 2>&1; then
|
||||
useradd --system --gid "$AW_SERVER_GROUP" --home-dir "$AW_SERVER_DATA_DIR" --shell /usr/sbin/nologin "$AW_SERVER_USER"
|
||||
fi
|
||||
|
||||
install -d -o "$AW_SERVER_USER" -g "$AW_SERVER_GROUP" /opt/activitywatch/bin
|
||||
install -d -o "$AW_SERVER_USER" -g "$AW_SERVER_GROUP" /opt/activitywatch/releases
|
||||
install -d -o "$AW_SERVER_USER" -g "$AW_SERVER_GROUP" "$AW_SERVER_WEBUI_DIR"
|
||||
install -d -o "$AW_SERVER_USER" -g "$AW_SERVER_GROUP" "$AW_SERVER_DATA_DIR"
|
||||
install -d -o "$AW_SERVER_USER" -g "$AW_SERVER_GROUP" "$AW_SERVER_LOG_DIR"
|
||||
|
||||
tmp_dir=$(mktemp -d)
|
||||
trap 'rm -rf "$tmp_dir"' EXIT
|
||||
|
||||
curl -fL "$AW_SERVER_DOWNLOAD_URL" -o "$tmp_dir/aw-server.zip"
|
||||
unzip -q "$tmp_dir/aw-server.zip" -d "$tmp_dir/unpacked"
|
||||
|
||||
server_bin=$(find "$tmp_dir/unpacked" -type f \( -name 'aw-server-rust' -o -name 'aw-server' \) | head -n 1)
|
||||
webui_dir=$(find "$tmp_dir/unpacked" -type d \( -name 'webui' -o -name 'aw-webui' \) | head -n 1 || true)
|
||||
|
||||
if [[ -z "$server_bin" || ! -f "$server_bin" ]]; then
|
||||
echo "aw-server binary not found in archive" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
release_dir="/opt/activitywatch/releases/aw-server-rust-v${AW_SERVER_VERSION}"
|
||||
rm -rf "$release_dir"
|
||||
install -d -o "$AW_SERVER_USER" -g "$AW_SERVER_GROUP" "$release_dir"
|
||||
install -m 0755 -o "$AW_SERVER_USER" -g "$AW_SERVER_GROUP" "$server_bin" "$release_dir/aw-server-rust"
|
||||
ln -sfn "$release_dir/aw-server-rust" /opt/activitywatch/bin/aw-server-rust
|
||||
|
||||
if [[ -n "$webui_dir" && -d "$webui_dir" ]]; then
|
||||
rm -rf "$AW_SERVER_WEBUI_DIR"
|
||||
mkdir -p "$AW_SERVER_WEBUI_DIR"
|
||||
cp -a "$webui_dir"/. "$AW_SERVER_WEBUI_DIR"/
|
||||
chown -R "$AW_SERVER_USER:$AW_SERVER_GROUP" "$AW_SERVER_WEBUI_DIR"
|
||||
fi
|
||||
|
||||
sed \
|
||||
-e "s#__AW_SERVER_USER__#$AW_SERVER_USER#g" \
|
||||
-e "s#__AW_SERVER_GROUP__#$AW_SERVER_GROUP#g" \
|
||||
-e "s#__AW_SERVER_DATA_DIR__#$AW_SERVER_DATA_DIR#g" \
|
||||
/root/bootstrap/activitywatch-server.service > /etc/systemd/system/activitywatch-server.service
|
||||
chmod 0644 /etc/systemd/system/activitywatch-server.service
|
||||
|
||||
systemctl daemon-reload
|
||||
systemctl enable activitywatch-server.service
|
||||
systemctl restart activitywatch-server.service
|
||||
systemctl --no-pager --full status activitywatch-server.service || true
|
||||
|
||||
for _ in $(seq 1 20); do
|
||||
if curl -fsS "http://127.0.0.1:${AW_SERVER_PORT}/api/0/info" >/dev/null 2>&1; then
|
||||
break
|
||||
fi
|
||||
sleep 2
|
||||
done
|
||||
|
||||
if [[ -f "$CLASSES_JSON" ]]; then
|
||||
curl -fsS -X POST \
|
||||
-H 'Content-Type: application/json' \
|
||||
--data-binary @"$CLASSES_JSON" \
|
||||
"http://127.0.0.1:${AW_SERVER_PORT}/api/0/settings/classes" >/dev/null
|
||||
echo "Applied worktime classes from $CLASSES_JSON"
|
||||
else
|
||||
echo "Worktime classes bootstrap not found, skipped: $CLASSES_JSON"
|
||||
fi
|
||||
|
||||
if [[ -f "$VIEWS_JSON" ]]; then
|
||||
curl -fsS -X POST \
|
||||
-H 'Content-Type: application/json' \
|
||||
--data-binary @"$VIEWS_JSON" \
|
||||
"http://127.0.0.1:${AW_SERVER_PORT}/api/0/settings/views" >/dev/null
|
||||
echo "Applied baseline views from $VIEWS_JSON"
|
||||
else
|
||||
echo "Views bootstrap not found, skipped: $VIEWS_JSON"
|
||||
fi
|
||||
@@ -0,0 +1,90 @@
|
||||
[
|
||||
{
|
||||
"id": 0,
|
||||
"name": ["Работа"],
|
||||
"rule": { "type": "none" },
|
||||
"data": {}
|
||||
},
|
||||
{
|
||||
"id": 1,
|
||||
"name": ["Работа", "1С"],
|
||||
"rule": {
|
||||
"type": "regex",
|
||||
"regex": "\\b(1cv8s?|1cv8c|1cestart)\\.exe\\b|1С:Предприятие|Запуск 1С:Предприятия|Загрузка конфигурационной информации|Доступ к информационной базе",
|
||||
"ignore_case": true
|
||||
},
|
||||
"data": { "color": "#194D33" }
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"name": ["Работа", "Документы"],
|
||||
"rule": {
|
||||
"type": "regex",
|
||||
"regex": "\\b(winword|excel|powerpnt|outlook|acrord32|acrord64)\\.exe\\b|Adobe Reader|Acrobat",
|
||||
"ignore_case": true
|
||||
},
|
||||
"data": { "color": "#2E7D32" }
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"name": ["Работа", "Коммуникации"],
|
||||
"rule": {
|
||||
"type": "regex",
|
||||
"regex": "\\b(teams|telegram|slack|thunderbird|zoom|skype|whatsapp|viber|discord)\\.exe\\b|Mattermost|Element|Riot",
|
||||
"ignore_case": true
|
||||
},
|
||||
"data": { "color": "#1E88E5" }
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"name": ["Работа", "Администрирование"],
|
||||
"rule": {
|
||||
"type": "regex",
|
||||
"regex": "\\b(mstsc|putty|kitty|winscp|anydesk|teamviewer|vncviewer|mmc|regedit|services|control|powershell|cmd)\\.exe\\b",
|
||||
"ignore_case": true
|
||||
},
|
||||
"data": { "color": "#6D4C41" }
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"name": ["Интернет"],
|
||||
"rule": { "type": "none" },
|
||||
"data": {}
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"name": ["Интернет", "Браузер"],
|
||||
"rule": {
|
||||
"type": "regex",
|
||||
"regex": "\\b(chrome|msedge|firefox|opera|brave|vivaldi|browser)\\.exe\\b",
|
||||
"ignore_case": true
|
||||
},
|
||||
"data": { "color": "#00897B" }
|
||||
},
|
||||
{
|
||||
"id": 7,
|
||||
"name": ["Система"],
|
||||
"rule": { "type": "none" },
|
||||
"data": {}
|
||||
},
|
||||
{
|
||||
"id": 8,
|
||||
"name": ["Система", "Windows"],
|
||||
"rule": {
|
||||
"type": "regex",
|
||||
"regex": "\\b(SearchHost|explorer|ShellExperienceHost|ApplicationFrameHost|RuntimeBroker|sihost|dwm|svchost|fontdrvhost|userinit)\\.exe\\b|\\\\Windows\\\\System32",
|
||||
"ignore_case": true
|
||||
},
|
||||
"data": { "color": "#607D8B" }
|
||||
},
|
||||
{
|
||||
"id": 9,
|
||||
"name": ["ActivityWatch"],
|
||||
"rule": {
|
||||
"type": "regex",
|
||||
"regex": "ActivityWatch|\\baw-(watcher|qt)\\.exe\\b",
|
||||
"ignore_case": true
|
||||
},
|
||||
"data": {}
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,39 @@
|
||||
[
|
||||
{
|
||||
"id": "summary",
|
||||
"name": "Summary",
|
||||
"elements": [
|
||||
{ "type": "top_titles", "size": 3 },
|
||||
{ "type": "timeline_barchart", "size": 3 },
|
||||
{ "type": "top_categories", "size": 3 },
|
||||
{ "type": "category_tree", "size": 3 }
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "window",
|
||||
"name": "Window",
|
||||
"elements": [
|
||||
{ "type": "top_apps", "size": 3, "props": {} }
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "DLP",
|
||||
"name": "DLP",
|
||||
"elements": []
|
||||
},
|
||||
{
|
||||
"id": "worktime",
|
||||
"name": "Worktime",
|
||||
"elements": [
|
||||
{ "type": "top_categories", "size": 3, "props": {} },
|
||||
{ "type": "timeline_barchart", "size": 3, "props": {} },
|
||||
{ "type": "category_tree", "size": 3, "props": {} },
|
||||
{ "type": "top_apps", "size": 3, "props": {} }
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "pve_audit",
|
||||
"name": "PVE Audit",
|
||||
"elements": []
|
||||
}
|
||||
]
|
||||
@@ -25,11 +25,16 @@ for file_name in \
|
||||
activitywatch-server.service \
|
||||
aw-server.env.example \
|
||||
aw-ru-patch.js \
|
||||
aw-sw-cleanup.js
|
||||
aw-sw-cleanup.js \
|
||||
aw-host-groups.json
|
||||
do
|
||||
pct push "$CT_ID" "$PROJECT_ROOT/aw-server/$file_name" "/root/bootstrap/$file_name"
|
||||
done
|
||||
|
||||
pct exec "$CT_ID" -- mkdir -p /root/bootstrap/settings
|
||||
pct push "$CT_ID" "$PROJECT_ROOT/aw-server/settings/classes-worktime.json" "/root/bootstrap/settings/classes-worktime.json"
|
||||
pct push "$CT_ID" "$PROJECT_ROOT/aw-server/settings/views-default.json" "/root/bootstrap/settings/views-default.json"
|
||||
|
||||
if [ -n "${AW_SERVER_VERSION:-}" ] &&
|
||||
[ -n "${AW_SERVER_DOWNLOAD_URL:-}" ] &&
|
||||
[ -n "${AW_SERVER_BIND_HOST:-}" ] &&
|
||||
|
||||
Reference in New Issue
Block a user