Ruby to EXE – Turn ruby scripts into portable executable apps

This method works with:

  1. Rails apps (your portable app will be a webserver);
  2. Scripts with gems;
  3. Multiple source file scripts;
  4. Simple, single source file scripts;

The final app is a single executable file that can run on systems without a ruby interpreter installed.


I developed a gem that automates this process. Check it out:


gem install rb2exe

echo "puts 'Hello world'" > test.rb
rb2exe test.rb

1. First, let’s create a simple Hello World app:

$ mkdir hello
$ cd hello
$ echo "puts 'Hello world'" > test.rb
$ ruby test.rb
Hello World

Part I: Standalone Ruby

2. Your ruby version should be 2.2.2, 64 bits:


If your version is different, please install the 2.2.2 (e.g. “rvm use 2.2.2”).
This will NOT work with 2.2.0, 2.2.3, 2.1, etc.

3. Duplicate the project folder, naming it as “app”:

$ cd ..
$ cp -r -pa hello app

4. In the project folder, create a “.package/payload/lib/ruby” sub-folder:

$ cd hello
$ mkdir -p .package/payload/lib/ruby

5. Move the “app” folder to “.package/payload/lib”

$ mv ../app .package/payload/lib
$ tree -a
├── .package
│   └── payload
│       └── lib
│           ├── app
│           │   └── test.rb
│           └── ruby
└── test.rb

6. Download ruby traveler 2.2.2 64 bits (5.6M), and unzip it on “.package/payload/lib/ruby”:

$ cd .package/payload/lib/ruby
$ wget
$ tar -xf traveling-ruby-20150715-2.2.2-linux-x86_64.tar.gz
$ rm traveling-ruby-20150715-2.2.2-linux-x86_64.tar.gz

7. Go back to “.package/payload/”:

$ cd ../..
$ pwd

8. Create a wrapper script (name it as “installer”):

$ nano installer
set -e

# Figure out where this script is located.
SELFDIR="`dirname \"$0\"`"
SELFDIR="`cd \"$SELFDIR\" && pwd`"

if [ -f "$SELFDIR/lib/vendor/Gemfile" ]
  # Tell Bundler where the Gemfile and gems are.
  export BUNDLE_GEMFILE="$SELFDIR/lib/vendor/Gemfile"

  # Run the actual app using the bundled Ruby interpreter, with Bundler activated.
  exec "$SELFDIR/lib/ruby/bin/ruby" -rbundler/setup "$SELFDIR/lib/app/test.rb"
  exec "$SELFDIR/lib/ruby/bin/ruby" "$SELFDIR/lib/app/test.rb"
chmod +x installer

Replace the “exec” line with your actual command to start the application. Eg. for Rails apps, it should be:
RAILS_ENV=production exec “$SELFDIR/lib/ruby/bin/ruby” -rbundler/setup “$SELFDIR/lib/app/bin/rails” server

The above script is based on the “traveling ruby” tutorial.

Part II: Gemfile

If your project has a Gemfile, you need to follow these extra steps:

9. Create a “tmp” folder on “.package/payload/lib”

$ cd lib
$ mkdir tmp
$ cd tmp

10. Copy the project Gemfile to tmp

$ cp ../app/Gemfile* .

11. Download gems into the “lib/vendor” folder

$ BUNDLE_IGNORE_CONFIG=1 bundle install --path ../vendor --without development

12. Delete tmp folder

$ cd ..
$ rm -Rf tmp

13. [Optional] Delete gem’s cache in the vendor folder

$ rm -f vendor/*/*/cache/*

14. Copy the Gemfile to the vendor folder

$ cp app/Gemfile* vendor/

15. Create a bundler config

$ mkdir vendor/.bundle/
$ cd vendor/.bundle/
$ nano config
BUNDLE_WITHOUT: development

Part III: Pack everything as a single self-extract file

This part is based on this Jeff Parent’s article.

17. Create a script to decompress everything

export TMPDIR=`mktemp -d /tmp/selfextract.XXXXXX`

ARCHIVE=`awk '/^__ARCHIVE_BELOW__/ {print NR + 1; exit 0; }' $0`

tail -n+$ARCHIVE $0 | tar -xz -C $TMPDIR


cd $CDIR
rm -rf $TMPDIR

exit 0


18. Package builder

cd payload
tar cf ../payload.tar ./*
cd ..

if [ -e "payload.tar" ]; then
    gzip payload.tar

    if [ -e "payload.tar.gz" ]; then
        cat decompress payload.tar.gz > output
        echo "payload.tar.gz does not exist"
        exit 1
    echo "payload.tar does not exist"
    exit 1

chmod +x output
echo "Self-extract file created"
exit 0
$ chmod +x decompress
$ chmod +x build
$ ./build
Self-extract file created

And that’s it. You can now rename and distribute the generated “output” file :)

Close Menu