HOME
The absolute path to the current user's home directory. Used as the default location for user configuration files, caches, and personal data. On Linux it is typically /home/username, on macOS /Users/username.
Last updated:
HOME holds the absolute path to the current user's home directory, and a huge amount of tooling builds paths from it: ~/.ssh, ~/.aws, ~/.config, ~/.cache, shell history, and the `~` shorthand all resolve through HOME. The login process sets it from the user's /etc/passwd entry, so it normally matches the account you logged in as. The trouble starts in containers, cron, and systemd services, where HOME is often unset or pointed at `/` — and every tool that expects ~/.config silently writes to the wrong place or fails to find its config.
- Provider
- General / OS
- Category
- system
- Set by
- Set by the login process based on the user's /etc/passwd entry
- Example
- /home/johndoe
How to set HOME
reference it in paths
cat "$HOME/.ssh/config"
cd "$HOME/projects"Dockerfile (give a non-root user a home)
ENV HOME=/home/appuser
RUN useradd --create-home --home-dir $HOME appuser
USER appuserWho sets HOME, and what trusts it?
HOME is set once, at login, by login(1) / PAM, copied from your user's entry in /etc/passwd. The shell never computes it — it just inherits and uses it. That distinction matters because of tilde expansion: when bash or zsh sees a bare ~, it substitutes $HOME; but ~alice is looked up in the passwd database directly, ignoring HOME entirely. So overriding HOME redirects ~, ~/.ssh, ~/.config — every dotfile lookup in every tool — while ~root keeps pointing at the real thing. The XDG base directory spec layers on top: XDG_CONFIG_HOME defaults to $HOME/.config and XDG_CACHE_HOME to $HOME/.cache, so a wrong HOME relocates those too.
The sudo trap: whose HOME is it?
Modern sudo (with default env_reset) sets HOME to the target user's home, so sudo somecommand runs with root's HOME. Older configurations and sudo -E preserve the calling user's HOME instead — and that mismatch created a generation of broken setups. The canonical casualty: sudo npm install -g writing root-owned files into your ~/.npm cache, after which plain npm install fails with EACCES until you chown -R the directory back. npm's own docs dedicate a page to cleaning this up. When you genuinely need root with root's environment, sudo -H (force target HOME) or sudo -i (full login shell) make the intent explicit.
Containers, CI, and the HOME=/ failure mode
Interactive logins get HOME from the passwd database; containers and CI jobs often skip that step. A container running as a UID with no passwd entry — standard practice on OpenShift, which assigns random UIDs — typically ends up with HOME=/ or unset. The symptoms look unrelated to HOME: pip can't write its cache, npm fails creating /.npm, git complains it can't find ~/.gitconfig, ssh can't locate ~/.ssh/known_hosts. The fixes are mechanical:
# Dockerfile: create the user WITH a home directory
RUN useradd --create-home --uid 10001 appuser
USER appuser
ENV HOME=/home/appuser
# or for arbitrary-UID platforms, point HOME somewhere writable
ENV HOME=/tmpThe same applies to cron and systemd services: don't assume a login environment, set HOME explicitly when a tool needs it. The Docker environment variables guide covers where ENV declarations belong in the image layering.
Windows: HOME usually doesn't exist
Windows' native equivalent is USERPROFILE (C:\Users\you), plus the HOMEDRIVE/HOMEPATH pair. Plain HOME is unset on a stock system — but Unix-heritage tools expect it, so environments fake it: Git for Windows sets HOME for its bash and the tools it ships, Cygwin and MSYS2 set their own, and cross-platform runtimes paper over the difference in code (Go's os.UserHomeDir() returns USERPROFILE on Windows; Python's pathlib.Path.home() checks USERPROFILE too). The practical rule for script authors: never read HOME directly in cross-platform code — use your language's home-directory API. And if a Windows tool behaves differently inside Git Bash than in PowerShell, a HOME mismatch between the two environments is a strong first suspect.
When overriding HOME is the right tool
Deliberately faking HOME is a legitimate isolation technique: pointing a single command at a sandbox directory gives you a throwaway profile without touching your real dotfiles — HOME=/tmp/clean some-tool is the quickest way to prove "is it my config or the tool?". Test harnesses do the same to keep tests hermetic. The boundary to respect: HOME is process-scoped state, so set it per invocation, never globally — a session-wide HOME override quietly relocates every config file of every program you start afterward. For ground rules on scoping variables like this, see the environment variable best practices guide.
References
Frequently Asked Questions
Why is HOME wrong or empty in my cron job or container?
cron and minimal container users often run without a proper login, so HOME is unset or set to /. Tools that read ~/.config, ~/.aws, or ~/.ssh then fail or write to the wrong place. Set HOME explicitly in the crontab/Dockerfile, or create the user with a real home directory.
Stay up to date
Get notified about new guides, tools, and cheatsheets.