Docs menu
Package managers
How Bundler works on Primcloud: Gemfile.lock enforcement, private gem sources via credentials, and the environment applied during bundle install.
On this page
Ruby has exactly one package manager on Primcloud: Bundler. Every gem you declare in a Gemfile and resolve into Gemfile.lock gets installed by Bundler during the build. There's no second package-manager surface to choose between: a Gemfile and Gemfile.lock at the repo root are both required, and they're the only inputs the build reads.
Supported package managers#
Bundler. Version resolved from Gemfile.lock's BUNDLED WITH line:
BUNDLED WITH
2.5.23
Missing that line, Primcloud installs its own default Bundler (currently 2.5.23). Pinning it means your local bundle and Primcloud's bundle behave identically, which is recommended.
Gemfile.lock is required. Detection fails without it; see Ruby on Primcloud → Detection. Bundler produces the lockfile the first time you run bundle install locally; commit it alongside your Gemfile.
Install behavior#
Every deploy runs bundle install with this environment:
| Variable | Value | Effect |
|---|---|---|
BUNDLE_DEPLOYMENT |
1 |
Enables Bundler's deployment mode: installs to BUNDLE_PATH, forbids modifying the lockfile mid-install. |
BUNDLE_FROZEN |
1 |
Fails restore if Gemfile.lock disagrees with Gemfile. |
BUNDLE_GEMFILE |
<app-dir>/Gemfile |
Tells Bundler where to find the Gemfile. |
BUNDLE_WITHOUT |
development:test |
Skips development and test groups. Override in the Secrets panel to change which groups are excluded. |
BUNDLE_PATH |
Path into the cached gem layer | Where installed gems land. |
GEM_PATH |
Same | So Ruby finds the installed gems at runtime. |
After a successful bundle install, bundle clean runs to prune gems that dropped out of the lockfile since the previous build. The RubyGems download cache (the .gem files under <BUNDLE_PATH>/cache) is deleted after install to keep the final image small. This doesn't affect future installs because the resolved gem files themselves remain.
Two additional BUNDLE_* values are worth calling out because they're commonly changed:
BUNDLE_WITHOUT: set this in the Secrets panel if you need different groups excluded on Primcloud.BUNDLE_WITHOUT=development:test:doc, for example.BUNDLE_JOBS: set to a higher number to parallelize gem downloads if your build's install phase is the bottleneck. Bundler defaults to 1.
Anything else (timeouts, retry counts, per-gem overrides) you can set via BUNDLE_* env vars using Bundler's documented naming convention.
Private packages and registries#
Private gem sources are supported through Bundler's env-var credential mechanism. Bundler reads credentials for a source from an environment variable whose name is derived from the source's hostname.
Example. For https://gems.contribsys.com:
source "https://rubygems.org"
source "https://gems.contribsys.com/" do
gem "sidekiq-pro"
end
Then in the Secrets panel, set:
BUNDLE_GEMS__CONTRIBSYS__COM=username:password
The naming convention: prefix BUNDLE_, then the hostname in uppercase with every . replaced by a double underscore. A few examples:
| Source URL | Variable |
|---|---|
https://gems.contribsys.com |
BUNDLE_GEMS__CONTRIBSYS__COM |
https://gem.fury.io |
BUNDLE_GEM__FURY__IO |
https://packagecloud.io |
BUNDLE_PACKAGECLOUD__IO |
Values you set in the Secrets panel are stored encrypted and never surfaced in build logs. Bundler resolves the credential at restore time and injects it into the outbound request.
Verify locally with:
BUNDLE_GEMS__CONTRIBSYS__COM=username:password bundle install
If that command works, the same value set on the environment will work on Primcloud.
Lockfiles#
Gemfile.lock is required. The build refuses to start without it. Bundler runs in deployment/frozen mode, which means:
- The lockfile is treated as authoritative.
bundle installwill not modify it during a build. - If the lockfile disagrees with the current
Gemfile(e.g., a gem was added toGemfilebutbundle installwasn't re-run locally), the build fails with a "TheGemfile's dependencies are satisfied, but the lockfile is out of date" or similar Bundler error.
The fix in both cases is the same: run bundle install locally, commit the updated Gemfile.lock, and push.
When you want to loosen this. There's no supported way to opt out of frozen mode for a Primcloud build. Bundler's deployment posture is the safer default and matches how Ruby apps behave in production everywhere else. If you're mid-migration and need to relax it temporarily, regenerate the lockfile locally and commit the result. That's the intended workflow.
Lockfile hygiene. Two common lockfile mistakes cause build failures:
- Not committing
Gemfile.lock. Detection fails outright. - Bumping a gem in
Gemfilewithout runningbundle install. Frozen mode rejects the resulting mismatch.
Both are caught locally the moment you try to run bundle install on the same tree, so they don't need to be diagnosed against a Primcloud build log. Reproduce with bundle install --frozen on your machine.