The command line package is now `tsunagi` and builds the `tsng` executable,
which the packages, the unit, the installers and the workflows install and
run. The core library package becomes `tsunagi-core`, keeping the library name
`tsunagi`, so no code changes `use tsunagi::...`. Directories follow
(crates/tsunagi-core, crates/tsunagi). Every command shown to a person is now
`tsng ...`.
Co-Authored-By: Claude <noreply@anthropic.com>
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>
Release / tsunagi-linux-aarch64 (push) Failing after 2m40s
Release / tsunagi-linux-x86_64 (push) Failing after 2m40s
Release / tsunagi-macos-aarch64 (push) Canceled after 0s
Release / tsunagi-windows-x86_64 (push) Canceled after 0s
Release / Publish release (push) Canceled after 0s
Adds the tray application to the release:
- Every target's archive now also contains the tsunagi-tray binary. On Linux it
is built against an old glibc baseline (via cargo-zigbuild) rather than static
musl, because a GUI must dlopen libGL/X11/Wayland at runtime and a static musl
binary cannot; the agent stays static musl. macOS and Windows build the tray
natively.
- New GUI package variants for Linux: `tsunagi-gui` .deb and .pkg.tar.zst, built
by the existing scripts with an extra tray argument. They install the agent
(service, polkit, user — same as the headless packages) plus the tray binary,
a desktop launcher (dist/linux/tsunagi-tray.desktop) and an icon
(dist/linux/tsunagi.svg), so the GUI appears in the applications menu. The GUI
package conflicts/replaces/provides the headless tsunagi so the two do not
coexist.
- The tray finds the system service with no configuration: the library's default
control-socket path now prefers /run/tsunagi/agent.sock when present (both the
tray and CLI use this), falling back to the per-user path.
No control-protocol change. Builds, fmt and clippy clean on macOS; the Linux GUI
cross-build and the packages are exercised only by a real CI run.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Release / tsunagi-linux-aarch64 (push) Successful in 2m39s
Release / tsunagi-linux-x86_64 (push) Successful in 2m32s
Release / tsunagi-macos-aarch64 (push) Canceled after 0s
Release / tsunagi-windows-x86_64 (push) Canceled after 0s
Release / Publish release (push) Canceled after 0s
Reworks the Linux packaging so the service runs as an unprivileged, dedicated
"tsunagi" user instead of root — the point of a native package is to set things
up properly for that OS's users — and adds Arch Linux packages beside the deb.
Both package families are built from the already-compiled static binary; nothing
is recompiled.
Service model (shared systemd unit, dist/linux/tsunagi.service):
- User=tsunagi with AmbientCapabilities=CAP_NET_ADMIN CAP_NET_BIND_SERVICE, so
it creates the TUN and binds low ports without root.
- StateDirectory/CacheDirectory/RuntimeDirectory give it /var/lib/tsunagi,
/var/cache/tsunagi and /run/tsunagi, and the agent is pointed at them (and the
socket at /run/tsunagi/agent.sock) through TSUNAGI_* env in the unit.
- The polkit rule now grants the resolve1 actions to the "tsunagi" group; the
service user is in it, and admins can add themselves.
CLI: when no state dir is chosen, the control commands prefer the system
service's socket at /run/tsunagi/agent.sock when it exists, so `sudo tsunagi
status`/`join` reach the packaged daemon with no flags. A per-user agent (its
socket absent from /run) still uses its own.
Packaging:
- deb (build-deb.sh): postinst now creates the tsunagi system user+group; unit
installed to /lib/systemd/system, binary to /usr/bin.
- Arch (new dist/arch/build-pkg.sh): a dependency-free .pkg.tar.zst assembled
with bsdtar + zstd (no makepkg, no Arch host) — .PKGINFO, a .INSTALL scriptlet
that creates the user and reloads systemd, and a gzipped .MTREE; unit to
/usr/lib/systemd/system.
- The polkit rule moved to dist/linux (shared by deb, Arch and the tarball), and
the tarball install.sh now creates the user and installs the unit + rule.
- Both release workflows build the deb and the Arch package on the two Linux
matrix entries (deb_arch/pkg_arch), install libarchive-tools+zstd for it, and
attach both to the release (Gitea API loop / gh).
Not exercised in this session: the .deb and .pkg.tar.zst build and install only
on Linux (no dpkg-deb/bsdtar+pacman locally); CLI build, clippy, fmt and tests
pass, and all shell/YAML is syntax-checked.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Release / tsunagi-linux-aarch64 (push) Failing after 3m12s
Release / tsunagi-linux-x86_64 (push) Failing after 2m21s
Release / tsunagi-macos-aarch64 (push) Canceled after 0s
Release / tsunagi-windows-x86_64 (push) Canceled after 0s
Release / Publish release (push) Canceled after 0s
Pushing a `v*` tag now builds the agent for every supported target and attaches
the archives to a GitHub release. Modelled on the furumi release workflow (a
build matrix, then a publish job that runs `gh release create`), adapted to this
project's two differences: it needs system integration (capabilities/polkit on
Linux, elevation+wintun on Windows, a root daemon on macOS), and its users run
varied distros, not just Ubuntu.
Linux is built as a fully **static musl** binary with cargo-zigbuild, so one
artifact runs on Arch, Alpine, NixOS and old-glibc systems alike, and can be
repackaged into whatever a distro prefers later. musl has no prebuilt
aws-lc-sys bindings, so the Linux jobs install cmake + libclang (bindgen) and
zig (the cross C compiler zigbuild drives). macOS (aarch64) and Windows (x86_64)
build natively; Linux covers x86_64 and aarch64.
Targets: x86_64/aarch64 linux-musl, aarch64 macOS, x86_64 Windows. Each archive
carries the binary, the top-level README, and the platform's install notes plus
integration files:
- dist/linux/: a static-friendly README, a systemd unit (runs as root, so no
capability grant or polkit rule is needed; a commented non-root variant is
included), and an install.sh that drops the binary and the unit or prints the
setcap/polkit alternative.
- dist/windows/: install notes covering wintun.dll and Run-as-administrator.
- dist/macos/: the existing LaunchDaemon plist and notes, now also shipped in
the archive.
Not exercised yet: the workflow only runs on a real tag push, and the
aws-lc-sys-under-musl build has not been run locally in this session (no zig
toolchain here). YAML and install.sh syntax are validated.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>