DEV Community

Milos
Milos

Posted on

RVM Ruby 2.6.0 — built with custom openssl version on Ubuntu 22.04

Setup: Ubuntu 22.04, rvm, RoR (4.2.X), Ruby 2.1.7

Recently I had a task to update Ruby from 2.1.7 to 2.6.0 while keeping the RoR version to 4.2.X.

After standard rvm install 2.6.0 and bundle install command, I had to bump Rails to 4.2.8 due some incompatibility with gems, and then bundle install yielded some errors for gems, which I had to resolve by installing sudo apt-get install libxml12-dev libcurl14-openssl-dev packages, which coincidently removed libssl1, and the build passed.

But when I ran the RoR app, I got SSL certification issue from the 3rd party service, which was working fine with previous versions of Ruby and Rails: SSL_connect returned=1 errno=0 state=error: certificate verify failed (unable to get local issuer certificate)

So I removed Ruby 2.6.0 and tried to build from scratch, and got issue during ruby install process, apparently I was missing openssl library files. Ruby 2.6.0 was not compatible with the system openssl libs, which was strange since the first time it passed.

It turns out that libssl1 , which was removed was crucial, and the 2.6.0 can’t be built with the new libs which were installed via apt-get install command, but I needed those libs to do bundle install. So it was closed loop.

Solution #1 (which didn’t work)

After digging the web, the most common solution was to do following:

rvm pkg install openssl
rvm install 2.6.0 --with-openssl-dir=/usr/local/rvm/usr
Enter fullscreen mode Exit fullscreen mode

And that passed, Ruby was built, but the problem with the SSL certificate when Rails up was started was still present.

The issue was that version of openssl that comes with rvm is 1.0.1i and the openssl in the libssl1 is 1.0.2n , which can be seen here and here. So there was some incompatibility with openssl version and the SSL certificate. By the way, SSL certificate was issued by Let’s Encrypt, so it wasn’t some custom certificate.

Solution #2 (which worked)

I had to download 1.0.2n openssl from Github and build it, install it and then rebuilt Ruby against it.

Note here I was using Docker, but this can be done outside of the Docker of course.

Here are the steps for building Ruby via rvm against custom version of openssl:

  1. We will need 2 locations
  2. One where we git clone openssl.
  3. One where we will install the cloned version to (we will install it but not for system, just for our usage).
  4. For git clone we will use /tmp.
  5. For install location we will use a/opt/openssla (for this you can create tmp folder somewhere e.g. ~/tmp, or you can use /opt/tmp or /opt, just don’t use something that the system would use)
  6. Run/Add following commands in Dockerfile:
ENV OPENSSL_PREFIX=/opt/openssl
ENV SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt

WORKDIR /tmp
RUN git clone --branch OpenSSL_1_0_2n https://github.com/openssl/openssl.git
RUN cd openssl
RUN ./config shared --prefix=$OPENSSL_PREFIX --openssldir=$OPENSSL_PREFIX/ssl
RUN make
RUN make install

RUN rvm install 2.6.0 -C --with-openssl-dir=$OPENSSL_PREFIX
ENV PATH /usr/local/rvm/bin:$PATH
RUN rvm --default use ruby-2.6.0
ENV PATH /usr/local/rvm/bin:/usr/local/rvm/rubies/ruby-2.6.0/bin:$PATH
ENV GEM_HOME /usr/local/rvm/rubies/ruby-2.6.0/lib/ruby/gems/2.6.0
Enter fullscreen mode Exit fullscreen mode

And that’s it. If that was successful you have Ruby complied against custom openssl library.

Important notes:

  1. If you omit ENV SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt the build process will not fail, but when you do bundle install it will give you:
Fetching source index from https://rubygems.org/
Could not verify the SSL certificate for
https://rubygems.org/quick/Marshal.4.8/nokogiri-1.13.10-x86_64-linux.gemspec.rz.
There is a chance you are experiencing a man-in-the-middle attack, but most
likely your system doesn't have the CA certificates needed for verification. For
information about OpenSSL certificates, see http://bit.ly/ruby-ssl. To connect
without using SSL, edit your Gemfile sources and change 'https' to 'http'
Enter fullscreen mode Exit fullscreen mode

And you would try to fix this by doing gem update — system or whatever, but the problem is that it needs path to certs.

So don’t forget to add ENV SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt.

  1. You have to build/compile openssl as shared library, otherwise rvm will complain. And for that we have shared option in line: RUN ./config shared — prefix=$OPENSSL_PREFIX — openssldir=$OPENSSL_PREFIX/ssl
  2. You can do build against a bit higher version of openssl like 1.1.1 , in that case just do RUN git clone — branch OpenSSL_1_1_1 https://github.com/openssl/openssl.git instead.

Cheers!

Top comments (2)

Collapse
 
danku profile image
Daniel McMahon

Nice post on this! I had encountered a similar issue recently when trying to install Ruby v3.0 on a Mac M3 chipset using rvm. Quite often I have to flip between what openssl version my system is using, I think for legacy versions its requiring v1.1.1 and for more recent versions it uses the native v3.x.x version.

When I encountered this problem it was difficult to find users detailing the explanation online, great to see a post on dev about it like yours!

I know you can use a specific command to specify your openssl version during installation i.e. rvm install 2.4 --with-openssl-dir=$HOME/.rvm/usr but if I recall even with this I had to modify my .zshrc file to source similar directories to your post correctly.

Nice informative post!

Collapse
 
milosdukic profile image
Milos

Thx!