Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/thiagokokada/nix-alien
Run unpatched binaries on Nix/NixOS
https://github.com/thiagokokada/nix-alien
nix nixos nixpkgs
Last synced: about 1 month ago
JSON representation
Run unpatched binaries on Nix/NixOS
- Host: GitHub
- URL: https://github.com/thiagokokada/nix-alien
- Owner: thiagokokada
- License: mit
- Created: 2021-10-27T00:26:44.000Z (about 3 years ago)
- Default Branch: master
- Last Pushed: 2024-03-15T09:33:49.000Z (8 months ago)
- Last Synced: 2024-03-15T10:46:38.831Z (8 months ago)
- Topics: nix, nixos, nixpkgs
- Language: Python
- Homepage:
- Size: 352 KB
- Stars: 378
- Watchers: 4
- Forks: 9
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
- awesome-nix - nix-alien - Run unpatched binaries on Nix/NixOS easily. (Command-Line Tools / Discovery)
README
# nix-alien
![nix-alien](./.github/nix-alien.jpg)
[![FlakeHub](https://img.shields.io/endpoint?url=https://flakehub.com/f/thiagokokada/nix-alien/badge)](https://flakehub.com/flake/thiagokokada/nix-alien)
[![ci](https://github.com/thiagokokada/nix-alien/actions/workflows/ci.yml/badge.svg)](https://github.com/thiagokokada/nix-alien/actions/workflows/ci.yml)
## Introduction
You are running nix/NixOS and have ever encountered the following problem?
```console
$ ./myapp
bash: ./myapp: No such file or directory
```Fear not, now there is `nix-alien` which will download necessary dependencies
for you.```console
$ nix-alien myapp # Run the binary inside a FHS shell with all needed shared dependencies to execute the binary
$ nix-alien-ld myapp # Spawns you inside a shell with NIX_LD_LIBRARY_PATH set to the needed dependencies, to be used with nix-ld
$ nix-alien-find-libs myapp # Lists all libs needed for the binary
```## Quick start
If your binary is located in `~/myapp`, run:
```console
$ nix --extra-experimental-features "nix-command flakes" run github:thiagokokada/nix-alien -- ~/myapp
```
> [!TIP]
> If you are trying to run an OpenGL binary (e.g.: `blender`) in non-NixOS
> systems, you can wrap the command above in
> [nixGL](https://github.com/guibou/nixGL):
> ```console
> $ nix --extra-experimental-features "nix-command flakes" run --impure github:guibou/nixGL --override-input nixpkgs nixpkgs/nixos-unstable -- nix run github:thiagokokada/nix-alien -- blender
> ```## Usage
Once `nix-alien` is installed in your system, all you need to do is run:
```console
$ nix-alien ~/myapp
```This will run `nix-alien` on `~/myapp` binary with a `FHSUserEnv` including all
shared library dependencies. The resulting `default.nix` file will be saved to
`$XDG_CACHE_HOME/nix-alien//fhs-env/default.nix`, making the next
evaluation faster. The cache is based on the binary absolute path. You can also
pass `--recreate` flag to force the recreation of `default.nix` file, and
`--destination` to change where `default.nix` file will be saved.To pass arguments to the app:
```console
$ nix-alien ~/myapp -- --foo bar
```In case you're using [`nix-ld`](https://github.com/Mic92/nix-ld), there is also
`nix-alien-ld`:```console
$ nix-alien-ld -- ~/myapp
```This will spawn a wrapped binary with `NIX_LD_LIBRARY_PATH` and `NIX_LD` setup.
The resulting `default.nix` file will be saved to
`$XDG_CACHE_HOME/nix-alien//nix-ld/default.nix`, making the next
evaluation faster. The cache is based on the binary absolute path. You can also
pass `--recreate` flag to force the recreation of `default.nix` file, and
`--destination` to change where `default.nix` file will be saved.To pass arguments to the app:
```console
$ nix-alien-ld ~/myapp -- --foo bar
```If you want to use the `fzf` based menu to find the libraries for scripting
purposes, you can run:```console
$ nix-alien-find-libs ~/myapp
```This will print the found libraries on the `stdout`. The informational messages
are printed to `stderr`, so you can easily redirect them to `/dev/null` if
needed. You can also use `--json` flag to print the result as a JSON instead.There are also some other options, check them using `--help` flag on each
program. Example for `nix-alien`:```console
usage: nix-alien [-h] [--version] [-l LIBRARY] [-p PACKAGE] [-c CANDIDATE] [-r] [-d PATH] [-P] [-E] [-s] [-f] program ...positional arguments:
program Program to run
ellipsis Arguments to be passed to the programoptions:
-h, --help show this help message and exit
--version show program's version number and exit
-l LIBRARY, --additional-libs LIBRARY
Additional library to search. May be passed multiple times
-p PACKAGE, --additional-packages PACKAGE
Additional package to add. May be passed multiple times
-c CANDIDATE, --select-candidates CANDIDATE
Library candidates that will be auto-selected if found via regex. Useful for automation.
-r, --recreate Recreate 'default.nix' file if exists
-d PATH, --destination PATH
Path where 'default.nix' file will be created
-P, --print-destination
Print where 'default.nix' file is located and exit
-E, --edit Edit 'default.nix' using $EDITOR (or 'nano' if unset)
-s, --silent Silence informational messages
-f, --flake Create and use 'flake.nix' file instead (experimental)
```### Usage without installing
You can run the scripts from this repo directly without cloning or installing
them, assuming you're using [a resonable up-to-date nix and enabled
experimental Flakes support](https://nixos.wiki/wiki/Flakes#Enable_flakes).```console
$ nix run "github:thiagokokada/nix-alien#nix-alien" -- ~/myapp
$ nix run "github:thiagokokada/nix-alien#nix-alien-ld" -- ~/myapp
$ nix run "github:thiagokokada/nix-alien#nix-alien-find-libs" -- ~/myapp
```Or if you don't have Flakes enabled but still wants to run it without
downloading it first:```console
$ nix --extra-experimental-features "nix-command flakes" run "github:thiagokokada/nix-alien#nix-alien" -- ~/myapp
$ nix --extra-experimental-features "nix-command flakes" run "github:thiagokokada/nix-alien#nix-alien-ld" -- ~/myapp
$ nix --extra-experimental-features "nix-command flakes" run "github:thiagokokada/nix-alien#nix-alien-find-libs" -- ~/myapp
```## NixOS Installation
You can add the following contents to a `/etc/nixos/nix-alien.nix` file:
``` nix
{ ... }:let
nix-alien-pkgs = import (
builtins.fetchTarball "https://github.com/thiagokokada/nix-alien/tarball/master"
) { };
in
{
environment.systemPackages = with nix-alien-pkgs; [
nix-alien
];# Optional, but this is needed for `nix-alien-ld` command
programs.nix-ld.enable = true;
}
```And afterwards, add it to `imports` section on `/etc/nixos/configuration.nix`
file.### NixOS installation with Flakes
> [!WARNING]
> Overriding `nix-alien` inputs may cause mismatches between the
> `nix-index-database` and `nixpkgs`, causing possibly incorrect results, so it
> is unsupported.If you're using NixOS with Flakes, you can do something similar to your NixOS
setup to install `nix-alien` on system `PATH`:```nix
{
description = "nix-alien-on-nixos";inputs.nixpkgs.url = "github:NixOS/nixpkgs";
inputs.nix-alien.url = "github:thiagokokada/nix-alien";outputs = { self, nixpkgs, nix-alien }: {
nixosConfigurations.nix-alien-desktop = nixpkgs.lib.nixosSystem rec {
system = "x86_64-linux"; # or aarch64-linux
specialArgs = { inherit self system; };
modules = [
({ self, system, ... }: {
environment.systemPackages = with self.inputs.nix-alien.packages.${system}; [
nix-alien
];
# Optional, needed for `nix-alien-ld`
programs.nix-ld.enable = true;
})
];
};
};
}
```Alternatively, you can also use the included overlay. Keep in mind that the
overlay will use your current `nixpkgs` pin instead the one included in this
project `flake.lock` file.This has the advantage of reducing the general size of your `/nix/store`,
however since the version of `nixpkgs` you currently have is not tested this may
cause issues.```nix
{
description = "nix-alien-on-nixos";inputs.nixpkgs.url = "github:NixOS/nixpkgs";
inputs.nix-alien.url = "github:thiagokokada/nix-alien";outputs = { self, nixpkgs, nix-alien }: {
nixosConfigurations.nix-alien-desktop = nixpkgs.lib.nixosSystem {
system = "x86_64-linux"; # or aarch64-linux
specialArgs = { inherit self; };
modules = [
({ self, ... }: {
nixpkgs.overlays = [
self.inputs.nix-alien.overlays.default
];
environment.systemPackages = with pkgs; [
nix-alien
];
# Optional, needed for `nix-alien-ld`
programs.nix-ld.enable = true;
})
];
};
};
}
```## Home-Manager Installation
You can add the following contents to your Home-Manager configuration file:
``` nix
{ ... }:let
nix-alien-pkgs = import (
builtins.fetchTarball "https://github.com/thiagokokada/nix-alien/tarball/master"
) { };
in
{
# ...
home.packages = with nix-alien-pkgs; [
nix-alien
];
}
```### Home-Manager installation with Flakes
If you're using Home-Manager with Flakes, you can use:
```nix
{
description = "nix-alien-on-home-manager";inputs.nixpkgs.url = "github:NixOS/nixpkgs";
inputs.home-manager.url = "github:nix-community/home-manager";
inputs.nix-alien.url = "github:thiagokokada/nix-alien";outputs = { self, nixpkgs, home-manager, nix-alien }:
let
system = "x86_64-linux"; # or aarch64-linux
pkgs = import nixpkgs { inherit system; };
in {
homeConfigurations.nix-alien-home = home-manager.lib.homeManagerConfiguration rec {
inherit pkgs;
extraSpecialArgs = { inherit self system; };
modules = [
({ self, system, ... }: {
home.packages = with self.inputs.nix-alien.packages.${system}; [
nix-alien
];
})
];
};
};
}
```## Development
On non-Flakes system, you can use `nix-shell` to start a development shell.
On Flakes enabled system, you can use `nix develop` instead.
If you have [`nix-direnv`](https://github.com/nix-community/nix-direnv/)
installed, there is a `.envrc` file configured to start the Flakes enabled
setup automatically. Just run `direnv allow` inside this repo.## Limitations
Binaries loading shared libraries dynamically (e.g.: with `dlopen`) will
probably not work with this script. However, this can be workarounded using
either `--additional-libs/-l` or `--additional-packages/-p` flag. The first one
can be used as:``` console
$ nix-alien -l libGL.so.1 -l libz.so.1 ~/myapp
```And this will be searched using `nix-locate` in a similar way as the other
libraries found in the binary. The second one can be used as:``` console
$ nix-alien -p libGL -p zlib ~/myapp
```To direct add the package to `default.nix` file.
> [!WARNING]
> There is no validation in `-p` flag, so you can receive an `undefied
> variable` error in case of an inexistent package.## Technical Description
This is achieved by enumerating the shared library dependencies from the ELF
header using `ldd` (actually,
[`pylddwrap`](https://github.com/Parquery/pylddwrap)) and then searching for the
equivalent library in `nixpkgs`. This is done by querying `nix-locate` locally.
To solve possible conflicts, human intervation is needed, but thanks to
[`fzf`](https://github.com/junegunn/fzf) and
[`pyfzf`](https://github.com/nk412/pyfzf) this is made easy by
showing an interactive list.## Credits
- Inspired by [Lassulus/nix-autobahn](https://github.com/Lassulus/nix-autobahn)
- Thanks to [Mic92/nix-ld](https://github.com/Mic92/nix-ld),
[Mic92/nix-index-database](https://github.com/Mic92/nix-index-database) and
[bennofs/nix-index](https://github.com/bennofs/nix-index), since without them
this project wouldn't be possible