Zachi Nachshon
Zachi Nachshon Software Architect and DevOps Engineer. Passionate technologist, OSS enthusiast and Raspberry Pi addict.

Configure Local Environment Using Dotfiles

Configure Local Environment Using Dotfiles

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

TL;DR

Control the following items from a Git backed repository:

  • .dotfiles
  • Homebrew packages / casks
  • macOS settings override

LONG


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 colours, 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 GitHub 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 GitHub repo helpful?

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

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 my own dotfiles solution that I use which I believe is well organized and easy to hop-on solution. It 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:

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

How to install?

The repository is managed via a Makefile with the following actions:

  1. dotfiles - create/remove dotfiles symlinks to/from this repo

  2. brew - (optional) install commonly used Homebrew packages and casks

  3. mac - (optional) macOS custom KeyBindings, Finder customizations, keyboard preferences and other overrides

  4. all - (optional) execute mac, dotfiles and brew in this order

  5. help - (optional) print available actions


dotfiles

What's included?

A well organized folder layout containing categorized scripts with minimum overhead to glue them all together. Symlinks are being managed within a dedicated hidden folder under $HOME/.dotfiles/<content-in-here> to prevent $HOME folder pollution.

Lets have a look at both the repository folder layout and the symlinks it creates:

  • $HOME/.dotfiles/ folder layout:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    
     .
     ├── ...
     ├── .dotfiles               
     │   └── custom  # symlinks to repository custom folder
     │       ├── .my-company  
     │       └── ...
     │   └── managed  # symlinks to repository managed folder
     │       ├── .aliases
     │       └── ...     
     │   └── .config  # symlink to management script
     └── ...
    
  • Repository layout:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    
     .
     ├── ...
     ├── dotfiles               
     │   └── custom  # file to symlink in specific machines e.g. work related / personal etc..
     │       ├── .my-company  
     │       └── ...
     │   └── home  # files that should get symlinked within $HOME folder directly
     │       ├── .gitignore_global       
     │       └── ...
     │   └── managed  # files to symlink across all machines
     │       ├── .aliases
     │       └── ...
     │   └── shell  # shell run commands to gets sourced on new shell session
     │       ├── .zshrc
     │       └── ...
     │   └── transient # content that gets sourced on new shell session but not symlinked
     │       └── .secrets       
     │   └── .dotfiles.sh  # dotfiles install/uninstall management script 
     └── ...
    


Managed Folder

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

These are the managed files I use (you can add your own):

  • .aliases - define shortcuts for commonly used *nix commands

    Example:

    1
    2
    3
    4
    5
    6
    7
    
     # -=-= Custom =-=-
     alias l="ls -lah" 
     alias dl="cd ~/Downloads"
     alias gop="cd ${GOPATH}/src/github.com"
       
     # -=-= ZSH =-=-
     alias zshconfig="vim ~/.zshrc"
    
  • .functions - add new utility scrips to the functions collection so they’ll be available right away

    Example:

    1
    2
    3
    4
    5
    
     # Create a new directory and cd into it
     mkd() {
       mkdir -p "$@"
       cd "$@" || exit
     }
    
  • .paths - add new environment variables you wish to make available on new shell sessions

    Example:

    1
    2
    3
    4
    5
    
     # -=-= 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):

  • .my-company - a work related content that should get sourced on every new shell session

    Example:

    1
    2
    3
    4
    5
    
     alias work-repos="cd codebase/my-company-repos" 
       
     work() {
        echo "I work at ACME Corporation."
     }
    


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.


Home Folder

A folder containing files that should be placed (or symlinked) within the $HOME folder directly and you wish to back them using the dotfiles GitHub repository for the same reasons we have described above. An example of such file is .gitignore_global.

To add such file as described:

  1. Place it within <repo-root>/dotfiles/home/
  2. Run the make dotfiles and choose install


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 the make dotfiles and choose install


Homebrew packages / casks

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 or cask you wish to install. Installation and updates takes place whenever make brew action 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 make brew 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 make brew to install/update


macOS settings override

These are usually settings you have changed from the macOS GUI (Graphical User Interface) or from the terminal. In case you do have custom macOS settings, you’ll probably want to back them via GitHub repository to be able to restore them 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 add/backup macOS settings:

  1. Find the terminal command corresponding to the setting you wish to backup
  2. Add it to the mac-os.sh file
  3. Run make mac to setup/restore settings


Demo

  • Install dotfiles (make dotfiles)

    dotfiles-install

  • Uninstall dotfiles (make dotfiles)

    dotfiles-uninstall

  • Install Homebrew packages/casks (make brew)

    brew-install

  • Override macOS with custom setting (make mac)

    mac-install


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 in the discussion below.

Thanks !


Credits: Logo created by Joel Glovier

comments powered by Disqus