---
title: "How to Install Nexus Repository Manager on Ubuntu 24.04"
description: "Deploy Sonatype Nexus Repository on Ubuntu 24.04 with Docker Compose and Nginx HTTPS, then set up npm and Maven proxy, hosted and group repositories for CI."
category: "CI/CD DevOps"
language: en
source: https://cubepath.com/docs/ci-cd-devops/nexus-repository-manager-installation
updated: 2026-09-25
---
# How to Install Nexus Repository Manager on Ubuntu 24.04
Sonatype Nexus Repository is an artifact manager: it caches packages from public registries such as npm and Maven Central, and hosts the packages your own team builds. Pointing your builds at Nexus makes them faster, keeps working when a public registry is slow or down, and gives you one place to control which artifacts are used. In this tutorial you will run Nexus Repository on Ubuntu 24.04 with Docker Compose, publish it over HTTPS with Nginx, and create npm and Maven repositories that your developers and CI pipelines can use.
## Prerequisites
To follow this guide you need:
- A server running Ubuntu 24.04 LTS, for example a CubePath VPS, with at least 4 vCPUs and 8 GB of RAM for a team setup (4 GB works for evaluation), and enough disk for the cached artifacts. 50 GB is a reasonable start.
- A non-root user with `sudo` privileges.
- A domain name such as `nexus.your_domain` with a DNS A record pointing to your server's public IP address.
- Ports 80 and 443 reachable from the internet.
Replace `nexus.your_domain` with your hostname and `your_admin_password` with the password you choose in Step 3.
## Step 1 - Installing Docker and Docker Compose
Running Nexus from Sonatype's official `sonatype/nexus3` image keeps the Java runtime and the application together and makes upgrades a matter of pulling a new image. Install Docker Engine and the Compose plugin from the Ubuntu repositories:
```bash
sudo apt update
sudo apt install docker.io docker-compose-v2
sudo systemctl enable --now docker
```
Check that both commands work:
```bash
sudo docker --version
sudo docker compose version
```
```output
Docker version 27.x.x, build ...
Docker Compose version 2.x.x
```
## Step 2 - Starting Nexus with Docker Compose
Create a directory for the deployment:
```bash
sudo mkdir -p /opt/nexus
sudo nano /opt/nexus/compose.yaml
```
Add the following service definition:
```yaml
services:
nexus:
image: sonatype/nexus3:latest
container_name: nexus
restart: unless-stopped
ports:
- "127.0.0.1:8081:8081"
environment:
INSTALL4J_ADD_VM_PARAMS: "-Xms2g -Xmx2g -XX:MaxDirectMemorySize=2g -Djava.util.prefs.userRoot=/nexus-data/javaprefs"
volumes:
- nexus-data:/nexus-data
ulimits:
nofile:
soft: 65536
hard: 65536
volumes:
nexus-data:
```
A few details are important here:
- The port is published on `127.0.0.1` only. Nginx will be the only public entry point, so Nexus is never exposed over plain HTTP.
- `INSTALL4J_ADD_VM_PARAMS` sets the Java heap and direct memory. On an 8 GB server, 2 GB each leaves room for the operating system and file cache. Scale these values with your RAM.
- The named volume `nexus-data` holds all repositories, the embedded database and configuration. It is the only thing you need to back up.
Start the container:
```bash
cd /opt/nexus
sudo docker compose up -d
```
Nexus takes one to three minutes to start. Follow the logs until it reports that it has started:
```bash
sudo docker compose logs -f nexus
```
```output
nexus | -------------------------------------------------
nexus |
nexus | Started Sonatype Nexus COMMUNITY 3.x.x-xx
nexus |
nexus | -------------------------------------------------
```
Press `CTRL+C` and confirm that the REST API answers:
```bash
curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:8081/service/rest/v1/status
```
```output
200
```
## Step 3 - Publishing Nexus with Nginx and HTTPS
Install Nginx and Certbot:
```bash
sudo apt install nginx certbot python3-certbot-nginx
```
Create a server block. `client_max_body_size` must be large enough for the biggest artifact you will upload, otherwise Nginx rejects uploads with a `413` error:
```bash
sudo nano /etc/nginx/sites-available/nexus
```
```nginx
server {
listen 80;
listen [::]:80;
server_name nexus.your_domain;
client_max_body_size 1G;
proxy_read_timeout 300s;
proxy_send_timeout 300s;
location / {
proxy_pass http://127.0.0.1:8081;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
```
Enable the site and reload Nginx:
```bash
sudo ln -s /etc/nginx/sites-available/nexus /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
```
Open the firewall for SSH and web traffic, then request a certificate:
```bash
sudo ufw allow OpenSSH
sudo ufw allow "Nginx Full"
sudo ufw enable
sudo certbot --nginx -d nexus.your_domain
```
Certbot adds TLS to the server block, sets up an HTTP to HTTPS redirect and installs a timer for automatic renewal.
## Step 4 - Completing the setup wizard
Nexus generates a random password for the `admin` user on first start. Read it from the data volume:
```bash
sudo docker compose -f /opt/nexus/compose.yaml exec nexus cat /nexus-data/admin.password
```
Open `https://nexus.your_domain`, select **Sign in** and log in as `admin` with that password. The setup wizard asks you to:
1. Set a new admin password (`your_admin_password`). The generated `admin.password` file is deleted afterwards.
2. Accept the license agreement if your version asks for it.
3. Choose whether to enable anonymous access. Disable it unless you want anyone on the internet to be able to download from your proxies.
Then go to **Settings (gear icon) > System > Capabilities**, create a **Base URL** capability and set it to `https://nexus.your_domain`, so that URLs generated by Nexus use the public hostname.
Nexus creates some Maven repositories by default. Open **Settings > Repository > Repositories** to see them: `maven-central` (a proxy of Maven Central), `maven-releases` and `maven-snapshots` (hosted) and `maven-public` (a group that combines them).
## Step 5 - Creating npm repositories
Nexus uses three repository types, and each format usually needs all three:
| Type | Purpose |
|---|---|
| Proxy | Caches a remote registry, such as `registry.npmjs.org`. |
| Hosted | Stores packages you publish yourself. |
| Group | Combines several repositories behind a single URL, so clients only need one address. |
You can create repositories in the UI under **Settings > Repository > Repositories > Create repository**, or with the REST API. The API is convenient because the commands can be saved and repeated. Run these on the server; `curl` prompts for the admin password.
Create an npm proxy of the public registry:
```bash
curl -u admin -X POST "http://127.0.0.1:8081/service/rest/v1/repositories/npm/proxy" \
-H "Content-Type: application/json" \
-d '{
"name": "npm-proxy",
"online": true,
"storage": { "blobStoreName": "default", "strictContentTypeValidation": true },
"proxy": { "remoteUrl": "https://registry.npmjs.org", "contentMaxAge": 1440, "metadataMaxAge": 1440 },
"negativeCache": { "enabled": true, "timeToLive": 1440 },
"httpClient": { "blocked": false, "autoBlock": true }
}'
```
Create a hosted repository for your private packages. `allow_once` prevents a released version from being overwritten:
```bash
curl -u admin -X POST "http://127.0.0.1:8081/service/rest/v1/repositories/npm/hosted" \
-H "Content-Type: application/json" \
-d '{
"name": "npm-hosted",
"online": true,
"storage": { "blobStoreName": "default", "strictContentTypeValidation": true, "writePolicy": "allow_once" }
}'
```
Create a group that serves both:
```bash
curl -u admin -X POST "http://127.0.0.1:8081/service/rest/v1/repositories/npm/group" \
-H "Content-Type: application/json" \
-d '{
"name": "npm-group",
"online": true,
"storage": { "blobStoreName": "default", "strictContentTypeValidation": true },
"group": { "memberNames": ["npm-hosted", "npm-proxy"] }
}'
```
Each successful call returns HTTP `201` with an empty body. List the npm repositories to confirm:
```bash
curl -s -u admin "http://127.0.0.1:8081/service/rest/v1/repositories" | grep '"name"'
```
```output
"name" : "npm-group",
"name" : "npm-hosted",
"name" : "npm-proxy",
...
```
Finally, npm clients authenticate with tokens, which Nexus handles through a separate security realm. Go to **Settings > Security > Realms**, move **npm Bearer Token Realm** to the **Active** list and select **Save**.
## Step 6 - Creating a user for CI
Do not use the admin account in pipelines. Create a role and a user with only the rights needed to read and publish:
1. Go to **Settings > Security > Roles > Create Role**. Name it `ci-deployer` and add the privileges `nx-repository-view-npm-*-*` and `nx-repository-view-maven2-*-*`.
2. Go to **Settings > Security > Users > Create local user**. Create `ci-deployer` with a strong password, status **Active** and the `ci-deployer` role.
These privileges allow browsing, reading and publishing in npm and Maven repositories but no administration.
## Step 7 - Using Nexus from npm and Maven
### npm
Point npm at the group so installs go through Nexus:
```bash
npm config set registry https://nexus.your_domain/repository/npm-group/
```
Log in against the hosted repository to publish. Enter the `ci-deployer` credentials when prompted:
```bash
npm login --registry=https://nexus.your_domain/repository/npm-hosted/
```
Install a package and publish your own:
```bash
npm install express
npm publish --registry=https://nexus.your_domain/repository/npm-hosted/
```
In the Nexus UI, **Browse > npm-proxy** now shows `express` and its dependencies cached locally, and **Browse > npm-hosted** shows your package.
### Maven
Add Nexus as a mirror and store the deploy credentials in `~/.m2/settings.xml`:
```xml
nexus
*
https://nexus.your_domain/repository/maven-public/
nexus
ci-deployer
ci_deployer_password
```
To publish with `mvn deploy`, add a `distributionManagement` section to the project's `pom.xml`. The `id` values must match the `server` id in `settings.xml`:
```xml
nexus
https://nexus.your_domain/repository/maven-releases/
nexus
https://nexus.your_domain/repository/maven-snapshots/
```
In CI, store the password as a masked variable and generate `settings.xml` or `.npmrc` at runtime instead of committing credentials to the repository.
## Step 8 - Cleanup and backups
Proxy repositories grow as long as you keep downloading new versions. Under **Settings > Repository > Cleanup Policies**, create a policy (for example, remove components not downloaded in 90 days) and assign it to your proxy repositories in each repository's settings. Nexus applies cleanup policies with a built-in daily task. Deleted content is only removed from disk after the **Admin - Compact blob store** task runs, which you can schedule under **Settings > System > Tasks**.
For backups, the simplest consistent method is a short stop and a copy of the data volume:
```bash
cd /opt/nexus
sudo docker compose stop nexus
sudo docker run --rm -v nexus_nexus-data:/data:ro -v /var/backups:/backup alpine \
tar -czf /backup/nexus-data-$(date +%F).tar.gz -C /data .
sudo docker compose start nexus
```
The volume name is the project directory name plus the volume name (`nexus_nexus-data`). Check it with `sudo docker volume ls` if you used a different directory.
To upgrade Nexus, back up first, then pull the new image and recreate the container:
```bash
sudo docker compose pull
sudo docker compose up -d
```
## Troubleshooting
**`502 Bad Gateway` from Nginx.** Nexus is still starting or has crashed. Check `sudo docker compose logs nexus` in `/opt/nexus`. Out of memory errors mean the heap settings are too large for the server or the server needs more RAM.
**npm returns `401 Unauthorized` when publishing.** The **npm Bearer Token Realm** is not active, or the user's role lacks the `nx-repository-view-npm-*-*` privilege.
**Uploads fail with `413 Request Entity Too Large`.** Increase `client_max_body_size` in the Nginx server block and reload Nginx.
**`admin.password` does not exist.** The setup wizard has already been completed, so the file was deleted. Log in with the password you set.
## Conclusion
Nexus Repository now runs on Ubuntu 24.04 in Docker behind Nginx with HTTPS, with npm proxy, hosted and group repositories, the default Maven repositories and a dedicated CI user. Next, you can add proxies for PyPI or Docker Hub using the same proxy, hosted and group pattern, connect Nexus to your LDAP directory for user management, and schedule the backup commands with a systemd timer.