Initial commit: AnyDesk installer for Raspberry Pi
This commit is contained in:
@@ -0,0 +1,4 @@
|
|||||||
|
# Build artefacts — fetched by build.sh, never committed
|
||||||
|
src/anydesk_arm64.deb
|
||||||
|
packages/
|
||||||
|
*.pkg
|
||||||
@@ -0,0 +1,108 @@
|
|||||||
|
# insin_anydesk
|
||||||
|
|
||||||
|
Insin package that installs [AnyDesk](https://anydesk.com) on Raspberry Pi devices
|
||||||
|
(arm64) managed by a self-hosted Insin server.
|
||||||
|
|
||||||
|
The package is published to the Insin server and assigned to the `raspberry pi`
|
||||||
|
device group in the admin panel. Each device's `insin monitor` picks it up on
|
||||||
|
its next heartbeat, extracts the pkg, and runs `postinst` as root.
|
||||||
|
|
||||||
|
## Package structure
|
||||||
|
|
||||||
|
```
|
||||||
|
insin_anydesk/
|
||||||
|
├── build.sh # CI script: pull deb + CLI, pack, publish
|
||||||
|
├── src/ # pkg contents — `cd src && insin pack anydesk@<ver>`
|
||||||
|
│ ├── postinst # apt-installs bundled .deb, enables systemd unit
|
||||||
|
│ ├── prem # stops + apt-removes anydesk on pkg removal
|
||||||
|
│ ├── install.cfg # install_path=/opt/insin/anydesk
|
||||||
|
│ └── anydesk_arm64.deb # bundled at build time by build.sh (gitignored)
|
||||||
|
└── packages/ # `insin pack` output (gitignored)
|
||||||
|
```
|
||||||
|
|
||||||
|
Recognised files in the ZIP (per Insin's package manager):
|
||||||
|
|
||||||
|
| File | Role |
|
||||||
|
|---------------|-------------------------------------------------------------------|
|
||||||
|
| `postinst` | Bash script run as root after extraction. New installs and version bumps trigger it; same-version reassignments are skipped. |
|
||||||
|
| `prem` | Bash script run before removal, or before overlaying a new version on top of an existing install. |
|
||||||
|
| `install.cfg` | `key=value` overrides. Supported keys: `install_path`, `run_postinst`, `run_prem`. |
|
||||||
|
|
||||||
|
Everything else in the ZIP (the `.deb`) is copied verbatim into the install
|
||||||
|
directory (`install_path`) alongside the scripts, so `postinst` can reference it
|
||||||
|
as `./anydesk_arm64.deb`.
|
||||||
|
|
||||||
|
### Metadata
|
||||||
|
|
||||||
|
There is no manifest inside the pkg — Insin derives `name` and `version` from
|
||||||
|
the `name@version.pkg` filename. The version must parse as `MAJOR.MINOR.PATCH`
|
||||||
|
(`Version.Parse`). The pkg version tracks the upstream AnyDesk version:
|
||||||
|
`anydesk@6.4.0` bundles the AnyDesk 6.4.0-1 arm64 `.deb`.
|
||||||
|
|
||||||
|
Republishing the same version is rejected server-side with 409. To force a
|
||||||
|
retry after a failed install, bump the version.
|
||||||
|
|
||||||
|
## Environment variables
|
||||||
|
|
||||||
|
| Var | Where | Purpose |
|
||||||
|
|-----------------|-----------|----------------------------------------------------------------------------------|
|
||||||
|
| `INSIN_URL` | build | Base URL of the Insin server (no trailing slash, no `/api`). |
|
||||||
|
| `INSIN_TOKEN` | build | Service token minted in the Insin admin panel (Service Tokens → New token). |
|
||||||
|
| `GIT_URL` | repo host | Full clone URL of this repo on Gitea (already set globally). |
|
||||||
|
| `GIT_USER` | repo host | Gitea username for push/pull (already set globally). |
|
||||||
|
| `GIT_KEY` | repo host | Gitea personal access token (already set globally). |
|
||||||
|
| `ANYDESK_VERSION` | build (optional) | Full deb tag (e.g. `6.4.0-1`). Default: `6.4.0-1`. |
|
||||||
|
| `PKG_VERSION` | build (optional) | Insin pkg semver. Default: `ANYDESK_VERSION` with the `-N` suffix stripped. |
|
||||||
|
| `INSIN_CLI_RID` | build (optional) | Override CLI artifact rid. Default: derived from `uname -m`; only `linux-arm64` is currently published, so the runner must be arm64. |
|
||||||
|
|
||||||
|
Never echo `INSIN_TOKEN`, `GIT_KEY`, or `GIT_USER` to logs. `build.sh` pipes
|
||||||
|
CLI stderr through a sed redactor as a safety net.
|
||||||
|
|
||||||
|
## Build & publish
|
||||||
|
|
||||||
|
```sh
|
||||||
|
./build.sh
|
||||||
|
# or override the anydesk version
|
||||||
|
ANYDESK_VERSION=6.4.1-1 PKG_VERSION=6.4.1 ./build.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
`build.sh`:
|
||||||
|
|
||||||
|
1. Downloads `anydesk_${ANYDESK_VERSION}_arm64.deb` from
|
||||||
|
`download.anydesk.com/rpi/` into `src/`.
|
||||||
|
2. Fetches the latest `insin` CLI (`linux-arm64`) from
|
||||||
|
`$INSIN_URL/api/v1/downloads/cli` into `/tmp/insin/`.
|
||||||
|
3. `cd src && insin pack anydesk@${PKG_VERSION}` →
|
||||||
|
`packages/anydesk@${PKG_VERSION}.pkg`.
|
||||||
|
4. `insin publish packages/anydesk@${PKG_VERSION}.pkg`.
|
||||||
|
|
||||||
|
## Rolling out
|
||||||
|
|
||||||
|
Publishing puts the pkg on the server. It does **not** assign it to any
|
||||||
|
device. After publish:
|
||||||
|
|
||||||
|
- Admin panel → **Groups → raspberry pi → Assignments** → add
|
||||||
|
`anydesk@<version>`, OR
|
||||||
|
- `PUT $INSIN_URL/api/v1/admin/groups/<piGroupId>/assignments` with
|
||||||
|
`Authorization: AdminToken $INSIN_TOKEN` and body
|
||||||
|
`{ "packageName": "anydesk", "version": "<version>" }`.
|
||||||
|
|
||||||
|
Each Pi picks up the assignment on its next heartbeat (default 10 min) and
|
||||||
|
runs `postinst`.
|
||||||
|
|
||||||
|
## On-device runtime
|
||||||
|
|
||||||
|
- `postinst` and `prem` run under `/bin/bash -c "./<script>"` as a single
|
||||||
|
subshell — one shell invocation, not line-by-line. `set -euxo pipefail` is
|
||||||
|
set at the top so failures surface loudly in the `insin monitor` journal.
|
||||||
|
- Exit codes are **logged but ignored** by the agent. A failed `postinst`
|
||||||
|
still marks the package as installed. To force a retry, bump the version.
|
||||||
|
- On upgrade, old files are **not** wiped before the new pkg is overlaid —
|
||||||
|
stale files in `install_path` persist unless `prem` cleans them.
|
||||||
|
Irrelevant for AnyDesk itself (the deb owns `/opt`, `/etc`, `/usr`), but
|
||||||
|
worth remembering if the pkg starts carrying additional state.
|
||||||
|
|
||||||
|
## References
|
||||||
|
|
||||||
|
- Insin publishing skill: `~/.claude/skills/publishing-packages-to-insin/`.
|
||||||
|
- AnyDesk RPi downloads: <https://anydesk.com/en/downloads/raspberry-pi>.
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Build & publish the insin anydesk package.
|
||||||
|
#
|
||||||
|
# Required env:
|
||||||
|
# INSIN_URL - e.g. https://insin.example.com
|
||||||
|
# INSIN_TOKEN - service token from the Insin admin panel
|
||||||
|
#
|
||||||
|
# Optional env:
|
||||||
|
# ANYDESK_VERSION - full deb version tag (default: 6.4.0-1)
|
||||||
|
# PKG_VERSION - insin package semver (default: derived from ANYDESK_VERSION)
|
||||||
|
# INSIN_CLI_RID - CLI artifact rid (default: auto-detected from uname -m)
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
: "${INSIN_URL:?INSIN_URL must be set}"
|
||||||
|
: "${INSIN_TOKEN:?INSIN_TOKEN must be set}"
|
||||||
|
|
||||||
|
ANYDESK_VERSION="${ANYDESK_VERSION:-6.4.0-1}"
|
||||||
|
PKG_VERSION="${PKG_VERSION:-${ANYDESK_VERSION%-*}}"
|
||||||
|
|
||||||
|
case "${INSIN_CLI_RID:-$(uname -m)}" in
|
||||||
|
linux-arm64|aarch64|arm64) RID="linux-arm64" ;;
|
||||||
|
linux-x64|x86_64|amd64)
|
||||||
|
echo "ERROR: no linux-x64 insin CLI artifact — run on an arm64 runner" >&2
|
||||||
|
exit 1 ;;
|
||||||
|
*) RID="${INSIN_CLI_RID:-linux-arm64}" ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
HERE="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
SRC="$HERE/src"
|
||||||
|
|
||||||
|
redact() { sed -E "s|${INSIN_TOKEN}|***|g"; }
|
||||||
|
|
||||||
|
echo "==> Downloading AnyDesk ${ANYDESK_VERSION} arm64 .deb"
|
||||||
|
curl -fsSL "https://download.anydesk.com/rpi/anydesk_${ANYDESK_VERSION}_arm64.deb" \
|
||||||
|
-o "$SRC/anydesk_arm64.deb"
|
||||||
|
|
||||||
|
echo "==> Fetching latest insin CLI ($RID)"
|
||||||
|
CLI_META="$(curl -fsSL "$INSIN_URL/api/v1/downloads/cli" 2>&1 | redact)"
|
||||||
|
read -r CLI_VERSION CLI_FILE < <(python3 -c '
|
||||||
|
import json, sys
|
||||||
|
m = json.loads(sys.argv[1])[0]
|
||||||
|
a = next(x for x in m["artifacts"] if x["rid"] == sys.argv[2])
|
||||||
|
print(m["version"], a["filename"])
|
||||||
|
' "$CLI_META" "$RID")
|
||||||
|
|
||||||
|
mkdir -p /tmp/insin
|
||||||
|
curl -fsSL "$INSIN_URL/api/v1/downloads/cli/$CLI_VERSION/$CLI_FILE" \
|
||||||
|
-o /tmp/insin.tar.gz 2>&1 | redact
|
||||||
|
tar -xzf /tmp/insin.tar.gz -C /tmp/insin
|
||||||
|
chmod +x /tmp/insin/insin
|
||||||
|
|
||||||
|
echo "==> Packing anydesk@${PKG_VERSION}"
|
||||||
|
( cd "$SRC" && /tmp/insin/insin pack "anydesk@${PKG_VERSION}" )
|
||||||
|
|
||||||
|
PKG="$HERE/packages/anydesk@${PKG_VERSION}.pkg"
|
||||||
|
[[ -f "$PKG" ]] || { echo "ERROR: expected $PKG but it wasn't produced" >&2; exit 1; }
|
||||||
|
|
||||||
|
echo "==> Publishing $PKG"
|
||||||
|
/tmp/insin/insin publish "$PKG" 2>&1 | redact
|
||||||
|
|
||||||
|
echo "==> Done: anydesk@${PKG_VERSION} published"
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
install_path=/opt/insin/anydesk
|
||||||
|
run_postinst=true
|
||||||
|
run_prem=true
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -euxo pipefail
|
||||||
|
|
||||||
|
DEB="anydesk_arm64.deb"
|
||||||
|
|
||||||
|
if [[ ! -f "$DEB" ]]; then
|
||||||
|
echo "postinst: bundled $DEB not found in $(pwd)" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ $EUID -ne 0 ]]; then
|
||||||
|
echo "postinst: must run as root (uid=$EUID)" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
export DEBIAN_FRONTEND=noninteractive
|
||||||
|
apt-get update
|
||||||
|
apt-get install -y --no-install-recommends "./$DEB"
|
||||||
|
|
||||||
|
systemctl enable --now anydesk
|
||||||
|
|
||||||
|
anydesk --version || true
|
||||||
|
|
||||||
|
echo "postinst: anydesk installed"
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -euxo pipefail
|
||||||
|
|
||||||
|
if [[ $EUID -ne 0 ]]; then
|
||||||
|
echo "prem: must run as root (uid=$EUID)" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
export DEBIAN_FRONTEND=noninteractive
|
||||||
|
systemctl disable --now anydesk 2>/dev/null || true
|
||||||
|
apt-get remove -y anydesk 2>/dev/null || true
|
||||||
|
|
||||||
|
echo "prem: anydesk removed"
|
||||||
Reference in New Issue
Block a user