Files
tsunagi/dist/deb/build-deb.sh
T
UltradesuandClaude Opus 4.8 a3856eed3b
Release / tsunagi-linux-aarch64 (push) Successful in 2m21s
Release / tsunagi-linux-x86_64 (push) Successful in 2m29s
Release / tsunagi-macos-aarch64 (push) Canceled after 0s
Release / tsunagi-windows-x86_64 (push) Canceled after 0s
Release / Publish release (push) Canceled after 0s
Build a dependency-free .deb and attach it to the release
Adds a Debian package to the release for the x86_64 and aarch64 Linux builds, so
`apt install ./tsunagi_*.deb` is a convenient path on the Ubuntu hosts. Because
the binary is static musl, the package declares no Depends — it is built with
plain dpkg-deb on the runner (no cargo-deb or nfpm), from dist/deb/build-deb.sh.

The package installs:
- the static binary at /usr/bin/tsunagi;
- a systemd service at /lib/systemd/system/tsunagi.service that runs the agent
  as root (ExecStart rewritten to /usr/bin; the source unit targets
  /usr/local/bin for the tarball installer);
- a polkit rule at /usr/share/polkit-1/rules.d granting the resolve1 actions to
  a "tsunagi" group, for running the agent as a non-root user instead of via the
  root service. postinst creates that system group and runs daemon-reload; prerm
  disables the service on removal.

Both release workflows gain a "Build the Debian package" step on the two Linux
matrix entries (deb/deb_arch), include the .deb in the uploaded run artifacts,
and attach it to the release (Gitea via the API loop, GitHub via gh). macOS and
Windows are unchanged. Service runs as root by default; the polkit rule/group is
the documented opt-in for the non-root path — say if you'd rather the service
itself run as the tsunagi user.

YAML and shell syntax validated; the .deb build itself runs only on the Linux
runner (no dpkg-deb locally) and has not been exercised in this session.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-10-02 13:34:33 +01:00

93 lines
3.0 KiB
Bash
Executable File

#!/usr/bin/env bash
# Assemble a dependency-free Debian package from a prebuilt static tsunagi
# binary, using only dpkg-deb (no cargo-deb, no nfpm). The binary is statically
# linked, so the package declares no Depends and runs on any Debian/Ubuntu.
#
# Usage: build-deb.sh <binary> <deb_arch> <version> <output.deb>
# <binary> path to the built tsunagi executable
# <deb_arch> Debian architecture: amd64 or arm64
# <version> package version (the tag without its leading v)
# <output> path to write the .deb to
set -euo pipefail
binary="$1"
arch="$2"
version="$3"
output="$4"
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/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"
mkdir -p "$root/DEBIAN"
cat > "$root/DEBIAN/control" <<CTRL
Package: tsunagi
Version: ${version}
Architecture: ${arch}
Maintainer: AB <ab@hexor.cy>
Section: net
Priority: optional
Homepage: https://github.com/Ultradesu/tsunagi
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 binary, a systemd service that runs the agent as root, and a
polkit rule that lets a non-root agent configure systemd-resolved.
CTRL
# A system group for the optional non-root run (the polkit rule grants it the
# resolve1 actions). The packaged service runs as root and does not need it.
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 [ -d /run/systemd/system ]; then
systemctl daemon-reload >/dev/null 2>&1 || true
fi
exit 0
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"