feat: openwrt packages (#82)

This commit is contained in:
LowderPlay
2026-08-18 03:09:15 +05:00
committed by GitHub
parent 3f74894786
commit 9883d31a67
10 changed files with 405 additions and 2 deletions
+35 -1
View File
@@ -11,6 +11,7 @@ env:
CARGO_TERM_COLOR: always
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}-probe
OPENWRT_ARM64_ARCHES: aarch64_generic aarch64_cortex-a53 aarch64_cortex-a72
jobs:
linux-amd64:
@@ -51,7 +52,7 @@ jobs:
compression-level: 0
linux-arm64:
name: Linux arm64 binary and .deb
name: Linux arm64 binary, .deb, and OpenWrt packages
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
@@ -73,6 +74,30 @@ jobs:
- name: Build Debian package
run: cargo deb --package probe --target aarch64-unknown-linux-musl --no-strip --no-build -- --bin cheburprobe
- name: Build legacy OpenWrt opkg packages
run: |
chmod +x probe/openwrt/build-ipk.sh
for arch in $OPENWRT_ARM64_ARCHES; do
OPENWRT_ARCH="$arch" probe/openwrt/build-ipk.sh \
target/aarch64-unknown-linux-musl/release/cheburprobe \
target/aarch64-unknown-linux-musl/openwrt
done
- name: Build current OpenWrt APK packages
run: |
chmod +x probe/openwrt/build-apk.sh
for arch in $OPENWRT_ARM64_ARCHES; do
docker run --rm \
--env OPENWRT_ARCH="$arch" \
--env PACKAGE_FILE_ARCH_SUFFIX=1 \
--volume "$PWD:/work" \
--workdir /work \
alpine:edge \
probe/openwrt/build-apk.sh \
target/aarch64-unknown-linux-musl/release/cheburprobe \
target/aarch64-unknown-linux-musl/openwrt
done
- name: Upload Linux arm64 binary
uses: actions/upload-artifact@v7
with:
@@ -87,6 +112,15 @@ jobs:
path: target/aarch64-unknown-linux-musl/debian/*.deb
compression-level: 0
- name: Upload OpenWrt arm64 and LuCI packages
uses: actions/upload-artifact@v7
with:
name: cheburprobe-openwrt-arm64-packages
path: |
target/aarch64-unknown-linux-musl/openwrt/*.apk
target/aarch64-unknown-linux-musl/openwrt/*.ipk
compression-level: 0
windows-amd64:
name: Windows amd64 binary
runs-on: windows-latest
+45 -1
View File
@@ -9,7 +9,7 @@
## Сборка
Готовые бинарные файлы и Debian-пакеты можно скачать на [странице релизов](https://github.com/LowderPlay/cheburcheck/releases).
Готовые бинарные файлы, Debian-пакеты и OpenWrt пакеты для arm64 можно скачать на [странице релизов](https://github.com/LowderPlay/cheburcheck/releases).
На Debian-based дистрибутивах можно собрать пакет через `cargo-deb`:
@@ -27,6 +27,50 @@ cargo run --package probe --bin cheburprobe -- \
Также доступен Docker-образ, который собирается из `probe/Dockerfile`.
Для OpenWrt на arm64 установите основной `.apk` и пакет LuCI. Пакеты из GitHub
Actions не подписаны, поэтому для локальной установки нужен флаг `--allow-untrusted`:
Узнать архитектуру на OpenWrt с `apk`:
```shell
apk --print-arch
```
Например, для результата `aarch64_cortex-a53` нужен файл с
`_aarch64_cortex-a53.apk` в имени:
```shell
apk --allow-untrusted add \
./cheburprobe-*_"$(apk --print-arch)".apk \
./luci-app-cheburprobe-*.apk
```
После установки откройте **Службы → Cheburprobe** в LuCI, заполните ID и токен,
включите сервис и нажмите **Сохранить и применить**. Те же настройки доступны
через UCI в `/etc/config/cheburprobe`. Конфигурационный файл устанавливается с
правами `0600`, поскольку токен хранится в нем в открытом виде.
На OpenWrt с пакетным менеджером `opkg` установите совместимые `.ipk` пакеты:
```shell
opkg print-architecture
```
Команда может вывести несколько строк. Выберите специфичную для процессора
архитектуру, например `aarch64_cortex-a53`, а не универсальную `all`.
```shell
opkg install \
./cheburprobe_*_<АРХИТЕКТУРА_УСТРОЙСТВА>.ipk \
./luci-app-cheburprobe_*_all.ipk
```
GitHub Actions выпускает пакеты для `aarch64_generic`, `aarch64_cortex-a53` и
`aarch64_cortex-a72`. Для другого имени архитектуры OpenWrt пакет можно собрать
с переменной `OPENWRT_ARCH`, например
`OPENWRT_ARCH=aarch64_cortex-a53 probe/openwrt/build-apk.sh <binary> <output-dir>`.
Та же переменная поддерживается скриптом `build-ipk.sh`.
## Получение доступа
Для подключения сканера нужен `PROBE_ID` и `PROBE_TOKEN`.
+101
View File
@@ -0,0 +1,101 @@
#!/bin/sh
set -eu
if [ "$#" -ne 2 ]; then
echo "usage: $0 <cheburprobe-binary> <output-directory>" >&2
exit 2
fi
BINARY=$1
OUTPUT_DIR=$2
APK=${APK:-apk}
ROOT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")/../.." && pwd)
WORK_DIR=$(mktemp -d)
trap 'rm -rf "$WORK_DIR"' EXIT INT TERM
mkdir -p "$OUTPUT_DIR"
OUTPUT_DIR=$(CDPATH= cd -- "$OUTPUT_DIR" && pwd)
VERSION=$(sed -n '/^name = "probe"$/,/^\[/{s/^version = "\([^"]*\)"$/\1/p;}' "$ROOT_DIR/probe/Cargo.toml")
ARCH=${OPENWRT_ARCH:-aarch64_generic}
PACKAGE_VERSION="${VERSION}-r1"
test -n "$VERSION"
test -f "$BINARY"
"$APK" --version | grep -q '^apk-tools 3\.' || {
echo "apk-tools 3.x is required to build OpenWrt APK packages" >&2
exit 1
}
add_openwrt_metadata() {
package_name=$1
package_root=$2
conffile=${3:-}
metadata_dir="$package_root/lib/apk/packages"
mkdir -p "$metadata_dir"
(cd "$package_root" && find . \( -type f -o -type l \) | sed 's|^\./|/|' | sort) \
> "$metadata_dir/$package_name.list"
if [ -n "$conffile" ]; then
printf '%s\n' "$conffile" > "$metadata_dir/$package_name.conffiles"
checksum=$(sha256sum "$package_root$conffile" | cut -d ' ' -f1)
printf '%s %s\n' "$conffile" "$checksum" \
> "$metadata_dir/$package_name.conffiles_static"
fi
}
build_apk() {
package_name=$1
package_arch=$2
package_root=$3
description=$4
depends=$5
post_install=${6:-}
filename_arch=
if [ "${PACKAGE_FILE_ARCH_SUFFIX:-0}" = 1 ] && [ "$package_arch" != noarch ]; then
filename_arch="_${package_arch}"
fi
output="$OUTPUT_DIR/${package_name}-${PACKAGE_VERSION}${filename_arch}.apk"
set -- \
mkpkg \
--info "name:$package_name" \
--info "version:$PACKAGE_VERSION" \
--info "tags:openwrt:section=net" \
--info "description:$description" \
--info "arch:$package_arch" \
--info "license:BSD-3-Clause" \
--info "origin:cheburcheck/probe" \
--info "url:https://github.com/LowderPlay/cheburcheck" \
--info "maintainer:Lowder <me@lowderplay.dev>" \
--info "depends:$depends"
if [ -n "$post_install" ]; then
set -- "$@" --script "post-install:$post_install"
fi
SOURCE_DATE_EPOCH=${SOURCE_DATE_EPOCH:-0} "$APK" "$@" \
--no-xattrs --files "$package_root" --output "$output"
echo "$output"
}
PROBE_ROOT="$WORK_DIR/cheburprobe"
mkdir -p "$PROBE_ROOT/usr/bin" "$PROBE_ROOT/etc/init.d" "$PROBE_ROOT/etc/config"
install -m 0755 "$BINARY" "$PROBE_ROOT/usr/bin/cheburprobe"
install -m 0755 "$ROOT_DIR/probe/openwrt/cheburprobe.init" "$PROBE_ROOT/etc/init.d/cheburprobe"
install -m 0600 "$ROOT_DIR/probe/openwrt/cheburprobe.config" "$PROBE_ROOT/etc/config/cheburprobe"
add_openwrt_metadata cheburprobe "$PROBE_ROOT" /etc/config/cheburprobe
build_apk cheburprobe "$ARCH" "$PROBE_ROOT" \
"Dynamic network probe daemon for Cheburcheck" "" \
"$ROOT_DIR/probe/openwrt/cheburprobe.postinst"
LUCI_ROOT="$WORK_DIR/luci-app-cheburprobe"
mkdir -p "$LUCI_ROOT/usr/share/luci/menu.d" "$LUCI_ROOT/usr/share/rpcd/acl.d" \
"$LUCI_ROOT/www/luci-static/resources/view/cheburprobe"
install -m 0644 "$ROOT_DIR/probe/openwrt/luci/menu.json" \
"$LUCI_ROOT/usr/share/luci/menu.d/luci-app-cheburprobe.json"
install -m 0644 "$ROOT_DIR/probe/openwrt/luci/acl.json" \
"$LUCI_ROOT/usr/share/rpcd/acl.d/luci-app-cheburprobe.json"
install -m 0644 "$ROOT_DIR/probe/openwrt/luci/config.js" \
"$LUCI_ROOT/www/luci-static/resources/view/cheburprobe/config.js"
add_openwrt_metadata luci-app-cheburprobe "$LUCI_ROOT"
build_apk luci-app-cheburprobe noarch "$LUCI_ROOT" \
"LuCI configuration interface for Cheburprobe" "cheburprobe luci-base"
+71
View File
@@ -0,0 +1,71 @@
#!/bin/sh
set -eu
if [ "$#" -ne 2 ]; then
echo "usage: $0 <cheburprobe-binary> <output-directory>" >&2
exit 2
fi
BINARY=$1
OUTPUT_DIR=$2
ROOT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")/../.." && pwd)
WORK_DIR=$(mktemp -d)
trap 'rm -rf "$WORK_DIR"' EXIT INT TERM
mkdir -p "$OUTPUT_DIR"
OUTPUT_DIR=$(CDPATH= cd -- "$OUTPUT_DIR" && pwd)
VERSION=$(sed -n '/^name = "probe"$/,/^\[/{s/^version = "\([^"]*\)"$/\1/p;}' "$ROOT_DIR/probe/Cargo.toml")
ARCH=${OPENWRT_ARCH:-aarch64_generic}
test -n "$VERSION"
test -f "$BINARY"
build_ipk() {
package_name=$1
package_arch=$2
package_root=$3
control_extra=$4
archive_name="${package_name}_${VERSION}-1_${package_arch}.ipk"
size_kib=$(du -sk "$package_root/data" | cut -f1)
cat > "$package_root/control/control" <<EOF
Package: ${package_name}
Version: ${VERSION}-1
Architecture: ${package_arch}
Maintainer: Lowder <me@lowderplay.dev>
License: BSD-3-Clause
Section: net
Priority: optional
Installed-Size: ${size_kib}
${control_extra}
EOF
printf '2.0\n' > "$package_root/debian-binary"
(cd "$package_root/control" && tar --sort=name --owner=0 --group=0 --numeric-owner -czf ../control.tar.gz .)
(cd "$package_root/data" && tar --sort=name --owner=0 --group=0 --numeric-owner -czf ../data.tar.gz .)
(cd "$package_root" && ar r "$OUTPUT_DIR/$archive_name" debian-binary control.tar.gz data.tar.gz)
echo "$OUTPUT_DIR/$archive_name"
}
PROBE_ROOT="$WORK_DIR/cheburprobe"
mkdir -p "$PROBE_ROOT/control" "$PROBE_ROOT/data/usr/bin" \
"$PROBE_ROOT/data/etc/init.d" "$PROBE_ROOT/data/etc/config"
install -m 0755 "$BINARY" "$PROBE_ROOT/data/usr/bin/cheburprobe"
install -m 0755 "$ROOT_DIR/probe/openwrt/cheburprobe.init" "$PROBE_ROOT/data/etc/init.d/cheburprobe"
install -m 0600 "$ROOT_DIR/probe/openwrt/cheburprobe.config" "$PROBE_ROOT/data/etc/config/cheburprobe"
install -m 0755 "$ROOT_DIR/probe/openwrt/cheburprobe.postinst" "$PROBE_ROOT/control/postinst"
printf '/etc/config/cheburprobe\n' > "$PROBE_ROOT/control/conffiles"
build_ipk cheburprobe "$ARCH" "$PROBE_ROOT" "Description: Dynamic network probe daemon for Cheburcheck
Connects to Cheburcheck and performs network measurements from OpenWrt."
LUCI_ROOT="$WORK_DIR/luci-app-cheburprobe"
mkdir -p "$LUCI_ROOT/control" "$LUCI_ROOT/data/usr/share/luci/menu.d" \
"$LUCI_ROOT/data/usr/share/rpcd/acl.d" \
"$LUCI_ROOT/data/www/luci-static/resources/view/cheburprobe"
install -m 0644 "$ROOT_DIR/probe/openwrt/luci/menu.json" \
"$LUCI_ROOT/data/usr/share/luci/menu.d/luci-app-cheburprobe.json"
install -m 0644 "$ROOT_DIR/probe/openwrt/luci/acl.json" \
"$LUCI_ROOT/data/usr/share/rpcd/acl.d/luci-app-cheburprobe.json"
install -m 0644 "$ROOT_DIR/probe/openwrt/luci/config.js" \
"$LUCI_ROOT/data/www/luci-static/resources/view/cheburprobe/config.js"
build_ipk luci-app-cheburprobe all "$LUCI_ROOT" "Depends: cheburprobe, luci-base
Description: LuCI configuration interface for Cheburprobe"
+13
View File
@@ -0,0 +1,13 @@
config cheburprobe 'main'
option enabled '0'
option probe_id ''
option probe_token ''
option mqtt_host 'wss://cheburcheck.ru/mqtt'
option mqtt_port '443'
option connection_timeout '30'
option max_concurrent_tasks '8'
option traceroute_max_hops '5'
option traceroute_retries '3'
option traceroute_control_hosts '3'
option log_level 'info'
+49
View File
@@ -0,0 +1,49 @@
#!/bin/sh /etc/rc.common
START=95
STOP=10
USE_PROCD=1
start_service() {
config_load cheburprobe
config_get_bool enabled main enabled 0
[ "$enabled" -eq 1 ] || return 0
config_get probe_id main probe_id
config_get probe_token main probe_token
config_get mqtt_host main mqtt_host 'wss://cheburcheck.ru/mqtt'
config_get mqtt_port main mqtt_port '443'
config_get connection_timeout main connection_timeout '30'
config_get max_concurrent_tasks main max_concurrent_tasks '8'
config_get traceroute_max_hops main traceroute_max_hops '5'
config_get traceroute_retries main traceroute_retries '3'
config_get traceroute_control_hosts main traceroute_control_hosts '3'
config_get log_level main log_level 'info'
procd_open_instance
procd_set_param command /usr/bin/cheburprobe
procd_set_param respawn 3600 5 5
procd_set_param env \
PROBE_ID="$probe_id" \
PROBE_TOKEN="$probe_token" \
MQTT_HOST="$mqtt_host" \
MQTT_PORT="$mqtt_port" \
MQTT_CONNECTION_TIMEOUT_SECS="$connection_timeout" \
MAX_CONCURRENT_TASKS="$max_concurrent_tasks" \
TRACEROUTE_MAX_HOPS="$traceroute_max_hops" \
TRACEROUTE_RETRIES="$traceroute_retries" \
TRACEROUTE_CONTROL_HOSTS="$traceroute_control_hosts" \
RUST_LOG="$log_level"
procd_set_param stdout 1
procd_set_param stderr 1
procd_close_instance
}
service_triggers() {
procd_add_reload_trigger cheburprobe
}
reload_service() {
stop
start
}
+5
View File
@@ -0,0 +1,5 @@
#!/bin/sh
[ -n "${IPKG_INSTROOT:-}" ] || /etc/init.d/cheburprobe enable
exit 0
+8
View File
@@ -0,0 +1,8 @@
{
"luci-app-cheburprobe": {
"description": "Manage Cheburprobe configuration",
"read": { "uci": [ "cheburprobe" ] },
"write": { "uci": [ "cheburprobe" ] }
}
}
+69
View File
@@ -0,0 +1,69 @@
'use strict';
'require view';
'require form';
'require uci';
return view.extend({
load: function() {
return uci.load('cheburprobe');
},
render: function() {
var m, s, o;
m = new form.Map('cheburprobe', _('Cheburprobe'),
_('Configure the Cheburcheck dynamic network probe. Changes are applied to the service automatically.'));
s = m.section(form.NamedSection, 'main', 'cheburprobe', _('Service settings'));
s.addremove = false;
o = s.option(form.Flag, 'enabled', _('Enable service'));
o.rmempty = false;
o = s.option(form.Value, 'probe_id', _('Probe ID'));
o.datatype = 'uinteger';
o.rmempty = false;
o = s.option(form.Value, 'probe_token', _('Probe token'));
o.password = true;
o.rmempty = false;
o = s.option(form.Value, 'mqtt_host', _('MQTT WebSocket URL'));
o.default = 'wss://cheburcheck.ru/mqtt';
o.rmempty = false;
o = s.option(form.Value, 'mqtt_port', _('MQTT port'));
o.datatype = 'port';
o.default = '443';
o.rmempty = false;
o = s.option(form.Value, 'connection_timeout', _('Connection timeout'), _('Seconds'));
o.datatype = 'and(uinteger,min(1))';
o.default = '30';
o = s.option(form.Value, 'max_concurrent_tasks', _('Maximum concurrent tasks'));
o.datatype = 'and(uinteger,min(1))';
o.default = '8';
o = s.option(form.Value, 'traceroute_max_hops', _('Traceroute maximum hops'));
o.datatype = 'and(uinteger,min(1))';
o.default = '5';
o = s.option(form.Value, 'traceroute_retries', _('Traceroute retries'));
o.datatype = 'and(uinteger,min(1))';
o.default = '3';
o = s.option(form.Value, 'traceroute_control_hosts', _('Traceroute control hosts'));
o.datatype = 'and(uinteger,min(1))';
o.default = '3';
o = s.option(form.ListValue, 'log_level', _('Log level'));
o.value('error', _('Error'));
o.value('warn', _('Warning'));
o.value('info', _('Info'));
o.value('debug', _('Debug'));
o.value('trace', _('Trace'));
o.default = 'info';
return m.render();
}
});
+9
View File
@@ -0,0 +1,9 @@
{
"admin/services/cheburprobe": {
"title": "Cheburprobe",
"order": 90,
"action": { "type": "view", "path": "cheburprobe/config" },
"depends": { "acl": [ "luci-app-cheburprobe" ] }
}
}