
If you have ever tried to run two Java projects on the same Ubuntu server, each requiring a different JDK version, you already know the pain. Symlinks break. The update-alternatives command gets messy. And before long, your JAVA_HOME points somewhere that does not match what your build tool expects.
SDKMAN (Software Development Kit Manager) solves this problem completely. It lets you install, switch, and manage multiple versions of Java, Maven, Gradle, Kotlin, and 16+ other JVM-based tools from a single command-line interface.
This tutorial walks you through a full SDKMAN on Ubuntu 26.04 setup on Ubuntu 26.04 LTS “Resolute Raccoon,” covering everything from prerequisites to installing SDKs, using the .sdkmanrc file for per-project version pinning, and cleaning up when you are done. Whether you are setting up a development laptop or provisioning a fresh cloud server, this guide gives you exactly what you need.
What Is SDKMAN and Why Developers on Ubuntu Use It
Before jumping into the terminal, it is worth understanding what SDKMAN actually does and why it is better than the alternatives.
Ubuntu’s default apt package manager installs one version of Java per release cycle. If your production app needs Java 11 and your new microservice targets Java 21, apt forces you into ugly workarounds like manual symlink management or installing third-party PPAs that can conflict with each other during system upgrades.
SDKMAN takes a different approach. It installs every SDK into its own directory under ~/.sdkman/candidates/, injects the active version into your PATH on each shell session, and lets you switch versions in seconds with a single command. You keep full control without touching a single system file.
Here is what SDKMAN manages out of the box:
- Java (Temurin, GraalVM, Corretto, Zulu, Liberica, Microsoft, and more)
- Apache Maven and Gradle
- Kotlin, Groovy, Scala
- Spring Boot CLI, Micronaut, Quarkus
- 16+ additional JVM-based SDKs
For teams running CI/CD pipelines where different projects pin different JDK builds, SDKMAN’s .sdkmanrc file is a standout feature. Commit it to your Git repo and every developer automatically uses the exact same SDK version. More on that in Step 7.
Prerequisites
Before you run a single command, confirm that your environment meets these requirements:
System:
- Ubuntu 26.04 LTS (Resolute Raccoon) installed, desktop or server edition
- A user account with
sudoprivileges - An active internet connection
Terminal access:
- Direct terminal on desktop
- SSH access on remote servers
Required packages:
curl(to download the SDKMAN installer script)zipandunzip(SDKMAN downloads SDKs as.ziparchives and extracts them locally)
If any of these three packages are missing, the SDKMAN installation will either fail outright or break silently mid-install when it tries to extract an SDK archive. You will handle all three in Step 2.
Step 1: Update Your Ubuntu 26.04 System
Always start with a system update. Running SDKMAN’s installer on top of stale packages can cause shared library conflicts, particularly with the versions of libssl and libc that curl depends on. This step takes two minutes and prevents hours of debugging.
Run these two commands:
sudo apt update
sudo apt upgrade -y
What these commands do:
sudo apt updatesyncs your local package index with Ubuntu’s repositories. It does not install or change anything yet; it just checks what is available.sudo apt upgrade -yinstalls all available updates for packages already on your system. The-yflag auto-confirms so you do not need to manually approve each upgrade.
Expected output (truncated example):
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
Calculating upgrade... Done
The following packages will be upgraded:
libssl3 openssl curl ...
After the upgrade completes, reboot if the system requests it. For servers, a quick sudo reboot ensures the new kernel and library versions are active before you proceed.
Step 2: Install Required Dependencies
With your system current, install the three packages SDKMAN depends on.
sudo apt install curl zip unzip -y
Why each package matters:
curlhandles the HTTPS download of the SDKMAN installer script. Without it, you cannot pull the installer fromget.sdkman.io.zipandunzipare used internally by SDKMAN every time you install an SDK. SDKMAN downloads SDK builds as.ziparchives to~/.sdkman/archives/and immediately unpacks them into~/.sdkman/candidates/. Missing either package causes a cryptic extraction error that does not clearly point back to the missing dependency.
Verify that all three installed correctly:
curl --version && zip --version && unzip --version
You should see version output for all three tools. If any command returns command not found, re-run the apt install line.
Sysadmin note: Ubuntu 26.04 minimal server images strip non-essential packages to reduce attack surface. Do not assume curl or unzip are already there, even on a freshly deployed cloud VPS.
Step 3: Download and Run the Official SDKMAN Installer
With dependencies in place, you are ready to install SDKMAN. The official installer is a single curl command that downloads and runs the setup script directly.
curl -s "https://get.sdkman.io" | bash
Breaking down this command:
curl -sfetches the installer script silently (no progress bars). The-sflag keeps output clean, which matters especially in CI/CD logs."https://get.sdkman.io"is the official installer URL served over HTTPS from SDKMAN’s own infrastructure.| bashpipes the downloaded script directly to Bash for execution.
What happens during installation:
- SDKMAN creates the
~/.sdkman/directory tree:bin/,candidates/,archives/,etc/,tmp/ - It appends an initialization block to your
~/.bashrcand~/.bash_profile - It downloads its native binary component (a small Go binary for parallel downloads)
Expected output (abbreviated):
Looking for a previous installation of SDKMAN...
Looking for unzip...
Looking for zip...
Looking for curl...
Installing SDKMAN scripts...
All done!
Please open a new terminal, or run the following in the existing one:
source "$HOME/.sdkman/bin/sdkman-init.sh"
Installing to a Custom Directory (Optional)
If your home directory is on an NFS mount (common in enterprise server environments), write speed and permission issues can make ~/.sdkman problematic. In that case, specify a local path before running the installer:
export SDKMAN_DIR="/usr/local/sdkman" && curl -s "https://get.sdkman.io" | bash
Why this matters: NFS-mounted home directories add latency on every archive read and write operation. SDKMAN downloads and unpacks several hundred megabytes of SDK files. On an NFS mount, this creates noticeable slowdowns and occasional permission errors that are difficult to trace.
For CI/CD Pipelines
If you run this inside a Jenkins pipeline, GitHub Actions runner, or any automated provisioning script, use CI mode to suppress interactive prompts and colored output:
curl -s "https://get.sdkman.io?ci=true" | bash
CI mode automatically sets sdkman_auto_answer=true, disables color output, and turns off self-update checks so your pipeline does not get interrupted by unexpected SDKMAN upgrades.
Step 4: Initialize SDKMAN in Your Current Shell
The installer modifies your ~/.bashrc, but that file is only read when you open a new terminal session. Your currently open terminal does not automatically pick up the changes. Run this command to activate SDKMAN without closing your terminal:
source "$HOME/.sdkman/bin/sdkman-init.sh"
Why source and not just running the script directly: When you run a script with bash script.sh, Bash spawns a child process. Every export and PATH change lives in that child process and dies when it exits. The source command (also written as .) runs the script inside your current shell process, so every variable change persists for your entire session. This is the same reason you use source ~/.bashrc to reload your shell config without logging out.
ZSH Users
If your default shell is ZSH (common on Ubuntu 26.04 desktop with Oh My Zsh installed), confirm SDKMAN added the init line to ~/.zshrc:
grep "sdkman-init" ~/.zshrc
If that returns nothing, add it manually:
echo 'source "$HOME/.sdkman/bin/sdkman-init.sh"' >> ~/.zshrc && source ~/.zshrc
Step 5: Verify the SDKMAN Installation
Before installing any SDKs, confirm that SDKMAN is working properly:
sdk version
Expected output:
SDKMAN!
script: 5.19.0
native: 0.5.0
The script version is the Bash-based core and the native version is the Go binary that handles parallel downloads. Both should display without errors.
Run sdk help as a secondary check:
sdk help
This prints the full command reference. If it loads cleanly, your SDKMAN installation is healthy and ready for use.
If you see sdk: command not found even after sourcing, check which shell you are running:
echo $SHELL
Then verify the SDKMAN init line exists in the correct rc file (~/.bashrc for Bash, ~/.zshrc for ZSH). If it is missing, the installer may have had a partial failure. Re-run Step 3.
Step 6: Install and Configure SDKMAN on Ubuntu 26.04
Now comes the practical part. This section covers how to list available SDKs, install Java and build tools, and switch between versions.
List Available Java Distributions
sdk list java
This command fetches the full catalog of available Java distributions and versions from SDKMAN’s API. The output is a paginated table showing vendor, version identifier, and status (installed or not).
Always run sdk list java before installing. SDKMAN version identifiers include the distribution suffix (for example, -tem for Temurin, -graal for GraalVM). Installing without knowing the exact identifier produces an “invalid candidate version” error.
Install Java 21 LTS (Temurin)
Eclipse Temurin is the recommended default for most Ubuntu server setups. It is TCK-certified, free for commercial use, and maintained under the Eclipse Adoptium Working Group.
sdk install java 21.0.3-tem
SDKMAN downloads the archive to ~/.sdkman/archives/, extracts it to ~/.sdkman/candidates/java/21.0.3-tem/, and sets it as the default Java version automatically.
Verify the installation:
java -version
Expected output:
openjdk version "21.0.3" 2024-04-16 LTS
OpenJDK Runtime Environment Temurin-21.0.3+9 (build 21.0.3+9)
OpenJDK 64-Bit Server VM Temurin-21.0.3+9 (build 21.0.3+9, mixed mode, sharing)
Install Java 11 LTS Alongside Java 21
One of SDKMAN’s core strengths is running multiple Java versions in parallel. Install Java 11 the same way:
sdk install java 11.0.23-tem
SDKMAN keeps both versions installed. Your system default stays on Java 21 until you explicitly switch.
Switch Between Java Versions
Temporary switch (current terminal session only):
sdk use java 11.0.23-tem
Permanent default switch (all future sessions):
sdk default java 11.0.23-tem
Why this matters for production work: sdk use changes the active version only in your current shell. Open a new terminal and the default version is active again. This is ideal for testing a legacy app under Java 11 without disturbing your system-wide default.
Install Maven and Gradle
sdk install maven
sdk install gradle
By default, SDKMAN installs the latest stable release of each tool. If you need a specific version:
sdk install gradle 8.7
sdk install maven 3.9.6
Why manage Maven and Gradle through SDKMAN instead of apt: Ubuntu 26.04’s apt repository ships one version of Maven per release cycle. If your project requires Maven 3.9.x and the repo only has 3.6.x, you either add a PPA (which introduces maintenance risk) or build from source (which wastes time). SDKMAN gives you any version in two seconds with zero PPA sprawl.
Step 7: Pin SDK Versions Per Project with .sdkmanrc
This step separates casual SDKMAN users from teams that actually rely on it in production.
Create a Project-Level .sdkmanrc File
Navigate to your project root and run:
sdk env init
This creates a .sdkmanrc file in the current directory. Open it with any text editor:
nano .sdkmanrc
Example .sdkmanrc content:
java=21.0.3-tem
maven=3.9.6
gradle=8.7
Save the file and load the pinned environment:
sdk env
To automatically install missing SDKs defined in the file:
sdk env install
Why .sdkmanrc is essential for team projects: When you commit this file to Git, every developer and every CI runner that executes sdk env uses the exact same SDK versions. This eliminates an entire class of “works on my machine” bugs caused by JDK micro-version differences between developer laptops and build servers. It also makes onboarding new team members faster because they do not spend time figuring out which Java version the project expects.
Step 8: Keep SDKMAN and SDKs Updated
SDKMAN ships a self-update mechanism for both the tool itself and the SDKs it manages.
Update SDKMAN itself:
sdk self-update
Check for and install SDK updates:
sdk upgrade
Update a specific SDK only:
sdk upgrade java
Why run sdk self-update regularly: SDKMAN’s native Go binary receives independent security patches separate from the SDK candidates it manages. Running an outdated SDKMAN version can leave you with broken TLS negotiation or failed archive verification when downloading new SDKs.
For servers, add a monthly cron job to automate this:
crontab -e
Add this line:
0 3 1 * * /bin/bash -l -c 'source $HOME/.sdkman/bin/sdkman-init.sh && sdk self-update && sdk upgrade'
This runs at 3:00 AM on the first day of every month.
Troubleshooting Common SDKMAN Errors on Ubuntu 26.04 LTS
Error 1: sdk: command not found After Installation
Cause: The installer modified ~/.bashrc but your current terminal session has not re-read it yet.
Fix:
source "$HOME/.sdkman/bin/sdkman-init.sh"
If the error persists, check whether you are using a login shell (common with SSH sessions) that reads ~/.bash_profile instead of ~/.bashrc:
echo $0
If the output starts with a - (like -bash), it is a login shell. Verify that ~/.bash_profile sources ~/.bashrc, or add the SDKMAN init line directly to ~/.bash_profile.
Error 2: curl: (6) Could Not Resolve Host: get.sdkman.io
Cause: DNS resolution failure or no active internet connection.
Fix: First test basic connectivity:
ping 8.8.8.8
Then test DNS:
nslookup get.sdkman.io
If ping 8.8.8.8 works but nslookup fails, your DNS is broken. On Ubuntu 26.04, check /etc/resolv.conf and verify a nameserver is configured. Cloud VPS images sometimes boot without a valid nameserver until cloud-init completes fully.
Error 3: unzip Error During SDK Install
Cause: The zip or unzip package is missing from the system.
Fix:
sudo apt install zip unzip -y
Then retry your SDK install:
sdk install java 21.0.3-tem
This happens most often on Ubuntu 26.04 server minimal images that skip non-essential packages by default.
Error 4: Permission Denied on Custom SDKMAN Directory
Cause: The custom SDKMAN_DIR path was created by root but you are running as a non-root user.
Fix:
sudo chown -R $USER:$USER /usr/local/sdkman
This transfers ownership of the entire directory tree to your current user, allowing SDKMAN to read and write without sudo.
Error 5: SDK Version Not Found After sdk list
Cause: You typed the version identifier incorrectly or mixed up distribution suffixes.
Fix: Re-run sdk list java and copy the exact identifier from the table, including the distribution suffix:
sdk list java | grep "21.*tem"
Copy the full identifier shown (example: 21.0.3-tem) and use it exactly in your install command.
How To Uninstall SDKMAN from Ubuntu 26.04 LTS
Step 1: Optional backup (recommended)
tar zcvf ~/sdkman-backup_$(date +%F-%kh%M).tar.gz -C ~/ .sdkman
This compresses your entire ~/.sdkman/ directory, including all downloaded SDK archives. If you reinstall SDKMAN later, you can restore the archives and avoid re-downloading gigabytes of files.
Step 2: Remove the SDKMAN directory
rm -rf ~/.sdkman
Step 3: Clean your shell config files
Open ~/.bashrc in a text editor:
nano ~/.bashrc
Scroll to the bottom and remove the SDKMAN initialization block. It looks like this:
#THIS MUST BE AT THE END OF THE FILE FOR SDKMAN TO WORK!!!
[[ -s "/home/yourusername/.sdkman/bin/sdkman-init.sh" ]] && source "/home/yourusername/.sdkman/bin/sdkman-init.sh"
Repeat this for ~/.bash_profile and ~/.zshrc if applicable.
Why clean the shell config files: Leaving the dead source line in ~/.bashrc after removing the ~/.sdkman directory generates a “No such file or directory” error every time you open a new terminal. It will not break anything critical, but it will confuse every developer who SSHes into that server and sees the error without knowing its cause.
Congratulations! You have successfully installed SDKMAN. Thanks for using this tutorial for installing SDKMAN on Ubuntu 26.04 LTS (Resolute Raccoon) system. For additional help or useful information, we recommend you check the official SDKMAN website.