Environment variables are named values every process inherits: where to find programs (PATH), the home directory, locale, and app settings such as database URLs. Knowing where to set them explains many puzzles, like why a command works in your shell but not in cron or a systemd service.
Before you start
- SSH access to a Linux server running bash (the default on most distros).
Read variables
echo $HOMEprintenv PATHList all variables with env or printenv. Common ones:
| Variable | Holds |
|---|---|
PATH | Directories searched for commands, separated by colons |
HOME | The user's home directory |
USER | Current username |
SHELL | Login shell |
LANG | Locale and character set |
EDITOR | Default editor for crontab -e, git and others |
Set variables in the current shell
export APP_ENV=productionThe variable is available to this shell and programs started from it, until you log out. Without export it stays a shell-only variable that child processes do not see. Set a variable for one command only:
APP_ENV=staging node server.jsRemove it with unset APP_ENV.
Make variables permanent for a user
Add the export line to ~/.bashrc (interactive shells) and reload:
echo 'export EDITOR=nano' >> ~/.bashrc && source ~/.bashrc~/.bashrc: read by interactive non-login shells; on most distros also loaded by~/.profileor~/.bash_profileat login.~/.profile/~/.bash_profile: read at login./etc/environment: simpleKEY=valuelines for all users (noexport, no variable expansion)./etc/profile.d/*.sh: scripts run at login for all users.
Fix "command not found" with PATH
If a program is installed but the shell cannot find it, its directory is not in PATH. Find the binary, then add its folder:
export PATH="$HOME/.local/bin:$PATH"Put that line in ~/.bashrc to keep it. Always include $PATH so you extend it instead of replacing it; overwriting PATH breaks basic commands until you log in again. Check which binary runs with which node or type node.
Variables for systemd services
Services do not read .bashrc. Set variables in the unit file:
[Service]
Environment=NODE_ENV=production
EnvironmentFile=/srv/myapp/.envAfter editing, run systemctl daemon-reload && systemctl restart myapp. Check what a running service sees with systemctl show myapp -p Environment.
Variables for cron jobs
Cron runs with a minimal environment and a short PATH. Set what you need at the top of the crontab:
PATH=/usr/local/bin:/usr/bin:/bin
APP_ENV=productionOr source a file in the job: . /srv/myapp/.env; /usr/local/bin/job.sh.
Variables for web apps
- PHP-FPM:
env[APP_ENV] = productionin the pool file (withclear_env = noto pass all). - Node.js, Python, Laravel: a
.envfile read by the app (dotenv), kept out of Git and readable only by the app user (chmod 600). - Docker:
environment:orenv_file:in Compose.
Troubleshooting
- Works in SSH, fails in cron or systemd: the variable or PATH entry only exists in your interactive shell. Set it for the service or cron explicitly.
- Change has no effect: you edited the file but did not reload. Run
source ~/.bashrcor log in again. - sudo loses variables: sudo resets the environment. Use
sudo -Ecarefully, or pass a variable:sudo VAR=value command.
Environment variables FAQ
Are environment variables safe for secrets?
Safer than hard-coding them in code, but any process of the same user can read them. Keep .env files private and out of version control.
What is the difference between .bashrc and .profile?
.profile runs at login; .bashrc runs for each interactive bash shell. Put PATH changes and exports where your distro's login chain will pick them up, usually .bashrc.
Can I set environment variables on cPanel hosting?
For Node.js and Python apps, the application manager in cPanel has a section for environment variables.
