It's not well known but with Rubygems and Bundler, you can distribute access-controlled commercial Rubygems. My gems, Sidekiq Pro and Sidekiq Enterprise, are the most well known example but I'm not a wizard: anyone can distribute gems to a limited set of customers. Here's how I do it.

  <VirtualHost *:443>
    DocumentRoot /var/www/gems

    SSLEngine on

    <Location />
      AuthType basic
      AuthName "private area"
      AuthBasicProvider file
      AuthUserFile /var/www/gems-passwd
      Require valid-user

The command to generate an entry is htpasswd -nb user pwd.

I have a /var/www/gems directory which looks like this:

$ pwd
$ ls -l
total 36
drwxrwxr-x 2 mike adm  4096 Apr  5 16:25 gems
-rw-rw-r-- 1 mike mike   65 Apr  5 16:25 latest_specs.4.8
-rw-rw-r-- 1 mike mike   82 Apr  5 16:25 latest_specs.4.8.gz
-rw-rw-r-- 1 mike mike   98 Apr  5 16:25 prerelease_specs.4.8
-rw-rw-r-- 1 mike mike  100 Apr  5 16:25 prerelease_specs.4.8.gz
drwxrwxr-x 3 mike adm  4096 Apr  5 16:25 quick
-rw-rw-r-- 1 mike mike 1307 Apr  5 16:25 specs.4.8
-rw-rw-r-- 1 mike mike  251 Apr  5 16:25 specs.4.8.gz
Put this in your Gemfile:

    source "" do
      gem "sidekiq-pro"

Run this bundle command:

    bundle config username:password

Run `bundle install` and you're done!
task :push => :release do
  require 'net/ssh'
  require 'net/scp'
  require 'sidekiq/pro/version'

  ver = ENV["VERSION"] || Sidekiq::Pro::VERSION

  Net::SCP.start("", "user") do |scp|
    scp.upload!("pkg/sidekiq-pro-#{ver}.gem", "/var/www/gems/gems")

  Net::SSH.start("", 'user') do |ssh|
    puts ssh.exec!("gem generate_index --directory /var/www/gems")
  puts "Released Sidekiq Pro #{ver}"

End Result

When I get a sale, my "Sidekiqbot" script sends me an email that the customer was set up. It feels pretty awesome to know the onboarding is completely automated.


That's it: Apache, CSV and some basic Linux/Ruby scripting. It took me weeks to develop all of this but there's nothing super difficult about it. I try to keep the server as simple as possible so I can focus on Sidekiq development and support, not operations. After all, you're buying what's in the gems, not what serves them. This simplicity has real benefits: it's cheap ($10/mo for two servers), easy to maintain and reliable. If you are thinking about following in my footsteps, I hope this blog post helps light the way.

This article is part of a larger group on the technical nitty gritty of a software business. Related articles are Charging for your Open Source (discussion on the money and legal aspects) and CGI: Ruby's bare metal (discussion on handling Stripe webhooks).


I became a member of Ruby Together because I rely on Bundler and the Rubygems infrastructure. The fact that we can do this at all is the beauty of Bundler and Rubygems: they are easily federated using HTTP and static files only. As an alternative, consider npm; it requires CouchDB, a full copy of the npm dataset to serve and only supports a single package server. This design is much more complex, requiring a much heavier server, and makes it effectively impossible for an individual to run an npm server due to the operational costs and maintenance required. I encourage anyone whose business depends on Ruby to join.

comments powered by Disqus