Skip to content

Commit cc1d6f0

Browse files
committed
merge both readmes
1 parent cc0d9b5 commit cc1d6f0

File tree

1 file changed

+158
-15
lines changed

1 file changed

+158
-15
lines changed

README.md

Lines changed: 158 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,107 @@
1-
# nix-ld-rs
1+
# nix-ld
22

33
Run unpatched dynamic binaries on NixOS.
4-
This is a rewrite of [nix-ld](https://github.com/Mic92/nix-ld) in Rust, with extra functionalities.
5-
It's intended to be upstreamed at some point.
64

7-
## Usage
5+
## Where is this useful?
6+
7+
While many proprietary packages in nixpkgs have already been patched with
8+
`autoPatchelfHook` patching, there are cases where patching is not possible:
9+
10+
- Use binary executable downloaded with third-party package managers (e.g. vscode, npm or pip) without having to patch them on every update.
11+
- Run games or proprietary software that attempts to verify its integrity.
12+
- Run programs that are too large for the nix store (e.g. FPGA IDEs).
13+
14+
While there are other solutions such as `buildFHSUserEnv` that restore a Linux file
15+
hierarchy as found on common Linux systems (`ld-linux-x86-64.so.2`), these
16+
sandboxes have their own weaknesses:
17+
18+
- setuid binaries cannot be executed inside a fhsuserenv
19+
- inside a `buildFHSUserEnv` you can not use other sandbox tools like bwrap or 'nix build'.
20+
- `buildFHSUserEnv` requires a subshell which does not work well with direnv
21+
22+
## How does nix-ld work?
23+
24+
Also read this [blog post](https://blog.thalheim.io/2022/12/31/nix-ld-a-clean-solution-for-issues-with-pre-compiled-executables-on-nixos/)
25+
to get the explaination in full detail. A summary is below:
26+
27+
Precompiled binaries that were not created for NixOS usually have a so-called
28+
link-loader hardcoded into them. On Linux/x86_64 this is for example
29+
`/lib64/ld-linux-x86-64.so.2`. for glibc. NixOS, on the other hand, usually has
30+
its dynamic linker in the glibc package in the Nix store and therefore cannot
31+
run these binaries. Nix-ld provides a shim layer for these types of binaries. It
32+
is installed in the same location where other Linux distributions install their
33+
link loader, ie. `/lib64/ld-linux-x86-64.so.2` and then loads the actual link
34+
loader as specified in the environment variable `NIX_LD`. In addition, it also
35+
accepts a colon-separated path from library lookup paths in `NIX_LD_LIBRARY_PATH`.
36+
This environment variable is rewritten to `LD_LIBRARY_PATH` before
37+
passing execution to the actual ld. This allows you to specify additional
38+
libraries that the executable needs to run.
39+
40+
## Installation
41+
42+
nix-ld is part of nixpkgs since NixOS 22.05. There one can enable it with the following
43+
nixos setting:
44+
45+
```nix
46+
{
47+
programs.nix-ld.enable = true;
48+
}
49+
```
50+
51+
To install `nix-ld` from the repository instead, use the following method:
52+
53+
```sh
54+
$ sudo nix-channel --add https://github.com/Mic92/nix-ld/archive/main.tar.gz nix-ld
55+
$ sudo nix-channel --update
56+
```
57+
58+
`/etc/nixos/configuration.nix`
59+
60+
```nix
61+
{
62+
imports = [
63+
<nix-ld/modules/nix-ld.nix>
64+
];
65+
# The module in this repository defines a new module under (programs.nix-ld.dev) instead of (programs.nix-ld)
66+
# to not collide with the nixpkgs version.
67+
programs.nix-ld.dev.enable = true;
68+
}
69+
```
70+
871

9-
`nix-ld-rs` is a drop-in replacement for `nix-ld`.
72+
### With nix flake
1073

11-
It honors the following environment variables:
74+
Add the following lines to `/etc/nixos/flake.nix`. Replace `myhostname` with the
75+
actual hostname of your system.
76+
77+
```nix
78+
# flake.nix
79+
{
80+
inputs.nixpkgs.url = "github:NixOS/nixpkgs/master";
81+
inputs.nix-ld.url = "github:Mic92/nix-ld";
82+
# this line assume that you also have nixpkgs as an input
83+
inputs.nix-ld.inputs.nixpkgs.follows = "nixpkgs";
84+
85+
outputs = { nix-ld, nixpkgs, ... }: {
86+
# replace `myhostname` with your actual hostname
87+
nixosConfigurations.myhostname = nixpkgs.lib.nixosSystem {
88+
system = "x86_64-linux";
89+
modules = [
90+
# ... add this line to the rest of your configuration modules
91+
nix-ld.nixosModules.nix-ld
92+
93+
# The module in this repository defines a new module under (programs.nix-ld.dev) instead of (programs.nix-ld)
94+
# to not collide with the nixpkgs version.
95+
{ programs.nix-ld.dev.enable = true; }
96+
];
97+
};
98+
};
99+
}
100+
```
101+
102+
## Usage
103+
104+
nix-ld honors the following environment variables:
12105

13106
- `NIX_LD`
14107
- `NIX_LD_{system}`
@@ -19,19 +112,69 @@ It honors the following environment variables:
19112
Here `{system}` is the value of the Nix `system` with dashes replaced with underscores, like `x86_64_linux`.
20113
You can also run `nix-ld-rs` directly for a list.
21114

22-
## Use in NixOS
115+
After setting up the nix-ld symlink as described above, one needs to set at least
116+
`NIX_LD` and `NIX_LD_LIBRARY_PATH` to run executables. For example, this can
117+
be done with a `shell.nix` in a nix-shell like this:
23118

24-
```
25-
{ pkgs, ... }: {
26-
programs.nix-ld.enable = true;
27-
programs.nix-ld.package = pkgs.nix-ld-rs;
119+
```nix
120+
with import <nixpkgs> {};
121+
mkShell {
122+
NIX_LD_LIBRARY_PATH = lib.makeLibraryPath [
123+
stdenv.cc.cc
124+
openssl
125+
# ...
126+
];
127+
NIX_LD = lib.fileContents "${stdenv.cc}/nix-support/dynamic-linker";
28128
}
29129
```
30130

31-
## Extra functionalities
131+
A full example is shown in [`./examples/masterpdfeditor.nix`](examples/masterpdfeditor.nix).
132+
133+
In [nix-autobahn](https://github.com/Lassulus/nix-autobahn) there is also a
134+
script called `nix-autobahn-ld` that automates generating shell expressions.
135+
136+
In [nix-alien](https://github.com/thiagokokada/nix-alien) there is another
137+
script called `nix-alien-ld` that uses another strategy, wrapping the program in
138+
a `writeShellScriptBin` with the `NIX_LD`/`NIX_LD_LIBRARY_PATH` environment
139+
variables set.
32140

33-
- `NIX_LD_LIBRARY_PATH` doesn't affect child processes (on `x86_64-linux` and `aarch64-linux`)
34-
- For example, shell environments spawned by the binary VSCode Server no longer get polluted
141+
To figure out what libraries a program needs, you can use `ldd` on the binary or
142+
set the `LD_DEBUG=libs` environment variable.
143+
144+
## FAQ
145+
146+
### How to find libraries for my executables?
147+
148+
You can use tools like [nix-autobahn](https://github.com/Lassulus/nix-autobahn),
149+
[nix-alien](https://github.com/thiagokokada/nix-alien) or use
150+
[nix-index](https://github.com/bennofs/nix-index)
151+
152+
### Why not set LD_LIBRARY_PATH directly instead of NIX_LD_LIBRARY_PATH?
153+
154+
LD_LIBRARY_PATH affects all programs, which can inject the wrong libraries in
155+
correct build nix application that have an RPATH set in their executable.
156+
157+
### Does this work on non-NixOS system?
158+
159+
No. Normal Linux distributions will have their own link-loader. Replacing those
160+
with nix-ld will break the system.
161+
162+
### My python/nodejs/ruby/$interpreter libraries do not find the libraries configured by nix-ld
163+
164+
Nix-ld is only used by unpatched executables that use the link loader at `/lib`
165+
or `/lib64`. If you use for example python from nixpkgs than it will not pick
166+
up `NIX_LD_LIBRARY_PATH` and `NIX_LD` since these types of binaries are
167+
configured to use a glibc from the nix store. If you encounter these cases i.e.
168+
when you are trying to use python packages installed in a virtualenv than you
169+
need to set `LD_LIBRARY_PATH` directly. You can also create yourself a wrapper
170+
like this:
171+
172+
```nix
173+
(pkgs.writeShellScriptBin "python" ''
174+
export LD_LIBRARY_PATH=$NIX_LD_LIBRARY_PATH
175+
exec ${pkgs.python3}/bin/python "$@"
176+
'')
177+
```
35178

36179
## Development
37180

@@ -47,7 +190,7 @@ It's recommended to set up transparent emulation using binfmt-misc so you can ru
47190

48191
Run `cargo test` or `cargo nextest run` to run the integration tests, and `just test` to run them on all supported platforms (binfmt required).
49192

50-
### Current behavior
193+
## Current behavior
51194

52195
<table>
53196
<thead>

0 commit comments

Comments
 (0)