Home-manager activation script to copy files (custom-fonts) fails with permission error on macOS

I wish to install a customised version of input mono fonts on macOS.

First, I tried

home.file."Library/Fonts/HomeManagerExtra".source = ../custom-fonts;

which successfully symlinked the custom fonts into the macOS fonts directory. But Font Book did not pick up the symlinked fonts. It did pick up the fonts specified in home.packages.

I observed that home-manager itself had copied, not symlinked, the fonts I had specified in home.packages. So I set out to instruct the home-manager to copy the custom-fonts through an activation script:

  home.activation = if pkgs.stdenv.isDarwin then 
    {
      copyExtraFonts = lib.hm.dag.entryAfter ["writeBoundary"] ''
       $DRY_RUN_CMD rm -rf $VERBOSE_ARG ~/Library/Fonts/HomeManagerExtra
       $DRY_RUN_CMD cp -r $VERBOSE_ARG ${../configs/fonts} ~/Library/Fonts/HomeManagerExtra
     '';
   } else { };

Note that I have set the script to be entered after writeBoundary, as specified in the home-manager manual.

The custom-fonts were copied successfully when the ~/Library/Fonts/HomeManagerExtra directory did not exist. However it failed on a second run with a permission error:

>> home-manager switch
/nix/store/1pjsk5hmq9daj80avfna3njzqdx3rxq9-home-manager-generation
Starting home manager activation
Activating checkFilesChanged
Activating checkLinkTargets
Activating writeBoundary
Activating copyExtraFonts
rm: cannot remove '/Users/jayesh/Library/Fonts/HomeManagerExtra/InputMono/InputMonoNarrow/InputMonoNarrow-BoldItalic.ttf': Permission denied
rm: cannot remove '/Users/jayesh/Library/Fonts/HomeManagerExtra/InputMono/InputMonoNarrow/InputMonoNarrow-ThinItalic.ttf': Permission denied
rm: cannot remove '/Users/jayesh/Library/Fonts/HomeManagerExtra/InputMono/InputMonoNarrow/InputMonoNarrow-ExtraLight.ttf': Permission denied
rm: cannot remove '/Users/jayesh/Library/Fonts/HomeManagerExtra/InputMono/InputMonoNarrow/InputMonoNarrow-MediumItalic.ttf': Permission denied
rm: cannot remove '/Users/jayesh/Library/Fonts/HomeManagerExtra/InputMono/InputMonoNarrow/InputMonoNarrow-Italic.ttf': Permission denied
...
There are 113 unread and relevant news items.
Read them by running the command 'home-manager news'.

Any clues on what is going wrong? I can’t think of a reason as to why home-manager does not have permission to remove-then-copy the custom-fonts, when it could happily copy the fonts from home.packages.

PS: Initially, the activation script did not have the rm command. Even in that case, the second run had failed because of lack of permission to cp.

Alright. I figured it out.

While executing the activation script, home-manager copied the files with read-only permissions for all, including the user themselves:

>> ls -ld ~/Library/Fonts/HomeManagerExtra/InputMono/InputMonoCondensed
dr-xr-xr-x  16 jayesh  staff  512 Jun 10 12:24 /Users/jayesh/Library/Fonts/HomeManagerExtra/InputMono/InputMonoCondensed


>> ls -l ~/Library/Fonts/HomeManagerExtra/InputMono/InputMonoCondensed/InputMonoCondensed-B*.ttf
-r--r--r--  1 jayesh  staff  136664 Jun 10 12:24 /Users/jayesh/Library/Fonts/HomeManagerExtra/InputMono/InputMonoCondensed/InputMonoCondensed-Black.ttf
-r--r--r--  1 jayesh  staff  139304 Jun 10 12:24 /Users/jayesh/Library/Fonts/HomeManagerExtra/InputMono/InputMonoCondensed/InputMonoCondensed-BlackItalic.ttf
-r--r--r--  1 jayesh  staff  109516 Jun 10 12:24 /Users/jayesh/Library/Fonts/HomeManagerExtra/InputMono/InputMonoCondensed/InputMonoCondensed-Bold.ttf
-r--r--r--  1 jayesh  staff  112248 Jun 10 12:24 /Users/jayesh/Library/Fonts/HomeManagerExtra/InputMono/InputMonoCondensed/InputMonoCondensed-BoldItalic.ttf

This happened only to the custom-fonts installed by the activation script. The fonts installed from home.packages had the correct permissions:

>> ls -ld ~/Library/Fonts/HomeManager/opentype 
drwxr-xr-x  100 jayesh  staff  3200 Jun 10 12:24 /Users/jayesh/Library/Fonts/HomeManager/opentype

>> ls -ld ~/Library/Fonts/HomeManager/opentype/FiraSans-Bo*
-rw-r--r--  1 jayesh  staff  305832 Jun 10 12:24 /Users/jayesh/Library/Fonts/HomeManager/opentype/FiraSans-Bold.otf
-rw-r--r--  1 jayesh  staff  314492 Jun 10 12:24 /Users/jayesh/Library/Fonts/HomeManager/opentype/FiraSans-BoldItalic.otf
-rw-r--r--  1 jayesh  staff  296368 Jun 10 12:24 /Users/jayesh/Library/Fonts/HomeManager/opentype/FiraSans-Book.otf
-rw-r--r--  1 jayesh  staff  306464 Jun 10 12:24 /Users/jayesh/Library/Fonts/HomeManager/opentype/FiraSans-BookItalic.otf

So I modified the permissions after copying, in the activation script:

home.activation = if pkgs.stdenv.isDarwin then 
{
  copyExtraFonts = lib.hm.dag.entryAfter ["writeBoundary"] ''
   $DRY_RUN_CMD rm -rf $VERBOSE_ARG ~/Library/Fonts/HomeManagerExtra
   $DRY_RUN_CMD cp -r $VERBOSE_ARG ${../configs/fonts} ~/Library/Fonts/HomeManagerExtra
   $DRY_RUN_CMD find $VERBOSE_ARG ~/Library/Fonts/HomeManagerExtra -type d -exec chmod 744 {} \;
   $DRY_RUN_CMD find $VERBOSE_ARG ~/Library/Fonts/HomeManagerExtra -type f -exec chmod 644 {} \;
 '';
} else { };

Now the permissions are set correctly.

>> ls -ld ~/Library/Fonts/HomeManagerExtra                             
drwxr--r--  4 jayesh  staff  128 Jun 10 12:31 /Users/jayesh/Library/Fonts/HomeManagerExtra

>> ls -ld ~/Library/Fonts/HomeManagerExtra/InputMono/InputMonoCondensed
drwxr--r--  16 jayesh  staff  512 Jun 10 12:31 /Users/jayesh/Library/Fonts/HomeManagerExtra/InputMono/InputMonoCondensed

>> ls -l ~/Library/Fonts/HomeManagerExtra/InputMono/InputMonoCondensed/InputMonoCondensed-B*.ttf
-rw-r--r--  1 jayesh  staff  136664 Jun 10 12:31 /Users/jayesh/Library/Fonts/HomeManagerExtra/InputMono/InputMonoCondensed/InputMonoCondensed-Black.ttf
-rw-r--r--  1 jayesh  staff  139304 Jun 10 12:31 /Users/jayesh/Library/Fonts/HomeManagerExtra/InputMono/InputMonoCondensed/InputMonoCondensed-BlackItalic.ttf
-rw-r--r--  1 jayesh  staff  109516 Jun 10 12:31 /Users/jayesh/Library/Fonts/HomeManagerExtra/InputMono/InputMonoCondensed/InputMonoCondensed-Bold.ttf
-rw-r--r--  1 jayesh  staff  112248 Jun 10 12:31 /Users/jayesh/Library/Fonts/HomeManagerExtra/InputMono/InputMonoCondensed/InputMonoCondensed-BoldItalic.ttf

Reruns of home-manager switch work as expected.