Configure Local Environment Using Dotfiles

Zachi Nachshon
Wix Engineering
Published in
7 min readFeb 2, 2021

--

Logo by Joel Glovier.

Automate your local dev configuration in style on a personal, work or any other machine using a dedicated CLI utility.

TL;DR

Using a dotfiles repository has never been so easy. Interact with any dotfiles repository using a well defined CLI utility rather than executing random scripts.

Control the following items from a Git backed repository:

  • .dotfiles (aliases, exports, functions, shell RC files and others…)
  • Settings and configurations (.gitconfig, .vimrc and others…)
  • Homebrew (packages, casks, services, drivers)
  • macOS/Linux settings and preferences

LONG

· Incentive
· Solution
· What’s included?
· Homebrew
· dotfiles
Session Folder
Custom Folder
Home Folder
Transient Folder
Shell Folder
· macOS/Linux Settings Override
· Demo
· Summary

What is a .dotfile? It is a standard text file usually located within the $HOME folder. It contains a dot prefix in its name and is a hidden file which you can list with ls -a on a *nix system.

What is a Homebrew package / cask? Homebrew is a package manager for macOS, it allows you to install CLI utilities (packages) & GUI applications (casks).

Why override macOS settings? It is relevant if you have custom macOS settings. These are usually the settings that you change from the macOS GUI (Graphical User Interface) or from the terminal. You should back these custom settings so you’ll be able to restore them on every new/formatted machine.

Incentive

We have all been there, being lost in the sea of information on our constant learning experience on a daily basis. When we identify a command / script / keybinding that it is useful to us, we’ll add it to a note taking application hoping to remember where it is stored for the next time.

The same goes for local applications and CLI utilities. When receiving a new machine or going through an OS re-install, we start a manual installation process of all the applications and CLI utilities we are used to, hopefully not to miss a few.

And what about run command files (*rc) such as zshrc and bashrc for example. They usually contain custom content such as terminal colors, plugins etc.. which you’ll want to restore so you’ll feel right at home within your comfortable shell.

It’s not a simple task trying to keep our magic scripts that are scattered all over the place, either if its changing a system setting we’ve got used to or the repetitive command we’re constantly searching for in Google since we cannot find the time to add a snippet for it since we cannot seem to find the appropriate note-taking-application-to-rule-them-all.

Solution

Automate your local development environment installations/updates with just a few terminal commands. Manage everything under a Git backed repository so you’ll keep your setting in a centralized location, detached from any machine and enjoy all the benefits a version control has to offer.

How does keeping dotfiles under a Git repo helpful?

Even though the dotfiles are located under the folder you have cloned the Git repository into, by using symlinks (symbolic link / soft link) we’re able to link them to $HOME or any other folder and every change within the repository is reflected on every new terminal shell session since these files get sourced with their latest content.

Tip: Additionally, you can call dotfiles reload on the existing session without the need to create a new session.

How do we start?

There are a lot of dotfiles repositories publicly available in GitHub. People share their own managed dotfiles, either if it’s a single script you’ll have to add to the .bash_profile or other more complex alternatives that require a different setup.

In this blog post I’ll share an example dotfiles solution similar to the one I’m using which is managed by a dotfiles-cli utility that allows its users some ease of mind when it comes to local environment setup.

Please feel free to fork my dotfiles GitHub repository and add your own content on top of it !

In case you wish to check the repository out before forking, you are welcome to clone and change it to suite your needs:

$ git clone https://github.com/ZachiNachshon/dotfiles-example.git ~/<my-codebase-folder>

Why using a dotfiles CLI utility?

  1. Simplify the complex dotfiles repository wiring by separating the files from the management layer
  2. Use a dedicated CLI utility to control all aspects of the dotfiles repository with ease
  3. Having a coherent dotfiles structure that is easy to get familiar with
  4. Allow a generic CLI to control multiple dotfiles repositories (private and public)
  5. Avoid from running arbitrary scripts

How to install the dotfiles CLI?

Install dotfiles-cli via Homebrew, pre-built release or from sources. Please head over to the download section for further installation information.

What’s included?

A well organized folder layout containing categorized scripts with minimum overhead to glue them all together using the dotfiles-cli utility.

An example of an expected repository structure (read here for more info):

.
├── ...
├── brew
│ ├── casks.txt
│ ├── drivers.txt
│ ├── packages.txt
│ ├── services.txt
│ └── taps.txt

├── dotfiles
│ ├── custom
│ │ ├── .my-company
│ │ └── ...
│ ├── home
│ │ ├── .gitconfig
│ │ ├── .vimrc
│ │ └── ...
│ ├── session
│ │ ├── .aliases
│ │ └── ...
│ ├── shell
│ │ ├── .zshrc
│ │ └── ...
│ └── transient
│ └── .secrets

├── os
│ ├── linux
│ │ ├── keyboard.sh
│ │ └── ...
│ └── mac
│ ├── finder.sh
│ └── ...

