When you need to set environment variables globally across all users (including root) on Linux systems, the most reliable method is to use /etc/environment
. This file is specifically designed for system-wide environment variables and is processed by PAM (Pluggable Authentication Modules), making it available to all users and services.
# Example: Setting JAVA_HOME in /etc/environment
JAVA_HOME="/usr/lib/jvm/java-11-openjdk-amd64"
PATH="$PATH:$JAVA_HOME/bin"
This solution meets all your requirements:
- Works for all users (including root)
- Available immediately after system boot
- Not shell-specific (works with bash, sh, dash, etc.)
- Consistent across Ubuntu, Debian, and RHEL-based systems
- Easy to script deployments
While /etc/profile
or /etc/bash.bashrc
might seem tempting, they have limitations:
# Not recommended for system-wide variables
# /etc/profile only affects login shells
# /etc/bash.bashrc only affects interactive bash shells
For automated setups, here's a robust script that works across distributions:
#!/bin/bash
JAVA_PATH=$(update-alternatives --list java | head -1 | sed 's%/bin/java%%')
echo "JAVA_HOME=\"$JAVA_PATH\"" | sudo tee -a /etc/environment
echo "PATH=\"\$PATH:\$JAVA_HOME/bin\"" | sudo tee -a /etc/environment
After making changes, verify with:
# For immediate testing in current session
su - $USER
echo $JAVA_HOME
# Alternative testing method (doesn't require new session)
systemd-run --user --wait /bin/sh -c 'echo $JAVA_HOME'
Remember that changes to /etc/environment
require either a new login session or system reboot to take effect for existing sessions.
On modern systems using systemd, you might need to additionally ensure the variables propagate to the user session:
# For systemd user instances
systemctl --user import-environment JAVA_HOME PATH
Setting environment variables that persist across all users (including root) and all shell types is a common sysadmin task, especially for Java development where JAVA_HOME
needs global availability. The challenge lies in finding a solution that works across different Linux distributions while surviving both interactive and non-interactive sessions.
For system-wide environment variables that need to be available to all users and services, the most reliable method is using /etc/environment
. This file is specifically designed for this purpose and is processed by PAM (Pluggable Authentication Modules) during login.
# Example: Setting JAVA_HOME in /etc/environment
sudo nano /etc/environment
# Add this line (adjust path to your Java installation):
JAVA_HOME="/usr/lib/jvm/java-11-openjdk-amd64"
1. Profile.d Scripts (Distribution-Compatible)
For more flexibility and easier scripting, create a file in /etc/profile.d/
:
sudo nano /etc/profile.d/java_home.sh
# Contents:
export JAVA_HOME="/usr/lib/jvm/java-11-openjdk-amd64"
export PATH="$JAVA_HOME/bin:$PATH"
2. PAM Environment (For Services)
To ensure variables are available even for non-shell sessions (like cron jobs or systemd services):
sudo nano /etc/security/pam_env.conf
# Add:
JAVA_HOME DEFAULT="/usr/lib/jvm/java-11-openjdk-amd64"
After making changes, verify the variable is available:
# Check in current session (may require re-login)
echo $JAVA_HOME
# Force reload for testing:
source /etc/environment
For systemd services, you might need to add to /etc/systemd/system.conf
:
DefaultEnvironment="JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64"
- Debian/Ubuntu:
/etc/environment
works best - RHEL/CentOS: Both
/etc/environment
and/etc/profile.d/
work well - Arch Linux: Prefers
/etc/profile.d/
approach
Here's a Bash script that handles the configuration programmatically:
#!/bin/bash
JAVA_PATH="/usr/lib/jvm/java-11-openjdk-amd64"
# For /etc/environment
if ! grep -q "JAVA_HOME=" /etc/environment; then
echo "JAVA_HOME=\"$JAVA_PATH\"" | sudo tee -a /etc/environment >/dev/null
fi
# For profile.d
sudo bash -c "cat > /etc/profile.d/java_home.sh << EOF
export JAVA_HOME=\"$JAVA_PATH\"
export PATH=\"\$JAVA_HOME/bin:\$PATH\"
EOF"
# Reload environment
source /etc/environment