mirror of
https://github.com/LowderPlay/cheburcheck.git
synced 2026-09-22 22:37:59 +03:00
feat: openwrt packages (#82)
This commit is contained in:
@@ -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
@@ -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`.
|
||||
|
||||
@@ -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"
|
||||
@@ -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"
|
||||
@@ -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'
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
#!/bin/sh
|
||||
|
||||
[ -n "${IPKG_INSTROOT:-}" ] || /etc/init.d/cheburprobe enable
|
||||
exit 0
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"luci-app-cheburprobe": {
|
||||
"description": "Manage Cheburprobe configuration",
|
||||
"read": { "uci": [ "cheburprobe" ] },
|
||||
"write": { "uci": [ "cheburprobe" ] }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"admin/services/cheburprobe": {
|
||||
"title": "Cheburprobe",
|
||||
"order": 90,
|
||||
"action": { "type": "view", "path": "cheburprobe/config" },
|
||||
"depends": { "acl": [ "luci-app-cheburprobe" ] }
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user