Skip to content

Instantly share code, notes, and snippets.

@kfox
Created December 2, 2021 02:26
Show Gist options
  • Save kfox/5d4b635de65bc9c177d04e1ca386bdc3 to your computer and use it in GitHub Desktop.
Save kfox/5d4b635de65bc9c177d04e1ca386bdc3 to your computer and use it in GitHub Desktop.
Keeping two or more SCM accounts separate using asdf and direnv

Keeping SCM accounts separate using asdf and direnv

These instructions will enable you to use different SSH keys for different accounts across different Source Code Management (SCM) providers like GitHub, Gitlab, and others, including internal on-prem versions of those providers. You can also use this approach to switch between multiple accounts for a single SCM provider, e.g. a personal Github account and a work Github account.

Installation and Setup

  1. Install asdf by following the Getting Started instructions. asdf is the tool used to manage any number of versions of various programming language runtimes or environments. You can use asdf and the appropriate asdf plugins to replace separate tools like nvm, pyenv, rvm, etc.

  2. Install the direnv plugin for asdf per these instructions. Direnv is the bit that "automagially" sets environment variables and activates virtual environments when changing directories.

  3. (Optional) If you want to use "legacy" tool version files like .python-version instead of (or in addition to) the default .tool-versions files that asdf uses, create an ~/.asdfrc file with these contents:

    legacy_version_file = yes
  4. Create and add unique SSH keys for each SCM account, naming the keys something like ~/.ssh/<username>-<use-case>, e.g. ~/.ssh/kfox-personal or ~/.ssh/kellyf-work.

  5. (Optional) If you want to use an SSH agent to manage your SSH keys, add the following to your ~/.ssh/config:

    Host *
      AddKeysToAgent yes
      UseKeychain yes
  6. Under the root directory of your coding workspace, create subdirectories for each separate SCM account:

    # assumes the root of your code "workspace" is located at ~/your-workspace-root
    mkdir -p ~/your-workspace-root/{<use-case-1>,<use-case-2>,[etc.]}

    For example:

    mkdir -p ~/your-workspace-root/{personal,work}

    If you run the above command, your directory structure should look like this:

    ~/your-workspace-root/personal
    ~/your-workspace-root/work
  7. In each subdirectory of your workspace root, create an .envrc file similar to the one below, substituting your email address and the appropriate SSH key:

    # ~/your-workspace-root/personal/.envrc
    export EMAIL='kfox-personal@example.com'
    export GIT_AUTHOR_EMAIL='kfox-personal@example.com'
    export GIT_COMMITTER_EMAIL='kfox-personal@example.com'
    export GIT_SSH_COMMAND='ssh -i ~/.ssh/kfox-personal -o IdentitiesOnly=yes'
    
    use asdf

    Then run this command to explicitly allow it:

    asdf exec direnv allow ~/your-workspace-root/personal/.envrc

    Repeat the above for each top-level workspace subdirectory, using the email address and SSH key pertaining to the repositories you'll have in those subdirectories.

Usage

Change to a subdirectory of your workspace root and clone or check out a repo that should be exclusive to the identity represented by that subdirectory, e.g. a personal-only repo or a work-specific repo.

Once a copy of the repo exists locally, you can then add an additional .envrc file in that repo to automatically manage other tedious details, like environment variables for client tokens or using virtual environments for specific versions of tools like Python, Node, or Ruby.

Each tool may have custom configuration available through the use of asdf plugins. For more details, read the Getting Started instructions for asdf.

For example, to add a virtual environment for a specific version of Python, assuming the repository root has a .python-version or a .tool-versions file:

asdf plugin-add python
echo pipenv > ~/.default-python-packages
asdf install

Then, to automatically enable it when you're in the repository, first create an .envrc in that repo like this:

source_up

use asdf python

And then allow that .envrc to be used:

asdf exec direnv allow

Now each time you change to that that repo's directory (or a subdirectory), the appropriate Python virtual environment will be automatically loaded for you.

.env files

To have your .envrc automatically load environment variables from a .env file in a given directory, just insert a line with dotenv before the use asdf line. Using the above .envrc as an example:

source_up

dotenv
use asdf python
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment