A CI pipeline that downloads its dependencies from the public internet on every run has two problems it rarely admits to: it is slow, and it is not reproducible, because the public registry can change, rate-limit or disappear. A repository manager fixes both by sitting between the builds and the world. This post follows a DevOps engineer deploying Nexus Repository OSS on MassiveGRID PaaS, which is built on Virtuozzo Application Platform, formerly Jelastic, beside the CI that uses it.

The company is a fintech we will call Wexford Ledgers, with a Java back end, a TypeScript front end and containerised deployments, building on the Jenkins DevOps Pack. The Nexus Repository Manager package deploys Sonatype's OSS release on a Java node with persistent blob storage.

Three repository types, one server

Nexus organises artefacts into repositories of three kinds. Proxy repositories cache a remote registry: Maven Central, npmjs, Docker Hub. Hosted repositories hold your own artefacts: release JARs, internal npm packages, production images. Group repositories present several of these as one URL, so a build configures one Maven repository and gets both the cache of Central and the company's own releases. The engineer creates a group per format: maven-all, npm-all, docker-all. Every build tool at Wexford now points at one host.

Where it runs, and why beside the CI

Nexus is installed in the same environment group as Jenkins, so the CI workers reach it over the platform's internal network by hostname, with no external traffic charge and no dependence on the internet for anything already cached. The first build after a cache miss fetches from the public registry once; every build after that, on any of the auto-scaling workers, gets the artefact from the local network in milliseconds. The eight-minute dependency download the team had lived with became about twenty seconds.

The container firewall on the Nexus node allows the web UI and repository port from the CI environment's internal addresses and from the office VPN; nothing is exposed to the public internet except, later, the Docker registry port for the production cluster's pulls, with authentication.

Sizing: Nexus is a Java application with a big disk

Sonatype recommends at least 4 GB of RAM for Nexus 3, and the JVM settings on the platform's Java node follow the cloudlet allocation. The engineer sets a limit of 48 cloudlets (a cloudlet is 128 MiB of RAM plus 400 MHz of CPU) so the heap can grow during large uploads and re-indexing, with vertical scaling allocating the actual amount by the hour; on a normal day the node sits around 24 cloudlets. The disk is the real capacity question. Proxy caches grow with every new dependency version anyone builds against, and Docker images are large. He starts the blob storage at 200 GB, expandable from the dashboard, and sets a disk load alert at 75%.

RepositoryTypeCleanup policySize after 6 months
maven-central proxyProxyRemove components unused for 90 days38 GB
npmjs proxyProxyRemove components unused for 60 days21 GB
docker-hub proxyProxyRemove unused for 30 days44 GB
maven-releases hostedHostedNever6 GB
docker-releases hostedHostedKeep last 20 tags per image31 GB

Cleanup policies and the weekly compact-blob-store task are what keep that table from doubling every six months. Without them, a repository manager is a disk that only grows.

Docker: the registry the production cluster pulls from

Wexford's production Kubernetes cluster pulls images from Nexus's hosted Docker repository, which runs on its own port with authentication. The engineer opens that port on the container firewall to the production environment's addresses and, because the cluster is in the same region, the pulls stay on the internal network. For deployments to another region he would attach a public IP and TLS via the Let's Encrypt add-on; for now nothing leaves the data centre. The Docker Hub proxy also protects the team from the public registry's pull rate limits, which had failed a deploy once.

Reproducibility, the quieter benefit

Speed is what the team noticed. Reproducibility is what the auditors noticed. Because every dependency a build ever used is cached in Nexus with its checksum, a release from last year can be rebuilt with exactly the artefacts it was built from, even if the public registry has since removed or replaced them. The backup of Nexus's blob storage to a backup storage node, weekly, is therefore not just for disaster recovery; it is part of the software supply-chain record the fintech's regulator asks about.

Cost

One more habit came with the server: every build tool's configuration now points at Nexus and nowhere else, enforced by a firewall rule on the CI workers that blocks direct access to the public registries. A build that tries to bypass the proxy fails loudly, which is how the team found two scripts still fetching from the internet.

A Java node averaging about 24 cloudlets an hour is roughly $59 a month at MassiveGRID's published $0.003372 per cloudlet-hour before discounts, plus the 200 GB disk. Against that, the engineer counted the eight minutes saved on each of about 300 builds a week on auto-scaling workers billed by the hour, which is about 40 worker-hours a week the company no longer pays for, and the deploy that no longer fails when Docker Hub is having a day.

Frequently Asked Questions

Nexus or the registry built into the GitLab server?

GitLab's registries are tied to projects and cover Docker and several package formats. Nexus is a general repository manager with proxying, grouping and cleanup policies across many formats, and it works with any CI. Teams using Jenkins, or needing a cache of public registries, usually run Nexus.

Can Nexus serve Helm charts, PyPI packages and NuGet too?

Yes. Nexus OSS supports Helm, PyPI, NuGet, RubyGems, Conda, apt and yum among others, each as proxy, hosted or group repositories on the same server.

How do I migrate an existing Nexus?

Nexus supports exporting and importing its configuration and blob stores; copy the data directory and blob store to the new node's persistent storage and start Nexus at the same version, then upgrade. Test the procedure on a clone of the new environment before switching CI to it.

Every dependency, cached next to your builds

Deploy Nexus Repository OSS with persistent blob storage on MassiveGRID PaaS, in the same environment group as your CI, and pay per cloudlet-hour. Free 14-day trial, no credit card.

Nexus Repository on MassiveGRID PaaS

Further Reading