How can I set an permanent environment variable per user independent from the used shell (bash, zsh and fish)?

  • not sure I understood, but if you want to set an environment variable for all shells, you can put it in ~/.profile (for one user) or /etc/profile (for all users)
    – tbrugere
    Jun 24, 2021 at 14:43
  • bash doesn't read ~/.profile, only /etc/profile. Jun 24, 2021 at 14:46
  • then, you could, in /etc/profile add a source $HOME/.custom-profile, and use that (though it's a bit hacky)
    – tbrugere
    Jun 24, 2021 at 14:47
  • 2
    @MarcusMüller bash does read .profile when started as a login shell. The exception is only if you or your sysadmin have created a ~/.bash_profile file. Then, but only then, bash will skip ~/.profile and read that one instead.
    – terdon
    Jun 24, 2021 at 14:52
  • @terdon didn't see that in man bash! Good to know. Jun 24, 2021 at 15:07

2 Answers 2


EDIT: according to What's the best distro/shell-agnostic way to set environment variables?, the best solution for this is ~/.pam_environment

EDIT: reverted to the hacky solution since ~/.profile is not read by all shells:

All shells source /etc/profile.

That means in /etc/profile, you could put a line like

. $HOME/.custom-profile

Then, you could add your variables to ~/.custom-profile for each user

  • You are just recreating the existing functionality. This is what ~/.profile is for. If a shell reads /etc/profile, it will also read ~/.profile.
    – terdon
    Jun 24, 2021 at 15:09
  • yep, I was misguided by the comment telling that bash didn't read ~/.profile, editing
    – tbrugere
    Jun 24, 2021 at 16:10
  • The zsh shell does not read ~/.profile by default, and neither does the fish shell.
    – Kusalananda
    Jun 24, 2021 at 16:17
  • @terdon zsh only reads /etc/profile if it's started in sh or ksh compatibility mode. The fish shell does not to my knowledge read /etc/profile.
    – Kusalananda
    Jun 24, 2021 at 16:19
  • ok reverting to previous answer
    – tbrugere
    Jun 24, 2021 at 16:20

All shells read different per-user profile files (zsh: ~/.profile, bash: ~/.bash_profile, csh has only an rc file, and so on). So you'd have to change all of these potential candidates.

However, most shells at the very least fall back to reading ~/.profile (thanks @terdon for pointing this out!), so that's where you can put your exports.

Since "logging in" is usually done by a process having the ability to change its uid and gid (typically: a login manager runnning as root), it's up to these programs to define the environment for the spawned program (e.g. a shell).

But: there's more than one login manager (your GDM/lightdm/KDM/... visual login manager, getty, logind/loginct, ssh, getty...), and they read configuration from different files, so there's no consistent way there, either.


Not the answer you're looking for? Browse other questions tagged .