4 ms·
> Bonus 4. In nix it is really easy to build single language applications. However if you need to mix two, finding good docs or examples is really hard. IE, if
by chriswarbo 6y ago
> Bonus 4. In nix it is really easy to build single language applications. However if you need to mix two, finding good docs or examples is really hard. IE, if you want to build the javascript front end of your web app as well as the python backend. These combinations need at least two derivations, and how to make it happen is bespoke every time.
For anything that doesn't fit a common nixpkgs function (like `buildPythonPackage`, etc.) then I always start with this:
nixpkgs.runCommand "my-application"
{
dependencies go here
}
''
shell commands go here
''
This is certainly "bespoke every time", but it's literally just a shell script (with explicit dependencies). This approach doesn't need much documentation either: we just copy-paste whatever commands are in the normal, non-Nix documentation for whatever we're doing. We'll probably need to add a few dependencies to the `buildInputs`, and possibly disable the sandbox to allow network access (which we can factor out later, if we like).
- georgyo 6y agoThat is a gross oversimplification. An javascript front end can have thousands of dependencies, and the nix build environment does not have network access unless it's computing a fixed output. To do that manually would be a nightmare, so you must automated either with tools you write or tools someone else has written. Then you still have to figure out how to combine it all together. Also on allowing network access in the sandbox requires elevated privileges which means you cannot do that method on environments you don't have full control. And it would create builds that are likely not reproducible.
- chriswarbo 6y ago> That is a gross oversimplification It's really not. I've used this successfully for Javascript projects (running npm and yarn), Python projects (running pip install), Scala projects (running sbt), Haskell projects (running cabal), Racket projects (running raco), Go projects (running go get), etc. It's pretty much like writing a Makefile, except we have to specify the buildInputs, and there are occasional annoyances like tools trying to write to $HOME (requiring an `export HOME="$PWD"` line at the top of the script). > the nix build environment does not have network access unless it's computing a fixed output Yes it does, if we avoid the sandbox. This used to be done by specifying a `__noChroot = true;` attribute; I don't know if that's changed in more recent Nix versions. > Also on allowing network access in the sandbox requires elevated privileges Sandboxing is a sensible default, but for practicality I usually set it to "relaxed" on NixOS and disable it entirely on macOS (since that often uses stuff from the host system). > which means you cannot do that method on environments you don't have full control. Could you give an example of where that would ever be an issue? The only thing I can think of is hydra.nixos.org, but there's no way in hell such a derivation would be acceptable for nixpkgs, so that's pretty irrelevant (similar to how it's really easy to make a .deb package from a directory and a control file; but there's no way in hell it complies with the Debian project's packaging guidelines) > And it would create builds that are likely not reproducible. Yes, that's why I mentioned we might want to factor out the input-fetching at some point. > Then you still have to figure out how to combine it all together. That has nothing to do with Nix. As long as a project has a build script, or a Makefile, or a list of commands in a README, or whatever, then we can plug it into that template and see if it works. Are you complaining that the Nix package manager doesn't have specific documentation for how to build every random application ever written?
- georgyo 6y ago>> which means you cannot do that method on environments you don't have full control. > Could you give an example of where that would ever be an issue? The only thing I can think of is hydra.nixos.org, but there's no way in hell such a derivation would be acceptable for nixpkgs, so that's pretty irrelevant (similar to how it's really easy to make a .deb package from a directory and a control file; but there's no way in hell it complies with the Debian project's packaging guidelines) In any production environment, using any external build service like nixbuild.net, self-host hydra. Basically anything beyond personal use. The post about all this is from Channable, Channable runs nix built code in production. Their developers (likely) cannot disable the sandbox and ship that code. You even say that there is "no way in hell such a derivation would be acceptable for nixpkgs" If you cannot share it, it's only good for you and you alone.
- chriswarbo 6y ago> production environment > in production Lol. If someone doesn't want to be executing random unverified binaries fetched from arbitrary online locations, then they shouldn't write such things in their build scripts. That has nothing to do with Nix. The same goes for Makefile, or whatever.
- jeofken 6y agoThanks for the example - I’ve been looking for how to make mix packaging easy. How do you add files to this build? For example, if I have this program.rb that depends on ruby: puts “Hello World” And then you add a file called package.nix let pkgs = import <nixpkgs> {}; in pkgs.runCommand "my-app" { buildInputs = [pkgs.ruby]; } '' pwd && ls; ruby ./program.rb '' How do you get your files in there - like “ADD” in a Dockerfile?
- xfer 6y agoexample in the manual: https://nixos.org/manual/nixpkgs/stable/#chap-trivial-builders https://nixos.org/manual/nixpkgs/stable/#chap-trivial-builde... shows how it creates a file `$out/message`. If you want to write to nix store with stdenv use $out.
- chriswarbo 6y agoYou can splice file paths directly into the script, like this: let pkgs = import <nixpkgs> {}; in pkgs.runCommand "my-app" { buildInputs = [pkgs.ruby]; } '' pwd && ls ruby ${./program.rb} '' Or you could add it as an env var: let pkgs = import <nixpkgs> {}; in pkgs.runCommand "my-app" { buildInputs = [pkgs.ruby]; program = ./program.rb; } '' pwd && ls; ruby "$program" ''