The idea is to build something to configure NixOS graphically. To me, this means: managing the installed software packages, and managing the enabled services, as well as updating and garbage-collecting. For the moment, I’m focusing on a solution for a declarative, global configuration; so for the moment it’s not calling nix-env
and it’s not supporting home-manager
.
The goal is not to make all of NixOS accessible via a GUI, and not give an alternative to writing Nix expressions for your configuration. Instead, this is a project to explore how far you can get graphically after installing NixOS (which — in the future — might be possible via a GUI installer as well).
Since the NixOS configuration is very “free-form”, I have to make some assumptions about the structure of your configuration.nix
file, as such:
- You have two additional
.nix
files, referenced from theimports
section in yourconfiguration.nix
:packages.nix
andservices.nix
packages.nix
is a flat list of packagesservices.nix
is a list of service options, likeservices.xserver.enable = true
.
In nixos-manager, you can mark packages for installation. They will be added to your local copy of packages.nix
. You can then trigger a nixos-rebuild from inside nixos-manager, which copies your local installation to the global installation inside /etc/nixos/nixos-manager/packages.nix
. Same for configuring services and services.nix
.
To gather service definitions, nixos-manager downloads and parses https://nixos.org/nixos/options.json. This way, the service definitions might not accurately reflect your system configuration, but I just found no other way to gather the definitions, see this Discourse thread.
Please recommend to me another platform where I can upload this, preferably lossless as the source mkv that I have.
Have you seen hnix? Why don’t you parse your you Nix files with
I’d love to! But sadly and ironically, it’s currently broken in nixpkgs. I’m waiting for someone to repair it, as I don’t have the knowledge to do that.
I’m using Haskell as the language of choice, simply because hnix
is available and allows me to easily parse and serialize the relevant Nix configuration files. The GUI is made via gi-gtk-declarative
, which serves me well and is pretty stable.
Yes, that’s possible. The files that nixos-manager uses shouldn’t be edited by hand, but you can configure services and packages the regular way as well, by editing configuration.nix
. Thus, nixos-manager is just an enhancement.
The list of packages only lists packages installed by nixos-manager, not globally installed ones. How come?
The simple reason is: I haven’t gotten to that part yet, and my Nix knowledge is so limited I’d have to ask how do that first.
nixos-manager isn’t in nixpkgs yet, so you’ll have to build it using…Nix!
nix-build -I nixpkgs=channel:nixos-unstable
The channel argument is necessary in case you’re not on nixos-unstable
.
After building it (see above), you have to tell home-manager to read nixos-manager’s configuration files. To do that, open your ~/.config/nixpkgs/home.nix
file and insert the following somewhere inside the main attribute set:
imports = [ ./hm-extra-services.nix ./hm-extra-packages.nix ]; manual.json.enable = true;
nixos-manager, when run in home-manager mode, will write these extra files. The second line enables JSON export of the available options in home-manager, which nixos-manager reads to generate the configuration UI.
To run nixos-manager in home-manager mode, simply run it with the --home-manager
argument. For example, if you built it with Nix, run:
result/bin/nixos-manager --home-manager
If you’ve built it with cabal
(for example, to try it out after changing the code), run:
cabal v2-run nixos-manager -- --home-manager
After building it (see above), you have to tell NixOS to read nixos-manager’s configuration files. To do that, open your /etc/nixos/configuration.nix
file and look for a line containing imports = …
. Usually it looks something like this:
{
# …
imports =
[ # Include the results of the hardware scan.
./hardware-configuration.nix
];
# …
}
So imports
contains an array of Nix files. You can extend this array by just listing more files, separated by spaces. To use NixOS manager, extend the list as such:
{
# …
imports =
[ # Include the results of the hardware scan.
./hardware-configuration.nix
./nixos-manager/services.nix
./nixos-manager/packages.nix
];
# …
}
nixos-manager will create these two files when you apply changes.
- The frontend for
nixos-rebuild
works. It supports--upgrade
and--rollback
. nix-collect-garbage
is also supported, supporting the-d
flag.- Rebuilding copies
packages.nix
andservices.nix
to/etc/nixos/nixos-manager
. Without these files being included in yourconfiguration.nix
, they’re worthless, though. - Configuring services works, with some minor quirks.
- Trying packages works, and installing/uninstalling too. The
packages.nix
will be updated accordingly.
- nixos-manager is written in the Haskell Language. You should be proficient with this language. I can’t give a full recommendation list for learning it (can anyone reading this?). It’s really worth it though. Some books are
- I’m using the GTK toolkit and specifically gi-gtk-declarative as a declarative approach to writing GTK applications. The documentation is here. A good blog post by the author is Declarative GTK+ Programming with Haskell.
Each module has haddock documentation. Finding information about the code just from that might be difficult though, so let me give you a short overview:
- Each of the tabs you see (notebook pages, in GTK-Speak) has a submodule. There’s
NixManager.Admin
,NixManager.Services
andNixManager.Packages
, respectively. - Inside each such submodule you have modules
Event
,Update
andView
.Event
contains the even data type for the submodule (which is then embedded inNixManager.ManagerEvent
)Update
contains the update handler (a function receiving the current state and an event and returns a new state, as well as an event and IO side-effects)View
contains thegi-gtk-declarative
classes for the notebook page.State
contains the state corresponding to the subsystem
- When starting a process, such as the rebuild process, we cannot easily run it in the background and emit an event when it’s finished (at least I don’t know how to do that comfortably with
gi-gtk-declarative-app-simple
). Instead, we are spawning the process (in the background, mind you), then wait for a small amount of time (which doesn’t block the GUI, fortunately) and then emit a “watch” event, which does the same thing, until the process signals completion. It sounds hacky, and it is, but it’s not that bad.
- nix42b — is another user-friendly Nix package manager, also written in Haskell. It doesn’t seem to be actively maintained anymore.