Initial AUR work

This commit is contained in:
Jack Kingsman
2026-04-09 19:39:57 -07:00
parent 424da7e232
commit 967269ef7d
5 changed files with 272 additions and 0 deletions

71
.github/workflows/publish-aur.yml vendored Normal file
View File

@@ -0,0 +1,71 @@
name: Publish AUR package
# Pushes the contents of pkg/aur/ to the remoteterm-meshcore AUR repository
# whenever a GitHub release is published. Can also be triggered manually for
# testing or out-of-band republishes.
#
# Required secrets:
# AUR_SSH_PRIVATE_KEY Private SSH key registered with the AUR maintainer
# account that owns the remoteterm-meshcore package.
# AUR_COMMIT_EMAIL Email used for the AUR git commit identity.
on:
release:
types: [published]
workflow_dispatch:
inputs:
version:
description: 'Version to publish (no v prefix, e.g. 3.9.1)'
required: true
concurrency:
# Serialize publishes so a fast back-to-back release sequence cannot race
# two pushes against the AUR repo. The later one wins by virtue of being
# the final state.
group: publish-aur
cancel-in-progress: false
jobs:
publish-aur:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Resolve version from event
id: version
run: |
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
VERSION="${{ inputs.version }}"
else
VERSION="${{ github.event.release.tag_name }}"
fi
VERSION="${VERSION#v}"
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
echo "Publishing AUR package for version $VERSION"
- name: Stamp pkgver into PKGBUILD
run: |
sed -i "s/^pkgver=.*/pkgver=${{ steps.version.outputs.version }}/" pkg/aur/PKGBUILD
sed -i "s/^pkgrel=.*/pkgrel=1/" pkg/aur/PKGBUILD
- name: Publish to AUR
uses: KSXGitHub/github-actions-deploy-aur@v4.1.2
with:
pkgname: remoteterm-meshcore
pkgbuild: pkg/aur/PKGBUILD
assets: |
pkg/aur/remoteterm-meshcore.install
pkg/aur/remoteterm-meshcore.service
pkg/aur/remoteterm.env
commit_username: jkingsman
commit_email: ${{ secrets.AUR_COMMIT_EMAIL }}
ssh_private_key: ${{ secrets.AUR_SSH_PRIVATE_KEY }}
commit_message: "Update to ${{ steps.version.outputs.version }}"
# Recompute sha256sums from the live release tarball + the bundled
# service/env files. The committed PKGBUILD has SKIP placeholders.
updpkgsums: true
# Validate the PKGBUILD parses and sources download, but skip the
# actual build (which would run uv sync + npm install for several
# minutes of CI time on every release).
test: true
test_flags: --clean --cleanbuild --nodeps --nobuild

117
pkg/aur/PKGBUILD Normal file
View File

@@ -0,0 +1,117 @@
# Maintainer: Jack Kingsman <jack.kingsman@gmail.com>
pkgname=remoteterm-meshcore
# pkgver is rewritten by .github/workflows/publish-aur.yml on each release.
pkgver=3.9.0
pkgrel=1
pkgdesc='Web interface for MeshCore mesh radio networks'
arch=(x86_64 aarch64)
url='https://github.com/jkingsman/Remote-Terminal-for-MeshCore'
license=('MIT')
# No system python dependency — we bundle a standalone interpreter via
# python-build-standalone so the package is immune to Arch python ABI bumps.
depends=(glibc)
makedepends=(uv nodejs npm)
optdepends=('bluez: BLE transport support')
backup=(etc/remoteterm-meshcore/remoteterm.env)
# The bundled python-build-standalone binary ships pre-stripped. makepkg's
# default strip pass corrupts its unusual ELF layout (.dynstr not in segment),
# so we disable stripping for the whole package.
options=(!strip)
install=remoteterm-meshcore.install
source=(
"$pkgname-$pkgver.tar.gz::https://github.com/jkingsman/Remote-Terminal-for-MeshCore/archive/refs/tags/$pkgver.tar.gz"
"remoteterm-meshcore.service"
"remoteterm.env"
)
# sha256sums are recomputed by `updpkgsums` in the publish workflow before
# the PKGBUILD is pushed to AUR. The committed values are intentionally SKIP
# so the file is honest about not tracking real hashes in this repo.
sha256sums=('SKIP'
'SKIP'
'SKIP')
# python-build-standalone: stripped install_only builds (~30 MB each).
# Bump _pyver and _pybuilddate when updating the bundled interpreter.
_pyver=3.13.13
_pybuilddate=20260408
source_x86_64=("python-${_pyver}-x86_64.tar.gz::https://github.com/astral-sh/python-build-standalone/releases/download/${_pybuilddate}/cpython-${_pyver}+${_pybuilddate}-x86_64-unknown-linux-gnu-install_only_stripped.tar.gz")
sha256sums_x86_64=('SKIP')
source_aarch64=("python-${_pyver}-aarch64.tar.gz::https://github.com/astral-sh/python-build-standalone/releases/download/${_pybuilddate}/cpython-${_pyver}+${_pybuilddate}-aarch64-unknown-linux-gnu-install_only_stripped.tar.gz")
sha256sums_aarch64=('SKIP')
_srcname="Remote-Terminal-for-MeshCore-$pkgver"
build() {
cd "$_srcname"
# Build frontend
cd frontend
npm ci
npm run build
cd ..
# Create venv using the bundled standalone Python interpreter, then install
# Python dependencies into it. This produces a fully self-contained venv
# that does not reference the system Python at all.
uv venv --python "$srcdir/python/bin/python3" .venv
uv sync --no-dev --frozen
}
package() {
cd "$_srcname"
local _optdir=/opt/remoteterm-meshcore
local _instdir="$pkgdir$_optdir"
# App source
install -d "$_instdir"
cp -r app "$_instdir/"
cp pyproject.toml uv.lock "$_instdir/"
# Frontend build
install -d "$_instdir/frontend"
cp -r frontend/dist "$_instdir/frontend/"
# Bundled Python interpreter
cp -a "$srcdir/python" "$_instdir/python"
# Python venv
cp -a .venv "$_instdir/"
# Fix shebangs and venv config: replace build-time paths with final
# install paths so the venv works from /opt after installation.
# sed only operates on regular file contents, so symlinks need separate
# fixup below.
find "$_instdir/.venv/bin" -type f -exec \
sed -i "s|$srcdir/$_srcname/.venv|$_optdir/.venv|g" {} +
find "$_instdir/.venv/bin" -type f -exec \
sed -i "s|$srcdir/python|$_optdir/python|g" {} +
sed -i \
-e "s|$srcdir/$_srcname/.venv|$_optdir/.venv|g" \
-e "s|$srcdir/python|$_optdir/python|g" \
"$_instdir/.venv/pyvenv.cfg" 2>/dev/null || true
# Recreate the venv interpreter symlinks — these are symlinks (not files),
# so sed cannot fix them. Point them at the bundled Python.
ln -sf "$_optdir/python/bin/python3" "$_instdir/.venv/bin/python"
ln -sf python "$_instdir/.venv/bin/python3"
ln -sf python "$_instdir/.venv/bin/python3.13"
# Data directory symlink
ln -s /var/lib/remoteterm-meshcore "$_instdir/data"
# Systemd service
install -Dm644 "$srcdir/remoteterm-meshcore.service" \
"$pkgdir/usr/lib/systemd/system/remoteterm-meshcore.service"
# Environment file
install -Dm640 "$srcdir/remoteterm.env" \
"$pkgdir/etc/remoteterm-meshcore/remoteterm.env"
# License
install -Dm644 LICENSE.md \
"$pkgdir/usr/share/licenses/$pkgname/LICENSE"
}

