# RubyGems.org: the Rails application behind the Ruby community's gem host

> RubyGems.org is the open source Rails app that runs the public gem registry. This review covers what the repository contains, how the gem processor and search stack fit together, how to run it locally with Docker, and where self-hosting stops making sense.

**rubygems/rubygems.org** — The Ruby community's gem hosting service.

- Repository: https://github.com/rubygems/rubygems.org
- Website: https://rubygems.org
- Stars: 2,441 · Forks: 1,024
- Language: Ruby
- License: MIT
- Published: 2026-09-28 · Updated: 2026-09-28 · Language: en
- Canonical page: https://hysenlabs.com/projects/rubygems-rubygems-org

## The problem RubyGems.org the application solves

Most Ruby developers meet rubygems.org as a service: you run `gem install` or `bundle install` and packages appear. The repository is a different artifact. It is the server side of that service, a Rails application that manages user accounts, renders gem pages, and accepts uploaded `.gem` files. The README frames the original motivation plainly: provide a better API for dealing with gems, create more transparent and accessible project pages, and let the community improve the site.

Who is it for, then? Three audiences. People who want to change how the public registry behaves, since the site is run by Ruby Central and the README points contributors at CONTRIBUTING.md. Security researchers and platform engineers who need to read the upload path rather than guess at it. And teams that want a private gem server with the same user and gem page model, though that is the weakest fit and the one most likely to disappoint.

What it is not: a client library. The `gem` command and Bundler live in separate repositories. Nothing in this repo is required to publish a gem to the public host.

## Two halves: the Rails app and the gem processor

The README describes the organization in two parts, and that split is the most useful thing to understand before reading code. The first part is the Rails app: user management, gem pages, the web surface. The second is the gem processor, which handles incoming gems and stores them. Storage differs by environment. In production the README says gems go to Amazon S3; in development they are written to the filesystem in `server/`.

That means the upload path is not a single controller action that writes a row and returns. A gem arrives, the processor handles it, and the artifact lands in a storage backend that is configured differently depending on where you run. Any change to upload behaviour has to be reasoned about against both backends, and the README does not describe a rollback path if a processor run fails partway through. That silence is worth noting rather than filling in.

The repository layout supports the split: `app/` and `config/` for the Rails side, `server/` for development artifact storage, plus `lib/`, `script/`, `db/` and `test/`. The top level also carries a `shipit.yml`, which indicates deploys are driven through Shopify's Shipit tooling, and the README links a multi-step deploy checklist on the rubygems-infrastructure wiki rather than documenting deployment inline.

## Search runs on OpenSearch, not on your database

The docker-compose file is the clearest architecture document in the repository. Alongside `db` (Postgres 14.15) and `cache` (Memcached 1.4.39), it defines a `search` service running OpenSearch 2.13.0 with `discovery.type=single-node` and the security plugin disabled, listening on port 9200. A `search-console` service runs OpenSearch Dashboards 2.13.0 on port 5601 and depends on `search` being healthy.

Two consequences follow. First, gem search is a separate moving part from the relational data. If OpenSearch is down or its index is stale, the site's search behaviour degrades independently of the database. Second, the compose file pins every image by digest, which is a deliberate reproducibility choice: you get the same Postgres, Memcached and OpenSearch bytes on every machine. The trade-off is that upgrading any of them means editing the digest, not just changing a tag.

There is also a `toxiproxy` service from `ghcr.io/shopify/toxiproxy` on port 8474. Its presence in the development stack suggests network fault injection is part of how the team exercises failure paths. The README says nothing about it, so treat that as an inference from the compose file rather than documented practice.

## Running RubyGems.org locally with Docker

The README does not spell out setup steps inline. It points to CONTRIBUTING.md and its Development Setup section, and says to open an issue if setup fails. What the repository does give you is a Dockerfile and a docker-compose.yml, so the infrastructure side is concrete even though the application bootstrap instructions live elsewhere.

Start the backing services first. This brings up Postgres on 5432, Memcached on 11211, OpenSearch on 9200 and the OpenSearch dashboard on 5601, all bound to 127.0.0.1.

```bash
docker compose up -d db cache search search-console
```

You should see the containers start, with `search-console` waiting until `search` reports healthy. The healthcheck polls `http://localhost:9200/_cluster/health?wait_for_status=green&timeout=5s`.

The application image is built from an Alpine base with a pinned Ruby version. The Dockerfile takes `RUBY_VERSION` as a build argument defaulting to 4.0.6 and `ALPINE_VERSION` defaulting to 3.23, so the Ruby and Alpine versions in the image are explicit rather than implied.

```dockerfile
ARG RUBY_VERSION=4.0.6
ARG ALPINE_VERSION=3.23
FROM ruby:$RUBY_VERSION-alpine${ALPINE_VERSION} AS base
```

Inside the build stage, gems are installed with a cache mount and a secret mount, and the bundler config excludes development and test groups by default.

```bash
bundle config set --local without 'development test'
bundle config set --local path /srv/vendor
bundle install --jobs 20 --retry 5
```

For the database schema and the Rails server itself, follow CONTRIBUTING.md. The README does not list the commands, and inventing them would be worse than sending you to the file the project actually maintains.

## Where this repository is the wrong tool

Self-hosting the public registry code to serve a handful of internal gems is the clearest mismatch. You inherit Postgres, Memcached and a JVM-based OpenSearch node, plus a Rails app whose user model, gem pages and transparency features exist to serve a public audience. The README's stated purposes are about community access and project pages, not about minimal private hosting. A lighter registry will cost you far less to operate.

The second limitation is documented rather than inferred: production and development use different storage backends. Gems go to Amazon S3 in production and to the filesystem under `server/` in development. If you run a private instance, you must decide which of those two you are reproducing, and the README does not describe a third option or a migration path between them.

Third, the README is silent on several operational questions that matter before you commit: how a failed gem processor run is recovered, what the deploy checklist actually contains beyond the wiki link, and what the `toxiproxy` service is used for. Those are real gaps, not oversights you can paper over with assumptions. The deploy process lives on the rubygems-infrastructure wiki, which is a separate repository from this one.

## RubyGems.org compared with a static gem mirror

The obvious alternative for private hosting is a static or filesystem-backed gem server, where you build an index once and serve files over HTTP. The difference in approach is architectural. A static mirror has no user accounts, no upload path, no search cluster and no processor deciding what to do with an incoming `.gem`. RubyGems.org has all four, because its purpose is to accept gems from the public and present them transparently.

That means the comparison is not about which is faster. It is about whether you need the write path at all. If your team only consumes gems, a read-only mirror matches the requirement. If you need to accept uploads from many users and expose per-gem project pages, you are in the territory this Rails app was built for, and the OpenSearch dependency is part of the deal rather than an optional extra.

A second alternative is contributing upstream instead of forking. The README directs contributors to CONTRIBUTING.md and the RFC repository at rubygems/rfcs. For most people who want a behaviour change in the public registry, that is the shorter path than running their own instance.

## Licence and the cost of staying current

The repository is MIT licensed, and the README points at the MIT-LICENSE file for the full text. MIT is permissive, so forking and running a modified instance is straightforward from a licensing standpoint. Note only that the project is managed by Ruby Central and that hosting is donated by Amazon Web Services with CDN service from Fastly; those are operational relationships around the public service, not terms attached to the source licence. This is a description of the licence file, not legal advice.

The upgrade cost is dominated by the pinned dependencies. The compose file pins Postgres, Memcached, OpenSearch and OpenSearch Dashboards by image digest, and the Dockerfile pins Ruby and Alpine through build arguments. Staying on a supported Ruby and Postgres means editing those pins, rebuilding, and re-running the test suite; the repository carries both a `test/` directory and GitHub Actions workflows for test, lint and docker. The last push to the default branch was on 2026-09-28, so the codebase is moving and a fork will drift from upstream unless you track it deliberately.

## Conclusion

Adopt this repository if you are contributing to the public registry, auditing how gem uploads are processed, or you genuinely need to run a private registry with the same Rails codebase. Do not adopt it if you only want to publish gems or mirror packages: `gem push` and `bundle install` already talk to rubygems.org, and a local clone adds a Postgres, Memcached and OpenSearch footprint for no benefit. Before committing, verify three things for yourself: the CONTRIBUTING.md development setup, the deploy checklist on the rubygems-infrastructure wiki, and the storage backend your environment will use, because the README states the gem processor writes to Amazon S3 in production and to the filesystem under `server/` in development. Those two paths are not interchangeable at configuration level.

## FAQ

### What is RubyGems.org?

It is the Rails application that runs the Ruby community's gem host, managed by Ruby Central. The README describes it as consisting of a Rails app for users and gem pages, plus a gem processor that stores incoming gems in Amazon S3 in production or on the filesystem under `server/` in development.

### How do I install RubyGems.org locally?

The README does not list setup commands. It points to the Development Setup section of CONTRIBUTING.md, and the repository ships a Dockerfile plus a docker-compose.yml covering Postgres, Memcached, OpenSearch and OpenSearch Dashboards. The README asks you to open an issue if setup gives you trouble.

### Where do RubyGems get installed by this application?

The README states that the gem processor stores incoming gems in Amazon S3 in production, or on the filesystem in `server/` during development. Those are the only two storage locations the README documents.

### How does a Ruby gem work on this service?

The README splits the service into a Rails app that manages users and displays gems, and a gem processor that handles incoming gems and stores them. It does not describe the internal format or resolution algorithm of a gem, which belongs to the client tooling rather than this repository.

## Sources

- [Issues](https://github.com/rubygems/rubygems.org/issues)
- [License: MIT](https://github.com/rubygems/rubygems.org/blob/master/LICENSE)
- [Project website](https://rubygems.org)
- [README](https://github.com/rubygems/rubygems.org/blob/master/README.md)
- [rubygems/rubygems.org on GitHub](https://github.com/rubygems/rubygems.org)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/rubygems-rubygems-org
