Files
tsunagi/dist/deb/build-deb.sh
T
Aleksandr BogomiakovandClaude c62d29fa14 Arch package: start the service and let the GUI reach the agent
The control socket is now opened to the tsunagi group (unit), the Arch
package enables and starts the service on install, adds the installing user
to the group, restarts a running agent on upgrade, and depends on the
libraries the tray loads at run time. The tray looks for the agent's socket
again on every poll instead of once at start, and a missing indicator
library is reported instead of panicking. Repository URLs unified.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-10-02 23:29:51 +01:00

131 lines
4.9 KiB
Bash
Executable File

#!/usr/bin/env bash
# Assemble a dependency-free Debian package from prebuilt tsunagi binaries,
# using only dpkg-deb (no cargo-deb, no nfpm).
#
# Usage: build-deb.sh <binary> <deb_arch> <version> <output.deb> [tray_binary]
# <binary> path to the built tsunagi (agent/CLI) executable
# <deb_arch> Debian architecture: amd64 or arm64
# <version> package version (the tag without its leading v)
# <output> path to write the .deb to
# [tray_binary] optional path to the tsunagi-tray GUI executable; when given,
# the package also installs the tray and a desktop launcher and
# is named tsunagi-gui (conflicting with the headless tsunagi).
set -euo pipefail
binary="$1"
arch="$2"
version="$3"
output="$4"
tray="${5:-}"
here="$(cd "$(dirname "$0")" && pwd)"
root="$(mktemp -d)"
trap 'rm -rf "$root"' EXIT
# Payload. Debian installs to /usr/bin (not /usr/local), so the service's
# ExecStart is rewritten to match; the source unit targets /usr/local/bin for
# the tarball installer.
install -D -m 0755 "$binary" "$root/usr/bin/tsunagi"
mkdir -p "$root/lib/systemd/system"
sed 's#/usr/local/bin/tsunagi#/usr/bin/tsunagi#' \
"$here/../linux/tsunagi.service" > "$root/lib/systemd/system/tsunagi.service"
chmod 0644 "$root/lib/systemd/system/tsunagi.service"
install -D -m 0644 "$here/../linux/50-tsunagi-resolved.rules" \
"$root/usr/share/polkit-1/rules.d/50-tsunagi-resolved.rules"
install -D -m 0644 "$here/../../README.md" "$root/usr/share/doc/tsunagi/README.md"
install -D -m 0644 "$here/../linux/README.md" "$root/usr/share/doc/tsunagi/INSTALL.md"
pkgname=tsunagi
extra_control=""
desc_gui=""
if [ -n "$tray" ]; then
pkgname=tsunagi-gui
# The GUI package is a superset of the headless one and must not coexist
# with it (both ship /usr/bin/tsunagi).
extra_control=$'Conflicts: tsunagi\nReplaces: tsunagi\nProvides: tsunagi\n'
# What the tray and its window load at run time.
extra_control+=$'Depends: libgtk-3-0 | libgtk-3-0t64, libayatana-appindicator3-1 | libappindicator3-1, libxdo3, libxkbcommon0, libwayland-client0, libx11-6, libgl1\n'
desc_gui=" It also installs the tray GUI (tsunagi-tray) and a desktop launcher so it can be started from the applications menu."
install -D -m 0755 "$tray" "$root/usr/bin/tsunagi-tray"
install -D -m 0644 "$here/../linux/tsunagi-tray.desktop" \
"$root/usr/share/applications/tsunagi-tray.desktop"
install -D -m 0644 "$here/../linux/tsunagi.svg" \
"$root/usr/share/icons/hicolor/scalable/apps/tsunagi.svg"
fi
mkdir -p "$root/DEBIAN"
cat > "$root/DEBIAN/control" <<CTRL
Package: ${pkgname}
Version: ${version}
Architecture: ${arch}
Maintainer: AB <ab@hexor.cy>
Section: net
Priority: optional
Homepage: https://github.com/house-of-vanity/tsunagi
${extra_control}Description: Serverless private mesh networking agent
tsunagi forms small private mesh IP networks between peers, with NAT
traversal and no central server. This package installs a static,
dependency-free agent, a systemd service that runs it as a dedicated
unprivileged "tsunagi" user with only CAP_NET_ADMIN and CAP_NET_BIND_SERVICE,
and a polkit rule for the local DNS resolver.${desc_gui}
CTRL
# The dedicated system user the service runs as. It is in the "tsunagi" group,
# which the polkit rule grants the resolve1 actions. systemd creates the state,
# cache and runtime directories for it on first start.
cat > "$root/DEBIAN/postinst" <<'POSTINST'
#!/bin/sh
set -e
if ! getent group tsunagi >/dev/null 2>&1; then
addgroup --system tsunagi >/dev/null 2>&1 || true
fi
if ! getent passwd tsunagi >/dev/null 2>&1; then
adduser --system --ingroup tsunagi --home /var/lib/tsunagi --no-create-home \
--gecos "tsunagi agent" --disabled-login tsunagi >/dev/null 2>&1 || true
fi
if [ -d /run/systemd/system ]; then
systemctl daemon-reload >/dev/null 2>&1 || true
fi
POSTINST
if [ -n "$tray" ]; then
cat >> "$root/DEBIAN/postinst" <<'POSTINST_GUI'
if command -v update-desktop-database >/dev/null 2>&1; then
update-desktop-database -q /usr/share/applications >/dev/null 2>&1 || true
fi
if command -v gtk-update-icon-cache >/dev/null 2>&1; then
gtk-update-icon-cache -q -t /usr/share/icons/hicolor >/dev/null 2>&1 || true
fi
POSTINST_GUI
fi
echo "exit 0" >> "$root/DEBIAN/postinst"
cat > "$root/DEBIAN/prerm" <<'PRERM'
#!/bin/sh
set -e
if [ "$1" = remove ] || [ "$1" = purge ]; then
if [ -d /run/systemd/system ]; then
systemctl disable --now tsunagi.service >/dev/null 2>&1 || true
fi
fi
exit 0
PRERM
cat > "$root/DEBIAN/postrm" <<'POSTRM'
#!/bin/sh
set -e
if [ -d /run/systemd/system ]; then
systemctl daemon-reload >/dev/null 2>&1 || true
fi
exit 0
POSTRM
chmod 0755 "$root/DEBIAN/postinst" "$root/DEBIAN/prerm" "$root/DEBIAN/postrm"
# --root-owner-group writes the payload as root:root without needing fakeroot.
dpkg-deb --root-owner-group --build "$root" "$output"
echo "built $output"