Upgrading Foreman to a supported Rails version

I’m capturing notes from a discussion with @ehelms on how to proceed with this.

Today Foreman is on Rails 7.0 and that’s been EOL since April 2025. The challenge is that Rails 7.2 (which itself is EOL since 2 weeks) has started to require Ruby 3.1. Ruby & Rails Compatibility Table | FastRuby.io is a nice overview.

Looking at Foreman 5.0 we’ll have the following supported operating systems and their Ruby versions.

OS Ruby
Debian 12 Ruby 3.1
Ubuntu 22.04 Ruby 3.0
Ubuntu 24.04 Ruby 3.2
EL 9 Ruby 3.0
EL 10 Ruby 3.3

Luckily Debian isn’t an issue. For Ubuntu we’re adding support for Ubuntu 24.04 in Foreman 5.0, which allows to deprecate Ubuntu 22.04 for Foreman 5.1. Those shouldn’t be the issue.

On the EL side it gets more complicated. We only started support for EL 10 very recently (Rebuilding our RPMs for el10) and right now don’t have an installer supported build while containers are feature incomplete. Even if we add installer support today, that may not take care of upgrades.

So we’re at an impasse: we can’t just drop EL 9 now without upsetting at least half of our community, if not more. On the other hand, using an unsupported Rails version is also a security risk waiting to happen.

I don’t see a whole lot of options, so if you see more then I’d love to hear more if you have them.

Accept the risk and continue containerization

This assumes that long term we want to move everyone from RPM-based installations to containerized installations.

Requirements:

  • Feature parity in foremanctl
  • A migration path from package-based installations to containerized
  • Get the community migrated

Benefits:

  • Fits the long term desire to only support containerized installations

Downsides:

  • May take a while during which we are at risk

Support EL 10 RPM-based installations & upgrades

Here we would introduce foreman-installer on EL 10 and see what’s needed to support upgrades.

Requirements:

  • EL10 compatibility in foreman-installer
  • Supported upgrade path from EL9 to EL10

Benefits:

  • Possibly short term feasible (to be tested)

Downsides:

  • Investing in a path we’d like to deprecate

Update EL9 to Ruby 3.1+ using DNF modules

EL9 does have a DNF module for a newer Ruby version that could be used. This is by far the least desirable option, but I want to mention it anyway.

Requirements:

  • Rebuild all (Ruby) packages
  • Extend the installer to enable the correct DNF modules

Benefits:

  • No need to get everyone to EL10

Downsides:

  • A huge amount of effort
  • DNF modules are complex for both packagers and users
3 Likes

For option 2 I’m taking a stab to see how hard it is. Writing down my steps.

I used GitHub - theforeman/foreman-installer-modulesync: Standard config files used across foreman-installer modules · GitHub to create a checkout for every module and then this simple script:

#!/usr/bin/env ruby

# frozen_string_literal: true

require 'json'

Dir['modules/*/puppet-*/metadata.json'].each do |path|
  metadata = JSON.parse(File.read(path))
  changed = false
  metadata['operatingsystem_support'].each do |os|
    if %w[RedHat CentOS AlmaLinux].include?(os['operatingsystem']) && !os['operatingsystemrelease'].include?('10')
      os['operatingsystemrelease'] << '10'
      changed = true
    end
  end

  File.write(path, "#{JSON.pretty_generate(metadata)}\n") if changed
end

For puppet-dns I also made a manual modification to enable EPEL 10 since that should include ISC DHCP (thanks Rebuilding our RPMs for el10 - #7 by bnerickson for the hint).

Then create the PRs using some shell:

for i in modules/theforeman/puppet-* ; do
  (
    cd $i && git checkout -b add-el10 && git commit -a -m 'Add EL 10 support' && git push --quiet $USER HEAD && hub pull-request --no-edit
  )
done

Now let’s see how unhappy CI is.

2 Likes

And it looks like we may first need a round of modulesync to update to the latest CI stack that supports EL 10. The rabbit hole is always deeper than you think.

1 Like

Big thanks to @bastelfreak for assisting with the modulesync PRs:

There are a few related ones. They’re largely ready, but some need a bit more work. Once those are ready, I can rebase my EL10 PRs.

1 Like

Looks like it largely passes tests, with the major exception being ISC DHCP (as expected). Candlepin may be an interesting case because that is a bit special, but I ran out of time today.

My two cents

That’s an understatement :joy:

For which path to choose, I think it also depends on how much time is needed to have feature parity and a migration path that allows to carry over existing data (no report loss, no machines to re-enroll, no SSL CA/certs to redeploy on clients etc). I want to stress the second part as if it requires reinstalling from scratch, migration will take way longer.

  • Accept the risk and continue containerization
    • Might be acceptable if time window is not very long. If clients are trusted and the login is not exposed on a public IP (IMHO it shouldn’t be exposed to the public, but Shodan tells a different story)
    • Might be mitigated with an announcement/advisory to keep web UI behind a firewall/on a private network/not exposed to the public internet (and again, IMHO should be always like this XD)
  • Support EL 10 RPM-based installations & upgrades
    • It would force a first migration for users, on short term, followed then by another one to use containerized version.
    • So it depends on how easy these migrations would be/how much downtime they imply. In place with ELevate from EL9 to EL10? Or exporting all the data on EL9/reimporting on a new EL10 install - just to then do it again a few months later?
  • Update EL9 to Ruby 3.1+ using DNF modules
    • Probably easier for users, as long as they’re using a machine dedicated to Foreman (as advised by docs)
    • Is it worth the effort?

Our goal is to support the following path with full in-place upgrade support for continuity:

EL9 RPM-based installation → EL9 container-based installation → EL10 container-based installation

This has already had some work done and the strategy is being mapped out in the foremanctl migration documentation.

If we introduce foreman-installer EL10 support, this would expand to:

EL9 RPM-based installation → EL10 rpm-based installation → EL10 container-based installation

Note, this will require leapp upgrade work to happen as we have done in the past to allow that in-place EL9 to EL10 upgrade for rpm-based installations. This is required also for the container in-place upgrade support but we expected it ot be simpler since most of the applications are in the container.

DNF modules were painful on EL8 and we made a conscious choice to avoid them when we went to EL9. Add on top of that, for the RHEL ecosystem the Ruby 3.1 module is already EOL.

6 Likes

Thanks, seems reasonable

Makes sense, the OS upgrade is independent from Foreman

Definitely not worth it