How to Install Apache Maven on Rocky Linux 10, 9 and 8

Last updated Saturday, May 16, 2026 9:46 am Joshua James 8 min read

Java builds get easier to repeat when dependency resolution, tests, and packaging all run through one project file. To install Apache Maven on Rocky Linux, use the AppStream package for a low-maintenance mvn command, or install the current Apache binary under /opt when a build needs a newer Maven core than Rocky ships.

Rocky Linux 10 currently packages Maven 3.9.9, Rocky Linux 9 packages Maven 3.6.3, and Rocky Linux 8 packages Maven 3.5.4. The manual path resolves the current Maven 3.x release from Apache’s download tree, sets /opt/maven/bin in your PATH, and keeps /opt/maven as a stable symlink for future upgrades.

Install Apache Maven on Rocky Linux

Start with DNF unless your project, CI runner, or plugin stack requires a newer Maven version than AppStream provides. The manual tarball method gives you the latest upstream Maven release, but you also own checksum verification, PATH setup, updates, and removal.

MethodSourceMaven Release UsedJava Maven Uses by DefaultBest For
DNF packageRocky AppStreamRocky 10: 3.9.9, Rocky 9: 3.6.3, Rocky 8: 3.5.4Rocky 10: Java 21, Rocky 9: Java 17, Rocky 8: Java 8Most systems that prefer distro-managed updates
Apache binary tarballApache Maven downloadsCurrent Maven 3.x releaseThe JDK you set with JAVA_HOMEBuild hosts that need the newest Maven 3.x release

Apache currently recommends Maven 3.9.15 for Maven 3.x users, while Maven 4 remains a preview release. Apache’s release history lists Maven 3.9.9 as an August 17, 2024 release and Maven 3.9.12 as a December 13, 2025 release, so old apache-maven-3.9.9-bin.tar.gz or apache-maven-3.9.12-bin.tar.gz filenames are historical unless your build is pinned to them.

Method 1: Install Apache Maven with DNF

Step 1: Refresh Rocky Linux Packages

Refresh package metadata and apply pending updates before installing Maven:

sudo dnf upgrade --refresh

This keeps the package set consistent before DNF resolves Maven, Java, and the supporting Java libraries. If DNF downloads are consistently slow, tune mirror selection and parallel downloads with the DNF speed guide for Rocky Linux after the install is complete.

Step 2: Install the Maven Package

Install Maven from Rocky Linux AppStream:

sudo dnf install maven

The Maven package pulls in the Java runtime and compiler package that Rocky associates with that Maven build. On Rocky Linux 10 that is Java 21, on Rocky Linux 9 it is Java 17, and on Rocky Linux 8 it is Java 8. Install a newer JDK separately only when your project needs it, then set JAVA_HOME so Maven uses that JDK.

Step 3: Verify Maven and Java

Check the Maven version and the Java runtime Maven selected:

mvn -version

Relevant output on Rocky Linux 10 includes:

Apache Maven 3.9.9 (Red Hat 3.9.9-3)
Maven home: /usr/share/maven
Java version: 21.0.11, vendor: Red Hat, Inc., runtime: /usr/lib/jvm/java-21-openjdk

Rocky Linux 9 reports Maven 3.6.3 with Java 17, while Rocky Linux 8 reports Maven 3.5.4 with Java 8. If your output shows the wrong Java branch for your project, use the JAVA_HOME troubleshooting section later in this article.

Confirm the Java compiler is available too:

javac -version

Expected output depends on the Rocky Linux release. Rocky Linux 10 currently returns:

javac 21.0.11

Method 2: Install Apache Maven from the Binary Tarball

The Apache binary tarball installs Maven outside the RPM database under /opt. Use this method when you want Apache’s current Maven 3.x release or need your Rocky build host to match another environment that already runs upstream Maven.

The PATH setup uses /opt/maven/bin, not the versioned /opt/apache-maven-3.9.15/bin directory. That symlink-based layout answers the common PATH problem directly: future upgrades only move the /opt/maven symlink, so you do not edit every shell profile when the version changes.

Step 1: Install Manual Method Prerequisites

Install Java 21, curl, and tar before downloading Maven:

sudo dnf install java-21-openjdk-devel tar curl

The JDK package provides both java and javac. The curl command fetches Apache metadata and release files, while tar extracts the downloaded tar.gz archive.

Verify the Java runtime before continuing:

java -version

Relevant output includes the OpenJDK branch and vendor:

openjdk version "21.0.11" 2026-04-15 LTS
OpenJDK Runtime Environment (Red_Hat-21.0.11.0.10-2) (build 21.0.11+10-LTS)

