Files
firmware/meshtasticd.spec.rpkg
Jonathan BennettandClaude Opus 5 8b8dc611c7 feat(portduino): add a test-menu action to power off the host (#11920)
A portduino node is a process on a computer that outlives it. shutdown() ends
at exit(EXIT_SUCCESS), so "Shutdown" only stops the daemon -- and the shipped
unit sets Restart=always, which makes it a restart in practice. There is no way
from the node's UI to halt the machine it runs on.

Add "Power Off Host" to the hidden test menu, behind its own confirmation. It is
kept separate from shutdownMenu() because the two mean different things: one
ends the node, the other ends the machine, and on a headless node nothing brings
the host back.

Confirming raises hostPowerOffRequested and then injects the ordinary
INPUT_BROKER_SHUTDOWN, so the normal sequence still runs and the NodeDB, message
store and waypoints are saved exactly as for any other shutdown. Only at the
portduino arm does it hand off to logind, falling through to exit() if that is
refused rather than claiming to shut down and sitting there.

The call is org.freedesktop.login1.Manager.PowerOff with interactive=false: the
daemon has no session and no way to answer a polkit prompt, so asking for one
would hang until timeout. It opens its own bus connection rather than reusing
the BLE backend's, which may already be torn down by then.

meshtasticd runs unprivileged with no session, so logind's default of
auth_admin_keep refuses it. bin/polkit-1/meshtasticd.rules grants the two
power-off actions to that one user, shipped from both the deb and the rpm
alongside the existing D-Bus policy. It deliberately does not grant
power-off-ignore-inhibit, so a package upgrade or a held lock still blocks the
halt; power-off-multiple-sessions is granted because logind escalates to it
whenever anyone is logged in, which on a node someone has SSH'd into is the
normal case.

HAS_HOST_POWEROFF gets its own __has_include test rather than reusing
HAS_BLUETOOTH: the two share a transport, not a purpose, and a build with
Bluetooth off should still be able to halt the box.

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-10-02 17:54:37 +00:00

197 lines
7.4 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# meshtasticd spec file for RPM-based distributions
#
# Build locally with:
# ```
# sudo dnf install rpkg-util
# rpkg local
# ```
#
# See:
# - https://docs.pagure.org/rpkg-util/v3/index.html
# - https://docs.fedoraproject.org/en-US/packaging-guidelines/Versioning/
%global meshtasticd_user meshtasticd
Name: meshtasticd
# Version Ex: 2.5.19
Version: {{{ meshtastic_version }}}
# Release Ex: 9127.daily.gitd7f5f620.fc41
Release: {{{ git_commits_num }}}%{?copr_projectname:.%{copr_projectname}}.git{{{ git_commit_sha }}}%{?dist}
VCS: {{{ git_dir_vcs }}}
Summary: Meshtastic daemon for communicating with Meshtastic devices
License: GPL-3.0
URL: https://github.com/meshtastic/firmware
Source0: {{{ git_dir_pack }}}
Source1: https://github.com/meshtastic/web/releases/download/v{{{ web_version }}}/build.tar
BuildRequires: systemd-rpm-macros
BuildRequires: python3-devel
BuildRequires: platformio
BuildRequires: python3dist(protobuf)
BuildRequires: python3dist(grpcio[protobuf])
BuildRequires: python3dist(grpcio-tools)
BuildRequires: git-core
BuildRequires: gcc-c++
BuildRequires: pkgconfig(yaml-cpp)
BuildRequires: pkgconfig(jsoncpp)
BuildRequires: pkgconfig(libgpiod)
BuildRequires: pkgconfig(bluez)
BuildRequires: pkgconfig(sdbus-c++)
BuildRequires: pkgconfig(libusb-1.0)
BuildRequires: libi2c-devel
BuildRequires: pkgconfig(libuv)
BuildRequires: pkgconfig(sqlite3)
BuildRequires: pkgconfig(libcurl)
# Web components:
BuildRequires: pkgconfig(openssl)
BuildRequires: pkgconfig(liborcania)
BuildRequires: pkgconfig(libyder)
BuildRequires: pkgconfig(libulfius)
# TFT components:
BuildRequires: pkgconfig(x11)
BuildRequires: pkgconfig(libinput)
BuildRequires: pkgconfig(xkbcommon-x11)
BuildRequires: pkgconfig(sdl2)
BuildRequires: pkgconfig(libnotify)
# libbsd is needed on older Fedora/RHEL to provide 'strlcpy'
%if 0%{?fedora} >= 39 || 0%{?rhel} >= 10
BuildRequires: glibc-devel >= 2.38
%else
BuildRequires: pkgconfig(libbsd-overlay)
%endif
Requires: systemd-udev
# bluetoothd and the 'bluetooth' group, needed for BLE peripheral support
Recommends: bluez
# Declare that this package provides the user/group it creates in %pre
# Required for Fedora 43+ which tracks users/groups as RPM dependencies
Provides: user(%{meshtasticd_user})
Provides: group(%{meshtasticd_user})
Provides: group(spi)
%description
Meshtastic daemon. Meshtastic is an off-grid
text communication platform that uses inexpensive LoRa radios.
%prep
{{{ git_dir_setup_macro }}}
# Unpack the web files
mkdir -p web
tar -xf %{SOURCE1} -C web
gzip -dr web
%build
# Use the “native-tft” environment from platformio to build a Linux binary
platformio run -e native-tft
%install
# Install meshtasticd binary
mkdir -p %{buildroot}%{_bindir}
install -m 0755 .pio/build/native-tft/meshtasticd %{buildroot}%{_bindir}/meshtasticd
# Install portduino VFS dir
install -p -d -m 0770 %{buildroot}%{_localstatedir}/lib/meshtasticd
# Install udev rules
mkdir -p %{buildroot}%{_udevrulesdir}
install -m 0644 bin/99-meshtasticd-udev.rules %{buildroot}%{_udevrulesdir}/99-meshtasticd-udev.rules
# Install config dirs
mkdir -p %{buildroot}%{_sysconfdir}/meshtasticd
install -m 0644 bin/config-dist.yaml %{buildroot}%{_sysconfdir}/meshtasticd/config.yaml
mkdir -p %{buildroot}%{_sysconfdir}/meshtasticd/config.d
mkdir -p %{buildroot}%{_sysconfdir}/meshtasticd/available.d
cp -r bin/config.d/* %{buildroot}%{_sysconfdir}/meshtasticd/available.d
# Install systemd service
install -D -m 0644 bin/meshtasticd.service %{buildroot}%{_unitdir}/meshtasticd.service
# Install meshtasticd start wrapper
install -D -m 0755 bin/meshtasticd-start.sh %{buildroot}%{_bindir}/meshtasticd-start.sh
# Install D-Bus policy (lets the meshtasticd user talk to bluetoothd for BLE)
install -D -m 0644 bin/dbus-1/meshtasticd.conf %{buildroot}%{_datadir}/dbus-1/system.d/meshtasticd.conf
# Install polkit rule (lets the meshtasticd user halt the host for "Power Off Host")
install -D -m 0644 bin/polkit-1/meshtasticd.rules %{buildroot}%{_datadir}/polkit-1/rules.d/meshtasticd.rules
# Install the web files under /usr/share/meshtasticd/web
mkdir -p %{buildroot}%{_datadir}/meshtasticd/web
cp -r web/* %{buildroot}%{_datadir}/meshtasticd/web
# Install default SSL storage directory (for web)
mkdir -p %{buildroot}%{_sysconfdir}/meshtasticd/ssl
# Install desktop icon
mkdir -p %{buildroot}%{_datadir}/icons/hicolor/scalable/apps
install -m 0644 bin/org.meshtastic.meshtasticd.svg %{buildroot}%{_datadir}/icons/hicolor/scalable/apps/org.meshtastic.meshtasticd.svg
%pre
# create spi group (for udev rules)
getent group spi > /dev/null || groupadd -r spi
# create a meshtasticd group and user
getent group %{meshtasticd_user} > /dev/null || groupadd -r %{meshtasticd_user}
getent passwd %{meshtasticd_user} > /dev/null || \
useradd -r -d %{_localstatedir}/lib/meshtasticd -g %{meshtasticd_user} -G spi \
-s /sbin/nologin -c "Meshtastic Daemon" %{meshtasticd_user}
# add meshtasticd user to appropriate groups (if they exist)
getent group gpio > /dev/null && usermod -a -G gpio %{meshtasticd_user} > /dev/null
getent group plugdev > /dev/null && usermod -a -G plugdev %{meshtasticd_user} > /dev/null
getent group dialout > /dev/null && usermod -a -G dialout %{meshtasticd_user} > /dev/null
getent group i2c > /dev/null && usermod -a -G i2c %{meshtasticd_user} > /dev/null
getent group video > /dev/null && usermod -a -G video %{meshtasticd_user} > /dev/null
getent group audio > /dev/null && usermod -a -G audio %{meshtasticd_user} > /dev/null
getent group input > /dev/null && usermod -a -G input %{meshtasticd_user} > /dev/null
getent group bluetooth > /dev/null && usermod -a -G bluetooth %{meshtasticd_user} > /dev/null
exit 0
%triggerin -- meshtasticd < 2.6.9
# migrate .portduino (if it exists and hasn’t already been copied)
if [ -d /root/.portduino ] && [ ! -e /var/lib/meshtasticd/.portduino ]; then
mkdir -p /var/lib/meshtasticd
cp -r /root/.portduino /var/lib/meshtasticd/.portduino
chown -R %{meshtasticd_user}:%{meshtasticd_user} \
%{_localstatedir}/lib/meshtasticd || :
# Fix SELinux labels if present (no-op on non-SELinux systems)
restorecon -R /var/lib/meshtasticd/.portduino 2>/dev/null || :
echo "Migrated meshtasticd VFS from /root/.portduino to /var/lib/meshtasticd/.portduino"
echo "meshtasticd now runs as the 'meshtasticd' user, not 'root'."
echo "See https://github.com/meshtastic/firmware/pull/6718 for details"
fi
%post
%systemd_post meshtasticd.service
%preun
%systemd_preun meshtasticd.service
%postun
%systemd_postun_with_restart meshtasticd.service
%files
%defattr(-,%{meshtasticd_user},%{meshtasticd_user})
%license LICENSE
%doc README.md
%{_bindir}/meshtasticd
%{_bindir}/meshtasticd-start.sh
%dir %{_localstatedir}/lib/meshtasticd
%{_udevrulesdir}/99-meshtasticd-udev.rules
%dir %{_sysconfdir}/meshtasticd
%dir %{_sysconfdir}/meshtasticd/config.d
%dir %{_sysconfdir}/meshtasticd/available.d
%config(noreplace) %{_sysconfdir}/meshtasticd/config.yaml
%config %{_sysconfdir}/meshtasticd/available.d/*
%{_unitdir}/meshtasticd.service
%attr(0644,root,root) %{_datadir}/dbus-1/system.d/meshtasticd.conf
%attr(0644,root,root) %{_datadir}/polkit-1/rules.d/meshtasticd.rules
%dir %{_datadir}/meshtasticd
%dir %{_datadir}/meshtasticd/web
%{_datadir}/meshtasticd/web/*
%dir %{_sysconfdir}/meshtasticd/ssl
%{_datadir}/icons/hicolor/scalable/apps/org.meshtastic.meshtasticd.svg
%changelog
%autochangelog