How to distribute private gems

How to distribute private gems

When I first started thinking about private gem distribution, I approached the problem the way I always do, backward from bundle install. What does a developer need to make that command succeed for a private library? Three things: a source (URL or repo), credentials that work in CI and locally, and a reliable way to receive updates without breaking deployments.

Not all code belongs on RubyGems.org opens a new window , and that’s okay. Sometimes the goal is internal reuse- sharing an SDK or auth client across services. Sometimes it’s a business model: you ship a private gem behind a license. Either way, the constraints are the same: authentication, delivery, and trust.

In this blog post, we’ll give an overview of the options for distributing private gems.

How Private Gems Are Born

Organizations use private gems for practical reasons. Gems that are built for internal usage can be seen as a convenient way to share libraries such as SDKs, service clients, and shared models across many services without coupling through a monorepo. Organizations can also have advanced functionality as closed source gems and sell access to it.

These use cases share common operational challenges: you must authenticate and authorize installs, deliver updates and prevent unauthorized redistribution. Addressing those concerns influences the distribution method you pick and the infrastructure you operate.

How RubyGems and Bundler Handle Sources

By default gem push targets RubyGems.org and Bundler resolves dependencies from the sources declared in your Gemfile. For example:

source "https://rubygems.org"

gem "rails", "~> 7.1"

However, both behaviors are configurable. gem push accepts a --host flag so you can upload to another gem server, and the RubyGems client will also read credentials from ~/.gem/credentials or the GEM_HOST_API_KEY environment variable. Meanwhile, Bundler reads sources from the Gemfile, but you can store credentials with bundle config (which writes to .bundle/config), configure mirrors, or point specific hosts to private registries.

Behind the scenes bundle install downloads metadata from the configured registry, verifies checksums, and installs gems locally. Because RubyGems.org lacks private access controls and payment hooks, organizations that aim to distribute their private gems usually use a private registry or use private Git repos as an alternative.

Private Gem Distribution

Git-Based Distribution

It’s the simplest option to distribute a private gem. Publish the gem source to a private repository and reference it in your Gemfile. This leverages existing Git authentication (SSH keys or OAuth) and avoids running a registry. For small teams or internal tooling this is often the path.

Referencing a Git repo moves work to the client. Bundler cannot use a pre-built index, so installs can be slower and metadata caching is limited. Because Bundler doesn’t have an index for Git sources, automating version access or licensing controls (for example, restricting which versions a particular customer can install) becomes harder to manage at scale.

gem "my_private_gem", git: "git@github.com:org/my_private_gem.git"
# or with specific branch/tag
gem "my_private_gem", git: "https://github.com/org/my_private_gem.git", branch: "main"
# or with specific ref
gem "my_private_gem", git: "git@github.com:org/my_private_gem.git", ref: "v1.2.3"

Private Gem Servers

Private gem servers, whether managed SaaS or self-hosted, address the shortcomings of Git-based installs by providing an indexable registry with access control, logging, and lifecycle management. Example commercial providers include Gemfury opens a new window and Cloudsmith opens a new window ; larger organizations often choose Artifactory opens a new window .

If you prefer an open-source server, two lightweight and commonly used options are Gemstash opens a new window and Geminabox opens a new window .

Gemstash (lightweight, RubyGems-friendly)

Gemstash is a small server that can host private gems, proxy and cache RubyGems.org, and provide simple authentication. It’s maintained by contributors in the RubyGems ecosystem and is opinionated for standard Bundler/Rubygems workflows.

Here’s a quick start to run a local server:

# install and run a local server
gem install gemstash
gemstash start   # serves at http://localhost:9292 by default

# build and push a gem
gem build mygem
gem push --host http://localhost:9292 pkg/mygem-0.1.0.gem

# point your Gemfile at the server
source 'http://localhost:9292'

It’s also possible to set up authentication and tokens in this Gemstash local server. Check their documentation opens a new window for more information.

Geminabox (simple, small footprint)

Geminabox is Sinatra app that serves gems from a directory. It’s extremely lightweight and easy to deploy (single process), making it a good choice for small teams or quick internal registries.

Here’s a quick start to run a local server:

# install and run the server
gem install geminabox
geminabox   # runs a server (defaults to http://localhost:9292)

# build and push a gem (uses 'gem inabox' which is provided by the geminabox toolchain)
gem build mygem
gem inabox pkg/mygem-0.1.0.gem --host http://localhost:9292

# point your Gemfile at the server
source 'http://localhost:9292'

For production use, Geminabox or Gemstash can be set up behind an authenticated reverse proxy strategy (Nginx with basic auth or an SSO gateway) or use TLS + token-based access. Both servers are widely used, well-documented, and simple to operate.

Bundler can be pointed at a private source using an authenticated URL, for example:

source "https://USERNAME:TOKEN@gem.fury.io/myorg/"

Tokens or API keys are typically injected through environment variables or stored in Bundler’s local config (.bundle/config). Running a registry gives you practical operational controls: you can revoke access, audit downloads, and integrate the registry with CI/CD for automated publishing.

Private Gem Registries

When productizing a gem, distribution and authentication become core product components. Projects like Sidekiq provide license keys that act as credentials against a private registry; others (for example, providers of long-term support) gate patches and releases behind subscription checks. The implementation is typically the same: a license service issues short-lived or revocable tokens, a registry enforces access, and CI/CD pipelines publish releases and reconcile entitlement after successful payments.

Fundamentally, a commercial private gem system typically rests on three pillars:

  • Entitlement Management: A service (like a license server) that knows who is allowed to access what.
  • Enforcement Point: A private registry that checks these entitlements before serving gems.
  • Automation Bridge: Pipelines that automatically grant or revoke access based on events like payment or subscription changes.

It also should account for other security controls like: rotating tokens, scoped credentials, and signing artifacts to reduce risks.

Security and DevOps Considerations

Shipping a private gem rests on a practical security responsibility: controlling who can fetch your packages.

Implement least-privilege tokens (separate tokens for publishing vs. install), integrate with SSO where possible, and have a token rotation and revocation process for offboarding or compromised keys.

Real-World Examples

Sidekiq Pro opens a new window

  • Uses token-based authentication for Bundler installs.
  • Paid customers receive personal tokens tied to their license.
  • Gems are hosted on a private server with strict version control.

Rails LTS opens a new window

  • Customers manually configure credentials after purchasing.
  • Patches are distributed as gem updates to specific Rails versions.
  • Focuses on compliance and security rather than automation.

Internal Gems (Enterprise Use)

  • Common in microservice organizations.
  • Teams use self-hosted Gemstash for internal SDKs.
  • Easy integration with GitHub Actions or CircleCI.

Conclusion

Private gems effectively bridge the gap between open-source collaboration and commercial or internal sustainability. By choosing the right distribution method, from a simple Git repo to a fully-featured private registry, and adhering to sound security principles, you can share your gem safely. Whether you’re building a shared internal SDK or selling a pro-tier library, the goal remains the same: secure your pipeline, manage trust, and respect your users’ access.

Need help setting up secure private gem distribution for your team? We can help. opens a new window

Get the book