From ee291f7a26fa27080093e87422189c49647e8df7 Mon Sep 17 00:00:00 2001 From: Arseny <20096ninja@gmail.com> Date: Thu, 24 Sep 2026 23:36:10 +0300 Subject: [PATCH 01/10] =?UTF-8?q?[UPDATE]=20=D0=B8=D0=BD=D0=B2=D0=B5=D0=BD?= =?UTF-8?q?=D1=82=D0=B0=D1=80=D1=8C:=20=D0=B0=D0=B4=D1=80=D0=B5=D1=81?= =?UTF-8?q?=D0=B0=20=D0=BF=D1=80=D0=BE=D0=B2=D0=BE=D0=B4=D0=BD=D0=BE=D0=B9?= =?UTF-8?q?=20=D1=81=D0=B5=D1=82=D0=B8=2011.0.0.x,=20node107?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- inventory/hosts.yml | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/inventory/hosts.yml b/inventory/hosts.yml index ec34ed4..553039d 100644 --- a/inventory/hosts.yml +++ b/inventory/hosts.yml @@ -1,37 +1,40 @@ all: vars: - scanner_repo: ssh://git@monitor.yss.su:2222/IU9/hackrf-scanner.git - scanner_branch: feature/scanner-v2 + scanner_src: "{{ playbook_dir }}/../hackrf-scanner" + control_pubkey: ~/.ssh/id_ed25519.pub gitea_host: monitor.yss.su gitea_port: 2222 - server_ip: 11.0.0.100 + server_ip: 11.0.0.101 hosts: node102: - ansible_host: 192.168.1.45 + ansible_host: 11.0.0.102 sdr_id: 1 - static_ip: 11.0.0.102 sdr_serial: a32868dc35944247 x: -0.68 y: -1.28 node104: - ansible_host: 192.168.1.50 + ansible_host: 11.0.0.104 sdr_id: 2 - static_ip: 11.0.0.104 sdr_serial: 42a068dc377ab507 note: PortaPack x: 2.28 y: 0.45 node105: - ansible_host: 192.168.1.87 + ansible_host: 11.0.0.105 sdr_id: 3 - static_ip: 11.0.0.105 sdr_serial: a32868dc33894f47 x: 3.77 y: -0.74 node106: - ansible_host: 192.168.1.42 + ansible_host: 11.0.0.106 sdr_id: 4 - static_ip: 11.0.0.106 sdr_serial: a32868dc346d2847 x: 0.00 y: 0.50 + node107: + ansible_host: 11.0.0.107 + sdr_id: 5 + sdr_serial: "" + note: HackRF ещё не подключался, серийник и координаты уточнить + x: 0.00 + y: 0.00 From c72bea1a5e1ab4e495ea046c12a462fc1e058d60 Mon Sep 17 00:00:00 2001 From: Arseny <20096ninja@gmail.com> Date: Thu, 24 Sep 2026 23:36:10 +0300 Subject: [PATCH 02/10] =?UTF-8?q?[ADD]=20=D0=BF=D0=BB=D0=B5=D0=B9=D0=B1?= =?UTF-8?q?=D1=83=D0=BA=D0=B8=20bootstrap,=20wifi-on,=20wifi-off,=20deploy?= =?UTF-8?q?,=20poweroff?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + bootstrap.yml | 13 +++++++++ deploy.yml | 58 ++++++++++++++++++++++++++++++++++++++++ poweroff.yml | 18 +++++++++++++ vars/wifi.yml.example | 4 +++ wifi-off.yml | 19 +++++++++++++ wifi-on.yml | 62 +++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 175 insertions(+) create mode 100644 bootstrap.yml create mode 100644 deploy.yml create mode 100644 poweroff.yml create mode 100644 vars/wifi.yml.example create mode 100644 wifi-off.yml create mode 100644 wifi-on.yml diff --git a/.gitignore b/.gitignore index 23e80b0..5a8222a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ keys/ +vars/wifi.yml *.retry diff --git a/bootstrap.yml b/bootstrap.yml new file mode 100644 index 0000000..cde1553 --- /dev/null +++ b/bootstrap.yml @@ -0,0 +1,13 @@ +# Голый узел: вход по паролю pi/raspberry, кладём ключ управляющей машины. +# После этого остальные плейбуки ходят по ключу. +# ansible-playbook bootstrap.yml -l node107 +- name: Ключ управляющей машины на узел + hosts: all + gather_facts: false + vars: + ansible_password: raspberry + tasks: + - name: Публичный ключ в authorized_keys пользователя pi + ansible.posix.authorized_key: + user: pi + key: "{{ lookup('file', control_pubkey) }}" diff --git a/deploy.yml b/deploy.yml new file mode 100644 index 0000000..71f5572 --- /dev/null +++ b/deploy.yml @@ -0,0 +1,58 @@ +# Исходники hackrf-scanner с управляющей машины (scanner_src) на узлы и сборка +# на месте. Интернет не нужен, зависимости ставит playbook.yml (тег base). +# Что уехало, видно в ~/hackrf-scanner/DEPLOYED (git describe). +- name: Код hackrf-scanner на узлы и сборка + hosts: all + gather_facts: false + vars: + scanner_dest: /home/pi/hackrf-scanner + tasks: + - name: Ревизия исходников на управляющей машине + delegate_to: localhost + run_once: true + ansible.builtin.command: git -C {{ scanner_src }} describe --always --dirty + register: rev + changed_when: false + + - name: Исходники на узле (без .git и build), лишние файлы удаляются + ansible.posix.synchronize: + src: "{{ scanner_src }}/" + dest: "{{ scanner_dest }}/" + delete: true + rsync_opts: + - "--exclude=.git" + - "--exclude=build*" + - "--exclude=.cache" + - "--exclude=__pycache__" + - "--exclude=DEPLOYED" + + - name: След клона прежнего провижнинга не нужен + ansible.builtin.file: + path: "{{ scanner_dest }}/.git" + state: absent + + - name: Метка ревизии + ansible.builtin.copy: + content: "{{ rev.stdout }}\n" + dest: "{{ scanner_dest }}/DEPLOYED" + mode: "0644" + + - name: Сборка + ansible.builtin.shell: | + cmake -B build -DCMAKE_BUILD_TYPE=RelWithDebInfo >/dev/null + cmake --build build -j"$(nproc)" + args: + chdir: "{{ scanner_dest }}" + register: build + changed_when: "'Building CXX' in build.stdout or 'Linking' in build.stdout" + + - name: Бинарники на месте + ansible.builtin.stat: + path: "{{ scanner_dest }}/build/{{ item }}" + register: bins + failed_when: not bins.stat.exists + loop: [peleng, scan] + + - name: Итог по узлу + ansible.builtin.debug: + msg: "[+] {{ inventory_hostname }}: {{ rev.stdout }} собран" diff --git a/poweroff.yml b/poweroff.yml new file mode 100644 index 0000000..cc70eb8 --- /dev/null +++ b/poweroff.yml @@ -0,0 +1,18 @@ +# Штатное выключение всех узлов перед снятием питания. +# Плейбук ждёт, пока ssh каждого узла перестанет отвечать. +- name: Выключение узлов + hosts: all + gather_facts: false + tasks: + - name: poweroff + become: true + community.general.shutdown: + delay: 0 + + - name: Узел ушёл из сети + delegate_to: localhost + ansible.builtin.wait_for: + host: "{{ ansible_host }}" + port: 22 + state: stopped + timeout: 90 diff --git a/vars/wifi.yml.example b/vars/wifi.yml.example new file mode 100644 index 0000000..f0f92be --- /dev/null +++ b/vars/wifi.yml.example @@ -0,0 +1,4 @@ +# Домашняя сеть для провижнинга (apt, обновления). Скопировать в vars/wifi.yml, +# он в .gitignore. Смена роутера - смена этих двух строк и прогон wifi-on.yml. +wifi_ssid: Keenetic-6852 +wifi_psk: пароль diff --git a/wifi-off.yml b/wifi-off.yml new file mode 100644 index 0000000..4f49bcf --- /dev/null +++ b/wifi-off.yml @@ -0,0 +1,19 @@ +# Перед работой Wi-Fi узлов выключается: адаптер сидит в 2,4 ГГц рядом +# с приёмником. Состояние радио NetworkManager помнит через перезагрузку, +# обратно включает только wifi-on.yml. +- name: Wi-Fi выключить + hosts: all + gather_facts: false + tasks: + - name: Радио Wi-Fi выключено + become: true + ansible.builtin.shell: | + if [ "$(nmcli radio wifi)" = disabled ]; then echo OK; else nmcli radio wifi off && echo CHANGED; fi + register: radio + changed_when: "'CHANGED' in radio.stdout" + + - name: wlan0 без адреса + ansible.builtin.command: ip -4 -o addr show wlan0 + register: wlan + changed_when: false + failed_when: wlan.stdout != "" diff --git a/wifi-on.yml b/wifi-on.yml new file mode 100644 index 0000000..dc54a8c --- /dev/null +++ b/wifi-on.yml @@ -0,0 +1,62 @@ +# Узлы подключаются к домашней сети (vars/wifi.yml) ради интернета для apt. +# Проводная сеть 11.0.0.0/24 без шлюза, поэтому маршрут по умолчанию +# и DNS приходят от Wi-Fi. В конце каждый узел обязан достучаться до интернета. +- name: Wi-Fi включить и подключить к домашней сети + hosts: all + gather_facts: false + vars_files: + - vars/wifi.yml + vars: + wifi_con: fleet-wifi + tasks: + - name: Радио Wi-Fi включено + become: true + ansible.builtin.shell: | + if [ "$(nmcli radio wifi)" = enabled ]; then echo OK; else nmcli radio wifi on && echo CHANGED; fi + register: radio + changed_when: "'CHANGED' in radio.stdout" + + - name: Профиль {{ wifi_con }} с актуальными SSID и паролем + become: true + community.general.nmcli: + conn_name: "{{ wifi_con }}" + ifname: wlan0 + type: wifi + ssid: "{{ wifi_ssid }}" + wifi_sec: + key-mgmt: wpa-psk + psk: "{{ wifi_psk }}" + autoconnect: true + state: present + register: profile + + - name: Переподключение после смены SSID или пароля + become: true + ansible.builtin.command: nmcli con down {{ wifi_con }} + when: profile.changed + failed_when: false + + - name: Подключение активно + become: true + ansible.builtin.shell: | + state=$(nmcli -t -f GENERAL.STATE con show {{ wifi_con }} | cut -d: -f2) + if [ "$state" = activated ]; then echo OK; else nmcli con up {{ wifi_con }} >/dev/null && echo CHANGED; fi + register: up + changed_when: "'CHANGED' in up.stdout" + + - name: Интернет доступен (DNS и HTTPS) + ansible.builtin.uri: + url: https://deb.debian.org/ + register: inet + retries: 6 + delay: 5 + until: inet.status == 200 + + - name: Адрес в домашней сети + ansible.builtin.command: nmcli -t -f IP4.ADDRESS con show {{ wifi_con }} + register: addr + changed_when: false + + - name: Итог по узлу + ansible.builtin.debug: + msg: "[+] {{ inventory_hostname }}: {{ addr.stdout | regex_replace('^IP4.ADDRESS\\[1\\]:', '') }}, интернет есть" From 0fe490c95e9305b4de03c2662ad79ef0b8f33664 Mon Sep 17 00:00:00 2001 From: Arseny <20096ninja@gmail.com> Date: Thu, 24 Sep 2026 23:36:10 +0300 Subject: [PATCH 03/10] =?UTF-8?q?[UPDATE]=20playbook=20=D0=B1=D0=B5=D0=B7?= =?UTF-8?q?=20=D0=BA=D0=BB=D0=BE=D0=BD=D0=B0=20=D0=B8=20=D1=81=D0=B1=D0=BE?= =?UTF-8?q?=D1=80=D0=BA=D0=B8,=20=D0=BA=D0=BE=D0=B4=20=D1=83=D0=B7=D0=BB?= =?UTF-8?q?=D0=B0=20=D0=BA=D0=BB=D0=B0=D0=B4=D1=91=D1=82=20deploy.yml,=20R?= =?UTF-8?q?EADME?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 74 ++++++++++++++++++++++++++++++---------------------- playbook.yml | 52 +++++------------------------------- run.sh | 9 ------- 3 files changed, 49 insertions(+), 86 deletions(-) delete mode 100755 run.sh diff --git a/README.md b/README.md index e8063fa..1a0372e 100644 --- a/README.md +++ b/README.md @@ -1,47 +1,59 @@ # fleet -Идемпотентный провижнинг парка приёмников пеленгации (Raspberry Pi + HackRF). -Один прогон приводит новую или старую малинку в рабочее состояние: обновление -системы, зависимости сборки, общий deploy-ключ до Gitea, клон и сборка -`hackrf-scanner`. - -Гоняется дома, пока узлы в сети с интернетом. После переноса в изолированную -сеть (коммутатор, статические IP) на карте уже есть всё; правки кода дальше -идут `rsync` + сборка на месте. Статические IP playbook не трогает. +Плейбуки ansible, которые приводят любую малинку парка (Raspberry Pi + +HackRF) в рабочее состояние и обслуживают её дальше: домашний Wi-Fi ради +интернета, пакеты, код `hackrf-scanner` со сборкой на месте, выключение. +Управление идёт по проводной сети 11.0.0.0/24 (`ansible_host` в инвентаре), +Wi-Fi нужен только на время установки пакетов и перед работой выключается, +потому что адаптер сидит в 2,4 ГГц рядом с приёмником. ## Требования -- на управляющей машине: `ansible` (Arch: `pacman -S ansible`), доступ по ssh - к узлам под `pi` по ключу; -- на узлах: Raspberry Pi OS (Debian 13), `pi` с sudo без пароля, интернет. +- управляющая машина: `ansible` с коллекциями `community.general` и + `ansible.posix`, `rsync`, `sshpass` (только для `bootstrap.yml`), + рядом лежит каталог `../hackrf-scanner` (переменная `scanner_src`); +- узлы: Raspberry Pi OS Lite (Debian 13, NetworkManager), пользователь `pi` + с sudo без пароля, статический адрес 11.0.0.x на eth0; на полном образе + с рабочим столом первый `full-upgrade` по Wi-Fi идёт больше часа; +- `vars/wifi.yml` (в `.gitignore`) по образцу `vars/wifi.yml.example`. -## Первый запуск +## Новый узел - scripts/gen-key.sh # пара keys/gitea_deploy (в .gitignore) - # добавить keys/gitea_deploy.pub как deploy key (read-only) - # в Gitea: IU9/hackrf-scanner - ansible-playbook playbook.yml # весь парк +```bash +nmap -sn 11.0.0.0/24 # какие узлы в сети +ansible-playbook bootstrap.yml -l node107 # ключ по паролю pi/raspberry +ansible-playbook wifi-on.yml # Wi-Fi и проверка интернета +ansible-playbook playbook.yml # пакеты, права, имя, паспорт +ansible-playbook wifi-off.yml # Wi-Fi выключен до следующего раза +ansible-playbook deploy.yml # код с этой машины, сборка на узле +``` -## Теги +Новый узел сначала вписывается в `inventory/hosts.yml`. Смена роутера: правка +`vars/wifi.yml` и `wifi-on.yml`, профиль на узлах обновится. - base apt upgrade, зависимости, pi в plugdev - hostname имя узла из инвентаря - key deploy-ключ, ssh config, known_hosts - repo clone/pull ветки scanner_branch (stash локальных правок) - build cmake configure + build +## Плейбуки - ansible-playbook playbook.yml -l node106 --tags repo,build +| Плейбук | Что делает | +|---|---| +| `bootstrap.yml` | ключ управляющей машины в `authorized_keys`, вход по паролю | +| `wifi-on.yml` | радио включено, профиль `fleet-wifi` с кредами из `vars/wifi.yml`, подключение, проверка DNS и HTTPS | +| `playbook.yml` | теги `base` (apt, зависимости, plugdev, udev для HackRF, fish), `hostname`, `key` (deploy-ключ Gitea), `env` (`~/node.env`, только засев) | +| `wifi-off.yml` | радио выключено, NetworkManager помнит это через перезагрузку | +| `deploy.yml` | `rsync` исходников без `.git` и `build`, ревизия в `~/hackrf-scanner/DEPLOYED`, `cmake` сборка, проверка бинарников | +| `poweroff.yml` | штатное выключение и ожидание, пока узел пропадёт из сети | + +Ограничение по узлам и тегам как обычно: `-l node106`, `--tags base`. ## Инвентарь -`inventory/hosts.yml`: адреса узлов в домашней сети (транзитные), а также -справочно -- статический IP для поля, серийник HackRF и координаты x, y (м). -Ветка репозитория -- переменная `scanner_branch`. +`inventory/hosts.yml`: адрес узла в проводной сети, `sdr_id`, серийник HackRF, +координаты x, y в метрах. Координаты и `server_ip` засеваются в `~/node.env` +один раз, полевые правки на узле плейбук не перетирает. ## Приёмка -1. Прогон без `failed`. -2. Второй прогон подряд -- `changed=0` на всех узлах. -3. На узле: `hackrf_info` видит устройство, `~/hackrf-scanner/build/` собран, - `git rev-parse --abbrev-ref HEAD` = `scanner_branch`, `hostname` = имя узла. -4. `ssh -T git@monitor.yss.su` с узла отвечает Gitea. +1. Все плейбуки без `failed`, второй прогон подряд `changed=0`. +2. После `wifi-on.yml` каждый узел печатает адрес в домашней сети и + "интернет есть", после `wifi-off.yml` у `wlan0` нет адреса. +3. На узле `~/hackrf-scanner/build/peleng` и `scan` собраны, `DEPLOYED` + совпадает с `git describe` на управляющей машине, `hostname` = имя узла. diff --git a/playbook.yml b/playbook.yml index 703a5c1..4be6f9a 100644 --- a/playbook.yml +++ b/playbook.yml @@ -1,3 +1,5 @@ +# Базовый провижнинг: пакеты, права на HackRF, имя узла, deploy-ключ, паспорт. +# Нужен интернет на узлах (wifi-on.yml). Код на узлы кладёт deploy.yml. - name: Провижнинг приёмников пеленгации hosts: all tasks: @@ -16,10 +18,10 @@ upgrade: full tags: [base] - - name: Зависимости сборки и утилиты HackRF + - name: Зависимости сборки, утилиты HackRF, python для node.py become: true ansible.builtin.apt: - name: [cmake, g++, pkg-config, git, rsync, libhackrf-dev, libusb-1.0-0-dev, libfftw3-dev, hackrf, fish] + name: [cmake, g++, pkg-config, git, rsync, libhackrf-dev, libusb-1.0-0-dev, libfftw3-dev, hackrf, python3, fish] state: present tags: [base] @@ -76,7 +78,7 @@ - name: Ключа нет run_once: true ansible.builtin.fail: - msg: "[!] нет keys/gitea_deploy -- запустите scripts/gen-key.sh" + msg: "[!] нет keys/gitea_deploy, запустите scripts/gen-key.sh" when: not deploy_key.stat.exists tags: [key] @@ -109,7 +111,7 @@ StrictHostKeyChecking accept-new tags: [key] - - name: ~/node.env для обёртки node.sh (только засев, полевые правки не трогаем) + - name: ~/node.env для node.py (только засев, полевые правки не трогаем) ansible.builtin.copy: dest: ~/node.env mode: "0644" @@ -120,45 +122,3 @@ Y={{ y }} SERVER={{ server_ip }} tags: [env] - - - name: Репозиторий уже клонирован? - ansible.builtin.stat: - path: ~/hackrf-scanner/.git - register: repo_dir - tags: [repo] - - - name: Локальные правки в репо (rsync-разработка)? - ansible.builtin.command: git status --porcelain - args: - chdir: ~/hackrf-scanner - register: dirty - changed_when: false - when: repo_dir.stat.exists - tags: [repo] - - - name: Stash локальных правок перед обновлением - ansible.builtin.command: git stash push -m fleet-provision - args: - chdir: ~/hackrf-scanner - when: repo_dir.stat.exists and dirty.stdout != "" - tags: [repo] - - - name: Репозиторий hackrf-scanner - ansible.builtin.git: - repo: "{{ scanner_repo }}" - dest: ~/hackrf-scanner - version: "{{ scanner_branch }}" - update: true - force: true - register: repo - tags: [repo] - - - name: Сборка - ansible.builtin.shell: | - cmake -B build -DCMAKE_BUILD_TYPE=RelWithDebInfo >/dev/null - cmake --build build -j4 - args: - chdir: ~/hackrf-scanner - register: build - changed_when: "'Building CXX' in build.stdout or 'Linking' in build.stdout" - tags: [build] diff --git a/run.sh b/run.sh deleted file mode 100755 index 5ba4d85..0000000 --- a/run.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/sh -# run.sh [аргументы ansible-playbook] примеры: -# ./run.sh весь парк, все теги -# ./run.sh --tags base -l node106 -# ./run.sh --check --diff сухой прогон -set -e -cd "$(dirname "$0")" -[ -f keys/gitea_deploy ] || { echo "[!] нет keys/gitea_deploy -- запустите scripts/gen-key.sh"; exit 1; } -exec ansible-playbook playbook.yml "$@" From 37dd184978349e5f51aaf1486efd128cbdee1bc1 Mon Sep 17 00:00:00 2001 From: Arseny <20096ninja@gmail.com> Date: Sun, 27 Sep 2026 12:42:48 +0300 Subject: [PATCH 04/10] =?UTF-8?q?[UPDATE]=20=D0=B8=D0=BD=D0=B2=D0=B5=D0=BD?= =?UTF-8?q?=D1=82=D0=B0=D1=80=D1=8C:=20=D1=83=D0=B7=D0=BB=D1=8B=20103=20?= =?UTF-8?q?=D0=B8=20108,=20=D1=81=D0=B5=D1=80=D0=B8=D0=B9=D0=BD=D0=B8?= =?UTF-8?q?=D0=BA=D0=B8,=20=D1=80=D0=B0=D1=81=D1=81=D1=82=D0=B0=D0=BD?= =?UTF-8?q?=D0=BE=D0=B2=D0=BA=D0=B0=2027.09?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- inventory/hosts.yml | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/inventory/hosts.yml b/inventory/hosts.yml index 553039d..81bd1b0 100644 --- a/inventory/hosts.yml +++ b/inventory/hosts.yml @@ -1,3 +1,4 @@ +# Координаты x, y в метрах, замер 27.09.2026 (комната). all: vars: scanner_src: "{{ playbook_dir }}/../hackrf-scanner" @@ -10,8 +11,14 @@ all: ansible_host: 11.0.0.102 sdr_id: 1 sdr_serial: a32868dc35944247 - x: -0.68 - y: -1.28 + x: 0.34 + y: 0.47 + node103: + ansible_host: 11.0.0.103 + sdr_id: 6 + sdr_serial: d63861dc2d9b4353 + x: 0.77 + y: 0.60 node104: ansible_host: 11.0.0.104 sdr_id: 2 @@ -23,18 +30,23 @@ all: ansible_host: 11.0.0.105 sdr_id: 3 sdr_serial: a32868dc33894f47 - x: 3.77 - y: -0.74 + x: 0.00 + y: -1.02 node106: ansible_host: 11.0.0.106 sdr_id: 4 sdr_serial: a32868dc346d2847 - x: 0.00 - y: 0.50 + x: 3.77 + y: -0.78 node107: ansible_host: 11.0.0.107 sdr_id: 5 - sdr_serial: "" - note: HackRF ещё не подключался, серийник и координаты уточнить - x: 0.00 + sdr_serial: b25062dc2242970b + x: 3.77 y: 0.00 + node108: + ansible_host: 11.0.0.108 + sdr_id: 7 + sdr_serial: a32868dc33324c47 + x: -0.74 + y: 0.47 From 5417445fb5b81c8afe51de54a0316090086231df Mon Sep 17 00:00:00 2001 From: Arseny <20096ninja@gmail.com> Date: Sun, 27 Sep 2026 12:42:48 +0300 Subject: [PATCH 05/10] =?UTF-8?q?[ADD]=20reboot.yml,=20=D0=BF=D0=B5=D1=80?= =?UTF-8?q?=D0=B5=D0=B7=D0=B0=D0=BF=D0=B8=D1=81=D1=8C=20node.env=20=D1=84?= =?UTF-8?q?=D0=BB=D0=B0=D0=B3=D0=BE=D0=BC=20env=5Fforce?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 6 +++++- playbook.yml | 4 ++-- reboot.yml | 19 +++++++++++++++++++ 3 files changed, 26 insertions(+), 3 deletions(-) create mode 100644 reboot.yml diff --git a/README.md b/README.md index 1a0372e..e6b9f24 100644 --- a/README.md +++ b/README.md @@ -40,6 +40,7 @@ ansible-playbook deploy.yml # код с этой маши | `playbook.yml` | теги `base` (apt, зависимости, plugdev, udev для HackRF, fish), `hostname`, `key` (deploy-ключ Gitea), `env` (`~/node.env`, только засев) | | `wifi-off.yml` | радио выключено, NetworkManager помнит это через перезагрузку | | `deploy.yml` | `rsync` исходников без `.git` и `build`, ревизия в `~/hackrf-scanner/DEPLOYED`, `cmake` сборка, проверка бинарников | +| `reboot.yml` | перезагрузка с ожиданием возврата, печатает ядро | | `poweroff.yml` | штатное выключение и ожидание, пока узел пропадёт из сети | Ограничение по узлам и тегам как обычно: `-l node106`, `--tags base`. @@ -48,7 +49,10 @@ ansible-playbook deploy.yml # код с этой маши `inventory/hosts.yml`: адрес узла в проводной сети, `sdr_id`, серийник HackRF, координаты x, y в метрах. Координаты и `server_ip` засеваются в `~/node.env` -один раз, полевые правки на узле плейбук не перетирает. +один раз, полевые правки на узле плейбук не перетирает. После смены +расстановки в инвентаре паспорта перезаписываются явно: + + ansible-playbook playbook.yml --tags env -e env_force=true ## Приёмка diff --git a/playbook.yml b/playbook.yml index 4be6f9a..9cdb559 100644 --- a/playbook.yml +++ b/playbook.yml @@ -111,11 +111,11 @@ StrictHostKeyChecking accept-new tags: [key] - - name: ~/node.env для node.py (только засев, полевые правки не трогаем) + - name: ~/node.env для node.py (засев; перезапись из инвентаря -e env_force=true) ansible.builtin.copy: dest: ~/node.env mode: "0644" - force: false + force: "{{ env_force | default(false) }}" content: | SDR_ID={{ sdr_id }} X={{ x }} diff --git a/reboot.yml b/reboot.yml new file mode 100644 index 0000000..2eb0a06 --- /dev/null +++ b/reboot.yml @@ -0,0 +1,19 @@ +# Перезагрузка узлов с ожиданием возврата по ssh (например, после обновления +# ядра). В конце каждый узел печатает ядро, на котором поднялся. +- name: Перезагрузка узлов + hosts: all + gather_facts: false + tasks: + - name: reboot и ожидание возврата + become: true + ansible.builtin.reboot: + reboot_timeout: 300 + + - name: Ядро после перезагрузки + ansible.builtin.command: uname -r + register: kernel + changed_when: false + + - name: Итог по узлу + ansible.builtin.debug: + msg: "[+] {{ inventory_hostname }}: поднялся, ядро {{ kernel.stdout }}" From bd4443d5f10837da124140c6daca029defa098ba Mon Sep 17 00:00:00 2001 From: Arseny <20096ninja@gmail.com> Date: Sat, 3 Oct 2026 18:27:34 +0300 Subject: [PATCH 06/10] =?UTF-8?q?[ADD]=20env.yml:=20=D0=BF=D0=B0=D1=81?= =?UTF-8?q?=D0=BF=D0=BE=D1=80=D1=82=20=D1=83=D0=B7=D0=BB=D0=B0=20=D0=B8?= =?UTF-8?q?=D0=B7=20=D0=B8=D0=BD=D0=B2=D0=B5=D0=BD=D1=82=D0=B0=D1=80=D1=8F?= =?UTF-8?q?=20=D0=BE=D1=82=D0=B4=D0=B5=D0=BB=D1=8C=D0=BD=D1=8B=D0=BC=20?= =?UTF-8?q?=D0=BF=D0=BB=D0=B5=D0=B9=D0=B1=D1=83=D0=BA=D0=BE=D0=BC,=20?= =?UTF-8?q?=D1=81=D0=B5=D1=80=D0=B2=D0=B5=D1=80=2011.0.0.100?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- env.yml | 22 ++++++++++++++++++++++ inventory/hosts.yml | 6 +++++- playbook.yml | 14 +------------- 3 files changed, 28 insertions(+), 14 deletions(-) create mode 100644 env.yml diff --git a/env.yml b/env.yml new file mode 100644 index 0000000..4ae8327 --- /dev/null +++ b/env.yml @@ -0,0 +1,22 @@ +# Паспорт узла ~/node.env из инвентаря: SDR_ID, X, Y, SERVER. Инвентарь главный, +# файл на узле перезаписывается целиком. peleng читает паспорт только при +# старте, поэтому после смены расстановки нужен scanner-start.yml. +# ansible-playbook env.yml --diff +- name: Паспорт узла из инвентаря + hosts: all + gather_facts: false + tasks: + - name: ~/node.env + ansible.builtin.copy: + dest: ~/node.env + mode: "0644" + content: | + SDR_ID={{ sdr_id }} + X={{ x }} + Y={{ y }} + SERVER={{ server_ip }} + register: env + + - name: Итог по узлу + ansible.builtin.debug: + msg: "[{{ '+' if env.changed else 'i' }}] {{ inventory_hostname }}: SDR_ID={{ sdr_id }} X={{ x }} Y={{ y }} SERVER={{ server_ip }}{{ ' (обновлён)' if env.changed else '' }}" diff --git a/inventory/hosts.yml b/inventory/hosts.yml index 81bd1b0..2b82997 100644 --- a/inventory/hosts.yml +++ b/inventory/hosts.yml @@ -5,7 +5,11 @@ all: control_pubkey: ~/.ssh/id_ed25519.pub gitea_host: monitor.yss.su gitea_port: 2222 - server_ip: 11.0.0.101 + server_ip: 11.0.0.100 + scanner_dir: /home/pi/hackrf-scanner + # Запуск по умолчанию для scanner-start.yml; поверх: -e scanner_args="--freq 2437 --lna 8" + scanner_profile: dji24 + scanner_args: "" hosts: node102: ansible_host: 11.0.0.102 diff --git a/playbook.yml b/playbook.yml index 9cdb559..3021c25 100644 --- a/playbook.yml +++ b/playbook.yml @@ -1,4 +1,4 @@ -# Базовый провижнинг: пакеты, права на HackRF, имя узла, deploy-ключ, паспорт. +# Базовый провижнинг: пакеты, права на HackRF, имя узла, deploy-ключ. # Нужен интернет на узлах (wifi-on.yml). Код на узлы кладёт deploy.yml. - name: Провижнинг приёмников пеленгации hosts: all @@ -110,15 +110,3 @@ IdentitiesOnly yes StrictHostKeyChecking accept-new tags: [key] - - - name: ~/node.env для node.py (засев; перезапись из инвентаря -e env_force=true) - ansible.builtin.copy: - dest: ~/node.env - mode: "0644" - force: "{{ env_force | default(false) }}" - content: | - SDR_ID={{ sdr_id }} - X={{ x }} - Y={{ y }} - SERVER={{ server_ip }} - tags: [env] From 401ef2c101f4837b9608c1b07e8a9c5e85613dd8 Mon Sep 17 00:00:00 2001 From: Arseny <20096ninja@gmail.com> Date: Sat, 3 Oct 2026 18:27:34 +0300 Subject: [PATCH 07/10] =?UTF-8?q?[ADD]=20scanner-start=20=D0=B8=20scanner-?= =?UTF-8?q?stop:=20peleng=20=D0=BD=D0=B0=20=D0=B2=D1=81=D0=B5=D1=85=20?= =?UTF-8?q?=D1=83=D0=B7=D0=BB=D0=B0=D1=85=20=D0=BE=D0=B4=D0=BD=D0=BE=D0=B9?= =?UTF-8?q?=20=D0=BA=D0=BE=D0=BC=D0=B0=D0=BD=D0=B4=D0=BE=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 40 +++++++++++++++++++++++++++++++--------- ansible.cfg | 2 ++ deploy.yml | 12 +++++------- scanner-start.yml | 23 +++++++++++++++++++++++ scanner-stop.yml | 22 ++++++++++++++++++++++ 5 files changed, 83 insertions(+), 16 deletions(-) create mode 100644 scanner-start.yml create mode 100644 scanner-stop.yml diff --git a/README.md b/README.md index e6b9f24..b5091d4 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,9 @@ # fleet Плейбуки ansible, которые приводят любую малинку парка (Raspberry Pi + -HackRF) в рабочее состояние и обслуживают её дальше: домашний Wi-Fi ради -интернета, пакеты, код `hackrf-scanner` со сборкой на месте, выключение. +HackRF) в рабочее состояние и управляют ею дальше: домашний Wi-Fi ради +интернета, пакеты, код `hackrf-scanner` со сборкой на месте, паспорт узла, +запуск и остановка сканера, перезагрузка и выключение. Управление идёт по проводной сети 11.0.0.0/24 (`ansible_host` в инвентаре), Wi-Fi нужен только на время установки пакетов и перед работой выключается, потому что адаптер сидит в 2,4 ГГц рядом с приёмником. @@ -23,11 +24,28 @@ Wi-Fi нужен только на время установки пакетов nmap -sn 11.0.0.0/24 # какие узлы в сети ansible-playbook bootstrap.yml -l node107 # ключ по паролю pi/raspberry ansible-playbook wifi-on.yml # Wi-Fi и проверка интернета -ansible-playbook playbook.yml # пакеты, права, имя, паспорт +ansible-playbook playbook.yml # пакеты, права, имя ansible-playbook wifi-off.yml # Wi-Fi выключен до следующего раза ansible-playbook deploy.yml # код с этой машины, сборка на узле +ansible-playbook env.yml # паспорт ~/node.env из инвентаря ``` +## Работа + +```bash +# 1. расстановка: x, y узлов и server_ip в inventory/hosts.yml +ansible-playbook env.yml --diff # 2. паспорта на узлы +ansible-playbook scanner-start.yml # 3. peleng на всех узлах +ansible-playbook scanner-start.yml -e scanner_args="--freq 2437 --lna 8" +ansible-playbook scanner-stop.yml # HackRF свободен (scan, калибровка) +``` + +`scanner-start.yml` на каждом узле зовёт `node.py start <профиль> <флаги>`: +останавливает прежний peleng и любой процесс, держащий HackRF, переинициализирует +USB и запускает peleng в фоне с логом `/tmp/peleng.log`. Профиль и флаги по +умолчанию - `scanner_profile` и `scanner_args` в инвентаре. peleng читает паспорт +только при старте, поэтому после `env.yml` нужен повторный `scanner-start.yml`. + Новый узел сначала вписывается в `inventory/hosts.yml`. Смена роутера: правка `vars/wifi.yml` и `wifi-on.yml`, профиль на узлах обновится. @@ -37,9 +55,12 @@ ansible-playbook deploy.yml # код с этой маши |---|---| | `bootstrap.yml` | ключ управляющей машины в `authorized_keys`, вход по паролю | | `wifi-on.yml` | радио включено, профиль `fleet-wifi` с кредами из `vars/wifi.yml`, подключение, проверка DNS и HTTPS | -| `playbook.yml` | теги `base` (apt, зависимости, plugdev, udev для HackRF, fish), `hostname`, `key` (deploy-ключ Gitea), `env` (`~/node.env`, только засев) | +| `playbook.yml` | теги `base` (apt, зависимости, plugdev, udev для HackRF, fish), `hostname`, `key` (deploy-ключ Gitea) | | `wifi-off.yml` | радио выключено, NetworkManager помнит это через перезагрузку | | `deploy.yml` | `rsync` исходников без `.git` и `build`, ревизия в `~/hackrf-scanner/DEPLOYED`, `cmake` сборка, проверка бинарников | +| `env.yml` | `~/node.env` (`SDR_ID`, `X`, `Y`, `SERVER`) из инвентаря, перезаписывается целиком | +| `scanner-start.yml` | `node.py start`: освободить HackRF, переинициализировать USB, peleng в фоне, `status` | +| `scanner-stop.yml` | `node.py stop`: peleng и любой процесс с HackRF остановлены, проверка `status` | | `reboot.yml` | перезагрузка с ожиданием возврата, печатает ядро | | `poweroff.yml` | штатное выключение и ожидание, пока узел пропадёт из сети | @@ -48,11 +69,10 @@ ansible-playbook deploy.yml # код с этой маши ## Инвентарь `inventory/hosts.yml`: адрес узла в проводной сети, `sdr_id`, серийник HackRF, -координаты x, y в метрах. Координаты и `server_ip` засеваются в `~/node.env` -один раз, полевые правки на узле плейбук не перетирает. После смены -расстановки в инвентаре паспорта перезаписываются явно: - - ansible-playbook playbook.yml --tags env -e env_force=true +координаты x, y в метрах. Общие переменные: `server_ip` (куда узлы шлют замеры), +`scanner_dir` (каталог сканера на узле), `scanner_profile` и `scanner_args` +(запуск по умолчанию). Инвентарь главный: `env.yml` перезаписывает паспорт узла, +правки руками на узле до следующего прогона. ## Приёмка @@ -61,3 +81,5 @@ ansible-playbook deploy.yml # код с этой маши "интернет есть", после `wifi-off.yml` у `wlan0` нет адреса. 3. На узле `~/hackrf-scanner/build/peleng` и `scan` собраны, `DEPLOYED` совпадает с `git describe` на управляющей машине, `hostname` = имя узла. +4. После `scanner-start.yml` каждый узел печатает "peleng запущен" и строку + замера, после `scanner-stop.yml` статус "не запущен". diff --git a/ansible.cfg b/ansible.cfg index a91ab09..ddd4611 100644 --- a/ansible.cfg +++ b/ansible.cfg @@ -3,6 +3,8 @@ inventory = inventory/hosts.yml remote_user = pi host_key_checking = False interpreter_python = auto_silent +# Все узлы парка одновременно: старт сканера ждёт USB и первый замер ~15 с на узел +forks = 16 [ssh_connection] pipelining = True diff --git a/deploy.yml b/deploy.yml index 71f5572..050aadd 100644 --- a/deploy.yml +++ b/deploy.yml @@ -4,8 +4,6 @@ - name: Код hackrf-scanner на узлы и сборка hosts: all gather_facts: false - vars: - scanner_dest: /home/pi/hackrf-scanner tasks: - name: Ревизия исходников на управляющей машине delegate_to: localhost @@ -17,7 +15,7 @@ - name: Исходники на узле (без .git и build), лишние файлы удаляются ansible.posix.synchronize: src: "{{ scanner_src }}/" - dest: "{{ scanner_dest }}/" + dest: "{{ scanner_dir }}/" delete: true rsync_opts: - "--exclude=.git" @@ -28,13 +26,13 @@ - name: След клона прежнего провижнинга не нужен ansible.builtin.file: - path: "{{ scanner_dest }}/.git" + path: "{{ scanner_dir }}/.git" state: absent - name: Метка ревизии ansible.builtin.copy: content: "{{ rev.stdout }}\n" - dest: "{{ scanner_dest }}/DEPLOYED" + dest: "{{ scanner_dir }}/DEPLOYED" mode: "0644" - name: Сборка @@ -42,13 +40,13 @@ cmake -B build -DCMAKE_BUILD_TYPE=RelWithDebInfo >/dev/null cmake --build build -j"$(nproc)" args: - chdir: "{{ scanner_dest }}" + chdir: "{{ scanner_dir }}" register: build changed_when: "'Building CXX' in build.stdout or 'Linking' in build.stdout" - name: Бинарники на месте ansible.builtin.stat: - path: "{{ scanner_dest }}/build/{{ item }}" + path: "{{ scanner_dir }}/build/{{ item }}" register: bins failed_when: not bins.stat.exists loop: [peleng, scan] diff --git a/scanner-start.yml b/scanner-start.yml new file mode 100644 index 0000000..8ee6a41 --- /dev/null +++ b/scanner-start.yml @@ -0,0 +1,23 @@ +# Запуск peleng на всех узлах одной командой node.py start: остановить прежний +# peleng и любой процесс, держащий HackRF, переинициализировать USB, запустить +# в фоне (лог /tmp/peleng.log). Профиль и флаги из инвентаря или поверх: +# ansible-playbook scanner-start.yml -e scanner_args="--freq 2437 --lna 8" +- name: Запуск сканера на узлах + hosts: all + gather_facts: false + tasks: + - name: node.py start {{ scanner_profile }} {{ scanner_args }} + ansible.builtin.command: + argv: "{{ ['python3', scanner_dir + '/scripts/node.py', 'start', scanner_profile] + scanner_args.split() }}" + register: start + changed_when: true + + - name: node.py status + ansible.builtin.command: + argv: ["python3", "{{ scanner_dir }}/scripts/node.py", "status"] + register: status + changed_when: false + + - name: Итог по узлу + ansible.builtin.debug: + msg: "{{ start.stdout_lines + status.stdout_lines }}" diff --git a/scanner-stop.yml b/scanner-stop.yml new file mode 100644 index 0000000..817d312 --- /dev/null +++ b/scanner-stop.yml @@ -0,0 +1,22 @@ +# Остановка peleng на всех узлах: node.py stop останавливает свой peleng и любой +# процесс, держащий HackRF. После этого HackRF свободен для scan или калибровки. +- name: Остановка сканера на узлах + hosts: all + gather_facts: false + tasks: + - name: node.py stop + ansible.builtin.command: + argv: ["python3", "{{ scanner_dir }}/scripts/node.py", "stop"] + register: stop + changed_when: stop.stdout | length > 0 + + - name: node.py status + ansible.builtin.command: + argv: ["python3", "{{ scanner_dir }}/scripts/node.py", "status"] + register: status + changed_when: false + failed_when: "'работает' in status.stdout" + + - name: Итог по узлу + ansible.builtin.debug: + msg: "{{ stop.stdout_lines + status.stdout_lines }}" From e2f224e622cbb07976c4c749b787808cc8d2bf3d Mon Sep 17 00:00:00 2001 From: Arseny <20096ninja@gmail.com> Date: Sat, 3 Oct 2026 18:38:26 +0300 Subject: [PATCH 08/10] =?UTF-8?q?[UPDATE]=20=D0=BF=D0=B0=D1=80=D0=B0=D0=BC?= =?UTF-8?q?=D0=B5=D1=82=D1=80=D1=8B=20=D0=B7=D0=B0=D0=BF=D1=83=D1=81=D0=BA?= =?UTF-8?q?=D0=B0=20=D1=81=D0=BA=D0=B0=D0=BD=D0=B5=D1=80=D0=B0=20=D0=B2=20?= =?UTF-8?q?inventory/group=5Fvars/all/scanner.yml?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 15 +++++++++------ inventory/group_vars/all/scanner.yml | 12 ++++++++++++ inventory/hosts.yml | 3 --- scanner-start.yml | 4 ++-- 4 files changed, 23 insertions(+), 11 deletions(-) create mode 100644 inventory/group_vars/all/scanner.yml diff --git a/README.md b/README.md index b5091d4..acfe5b7 100644 --- a/README.md +++ b/README.md @@ -35,15 +35,18 @@ ansible-playbook env.yml # паспорт ~/node.env и ```bash # 1. расстановка: x, y узлов и server_ip в inventory/hosts.yml ansible-playbook env.yml --diff # 2. паспорта на узлы -ansible-playbook scanner-start.yml # 3. peleng на всех узлах -ansible-playbook scanner-start.yml -e scanner_args="--freq 2437 --lna 8" +# 3. частота и усиления: inventory/group_vars/all/scanner.yml +ansible-playbook scanner-start.yml # 4. peleng на всех узлах +ansible-playbook scanner-start.yml -e scanner_args="--freq 2437" # разово поверх ansible-playbook scanner-stop.yml # HackRF свободен (scan, калибровка) ``` `scanner-start.yml` на каждом узле зовёт `node.py start <профиль> <флаги>`: останавливает прежний peleng и любой процесс, держащий HackRF, переинициализирует -USB и запускает peleng в фоне с логом `/tmp/peleng.log`. Профиль и флаги по -умолчанию - `scanner_profile` и `scanner_args` в инвентаре. peleng читает паспорт +USB и запускает peleng в фоне с логом `/tmp/peleng.log`. Профиль и флаги лежат в +`inventory/group_vars/all/scanner.yml` (`scanner_profile`, `scanner_args`); узлу +можно задать своё значение в `inventory/hosts.yml`, разовый запуск поверх всего +через `-e`. peleng читает паспорт только при старте, поэтому после `env.yml` нужен повторный `scanner-start.yml`. Новый узел сначала вписывается в `inventory/hosts.yml`. Смена роутера: правка @@ -70,8 +73,8 @@ USB и запускает peleng в фоне с логом `/tmp/peleng.log`. П `inventory/hosts.yml`: адрес узла в проводной сети, `sdr_id`, серийник HackRF, координаты x, y в метрах. Общие переменные: `server_ip` (куда узлы шлют замеры), -`scanner_dir` (каталог сканера на узле), `scanner_profile` и `scanner_args` -(запуск по умолчанию). Инвентарь главный: `env.yml` перезаписывает паспорт узла, +`scanner_dir` (каталог сканера на узле). Параметры запуска сканера - в +`inventory/group_vars/all/scanner.yml`. Инвентарь главный: `env.yml` перезаписывает паспорт узла, правки руками на узле до следующего прогона. ## Приёмка diff --git a/inventory/group_vars/all/scanner.yml b/inventory/group_vars/all/scanner.yml new file mode 100644 index 0000000..8e64820 --- /dev/null +++ b/inventory/group_vars/all/scanner.yml @@ -0,0 +1,12 @@ +# Как запускать сканер: scanner-start.yml берёт эти значения на всех узлах. +# Правка тут, затем ansible-playbook scanner-start.yml. +# +# Узлу можно задать своё значение в inventory/hosts.yml (например, другой +# --lna у PortaPack node104), оно перекроет этот файл. Разовый запуск поверх +# всего: ansible-playbook scanner-start.yml -e scanner_args="--freq 2437". +# +# Профили node.py: dji24, vtx58, lte, pp24, pn24. Флаги peleng переопределяют +# профиль; калибровка сервера должна быть снята с теми же --lna и --vga. + +scanner_profile: dji24 +scanner_args: "--freq 2422 --lna 8" diff --git a/inventory/hosts.yml b/inventory/hosts.yml index 2b82997..609abab 100644 --- a/inventory/hosts.yml +++ b/inventory/hosts.yml @@ -7,9 +7,6 @@ all: gitea_port: 2222 server_ip: 11.0.0.100 scanner_dir: /home/pi/hackrf-scanner - # Запуск по умолчанию для scanner-start.yml; поверх: -e scanner_args="--freq 2437 --lna 8" - scanner_profile: dji24 - scanner_args: "" hosts: node102: ansible_host: 11.0.0.102 diff --git a/scanner-start.yml b/scanner-start.yml index 8ee6a41..fad57e6 100644 --- a/scanner-start.yml +++ b/scanner-start.yml @@ -1,7 +1,7 @@ # Запуск peleng на всех узлах одной командой node.py start: остановить прежний # peleng и любой процесс, держащий HackRF, переинициализировать USB, запустить -# в фоне (лог /tmp/peleng.log). Профиль и флаги из инвентаря или поверх: -# ansible-playbook scanner-start.yml -e scanner_args="--freq 2437 --lna 8" +# в фоне (лог /tmp/peleng.log). Профиль и флаги в inventory/group_vars/all/scanner.yml, +# разово поверх: ansible-playbook scanner-start.yml -e scanner_args="--freq 2437" - name: Запуск сканера на узлах hosts: all gather_facts: false From 87f752a0f89c25c75e163ebad71af8211633ea02 Mon Sep 17 00:00:00 2001 From: Arseny <20096ninja@gmail.com> Date: Sat, 3 Oct 2026 18:40:08 +0300 Subject: [PATCH 09/10] =?UTF-8?q?[UPDATE]=20README:=20ansible=20=D0=BD?= =?UTF-8?q?=D0=B0=20Alt=20Linux?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index acfe5b7..150794e 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,11 @@ Wi-Fi нужен только на время установки пакетов - управляющая машина: `ansible` с коллекциями `community.general` и `ansible.posix`, `rsync`, `sshpass` (только для `bootstrap.yml`), рядом лежит каталог `../hackrf-scanner` (переменная `scanner_src`); + Alt Linux p11 и Sisyphus: `apt-get install ansible + python3-module-ansible-collections-ansible-posix sshpass rsync openssh-clients`; + на p10 пакет `ansible` 2.9 не подходит, нужны `ansible-core + python3-module-packaging glibc-locales` и `ansible-galaxy collection install + community.general ansible.posix`; - узлы: Raspberry Pi OS Lite (Debian 13, NetworkManager), пользователь `pi` с sudo без пароля, статический адрес 11.0.0.x на eth0; на полном образе с рабочим столом первый `full-upgrade` по Wi-Fi идёт больше часа; From 18bb3335c6a4cb7754d3af4e4566b35adb6d7a2a Mon Sep 17 00:00:00 2001 From: Arseny <20096ninja@gmail.com> Date: Sat, 3 Oct 2026 18:54:52 +0300 Subject: [PATCH 10/10] add Alt install --- install-on-alt.sh | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 install-on-alt.sh diff --git a/install-on-alt.sh b/install-on-alt.sh new file mode 100644 index 0000000..13c32cc --- /dev/null +++ b/install-on-alt.sh @@ -0,0 +1,3 @@ +apt-get install ansible-core python3-module-packaging glibc-locales sshpass rsync openssh-clients +export LANG=en_US.UTF-8 +ansible-galaxy collection install community.general ansible.posix