Open-source project
rubygems/gemstash avatar
rubygems/gemstash

Gemstash: a RubyGems.org cache and private gem server for Bundler users

A RubyGems.org cache and private gem server

794 stars139 forksRubyMIT

At a glance

What is it?
Gemstash is a Ruby server that sits between Bundler and RubyGems.org, caching gems locally and also serving private gems that should not be public. It suits teams bundling the same dependency set across several machines, and it is unnecessary if you bundle only public gems and rarely repeat them.
Who is it for?
Gemstash earns its place in a team that bundles the same dependencies from many machines, or that needs to publish internal gems without exposing them to the public registry, since the same process handles both jobs and Bundler reaches it through a single mirror configuration. It is the wrong tool for a solo project pulling a handful of public gems once, and it is the wrong tool when the gem server itself cannot be customized.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 10 days ago.
What is it written in?
Mainly Ruby, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Two jobs in one process: caching public gems and serving private ones

Gemstash is described as both a cache for remote servers such as https://rubygems.org and a private gem source. The double definition is the design, not a loose summary. The same server sits in front of Bundler, forwards what it does not have to the public registry, keeps what comes back, and can also hold gems that were never published anywhere.

The audience falls into two groups. The first is the team that runs Bundler across many machines that can reach a server under their own control. The second is the team producing gems that should not be available to everyone. A third group, less obvious, is anyone who bundles the same set of gems across several projects, since the cache removes repeated downloads even without private content.

The project is explicit about who does not need it: if you only use gems from https://rubygems.org and do not bundle the same gems frequently, the documentation says you may not need Gemstash yet. That admission is worth taking seriously, because a caching proxy is extra infrastructure and it is only worth the operational cost when the cache actually hits.

The project lives under the rubygems organisation and is maintained by Ruby Central, a non-profit that describes its mission as supporting critical Ruby infrastructure such as Bundler, RubyGems and Gemstash. The top-level repository entries, with lib/, exe/, bin/, man/, spec/ and a gemstash.gemspec, follow the conventions of a well established command line gem rather than a service framework.

Bundler reaches the cache through a mirror, not a new source

The wiring is one Bundler setting. You tell Bundler to mirror https://rubygems.org to your local Gemstash address, and Bundler then treats the local server as the origin for those gems while Gemstash handles the rest.

bash
    $ bundle config mirror.https://rubygems.org http://localhost:9292

The Gemfile itself does not change. A file that still points at the public source will resolve through the mirror, which is why the same Gemfile works on a developer laptop with no cache and on a build machine behind one.

The fallback mechanism is the part most people miss. Bundler can be told to go straight to https://rubygems.org when the local server is down or merely slow, and the timeout can be a boolean or a number of seconds.

bash
    $ bundle config mirror.https://rubygems.org.fallback_timeout true
    $ bundle config mirror.https://rubygems.org.fallback_timeout 3

That setting is what keeps a cache from becoming a single point of failure. Without it, an unreachable Gemstash turns into a failed bundle; with it, the build degrades to the public registry. The trade-off is that the cache no longer guarantees that a build used exactly the artifact the team pinned, so teams that need byte-identical reproducibility have to decide which side of that they want.

Gem files persist, dependency metadata expires after 30 minutes

The caching rules are specific and they matter when you plan capacity. Gem files, the .gem archives themselves, are cached indefinitely. Gem dependency metadata is cached for 30 minutes, so a bundle performed inside that window can succeed with the network disconnected. The project demonstrates this by deleting the lockfile and the bundle path, then running Bundler again with the connection off.

bash
    $ rm -rf Gemfile.lock .bundle
    $ bundle

The practical rule that follows is worth stating plainly: bundling with a complete Gemfile.lock where every gem is already cached will never reach out to https://rubygems.org at all, while a bundle that has to resolve a new dependency will need network access to the public registry. The 30 minute metadata window means a machine resolving fresh dependencies still depends on rubygems.org being reachable even when every archive is local.

Storage sits in a directory named ~/.gemstash, which holds the cached gems, the private gems, a server log, the database and the Gemstash configuration. The documentation links to a page describing how to point that at a different directory, and to another describing how to swap the database. Gemstash uses SQLite to hold details about private gems, and the database file only appears once private gems are in use, so an installation that has never served a private gem will not have one.

For anything cached in memory, such as dependency information, the lifetime is 30 minutes before it is fetched again. Memcached is offered as a replacement for the in-memory cache when several processes or hosts need to share that layer.

A private gem source shares the same server and the same SQLite database

The second role of Gemstash is as a private gem source, and it uses the same process rather than a second service. The reference documentation lists commands for authorize, setup, start, stop, status and version, and setup is the one that prepares a gem to be pushed into the private source.

Metadata about those private gems lives in the SQLite database inside ~/.gemstash, which appears only once private gems are actually used. This is a deliberate simplification: there is no separate database server to operate, and the same directory that holds the cached public gems holds the private ones.

That single design also defines the boundary. The private source is not a separate host with its own access control, and the documentation on customizing the server covers the database, storage and caching rather than fine grained permissions. Deploying the server for other people to use is a separate topic in the documentation, listed under deploying Gemstash, which is where the operational questions about running this in front of a team get addressed.

Multiple gem sources are supported as well, with a dedicated page for that, and using Gemstash as a mirror is documented separately from the caching role described here. Those three modes, cache, private source and mirror, share the same command line and the same storage layout, so the mental model stays small even though the configuration surface is not.

Puma and Rack are the server, and neither can be changed

Gemstash is a Rack application served by Puma. That pairing explains the process model you get with a simple start command and no container or reverse proxy scaffolding of your own, and it also explains one of the project's stated limits: the documentation says that Puma and Rack are not customizable at this point.

That single sentence carries real weight for anyone planning to deploy this. You cannot swap in a different web server, cannot change how requests are threaded, and cannot adjust the server stack to fit an existing platform. What you can adjust is the layer underneath, the database, the storage directory and the cache, and the layer above, the command line and the Bundler settings on the client side.

The server listens on port 9292 by default, which is why the mirror configuration in the quickstart points at http://localhost:9292. The port is a hardcoded habit rather than a documented configuration knob, so a plan that expects to move Gemstash behind another port needs to check the configuration reference rather than assume it.

For development, the repository documents a conventional setup. After checking out the repo, you run bin/setup to install dependencies, then rake to run RuboCop and the tests, and bin/gemstash runs the server from source. There is also bin/console for an interactive prompt, which is the fastest way to inspect what a running instance actually holds.

Against plain Bundler, Gemstash trades a dependency on a server for reuse and privacy

The alternative that always exists is pointing Bundler straight at https://rubygems.org and managing the repeated downloads yourself. The documentation itself proposes this comparison when it says you may not need Gemstash yet if you only use public gems and do not bundle them frequently. The difference in approach is straightforward: Bundler alone fetches everything from the public registry on every fresh machine, while Gemstash puts a local Rack application in front of that registry and keeps what it fetched.

What the cache buys is bandwidth and repeatability of the download step, plus the ability to work with the network disconnected once archives are local. What it costs is a process to install, a directory to persist, and a dependency metadata window of 30 minutes that keeps a link to the public registry for fresh resolutions. On a CI runner that resolves a new dependency every build, that link is still there and the cache does not remove it.

For private gems there is no like-for-like comparison in the documentation, since publishing to an internal source is a different requirement rather than a variant of the public one. There the difference is ownership: the gems never need to leave the servers you control.

The licensing picture is straightforward. The gem is distributed as open source under the MIT License, with LICENSE.txt at the top of the repository. That is a permissive licence for a server component you deploy inside a company network, and it carries no copyleft obligation on applications that merely use the gems it serves. The README also carries the Contributor Covenant for contributions to the project itself.

Editorial conclusion

Gemstash earns its place in a team that bundles the same dependencies from many machines, or that needs to publish internal gems without exposing them to the public registry, since the same process handles both jobs and Bundler reaches it through a single mirror configuration. It is the wrong tool for a solo project pulling a handful of public gems once, and it is the wrong tool when the gem server itself cannot be customized. Before adopting it, verify three things: that your Bundler version accepts the mirror.https://rubygems.org setting and its fallback_timeout key, that your private gem names do not collide with names on RubyGems.org, and that the storage directory ~/.gemstash sits on a volume your team can back up, because it holds the cached gems, the SQLite database and the server log.

Frequently asked questions

How do I install and start Gemstash?

Install it with gem install gemstash, then start the server with gemstash start. No further setup is required, and the server listens on port 9292. You can stop it later with gemstash stop.

How do I point Bundler at a Gemstash server?

Run bundle config mirror.https://rubygems.org http://localhost:9292 so that Bundler resolves public gems through the local server. You can also set bundle config mirror.https://rubygems.org.fallback_timeout to true or to a number of seconds so bundling still works when the server is unreachable.

Where does Gemstash store cached gems and how long are they kept?

Everything lives in the ~/.gemstash directory, which holds cached and private gems, the server log, the database and the configuration. Gem files are cached indefinitely, while gem dependency metadata is cached for 30 minutes, and metadata can be held in memcached instead of memory.

Can I run Gemstash in production?

The documentation has a dedicated deploying Gemstash page, and the project is maintained by Ruby Central as part of the RubyGems toolchain, with the newest listed releases being v2.8.2 on 2026-04-02. The server stack itself is fixed, since the documentation states that Puma and Rack are not customizable at this point.

Official sources

  1. Issues
  2. License: MIT
  3. README
  4. Releases
  5. rubygems/gemstash on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/rubygems-gemstash.svg)](https://hysenlabs.com/projects/rubygems-gemstash)

Was this useful?