Java 21 is available in the default AppStream repositories for Rocky Linux 10, 9, and 8. If your project targets Java 17 or Java 11 instead, install the matching java-17-openjdk-devel or java-11-openjdk-devel package and adjust the JAVA_HOME path in the profile script below.

Step 2: Download the Latest Maven 3.x Tarball

Resolve the latest Maven 3.x version from Apache’s download tree and download the matching binary archive:

cd /tmp
MAVEN_VERSION=$(curl -fsSL https://dlcdn.apache.org/maven/maven-3/ | grep -oE 'href="[0-9]+[.][0-9]+[.][0-9]+/' | cut -d'"' -f2 | tr -d '/' | sort -V | tail -n 1)

if [ -z "$MAVEN_VERSION" ]; then
  echo "Error: Could not determine the latest Maven version."
else
  curl -fL --progress-bar "https://dlcdn.apache.org/maven/maven-3/${MAVEN_VERSION}/binaries/apache-maven-${MAVEN_VERSION}-bin.tar.gz" -o "apache-maven-${MAVEN_VERSION}-bin.tar.gz"
fi

This sequence reads Apache’s Maven 3 download directory, extracts versioned folders, chooses the newest version with version sorting, and downloads the matching tarball from Apache’s CDN. Keep the same terminal open because the MAVEN_VERSION variable is reused in the next steps.

A completed curl transfer ends with a full progress bar:

######################################################################## 100.0%

Download the SHA512 checksum from Apache’s canonical download host and verify the tarball before extracting it:

curl -fL --progress-bar "https://downloads.apache.org/maven/maven-3/${MAVEN_VERSION}/binaries/apache-maven-${MAVEN_VERSION}-bin.tar.gz.sha512" -o "apache-maven-${MAVEN_VERSION}-bin.tar.gz.sha512"
printf '%s  apache-maven-%s-bin.tar.gz\n' "$(cat "apache-maven-${MAVEN_VERSION}-bin.tar.gz.sha512")" "$MAVEN_VERSION" | sha512sum -c -

Expected output for the current Apache Maven release is:

apache-maven-3.9.15-bin.tar.gz: OK

If the version lookup fails, open the Apache Maven download page, set MAVEN_VERSION manually to the current Maven 3.x release, and rerun the download and checksum commands.

Step 3: Extract Maven to /opt

Extract the verified archive into /opt:

sudo tar xzf "apache-maven-${MAVEN_VERSION}-bin.tar.gz" -C /opt/

The archive creates a versioned directory such as /opt/apache-maven-3.9.15. If you closed the terminal and lost the variable, set MAVEN_VERSION again before running extraction commands that use it.

Step 4: Create the Stable Maven Symlink

Create or refresh the /opt/maven symlink:

sudo ln -sfn "/opt/apache-maven-${MAVEN_VERSION}" /opt/maven

The -sfn options create a symbolic link, replace an existing link, and treat an existing symlink as the file to replace. Future manual upgrades can extract a newer versioned directory and point /opt/maven at it.

Step 5: Configure JAVA_HOME, M2_HOME, and PATH

Create a system-wide profile script for Maven and the JDK:

printf '%s\n' \
'export JAVA_HOME=/usr/lib/jvm/java-21-openjdk' \
'export M2_HOME=/opt/maven' \
'case ":${PATH}:" in' \
'  *":${M2_HOME}/bin:"*) ;;' \
'  *) PATH="${M2_HOME}/bin:${PATH}" ;;' \
'esac' \
'case ":${PATH}:" in' \
'  *":${JAVA_HOME}/bin:"*) ;;' \
'  *) PATH="${JAVA_HOME}/bin:${PATH}" ;;' \
'esac' \
'export PATH' | sudo tee /etc/profile.d/maven.sh > /dev/null

The profile sets JAVA_HOME to Java 21, points M2_HOME at the stable Maven symlink, and prepends both Java and Maven binaries to PATH without duplicating entries when the file is reloaded. If you installed Java 17 or Java 11 instead, change only the JAVA_HOME value before saving the file.

If the DNF Maven package is also installed, this PATH order makes the /opt/maven copy win in new login shells. Remove the DNF package later if you want only one Maven installation on the system.

Step 6: Load the Maven Profile

Load the profile in your current terminal:

source /etc/profile.d/maven.sh

Opening a new terminal or logging out and back in also loads the profile. Use that option if your shell customizations overwrite PATH after system profile scripts run.

Step 7: Verify the Manual Maven Installation

Confirm that your shell resolves Maven from /opt/maven/bin and that Maven uses the intended JDK:

command -v mvn
mvn -version
javac -version

Relevant output on a Java 21 setup includes:

/opt/maven/bin/mvn
Apache Maven 3.9.15 (98b2cdbfdb5f1ac8781f537ea9acccaed7922349)
Maven home: /opt/maven
Java version: 21.0.11, vendor: Red Hat, Inc., runtime: /usr/lib/jvm/java-21-openjdk
javac 21.0.11

Create a Test Apache Maven Project on Rocky Linux

A small quickstart project proves that Maven can download plugins, compile Java source, run tests, and package a JAR. Run these commands from a temporary working directory if you do not want the sample project in your current folder.

Step 1: Generate a Quickstart Project

Generate a basic Java project from Maven’s quickstart archetype:

mvn -B archetype:generate -DgroupId=com.example.app -DartifactId=my-app -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false

The command creates a my-app directory with a pom.xml, Java source files, and a test skeleton. The first run can take longer because Maven has to populate your local ~/.m2 cache.

Step 2: Build the Project

Enter the project directory and package the sample application. The compiler flags keep the older quickstart archetype compatible with Java 8 through Java 21:

cd my-app
mvn -B package -Dmaven.compiler.source=8 -Dmaven.compiler.target=8

Relevant output includes the build success line:

[INFO] BUILD SUCCESS

Step 3: Run the Compiled Application

Run the generated class from the packaged JAR:

java -cp target/my-app-1.0-SNAPSHOT.jar com.example.app.App

The sample application prints:

Hello World!

Troubleshoot Apache Maven on Rocky Linux

JAVA_HOME Is Missing or Points to the Wrong JDK

Maven prints this error when JAVA_HOME is missing, stale, or pointed at a directory that does not contain a working JDK:

The JAVA_HOME environment variable is not defined correctly,
this environment variable is needed to run this program.

Check the current variable and the Java command path:

printf 'JAVA_HOME=%s\n' "$JAVA_HOME"
readlink -f /usr/bin/java

When JAVA_HOME is unset, the first line is empty:

JAVA_HOME=
/usr/lib/jvm/java-21-openjdk/bin/java

Set a system-wide Java 21 environment file when Maven should use that JDK:

printf '%s\n' \
'export JAVA_HOME=/usr/lib/jvm/java-21-openjdk' \
'case ":${PATH}:" in' \
'  *":${JAVA_HOME}/bin:"*) ;;' \
'  *) PATH="${JAVA_HOME}/bin:${PATH}" ;;' \
'esac' \
'export PATH' | sudo tee /etc/profile.d/java-home.sh > /dev/null
source /etc/profile.d/java-home.sh

Verify Maven again:

mvn -version | grep 'Java version'

Expected output for Java 21 is:

Java version: 21.0.11, vendor: Red Hat, Inc., runtime: /usr/lib/jvm/java-21-openjdk

DNF Maven Uses Java 17 or Java 8 Instead of Java 21

The DNF package intentionally follows Rocky’s Maven packaging: Rocky Linux 9 uses Java 17 for Maven, and Rocky Linux 8 uses Java 8. Installing java-21-openjdk-devel alone does not always change the mvn launcher, so set JAVA_HOME when the build must run with Java 21.

sudo dnf install java-21-openjdk-devel
printf '%s\n' \
'export JAVA_HOME=/usr/lib/jvm/java-21-openjdk' \
'case ":${PATH}:" in' \
'  *":${JAVA_HOME}/bin:"*) ;;' \
'  *) PATH="${JAVA_HOME}/bin:${PATH}" ;;' \
'esac' \
'export PATH' | sudo tee /etc/profile.d/java-home.sh > /dev/null
source /etc/profile.d/java-home.sh
mvn -version | grep 'Java version'

Use /usr/lib/jvm/java-17-openjdk or /usr/lib/jvm/java-11-openjdk instead if your project targets those branches.

mvn Command Not Found After Manual Install

If the shell cannot find mvn after a manual install, the profile did not load or the symlink is missing:

bash: mvn: command not found

Check the PATH result and the Maven symlink target:

command -v mvn || echo "mvn not found in PATH"
readlink -f /opt/maven
test -x /opt/maven/bin/mvn && echo "/opt/maven/bin/mvn exists"

Relevant output when Maven exists but PATH is not loaded looks like this:

mvn not found in PATH
/opt/apache-maven-3.9.15
/opt/maven/bin/mvn exists

Reload the profile or open a new terminal:

source /etc/profile.d/maven.sh
command -v mvn

Source Option 5 Is No Longer Supported

Older quickstart projects can fail on Java 17 or Java 21 because the default compiler settings target Java 5:

[ERROR] Source option 5 is no longer supported. Use 7 or later.
[ERROR] Target option 5 is no longer supported. Use 7 or later.

For the sample project in this article, rebuild with explicit Java 8 source and target settings:

mvn -B package -Dmaven.compiler.source=8 -Dmaven.compiler.target=8

For a real project, place the compiler settings in pom.xml so every developer and CI runner uses the same Java target.

Update Apache Maven on Rocky Linux

Update DNF-Installed Maven

DNF-installed Maven updates with normal Rocky Linux package updates:

sudo dnf upgrade --refresh

To check only Maven and its direct package transaction, run:

sudo dnf upgrade --refresh maven

Update Manually Installed Maven

Manual Maven updates repeat the same download, checksum, extraction, and symlink steps. Run these commands when you want a one-time update:

cd /tmp
MAVEN_VERSION=$(curl -fsSL https://dlcdn.apache.org/maven/maven-3/ | grep -oE 'href="[0-9]+[.][0-9]+[.][0-9]+/' | cut -d'"' -f2 | tr -d '/' | sort -V | tail -n 1)

if [ -z "$MAVEN_VERSION" ]; then
  echo "Error: Could not determine the latest Maven version."
else
  curl -fL --progress-bar "https://dlcdn.apache.org/maven/maven-3/${MAVEN_VERSION}/binaries/apache-maven-${MAVEN_VERSION}-bin.tar.gz" -o "apache-maven-${MAVEN_VERSION}-bin.tar.gz"
  curl -fL --progress-bar "https://downloads.apache.org/maven/maven-3/${MAVEN_VERSION}/binaries/apache-maven-${MAVEN_VERSION}-bin.tar.gz.sha512" -o "apache-maven-${MAVEN_VERSION}-bin.tar.gz.sha512"
  printf '%s  apache-maven-%s-bin.tar.gz\n' "$(cat "apache-maven-${MAVEN_VERSION}-bin.tar.gz.sha512")" "$MAVEN_VERSION" | sha512sum -c -
  sudo tar xzf "apache-maven-${MAVEN_VERSION}-bin.tar.gz" -C /opt/
  sudo ln -sfn "/opt/apache-maven-${MAVEN_VERSION}" /opt/maven
  mvn -version
fi

For repeated checks, save a small update helper in your home directory:

cat <<'EOF' > ~/update-maven.sh
#!/usr/bin/env bash
set -euo pipefail

for cmd in curl grep cut tr sort sed head tail sha512sum tar mvn sudo; do
  if ! command -v "$cmd" >/dev/null 2>&1; then
    echo "Error: $cmd is required but not installed."
    echo "Run: sudo dnf install curl tar grep coreutils sed"
    exit 1
  fi
done

latest_maven_version() {
  curl -fsSL https://dlcdn.apache.org/maven/maven-3/ | grep -oE 'href="[0-9]+[.][0-9]+[.][0-9]+/' | cut -d'"' -f2 | tr -d '/' | sort -V | tail -n 1 || true
}

echo "Checking for Maven updates..."
MAVEN_COMMAND=$(command -v mvn)
CURRENT_VERSION=$(mvn -version 2>/dev/null | sed -n 's/^Apache Maven \([0-9][0-9.]*\).*/\1/p' | head -n 1)
CURRENT_VERSION=${CURRENT_VERSION:-not installed}
LATEST_VERSION=$(latest_maven_version)

if [ -z "$LATEST_VERSION" ]; then
  echo "Error: Could not determine the latest Maven version from Apache."
  exit 1
fi

echo "Current installed version: $CURRENT_VERSION"
echo "Latest available version:  $LATEST_VERSION"
echo "Active mvn command:        $MAVEN_COMMAND"
echo ""

if [ "$MAVEN_COMMAND" != "/opt/maven/bin/mvn" ]; then
  echo "Warning: mvn is not resolving to /opt/maven/bin/mvn."
  echo "Reload /etc/profile.d/maven.sh or adjust PATH after the update."
  echo ""
fi

if [ "$CURRENT_VERSION" = "$LATEST_VERSION" ]; then
  echo "Already up to date."
  exit 0
fi

read -r -p "Continue with update? (y/n) " reply
case "$reply" in
  [Yy]*) ;;
  *) echo "Update cancelled."; exit 0 ;;
esac

cd /tmp
echo "Downloading Maven $LATEST_VERSION..."
curl -fL --progress-bar "https://dlcdn.apache.org/maven/maven-3/${LATEST_VERSION}/binaries/apache-maven-${LATEST_VERSION}-bin.tar.gz" -o "apache-maven-${LATEST_VERSION}-bin.tar.gz"
curl -fL --progress-bar "https://downloads.apache.org/maven/maven-3/${LATEST_VERSION}/binaries/apache-maven-${LATEST_VERSION}-bin.tar.gz.sha512" -o "apache-maven-${LATEST_VERSION}-bin.tar.gz.sha512"

echo "Verifying SHA512 checksum..."
printf '%s  apache-maven-%s-bin.tar.gz\n' "$(cat "apache-maven-${LATEST_VERSION}-bin.tar.gz.sha512")" "$LATEST_VERSION" | sha512sum -c -

echo "Extracting to /opt..."
sudo tar xzf "apache-maven-${LATEST_VERSION}-bin.tar.gz" -C /opt/

echo "Updating /opt/maven..."
sudo ln -sfn "/opt/apache-maven-${LATEST_VERSION}" /opt/maven

rm -f "apache-maven-${LATEST_VERSION}-bin.tar.gz" "apache-maven-${LATEST_VERSION}-bin.tar.gz.sha512"

echo "Update complete."
mvn -version
EOF

Make the helper executable and run it whenever you want to check for a newer Apache Maven release:

chmod +x ~/update-maven.sh
~/update-maven.sh

Expected output when the manual installation is already current:

Checking for Maven updates...
Current installed version: 3.9.15
Latest available version:  3.9.15
Active mvn command:        /opt/maven/bin/mvn

Already up to date.

Avoid unattended Maven tarball upgrades on production build hosts. Review Maven release notes, update a staging build host first, and run your project test suite before moving a shared CI runner to a newer Maven release.

Remove Apache Maven from Rocky Linux

Remove DNF-Installed Maven

Remove the DNF-managed Maven package with:

sudo dnf remove maven

DNF shows the packages it plans to remove before you confirm. Review that transaction carefully when Java is shared with other tools on the same system.

If DNF was your only Maven installation, verify that no mvn command remains in PATH. If the command still resolves to /opt/maven/bin/mvn, remove the manual installation separately.

command -v mvn || echo "mvn not found"

Expected output after removal is:

mvn not found

Remove Manually Installed Maven

The following commands permanently delete the versioned Maven directories under /opt, the /opt/maven symlink, and the Maven profile script. If you want a backup first, run mkdir -p ~/maven-backup && sudo cp -a /opt/apache-maven-* /opt/maven /etc/profile.d/maven.sh ~/maven-backup/.

