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.
| Method | Source | Maven Release Used | Java Maven Uses by Default | Best For |
|---|---|---|---|---|
| DNF package | Rocky AppStream | Rocky 10: 3.9.9, Rocky 9: 3.6.3, Rocky 8: 3.5.4 | Rocky 10: Java 21, Rocky 9: Java 17, Rocky 8: Java 8 | Most systems that prefer distro-managed updates |
| Apache binary tarball | Apache Maven downloads | Current Maven 3.x release | The JDK you set with JAVA_HOME | Build 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.gzorapache-maven-3.9.12-bin.tar.gzfilenames 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-develorjava-11-openjdk-develpackage and adjust theJAVA_HOMEpath 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_VERSIONmanually 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/mavensymlink, and the Maven profile script. If you want a backup first, runmkdir -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 withcp -a ~/.m2 ~/m2-backupif 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.


Formatting tips for your comment
You can use basic HTML to format your comment. Useful tags currently allowed in published comments:
<code>command</code>command<strong>bold</strong><em>italic</em><blockquote>quote</blockquote>