Setting the user profile image under Gnome

tl;dr: Can anyone help with a working code snippet that allows for the declarative setting of the user profile image under Gnome?

I am trying to declaratively set the user profile image under Gnome. I’ve read a number of postings which all say that it should be possible by creating a file called .face (png or jpg file) in the home directory. Some relevant post include:

I have done this using the following code in home-manager:

home.file.".face" = {
    source = .../assets/pics/face.png;
  };

This successfully creates the .face file but there is no change to the user profile. Logging out or restarting does not impact the session.

Further research shows that the file located at /var/lib/AccountsService/users/user needs to point to the profile image. However the file does not, instead its contents points to a different file:

[User]
Session=
Icon=/var/lib/AccountsService/icons/user
SystemAccount=false

Can anyone help with a working code snippet that allows for the declarative setting of the user profile image or code that how allow me to replace the image file pointer referenced at /var/lib/AccountsService/users/user?

Thanks in advance.

1 Like

I’ve accomplished this by having a script run before the display manager. This script tries to either add or update the profile image in the user’s config file.

@jakehamilton, thank you for the pointer. I have tried to apply your suggestion by creating a separate function with your code. For the purpose of aiding my understanding I stripped out a few variables and hard-coded some values. The function builds with no errors when I do a nixos-rebuild swithch --flake .# but there is no effect on the image. Again I tried restarting the machine just in case caches needed to be flushed but there was no success. Would you please be able to cast an eye over the following code. It should be straight forward as it is a direct clone of your code, with the exception that a few variables have been hard coded:

{ config, lib, pkgs, ... } :

{
  systemd.services.orion-user-icon = {
    before = ["display-manager.service"];
    wantedBy = ["display-manager.service"];
  
    serviceConfig = {
      Type = "simple";
      User = "root";
      Group = "root";
    };
  
     script = ''
       config_file=/var/lib/AccountsService/users/orion
         icon_file=/home/orion/Pictures/face.png
  
         if ! [ -d "$(dirname "$config_file")"]; then
           mkdir -p "$(dirname "$config_file")"
         fi
  
         if ! [ -f "$config_file" ]; then
           echo "[User]
           Session=gnome
           SystemAccount=false
           Icon=$icon_file" > "$config_file"
         else
           icon_config=$(sed -E -n -e "/Icon=.*/p" $config_file)
  
           if [[ "$icon_config" == "" ]]; then
             echo "Icon=$icon_file" >> $config_file
           else
             sed -E -i -e "s#^Icon=.*$#Icon=$icon_file#" $config_file
           fi
         fi
        '';
      };
  
}

As mentioned above, the code builds with no errors but does not seem to get executed. I am of course importing it via “imports” in my configuration.nix file. Thank you for your help.

For anyone else looking for a working solution to this issue, I have implemented the following hack. It’s ugly but it works. Just add the following to your configuration.nix file:

{ config, lib, pkgs, ... } :

{
  system.activationScripts.script.text = ''
    cp /home/orion/pics/face.png /var/lib/AccountsService/icons/orion
        '';
  
}

Make sure to change the file location and user name to meet your needs.

1 Like

Seems not to be working anymore on nixos 23.11

You have to write the users/ file too:

  system.activationScripts.script.text = ''
    mkdir -p /var/lib/AccountsService/{icons,users}
    cp /nix/persist/home/n0rad/Pictures/face.png /var/lib/AccountsService/icons/n0rad
    echo -e "[User]\nIcon=/var/lib/AccountsService/icons/n0rad\n" > /var/lib/AccountsService/users/n0rad
  '';

Note that if the folder holding the picture is a home.persistence mount done with impermanence, you have to give the source path because the script run before the path is mounted

I tried your method on a few computers, and it worked on some, and it did not on others.

It came down to:

  • permissions
  • image has to be PNG

This was the only way I could make it consistent.

    system.activationScripts.script.text = ''
      mkdir -p /var/lib/AccountsService/{icons,users}
      cp ${user-settings.user.home}/dev/nix/nixos/modules/desktops/gnome/.face /var/lib/AccountsService/icons/MY_USER_NAME
      echo -e "[User]\nIcon=/var/lib/AccountsService/icons/MY_USER_NAME\n" > /var/lib/AccountsService/users/MY_USER_NAME

      chown root:root /var/lib/AccountsService/users/MY_USER_NAME
      chmod 0600 /var/lib/AccountsService/users/MY_USER_NAME

      chown root:root /var/lib/AccountsService/icons/MY_USER_NAME
      chmod 0444 /var/lib/AccountsService/icons/MY_USER_NAME
    '';

In case others come looking for something similar.

1 Like