Skip to content

Instantly share code, notes, and snippets.

@brandondrew
Last active January 3, 2023 04:46
Show Gist options
  • Save brandondrew/ebb2d94f7f85a77986f66a447c0e2257 to your computer and use it in GitHub Desktop.
Save brandondrew/ebb2d94f7f85a77986f66a447c0e2257 to your computer and use it in GitHub Desktop.
How To Upgrade Ruby for your Rails App, Locally & on a Server with Passenger
Overview
--------
Consider the commands given to be examples, not to necessarily be precisely
what you will use. They were based on my circumstances, in which
* my local platform is macOS,
* where Homebrew is the de facto package manager;
* my laptop (and the server) are managing Ruby with rbenv;
* vim is my remote editor of choice, and an acceptable local editor; and
* the server is using nginx and passenger.
If you have a different setup, then you'll need to adapt your commands
accordingly, but the main points may remain the same. This may still
prevent you from forgetting an important change that you need to make.
Upgrading your Local Ruby Environment
-------------------------------------
First, ensure you've got the latest versions of your tools to upgrade Ruby
brew update
brew upgrade ruby-build rbenv
Let's set a variable to represent the version of Ruby you're installing, so we can use it everywhere.
We'll be ~~lazy~~ *efficient* and make it something easy to type
RB='2.7.4'
Locally install the version of Ruby you're going to upgrade to:
rbenv install $RB
Update all 3 places that your Ruby version is listed in your app. This is
one of the things that is so easy to forget.
vim .ruby-version .travis.yml Gemfile
You may need to reinstall the version of Bundler listed in your Gemfile.lock,
if you're not using the latest one. You may want to update Bundler too, but
here we're focusing on Ruby.
tail Gemfile.lock # Bundler version used
bundler --version # Bundler version installed
command gem install bundler:2.1.4 --no-document # if needed
Reinstall your gems:
bundle install
Updating your Server
--------------------
After you push to origin, create a pull request, and merge to master,
ensure you've got the latest versions of Ruby available on the server.
Log in as the current app user, and issue a command like this:
cd /home/app_portal/.rbenv/plugins/ruby-build && git pull && cd -
If you first try to install the version of Ruby directly, and it fails,
the output will list the exact command to use to update available Rubies.
Check to see what is already installed, to see if someone else has already
installed the version you want:
rbenv versions
Next install the new version of Ruby (obviously replacing the version here with the one you're installing):
RB='2.7.4'
rbenv install $RB
You might get a message like
rbenv: cannot rehash: /home/app_portal/.rbenv/shims/.rbenv-shim exists
The developers of rbenv don't even seem to know why this happens. But you can fix it with
rm /home/app_portal/.rbenv/shims/.rbenv-shim
rbenv rehash
Next, switch to that version of Ruby (and perhaps install bundler, using whatever version your Gemfile expects):
cd # you can alternately cd to /tmp if you don't want this version as default
rbenv local $RB
command gem install bundler:2.1.4 --no-document # if you need this
After you deploy your new app, make a change to the configuration to list the path
to the new Ruby. You may need to switch to a new user, but your command should be something like:
sudo vim /etc/nginx/sites-available/portal.conf
If instead of editing your config file you've had the foresight to create a symbolic link
to the current version of Ruby, you can instead change it with something like this:
rm -i /home/app_portal/.rbenv/versions/current
ln -s /home/app_portal/.rbenv/versions/"$RB" /home/app_portal/.rbenv/versions/current
Unfortunately, whether you use the symbolic link or you edit the nginx config file every time,
you _may_ still need to restart nginx to pick up this change (but try `reload`ing).. (Simply restarting your app does not seem
to be sufficient.) This turns out to be true even if you use a symbolic link to point
to the current version of Ruby, and change the link rather than changing your Passenger
configuration. This is a major drawback of using Passenger + nginx, in my opinion. I would
personally be very much inclined to choose something else, if other options lack this problem.
sudo service nginx reload # try this first and see if it is sufficient
sudo service nginx restart # this definitely works, but momentarily impacts other apps on the server
If you add this change of the symbolic link along with the subsequent restart of nginx to
your deployment process, you can install the new version of Ruby and then just deploy.
That should really be the goal.
You should also add a deployment step that checks for the availability of the Ruby version
specified in `.ruby-version` at the very beginning of the deployment, and terminate
it if that's not available.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment