GDM Background Image and Theme

Hey, good evening, did anyone have any luck setting a custom GDM background image/theme? I’m a bit confused on how to even begin to approach this, I know I’ll probably have to override GDM as the stylesheets need to be patched for this to work but I have no idea on how to even begin this.

After messing around with the gnome-shell derivation I finally managed to get this working so for reference if anyone wants to customise their GDM Greeter as I did I’ll explain the steps I took, this should work without much modification for any theme that provides a gresource file and despite somethings feeling a bit “hacky” it works fine.

So first things first I decided to get the wallpaper going, ideally we want a derivation that properly sources the image and caches it accordingly. After snooping around for a bit I found this cool derivation nixpkgs uses to define standard system wallpaper, it works like a charm and I only hope this gets exposed to us as a builder. Just copy it and use any regular fetcher to fetch your wallpaper, this derivation won’t work with file paths.

After that I only patched gnome-shell’s source code to accept my wallpaper (providing a fallback colour as well just to be on the safe side):

diff --git a/data/theme/gnome-shell-sass/widgets/_screen-shield.scss b/data/theme/gnome-shell-sass/widgets/_screen-shield.scss
index 00c549a53..b5c0be683 100644
--- a/data/theme/gnome-shell-sass/widgets/_screen-shield.scss
+++ b/data/theme/gnome-shell-sass/widgets/_screen-shield.scss
@@ -66,7 +66,10 @@
 }

 #lockDialogGroup {
-  background-color: lighten(#2e3436, 8%);
+  background: @backgroundColour@ url(file://@backgroundPath@);
+  background-repeat: no-repeat;
+  background-size: cover;
+  background-position: center;
 }

 #unlockDialogNotifications {

Then just a very simple overlay for gnome-shell and badabingo your GDM will have a nice wallpaper:

nixpkgs = {
  overlays = [
    (self: super: {
      gnome3 = super.gnome3.overrideScope' (selfg: superg: {
        gnome-shell = superg.gnome-shell.overrideAttrs (old: {
          buildInputs = (old.buildInputs or []) ++ [
            # CHEEKY WALLPAPER DERIVATION HERE
          ];
          patches = (old.patches or []) ++ [
            (pkgs.substituteAll {
              backgroundColour = "#d94360";
              backgroundPath = wallpaper.gnomeFilePath;
              src = ./greeter-background.patch;
            })
          ];
        });
      });
    })
  ];
};

That should suffice if all you want is a nice wallpaper that can be easily replicated in multiple environments but I also wanted a theme so I went a bit further. First things first I needed to get a theme going, I decided to use materia-theme because it plays well with the material-shell, has a GDM theme already. and I think it looks better than the material-shell’s recommended theme So I first wrote a derivation to build the theme:

materia-theme = with pkgs; stdenv.mkDerivation rec {
  pname = "materia-theme";
  version = "30019245337751ac7e5296a58ca9fac7bdd7d61b";
  src = fetchFromGitHub {
    owner = "nana-4";
    repo = pname;
    rev = version;
      sha256 = "sha256-XOl0iREFPInvIr//a9PLLstZ6O9PfITvLOILNV0uwOg=";
    };
    nativeBuildInputs = [
      bc
      fontconfig
      gnome3.gnome-shell
      inkscape
      meson
      ninja
      nodePackages.sass
      optipng
    ];
    buildInputs = [ gnome3.gnome-themes-extra gdk-pixbuf librsvg wallpaper ];
    propagatedUserEnvPkgs = [ gtk-engine-murrine ];
    mesonFlags = [
      "-Dgnome_shell_version=${lib.versions.majorMinor gnome3.gnome-shell.version}"
    ];
    dontBuild = true;
  });

After I verified the derivation worked I patched materia-theme so it would take my wallpaper into account when generating the theme:

diff --git a/src/gnome-shell/sass/components/gdm/_screen-shield.scss b/src/gnome-shell/sass/components/gdm/_screen-shield.scss
index 8d0d1136..8e3afa00 100644
--- a/src/gnome-shell/sass/components/gdm/_screen-shield.scss
+++ b/src/gnome-shell/sass/components/gdm/_screen-shield.scss
@@ -73,7 +73,10 @@
   } 
  
   #lockDialogGroup { 
-    background-color: theme-color.$system; 
+    background: theme-color.$system url(file://@backgroundPath@); 
+    background-repeat: no-repeat; 
+    background-size: cover; 
+    background-position: center; 
     color: theme-color.$on-system; 
   } 
  
@@ -152,8 +155,10 @@ 
   } 
  
   #lockDialogGroup { 
-    background-color: theme-color.$system; 
-    background-repeat: repeat; 
+    background: theme-color.$system url(file://@backgroundPath@); 
+    background-repeat: no-repeat; 
+    background-size: cover; 
+    background-position: center; 
     color: theme-color.$on-system; 
   }

Added the patch to my materia-theme derivation just like I did to gnome-shell:

