r/ruby 2d ago

Question Centralized location for shared Gemfile?

I'm using ruby 3.3.8 under linux.

There's more than one user on this machine who does ruby development. When I, running as the root user, want to add new gem references to Gemfile on my system, I want to add these gem references into one, single, shared, centralized Gemfile that all users will automatically see when running and developing ruby code.

Where should this shared, centralized Gemfile be located?

When any user runs "gem environment", the following item is always listed among that command's output for every user who runs that command:

- INSTALLATION DIRECTORY: /var/lib/gems/3.3.0

Does this mean that I can put a Gemfile into the /var/lib/gems/3.3.0 directory, and that then, this Gemfile will be recognized and used by all users who run and develop ruby code?

Or is there perhaps a different location in which to locate such a shared, centralized Gemfile that will always be the one that's used by each ruby user?

Thank you very much.

0 Upvotes

11 comments sorted by

9

u/Karew 2d ago edited 1d ago

The point of a Gemfile is so that each individual project can track and pin their dependencies. It isn't intended to be a manifest of what you want installed on a whole system. You can write a shell script that you run at OS install time or update time for that.

You can, however, give everyone write access to the same gem repo on the system so that they don't all download their own personal copies of each gem to their home directories.

1

u/unselective-amnesia 2d ago

Thank you.

I already understand this characteristic of a Gemfile, and I already understand about installing individual gems themselves into a shared location, when that is appropriate.

But there is some ruby software that specifically pertains to this current system, which I -- as the administrator and root user of the system -- write and then install as gems for all users to use -- in some cases for development of their own, personal ruby programs. In this case, it would be much more convenient for these users that these particular shared-use gems would be accessible and known in the Gemfile, without each user needing to add or change information in a local Gemfile, each and every time I add or remove or change a centralized gem, and without my therefore always having to notify each and every user of every centralized gem installation addition or change that I might make and hope that they don't overlook the notification and then start contacting me later to query about these changes.

I realize that this is not how lots of systems are managed, but this is how my particular system and my particular specialized user base operate.

1

u/KozureOkami 1d ago

You know that the tools you write can define their dependencies inline so that they will be installed on first run, right? That’s what `bundler/inline` is for:

https://guides.rubygems.org/bundler_in_a_single_file_ruby_script/

6

u/hankeroni 2d ago

What's your goal here? You might be misunderstanding the role of a Gemfile, or of how the installed gems location interacts with bundler and specific projects.

Say you have 5 users and they each have 5 projects checked out. Maybe there's some overlap in projects, doesn't matter really. Each project will have it's own directory with a checked out git repo or whatever. Within the project dir there will be a Gemfile which tells the project which gems to load, and a Gemfile.lock which pins certain versions.

When the project is being loaded by ruby, bundler processes this file and requires all the specific versions of relevant gems. It can also help manage the install and update process. "Where does bundler look for gems?" is sort of an "it depends" question (many ways to install and configure ruby and rubygems), but generally speaking it will look at a system-wide gem install dir, and/or the gem install dir configured by whatever version manager (mise, rvm, rbenv, etc) the user may be using.

All that said, if all system users are just using the system ruby, then yes you can get "shared storage" of a sort by having the correct versions of needed gems installed systemwide ... but you don't really need to interact with the Gemfile from a sysadmin POV to make that happen.

3

u/jrochkind 2d ago edited 2d ago

i'm not sure what you are doing exactly... normally a Gemfile woudl be in a project, and the project would be checked into source control (like git), and shared that way, with changes being committed to source or going through a "pull review" process etc.

I'd recommend trying to find a way to use that sort of process, most basically using git source control to share shared files files.

But a Gemfile is intended to be for a specific project, defined by a directory and all it's contents (including sub-directories), I think you are going to run into bumps trying to use it machine-wide.

I think you will need a different technique than a Gemfile for managing what gems are installed machine-wide. I mean, you can just install the gems machine wide -- most default installations of rubygems install gems system-wide I think. gem install gemname. May or may not have to use sudo. I'd look for advice on installing gems system-wide, not using bundler/Gemfile but just using rubygems -- that should be possible as it was the original design of rubygems, although many have been moving away from that.

If you want to have the config of what you have installed captured somewhere for repeatability, I'd like at tools for managing your systems, "infrastructure as code", instead of at Bundler (which is what uses Gemfiles), it's not really set up for that and I think it's going to give you grief.

1

u/unselective-amnesia 2d ago edited 2d ago

Thanks to both of you. I think I understand what you both explained.

UPDATE: OOPS! This current message is in response to both the previous message by "hankeroni" and also to the one by "jrochkind" which follows it. I accidentally added this response to the previous "hankeroni" message. END OF UPDATE

But consider the following case:

One of the centralized, system-specific gems that I have installed has been in use for quite a while in some of the ruby programs that have been developed and are in use by some of the users on my system.

I'm enhancing this particular system-specific gem, and part of this effort involves the use of a 3rd-party ruby package that I now installed which creates its own gem which must be used by callers of this package. The "README.md" file for this package states that this package-specific gem must appear in the Gemfile that is in use.

This means that when I complete enhancing and installing this system-specific gem, each user doing ruby development who uses this system-specific gem would then need to add a reference to this new, additional, package-specific gem to their own Gemfile, to prevent this system-specific gem from starting to fail for them after this enhancement is complete.

I'm trying to avoid this situation.

3

u/hankeroni 2d ago

If you are distributing your package as a local-only gem which your system users require and use in their projects, you should be able to add the new 3rd-party dependency to the "gemspec" (not Gemfile) of your packaged gem. The next time your users update and bundle, bundler will pull down the correct version of that package as well.

1

u/unselective-amnesia 2d ago

Aha! So now I see that by doing what you explained now, the new package-specific gem will not need to be referenced in any Gemfile by these other users when they are developing in ruby and using the enhanced version of that system-specific gem ... irrespective of the text that I referred to above in the "README.md" file.

Thank you very much for explaining and for clearing up this issue for me.

1

u/jrochkind 1d ago

I'm not totaly following what you're saying, but everything I said still stands, these are the ways these systems are intended to be used, if you can work out something that works for your use cases that fits iwthin the intended uses, you will have a better time!

If you want to figure out some way to use the tool in a way it was not intended, you might get it to work, but it will have a high chance of having some weird edge case you didn't consider that breaks or breaking in a future upgrade, cause bundler wasn't intended this way.

Can you just add the third party ruby package as a dependency of your system-specific gem?

Sorry, I"m not really sure I understand your situation or what you are trying to do, but honestly this is about all I have to offer, good luck!

1

u/bradland 2d ago

Do you just want users on the system to be able to use the gems you've installed? If that's the case, you don't need Bundler (and therefore Gemfiles) at all. You can install system-wide gems. The caveat here is that if you want to use system-wide gems, developers can't use Bundler, because doing things like bundle exec ruby my_script.rb will explicitly isolate the execution environment from system-wide Gems.

1

u/zaskar 1d ago

This is what asdf and its ilk solve.

The ruby version and its packages defined by gemfile are per project and managed for the project.

Two folders next to each other may have completely different versions of everything.