Exodus
Painless relocation of Linux binaries–and all of their dependencies–without containers.
Install / Use
/learn @intoli/ExodusREADME
Exodus is a tool that makes it easy to successfully relocate Linux ELF binaries from one system to another. This is useful in situations where you don't have root access on a machine or where a package simply isn't available for a given Linux distribution. For example, CentOS 6.X and Amazon Linux don't have packages for Google Chrome or aria2. Server-oriented distributions tend to have more limited and outdated packages than desktop distributions, so it's fairly common that one might have a piece of software installed on their laptop that they can't easily install on a remote machine.
With exodus, transferring a piece of software that's working on one computer to another is as simple as this.
exodus aria2c | ssh intoli.com
Exodus handles bundling all of the binary's dependencies, compiling a statically linked wrapper for the executable that invokes the relocated linker directly, and installing the bundle in ~/.exodus/ on the remote machine.
You can see it in action here.

Table of Contents
- The Problem Being Solved - An overview of some of the challenges that arise when relocating binaries.
- Installation - Instructions for installing exodus.
- Usage
- The Command-Line Interface - The options supported by the command-line utility.
- Usage Examples - Common usage patterns, helpful for getting started quickly.
- How It Works - An overview of how exodus works.
- Known Limitations - Situations that are currently outside the scope of what exodus can handle.
- Development - Instructions for setting up the development environment.
- Contributing - Guidelines for contributing.
- License - License details for the project.
The Problem Being Solved
If you simply copy an executable file from one system to another, then you're very likely going to run into problems. Most binaries available on Linux are dynamically linked and depend on a number of external library files. You'll get an error like this when running a relocated binary when it has a missing dependency.
aria2c: error while loading shared libraries: libgnutls.so.30: cannot open shared object file: No such file or directory
You can try to install these libraries manually, or to relocate them and set LD_LIBRARY_PATH to wherever you put them, but it turns out that the locations of the ld-linux linker and the glibc libraries are hardcoded.
Things can very quickly turn into a mess of relocation errors,
aria2c: relocation error: /lib/libpthread.so.0: symbol __getrlimit, version
GLIBC_PRIVATE not defined in file libc.so.6 with link time reference
segmentation faults,
Segmentation fault (core dumped)
or, if you're really unlucky, this very confusing symptom of a missing linker.
$ ./aria2c
bash: ./aria2c: No such file or directory
$ ls -lha ./aria2c
-rwxr-xr-x 1 sangaline sangaline 2.8M Jan 30 21:18 ./aria2c
Exodus works around these issues by compiling a small statically linked launcher binary that invokes the relocated linker directly with any hardcoded RPATH library paths overridden.
The relocated binary will run with the exact same linker and libraries that it ran with on its origin machine.
Installation
The package can be installed from the package on pypi.
Running the following will install exodus locally for your current user.
pip install --user exodus-bundler
You will then need to add ~/.local/bin/ to your PATH variable in order to run the exodus executable (if you haven't already done so).
This can be done by adding
export PATH="~/.local/bin/:${PATH}"
to your ~/.bashrc file.
Optional/Recommended Dependencies
It is also highly recommended that you install gcc and one of either musl libc or diet libc on the machine where you'll be packaging binaries. If present, these small C libraries will be used to compile small statically linked launchers for the bundled applications. An equivalent shell script will be used as a fallback, but it carries significant overhead compared to the compiled launchers.
Usage
Command-Line Interface
The command-line interface supports the following options.
usage: exodus [-h] [-c CHROOT_PATH] [-a DEPENDENCY] [-d] [--no-symlink FILE]
[-o OUTPUT_FILE] [-q] [-r [NEW_NAME]] [--shell-launchers] [-t]
[-v]
EXECUTABLE [EXECUTABLE ...]
Bundle ELF binary executables with all of their runtime dependencies so that
they can be relocated to other systems with incompatible system libraries.
positional arguments:
EXECUTABLE One or more ELF executables to include in the exodus
bundle.
optional arguments:
-h, --help show this help message and exit
-c CHROOT_PATH, --chroot CHROOT_PATH
A directory that will be treated as the root during
linking. Useful for testing and bundling extracted
packages that won't run without a chroot. (default:
None)
-a DEPENDENCY, --add DEPENDENCY, --additional-file DEPENDENCY
Specifies an additional file to include in the bundle,
useful for adding programatically loaded libraries and
other non-library dependencies. The argument can be
used more than once to include multiple files, and
directories will be included recursively. (default:
[])
-d, --detect Attempt to autodetect direct dependencies using the
system package manager. Operating system support is
limited. (default: False)
--no-symlink FILE Signifies that a file must not be symlinked to the
deduplicated data directory. This is useful if a file
looks for other resources based on paths relative its
own location. This is enabled by default for
executables. (default: [])
-o OUTPUT_FILE, --output OUTPUT_FILE
The file where the bundle will be written out to. The
extension depends on the output type. The
"{{executables}}" and "{{extension}}" template strings
can be used in the provided filename. If omitted, the
output will go to stdout when it is being piped, or to
"./exodus-{{executables}}-bundle.{{extension}}"
otherwise. (default: None)
-q, --quiet Suppress warning messages. (default: False)
-r [NEW_NAME], --rename [NEW_NAME]
Renames the binary executable(s) before packaging. The
order of rename tags must match the order of
positional executable arguments. (default: [])
--shell-launchers Force the use of shell launchers instead of attempting
to compile statically linked ones. (default: False)
-t, --tarball Creates a tarball for manual extraction instead of an
installation script. Note that this will change the
output extension from ".sh" to ".tgz". (default:
False)
-v, --verbose Output additio