View File

@@ -0,0 +1,27 @@
pre_install() {
getent group remoteterm > /dev/null || groupadd -r remoteterm
getent passwd remoteterm > /dev/null || \
useradd -r -g remoteterm -d /var/lib/remoteterm-meshcore -s /sbin/nologin \
-c "RemoteTerm for MeshCore" remoteterm
}
pre_upgrade() {
pre_install
}
post_install() {
echo "==> Set your radio connection (serial, TCP, or BLE) in"
echo "==> /etc/remoteterm-meshcore/remoteterm.env"
echo "==> Start the service with: systemctl enable --now remoteterm-meshcore"
echo "==> The web UI will be at http://localhost:8000"
}
post_upgrade() {
# Clean orphaned __pycache__ dirs left by the previous Python version
find /opt/remoteterm-meshcore -type d -name __pycache__ -exec rm -rf {} + 2>/dev/null || true
systemctl daemon-reload
if systemctl is-active --quiet remoteterm-meshcore; then
systemctl restart remoteterm-meshcore
fi
}

View File

@@ -0,0 +1,29 @@
[Unit]
Description=RemoteTerm for MeshCore
Documentation=https://github.com/jkingsman/Remote-Terminal-for-MeshCore
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=remoteterm
Group=remoteterm
WorkingDirectory=/opt/remoteterm-meshcore
EnvironmentFile=/etc/remoteterm-meshcore/remoteterm.env
ExecStart=/opt/remoteterm-meshcore/.venv/bin/uvicorn app.main:app --host 0.0.0.0 --port 8000
Restart=on-failure
RestartSec=5s
StateDirectory=remoteterm-meshcore
# Hardening
ProtectSystem=strict
ProtectHome=yes
PrivateTmp=yes
NoNewPrivileges=yes
# Serial port access (uucp group on Arch)
SupplementaryGroups=uucp
[Install]
WantedBy=multi-user.target

28
pkg/aur/remoteterm.env Normal file
View File

@@ -0,0 +1,28 @@
# RemoteTerm for MeshCore configuration
# https://github.com/jkingsman/Remote-Terminal-for-MeshCore
# Transport: uncomment ONE section below
# Serial auto-detect (default — no config needed)
# Serial manual port
#MESHCORE_SERIAL_PORT=/dev/ttyUSB0
# TCP
#MESHCORE_TCP_HOST=192.168.1.100
#MESHCORE_TCP_PORT=4000
# BLE (also requires the optional `bluez` package)
#MESHCORE_BLE_ADDRESS=AA:BB:CC:DD:EE:FF
#MESHCORE_BLE_PIN=123456
# Database
MESHCORE_DATABASE_PATH=/var/lib/remoteterm-meshcore/meshcore.db
# Bots can run arbitrary Python on the server. Leave this set to 'true' unless
# you trust everyone on your network.
MESHCORE_DISABLE_BOTS=true
# HTTP Basic Auth (recommended when bots are enabled)
#MESHCORE_BASIC_AUTH_USERNAME=
#MESHCORE_BASIC_AUTH_PASSWORD=