Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

incron: init at 0.5.12 #45638

Merged
merged 18 commits into from Aug 31, 2018
Merged

incron: init at 0.5.12 #45638

merged 18 commits into from Aug 31, 2018

Conversation

aanderse
Copy link
Member

Motivation for this change

The incron package is available on many other distributions but lacking in NixOS.

Things done
  • Tested using sandboxing (nix.useSandbox on NixOS, or option sandbox in nix.conf on non-NixOS)
  • Built on platform(s)
    • NixOS
    • macOS
    • other Linux distributions
  • Tested via one or more NixOS test(s) if existing and applicable for the change (look inside nixos/tests)
  • Tested compilation of all pkgs that depend on this change using nix-shell -p nox --run "nox-review wip"
  • Tested execution of all binary files (usually in ./result/bin/)
  • Thorough application testing within a fresh nixos container.
  • Determined the impact on package closure size (by running nix path-info -S before and after)
  • Fits CONTRIBUTING.md.

patchPhase = ''
sed -i "s|PREFIX = /usr/local|PREFIX = $out|g" Makefile
sed -i "s|/bin/bash|${bash}/bin/bash|g" usertable.cpp
sed -i "s|/usr/local/bin:/usr/bin:/bin:/usr/X11R6/bin|/run/current-system/sw/bin|g" usertable.cpp
Copy link
Member Author

@aanderse aanderse Aug 26, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this seems weird. Also, here https://github.com/ar-/incron/blob/1eedfbc9b318372efd119fd17f4abdbde561a53d/usertable.cpp#L605

What's the expected behaviour here? Am I reading it right that it clears PATH and then sets it according to line 13? Is that sensible at all compared to actually inheriting PATH?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@srhb my assumption is that since the user defined command runs as the user it doesn't seem entirely crazy to clear any unwanted extras out of the environment. By adding PATH back in as the standard list of installed software the command can execute in a clean state I guess?

Is the path I used valid to grant the command access to the full list of software available to the user? Even if the path is valid does it make sense in the context of nixos? We want to balance changing the intended behavior of the software and what users would expect vs. what makes sense for nixos.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this might be a case of conflicting logic especially with NixOS.

The path you added adds in the system profile, but not the user's profile, which is what seems like what incron should really be doing (or possibly both of them.) I'm not really sure how to do this in a sensible way aside from using ~/.nix-profile/bin on PATH as well. I feel like it isn't correct to try to reconstruct the user's PATH by manually adding these things onto it. After all, that's what the normal login process would take care of, so I guess I don't have any terribly good ideas on how to deal with the assumptions in this program.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@srhb I recall the issue now. The process is run as root and therefore it can't simply inherit PATH. So the issue becomes how to best reproduce what PATH would look like for a given user.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@srhb I've modified the PATH to better match what NixOS provides as the user path... which as you mentioned is unfortunately best guess manually reconstructing the users PATH variable. I believe this new code to be most inline with what existing users might expect if using this software, and what is most aligned with the intention of the software developer.

nixos/modules/services/monitoring/incron.nix Show resolved Hide resolved
patches = [ ./default_path.patch ];

prePatch = ''
sed -i "s|PREFIX = /usr/local|PREFIX = $out|g" Makefile
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it not possible to use makeFlags = [ "PREFIX=$(out)" ];?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately this would get overridden:

https://github.com/ar-/incron/blob/master/Makefile#L2

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it? It usually works.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just tested and in this case it does not.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, found it: https://www.gnu.org/software/make/manual/html_node/Overriding.html#Overriding makeFlags really have greater priority.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure what the issue is then... I pasted your suggested makeFlags in but get this error:

install -m 0755 -d /usr/local/share/man/man1
install: cannot create directory '/usr': Permission denied

It appears to me in this case the value is not being overridden.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, the issue is that you are overriding installPhase. The default installPhase does something like make $makeFlags $installFlags $installTargets.

You could switch to something like the following:

  installFlags = [ "PREFIX=$(out)" ];
  installTargets = [ "install-man" ];

  preInstall = ''
    mkdir -p $out/bin

    # make install doesn't work because setuid and permissions
    # just manually install the binaries instead
    cp incrond incrontab $out/bin/
  '';

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be removed now

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah missed that on the last commit. Thanks for the explanation, that makes sense.


stdenv.mkDerivation rec {
name = "incron-0.5.12";
src = fetchurl {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not use fetchFromGitLab?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generally speaking, is fetchFromGitLab/fetchFromGitHub preferred over fetchurl?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. There can be some better caching done or something.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for explaining. I've adjusted as recommended. Thank you.

if (clearenv() != 0)
goto failed;

+ // try to recreate the user path as best as possible
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The profiles are arbitrary. NIX_PROFILES environment variable would contain all of them but that probably will not be available to the systemd service. Instead, it is common to provide extraPackages option in the NixOS module and then add them to the service (example).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How would you recommend doing this on a per user basis? Or are you just suggesting to skip that entirely and have the extraPackages cover all users? If so, would that not restrict users somewhat as they can't modify configuration.nix?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well would not be able to install packages to global profiles either, would they?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, but that is why ~/.nix-profile/bin is included in the path as well.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh right, pwd->pw_name is probably the user’s name. Maybe this would be good enough until the upstream adds user service support, if a comment that this is does not support other profiles than the common ones is added.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've added a comment... please suggest any changes to wording.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've modified this so the user can explicitly set the path for the system incrontab. Each users incrontab will still rely on the packages available to that user, but that can still work out reasonably well considering the users.users..packages option.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On the other hand, the original code also does not try to emulate user’s PATH, so maybe we can just take the config.system.path from the service.

src = fetchFromGitHub {
owner = "ar-";
repo = "incron";
rev = "incron-0.5.12";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can re-use name here so that updating is easier.


# make install doesn't work because setuid and permissions
# just manually install the binaries instead
cp incrond incrontab $out/bin/
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use of install for mkdir -p and cp here might be slightly better, but this is a minor nit and should work as is.

systemd.services.incron = {
description = "File system events scheduler";
wantedBy = [ "multi-user.target" ];
path = [ config.system.path ];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This path is likely overbroad, and can enable accidental dependencies - e.g. if incron depends on foo being in path, which it is on your system and a test system, this will work, but on someone's minimal system, that might be missing.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the suggestion. I've modified this so the user can explicitly set the path for the system incrontab.

|| setenv("HOME", pwd->pw_dir, 1) != 0
|| setenv("SHELL", pwd->pw_shell, 1) != 0
- || setenv("PATH", DEFAULT_PATH, 1) != 0)
+ || setenv("PATH", DEFAULT_PATH.c_str(), 1) != 0)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe instead of the patch to add PATH entries, we should instead delete this PATH-setting code and defer to some other PATH loading mechanism. This seems hairy and prone to problems.

Copy link
Member Author

@aanderse aanderse Aug 29, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that sounds like a fairly large change which would really belong upstream.

I went with the logic as I thought it best preserves the intended behaviour of the application.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@grahamc If I modified such that user incrontab files ran with config.system.path as the PATH as mentioned by @jtojnar and left the extraPackages option for the system incrontab would that be acceptable?

config = mkIf cfg.enable {

warnings = optional (cfg.allow != null && cfg.deny != null)
''If `services.incron.allow` is set then `services.incron.deny` will be ignored.'';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor nitpick: " is enough here.

@jtojnar
Copy link
Contributor

jtojnar commented Aug 31, 2018

Great review, thanks.

@jtojnar jtojnar merged commit f0136e4 into NixOS:master Aug 31, 2018
@aanderse aanderse deleted the incron branch November 4, 2018 12:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants