nix-darwin
                                
                                 nix-darwin copied to clipboard
                                
                                    nix-darwin copied to clipboard
                            
                            
                            
                        applications are only linked for system packages, not user packages
When I do this:
{ users.users.brianhicks.packages = [ pkgs.emacsMacport ]; }
I expect Emacs.app to be available somewhere—maybe in ~/Applications/Nix Apps. But it's not! However, if I do this:
{ environment.systemPackages = [ pkgs.emacsMacport ]; }
Then ~/Applications/Nix Apps/Emacs.app gets created.
This is important to me because I manage my packages through home-manager, where I create a big ol' bundle of emacs packages all together. I'd rather not have to move all that configuration out of home-manager just to use graphical Emacs!
According to @rvolosatovs in https://github.com/rycee/home-manager/pull/702#issuecomment-489431636, it's because these lines specifically (and only) include the system packages:
https://github.com/LnL7/nix-darwin/blob/3ba909eb2dd3ddd893604f83048fa76cc2e47e74/modules/system/applications.nix#L17-L21
@LnL7 I don't have a great idea of how hard this would be to fix. Do you think it would be something someone newish (read: me) could take on? Would a patch for this behavior be welcome?
The main problem is that there's no link between the user running darwin-rebuild and users entries. It's probably better to link per user applications instead and move system packages to /Applications.
I'm having some trouble understanding what you're saying about the running user. Why does this matter? Shouldn't stuff end up in /$USER_HOME/Applications regardless of who is running it?
Regardless, is that a change you're open to? I'm happy to look into it but I would rather not waste everyone's time by making something that would be doomed before I started 😁
OK, I've taken more time to think about it today, and just want to check my understanding. I think we'd need to:
- change https://github.com/LnL7/nix-darwin/blob/3ba909eb2dd3ddd893604f83048fa76cc2e47e74/modules/system/applications.nix to symlink into /Applications/Nix Appsinstead of~/Applicationsor~/Applications/Nix Apps.
- Figure out some way of removing the old symlinks in ~.
- add similar app linking logic in https://github.com/LnL7/nix-darwin/blob/3ba909eb2dd3ddd893604f83048fa76cc2e47e74/modules/users/default.nix somewhere. This would put applications in users.<user?>.packagesin~/Applicationsor~/Applications/Nix Appslike the system packages are now.
The first seems pretty approachable; I'm sure I could handle it. But I'm not sure if the second or third even make sense. @LnL7, what do you think? Would that be a good way to move forward on this?
(to be clear, if it's "yes" I plan to make PRs to do this!)
Yeah that's what I was suggesting.
Great, thank you. Sorry for the noise; I wanted to make sure I understood you completely before I sent in a PR. :)
On Jul 18, 2019, at 2:59 PM, Daiderd Jordan [email protected] wrote:
Yeah that's what I was suggesting.
— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/LnL7/nix-darwin/issues/139?email_source=notifications&email_token=AACWYSLJ54ZKV62VBADHAZTQADDS3A5CNFSM4HK37DL2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD2JTTQQ#issuecomment-512965058, or mute the thread https://github.com/notifications/unsubscribe-auth/AACWYSO5ZD7T64654SUZBLTQADDS3ANCNFSM4HK37DLQ.
For future reference, you can override the applications link like:
system.build.applications = pkgs.lib.mkForce (pkgs.buildEnv {
  name = "applications";
  paths = config.environment.systemPackages ++ config.home-manager.users.myusername.home.packages;
  pathsToLink = "/Applications";
});
It'd be nice if it was a config option though to avoid the mkForce.
@jsravn Nice, thanks for sharing that. It's a shame the larger change to place system-wide app links under /Applications and per-user app links under ~/Applications didn't end up getting seen through, because it feels like the ideal outcome.
Seems like spotlight struggles to index the links in ~/Applications however. I'm pretty sure it worked for me at one point but it's not working anymore. Any ideas?
I modified the activation script to create aliases which get picked up by spotlight.
    system.activationScripts.applications.text = pkgs.lib.mkForce (''
      echo "setting up ~/Applications/NixApps..."
      mkdir -p ~/Applications
      rm -rf ~/Applications/NixApps
      mkdir -p ~/Applications/NixApps
      chown myusername ~/Applications/NixApps
      find ${config.system.build.applications}/Applications -maxdepth 1 -type l | while read f; do
        echo "Linking $f"
        src=$(/usr/bin/stat -f%Y $f)
        osascript -e "tell app \"Finder\" to make alias file at POSIX file \"/Users/myusername/Applications/NixApps/\" to POSIX file \"$src\"";
      done
    '');
It can probably be made a bit nicer but it works.
@jsravn I found that some alias files were ending up with different names over time, e.g. with numeric suffixes. Making the name of the alias file explicit as follows seems to help:
  system.activationScripts.applications.text = pkgs.lib.mkForce (''
      echo "setting up ~/Applications/Nix..."
      rm -rf ~/Applications/Nix
      mkdir -p ~/Applications/Nix
      chown ${me} ~/Applications/Nix
      find ${config.system.build.applications}/Applications -maxdepth 1 -type l | while read f; do
        src="$(/usr/bin/stat -f%Y $f)"
        appname="$(basename $src)"
        osascript -e "tell app \"Finder\" to make alias file at POSIX file \"/Users/${me}/Applications/Nix/\" to POSIX file \"$src\" with properties {name: \"$appname\"}";
    done
  '');
(Note that ${me} is just a local attribute with my username.)
Nice one! @LnL7 would you accept a PR with this change?
Relying on applescript seems pretty undesirable to me, especially for headless usecases. But should be pretty easy to create an alias using CoreFoundation if there's no binary that create one on the system already.
Hello. I’ve encountered this issue today. At the moment I’ve applied a fix from above. I’d like to fix it permanently though. I’ll continue Brian’s PR unless you have time to fix it @LnL7. What are your thoughts?
So on Catalina, I tried the above suggestions of using aliases created through AppleScript instead of symlinks, but Spotlight still couldn't find the apps Nix installed into ~/Applications. I even tried creating the symlinks and aliases in /Applications, but still nothing. So now I'm just copying the entire app directory over! Wasteful but at least it shows up in Spotlight!
  system.activationScripts.applications.text = pkgs.lib.mkForce (''
    rm -rf ~/Applications/Nix\ Apps
    mkdir -p ~/Applications/Nix\ Apps
    for app in $(find ${config.system.build.applications}/Applications -maxdepth 1 -type l); do
      src="$(/usr/bin/stat -f%Y "$app")"
      cp -r "$src" ~/Applications/Nix\ Apps
    done
  '');
Copying (or moving?) the entire app to /Applications is actually the approach taken by brew cask. I suspect there's a good reason for that so I do the same as you do in my nix-darwin config.
Copying the applications solved the issue for me too. I added the -L flag to follow symlinks too (this helped copy the alacritty app properly, for example).
So now I'm just copying the entire app directory over!
@andreykaipov @wangkev
If you comment out the program to uninstall, and run nix-collect-garbage is the copied app directory will be removed or not?
I don't want leave garbage files/links/directories after uninstalling them.
@ihsanturk If I understand the question correctly - the copied apps aren't removed even when you uninstall Nix because Nix doesn't know what directories you create in your custom activation script, so you don't have to worry about commenting them out in your config before running garbage collection. As part of my uninstall script I have to manually remove the created directory.
Also I've since changed the above script to compare the hashes of <app>/Contents/MacOS to prevent unnecessary copying. It makes for a rather large snippet, but you can view it here.
@ihsanturk Yes. the app will be removed. It's in the script.
system.activationScripts.applications.text = pkgs.lib.mkForce (''
  rm -rf ~/Applications/Nix\ Apps
  mkdir -p ~/Applications/Nix\ Apps
  for app in $(find ${config.system.build.applications}/Applications -maxdepth 1 -type l); do
    src="$(/usr/bin/stat -f%Y "$app")"
    cp -r "$src" ~/Applications/Nix\ Apps
  done
'');
The script starts with rm -rf ~/Applications/Nix\ Apps which removes all previously copied apps. Then later in the script it copies new list of apps.
Thanks! Those were my two wishes:
... compare the hashes of
/Contents/MacOS to prevent unnecessary copying. 
The script starts with
rm -rf ~/Applications/Nix\ Appswhich removes all previously copied apps.
Now I will integrate them. I hope these will be solved more generally by Nix itself.
I really don't understand why nix-darwin puts anything in the home directory. These are system packages, shouldn't they go to /Applications? I would assume ~/Applications would be used by home-manager, but apparently it can't (on mac) because of the conflict.
@akoppela Thank you!
↓ FYI I improved your snippet by resolving the symlinks in bulk, and using APFS's copy-on-write.
  system.activationScripts.applications.text = let
    env = pkgs.buildEnv {
      name = "system-applications";
      paths = config.environment.systemPackages;
      pathsToLink = "/Applications";
    };
  in mkForce ''
    # Set up applications.
    echo "setting up ~/Applications..." >&2
    rm -rf ~/Applications/Nix\ Apps
    mkdir -p ~/Applications/Nix\ Apps
    find ${env}/Applications -maxdepth 1 -type l -exec readlink '{}' + |
        while read src; do
          /bin/cp -cr "$src" ~/Applications/Nix\ Apps
        done
  '';
Folders symlinked to ~/Applications do not show up in spotlight, and copying them seems like a waste of disk space. Not to mention that it can take a while too if you have a lot of packages. I found a workaround using APFS aliases, those show up in spotlight and barely take any disk space.
This is my activation script:
  # Nix-darwin does not link installed applications to the user environment. This means apps will not show up
  # in spotlight, and when launched through the dock they come with a terminal window. This is a workaround.
  # Upstream issue: https://github.com/LnL7/nix-darwin/issues/214
  system.activationScripts.applications.text = lib.mkForce ''
    echo "setting up ~/Applications..." >&2
    applications="$HOME/Applications"
    nix_apps="$applications/Nix Apps"
    # Needs to be writable by the user so that home-manager can symlink into it
    if ! test -d "$applications"; then
        mkdir -p "$applications"
        chown ${username}: "$applications"
        chmod u+w "$applications"
    fi
    # Delete the directory to remove old links
    rm -rf "$nix_apps"
    mkdir -p "$nix_apps"
    find ${config.system.build.applications}/Applications -maxdepth 1 -type l -exec readlink '{}' + |
        while read src; do
            # Spotlight does not recognize symlinks, it will ignore directory we link to the applications folder.
            # It does understand MacOS aliases though, a unique filesystem feature. Sadly they cannot be created
            # from bash (as far as I know), so we use the oh-so-great Apple Script instead.
            /usr/bin/osascript -e "
                set fileToAlias to POSIX file \"$src\" 
                set applicationsFolder to POSIX file \"$nix_apps\"
                tell application \"Finder\"
                    make alias file to fileToAlias at applicationsFolder
                    # This renames the alias; 'mpv.app alias' -> 'mpv.app'
                    set name of result to \"$(rev <<< "$src" | cut -d'/' -f1 | rev)\"
                end tell
            " 1>/dev/null
        done
  '';
I have done something similar for home-manager, which integrates with this just fine.
Commit from my dotfiles: https://github.com/IvarWithoutBones/dotfiles/commit/0b3faad8bd1d0e1af6103caf59b206666ab742f4