mirror of
https://github.com/foo-dogsquared/nixos-config.git
synced 2025-01-31 22:57:55 +00:00
441 lines
18 KiB
Plaintext
441 lines
18 KiB
Plaintext
= nix-wrapper-manager-fds
|
|
:toc:
|
|
|
|
|
|
wrapper-manager-fds is foodogsquared's reimagining of https://github.com/viperML/wrapper-manager/[wrapper-manager].
|
|
|
|
[CAUTION]
|
|
====
|
|
wrapper-manager-fds is considered unstable and the author is still freely experimenting with various aspects of the project including the module options, library set API, and ease of use for third-partyuse.
|
|
Expect constant breakages here and put on a hard hat before exploring this part of the town.
|
|
====
|
|
|
|
As a recap, the original aim of wrapper-manager is to pave a way of configuring Nix environments through wrappers.
|
|
There has been https://discourse.nixos.org/t/declarative-wrappers/1775[interest on] https://github.com/NixOS/rfcs/pull/75[this feature] footnote:[I mean, a part of the nixpkgs package set has dedicated wrappers for some packages such as GIMP, Inkscape, and Blender.] and I sometimes configure programs through wrappers instead of the typical module system.
|
|
It has its use cases such as quickly creating variants of the same program for specific reasons (for example, creating specialized versions of yt-dlp for downloading audio, video, and more).
|
|
But why not create something more than that?
|
|
And that's how wrapper-manager-fds came to be.
|
|
|
|
[#installation]
|
|
== Installation
|
|
|
|
[#installation-channels]
|
|
=== Channels
|
|
|
|
You can install wrapper-manager-fds with https://zero-to-nix.com/concepts/channels[Nix channels].
|
|
|
|
[source, shell]
|
|
----
|
|
nix-channel --add https://github.com/foo-dogsquared/wrapper-manager-fds/archive/master.tar.gz wrapper-manager-fds
|
|
nix-channel --update
|
|
----
|
|
|
|
Then in your environment configuration, you'll have to import it.
|
|
For more details, see <<user-entrypoint>>.
|
|
|
|
[#installation-pinning-tool]
|
|
=== Pinning tool
|
|
|
|
A recommended (non-flakes) way to install Nix dependencies is to use a pinning tool.
|
|
There are a handful of pinning tool out there but in this case, we'll use https://github.com/andir/npins[npins] as our tool of choice.
|
|
Assuming you have already initialized npins, you can simply add wrapper-manager-fds to your Nix project with the following command.
|
|
|
|
[source, shell]
|
|
----
|
|
npins add github foo-dogsquared wrapper-manager-fds
|
|
----
|
|
|
|
Similar to channels installation, you'll have to import the <<user-entrypoint>> object.
|
|
|
|
[#installation-manual-pinning]
|
|
=== Manual pinning
|
|
|
|
Though not recommended, you could manually pin the Nix library yourself like in the following code.
|
|
|
|
[source, nix]
|
|
----
|
|
{ pkgs, ... }:
|
|
|
|
let
|
|
wrapper-manager-fds = builtins.fetchTarball "https://github.com/foo-dogsquared/wrapper-manager-fds/archive/master.tar.gz";
|
|
wrapperManager = import wrapper-manager-fds { };
|
|
wrapperManagerLib = import wrapperManagerLib.lib { inherit pkgs; }
|
|
in
|
|
wrapperManagerLib.env.build { }
|
|
----
|
|
|
|
[#installation-flakes]
|
|
=== Flakes
|
|
|
|
This project also has a https://zero-to-nix.com/concepts/flakes[flake object].
|
|
In your flake definition, just import it as one of the inputs.
|
|
Unlike the other methods, the flake output is the user entrypoint so no need to import it or anything.
|
|
|
|
[source, nix]
|
|
----
|
|
{
|
|
inputs.wrapper-manager-fds.url = "github:foo-dogsquared/wrapper-manager-fds";
|
|
|
|
outputs = { nixpkgs, ... }@inputs: {
|
|
nixosConfigurations.desktop = nixpkgs.lib.nixosSystem {
|
|
modules = [
|
|
./hosts/desktop.nix
|
|
inputs.wrapper-manager-fds.nixosModules.default
|
|
];
|
|
};
|
|
};
|
|
}
|
|
----
|
|
|
|
[#user-entrypoint]
|
|
=== User entrypoint
|
|
|
|
Most of the things you need from the project are all retrieveable from the entrypoint of this project (`default.nix`) which is an attribute set closely structured from a typical Nix flake that you see.
|
|
For example, if you want the NixOS module for wrapper-manager, you could refer to `nixosModules.default`.
|
|
Here's the breakdown of the attrset entries in the entrypoint.
|
|
|
|
* `lib` is an attribute set containing the main functions: `eval` and `build`.
|
|
(More details to use them are in <<as-a-library>>.)
|
|
|
|
* `nixosModules` contains a set of NixOS modules for wrapper-manager-fds integration.
|
|
You could get the main module with the `default` attribute.
|
|
|
|
* `homeModules` are for home-manager modules and similarly structured to `nixosModules` attribute.
|
|
|
|
* `wrapperManagerLib` contains a path intended to be imported within your Nix code.
|
|
It simply contains the library set that can be used outside of the wrapper-manager-fds module environment.
|
|
|
|
|
|
[#getting-started]
|
|
== Getting started
|
|
|
|
Now that you have wrapper-manager-fds on the go, let's have a breakdown of what it is, exactly.
|
|
The project itself is made of different parts which you can use for different purposes.
|
|
|
|
[#the-module-environment]
|
|
=== The module environment
|
|
|
|
One part of the project is the module environment.
|
|
Just like https://github.com/nix-community/home-manager[home-manager] and https://github.com/nix-community/disko[disko] and https://github.com/viperML/wrapper-manager[the original source], wrapper-manager-fds comes with its own module environment.
|
|
Instead of a home environment from home-manager or an installation script from disko, wrapper-manager-fds module environment evaluates to a derivation containing a wrapper script. footnote:[While the original source also evaluates similar to that, it typically involves a set of wrappers inside of the same configuration environment rather than a single wrapper.]
|
|
This can be thought of as a declarative layer over `makeWrapper` build hook from nixpkgs.
|
|
|
|
Here's a very simple example of a wrapper for Neofetch.
|
|
|
|
[source, nix]
|
|
----
|
|
{ lib, pkgs, ... }:
|
|
|
|
{
|
|
wrappers.neofetch = {
|
|
arg0 = lib.getExe' pkgs.neofetch "neofetch";
|
|
appendArgs = [
|
|
"--ascii_distro" "guix"
|
|
"--title_fqdn" "off"
|
|
"--os_arch" "off"
|
|
];
|
|
};
|
|
}
|
|
----
|
|
|
|
Or if you want fastfetch...
|
|
|
|
[source, nix]
|
|
----
|
|
{ lib, pkgs, ... }:
|
|
|
|
{
|
|
wrappers.fastfetch = {
|
|
arg0 = lib.getExe' pkgs.fastfetch "fastfetch";
|
|
appendArgs = [ "--logo" "Guix" ];
|
|
env.NO_COLOR = "1";
|
|
};
|
|
}
|
|
----
|
|
|
|
Or even both in the same configuration (which you can do).
|
|
|
|
[source, nix]
|
|
----
|
|
{
|
|
imports = [
|
|
./fastfetch.nix
|
|
./neofetch.nix
|
|
];
|
|
}
|
|
----
|
|
|
|
You could even create https://specifications.freedesktop.org/desktop-entry-spec/latest/[XDG desktop entry] files useful for the application to be launched through an application launcher/menu.
|
|
For example, you could create an executable and a desktop entry to launch a custom Firefox profile in your home-manager configuration.
|
|
|
|
[source, nix]
|
|
----
|
|
{ config, lib, pkgs, ... }:
|
|
|
|
{
|
|
programs.firefox.profiles.custom-profile = {
|
|
# Put some profile-specific settings here.
|
|
};
|
|
|
|
wrapper-manager.packages.browsers = {
|
|
wrappers.firefox-custom-profile = {
|
|
arg0 = lib.getExe' config.programs.firefox.package "firefox";
|
|
prependArgs = [
|
|
"-P" "custom-profile"
|
|
];
|
|
xdg.desktopEntry = {
|
|
enable = true;
|
|
settings = {
|
|
desktopName = "Firefox (custom-profile)";
|
|
startupNotify = true;
|
|
startupWMClass = "firefox";
|
|
icon = "firefox";
|
|
mimeTypes = [
|
|
"text/html"
|
|
"application/xhtml+xml"
|
|
"application/vnd.mozilla.xul+xml"
|
|
"x-scheme-handler/http"
|
|
"x-scheme-handler/https"
|
|
];
|
|
};
|
|
};
|
|
};
|
|
};
|
|
}
|
|
----
|
|
|
|
[#as-a-library]
|
|
=== As a library
|
|
|
|
wrapper-manager also comes with a library set which you can use to evaluate and build wrapper-manager packages yourself.
|
|
This is found in the `wrapperManagerLib` attribute from the user entrypoint where it needs an attribute set containing a nixpkgs instance in `pkgs`.
|
|
|
|
[#src:example-lib-build]
|
|
.An example of importing wrapper-manager library
|
|
[source, nix]
|
|
----
|
|
{ pkgs }:
|
|
|
|
let
|
|
wrapper-manager = import (builtins.fetchgit { }) { };
|
|
|
|
wmLib = import wrapper-manager.wrapperManagerLib { inherit pkgs; };
|
|
in
|
|
wmLib.env.build {
|
|
inherit pkgs;
|
|
modules = [ ./fastfetch.nix ];
|
|
specialArgs.yourMomName = "Joe Mama";
|
|
}
|
|
----
|
|
|
|
Here's a quick rundown of what you can do with the library.
|
|
|
|
* Evaluate a wrapper-manager module with `env.eval` where it accepts an attrset similar to the <<src:example-lib-build, previous code listing>> containing a list of additional modules, the nixpkgs instance to be used, and `specialArgs` to be passed on to the `lib.evalModules` from nixpkgs.
|
|
|
|
* Build a wrapper through `env.build` returning a derivation of the wrapper.
|
|
It accepts the same arguments as `env.eval`.
|
|
|
|
There is also `lib` attribute if all you want to do is to build and/or evaluate a wrapper-manager configuration.
|
|
It only contains the function from `env` subset which contains `build` and `eval`.
|
|
|
|
[#as-a-composable-module]
|
|
=== As a composable module
|
|
|
|
The most user-friendly way of using wrapper-manager would be as a composable nixpkgs module of an existing environment.
|
|
wrapper-manager provides a Nix module specifically for NixOS and home-manager environment. footnote:[Any other environments are basically unsupported and if you like to use it outside of NixOS and home-manager, you're on your own.]
|
|
You can import them through the `{nixos,home}Modules.default` from the user entrypoint of the project.
|
|
|
|
Most of the things set up here are implemented to make declaring wrappers ergonomic with the environment.
|
|
For a start, wrapper-manager-fds sets up a module namespace in `wrapper-manager`.
|
|
Here's a quick breakdown of the features that the module has.
|
|
|
|
* Passes the wrapper-manager library through `wrapperManagerLib` module argument.
|
|
This is nice if you want to only use wrapper-manager to quickly create wrappers inside of the configuration without using the wrapper-manager NixOS/home-manager integration module.
|
|
|
|
* You could declare wrappers through `wrapper-manager.packages.<name>` where each of the attribute value is expected to be a wrapper-manager configuration to be added in its respective wider-scope environment.
|
|
|
|
* You could include other modules through `wrapper-manager.sharedModules`.
|
|
This is useful for extending wrapper-manager inside of the configuration environment.
|
|
|
|
Here's an example of adding wrappers through wrapper-manager inside of a home-manager configuration.
|
|
The following configuration will create a wrapped package for yt-dlp with an additional wrapper script named `yt-dlp-audio` and `yt-dlp-video`.
|
|
|
|
[source, nix]
|
|
----
|
|
{ config, lib, pkgs, ... }:
|
|
|
|
{
|
|
home.packages = with pkgs; [
|
|
flowtime
|
|
blanket
|
|
];
|
|
|
|
wrapper-manager.packages = {
|
|
music-setup = {
|
|
basePackages = [ pkgs.yt-dlp ];
|
|
wrappers.yt-dlp-audio = {
|
|
arg0 = lib.getExe' pkgs.yt-dlp "yt-dlp";
|
|
prependArgs = [
|
|
"--config-location" ./config/yt-dlp/audio.conf
|
|
];
|
|
};
|
|
wrappers.yt-dlp-video = {
|
|
arg0 = lib.getExe' pkgs.yt-dlp "yt-dlp";
|
|
prependArgs = [
|
|
"--config-location" ./config/yt-dlp/video.conf
|
|
];
|
|
};
|
|
};
|
|
};
|
|
}
|
|
----
|
|
|
|
|
|
[#development]
|
|
== Development
|
|
|
|
If you want to hack this hack, you'll need either Nix with flakes enabled (`experimental-features = nix-command flakes` in `nix.conf`) or not.
|
|
Either way, this should be enough to cater both flake- and non-flake users.
|
|
|
|
This project supports the current stable and unstable version of NixOS.
|
|
Specifically, we're looking out for the nixpkgs instance both of these versions has.
|
|
As an implementation detail, we pin these branches through https://github.com/andir/npins[npins] which both flakes- and non-flake-based setups uses.
|
|
Just be familiar with it and you'll be fine for the most part. footnote:[Most likely, you don't even need to interact with it for the most part since handling update cadence is handled automatically through the remote CI.]
|
|
|
|
Setting up the development environment should be easy enough.
|
|
|
|
* For flake users, you can just reproduce the development environment with `nix develop`.
|
|
* For non-flake users, you can do the same with `nix-develop`.
|
|
|
|
[#development-library-set-and-modules]
|
|
=== Library set and modules
|
|
|
|
This Nix project has a test infrastructure set up at link:./tests[./tests] covering the library set nad the wrapper-manager module environment.
|
|
For its library set, it makes use of the nixpkgs library and a JSON schema to validate if it passes the whole tests.
|
|
To make use of it, you can run it with the following commands.
|
|
|
|
* For flake users, you can run `nix flake check`.
|
|
* For non-flake users, you can do the same with `nix-build tests/ -A libTestPkg` or `nix build -f tests/ libTestPkg`.
|
|
|
|
The derivation output should be successfully built if all of the tests in the suite passes.
|
|
Otherwise, it should fail and you'll have to see the build log containing all of the tests that failed.
|
|
|
|
On another note, there is a quicker way of checking the test suite with `nix eval -f tests lib` (or `nix-instantiate --eval --strict tests/ -A lib`) where it contains the raw test data which is useful if you don't want to essentially build a new derivation each time.
|
|
It is also quicker to eyeball results in this way especially if you're always working with the tests anyways.
|
|
|
|
[#development-website]
|
|
=== Website
|
|
|
|
This project also has a website set up with https://gohugo.io/[Hugo].
|
|
The files that you need to see are in link:./docs[./docs] directory.
|
|
|
|
* For flake users, you can build the website with `nix build .#website`.
|
|
* For non-flake users, you can do the same with `nix-build docs/`.
|
|
|
|
There is also a dedicated development environment placed in `docs/shell.nix` but this should be a part of the primary development environment already.
|
|
You can enter it with `nix develop .#website` or `nix-shell docs/`.
|
|
|
|
Just take note that the website also requires the NixOS options which comes in a JSON file.
|
|
This should be already taken care of in the package definition of the website but otherwise it is something that you'll have to be aware of.
|
|
|
|
The more important task to developing this part of the project is continuously getting feedback from it.
|
|
You can do so but
|
|
|
|
|
|
[#goals-and-non-goals]
|
|
== Goals and non-goals
|
|
|
|
As a Nix project, wrapper-manager-fds aims for the following goals.
|
|
|
|
* Create an ecosystem of creating them wrappers, mainly through its library set and the module environment.
|
|
|
|
* Make creating wrappers ergonomic for its users.
|
|
Not necessarily user-friendly but it should easy enough to get started while allowing some flexibility, yeah?
|
|
|
|
* Make a nice environment for creating custom wrappers which is already quite possible thanks to the heavy lifting of the nixpkgs module system.
|
|
|
|
|
|
[#faq]
|
|
== Frequently asked questions (FAQ)
|
|
|
|
[qanda]
|
|
Is this compatible with the original wrapper-manager?::
|
|
Nope.
|
|
It is a reimagining with a completely different way of using it so it won't be fully compatible with it from the start.
|
|
|
|
Why reimplement this anyways?::
|
|
For funsies and also because there are some things I find not so great with using the project.
|
|
https://github.com/viperML/wrapper-manager/tree/307eb5c38c8b5102c39617a59b63929efac7b1a7[As of this writing], using wrapper-manager to simply create wrappers anywhere is a pain.
|
|
|
|
Why not just incorporate the wanted changes into the original implementation?::
|
|
While it could be done, there will be some unwanted major changes into the project which would cause inconvenience to its users anyways so it isn't a good idea.
|
|
|
|
Can't you just create a wrapper with `pkgs.makeWrapper` and such from nixpkgs?::
|
|
Yeah, you can.
|
|
There's nobody stopping you from doing so and surely there's no hitman preparing to assissinate right behind you as you about to deny wrapper-manager-fds and smugly type `make` in `makeWrapper`.
|
|
In fact, wrapper-manager uses `makeWrapper` as the main ingredient.
|
|
Just think of wrapper-manager as a declarative version of that among the bajillion ways of making wrappers in the Nix ecosystem.
|
|
+
|
|
As an additional point, there are still use cases for it even with a simple `pkgs.writeShellScriptBin`.
|
|
In fact, if you have a situation like say having to create a one-off wrapper script to be added in a NixOS system, you can simply do the following:
|
|
+
|
|
[source, nix]
|
|
----
|
|
let
|
|
ytdlpAudio = pkgs.writeScriptBin "yt-dlp-audio" ''
|
|
${pkgs.yt-dlp}/bin/yt-dlp --config-location "${../../config/yt-dlp/audio.conf}" $@
|
|
'';
|
|
in
|
|
{
|
|
environment.systemPackages = [ ytdlpAudio ];
|
|
}
|
|
----
|
|
+
|
|
BAM!
|
|
No need for wrapper-manager!
|
|
|
|
Why use the module system?::
|
|
Because screw you, that's why!!!
|
|
Am I stupid and lazy for basically using a battle-hardened configuration system library such as nixpkgs module system? footnote:[The answer is yes to both!]
|
|
+
|
|
Seriously though, the main reason is pretty simple: it is quite established and a battle-hardened part in the Nix ecosystem.
|
|
It has gone through the test of time and the numerous 339 users of the entire Nix ecosystem are quite adamant in the declarative aspect of the Nix thingy.
|
|
So... why not use it.
|
|
|
|
Any problems (and impending explosions) when using this project?::
|
|
As far as I can tell, not much (especially explosions) but there are a few caveats you need to know.
|
|
Just know this is something the author is trying to resolve.
|
|
+
|
|
--
|
|
* wrapper-manager-fds is not great at handling double wrappers.
|
|
It just naively wraps a package and goes on its merry way.
|
|
|
|
* wrapper-manager-fds doesn't handle any replacement for the related files very well.
|
|
This is especially noticeable in large desktop-adjacent packages such as Inkscape, Firefox, and Blender with a bunch of plugins and whatnot where they have their own wrappers.
|
|
This means you cannot set `programs.NAME.package` or something similar with it.
|
|
--
|
|
|
|
|
|
[#acknowledgements]
|
|
== Acknowledgements
|
|
|
|
I found a bunch of things for inspiration (READ: to steal ideas from).
|
|
Here's a list of resources I've found.
|
|
|
|
* The original source of the reimagining, of course: https://github.com/viperML/wrapper-manager[wrapper-manager].
|
|
|
|
* https://github.com/NixOS/rfcs/pull/75[Nix RFC 75] which also comes https://github.com/NixOS/nixpkgs/pull/85103[with its implementation and discussion around what works and whatnot].
|
|
|
|
* https://discourse.nixos.org/t/pre-rfc-module-system-for-wrappers-in-nixpkgs/42281[This NixOS Discourse post loudly thinking about the same idea.]
|
|
|
|
|
|
[#copyright]
|
|
== Copyright
|
|
|
|
This project is licensed under MIT License (SPDX identifier: https://spdx.org/licenses/MIT.html[`MIT`]).
|
|
Just see link:./LICENSE[`./LICENSE`] for full text and details and whatnot.
|
|
|
|
The documentation (except for the code examples), on the other hand, is licensed under https://www.gnu.org/licenses/fdl-1.3.txt[GNU Free Documentation License] v1.3 only with no "Invariants" section (SPDX identifier: https://spdx.org/licenses/GFDL-1.3-no-invariants-only[`GFDL-1.3-no-invariants-only`])
|
|
You can see either the link or link:./docs/LICENSE[`./docs/LICENSE`] for more info.
|
|
The code examples, similar to the project codebase, are licensed under MIT with the same conditions apply and all that jazz.
|