materia-theme = with pkgs; stdenv.mkDerivation rec {
  pname = "materia-theme";
  version = "30019245337751ac7e5296a58ca9fac7bdd7d61b";
  src = fetchFromGitHub {
    owner = "nana-4";
    repo = pname;
    rev = version;
      sha256 = "sha256-XOl0iREFPInvIr//a9PLLstZ6O9PfITvLOILNV0uwOg=";
    };
    nativeBuildInputs = [
      bc
      fontconfig
      gnome3.gnome-shell
      inkscape
      meson
      ninja
      nodePackages.sass
      optipng
    ];
    buildInputs = [ gnome3.gnome-themes-extra gdk-pixbuf librsvg wallpaper ];
    propagatedUserEnvPkgs = [ gtk-engine-murrine ];
    mesonFlags = [
      "-Dgnome_shell_version=${lib.versions.majorMinor gnome3.gnome-shell.version}"
    ];
    dontBuild = true;
    patches = [
      (pkgs.substituteAll {
        backgroundPath = wallpaper.gnomeFilePath;
        src = ./greeter-background.patch;
      })
    ];
  });

And then I just need to make an overlay that would take my theme derivation, compile its gresource file and place it in the gnome-shell’s $out/share folder as explained in the theme documentation. I think making this part of the build procress would be ideal but I wasn’t able to get this working so I decided the postInstall hook would be a good solution as well, albeit a bit more “hacky”:

nixpkgs = {
 config.allowUnfree = true;
 overlays = [
   (self: super: {
     gnome3 = super.gnome3.overrideScope' (selfg: superg: {
       gnome-shell = superg.gnome-shell.overrideAttrs (old: {
         buildInputs = (old.buildInputs or []) ++ [
         ];
         postInstall = (old.postInstall or "") + ''
           glib-compile-resources --target="$out/share/gnome-shell/gnome-shell-theme.gresource" --sourcedir="THEME\'S GRESOURCE FOLDER HERE" "THEME\'S GRESOURCE FILE HERE"
         '';
       });
     });
   })
 ];
};

Build that bad boy up and you should have a GDM session so fashionable it could be displayed in the Madrid Fashion Week.

Hi, NixOS noob here.

Can you clarify what your patches do exactly? Does your first “very simple overlay” solution change the login background, or just the desktop background?

I want to change the login background. In hopes that that’s what you’re doing, I tried following what you did, but it didn’t work.

I copy-pasted the following into /etc/nixos/configuration.nix:

nixpkgs = {
  overlays = [
    (self: super: {
      gnome3 = super.gnome3.overrideScope' (selfg: superg: {
        gnome-shell = superg.gnome-shell.overrideAttrs (old: {
          buildInputs = (old.buildInputs or []) ++ [
            # CHEEKY WALLPAPER DERIVATION HERE
          ];
          patches = (old.patches or []) ++ [
            (pkgs.substituteAll {
              backgroundColour = "#d94360";
              backgroundPath = wallpaper.gnomeFilePath;
              src = ./greeter-background.patch;
            })
          ];
        });
      });
    })
  ];
};

and ran nixos-rebuild switch, and got the error error: undefined variable 'wallpaper' at /etc/nixos/configuration.nix:103:34.

Also, the next line says src = ./greeter-background.patch. What is greeter-background.patch? Is it the diff you placed just above? And where should I place this file for this to all come together?

Any help? Can you condense your instructions down to minimal steps that someone who has never patched NixOS can follow?

DiCaius’s patch failed to apply, and I found why: _screen-shield.scss has changed from [1] to [2].

Good news, though! I have a new solution.

I found a feature request open asking for GNOME to support this very thing: Feature request: Make GDM background color and image configurable with gsettings. (#3877) · Issues · GNOME / gnome-shell · GitLab.

And they’ve uploaded a patch. And it works!

Instructions:

  1. Visit https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/3877, download gnome-shell_3.38.3-3ubuntu1_3.38.3-3ubuntu2.patch and move it to your /etc/nixos/ folder.
  2. Place the following in your /etc/nixos/configuration.nix:
nixpkgs = {
  overlays = [
    (self: super: {
      gnome = super.gnome.overrideScope' (selfg: superg: {
        gnome-shell = superg.gnome-shell.overrideAttrs (old: {
          patches = (old.patches or []) ++ [
            (pkgs.substituteAll {
              src = ./gnome-shell_3.38.3-3ubuntu1_3.38.3-3ubuntu2.patch;
            })
          ];
        });
      });
    })
  ];
};

services.xserver.desktopManager.gnome.extraGSettingsOverrides = ''
[com.ubuntu.login-screen]
background-repeat='no-repeat'
background-size='cover'
background-color='#777777'
background-picture-uri='file:///etc/nixos/background.jpg'
'';
  1. Adjust the above background-picture-uri to point to your background. (I put my background at /etc/nixos/background.jpg.)

The great thing about this patch is that it stores the settings in dconf/gsettings, which means that you don’t have to re-compile GNOME Shell every time you want to change your background. Just update your extraGSettingsOverrides and run nixos-rebuild switch` again.

If you’re bothered by having the word “Ubuntu” in your NixOS build, simply rename the settings in the patch.

1 Like

Sorry for the late reply I was busy solving a few things, the method here changes the login screen background, not the desktop. The wallpaper variable is a package with my wallpaper made using the nixpkgs derivation I linked in my original post and is not necessary, I just use ot because I like to have my wallpapers managed and sourced from GitHub when I need to migrate from one machine to the other, as for the issues with the patch, I believe I was running an older version of gnome (haven’t updated in a while) so your mileage may vary since there was a huge update in Gnome 40. I also may have messed it up a bit, as I mentioned I use a custom theme that I also wanted to apply to the login screen ao I may have mixed things up a bit. Thank you for improving my original solution with the improved patch, I’m currently running it as I’m updating to Gnome 40

Btw, the new patch worked like a charm. I still need to make some changes to get the custom theme going but the wallpaper is there.