├── plugins
│ ├── zsh
│ │ ├── oh_my_zsh.sh
│ │ └── ...
│ └── bash
│ ├── dummy.sh
│ └── ...
└── ...

Tip: Run dotfiles structure to get a reminder on the expected dotfiles repo structure.

Homebrew

Automate the installation process of favorite CLI utilities & GUI applications by using Homebrew macOS package manager. All you will have to do is to update simple text files with the package, cask, driver or service you wish to install. Installation and updates takes place whenever dotfiles brew <option> command is being called.

To add a CLI utility (a.k.a Homebrew package):

  1. Search for a desired package in here
  2. Add the package name to the packages.txt file
  3. Run dotfiles brew packages to install/update

To add a GUI application (a.k.a Homebrew cask):

  1. Search for a desired cask in here
  2. Add the cask name to the casks.txt file
  3. Run dotfiles brew casks to install/update

Tip: Similar flow for installing drivers and services via Homebrew.

dotfiles

Session Folder

A folder containing dotfiles which are relevant across all machines (work, personal etc..) that get sourced along on every new shell session or upon dotfiles reload command.

Example of such session files I use (you can add your own):

  1. .aliases - define shortcuts for commonly used *nix commands. Example:
# -=-= Custom =-=-
alias l="ls -lah"
alias dl="cd ~/Downloads"
alias gop="cd ${GOPATH}/src/github.com"

# -=-= ZSH =-=-
alias zshconfig="vim ~/.zshrc"

2. .functions - add new utility scrips to the functions collection so they'll be available right away. Example:

# Create a new directory and cd into it
mkd() {
mkdir -p "$@"
cd "$@" || exit
}

3. .paths - add new environment variables you wish to make available on new shell sessions. Example:

# -=-= Kubernetes =-=-
export KUBECONFIG=$HOME/.kube/k3s/config

# -=-= Path =-=-
export PATH=/usr/local/bin:/usr/bin:${JAVA_HOME}/bin:${GOROOT}/bin:${GOPATH}/bin:${PATH}

Custom Folder

A folder containing custom files to symlink, usually relevant to specific machines e.g. work related or personal etc..

I have added an example file to the repository (you can and should add your own):

  1. .my-company - a work related content that should get sourced on every new shell session. Example:
alias work-repos="cd codebase/my-company-repos" 

work() {
echo "I work at ACME Corporation."
}

Home Folder

A folder containing files that should get symlinked from the dotfiles GitHub repository to the $HOME folder for the same reasons we have described in here. A few examples are .gitignore_global, .gitconfig, .vimrc and others…

To add such file as described:

  1. Place it within <repo-root>/dotfiles/home/
  2. Run dotfiles sync home

Transient Folder

A folder containing transient files, meaning, files that shouldn’t get checked-in into source control or symlinked anywhere but should get sourced along on every new shell session.

You can use this to export ENV vars with sensitive information such as secrets to become available on newly opened shells. Files under transient folder are git ignored by default to prevent from committing to a source control.

Shell Folder

A folder containing run command files (*rc) such as zshrc and bashrc for example. They usually contain custom content such as terminal colours, plugins etc.. which you’ll probably want to backup and restore once needed.

To add such file as described:

  1. Place it within <repo-root>/dotfiles/shell/
  2. Run dotfiles sync shell

Note: Only the relevant shell *.rc file is being symlinked to $HOME folder, depends on the shell you are using. Currently supported shells are: bash, zsh.

macOS/Linux Settings Override

These are usually settings you have changed from the macOS/Linux GUI (Graphical User Interface) or from the terminal. In case you do have custom macOS/Linux settings, you’ll probably want to back them via GitHub repository to be able to restore on-demand.

Restoring these settings could take place either on new machine, after OS re-install or in case you have tweaked some knobs and forgot how to revert.

To override macOS/Linux settings and preferences:

  1. Find the terminal command corresponding to the setting you wish to backup

2. Add the command to a script files under:

  • macOS: <repo-root>/dotfiles/os/mac
  • Linux: <repo-root>/dotfiles/os/linux

3. Run dotfiles os <mac/linux> to override settings and preferences

Note: Check out macOS settings examples in here.

Demo

Click here for a running demo.

Summary

I hope this post helped to shed some light on how dotfiles could be useful for your local environment and you have found the way I’m automating dotfiles with Homebrew & macOS overrides insightful and helpful.

Please leave your comment, suggestion or any other input you think is relevant to this post.

Like this post?
You can find more by:

Checking out my blog: https://blog.zachinachshon.com
Following me on twitter: @zachinachshon

Thanks for reading! ❤️

--

--

Zachi Nachshon
Wix Engineering

Software Architect and DevOps Engineer. Passionate technologist, OSS enthusiast and Raspberry Pi addict — https://zachinachshon.com