
OpenSSL error installing Ruby
There's a big mess in the Ruby world right now: Ruby can't find its OpenSSL dependency. The solution consists of telling Ruby where to find OpenSSL. If that fails, downgrade to a version it can find.
Contents
- Scope of the problem
- Error messages
- The best solution
- Older versions, a less-good solution
- Further reading and credit
Scope of the problem
I am having a persistent problem installing Ruby. It is OpenSSL problem, one that a lot of other people in the Ruby community also seem to be banging their heads against. The Ruby installer apparently cannot find its OpenSSL dependency or (my theory) it gets jammed between two different versions of OpenSSL. Some users have recoursed to downgrading to old, potentially unsafe versions of OpenSSL. Lots of software development is blocked and insecure code is running. This situation is a mess.
At minimum, this is scope of the problem:
- It impacts people who install Ruby with rbenv, rvm, or chruby, and apparently people who build Ruby from source.
- It impacts Macs with any chips: M1, M2, M3 or Intel. (MacOS and maybe Ubuntu?)
- It happens to people who install OpenSSL with both Homebrew and MacPorts.
- It happens with most or all versions of Ruby! The problem seems to crop up for people who at some point install Ruby 3.1 and above. But, after that, it can mess up your ability to install lower versions on the same computer.
It looks like this problem has been exploding in frequency since Christmas of 2021, when Ruby 3.1 was released. At that time, the language added support for OpenSSL version 3 to Ruby's standard library. This is great news for security reasons, but it adds a hitch to installation for many users. Your system either loses track of the installed OpenSSL or can get jammed between OpenSSL versions with some parts pointing to version 1 and some to version 3 of OpenSSL. The result can be that you are no longer able to install any version of Ruby.
Error messages
I first noticed the problem when running the rvm install 3.3.0 command. The command outputs this, asking you to open a log file:
Error running '__rvm_make -j8',
please read /Users/johnsskinner/.rvm/log/1705608818_ruby-3.3.0/make.log
There has been an error while running make. Halting the installation.
The problem often presents itself with variations on this error message, such as Error running '__rvm_make -j10'
or Error running '__rvm_make -j16'
. The "j" flag followed by a number stands for "jobs." I think the number of jobs is determined by the number of cores in your processor.
I recommend opening this log file in a text editor. Search the log for the string error
and you'll find the errors are rather obscure (and vary depending on the situation). Now search for the string openssl@
— if you see references to a mix of different version numbers after the @ sign, your machine is stuck between OpenSSL versions. It is confused!

The errors in the log file typically point to trouble running these C files, which are a part of OpenSSL for Ruby, Ruby's wrapper for the shared OpenSSL library:
- openssl_missing.h
- ossl.c
- ossl_pkey_rsa.o
- ossl_hmac.o
An example line in the log file that indicates the problem:
make[2]: *** [ossl_hmac.o] Error 1
Click to expand a longer example from the log file
In file included from ossl_config.c:10:
In file included from ./ossl.h:177:
./openssl_missing.h:195:11: warning: 'TS_VERIFY_CTS_set_certs' macro redefined [-Wmacro-redefined]
# define TS_VERIFY_CTS_set_certs(ctx, crts) ((ctx)->certs=(crts))
^
/usr/local/Cellar/openssl@3/3.2.1/include/openssl/ts.h:426:11: note: previous definition is here
# define TS_VERIFY_CTS_set_certs(ctx, cert) TS_VERIFY_CTX_set_certs(ctx,cert)
^
linking shared-object readline.bundle
In file included from ossl_digest.c:10:
In file included from ./ossl.h:177:
./openssl_missing.h:195:11: warning: 'TS_VERIFY_CTS_set_certs' macro redefined [-Wmacro-redefined]
# define TS_VERIFY_CTS_set_certs(ctx, crts) ((ctx)->certs=(crts))
^
/usr/local/Cellar/openssl@3/3.2.1/include/openssl/ts.h:426:11: note: previous definition is here
# define TS_VERIFY_CTS_set_certs(ctx, cert) TS_VERIFY_CTX_set_certs(ctx,cert)
^
linking shared-object nkf.bundle
In file included from ossl_engine.c:10:
In file included from ./ossl.h:177:
./openssl_missing.h:195:11: warning: 'TS_VERIFY_CTS_set_certs' macro redefined [-Wmacro-redefined]
# define TS_VERIFY_CTS_set_certs(ctx, crts) ((ctx)->certs=(crts))
^
/usr/local/Cellar/openssl@3/3.2.1/include/openssl/ts.h:426:11: note: previous definition is here
# define TS_VERIFY_CTS_set_certs(ctx, cert) TS_VERIFY_CTX_set_certs(ctx,cert)
^
1 warning generated.
compiling constants.c
ld: warning: ignoring duplicate libraries: '-lruby.3.2'
1 warning generated.
1 warning generated.
compiling strscan.c
compiling ossl_hmac.c
ld: warning: ignoring duplicate libraries: '-lruby.3.2'
compiling basicsocket.c
checking ../.././parse.y and ../.././ext/ripper/eventids2.c
compiling ossl_kdf.c
compiling syslog.c
ripper.c:10310:9: warning: variable 'yynerrs' set but not used [-Wunused-but-set-variable]
int yynerrs = 0;
^
In file included from ossl_hmac.c:10:
In file included from ./ossl.h:177:
./openssl_missing.h:195:11: warning: 'TS_VERIFY_CTS_set_certs' macro redefined [-Wmacro-redefined]
# define TS_VERIFY_CTS_set_certs(ctx, crts) ((ctx)->certs=(crts))
^
/usr/local/Cellar/openssl@3/3.2.1/include/openssl/ts.h:426:11: note: previous definition is here
# define TS_VERIFY_CTS_set_certs(ctx, cert) TS_VERIFY_CTX_set_certs(ctx,cert)
^
ossl_hmac.c:249:35: error: incomplete definition of type 'struct evp_md_ctx_st'
pkey = EVP_PKEY_CTX_get0_pkey(EVP_MD_CTX_get_pkey_ctx(ctx));
^~~~~~~~~~~~~~~~~~~~~~~~~~~~
./openssl_missing.h:230:41: note: expanded from macro 'EVP_MD_CTX_get_pkey_ctx'
# define EVP_MD_CTX_get_pkey_ctx(x) (x)->pctx
~~~^
/usr/local/Cellar/openssl@3/3.2.1/include/openssl/types.h:107:16: note: forward declaration of 'struct evp_md_ctx_st'
typedef struct evp_md_ctx_st EVP_MD_CTX;
^
1 warning and 1 error generated.
make[2]: *** [ossl_hmac.o] Error 1
make[2]: *** Waiting for unfinished jobs....
compiling socket.c
installing default ripper libraries
In file included from ossl_kdf.c:5:
In file included from ./ossl.h:177:
./openssl_missing.h:195:11: warning: 'TS_VERIFY_CTS_set_certs' macro redefined [-Wmacro-redefined]
# define TS_VERIFY_CTS_set_certs(ctx, crts) ((ctx)->certs=(crts))
^
/usr/local/Cellar/openssl@3/3.2.1/include/openssl/ts.h:426:11: note: previous definition is here
# define TS_VERIFY_CTS_set_certs(ctx, cert) TS_VERIFY_CTX_set_certs(ctx,cert)
^
compiling zlib.c
1 warning generated.
make[1]: *** [ext/openssl/all] Error 2
make[1]: *** Waiting for unfinished jobs....
compiling ipsocket.c
linking shared-object syslog.bundle
linking shared-object strscan.bundle
ld: warning: ignoring duplicate libraries: '-lruby.3.2'
ld: warning: ignoring duplicate libraries: '-lruby.3.2'
installing default syslog libraries
linking shared-object stringio.bundle
compiling tcpsocket.c
compiling tcpserver.c
ld: warning: ignoring duplicate libraries: '-lruby.3.2'
compiling sockssocket.c
compiling udpsocket.c
compiling unixsocket.c
compiling unixserver.c
compiling option.c
compiling ancdata.c
compiling raddrinfo.c
compiling ifaddr.c
installing default socket libraries
linking shared-object zlib.bundle
ld: warning: ignoring duplicate libraries: '-lruby.3.2'
linking shared-object socket.bundle
ld: warning: ignoring duplicate libraries: '-lruby.3.2'
1 warning generated.
linking shared-object ripper.bundle
ld: warning: ignoring duplicate libraries: '-lruby.3.2'
make: *** [build-ext] Error 2
+__rvm_make:0> return 2
While investigating this problem, I tried installing various versions of Ruby. Back in version 2 the error message (for apparently the same problem) was somewhat more clear:
kernel_require.rb:83:in `require': cannot load such file -- openssl (LoadError)
A search for the Ruby version 2 error message reveals that people have been having some variety of this problem for more than a decade.
The best solution
The ideal is to use version 3 of OpenSSL. Version 1 is deprecated, and version 2 never existed! To use this up-to-date version of OpenSSL, you must be installing Ruby version 3.1 or higher. This is because Ruby versions 3.0 and before require older versions of OpenSSL. (I talk about these older versions in the next section.)
As a Homebrew user, I use the below command to install the latest OpenSSL:
brew install openssl@3
Now OpenSSL version 3 has been installed somewhere. But Ruby does not know where. Or more accurately, it is Ruby's wrapper for OpenSSL which does not know. The wrapper requires the user to specify where "in some cases." If you are seeing this problem, you are one of these cases.
You will need to get this installation location from Homebrew and pass it along to the Ruby wrapper. How you do that varies a little depending on what software you use to manage Ruby versions:
As an RVM user, I use the command:
rvm install 3.3.0 --with-openssl-dir=$(brew --prefix openssl@3)
Those who use rbenv to manage their Ruby versions would instead run:
RUBY_CONFIGURE_OPTS="--with-openssl-dir=$(brew --prefix openssl@3)" rbenv install 3.3.0
Fill in the Ruby version number you are trying to install. But remember, this only works for Ruby 3.1 or higher. Refer to the Older Versions section if you must use a version of Ruby older than 3.1.
After you do this, you might have a working version of Ruby. You can verify the installation of Ruby by listing the versions you now have installed using rvm list or rbenv versions.
On the other hand, maybe the above won't work for you! After all, Ruby's OpenSSL gem has a bug report open right now in which the --with-openssl-dir
option just doesn't work correctly in some cases. Computers are hard, who knows. A fallback option is to try an older version of the OpenSSL library:
Older versions, a less-good solution
If the above "best solution" does not work for you, there are other, sketchier possibilities. They involve tinkering with Ruby and OpenSSL versions. This table illuminates what is possible:
Ruby version | Maximum OpenSSL version |
---|---|
Ruby 3.1 and newer | OpenSSL 3.0 (currently the newest) |
Ruby 2.4 to 3.0 | OpenSSL up to 1.1 |
Ruby 2.3 and older | OpenSSL up to 1.0 (scary old) |
Ideally you should use the most up-to-date version of OpenSSL supported by your version of Ruby, as listed in the table. Yet, some people appear to be having luck resolving their Ruby installation error by downgrading their OpenSSL version below the newest that is officially supported by their Ruby version. In practice, this probably means downgrading to version 1.1 of OpenSSL. Remember, version 2 never existed. And version 1.0 is "scary old" as you can see in the table.
⚠ Warning: There is some advice going around (on this Homebrew GitHub thread for example) that the solution to this error is to downgrade your OpenSSL to version 1.0, an ancient (2010) version which is no longer supported. This is probably a bad idea unless you must install an old version of Ruby (2.3 or earlier) which requires it. OpenSSL version 1.0 has not been getting security updates since 2015 and OpenSSL version 1.1 stopped getting security updates as of late 2023. Using either of these is risky!
In fact, openssl@1.1
is so old and insecure that Homebrew wisely stopped supporting this outdated version. So, if you are a homebrew user and you want to follow the below steps, you will have to circumvent this limit. Obviously, you would be playing a dangerous game. You may go to SSL jail.
Run this installation command to verify that the old OpenSSL version "has been disabled because it is not supported upstream":
brew install openssl@1.1
If you're sure you really wanna do this, circumvent the disabled status by editing Ruby a file:
brew edit openssl@1.1
This should open the file openssl@1.1.rb
in your system's text editor. Comment out any line in this file that starts with disable!
or deprecate!
. The resulting file will contain something like this:
# disable! date: "2024-10-24", because: :unsupported
Now that you have sabotaged the file, complete your crime by running:
HOMEBREW_NO_INSTALL_FROM_API=1 brew install openssl@1.1
You might have to re-run the above steps a few times: maybe once to get the local file, then another time after you've commented out the disable line. You might have to try reinstall
in addition to install
in the above command.
OK, now that you have sinfully installed an old version of OpenSSL, there is another trick. Skipping this is where people get tangled up in this problem for a long time:
- If you have ever installed OpenSSL version 3 (as in the "best solution" section above)
- or, if you have ever installed Ruby 3.1 or higher on your computer
then you must unlink OpenSSL version 3 and link up the downgraded version.
brew unlink openssl@3
brew link openssl@1.1
Don't skip the unlinking and linking. Things can get confusingly tangled if you skip the step.
If the step fails, you might have to remove bits of the OpenSSL version 3 configuration. Or, you might have to add the --force
option to the above link and/or unlink commands.
Finally, use RVM or rbenv to install your Ruby version as you usually would. For example:
rvm install 3.2.2
Once you get Ruby installed, you can verify the OpenSSL version it is using with:
ruby -ropenssl -e 'puts OpenSSL::OPENSSL_LIBRARY_VERSION'
When you change Ruby versions (with rvm use 3.0.0
or whatever) the OpenSSL version should change according to however you set up that Ruby version. It should be no problem to have multiple versions of Ruby and multiple versions of OpenSSL installed at the same time.
What if none of the above has worked for you? You can start digging through the further reading section. If you learn something I don't know, please reach out to me on Mastodon.
What if downgrading did work for you but now you feel bad about running a out-of-date version of OpenSSL? Then you are smart! OpenSSL's Heartbleed bug, a decade ago, was the most catastrophic security problem in internet history to that date. If a similar bug were discovered today, when you and howevermany other Rubyists are running a copy of OpenSSL no longer getting any security updates, with no clear path to upgrade, it would be a disaster the scale of which I don't like to contemplate.

It is rational to want to keep running an old version of Ruby on a legacy app where it works well enough. But open-source software is typically created by volunteers who unfortunately have limited time, and who have chosen not to patch old versions of OpenSSL and Ruby. This classic XKCD cartoon captures the situation.
Update: shortly after I wrote this, the XZ backdoor vividly illustrated my point that OpenSSL exploits are a catastrophe waiting to happen, and limited volunteer time is a major problem.
OpenSSL version 3 is not yet a hard requirement of Ruby, but it will probably become a hard requirmenet of some Ruby installation methods. Unless your Ruby app is an offline one, it is time to accept that you must upgrade. Ruby 3.0 and below will never be secure.
Further reading and credit
More about this problem from GitHub and blogs:
-
Installing with
LDFLAGS
settings by blogger Nicky Marino - While using rbenv, containing a reminder to keep Xcode up to date
- While using MacPorts featuring more advice on how to unlink and re-link OpenSSL
- Using RVM and MacPorts by blogger Jakob Skjerning
- With a deeper dive into Homebrew and its binutils
- While trying to downgrade to OpenSSL version 1.0 which, once again, you probably shouldn't do
People who helped me with this: