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

modules: introduce userhosts #225

Closed
wants to merge 6 commits into from

Conversation

bobvanderlinden
Copy link

@bobvanderlinden bobvanderlinden commented Sep 29, 2022

The userhosts module allows changing DNS lookups within the shell. Where usually you'd change /etc/hosts, it is now possible to change these entries within the shell without root.

This uses LD_PRELOAD to let ld.so load the libuserhosts.so library and the HOSTS_FILE is set to a Nix-generated hosts file containing the hosts entries from the devshell configuration.

This PR is similar to #75, but is based on userhosts instead of hostctl.

Example:

pkgs.mkShell {
  imports = [
    ./extra/services/userhosts.nix
  ];

  services.userhosts.hosts = {
    "127.0.0.1" = [ "mydomain.test" "example.org" ];
  };
}

Which allows:

[devshell]$ nc -v example.org 8080
nc: connect to example.org (127.0.0.1) port 8080 (tcp) failed: Connection refused

The userhosts module allows changing DNS lookups within the shell. Where
usually you'd change /etc/hosts, it is now possible to change these
entries within the shell without root.

This uses LD_PRELOAD to let ld.so load the libuserhosts.so library and
the HOSTS_FILE is set to a Nix-generated hosts file containing the hosts
entries from the devshell configuration.
@bobvanderlinden bobvanderlinden changed the title add userhosts module modules: introduce userhosts Sep 29, 2022
};
};

config = mkIf (cfg.hosts != {}) {
Copy link
Member

Choose a reason for hiding this comment

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

Can you add a warning trace if !stdenv.isLinux?

Copy link
Author

Choose a reason for hiding this comment

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

I have attempted to add this, but I can't figure it out.

I attempted the method used in NixOS modules by setting the warnings option, but that option is not (yet?) supported by dev-shell it seems? The commit where I tried is here: https://github.com/bobvanderlinden/devshell/blob/51e8c6bb6f8ab4d3b11acad8953b70f994a45591/extra/services/userhosts.nix#L44
Is it worth the trouble to add a warnings option to dev-shell?

I also attempted to use an assertion. However, somehow it causes an infinite recursion and I couldn't figure out why: https://github.com/bobvanderlinden/devshell/blob/6e7f3cd057082eb76b37a525991992a1946a27e8/extra/services/userhosts.nix#L44
Next to the infinite recursion problem, I thought it wouldn't be ideal using assertion as the test would still fail on MacOS.

In addition, there needs to be some way to skip tests for specific hosts. I haven't found an example in dev-shell yet to do so, do you have some pointers for targeting a test to a single system?

I was contemplating these issues and thought it might be better to work on MacOS support in userhosts instead, as MacOS should be able to do the same thing with DYLD_INSERT_LIBRARIES. That's probably what I'll do next once I get my hands on a OSX machine 😅

Copy link
Member

Choose a reason for hiding this comment

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

Something like that is probably enough:

mkIf (cfg.hosts != {})
if !stdenv.isLinux then
  builtins.trace "warning: userhosts is only available on Linux right now" {}
else
  // rest of the code

I guess NixOS has a warnings option and collects all of them later in the module system, but we don't have that here :)

You can use DYLD_INSERT_LIBRARIES, but I think there are some restrictions and it only works if the macOS system integrity checks are disabled. See https://github.com/jacereda/fsatrace#macos-usage

Copy link
Author

Choose a reason for hiding this comment

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

Ah that makes sense.

You can use DYLD_INSERT_LIBRARIES, but I think there are some restrictions and it only works if the macOS system integrity checks are disabled. See https://github.com/jacereda/fsatrace#macos-usage

Indeed 😢 I ran into this issue working on userhosts for OSX. Oh well, it's fine to be used for Linux for now.

I also made sure the userhosts test is not emitted for non-Linux systems.

That said, I still run into:

error: infinite recursion encountered

       at /nix/store/if23ghw4vi4981dawad0x1vkkkwbmja5-source/lib/modules.nix:469:28:

          468|         builtins.addErrorContext (context name)
          469|           (args.${name} or config._module.args.${name})
             |                            ^
          470|       ) (lib.functionArgs f);

Whenever I use pkgs.stdenv.isLinux in the if condition of the userhosts module. I don't get this when I replace it with true or false.
I also tried adding , system }: to the module arguments and using system == "x86_64-linux", but even that causes infinite loop. I'm quite at a loss why this is happening and I have a hard time debugging this. Any hints on how to continue?

Copy link
Member

Choose a reason for hiding this comment

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

I will go out on a limb and assume that you are using overlays. Stop using overlays!

Typically that would happen if you have your own overlay that has the devshell in it. Then in order to resolve the pkgs attribute, it would have to compute the devshell, and infinite recursion ensues.

Instead do something like this:

let
  sources = import ./nix/sources.nix; # assuming you're using niv
  pkgs = import sources.nixpkgs {};
  devshell = pkgs.callPackage sources.devshell {};
in
devshell.mkShell { ...

Copy link
Author

Choose a reason for hiding this comment

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

From what I can tell, devshell is not in my overlay. I only have a few packages that I created myself in my overlay. Nothing related to devshell.

The CI seems to be running into the same issue.

@bobvanderlinden
Copy link
Author

I've found that this solution isn't great. It'll crash programs that were linked to a different glibc version, so using any executables that aren't defined in the shell can be affected.

It showed up on Debian, which has an older version of glibc. git crashed because the LD_PRELOAD of userhosts resulted in an incompatible glibc version being loaded first.

@bobvanderlinden bobvanderlinden deleted the pr-userhosts branch November 24, 2022 23:20
@flokli
Copy link
Member

flokli commented Nov 25, 2022

@bobvanderlinden yes, NSS isn't great. I wrote about this stuff in https://flokli.de/posts/2022-11-18-nsncd/.

This however speaks about per-host NSS config.

I'd probably recommend using *.localhost hostnames when you want to have multiple vhosts pointing back to your own machine. That should work on most linux systems using nss-systemd.

https://serverfault.com/a/1103995 suggests it might work on MacOS too, but i didn't check.

@bobvanderlinden
Copy link
Author

bobvanderlinden commented Nov 28, 2022

Yea, if I could change all applications at my workplace to use *.localhost I would, but it's not trivial to do so atm 😅 nsncd sounds good though, I'll enable it on my system.

@flokli
Copy link
Member

flokli commented Nov 28, 2022

Thanks! Please reach out if you encounter any issues, I'm very interested in them :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants