Get executable path of pkgs.writeScriptBin (Nextcloud occ)

I want to execute the nextcloud-occ command within a custom systemd service.
nextcloud-occ is defined in the nextcloud module using this expression

occ = pkgs.writeScriptBin "nextcloud-occ" "...";

simply calling nextcloud-occ doesn’t work within a systemd service definition because as far I understand systemd has no access to the PATH variables.

my next approach was to reference the package like ${pkgs.nextcloud27}/bin/nextcloud-occ. But this doesnt work either. Because nextcloud-occ ist not part of this nix package. Instead it’s an own package defined with pkgs.writeScriptBin in the nextcloud module.

How can I reference that package from my systemd service?
Any ideas?

Currently I’m using /run/current-system/sw/bin/nextcloud-occ. This works. But I’m not sure if this is the right way to handle this. Because if multiple instances of nextcloud-occ would be installed it is not predictable (from my systemd service point of view) which nextcloud-occ instance is actually referenced by that path.

systemd = {
    paths.nextcloud-brother-filewatch = {
      wantedBy = [ "multi-user.target" ]; 
      pathConfig.PathChanged = [ "${nextcloud-folder}" ];

    };

    services.nextcloud-brother-filewatch = {
      wantedBy = [ "multi-user.target" ]; 
      after = [ "network.target" ];
      description = "Watch 'brother's home dir for changes and trigger nextcloud rescan.";
      path = [ "occ" ];
      serviceConfig = {
        Type = "oneshot";
        User = "nextcloud";  # todo replace by nextcloud config variable 
        ExecStart = "/run/current-system/sw/bin/nextcloud-occ groupfolders:scan ${nextcloud-groupfolder-id}";         
      };  # 
    };
  };

It might be accessible via config.services.nextcloud.occ? It looks like there’s a test doing this:

1 Like

You nailed it - thank you very much! :tada:

TL;DR:
I replaced /run/current-system/sw/bin/nextcloud-occ by ${config.services.nextcloud.occ}/bin/nextcloud-occ and it works. :+1:
And I learned to peek other .nix files nearby in the github repository. :face_with_peeking_eye:

Summary

nixos-option services.nextcloud.occ returns

Value:
«derivation /nix/store/4kfpdmihn8sa3yqa17k5wqnsikalj2ls-nextcloud-occ.drv»

Default:
«derivation /nix/store/4kfpdmihn8sa3yqa17k5wqnsikalj2ls-nextcloud-occ.drv»

Type:
"package"

Description:
{
  text = ''
    The nextcloud-occ program preconfigured to target this Nextcloud instance.
  '';
}

Declared by:
[ "/nix/var/nix/profiles/per-user/root/channels/nixos/nixos/modules/services/web-apps/nextcloud.nix" ]

Defined by:
[ "/nix/var/nix/profiles/per-user/root/channels/nixos/nixos/modules/services/web-apps/nextcloud.nix" ]

looking into that file /nix/store/4kfpdmihn8sa3yqa17k5wqnsikalj2ls-nextcloud-occ.drv showed me the right path to nextcloud-occ which is /fdab4jbgjphr4agk6j5i568qpm2p84hy-nextcloud-occ/bin/nextcloud-occ

double checked by ll /run/current-system/sw/bin/nextcloud-occ returns

/run/current-system/sw/bin/nextcloud-occ -> /nix/store/fdab4jbgjphr4agk6j5i568qpm2p84hy-nextcloud-occ/bin/nextcloud-occ

now I adjusted my systemd configuration to

systemd = {
    paths.nextcloud-brother-filewatch = {
      wantedBy = [ "multi-user.target" ]; 
      pathConfig.PathChanged = [ "${nextcloud-folder}" ];

    };

    services.nextcloud-brother-filewatch = {
      wantedBy = [ "multi-user.target" ]; 
      after = [ "network.target" ];
      description = "Watch 'brother's home dir for changes and trigger nextcloud rescan.";
      path = [ "occ" ];  # todo>:to be removed. is this statement still necessary ?
      serviceConfig = {
        Type = "oneshot";
        User = "nextcloud";  # todo replace by nextcloud config variable 
        ExecStart = "${config.services.nextcloud.occ}/bin/nextcloud-occ groupfolders:scan ${nextcloud-groupfolder-id}";         
      };  
    };
  };

great :slight_smile:

1 Like

@peterhoeg suggested to
replace ${config.services.nextcloud.occ}/bin/nextcloud-occ
by ${lib.getExe config.services.nextcloud.occ}
which looks a little bit more elegant to me :smiley:

1 Like

If you use lib.getExe I recommend not using interpolation.

let
  something1 = lib.getExe config.services.nextcloud.occ;
  something2 = "${lib.getExe config.services.nextcloud.occ}";
in ''
  ${something1} --flag --other-flag
''

Which seems cleaner to you?