In a *nix environment (Linux, MacOS, WSL), software without packages can sometimes install to global spaces by default. This is often undesirable, due to running unverified scripts as root, conflicts with other packages, and potentially breaking the software during an OS upgrade. Instead, these custom installs should be placed in your home directory. In my case, $HOME
is /home/fritzy
or /Users/fritzy
on MacOS.
But where in your $HOME? As the title implies, $HOME/.local
.
This directory is a GNOME convention that other software has adopted as well. Similar to /usr/local
, it is designated for custom or non-package installed software. The .
at the beginning of the directory name has the added benefit of hiding the directory, preventing cluttering an often-used space.
Setting up $HOME/.local
If it doesn't exist, go ahead and create it, along with a bin
directory as your user. No special permissions are needed.
mkdir -p $HOME/.local/bin
Then, make sure that $HOME/.local/bin
is in your $PATH, preferably with a higher priority than /usr/bin
.
For Linux Bash users do:
echo PATH=$HOME/local.bin:\$PATH >> $HOME/.bashrc
Custom Installers
Now we can install some software. I wanted to install Starship, a cross-shell prompt in my WSL2 Ubuntu. The only documented way to install this is to install by directly executing a download -- questionable from a security perspective.
curl -fsSL https://starship.rs/install.sh | bash
Instead, I downloaded and inspected the script. I discovered a few things. By default, it would install to /usr/bin
, a global space requiring root access. But there was good news; I found a command-line option to set the install directory.
curl https://starship.rs/install.sh --output install.sh # download
chmod +x install.sh # make it executable
./install.sh -b $HOME/.local/bin # the -b option is what discovered
rm ./install.sh # don't need this anymore
I then followed the instructions for setting up Starship for Bash.
echo 'eval "$(starship init bash)"' >> $HOME/.bashrc
Custom Compiled Installs (Node.js)
If you build custom software, you'll want to find the "prefix" option, and set it to $HOME/.local
. When following build instructions, you should ignore anything that tells you to use sudo
when installing; you won't need it with a prefix in your home directory, and doing so may cause problems later.
Let's clone Node.js, compile it, and install it to our .local
prefix.
Checking Out
cd ~/build # I use a build directory for custom compiling
git clone git@github.com:nodejs/node.git
cd node
Updating Tags
git fetch --all --tags # update fetched branches and tags
git tag # lists tags
As an aside, if you want to sort tags with semver logic, you can update your git config.
git config --global tag.sort version:refname
Checkout a Tag As a Branch
git checkout tags/v15.8.0 -b build-v15.8.0
Configure and Compile
Now we can compile it.
./configure --prefix=$HOME/.local
make -j12 # number of hardware thread on my cpu
make install # sets everything up in your prefix directory
The first make
line will take a bit, but hey, you look really busy and smart when you're compiling code.
Now when you run node -V
, it'll show your newly install Node.js version. You also now have the added benefit of being able to install 'global' npm packages without sudo. You'll notice that you now have include
lib
and share
directories in your $HOME/.local
, just like you would with a /usr/local
prefix.
You can get similar benefits of using nvm without having to compile.
Keep It Clean
Installing unpackaged software in your $HOME/.local
directory is more secure, more stable across OS upgrades, and prevents unnecessary root
usage going forward. It can take a bit of investigation with some software, but is worth having a cleaner install in the end. Ideally, the vast majority of your software simply uses OS supported packages, but now you have a plan for when it doesn't.
For you MacOS users, OS upgrades would regularly break Brew for me, but you can even install Brew into your home directory.
Please comment below, or send me your thoughts on Twitter @fritzy.
Top comments (0)