How to set up a GTK3 theme, thats not in the nix pkgs?

Im a newbie and have a hard time figuring out how to do it. Saw a GTK3 theme, liked it and have no clue how to apply it to the system as it is not in the nix pkgs.

There are two ways, one simple, manual way and one using nix.

If you just want to get it working, download the theme zip and extract it to ~/.local/share/themes/<theme-name>. You’ll be able to configure gtk to use it as usual.

If you want to install it declaratively using nix, you’ll have to write a package for it. Nix makes writing packages downstream, without interacting with the upstream project at all, really easy.

Assuming you use a configuration.nix and not flakes, I’d suggest you do something like this:

  1. Create a new directory called pkgs in your /etc/nixos directory, adjacent to your configuration.nix.
  2. Write a default.nix file in this new directory, containing something like this:
# /etc/nixos/pkgs/default.nix
{pkgs, ...}: let
  callPackage = pkgs.callPackage;
in {
  nixpkgs.overlays = [(final: prev: {
    mypackages = {
      gtk-theme = callPackage ./gtk-theme.nix {};
    };
  })];
}
  1. Write a gtk-theme.nix in the same directory, adjacent to the default.nix. As you see above, we’ll be running the callPackage function on it. This is the function typically used to build nix packages using the various things available in nixpkgs.
    Without knowing what theme you want to package, I can’t help much with this file. Here’s an example from the nixpkgs repo though: nixpkgs/default.nix at 85bcb95aa83be667e562e781e9d186c57a07d757 · NixOS/nixpkgs · GitHub
    The crux here is that the extracted theme is installed to $out/share/themes - NixOS automatically places the share/themes directories of all installed packages in the profile-wide share directory to make them available.
    Obviously, you can name the file whatever you want. Just make sure to change the ./gtk-theme.nix in the default.nix to whatever you call the file.
  2. Import this pkgs/default.nix file in your main configuration.nix, and use your new package:
# /etc/nixos/configuration.nix
{pkgs, lib, config, ...}: {
  imports = [
    ./pkgs
  ];
  
  environment.systemPackages = with pkgs; [
    mypackages.gtk-theme
  ];

  # This next stuff is technically not necessary if you're going to use
  # a theme chooser or set it in your user settings, but if you go
  # through all this effort might as well set it system-wide.
  #
  # Oddly, NixOS doesn't have a module for this yet.
  environment.etc."xdg/gtk-2.0/gtkrc".text = ''
    gtk-theme-name = "<gtk-theme>"
  '';

  environment.etc."xdg/gtk-3.0/settings.ini".text = ''
    [Settings]
    gtk-theme-name = <gtk-theme>
  '';
}

Substituting your theme’s name for <gtk-theme>, of course. If you like, you can change the package name to the theme’s name too, just make sure to do the same in pkgs/default.nix.

:+1:, just two nitpicks:

NixOS automatically places the profiles’ /share directory into XDG_DATA_DIRS (e.g. /run/current/system/sw/share for environment.systemPackages) but it does not link installed packages’ share/ directories there. Though, confusingly, some desktop environments do this but it is not the default. Coincidentally, NixOS does link share/themes directory so it will still work in this case.

/etc/xdg goes to XDG_CONFIG_DIRS and NixOS already sets that.

1 Like

Thanks! Updated my comment for posterity :slight_smile:

Thank you @TLATER for fast response. Im trying to get this theme: Goldy-Dark-GTK - pling.com. Doing it declaratively and I am at step 3 right now. Tried understanding what is in that repo, but I think its to hard for me to comprehend what to do exactly inside the gtk-theme.nix file?

Sure! I think this is the simplest possible package, with annotations:

# /etc/nixos/pkgs/gtk-theme.nix

