Flake-based dev environment for Ruby on Rails

After a lot of trial and tribulation and combing through GitHub discussions, I got a flake-based dev environment working for a Ruby on Rails app.

Some features:

  • It specifies an update shell for updating and auditing dependencies.
  • It should work on any major Nix-friendly platform without issue
  • It should avoid the Nokogiri issues that many others have run into when trying to use Nix and Ruby on Rails together.

If any of you encounter issues, please let me know! I could probably turn the Nix bits into a template if anyone would find that useful.

3 Likes

This is a wonderful template!

How would you recommend someone to move from an existing Rails application to use Nix with this template?

Copy the files over that you have changed/added from what Rails itself would generate? (which seem to be flake.nix, flake.lock, .envrc, scripts/) and then run nix run nixpkgs#bundix?

Or using some other method?

(I’m very new to Nix, so maybe I am confused by something trivial)

1 Like

Good question! Off the top of my head, this is what I would do:

  • Generate Gemfile.lock
  • Edit Gemfile.lock to remove the system-specific information from the nokogiri entry (otherwise you’ll get errors when you try to build)
  • Run bundix using that same method you mentioned, which will generate a gemset.nix
  • At that point, you should be able to copy the Nix stuff from the example project into your directory and run direnv allow. That gives you access to an executable called update-deps that you can run any time you change your Gemfile. That script deletes Gemfile.lock and gemset.nix and regenerates both, and it uses the local Bundler config to not apply --use-system-libraries when installing Nokogiri.
  • If you run which rails you should see something like /nix/store/mbxfqhd67p1dpq5cl8b0li3917fp34mx-rails-env/bin/rails, which means that the application is properly bundled and thus you can just run rails server to start the server.
1 Like

Thank you! This mostly worked. There was one change necessary to get gems like nokogiri to keep working as intended when running update-deps: The BUNDLE_FORCE_RUBY_PLATFORM=true environment variable.

This can be overridden in the bundler configuration, which was the case on my machine (for reasons unbeknownst to me). Without this set to true, you will end up still trying to build OS-specific versions of gems, which results in different hashes when running nix develop.

I ended up changing the line in the scripts/update.sh from

@bundler@ lock

to

BUNDLE_FORCE_RUBY_PLATFORM=true @bundler@ lock

to make sure it is always set.

1 Like

Ah, nice! I’ll update my repo with that. I assumed that this would be enough:

But I don’t know the mechanics of Ruby development well enough to account for the possibility that that wouldn’t be respected. Thanks for the tip!

UPDATE: changes pushed to repo.

1 Like

Thank you for the update! :green_heart:

Something else came to mind: Currently JS packages do not seem to be managed by Nix, but rather still by running nodejs or yarn by hand. Does it make sense to add this as well?

I am curious about yarn as well. Is there a recent update to these scripts with enhancements for yarn?

Looking at the code, the meat of the flake.nix is really just pkgs.mkShell { ... } with buildInputs = [ pkgs.node ]. You’d probably be fine with buildInputs = [ pkgs.node pkgs.yarn ].

You might find the wiki.nixos.org page on NodeJS useful.

Thank you for the reply. I am writing an article on Nix and Ruby for app signal and am struggling to find a good configuration to provide as a starting point. I have a basic setup to install the usual suspects – DB, a version of Ruby, Redis, etc – but it’s not much more than having a clean environment. One would have to run bundle, etc, start the DB server. Ideally, I’d like to provide some steps to do the gems and stuff for Yarn and maximize automation when the Nix shell starts. I’ve not yet found what I think is ideal. Any suggestions?

Nix’s mkShell (that the flake’s devShell outputs consist of) is mostly for getting that clean environment for working with packages. (There are ways of hooking behaviour onto shell entrance, but … it’s maybe not so elegant).

For a tool which helps manage both the dev dependencies (tools, libs), as well as stuff like services to run, it’d be worth taking a look at https://devenv.sh/ (e.g. its language support, implementation of that language support).

I see in the docs it supports running commands when it enters the devenv.

It also works with direnv, so can be activated automatically.

For a guide on Ruby & nix, note that the opening post to this thread includes “…avoid the Nokogiri issues than many others have run into when trying to use Nix and Ruby…”. – Since Nokogiri has a dependency on a native lib, it’s a gem you might run into trouble with. (I don’t know what). – The wiki.nixos.org page on Ruby has some notes about this.

I think your statement is confusing

That flag actually says for Bundler to build the OS specific Gem locally and not download the prebuilt one.

This makes sense in Nix since anything prebuilt doesn’t have any RPATH etc…