Review the manual-install paths before deleting them:

sudo find /opt -maxdepth 1 \( -name 'apache-maven-*' -o -name 'maven' \) -print
test -f /etc/profile.d/maven.sh && echo /etc/profile.d/maven.sh

Delete the manual installation files:

sudo rm -rf /opt/apache-maven-*
sudo rm -f /opt/maven
sudo rm -f /etc/profile.d/maven.sh

If you created a separate Java profile while troubleshooting, remove it too:

sudo rm -f /etc/profile.d/java-home.sh

Clear the shell command cache or open a new terminal:

hash -r
command -v mvn || echo "mvn not found"

Remove Maven User Data

The next command permanently deletes your local Maven repository, cached dependencies, and Maven settings in ~/.m2. Back it up first with cp -a ~/.m2 ~/m2-backup if you may need those settings or cached artifacts later.

Remove the user-level Maven directory only when you no longer need it:

rm -rf ~/.m2

Conclusion

Apache Maven is ready on Rocky Linux as either a DNF-managed build tool or a current Apache binary under /opt/maven. Use the DNF package when stability and automatic updates matter most, keep the manual install for upstream Maven compatibility, and pair new Java projects with Git on Rocky Linux before pushing them into CI.

Follow LinuxCapable

Want more LinuxCapable guides in Google?

Add LinuxCapable as a preferred source so Google can show more of our fresh Linux tutorials in Top Stories and From your sources when relevant.

Add LinuxCapable as a preferred source on Google
Search LinuxCapable

Need another guide?

Search LinuxCapable for package installs, commands, troubleshooting, and follow-up guides related to what you just read.

Found this guide useful?

Support LinuxCapable to keep tutorials free and up to date.

Buy me a coffeeBuy me a coffee
Before commenting, please review our Comments Policy.
Formatting tips for your comment

You can use basic HTML to format your comment. Useful tags currently allowed in published comments:

You type Result
<code>command</code> command
<strong>bold</strong> bold
<em>italic</em> italic
<blockquote>quote</blockquote> quote block

Got a Question or Feedback?

We read and reply to every comment - let us know how we can help or improve this guide.

Let us know you are human: