From 510515532380fbbc46d348bc89514a745ba4da68 Mon Sep 17 00:00:00 2001 From: igor04091968 Date: Mon, 27 Apr 2026 17:29:17 +0300 Subject: [PATCH] feat(linux): add remote client rollout for admin host --- README.md | 7 ++ docs/POST_MEMORY_2026-04-27.md | 21 ++++ docs/linux-client.md | 70 ++++++++++++ scripts/install_aw_linux_client.sh | 174 +++++++++++++++++++++++++++++ 4 files changed, 272 insertions(+) create mode 100755 docs/linux-client.md create mode 100755 scripts/install_aw_linux_client.sh diff --git a/README.md b/README.md index 4c9d183..3c038c2 100755 --- a/README.md +++ b/README.md @@ -9,6 +9,7 @@ - `docs/runbook.md` — быстрый runbook для оператора. - `docs/operations.md` — регламент сопровождения, бэкапов, обновлений и rollback. - `docs/windows/ensemble.md` — orchestration-пакет для Windows-деплоя и проверки. +- `docs/linux-client.md` — user-space rollout Linux-клиента ActivityWatch на удалённый `AW server`. - `docs/dlp-gap-analysis.md` — разрыв до enterprise DLP и roadmap. - `proxmox/` — шаблонные скрипты подготовки и наполнения CT на стороне Proxmox. - `aw-server/` — установочные скрипты, env-шаблон, systemd unit и RU patch для Web UI. @@ -16,6 +17,7 @@ - `pfsense/` — внешний poller для pfSense API и systemd unit под Debian/Ubuntu utility VM. - `windows/` — PowerShell toolkit: single-user, domain-users, ensemble orchestration, hardening/recovery, validation, phase-2 DLP telemetry (`aw-dlp-incidents_*`, `aw-dlp-endpoint-signals_*`). - `scripts/quality-gate.sh` — локальный preflight-пайплайн проверок. +- `scripts/install_aw_linux_client.sh` — установка Linux bundle + autostart для remote AW server. ## Базовый сценарий @@ -42,6 +44,11 @@ - `ansible/deploy_aw_pfsense_poller.yml` +Для Linux desktop/admin host, который должен слать watcher'ы на удалённый AW server: + +- `docs/linux-client.md` +- `scripts/install_aw_linux_client.sh` + Скрипты `proxmox/create-ct.sh` и `proxmox/push-aw-artifacts.sh` по умолчанию читают: - `secrets/deploy.secrets.env` diff --git a/docs/POST_MEMORY_2026-04-27.md b/docs/POST_MEMORY_2026-04-27.md index 50ef15a..ec0f8a0 100644 --- a/docs/POST_MEMORY_2026-04-27.md +++ b/docs/POST_MEMORY_2026-04-27.md @@ -28,7 +28,28 @@ - `socks5://127.0.0.1:1080` активен. - `sing-box` запущен и пропускает трафик. +4. Подготовлен и развернут Linux-клиент ActivityWatch для `10.10.10.2`. +- В репозиторий добавлен rollout: + - `scripts/install_aw_linux_client.sh` + - `docs/linux-client.md` +- На `10.10.10.2` под пользователем `admin` установлен bundle `ActivityWatch 0.13.2` в: + - `~/.local/opt/activitywatch/v0.13.2/activitywatch` +- Созданы: + - `~/.config/activitywatch/aw-client/aw-client.toml` с `10.10.10.13:5600` + - `~/.config/activitywatch/aw-qt/aw-qt.toml` + - `~/.local/bin/activitywatch-remote-aw` + - `~/.config/autostart/activitywatch-remote-aw.desktop` +- Проверка показала: + - удаленный `AW server` с `10.10.10.2` достижим; + - `aw-qt --no-gui` стартует; + - bucket `aw-watcher-afk_pve-detmir` появился на сервере. +- Текущий blocker: + - на `10.10.10.2` нет активной `X11/GUI` сессии; + - `aw-watcher-window` падает с `DISPLAY environment variable not set`; + - `aw-watcher-afk` падает на `failed to acquire X connection`. + ## Зафиксированные выводы - На текущем этапе `10.10.10.2` является фактическим runtime-хостом для `AW server` и `pfSense poller`. - Документация должна исходить из host-based сценария как из подтвержденного рабочего контура, а CT/LXC-схему держать как отдельный вариант развертывания. +- Для Linux-клиента на `10.10.10.2` установка завершена, но полноценные watcher-события начнутся только после реального графического логина пользователя. diff --git a/docs/linux-client.md b/docs/linux-client.md new file mode 100755 index 0000000..37be37e --- /dev/null +++ b/docs/linux-client.md @@ -0,0 +1,70 @@ +# Linux client deployment + +## Назначение + +Этот сценарий ставит `ActivityWatch` в user-space Linux-хоста и направляет watcher'ы на уже существующий `AW server`, не поднимая локальный `aw-server-rust`. + +Подтвержденный целевой кейс: + +- Linux desktop/admin host: `10.10.10.2` +- удаленный `AW server`: `10.10.10.13:5600` + +## Что делает скрипт + +- скачивает официальный Linux ZIP `ActivityWatch`; +- распаковывает bundle в `~/.local/opt/activitywatch/v`; +- обновляет symlink `~/.local/opt/activitywatch/current`; +- пишет `aw-client.toml` с указанием удаленного `AW server`; +- пишет `aw-qt.toml`, где оставляет только `aw-watcher-afk` и `aw-watcher-window`; +- создает launcher `~/.local/bin/activitywatch-remote-aw`; +- создает XDG autostart entry `~/.config/autostart/activitywatch-remote-aw.desktop`. + +## Установка + +```bash +cd /path/to/AWatch-rus +sh ./scripts/install_aw_linux_client.sh \ + --server-host 10.10.10.13 \ + --server-port 5600 +``` + +Если нужно переустановить ту же версию: + +```bash +sh ./scripts/install_aw_linux_client.sh --force +``` + +## Ключевые файлы + +- `~/.config/activitywatch/aw-client/aw-client.toml` +- `~/.config/activitywatch/aw-qt/aw-qt.toml` +- `~/.local/bin/activitywatch-remote-aw` +- `~/.config/autostart/activitywatch-remote-aw.desktop` + +## Ручной запуск + +```bash +~/.local/bin/activitywatch-remote-aw +``` + +## Проверка + +Проверка bundle и конфигурации: + +```bash +~/.local/opt/activitywatch/current/aw-qt --help +~/.local/opt/activitywatch/current/aw-watcher-afk/aw-watcher-afk --help +~/.local/opt/activitywatch/current/aw-watcher-window/aw-watcher-window --help +cat ~/.config/activitywatch/aw-client/aw-client.toml +cat ~/.config/activitywatch/aw-qt/aw-qt.toml +``` + +Проверка на сервере: + +```bash +curl -fsS http://10.10.10.13:5600/api/0/buckets | jq -r 'keys[]' | grep '^aw-watcher-' +``` + +## Ограничение + +`aw-watcher-window` и `aw-watcher-afk` требуют реальную пользовательскую desktop-сессию (`X11`/поддерживаемый GUI login). Если на хосте нет активного GUI-сеанса, установка пройдет, но событий от watcher'ов не будет до первого нормального графического входа пользователя. diff --git a/scripts/install_aw_linux_client.sh b/scripts/install_aw_linux_client.sh new file mode 100755 index 0000000..8be886f --- /dev/null +++ b/scripts/install_aw_linux_client.sh @@ -0,0 +1,174 @@ +#!/usr/bin/env sh +set -eu + +VERSION="0.13.2" +SERVER_HOST="10.10.10.13" +SERVER_PORT="5600" +INSTALL_BASE="${HOME}/.local/opt/activitywatch" +BIN_DIR="${HOME}/.local/bin" +AUTOSTART_DIR="${HOME}/.config/autostart" +CONFIG_ROOT="${XDG_CONFIG_HOME:-$HOME/.config}/activitywatch" +FORCE="0" + +usage() { + cat <<'EOF' +Usage: install_aw_linux_client.sh [options] + +Options: + --server-host HOST Remote AW server host (default: 10.10.10.13) + --server-port PORT Remote AW server port (default: 5600) + --version VERSION ActivityWatch version (default: 0.13.2) + --install-base PATH Install root (default: ~/.local/opt/activitywatch) + --force Reinstall selected version even if it exists + -h, --help Show this help +EOF +} + +while [ "$#" -gt 0 ]; do + case "$1" in + --server-host) + SERVER_HOST="$2" + shift 2 + ;; + --server-port) + SERVER_PORT="$2" + shift 2 + ;; + --version) + VERSION="$2" + shift 2 + ;; + --install-base) + INSTALL_BASE="$2" + shift 2 + ;; + --force) + FORCE="1" + shift + ;; + -h|--help) + usage + exit 0 + ;; + *) + echo "Unknown option: $1" >&2 + usage >&2 + exit 1 + ;; + esac +done + +ARCHIVE="activitywatch-v${VERSION}-linux-x86_64.zip" +DOWNLOAD_URL="https://github.com/ActivityWatch/activitywatch/releases/download/v${VERSION}/${ARCHIVE}" +VERSION_DIR="${INSTALL_BASE}/v${VERSION}" +CURRENT_LINK="${INSTALL_BASE}/current" +TMP_DIR="$(mktemp -d)" +ARCHIVE_PATH="${TMP_DIR}/${ARCHIVE}" +BUNDLE_DIR="" + +cleanup() { + rm -rf "${TMP_DIR}" +} +trap cleanup EXIT INT TERM + +download_archive() { + if command -v curl >/dev/null 2>&1; then + curl -fL "${DOWNLOAD_URL}" -o "${ARCHIVE_PATH}" + return + fi + + if command -v wget >/dev/null 2>&1; then + wget -O "${ARCHIVE_PATH}" "${DOWNLOAD_URL}" + return + fi + + echo "Neither curl nor wget is available" >&2 + exit 1 +} + +extract_archive() { + mkdir -p "${VERSION_DIR}" + + if command -v unzip >/dev/null 2>&1; then + unzip -q "${ARCHIVE_PATH}" -d "${VERSION_DIR}" + return + fi + + python3 -m zipfile -e "${ARCHIVE_PATH}" "${VERSION_DIR}" +} + +resolve_bundle_dir() { + if [ -x "${VERSION_DIR}/aw-qt" ]; then + BUNDLE_DIR="${VERSION_DIR}" + return + fi + + if [ -x "${VERSION_DIR}/activitywatch/aw-qt" ]; then + BUNDLE_DIR="${VERSION_DIR}/activitywatch" + return + fi + + echo "Cannot find aw-qt inside ${VERSION_DIR}" >&2 + exit 1 +} + +write_file() { + target="$1" + mkdir -p "$(dirname "${target}")" + cat > "${target}" +} + +if [ -d "${VERSION_DIR}" ] && [ "${FORCE}" != "1" ]; then + echo "Version directory already exists: ${VERSION_DIR}" >&2 + echo "Use --force to reinstall the same version." >&2 + exit 1 +fi + +rm -rf "${VERSION_DIR}" +mkdir -p "${INSTALL_BASE}" "${BIN_DIR}" "${AUTOSTART_DIR}" "${CONFIG_ROOT}" + +download_archive +extract_archive +resolve_bundle_dir +rm -f "${CURRENT_LINK}" +ln -sfn "${BUNDLE_DIR}" "${CURRENT_LINK}" + +write_file "${CONFIG_ROOT}/aw-client/aw-client.toml" </dev/null 2>&1 || true +"${CURRENT_LINK}/aw-watcher-afk/aw-watcher-afk" --help >/dev/null 2>&1 || true +"${CURRENT_LINK}/aw-watcher-window/aw-watcher-window" --help >/dev/null 2>&1 || true + +echo "Installed ActivityWatch ${VERSION} into ${VERSION_DIR}" +echo "Remote server target: ${SERVER_HOST}:${SERVER_PORT}" +echo "Launcher: ${BIN_DIR}/activitywatch-remote-aw" +echo "Autostart: ${AUTOSTART_DIR}/activitywatch-remote-aw.desktop"