Scaffold overlay для преднастроенного RustDesk-клиента
Тонкая обвязка поверх rustdesk@1.4.9: preconfigure.sh патчит RENDEZVOUS_SERVERS+RS_PUB_KEY в hbb_common, build-windows.ps1 — локальный оркестратор сборки. Значения сервера/ключа не в репо (config/server.env в .gitignore, в CI — gitea secrets). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+10
@@ -0,0 +1,10 @@
|
|||||||
|
# Реальные значения сервера/ключа — никогда не коммитим (публичный репо)
|
||||||
|
config/server.env
|
||||||
|
|
||||||
|
# Клон апстрима и артефакты сборки
|
||||||
|
/rustdesk/
|
||||||
|
/build/
|
||||||
|
/dist/
|
||||||
|
*.exe
|
||||||
|
*.apk
|
||||||
|
*.zip
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
# rustdesk-custom
|
||||||
|
|
||||||
|
Тонкий overlay поверх [RustDesk](https://github.com/rustdesk/rustdesk): собирает **преднастроенный**
|
||||||
|
клиент RustDesk, из коробки указывающий на свой self-hosted сервер (hbbs/hbbr). Сам код RustDesk сюда
|
||||||
|
не форкается — апстрейт клонируется в CI по пину и патчится минимальным скриптом.
|
||||||
|
|
||||||
|
## Как это работает
|
||||||
|
|
||||||
|
RustDesk в 1.4.9 хранит адрес сервера и публичный ключ как **хардкод-константы** в сабмодуле `hbb_common`
|
||||||
|
(`RENDEZVOUS_SERVERS`, `RS_PUB_KEY` в `libs/hbb_common/src/config.rs`). Старого механизма `option_env!`
|
||||||
|
в актуальном master нет. Поэтому преднастройка = патч этих двух констант перед сборкой
|
||||||
|
([`scripts/preconfigure.sh`](scripts/preconfigure.sh)).
|
||||||
|
|
||||||
|
Значения (адрес сервера, ключ) **не хранятся в этом публичном репозитории**:
|
||||||
|
- локально — в `config/server.env` (в `.gitignore`);
|
||||||
|
- в CI — в gitea Actions secrets.
|
||||||
|
|
||||||
|
## Быстрый старт (локально, Windows)
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
copy config\server.env.example config\server.env # заполнить RUSTDESK_SERVER / RUSTDESK_PUB_KEY
|
||||||
|
pwsh -File scripts\build-windows.ps1
|
||||||
|
```
|
||||||
|
|
||||||
|
Тулчейн (Rust 1.75, LLVM 15.0.6, Flutter 3.24.5, vcpkg@пин) нужно поднять один раз — см.
|
||||||
|
[docs/CODEMAP.md](docs/CODEMAP.md). Первая сборка долгая: vcpkg компилит ffmpeg/aom из исходников.
|
||||||
|
|
||||||
|
## Пины
|
||||||
|
|
||||||
|
Все версии зафиксированы в [`upstream.txt`](upstream.txt) (правило проекта: никаких `latest`).
|
||||||
|
Обновление RustDesk = поднять `RUSTDESK_TAG` и сверить остальные пины с новым `flutter-build.yml` апстрима.
|
||||||
|
|
||||||
|
## Платформы
|
||||||
|
|
||||||
|
- **Windows** — локально на GUSIK-PC + CI-раннер `windows:host`.
|
||||||
|
- **Android** — CI на build-VM 118 (NDK r28c, cargo-ndk 3.1.2), раздача APK как в GusVoice
|
||||||
|
(gitea release + self-hosted F-Droid).
|
||||||
|
|
||||||
|
## Лицензия
|
||||||
|
|
||||||
|
RustDesk распространяется под AGPL-3.0. Собранные этим overlay бинарники — производная работа RustDesk
|
||||||
|
и подчиняются AGPL-3.0. Скрипты этого репозитория — тонкая обвязка сборки.
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
# Скопируй в config/server.env (он в .gitignore, в репозиторий НЕ попадает) и заполни.
|
||||||
|
# В CI эти же значения задаются как gitea Actions secrets — в код/публичный репо не коммитим.
|
||||||
|
|
||||||
|
# Хост(ы) твоего hbbs. Порт по умолчанию 21116. Нестандартный: host:port.
|
||||||
|
# Несколько серверов — через запятую.
|
||||||
|
RUSTDESK_SERVER=rustdesk.example.home
|
||||||
|
|
||||||
|
# Публичный ключ сервера — содержимое id_ed25519.pub рядом с hbbs (base64).
|
||||||
|
# Технически не секрет (клиенты его и так получают), но в публичный репо не кладём.
|
||||||
|
RUSTDESK_PUB_KEY=PASTE_BASE64_PUBLIC_KEY_HERE
|
||||||
|
|
||||||
|
# Опционально: URL API-сервера (только RustDesk Server Pro). Для обычного hbbs/hbbr оставь пустым.
|
||||||
|
RUSTDESK_API_SERVER=
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
# CODEMAP — rustdesk-custom
|
||||||
|
|
||||||
|
Карта overlay-репозитория для преднастроенной сборки RustDesk. Держать актуальной при каждом изменении.
|
||||||
|
|
||||||
|
## Структура
|
||||||
|
|
||||||
|
| Путь | Назначение |
|
||||||
|
|------|-----------|
|
||||||
|
| `upstream.txt` | Пины: `RUSTDESK_TAG`, версии Rust/LLVM/Flutter, `VCPKG_COMMIT_ID`, `VCPKG_TRIPLET`, Android-пины. Единственный источник версий. |
|
||||||
|
| `scripts/preconfigure.sh` | Патчит `RENDEZVOUS_SERVERS` и `RS_PUB_KEY` в `hbb_common/src/config.rs` клона. Значения из env. Проверяет, что патч применился. |
|
||||||
|
| `scripts/build-windows.ps1` | Оркестратор локальной Windows-сборки: load env → клон@пин → preconfigure → `python build.py --flutter` → `dist/`. Есть preflight тулчейна. |
|
||||||
|
| `config/server.env.example` | Шаблон значений. Реальный `config/server.env` — в `.gitignore`. |
|
||||||
|
| `.gitea/workflows/` | CI: `build-windows.yaml` (раннер `windows:host`), `build-android.yaml` (VM 118). *(в работе)* |
|
||||||
|
| `rustdesk/` | Клон апстрима (gitignored, создаётся сборкой). |
|
||||||
|
| `dist/` | Готовые артефакты (gitignored). |
|
||||||
|
|
||||||
|
## Механизм преднастройки (важно)
|
||||||
|
|
||||||
|
RustDesk 1.4.9, `libs/hbb_common/src/config.rs` (сабмодуль `rustdesk/hbb_common`, пин `7e1c392`):
|
||||||
|
```rust
|
||||||
|
pub const RENDEZVOUS_SERVERS: &[&str] = &["rs-ny.rustdesk.com"];
|
||||||
|
pub const RS_PUB_KEY: &str = "OeVuKk5nlHiXp+APNn0Y3pC1Iwpwn44JGqrQCsWqmBw=";
|
||||||
|
```
|
||||||
|
- `option_env!(RENDEZVOUS_SERVER/RS_PUB_KEY)` из старого PR #2810 **в master вырезан** — только патч констант.
|
||||||
|
- Порт hbbs по умолчанию 21116 (не указывать, если стандартный). Нестандартный — `host:port`.
|
||||||
|
- API-сервер (только RustDesk Server Pro) отдельной const в 1.4.9 не имеет; для обычного hbbs/hbbr не нужен.
|
||||||
|
- Альтернатива без сборки (на будущее): переименовать официальный бинарь в
|
||||||
|
`rustdesk-host=<server>,key=<pubkey>.exe` — конфиг читается из имени файла (`EXE_RENDEZVOUS_SERVER`).
|
||||||
|
|
||||||
|
## Windows toolchain (поднять один раз на GUSIK-PC)
|
||||||
|
|
||||||
|
Версии — из `upstream.txt` (пины из `flutter-build.yml@1.4.9`):
|
||||||
|
- **Rust 1.75** — `rustup toolchain install 1.75`; в дереве клона `rustup override set 1.75`
|
||||||
|
(апстрим держит 1.75 из-за i128 ABI-изменения в 1.78+).
|
||||||
|
- **LLVM 15.0.6** — для bindgen; задать `LIBCLANG_PATH` на `bin` LLVM.
|
||||||
|
- **Flutter 3.24.5** (канал stable) в PATH. Апстрим применяет патч
|
||||||
|
`.github/patches/flutter_3.24.4_dropdown_menu_enableFilter.diff` к SDK — при ошибке сборки применить.
|
||||||
|
- **vcpkg@120deac3** — склонировать, `bootstrap-vcpkg`, задать `VCPKG_ROOT`. Триплет `x64-windows-static`.
|
||||||
|
Зависимости из `vcpkg.json`: aom, libvpx, libyuv, opus, libjpeg-turbo, mfx-dispatch,
|
||||||
|
**ffmpeg** (static, features amf/nvcodec/qsv — hwcodec). ffmpeg/aom — длинная первая компиляция.
|
||||||
|
- Сборка: `python build.py --flutter` (флаги: `--hwcodec`, `--portable`, `--vram`, `--skip-cargo`).
|
||||||
|
|
||||||
|
### Открытый вопрос (решить при первой сборке)
|
||||||
|
Апстрим для Windows-x64 подменяет flutter-engine кастомным `windows-x64-release.zip` (ради Win7).
|
||||||
|
Для таргета Win10/11, вероятно, можно оставить стоковый engine 3.24.5 и пропустить подмену — проверить,
|
||||||
|
не падает ли `flutter build windows` без неё.
|
||||||
|
|
||||||
|
## Android toolchain (VM 118, позже)
|
||||||
|
Flutter 3.24.5, NDK r28c, cargo-ndk 3.1.2, Rust android-таргеты, vcpkg android-триплеты
|
||||||
|
(oboe, cpu-features, ffmpeg host=false). Публикация APK: gitea release + F-Droid (шаблон GusVoice).
|
||||||
|
|
||||||
|
## Секреты в CI (gitea Actions)
|
||||||
|
`RUSTDESK_SERVER`, `RUSTDESK_PUB_KEY`, (опц.) `RUSTDESK_API_SERVER`. Префикс имён — не `GITHUB_`/`GITEA_`
|
||||||
|
(зарезервированы), при необходимости `GT_`.
|
||||||
@@ -0,0 +1,95 @@
|
|||||||
|
<#
|
||||||
|
Локальная сборка преднастроенного RustDesk-клиента под Windows (GUSIK-PC).
|
||||||
|
Делает: клон rustdesk@пин -> preconfigure (вшить сервер+ключ) -> python build.py --flutter -> dist/.
|
||||||
|
Тулчейн (Rust 1.75 / LLVM 15 / Flutter 3.24.5 / vcpkg@пин) должен быть уже поднят —
|
||||||
|
скрипт делает preflight-проверку и подсказывает, чего не хватает.
|
||||||
|
|
||||||
|
Запуск: pwsh -File scripts\build-windows.ps1
|
||||||
|
Опции: -Clean (снести клон и склонировать заново)
|
||||||
|
#>
|
||||||
|
[CmdletBinding()]
|
||||||
|
param(
|
||||||
|
[switch]$Clean,
|
||||||
|
[switch]$SkipBuild # только клон+preconfigure, без компиляции (для отладки)
|
||||||
|
)
|
||||||
|
$ErrorActionPreference = 'Stop'
|
||||||
|
$root = Split-Path -Parent $PSScriptRoot # корень overlay-репо
|
||||||
|
$src = Join-Path $root 'rustdesk' # клон апстрима
|
||||||
|
$dist = Join-Path $root 'dist'
|
||||||
|
|
||||||
|
# --- читаем пины ---
|
||||||
|
$pins = @{}
|
||||||
|
Get-Content (Join-Path $root 'upstream.txt') | Where-Object { $_ -match '^\s*[A-Z]' } | ForEach-Object {
|
||||||
|
$k,$v = $_ -split '=',2; $pins[$k.Trim()] = $v.Trim()
|
||||||
|
}
|
||||||
|
$TAG = $pins['RUSTDESK_TAG']
|
||||||
|
$REPO = $pins['RUSTDESK_REPO']
|
||||||
|
Write-Host "== RustDesk custom build == tag=$TAG" -ForegroundColor Cyan
|
||||||
|
|
||||||
|
# --- загрузка config/server.env ---
|
||||||
|
$envFile = Join-Path $root 'config\server.env'
|
||||||
|
if (-not (Test-Path $envFile)) {
|
||||||
|
throw "Нет $envFile. Скопируй config\server.env.example -> config\server.env и заполни RUSTDESK_SERVER/RUSTDESK_PUB_KEY."
|
||||||
|
}
|
||||||
|
Get-Content $envFile | Where-Object { $_ -match '^\s*[A-Z].*=' } | ForEach-Object {
|
||||||
|
$k,$v = $_ -split '=',2
|
||||||
|
Set-Item -Path "Env:$($k.Trim())" -Value $v.Trim()
|
||||||
|
}
|
||||||
|
if (-not $env:RUSTDESK_SERVER -or -not $env:RUSTDESK_PUB_KEY) {
|
||||||
|
throw "В config\server.env не заданы RUSTDESK_SERVER и/или RUSTDESK_PUB_KEY."
|
||||||
|
}
|
||||||
|
|
||||||
|
# --- preflight тулчейна ---
|
||||||
|
function Need($name, $test, $hint) {
|
||||||
|
if (-not (& $test)) { Write-Host " [нет] $name — $hint" -ForegroundColor Yellow; return $false }
|
||||||
|
Write-Host " [ok] $name" -ForegroundColor Green; return $true
|
||||||
|
}
|
||||||
|
Write-Host "Preflight тулчейна:" -ForegroundColor Cyan
|
||||||
|
$ok = $true
|
||||||
|
$ok = (Need 'git' { Get-Command git -EA SilentlyContinue } 'установи Git for Windows') -and $ok
|
||||||
|
$ok = (Need 'bash' { Get-Command bash -EA SilentlyContinue } 'нужен git-bash для preconfigure.sh') -and $ok
|
||||||
|
$ok = (Need 'python' { Get-Command python -EA SilentlyContinue } 'нужен Python 3 для build.py') -and $ok
|
||||||
|
$ok = (Need 'rustup' { Get-Command rustup -EA SilentlyContinue } 'установи rustup') -and $ok
|
||||||
|
$ok = (Need 'flutter' { Get-Command flutter -EA SilentlyContinue } "Flutter $($pins['FLUTTER_VERSION']) stable в PATH") -and $ok
|
||||||
|
$ok = (Need 'vcpkg' { $env:VCPKG_ROOT -and (Test-Path (Join-Path $env:VCPKG_ROOT 'vcpkg.exe')) } "склонируй vcpkg@$($pins['VCPKG_COMMIT_ID']), задай VCPKG_ROOT") -and $ok
|
||||||
|
$ok = (Need 'LLVM' { $env:LIBCLANG_PATH -and (Test-Path $env:LIBCLANG_PATH) } "LLVM $($pins['LLVM_VERSION']), задай LIBCLANG_PATH") -and $ok
|
||||||
|
if (-not $ok) { throw "Тулчейн неполный — см. docs\CODEMAP.md (раздел 'Windows toolchain')." }
|
||||||
|
|
||||||
|
# --- клон / обновление до пина ---
|
||||||
|
if ($Clean -and (Test-Path $src)) { Remove-Item -Recurse -Force $src }
|
||||||
|
if (-not (Test-Path $src)) {
|
||||||
|
Write-Host "Клонирую rustdesk@$TAG ..." -ForegroundColor Cyan
|
||||||
|
git clone --branch $TAG --depth 1 --recurse-submodules --shallow-submodules $REPO $src
|
||||||
|
} else {
|
||||||
|
Write-Host "Клон уже есть — сбрасываю патчи до чистого $TAG ..." -ForegroundColor Cyan
|
||||||
|
git -C $src checkout -- .
|
||||||
|
git -C $src submodule foreach --recursive 'git checkout -- .'
|
||||||
|
}
|
||||||
|
|
||||||
|
# зафиксировать Rust 1.75 для этого дерева
|
||||||
|
Push-Location $src
|
||||||
|
rustup override set $pins['RUST_VERSION'] | Out-Null
|
||||||
|
Pop-Location
|
||||||
|
|
||||||
|
# --- preconfigure: вшить сервер+ключ ---
|
||||||
|
Write-Host "Preconfigure (вшиваю сервер+ключ)..." -ForegroundColor Cyan
|
||||||
|
bash "$root/scripts/preconfigure.sh" "$src"
|
||||||
|
|
||||||
|
if ($SkipBuild) { Write-Host "SkipBuild — остановился после preconfigure." -ForegroundColor Yellow; return }
|
||||||
|
|
||||||
|
# --- сборка ---
|
||||||
|
Write-Host "Сборка: python build.py --flutter (первый раз долго: vcpkg ffmpeg/aom)..." -ForegroundColor Cyan
|
||||||
|
Push-Location $src
|
||||||
|
python build.py --flutter
|
||||||
|
Pop-Location
|
||||||
|
|
||||||
|
# --- собрать артефакт ---
|
||||||
|
New-Item -ItemType Directory -Force $dist | Out-Null
|
||||||
|
$exe = Get-ChildItem -Path $src -Recurse -Filter 'rustdesk*.exe' -EA SilentlyContinue |
|
||||||
|
Where-Object { $_.FullName -match 'Release|portable' } | Select-Object -First 1
|
||||||
|
if ($exe) {
|
||||||
|
Copy-Item $exe.FullName (Join-Path $dist $exe.Name) -Force
|
||||||
|
Write-Host "Готово: $(Join-Path $dist $exe.Name)" -ForegroundColor Green
|
||||||
|
} else {
|
||||||
|
Write-Host "Сборка завершилась, но .exe не найден автоматически — глянь $src\build и $src\flutter\build." -ForegroundColor Yellow
|
||||||
|
}
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Вшивает адрес сервера и публичный ключ в клон RustDesk перед сборкой.
|
||||||
|
# Патчит две константы в сабмодуле hbb_common:
|
||||||
|
# pub const RENDEZVOUS_SERVERS: &[&str] = &["rs-ny.rustdesk.com"];
|
||||||
|
# pub const RS_PUB_KEY: &str = "OeVu...";
|
||||||
|
#
|
||||||
|
# Значения берутся из окружения (см. config/server.env.example):
|
||||||
|
# RUSTDESK_SERVER — хост(ы) hbbs. Несколько — через запятую. Порт по умолчанию 21116,
|
||||||
|
# нестандартный указывать как host:port.
|
||||||
|
# RUSTDESK_PUB_KEY — публичный ключ сервера (содержимое id_ed25519.pub, base64).
|
||||||
|
# RUSTDESK_API_SERVER — (опц.) URL API-сервера (RustDesk Server Pro). Пусто — пропустить.
|
||||||
|
#
|
||||||
|
# Использование: RUSTDESK_SERVER=... RUSTDESK_PUB_KEY=... ./scripts/preconfigure.sh <путь-к-клону-rustdesk>
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SRC="${1:?укажи путь к клону rustdesk первым аргументом}"
|
||||||
|
CFG="$SRC/libs/hbb_common/src/config.rs"
|
||||||
|
|
||||||
|
[ -f "$CFG" ] || { echo "ОШИБКА: не найден $CFG — сабмодуль hbb_common не инициализирован?" >&2; exit 1; }
|
||||||
|
: "${RUSTDESK_SERVER:?не задан RUSTDESK_SERVER}"
|
||||||
|
: "${RUSTDESK_PUB_KEY:?не задан RUSTDESK_PUB_KEY}"
|
||||||
|
|
||||||
|
# Собираем Rust-массив &["a", "b"] из запятой-разделённого списка серверов.
|
||||||
|
IFS=',' read -ra SRV <<< "$RUSTDESK_SERVER"
|
||||||
|
ARR=""
|
||||||
|
for s in "${SRV[@]}"; do
|
||||||
|
s="$(echo -n "$s" | tr -d '[:space:]')"
|
||||||
|
[ -n "$s" ] && ARR="${ARR}\"${s}\", "
|
||||||
|
done
|
||||||
|
ARR="&[${ARR%, }]"
|
||||||
|
|
||||||
|
# Экранируем спецсимволы sed-замены (& | \) в подставляемых значениях.
|
||||||
|
esc() { printf '%s' "$1" | sed -e 's/[\\&|]/\\&/g'; }
|
||||||
|
ARR_ESC="$(esc "$ARR")"
|
||||||
|
KEY_ESC="$(esc "$RUSTDESK_PUB_KEY")"
|
||||||
|
|
||||||
|
# Патч RENDEZVOUS_SERVERS
|
||||||
|
sed -i -E "s|^pub const RENDEZVOUS_SERVERS: &\[&str\] = .*;|pub const RENDEZVOUS_SERVERS: \&[\&str] = ${ARR_ESC};|" "$CFG"
|
||||||
|
# Патч RS_PUB_KEY
|
||||||
|
sed -i -E "s|^pub const RS_PUB_KEY: &str = .*;|pub const RS_PUB_KEY: \&str = \"${KEY_ESC}\";|" "$CFG"
|
||||||
|
|
||||||
|
# Проверяем, что патч применился (значения не печатаем целиком — только факт).
|
||||||
|
grep -q "^pub const RENDEZVOUS_SERVERS: &\[&str\] = &\[\"" "$CFG" || { echo "ОШИБКА: не удалось пропатчить RENDEZVOUS_SERVERS" >&2; exit 1; }
|
||||||
|
if grep -q "OeVuKk5nlHiXp" "$CFG"; then
|
||||||
|
echo "ОШИБКА: RS_PUB_KEY остался дефолтным RustDesk" >&2; exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "[preconfigure] RENDEZVOUS_SERVERS -> ${#SRV[@]} сервер(ов), RS_PUB_KEY вшит."
|
||||||
|
|
||||||
|
# Опциональный API-сервер (RustDesk Server Pro). По умолчанию у hbbs/hbbr его нет.
|
||||||
|
if [ -n "${RUSTDESK_API_SERVER:-}" ]; then
|
||||||
|
# В 1.4.9 отдельной const API_SERVER нет; дефолт задаётся через overrideConfig/filename.
|
||||||
|
# Оставляем маркер для ручной доработки, если понадобится Pro-API.
|
||||||
|
echo "[preconfigure] RUSTDESK_API_SERVER задан ($RUSTDESK_API_SERVER) — вшивание API требует доп. патча (см. docs/CODEMAP.md)."
|
||||||
|
fi
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
# Пины апстрима RustDesk и тулчейна (правило: никаких latest).
|
||||||
|
# Значения взяты из rustdesk/rustdesk@1.4.9 .github/workflows/flutter-build.yml.
|
||||||
|
# Обновление апстрима = поднять RUSTDESK_TAG и сверить остальные пины с новым flutter-build.yml.
|
||||||
|
|
||||||
|
RUSTDESK_TAG=1.4.9
|
||||||
|
RUSTDESK_REPO=https://github.com/rustdesk/rustdesk.git
|
||||||
|
|
||||||
|
# Тулчейн (Windows x64 flutter-сборка)
|
||||||
|
RUST_VERSION=1.75
|
||||||
|
LLVM_VERSION=15.0.6
|
||||||
|
FLUTTER_VERSION=3.24.5
|
||||||
|
VCPKG_COMMIT_ID=120deac3062162151622ca4860575a33844ba10b
|
||||||
|
VCPKG_TRIPLET=x64-windows-static
|
||||||
|
|
||||||
|
# Android (VM 118)
|
||||||
|
ANDROID_FLUTTER_VERSION=3.24.5
|
||||||
|
CARGO_NDK_VERSION=3.1.2
|
||||||
|
NDK_VERSION=r28c
|
||||||
Reference in New Issue
Block a user