# These are the inputs to our function (yes, this is a function).
#
# `callPackage` will automatically fill in these arguments with
# anything that is available in `pkgs`, so that includes all packages,
# as well as some build utilities and library functions.
{
  stdenvNoCC,
  fetchFromGitHub,
  gtk-engine-murrine,
}:
# This function (stdenvNoCC.mkDerivation) is the "build a package for
# me please" function from nixpkgs.
#
# It's an enhanced version of a nix builtin function for building
# derivations (read: packages), and provides some basic utilities that
# you usually need (e.g. `cp` and `mkdir`).
#
# I'm using the NoCC variant of stdenv, which doesn't include a C
# compiler, and therefore takes less time to download.
stdenvNoCC.mkDerivation {
  # Just the package name, this is used for the file name in
  # `/nix/store` and primarily useful for debugging or displaying
  # info. It's also mandatory.
  pname = "goldy-plasma-themes";
  # The version of the package; In this case, the project isn't
  # versioned, so the recommended practice is to use unstable-<date>.
  version = "unstable-2023-06-09";

  # This downloads the theme directly from GitHub instead of the
  # distribution site you linked.
  #
  # While I feel a bit guilty about it, because this doesn't tick the
  # donation thing, the distribution site doesn't seem to maintain
  # permalinks and therefore the hash will randomly change, which will
  # cause you headaches.
  #
  # That site also very likely tries to prevent automated downloads,
  # since those won't create ad revenue, so it'd be a headache
  # anyway. Downloading the theme directly from GitHub works better
  # for this.
  #
  # If you like the theme enough, I'd suggest doing a direct donation
  # somehow.
  src = fetchFromGitHub {
    owner = "L4ki";
    repo = "Goldy-Plasma-Themes";
    # This is the commit of the theme we download.
    rev = "8f1cb24f22b226632572b222e619922a70d3ee5a";
    # Nix will check this hash every time it downloads the theme, to make sure GitHub has not
    # sent you a virus instead of the theme (or that the download has not somehow become
    # corrupted).
    hash = "sha256-671/3gqna05zOqqNlg8BBo1hUFzAIZWofSwyRYyJ0k8=";
  };

  # This theme uses the murrine engine, so we need to add it here.
  propagatedUserEnvPkgs = [gtk-engine-murrine];

  # This is the actual process for "installing" the files into the
  # package. It's basically just a bash script.
  installPhase = ''
    # 1. We create the $out directory, which is where nix will pick up our
    #    package contents from.
    # 2. We then copy the GTK theme into the directory it belongs in
    #   - I also rename the directory so it doesn't have spaces in
    #     it, figure that will cause issues. The zip from that
    #     distribution site you linked to does the same.
    mkdir -p $out/share/themes/
    cp --archive 'Goldy GTK Themes' $out/share/themes/Goldy-Dark-GTK
  '';
}

Compared to the one I linked previously it lacks:

  • The multiple fetchurls - in this case we only need one source.
  • sourceRoot - with only one source we don’t need to tell nix what our source root is.
  • meta - we don’t need metadata for a simple downstream package, but usually it’s mandatory upstream.
  • preInstall/postInstall - these are “hooks” that are useful if you want to override a package - again, mostly useless for a simple downstream package, but very useful upstream.

The theme name is Goldy-Dark-GTK, for reference.

Thank you again @TLATER. Did everything according to your instructions and tried to rebuild the system and I get an error saying:
A definition for option environment.etc."xdg/gtk-2.0/gtkrc".source' is not of type path’. Definition values:
- In `/etc/nixos/configuration.nix’:
‘’
gtk-theme-name = “Goldy-Dark-GTK”
‘’

Ah, my bad, the source should be text.

Build the system, but it seems the theme is not applied to it. Any ideas?

Hmm, my immediate thoughts are one of these might be the issue:

  • Do you set a different theme in ~/.config/gtk-* so it overrides the system-wide theme?
  • Did you restart your DE? It won’t magically switch when you switch.

If neither of those is the problem, maybe check with e.g. themechanger to see if the theme is actually picked up correctly?

I’m unsure what could go wrong otherwise, journalctl --boot and journalctl --user --boot after a fresh boot might give some hints.

Checked the gtk files, the themes there are correct after rebooting noting changed. Themechanger hints that the theme is possibly not picked up correctly. The preview icon is a bit grayed out and has a question mark on it. Also the boot logs say gtk-icon-size is not a valid property name. I put full logs in my git repo: https://github.com/Solandis/nix-logs
P.S. birž just means june :smiley: