Builds a .deb that installs:
| Payload | Installed to |
|---|---|
yadorilink (CLI) |
/usr/bin/yadorilink |
yadorilink-daemon |
/usr/bin/yadorilink-daemon |
systemd --user service unit |
/usr/lib/systemd/user/yadorilink-daemon.service |
| license texts | /usr/share/doc/yadorilink/ |
This is a CLI/daemon-only package:
yadorilink-desktop-app (the tray/menu-bar status GUI, macOS/Windows only)
and a Linux file-manager shell integration are explicitly out of scope.
There is no GTK/appindicator dependency anywhere in this
package as a result. yadorilink-coordination is a
server-side binary and, as on the other platforms' installers, is
not part of this package — deploy it to your own server instead.
This
package goes with a hand-authored debian/control + postinst/postrm
pair built via dpkg-deb (this directory's build-deb.sh), not
cargo-deb, for three reasons:
- Consistency with this repo's existing installers. Both
installer/macos(build-pkg.sh,Distribution.xml, hand-writtenscripts/preinstall/postinstall) andinstaller/windows(yadorilink.iss, hand-writtendaemon-task.ps1) are hand-authored, heavily-commented shell/Pascal-script/PowerShell rather than driven by packaging-metadata-in-the-manifest tooling. A hand-authored.debkeeps that same pattern rather than introducing a fourth, different style of installer for the fourth platform. - No changes to any crate's
Cargo.toml.cargo-debreads its packaging metadata from a[package.metadata.deb]table in the binary crate's ownCargo.toml— meaningcrates/yadorilink-cli/Cargo.tomlandcrates/yadorilink-daemon/Cargo.tomlwould need edits. Those are shared files other task groups of this same change (and unrelated future changes) may be actively editing; a self-containedinstaller/linux/that touches no crate manifest avoids that collision surface entirely. (cargo-debitself is also not added as a dependency of any crate — it would only ever be a build-time tool — but the metadata-placement issue above applies regardless of dependency vs. dev-tool status.) - This package is trivially simple. Two binaries, one static unit
file, and a handful of doc files — the templating/dependency-resolution
cargo-debautomates isn't buying much here, and a plaincontrolfile is easier for a reader unfamiliar withcargo-debto audit line by line, matching this repo's general preference (see the other two installers' READMEs) for scripts that are transparent about exactly what they do.
If a future change wants cargo-deb (e.g. once RPM/other formats such as
Fedora/openSUSE/Arch are being juggled too), it remains a reasonable
revisit — this decision is scoped to this first .deb, not a permanent
constraint.
- A Debian/Ubuntu-family Linux machine (or CI runner), matching this
package's own
Depends: libc6and its systemd-based baseline. - Rust/cargo, for
cargo build --release. dpkg-deb, for building the archive itself — part of the basedpkgpackage, present on essentially every Debian-family system already (apt-get install dpkg-devif somehow missing, e.g. a minimal container image).- Optionally
lintian, for an extra structural lint pass (apt-get install lintian) — not required to build or install.
./build-deb.shThis runs cargo build --release --workspace --exclude yadorilink-desktop-app --bin yadorilink --bin yadorilink-daemon (explicitly excluding both the
desktop app and yadorilink-daemon's second, maintainer-only
yadorilink-sign-manifest bin target — see that crate's Cargo.toml),
stages the payload under .stage/ (rebuilt from scratch every run, safe
to delete between builds), and produces:
dist/yadorilink_<version>_<arch>.deb
dist/yadorilink_<version>_<arch>.deb.sha256
Version comes from the workspace's Cargo.toml ([workspace.package]);
architecture is auto-detected from uname -m (amd64/arm64). Override
either, or skip the cargo build step and package prebuilt binaries from
elsewhere:
PKG_VERSION=0.1.0 PKG_ARCH=arm64 ./build-deb.sh
YADORILINK_BIN_DIR=/path/to/target/release ./build-deb.shOnly an x86_64/amd64 build has actually been run through real Linux
CI/manual verification so far; arm64 is untested and should be treated
as experimental until someone actually runs it there.
sudo dpkg -i dist/yadorilink_<version>_<arch>.deb
# or, to also resolve the libc6 dependency automatically if missing:
sudo apt install ./dist/yadorilink_<version>_<arch>.debThe systemd --user unit is installed but not started or enabled
automatically (see systemd/yadorilink-daemon.service's header comment
— a per-user unit generally shouldn't be silently enabled by a package
installed as root). After installing,
each user who wants the daemon running persistently runs, once:
systemctl --user enable --now yadorilink-daemonThen, same as macOS/Windows: yadorilink login, yadorilink device register ..., yadorilink share create <name> --path <folder>,
yadorilink status, etc. — see the top-level README for CLI usage.
debian/postinst (installed as the package's postinst) only runs
systemctl daemon-reload (so a running system manager notices the new
unit file) and prints the systemctl --user enable --now reminder above
— it takes no other action, deliberately (see its own header comment for
why: it runs as root with no specific user session to target, unlike the
macOS postinstall's launchctl asuser trick which at least has a
"console user" to find).
debian/postrm similarly only prints a reminder on remove/purge: a
per-user systemd unit the user enabled themselves can't be reached by a
root-run dpkg -r/apt remove either, so if you enabled the unit,
disable it yourself first (or use uninstall.sh, which does this for
you in the right order).
./uninstall.sh # stop/disable the user unit, then remove the package
./uninstall.sh --purge-data # also remove ~/.local/share/yadorilinkRun as your normal user, without sudo on the whole script — see
uninstall.sh's header comment for why (systemctl --user always
targets the invoking user's own session; running the whole script under
sudo would silently disable nothing). It escalates via sudo internally
only for the actual package removal (dpkg -r).
Once built (./build-deb.sh) on a real Debian/Ubuntu machine or VM:
./verify-deb.sh dist/yadorilink_<version>_<arch>.debThis checks the checksum sidecar, the control file's Package/Version
fields, and that the payload contains /usr/bin/yadorilink,
/usr/bin/yadorilink-daemon (both executable), and
/usr/lib/systemd/user/yadorilink-daemon.service (not executable) —
without requiring root or actually installing anything. It also runs
lintian if installed.
Beyond that structural check, verify the real install end to end:
sudo apt install ./dist/yadorilink_<version>_<arch>.deb- Confirm both binaries run:
yadorilink --version,yadorilink-daemon --version(or--help). - Confirm the unit file is present and well-formed:
systemctl --user cat yadorilink-daemon(before enabling it, this just prints the unit's contents from the shipped file). systemctl --user enable --now yadorilink-daemon, thensystemctl --user status yadorilink-daemonand confirm it'sactive (running).- Kill the daemon process directly (
pkill yadorilink-daemon) and confirm systemd restarts it within a couple seconds (Restart=on-failure) —journalctl --user -u yadorilink-daemonshould show the restart. - Run
yadorilink statusagainst the running daemon and confirm it reaches it over the Unix-domain-socket control transport (seecrates/yadorilink-cli/src/device_config.rsfor the default socket path,~/.local/share/yadorilink/daemon.sock). ./uninstall.sh, then confirm the unit is gone (systemctl --user status yadorilink-daemonreports not-found) and the binaries are removed (which yadorilink/which yadorilink-daemonboth empty).
This packaging was originally authored and structurally exercised from a
macOS development machine (see git history), which could not run
dpkg -i, systemctl, or produce real Linux binaries. A later
verification pass re-ran this package for real on a real Linux (x86_64)
machine, closing most of that original gap:
cargo build --release --workspace --exclude yadorilink-desktop-app --bin yadorilink --bin yadorilink-daemon— succeeds, realx86_64-unknown-linux-gnubinaries../build-deb.shend to end, includingdpkg-deb --build --root-owner-group— produces a real, valid.deb(verified withverify-deb.sh: checksum, control fields, payload paths and modes all correct).lintianagainst the built.deb— clean (run via a disposable Ubuntu 24.04 container, sincelintianwasn't installed on the build host either:docker run ... ubuntu:24.04 ... lintian yadorilink_<version>_amd64.deb).- A real
dpkg -i/apt install— succeeds. Exercised as part of a full APT-repository acceptance test (seeinstaller/linux/apt/): a clean Ubuntu 24.04 container ran the archive-keyring package,apt-get update(verified the repository's GPG signature),apt-get install yadorilink, and confirmedpostinstran (Setting up yadorilink (0.1.0) ...plus its reminder text), both binaries execute (yadorilink --version,yadorilink-daemon --version), anddpkg -s yadorilinkreportsStatus: install ok installed. systemd-analyze verify /usr/lib/systemd/user/yadorilink-daemon.serviceagainst the installed unit (soExecStart's path actually resolves) — zero errors or warnings.
What is still not verified, and needs a real Linux machine/VM with a live user session (a plain container has no session bus):
systemctl --user enable --now yadorilink-daemonactually starting the daemon,Restart=on-failureactually restarting it after a crash, andWantedBy=default.targetactually autostarting it at login../uninstall.sh's livesystemctl --user disable --nowpath (itsdpkg -rhalf is implicitly covered by the apt test above removing the package cleanly when the container exits, but the per-user unit stop/disable step needs a real session to exercise).
build-deb.sh was already structurally arm64-aware before this
verification pass (uname -m's aarch64|arm64 case, PKG_ARCH
override) — that part of
the earlier "untested and should be treated as experimental" caveat above
was about the build itself having never been run for arm64, not about
missing code. That later verification pass actually ran it:
cargo build --release --workspace --exclude yadorilink-desktop-app --bin yadorilink --bin yadorilink-daemonunder real arm64 execution (QEMU user-mode emulation viadocker run --platform linux/arm64 rust:1.98-bookworm, i.e. genuinely running as an arm64 process, not just cross-compiled and left unexecuted).PKG_ARCH=arm64 YADORILINK_BIN_DIR=<arm64 binaries> ./build-deb.shagainst those binaries, thendpkg-deb --info/--contentson the result (structural check only — this build host cannot execute an arm64 ELF outside of QEMU emulation).installer/docker/Dockerfilehad a real bug caught and fixed: the builder stage was pinned to--platform=$BUILDPLATFORMfor build speed, which silently produced an amd64 binary inside the arm64 runtime image (a wrong-architecture binary gives "no such file or directory" at container start, not "exec format error", because the copied glibc dynamic linker path doesn't exist in the target image — easy to miss without actually running the image). Fixed by dropping that pin; see the Dockerfile's own comment. The fix was re-verified against real arm64 compilation mechanics (QEMU registered, workspace crates compiling foraarch64), but the final confirming end-to-enddocker run --platform linux/arm64 ... --versionhas not been completed to a clean pass — seeinstaller/docker/README.mdfor the exact status. Treat the arm64 image as unverified until that run completes.
Not yet run on real arm64 hardware (only QEMU emulation, which proves the build/packaging mechanics work but not real-hardware performance or any QEMU-masked instruction-level issue) — treat this as "arm64 packaging is now exercised and works" rather than "arm64 has been through the same depth of manual verification as amd64" (the live systemd-session gaps above apply here too, and were not re-checked separately for arm64).
build-deb.sh— builds the workspace binaries and produces the.debverify-deb.sh— standalone structural verification of a built.deb(checksum, control metadata, payload contents/modes, optional lintian)debian/control— control file template (@VERSION@/@ARCH@substituted at build time)debian/postinst,debian/postrm— package scripts (reminders only, no automatic systemd enable/disable — see "What the package does" above)debian/copyright— DEP-5 copyright file, references the bundledLICENSE-MITsystemd/yadorilink-daemon.service— the daemon's systemd--userservice unit, installed to/usr/lib/systemd/user/uninstall.sh— companion uninstaller (run as your normal user, not with sudo — see its header comment)