Updating web app from Rails 4 to Rails 7

A few months ago, certbot gave me the warning “Your system is not supported by certbot-auto anymore.”. With my Rails 4 app running on old Ubuntu 14.04, it was time to update the app & environment.

Since I’m using Digital Ocean’s droplets, it was easy to spin up a new droplet, setup the new droplet, and then destroy the old droplet. This is way better than operating in situ.

This blog post will provide a high level overview of update steps & pitfalls encountered.

  1. Spin up a Ruby on Rails (v7.0.4.2, OS Ubuntu 22.04) droplet https://marketplace.digitalocean.com/apps/ruby-on-rails This also involved setting up a SSH key to access the new droplet server.

  2. Exfiltrate the example Rails 7 app from the server to my local machine scp -r root@{SERVER_IP}:/home/rails/example .

  3. Create a new private GitHub repo for this example Rails 7 app

  4. Run the new example Rails 7 app locally This step should be super simple, but it was not. Getting RVM to run Ruby 3.2.0 with OpenSSL was not trivial on my Intel Mac. Here’s what I ran to setup Ruby 3.2.0 locally:

    sudo -i
    cd /usr/local/src
    curl -O https://www.openssl.org/source/openssl-1.0.2t.tar.gz
    tar xzf openssl-1.0.2t.tar.gz
    cd openssl-1.0.2t
    ./Configure darwin64-x86_64-cc
    make
    make install

    rvm reinstall 3.2.0 --with-openssl-dir=/usr/local/ssl

  5. In the new Rails 7 app, I moved my psql DB migrations over by hand. I copied the files and had to update the ActiveRecord::Migration with ActiveRecord::Migration[7.0].

  6. Draw the rest of the owl. I had to port lots of Rails files over from my Rails 4 to the target Rails 7 app.

    I ran into an issue with a model validation callback. To fix my issue, I created a migration to add uniqueness validation at the postgres layer and removed the uniqueness check in my model.

    This also include various site fixes. Such as Open Street Map tiles, using 3rd party APIs, and Font Awesome icons.

  7. Setup deployment to the server using Capistrano.

    Setting up Capistrano with Puma on Digital Ocean was not trivial at all. I followed this guide by Matthew Hoelter https://www.matthewhoelter.com/2020/11/10/deploying-ruby-on-rails-for-ubuntu-2004.html

    In my config/deploy.rb file, I had to add this set :branch, :main

    In my root Capfile, I had to use install_plugin Capistrano::Puma::Systemd due to using Puma 5.6.5.

    After a ton of trial and error, I had setup my nginx config at /etc/nginx/sites-available/rails.

    There was a ton of issues with the .sock file from Puma not getting generated.

    Setting up the secret_key_base is a newer Rails convention. Luckily Matthew’s blog post goes into detail on how to set it up in /etc/environment

    Using systemctl, I got puma setup to run the command bundle exec puma -C /home/rails/apps/[APP_NAME]/shared/puma.rb.

    Also, due to running on Digital Ocean, I had to update permissions for the rails user. cd /home; chmod o=rx rails. See Stack Overflow for details https://stackoverflow.com/questions/70028324/nginx-permission-denied-accessing-puma-socket-that-does-exist-in-the-correct-loc Without running this, I was getting a 502 (Bad Gateway) error, even though everything else was setup. I can see traffic in my nginx.access.log, but I was still getting the 502 (before running this command).

  8. Move psql data over. This step is going to vary a lot on your setup. I was able to run pg_dump to export my data and import data using psql APP_NAME_production < latest_pg_dump.sql.

  9. Update A record. In order to point my domain to my new droplet, I went into Digital Ocean and updated the A record from my old IP to my new IP. This is going to vary depending who you’re using for domain names.

  10. Run certbot. Running certbot for SSL was super easy. https://certbot.eff.org/instructions?ws=nginx&os=ubuntufocal

  11. Destroy old droplet. When you’ve verified everything is working with your new Rails 7 app, you can destroy the old droplet in Digital Ocean.

My app, GeoGraph, is now running on Rails 7 and lets anyone bookmark their location.