Making your own gem server


Ruby Gem bundler process is a very slow process. It takes considerable amount of time to fetch the index from rubygems.org. This slowness interrupts concentration and productivity.

So the idea of having a local gem server had been going in my company, Case Commons, for sometime. We use more than 100 open source gems from ruby gems. Instead of fetching the same data over and over again by every developer, we can cache all the gems to a local server.

Advantages

  • Fetching gems from this server will be blazingly fast.
  • It will also eliminate our dependency on Rubygems during deploys and other crucial periods. Rubygems has sometime had issues like slow connectivity or no connection.

Features of the server

  • Storing the local repository of the gems that need to be served.
  • Forwarding requests for gems to rubygems.org for the gems it doesn’t have.

Let us use nginx to serve the gems.

Steps

  • The gem repository can be called as local_gems. All the raw gem files *.gem should be stored in a sub directory local_gems/gems directory.

  • While being in the ‘local_gems’ repository and outside the ‘gem’ subfolder, make an index of all the available gems on the server.

  gem generate_index

.

  • Install nginx on our machine by executing,
brew install nginx
  • Configure nginx to serve our ruby gem repository folder. The nginx configuration is usually stored at /usr/local/etc/nginx/nginx.conf. In this configuration file, we want to have something like this,
http {
  server {
    location {
      try_files $uri @rubygems;
    }   
    
    location @rubygems {
      proxy_pass https://rubygems.org;
    }
  }
}
  • Start/reload nginx by
sudo nginx / sudo nginx -s reload
  • Next, point the Gemfile to this server. Assuming the local gem server is on port 8080 (the nginx default),
  gem sources --remove https://rubygems.org/
  gem sources --add http://localhost:8080

Here we go, let us bundle.

  bundle

And we see that our bundler is now fetching results from our local server.

Also we notice, the gems that are not available on the local server are fetched from the ruby gem server.

Sample bundler output:

Fetching gem metadata from http://localhost:8080/.......
Installing awesome_print 1.2.0
….
….
Your bundle is complete!
Use `bundle show [gemname]` to see where a bundled gem is installed.

Related Posts

Using Chef Vault with TDD

Automate encryption of your ssh keys on server using TDD