These modules define nixosModules.cad (and freecad/openscad) referenced by
the t480 host module list but were untracked, so the flake could not resolve
them (undefined variable 'cad'). Track them so the build evaluates.
two network/storage admin tools that only shadow needs, grouped behind one
attrset so the host list stays a list of intents rather than of packages.
winbox is a one-liner: pkgs.winbox resolves to winbox4, which nixpkgs
already builds through autoPatchelfHook against the qt/xcb stack it needs.
it does not go anywhere near nix-ld, so nothing has to be added to the
nix-ld library list for it - a comment says so, since the opposite is an
easy assumption to make about a vendored mikrotik binary. the installed
binary is WinBox, capital w, which is worth knowing at a shell prompt.
unraid-usb-creator is not in nixpkgs and upstream ships an appimage only,
so it is a repack. the appimage is a qt6/qml app - a fork of rpi-imager -
built with linuxdeploy, which means it already vendors the whole qt6 stack
plus xcb, icu, gnutls and krb5 under usr/lib. that bundle is kept verbatim
and autopatchelfed against only the handful of libraries linuxdeploy
deliberately leaves to the host: libc, libstdc++, GL, x11, fontconfig and
friends. no FHS wrapper, so no ~400mb buildFHSEnv closure. the usr/ layout
has to survive as a unit because qt.conf sitting next to the binary
declares Prefix=../ with Plugins=plugins and Qml2Imports=qml.
the non-obvious part is appendRunpaths rather than runtimeDependencies for
openssl. qt's tls backend dlopens libssl/libcrypto, so autopatchelf never
sees the dependency, and without it the app cannot fetch the release json
or stream the image. it has to be appendRunpaths because in auto-patchelf
`rpath += runtime_deps` sits inside the set-interpreter branch and so only
ever reaches executables, while `rpath.extend(append_rpaths)` runs for
every patched file. the dlopen happens from plugins/tls/libqopensslbackend
.so and glibc resolves dlopen against the calling object's DT_RUNPATH - the
wrapper's runpath is not consulted - so the path must land on the plugin
itself.
QT_QPA_PLATFORM is pinned to xcb because linuxdeploy bundled only the xcb
platform plugin; there is no libqwayland*.so anywhere in the appimage, so
this always runs through xwayland under hyprland regardless. --set-default
rather than --set, so it can still be overridden if upstream ever ships the
wayland plugin.
udisks2 is enabled from this module even though hyprland/default.nix
already enables it for udiskie. the app enumerates and unmounts removable
drives over the udisks2 d-bus api rather than poking /dev, which is how it
avoids needing root, and repeating the option keeps the module standalone
on a host with no hyprland. bool options merge on equal values, so this
costs nothing.
v1.1.0 is pinned by hash. note the tag is not returned by the github
releases api - which only lists the v2.0.x line - but the asset url that
unraid.net/download redirects to is live and matches.
verified: shadow evaluates clean, both packages build, the .desktop Exec
is rewritten from the bare name to the absolute store path, ldd on the
main binary reports nothing unresolved, and the openssl lib dir is present
on libqopensslbackend.so's runpath. not yet exercised at runtime against
an actual usb stick.
both were installed but never launched. they ship their own units, but in
$out/share/systemd/user - not $out/lib/systemd/user - and that distinction
is why they need redeclaring rather than merely enabling:
* systemd.packages would collect nothing, since nixpkgs' generateUnits
globs only $pkg/etc/systemd/user and $pkg/lib/systemd/user.
* the units are nonetheless visible to the user manager, via
environment.pathsToLink -> /run/current-system/sw/share/systemd/user,
which is on the search path because XDG_DATA_DIRS ends with
/run/current-system/sw/share. but visible is not enabled - nothing
creates the WantedBy symlink, so they sit unstarted.
* wantedBy alone would not help either: with no other keys nixos
synthesises a replacement unit with an empty [Service] section, and it
shadows upstream's because /etc/systemd/user takes precedence over
$XDG_DATA_DIRS.
binding them to graphical-session.target, which uwsm manages properly,
means they start and stop with the session instead of leaking across
logins - same reasoning as udiskie, so that moves into the same attrset.
close to upstream's definitions but not identical: hyprsunset's
Requires=graphical-session.target is dropped, because PartOf already
propagates the stop while Requires would additionally make starting
hyprsunset by hand pull up the whole session target. the Slice=session.slice
asymmetry is upstream's own - hyprsunset sets it, hypridle does not - and is
noted inline so it does not get "fixed" later.
hypridle gets an explicit path because its config shells out to hyprlock,
pidof, brightnessctl, hyprctl, loginctl, systemctl and notify-send. that
config lives in the dotfiles repo, so this list can silently drift out of
sync with it: a binary used there but missing here fails as a bare "command
not found" inside hypridle, and Restart=on-failure will not catch it because
hypridle itself stays up. flagged in a comment at both ends.
udiskie was installed but never actually launched - nothing in the dotfiles autostarts it, and services.udisks2 was off, so even once started it had no daemon to talk to. binds it to graphical-session.target (managed by uwsm) so it starts and stops with the session. only touches removable media: udisks2 reports the internal sata disks as HintSystem=true, so the drives declared in disks.nix are left alone.
the xorg package set is deprecated in nixpkgs 26.05. pkgs.xrandr resolves to the same xrandr-1.5.4 derivation, so hyprland autostart scripts calling xrandr are unaffected.
moves user identity and init.defaultBranch into /etc/gitconfig instead of stow-managed dotfiles. note: a per-user ~/.gitconfig still overrides these, so identity must stay out of the stow repo to avoid shadowing.