mirror of
https://github.com/foo-dogsquared/nix-module-wrapper-manager-fds.git
synced 2025-01-30 22:57:58 +00:00
wrapper-manager-fds/docs: update README
Rather migrate it as part of the documentation content.
This commit is contained in:
parent
7cd03e86a7
commit
4c8f811cab
470
README.adoc
470
README.adoc
@ -1,470 +0,0 @@
|
||||
= 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.
|
||||
|
||||
.Creating a custom Firefox desktop entry launching a custom profile
|
||||
[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`.
|
||||
|
||||
.Installing yt-dlp with custom variants of it inside of a home-manager configuration
|
||||
[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`.
|
||||
|
||||
As an additional note, it is recommended to use something like direnv with `use flake` or `use nix` depending on your personal preferences to use flake or not.
|
||||
|
||||
Take note there is a `Makefile` full of commands intended for easily interacting with the project but it is heavily assumed you're in the development environment of the project.
|
||||
|
||||
[#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 simply with the following commands:
|
||||
|
||||
* For flake users, `nix develop --command hugo -s ./docs serve`.
|
||||
* For non-flake users, `nix-shell docs --command hugo -s ./docs serve`.
|
||||
* If you're using `Makefile` of this project, `make docs-serve`.
|
||||
|
||||
[#development-nix]
|
||||
=== Nix environment
|
||||
|
||||
As for developing the environment with Nix itself, it is very much preferred to make wrapper-manager-fds work with non-flake setups.
|
||||
This also includes the workflow of the development itself for the purpose of easier time bootstrapping wrapper-manager-fds.
|
||||
|
||||
Due to the unfortunate situation with flakes as an experimental feature, it is more like a second-class citizen in terms of support.
|
||||
This is because it is pretty easy to make a flake with non-flake tools compared to vice versa. footnote:[flake-compat is great and all but it holds back wrapper-manager-fds in making it easy to bootstrap if we rely on it.]
|
||||
|
||||
Here's an exhaustive guidelines that you have to keep in mind when developing related files within the project:
|
||||
|
||||
* This project uses https://calver.org/[calendar versioning] following software versioning of the upstream.
|
||||
The unstable branches are basically deployed with development versions of this project.
|
||||
|
||||
* Only the current stable branch and the unstable branch of NixOS is supported.
|
||||
|
||||
* The preferred default nixpkgs branch at development is `nixos-unstable`.
|
||||
|
||||
* There shouldn't be any user consumables that requires anything from the npins sources.
|
||||
|
||||
|
||||
[#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.
|
1
README.adoc
Symbolic link
1
README.adoc
Symbolic link
@ -0,0 +1 @@
|
||||
docs/content/en-US/project-overview.adoc
|
474
docs/content/en-US/project-overview.adoc
Normal file
474
docs/content/en-US/project-overview.adoc
Normal file
@ -0,0 +1,474 @@
|
||||
---
|
||||
title: Project overview
|
||||
---
|
||||
= 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.
|
||||
|
||||
.Creating a custom Firefox desktop entry launching a custom profile
|
||||
[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`.
|
||||
|
||||
.Installing yt-dlp with custom variants of it inside of a home-manager configuration
|
||||
[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`.
|
||||
|
||||
As an additional note, it is recommended to use something like direnv with `use flake` or `use nix` depending on your personal preferences to use flake or not.
|
||||
|
||||
Take note there is a `Makefile` full of commands intended for easily interacting with the project but it is heavily assumed you're in the development environment of the project.
|
||||
|
||||
[#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 simply with the following commands:
|
||||
|
||||
* For flake users, `nix develop --command hugo -s ./docs serve`.
|
||||
* For non-flake users, `nix-shell docs --command hugo -s ./docs serve`.
|
||||
* If you're using `Makefile` of this project, `make docs-serve`.
|
||||
|
||||
[#development-nix]
|
||||
=== Nix environment
|
||||
|
||||
As for developing the environment with Nix itself, it is very much preferred to make wrapper-manager-fds work with non-flake setups.
|
||||
This also includes the workflow of the development itself for the purpose of easier time bootstrapping wrapper-manager-fds.
|
||||
|
||||
Due to the unfortunate situation with flakes as an experimental feature, it is more like a second-class citizen in terms of support.
|
||||
This is because it is pretty easy to make a flake with non-flake tools compared to vice versa. footnote:[flake-compat is great and all but it holds back wrapper-manager-fds in making it easy to bootstrap if we rely on it.]
|
||||
|
||||
Here's an exhaustive guidelines that you have to keep in mind when developing related files within the project:
|
||||
|
||||
* This project uses https://calver.org/[calendar versioning] following software versioning of the upstream.
|
||||
The unstable branches are basically deployed with development versions of this project.
|
||||
|
||||
* Only the current stable branch and the unstable branch of NixOS is supported.
|
||||
|
||||
* The preferred default nixpkgs branch at development is `nixos-unstable`.
|
||||
|
||||
* There shouldn't be any user consumables that requires anything from the npins sources.
|
||||
|
||||
|
||||
[#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.
|
||||
Plus it also justifies me implementing a bunch of features that would otherwise be deemed inconsistent with the project.
|
||||
|
||||
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.
|
@ -1,4 +0,0 @@
|
||||
---
|
||||
title: Quick breakdown
|
||||
---
|
||||
include::../../../README.adoc[]
|
@ -1 +1 @@
|
||||
{{ with .GetPage "/quick-breakdown" }}{{ .Render "single" }}{{ end }}
|
||||
{{ with .GetPage "/project-overview" }}{{ .Render "single" }}{{ end }}
|
||||
|
Loading…
Reference in New Issue
Block a user