TL;DR

A thought experiment and proof-of-concept shows you can use Go's module fetcher (go get) to download Ruby gems by pointing GOPATH at a Ruby load path. The Go proxy and sumdb provide caching and cryptographic integrity for any tagged repo that includes a go.mod, but the approach has practical limitations and trade-offs.

What happened

An experiment demonstrates that Go’s module system can be repurposed as a transport layer for Ruby gems. By setting GOPATH to a directory that Ruby will search and running go get on a GitHub repo with a tag, Go’s tooling places the module into GOPATH/pkg/mod with each version isolated in its own directory. Pointing RUBYLIB at the module’s lib directory makes require "rack" succeed because Ruby only needs the files on disk. The Go proxy (proxy.golang.org) serves a zip and sum.golang.org records a SHA-256 hash in a transparency log, so the fetched content obtains Go-style integrity guarantees. The trick relies on adding a go.mod and tagging the repo; the proxy will cache whatever zip it receives, even if it contains no Go code. The author created a proof-of-concept called go-bundler but notes several limits, such as filesystem name escapes and incompatibility with gems that require native compilation.

Why it matters

  • It exposes a way to obtain cryptographic supply-chain integrity for non-Go packages by leveraging Go’s proxy and sum database.
  • Decentralized, self-describing import paths change how packages are located and cached compared with registry-based systems.
  • The approach highlights which package-manager responsibilities (naming, transport, integrity) can be separated and re-used across ecosystems.
  • It reveals practical limits of retrofitting one language’s infrastructure onto another, especially for native extensions and platform quirks.

Key facts

  • Setting GOPATH to a Ruby vendor_gems path and running go get fetches a tagged repo into GOPATH/pkg/mod with a versioned directory.
  • Go’s proxy (proxy.golang.org) supplies a zip of the module; the client computes a SHA-256 and consults sum.golang.org.
  • sum.golang.org logs the module’s hash in a transparency (Merkle-tree) log; first fetches write the permanent entry and later fetches verify it.
  • A repo only needs a go.mod at the root and a git tag to be cached and logged; the proxy does not validate that the contents are Go code.
  • Multiple versions coexist on disk because Go places each version in its own directory.
  • Minimal Version Selection (MVS) used by Go yields deterministic, older-or-exact-version resolution rather than always choosing the newest matching release.
  • Filesystems workarounds in Go (case-folding escapes) affect on-disk names and may complicate tooling for other languages.
  • Gems requiring native compilation break this approach, since Ruby native extensions often need a build step Go doesn’t provide.
  • The experiment is presented as a proof-of-concept (go-bundler) rather than as an endorsed production practice.

What to watch next

  • Development or release of go-bundler or similar tooling that automates parsing gemspecs and recursing dependencies — not confirmed in the source
  • Any policy or behavior changes at proxy.golang.org or sum.golang.org that would limit caching of non-Go content — not confirmed in the source
  • Efforts to create shared, content-addressed, transparency-logged distribution layers usable across multiple language ecosystems — not confirmed in the source

Quick glossary

  • go get: A Go tool command that fetches and installs modules or packages from remote repositories, resolving versions and placing code in GOPATH or module cache.
  • proxy.golang.org: A caching proxy operated for Go modules that mirrors public module versions and serves zipped module contents to clients.
  • sum.golang.org (sumdb): A transparency log that records cryptographic hashes of Go module versions so clients can verify integrity and detect tampering.
  • go.mod: A file that declares a Go module’s path and versioning information; presence at a repo root is used by Go’s module proxy.
  • Minimal Version Selection (MVS): Go’s dependency resolution strategy that prefers the minimum version required to satisfy constraints, yielding deterministic results without backtracking.

Reader FAQ

Is this behavior officially supported by the Go team?
The source notes the Go team did not intend this use; the behavior arises from how the proxy and sumdb operate.

Will gems with native extensions installed this way work?
Native extensions are a problematic area; the experiment works for pure Ruby code but fails for gems that require compilation.

Does using Go’s proxy and sumdb give cryptographic integrity for fetched gems?
Yes — the proxy returns a zip, Go computes a SHA-256, and sum.golang.org records or verifies that hash in a transparency log.

Is this a recommended replacement for Bundler or RubyGems?
No. The project is presented as a proof-of-concept and the author warns against adopting it as a standard practice.

Cursed Bundler: Using go get to install Ruby Gems Dec 25, 2025 Here’s a thought experiment. What if Ruby had require "github.com/rails/rails" and you used go get to fetch it?…

Sources

Related posts

By

Leave a Reply

Your email address will not be published. Required fields are marked *