├── package.sh ├── list-ruby.sh ├── config.rc ├── package-ruby.sh └── README.md /package.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | . ./config.rc 4 | 5 | install_rvm 6 | fpm -s dir -t deb -C ./build -n rvm -v $(date +%Y%m%d%H%M%S) opt/rvm 7 | -------------------------------------------------------------------------------- /list-ruby.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | 4 | . ./config.rc 5 | 6 | if [ ! -f $rvm_path/scripts/rvm ] ; then 7 | # install rvm and retry. 8 | echo "RVM not found; installing now to $rvm_path" 9 | install_rvm 10 | exec bash $0 "$@" 11 | fi 12 | 13 | # Run this in a subshell so the rvm loading doesn't infect our current shell. 14 | ( 15 | . $rvm_path/scripts/rvm 16 | rvm list known 17 | ) 18 | 19 | -------------------------------------------------------------------------------- /config.rc: -------------------------------------------------------------------------------- 1 | PREFIX=/opt/rvm 2 | DESTDIR=$PWD/build 3 | 4 | export rvm_path=$DESTDIR/$PREFIX 5 | export rvm_prefix=$DESTDIR/$PREFIX 6 | export rvm_ignore_rvmrc=1 7 | 8 | install_rvm() { 9 | curl -B "https://rvm.beginrescueend.com/install/rvm" | bash 10 | 11 | ## Hack the 'rvm' loader to use $PREFIX, not wherever it's currently installed 12 | #( 13 | #rvm_orig="$rvm_path/src/rvm/scripts/rvm" 14 | #sed -ne 1p $rvm_orig 15 | #echo "[ -z "\$rvm_path" ] && export rvm_path=$PREFIX" 16 | #echo "[ -z "\$rvm_prefix" ] && export rvm_prefix=$PREFIX" 17 | #echo "[ -z "\$rvm_ignore_rvmrc" ] && export rvm_ignore_rvmrc=1" 18 | #sed -ne '2,$p' $rvm_orig 19 | #) > $rvm_path/scripts/rvm 20 | } 21 | -------------------------------------------------------------------------------- /package-ruby.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | wantruby=$1 4 | if [ -z "$wantruby" ] ; then 5 | echo "Usage: $0 " 6 | echo "Example: $0 jruby" 7 | exit 1 8 | fi 9 | 10 | . ./config.rc 11 | 12 | if [ ! -f $rvm_path/scripts/rvm ] ; then 13 | # install rvm and retry. 14 | echo "RVM not found; installing now to $rvm_path" 15 | install_rvm 16 | exec bash $0 "$@" 17 | fi 18 | 19 | # Run this in a subshell so the rvm loading doesn't infect our current shell. 20 | ( 21 | . $rvm_path/scripts/rvm 22 | rvm use $wantruby || rvm install $wantruby 23 | ) 24 | 25 | rubyinfo="$(. $rvm_path/scripts/rvm; rvm use $wantruby > /dev/null; rvm info | sed -ne '/^ ruby:/,/^ *$/p')" 26 | ruby="$(echo "$rubyinfo" | awk -F\" '/ interpreter:/ { print $2 }')" 27 | version="$(echo "$rubyinfo" | awk -F\" '/ version:/ { print $2 }')" 28 | rubyname="$(. $rvm_path/scripts/rvm; rvm use $wantruby > /dev/null; rvm current)" 29 | 30 | echo "rubyinfo: $rubyinfo" 31 | echo "ruby: $ruby" 32 | echo "version: $version" 33 | echo "name: $rubyname" 34 | 35 | # DESTDIR comes from 'config.rc' 36 | echo "patching rvm scripts to remove path '$DESTDIR/'" 37 | find $DESTDIR/$PREFIX/{wrappers,environments} -type f -print0 \ 38 | | xargs -0n1 sed -i -e "s,$DESTDIR/,,g" 39 | find $DESTDIR/$PREFIX/rubies/${rubyname} -type f -name '*.rb' -print0 \ 40 | | xargs -0n1 sed -i -e "s,$DESTDIR/,,g" 41 | find $DESTDIR/$PREFIX/rubies/${rubyname} -type f -name '*.h' -print0 \ 42 | | xargs -0n1 sed -i -e "s,$DESTDIR/,,g" 43 | for i in $DESTDIR/$PREFIX/{rubies/${rubyname}/bin,wrappers/${rubyname}}/{erb,gem,irb,rake,rdoc,ri,testrb} ; do 44 | sed -i -e "s,$DESTDIR/,,g" $i 45 | done 46 | 47 | # Mangle the 'ruby' binary to fix the RPATH (LD_RUN_PATH) stuff. 48 | rubybin=$DESTDIR/$PREFIX/rubies/${rubyname}/bin/ruby 49 | echo "Checking if we need to patch the ruby binary; $rubybin" 50 | if readelf -d $rubybin | grep RPATH | grep -qF $DESTDIR ; then 51 | echo "patching ruby binary to use correct library path" 52 | old_libpath=$(readelf -d $rubybin | grep RPATH | sed -re 's/.*\[(.*)\]/\1/') 53 | fixed_libpath=$(echo "$old_libpath" | sed -e "s,$DESTDIR/,,g") 54 | echo "Old: ${old_libpath}" 55 | echo "New: ${fixed_libpath}" 56 | export old_libpath 57 | export fixed_libpath 58 | # Replace the ld libpath with the fixed libpath, padded by nulls 59 | ruby -p -e ' 60 | $_.gsub!(ENV["old_libpath"]) do |s| 61 | ENV["fixed_libpath"] + ("\0" * (ENV["old_libpath"].size - ENV["fixed_libpath"].size)) 62 | end 63 | ' $rubybin > $rubybin.patched 64 | fi 65 | 66 | 67 | # skip the 'src' dir, too, we don't want it. 68 | 69 | echo "Packaging up $ruby-$version" 70 | [ -z "$iteration" ] && iteration=3 71 | fpm -s dir -t deb -C ./build -n rvm-${ruby}-${version} -v ${version}-${iteration} \ 72 | opt/rvm/{gems,rubies,wrappers,environments,log,bin}/${rubyname} 73 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Packaging rvm stuff for deployment 2 | 3 | The overal goal of this project is to help with deploying ruby apps. Solved here is the problem of packaging an rvm-provided ruby. Steps in general: 4 | 5 | * Forget about worrying about old versions of ruby. 6 | * Package up whatever version of ruby with this project 7 | * Package up your application (use bundler to vendor in the gem dependencies) 8 | * Deploy both to production. 9 | 10 | 'package.sh' packages 'rvm' for deployment if you want it, not required to deploy. 11 | 12 | 'package-ruby.sh' packages any ruby you choose to install with rvm. 13 | 14 | Requires fpm to package things. 15 | 16 | ## Notes on deployment 17 | 18 | Because rvm assumes installing to $HOME/.rvm/stuff, there's a bunch of hackery 19 | this package-ruby.sh does to 'undo' the assumptions. 20 | 21 | For example, if you package ruby 1.9.2, the resulting package will want to 22 | install to /opt/somewhere, where rvm believes it is installed to somewhere like 23 | this: 24 | 25 | % readelf -a ruby | grep 'Library' 26 | 0x000000000000000f (RPATH) Library rpath: [/home/jls/rvm-packaging/build//opt/rvm/rubies/ruby-1.9.2-p180/lib] 27 | 28 | Obviously this is wrong. That path won't exist when we install the package to 29 | production. Until I figure out the right way to solve this, I've worked around 30 | it by having a 'runner' script that looks like this: 31 | 32 | #!/bin/sh 33 | ruby="ruby-1.9.2-p180" 34 | export LD_LIBRARY_PATH=/opt/rvm/rubies/${ruby}/lib 35 | export GEM_HOME=./vendor/bundle/ruby/1.9.1/ 36 | export RUBYLIB=/opt/rvm/rubies/${ruby}/lib/ruby/1.9.1:/opt/rvm/rubies/${ruby}/lib/ruby/1.9.1/x86_64-linux/:./lib 37 | PATH=/opt/rvm/rubies/${ruby}/bin:${PATH} 38 | ruby "$@" 39 | 40 | Then to run a script with our rvm-packaged thing, I do: 41 | 42 | run.sh myscript.rb ... 43 | 44 | ## Example running with bundler deployment 45 | 46 | These steps assume you already built the ruby package you wanted from the 47 | examples further down on this page. 48 | 49 | Assuming you wrote an app and ran 'bundle install --deployment' and are now 50 | ready to deploy using ruby 1.9.2: 51 | 52 | % GEM_PATH=vendor/bundle/ruby/1.9.1/ /opt/rvm/rubies/ruby-1.9.2-p180/bin/ruby your-app.rb 53 | 54 | ## Example packaging jruby 55 | 56 | % bash package-ruby.sh jruby 57 | ... 58 | RVM not found; installing now to /home/jls/projects/rvm-packaging/build//opt/rvm 59 | ... 60 | WARN: jruby jruby-1.6.0 is not installed. 61 | To install do: 'rvm install jruby-1.6.0' 62 | jruby-1.6.0 - #fetching 63 | jruby-1.6.0 - #downloading jruby-bin-1.6.0, this may take a while depending on your connection... 64 | jruby-1.6.0 - #installing to /home/jls/projects/rvm-packaging/build//opt/rvm/rubies/jruby-1.6.0 65 | ... 66 | patching rvm scripts to remove path '/home/jls/projects/rvm-packaging/build/' 67 | Packaging up jruby-1.6.0 68 | Created /home/jls/projects/rvm-packaging/rvm-jruby_1.6.0-1_amd64.deb 69 | 70 | % sudo dpkg -i rvm-jruby_1.6.0-1_amd64.deb 71 | ... 72 | % /opt/rvm/wrappers/jruby-1.6.0/ruby -e 'puts [RUBY_PLATFORM, RUBY_VERSION].join("-")' 73 | java-1.8.7 74 | % /opt/rvm/wrappers/jruby-1.6.0/ruby --1.9 -e 'puts [RUBY_PLATFORM, RUBY_VERSION].join("-")' 75 | java-1.9.2 76 | 77 | 78 | ## Example packaging ruby 1.9.2 79 | 80 | % bash package-ruby.sh ruby-1.9.2 81 | ... 82 | ruby-1.9.2-p180 - #compiling 83 | ... 84 | patching rvm scripts to remove path '/home/jls/projects/rvm-packaging/build/' 85 | Packaging up ruby-1.9.2p180 86 | Created /home/jls/projects/rvm-packaging/rvm-ruby-1.9.2p180_1.9.2p180-1_amd64.deb 87 | 88 | % sudo dpkg -i rvm-ruby-1.9.2p180_1.9.2p180-1_amd64.deb 89 | ... 90 | 91 | % /opt/rvm/rubies/ruby-1.9.2-p180/bin/gem env 92 | RubyGems Environment: 93 | - RUBYGEMS VERSION: 1.3.7 94 | - RUBY VERSION: 1.8.7 (2010-06-23 patchlevel 299) [x86_64-linux] 95 | - INSTALLATION DIRECTORY: /opt/rvm/gems/ruby-1.9.2-p180 96 | - RUBY EXECUTABLE: /usr/bin/ruby1.8 97 | - EXECUTABLE DIRECTORY: /opt/rvm/gems/ruby-1.9.2-p180/bin 98 | - RUBYGEMS PLATFORMS: 99 | - ruby 100 | - x86_64-linux 101 | - GEM PATHS: 102 | - /opt/rvm/gems/ruby-1.9.2-p180 103 | - /opt/rvm/gems/ruby-1.9.2-p180@global 104 | - GEM CONFIGURATION: 105 | - :update_sources => true 106 | - :verbose => true 107 | - :benchmark => false 108 | - :backtrace => false 109 | - :bulk_threshold => 1000 110 | - REMOTE SOURCES: 111 | - http://rubygems.org/ 112 | 113 | 114 | 115 | --------------------------------------------------------------------------------