Build, deploy, and run Nexus Repository Core OSS from source!
As of version 3, Sonatype no longer publishes binary distributions of the plain open-source edition of Nexus Repository — pre-built binary downloads are a so-called "Community" edition of Nexus 3, which is crippleware subject to usage limits (as of this writing, 40,000 stored components total and 100,000 requests per day; see Sonatype's Usage Center docs). These limits have been disruptive and frustrating for the Nexus community: see for example sonatype/nexus-public#883, as well as this blog post detailing the issue.
Still, Sonatype continues to release the core of Nexus 3 as open source (EPL-1.0), for which we are grateful! As of this writing (fall 2026), Nexus Core remains synced with every Community/Pro release — it's just that Core has no official ready-to-run binaries. This project exists to deal with that: it builds Nexus Core from source and deploys it using the same "unix archive" layout convention as Sonatype's official distributions.
Core differs from Community/Pro in that the open-source build supports only three repository formats — Maven, apt, and raw — with an embedded H2 datastore (or the bundled MyBatis/SQL datastore) and S3 blob storage. Community Edition and Pro add many more formats — npm, Docker/OCI, NuGet, PyPI, Go, Conda, RubyGems, Helm, and others — plus features like clustering/HA (Pro only) that live outside the nexus-public source tree entirely. If your use case needs one of those formats, this project won't get you there. But if Maven is all you need, Core built from source is a fully-capable, unrestricted Nexus Repository.
Every script here is heavily commented with the specific build/runtime quirks it works around, and when/how they were confirmed — read the scripts themselves for details beyond this overview.
The content of this repository is dedicated to the public domain — see UNLICENSE.
Trademark Notice: Sonatype, Nexus, and Nexus Repository are trademarks of Sonatype, Inc. This repository is an independent open source project and is not affiliated with, endorsed by, sponsored by, or connected to Sonatype, Inc.
Building and deploying have quite different requirements — only the deploy/service-management layer is tied to a specific OS family.
Relevant files: bin/build.sh, bin/latest-tag.sh
Portable POSIX shell with no distro-specific assumptions: git, curl, python3, tar, and any POSIX /bin/sh on PATH. No root required. bin/build.sh bootstraps its own JDK 25, Maven 3.9, and Node.js/corepack into hidden directories alongside the nexus-public checkout — it does not require (or touch) any JDK/Maven/Node already on your system.
One caveat: those automatic downloads (Temurin JDK, Node.js) currently target Linux x86_64 specifically (hardcoded URLs). On another OS or architecture, the build itself will still work — the Maven/Node tooling involved is all cross-platform — but you'll need to seed the toolchain yourself first: install a matching JDK 25+, Maven 3.9+, and Node.js+corepack for your platform at $NEXUS_PUBLIC_DIR/.build-jdk, .build-maven, and .build-node respectively (default $NEXUS_PUBLIC_DIR is /opt/nexus-public). build.sh only checks that those directories already contain a working, correctly-versioned toolchain — it doesn't care how they got there, so a pre-seeded directory is used as-is and the download step is skipped entirely. Patches to teach build.sh to detect OS/arch and fetch the right archive automatically are welcome.
Relevant files: setup.sh, service/sysv/nexus, bin/upgrade.sh, bin/restart.sh
Debian/Ubuntu-family Linux with systemd: setup.sh uses adduser in the Debian style, and service/sysv/nexus uses systemd-run for process isolation and pgrep -u for process matching. Root access is required (bin/upgrade.sh --dry-run is the exception — it builds and reports what would happen without touching anything live, so it needs no privileges).
Adapting the deploy layer to other init systems or distros should be straightforward — it's a small, self-contained script (service/sysv/nexus) plus a few lines in setup.sh, none of which touches the build itself. Contributions for other targets (e.g. a native systemd unit, or an RHEL/openrc equivalent) are welcome.
On a fresh machine, as root:
git clone https://github.com/scijava/nexus-core-oss /opt/nexus-core-oss
/opt/nexus-core-oss/setup.shThis creates the nexus service user and data directory, clones nexus-public to /opt/nexus-public, symlinks service/sysv/nexus to /etc/init.d/nexus, and — since /opt/nexus3 doesn't exist yet — builds the latest release and starts it.
Nexus is now running, but empty and unconfigured. See Post-install configuration below.
The live layout follows Sonatype's standard "Unix archive" pattern:
/opt/nexus3is a symlink to the current versioned install (e.g./opt/nexus-core-3.96.0-09), containingbin/,etc/,deploy/.- The data directory (
karaf.data) is/opt/sonatype-work/nexus3by default (override withNEXUS_DATA_DIR). - The service runs as the
nexussystem user by default.
bin/upgrade.sh first checks the latest release-* tag (bin/latest-tag.sh) against what's currently deployed, and exits immediately if they already match. Only when there's an actual new release does it build it (bin/build.sh), stage it at /opt/nexus-core-<version>, repoint the /opt/nexus3 symlink, and restart the service — so rollback is just repointing the symlink back to the previous version and restarting.
Run bin/upgrade.sh --dry-run to build and report what would happen without touching anything live (a no-op if already current). This is safe to run as an unprivileged user and safe to run routinely (e.g. from cron) — it costs nothing when already up to date.
To just build without deploying anything (e.g. to test the recipe still works against a new release), run bin/build.sh directly; it prints the resulting assembly directory on stdout.
service/sysv/nexus implements its own start/stop/status logic rather than trusting Nexus Core's own launcher (which has no real service-control support beyond running in the foreground — see the script's comments) or a pidfile. Ubuntu's systemd compatibility generator means systemctl start|stop|status nexus also works once the symlink is in place, but there is no native nexus.service unit and thus no restart-on-crash policy.
Always go through /etc/init.d/nexus (or bin/restart.sh, suitable for a cron-driven periodic restart) — never invoke /opt/nexus3/bin/nexus start/stop directly. An overlapping start can leave two Nexus processes fighting over the same embedded database and blob store. After starting or stopping, verify actual process state with pgrep -af nexus-repository (exactly one process after start, none after stop).
Machine-specific settings (JDK location, heap size, install paths) belong in /etc/default/nexus, sourced by service/sysv/nexus if present — no need to edit service/sysv/nexus directly. Recognized variables, all optional:
| Variable | Default | Purpose |
|---|---|---|
NEXUS_HOME |
/opt/nexus3 |
Path to the active install (the symlink bin/upgrade.sh repoints) |
NEXUS_DATA_DIR |
/opt/sonatype-work/nexus3 |
Data directory / karaf.data |
NEXUS_USER |
nexus |
System user the service runs as |
NEXUS_JAVA_HOME |
unset (trust PATH) |
JDK used to run Nexus. Set this if your system's default java is older than the current release requires — see service/sysv/nexus for why the bundled launcher can't detect a suitable JDK on its own the way Sonatype's official distributions do |
NEXUS_JAVA_MIN_MEM, NEXUS_JAVA_MAX_MEM, NEXUS_DIRECT_MAX_MEM |
2703m each |
JVM heap/direct-memory sizing — raise these on boxes with more RAM to spare |
Example /etc/default/nexus:
NEXUS_JAVA_HOME=/usr/lib/jvm/java-25-openjdk-amd64
NEXUS_JAVA_MIN_MEM=8192m
NEXUS_JAVA_MAX_MEM=8192m
NEXUS_DIRECT_MAX_MEM=8192mbin/build.sh and bin/upgrade.sh also honor NEXUS_PUBLIC_DIR (default /opt/nexus-public) to relocate the source checkout.
For a healthy repository, configure the following after a fresh installation, from the web UI under Settings → System → Capabilities:
- Add NXRM2 style URLs, to support queries to both
/repositoriesand/content/repositories. Failing to do so results in missed queries and a high volume of 404 spam. - Also consider setting: Base URL, Audit, Outreach notifications, Default Role.
Nexus warns under Status → Support when stored secrets use its default encryption key. Configure a unique key before adding credentials, tokens, or other sensitive configuration.
Important: Once Nexus uses this key, the key file is required to decrypt stored secrets. Back it up securely, do not commit it to version control, and do not lose it.
- Stop Nexus (
/etc/init.d/nexus stop; confirm no process remains withpgrep -af nexus-repository). - Generate the key file (adjust
$NEXUS_DATA_DIRif you overrode it):install -d -o nexus -g nexus -m 700 /opt/sonatype-work/nexus3/etc/secrets key=$(openssl rand -base64 32) install -o nexus -g nexus -m 600 /dev/null /opt/sonatype-work/nexus3/etc/secrets/nexus-secrets.json printf '{\n "active": "master",\n "keys": [\n {\n "id": "master",\n "key": "%s"\n }\n ]\n}\n' "$key" \ > /opt/sonatype-work/nexus3/etc/secrets/nexus-secrets.json unset key
- Point Nexus at it:
printf '\nnexus.secrets.file=/opt/sonatype-work/nexus3/etc/secrets/nexus-secrets.json\n' \ >> /opt/sonatype-work/nexus3/etc/nexus.properties
- Start Nexus (
/etc/init.d/nexus start) and confirm under Status → Support → System Status Checks that Default Secret Encryption Key reports healthy.
Include the nexus-secrets.json file in secure backups, mode 0600. A restored Nexus database containing encrypted secrets requires this same key file.