I adore tinkering with my machine, trying new tools, extensions, themes, and ideas. When I was younger, it was just a way to learn. Now, it’s a way for me to refine my workspace and bring myself small joys.
While tinkering can be fun, it can be a chore to set up a new machine, keep configurations up to date between machines, or even just remember to keep up to date backups.
What about when we want to configure a whole desktop environment? While NixOS offers configuration settings like services.gnome.gnome-keyring.enable
for system-wide features, there’s a lack of knobs when you want to set things like user-specific GNOME ‘Favorite Apps’ or extensions.
Let’s explore a useful addition to your NixOS configuration: Home Manager and its dconf
module.
This article uses Nix flakes which is an experimental feature. You may need to set this in your configuration:
Getting Home Manager set up
Home manager a tool from the Nix ecosystem that helps you take the declarative ideals of Nix/NixOS and apply them to your user’s home directory ($HOME
). It plugs in (as a NixOS module) into an existing NixOS configuration, or can be installed on different Linux as a user service.
In order to make some parts of your configuration declarative, Home Manager might take control of certain file paths, or set various options in things like dconf
.
Because of its job, Home Manager can make updating your configuration feel more error-prone, but don’t fear: Use a VCS like git
to store your configuration. If your Home Manager setup breaks or acts strange for any reason, check the service status via systemctl status home-manager-$USER
and journalctl -u home-manager-$USER.service
. When in doubt, roll back your configuration and delete any files the errors are complaining about.
In our example, the user is named
ana
, and the machine is namedgizmo
.
In your Nix flake, add the input for Home Manager and ensure it follows the nixpkgs
you’re using:
If you don’t already have GNOME configured, you can do that via a nixosModule
like this:
Next, add a nixosModule
that enables home-manager
:
I create a nixosModule
for each of my users (you may have another way, feel free to do that):
You can enable Home Manager for your user like this:
Now create the home.nix
referenced above:
Before enabling, ensure your nixosConfiguration
has these modules, as well as home-manager.nixosModules.home-manager
:
With that, you should be able to switch into the new configuration:
Validate it worked by reviewing the output:
If you see errors, dig deeper via journalctl -u home-manager-ana.service
.
Find out more about building Linux systems using Nix
Declaratively configuring GNOME
There are a lot of knobs to set in GNOME.
GNOME breaks down into having GTK3/4 (which has UI, icon, and cursor themes), as well as an group of fairly tightly integrated components which are primarily configured by dconf
, which most folks configure via gnome-settings
or the settings panels of the relevant applications.
If you’re curious and wanted to watch how/if various dconf
settings get changed when doing things, you can ‘watch’ while you click around an application:
If it’s too noisy, you can limit what you see by changing the /
to a selector, for example /org/gnome/desktop/
.
Home Manager offers a dconf
module, which we can use to declaratively set these values.
GTK3/GTK4 cursor, icon, and window themes
To set the GTK icon theme, first search for a theme. this search or this one can help you find already packaged themes. You can click the “Source” button on any of those packages to see the expression used to package it, just in case you end up needing to make your own.
Here are the relevant settings, with some examples of what I’ve found that I like:
Want to set the GNOME Shell theme? We do this below after discussing
dconf
a bit more.
Finding the name
field for a given package can be a bit inconsistent. 😔
Most of the time, you can guess it, or copy it from what shows up when you check with gnome-tweaks
. Usually, you can find the package repository via the “Homepage” link on the searches listed above, or in the expression via the meta.homepage
(example) or src
fields (example). From there you can usually find some listing of the theme name (example).
To use a theme not already packaged, you’ll need to take a good starting point, edit it, then add your custom package to your flake:
Once done, you should be able to use it by setting, for example, gtk.theme.package = pkgs.my-artisanal-theme
.
Setting GNOME options
As mentioned above, most GNOME settings exist in dconf
. Run dconf watch /
and set whatever option you’re looking to declaratively persist, and observe the output:
Here’s what I see when I run gnome-settings
and visit the ‘Appearance’ pane, then in ‘Style’ click between ‘Light’ and ‘Dark’.
Let’s try setting those from the command line an observing the gnome-settings
window change:
Using this information, we can add this to the user configuration:
After a bit of tweaking, you might end up with something like this:
GNOME Extensions
Once user extensions are enabled, extensions can be added to the home.packages
set then enabled in dconf.settings."org/gnome/shell".enabled-extensions
. After, they can be configured just as any other GNOME option as described just above.
A GNOME Shell theme can be picked like this:
Troubleshooting
I made a bunch of changes then ran
nixos-rebuild switch
, but some things didn’t change?
Log out and log back in. I found some things just didn’t set themselves until you did!
I accidentally altered GNOME settings which I’d set via Home Manager, and they aren’t changing back on a
nixos-rebuild switch
?
It is possible to change dconf
values once set via Home Manager, if this happens and nixos-rebuild switch
isn’t causing a change, you may need to restart the home-manager
service with systemctl restart home-manager-$USER
. If that fails, make a change (for example touch
) your user home configuration first.
Some changes I made are not reflecting when I
nixos-rebuild switch
?
Check systemctl status home-manager-$USER
and ensure the service started successfully, if not, dig in with journalctl -u home-manager-$USER
and make sure to carefully read the error.
The setting I want isn’t tracked by Home Manager or
dconf
?
It might be complicated. You can try seeing if the program creates an entry in your XDG directories, such as ~/.config
or ~/.cache
. If so, you can often provision content into the file with the home.file
option. Please note this will make the file unwritable, which may impact some programs.
Conclusion
Once various all of your preferred settings are persisted, it becomes straightforward to share key settings and extensions between multiple machines, or even architectures. By taking a little bit more time when configuring our system, we can avoid having to do it again.
Using these strategies I was able to have 3 different machines (an x86_64 desktop workstation, an x86_64 laptop, and a headed aarch64 server) with the same settings, and keep them all consistent so I can spend more time doing what I enjoy (tinkering) instead of what I don’t (re-configuring machines).
If you’re looking for a complete home configuration, you can check out mine here.
Here’s what it looks like: