Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
Automatic Git commit signing with GPG on OSX
# In order for gpg to find gpg-agent, gpg-agent must be running, and there must be an env
# variable pointing GPG to the gpg-agent socket. This little script, which must be sourced
# in your shell's init script (ie, .bash_profile, .zshrc, whatever), will either start
# gpg-agent or set up the GPG_AGENT_INFO variable if it's already running.
# Add the following to your shell init to set up gpg-agent automatically for every shell
if [ -f ~/.gnupg/.gpg-agent-info ] && [ -n "$(pgrep gpg-agent)" ]; then
source ~/.gnupg/.gpg-agent-info
export GPG_AGENT_INFO
else
eval $(gpg-agent --daemon --write-env-file ~/.gnupg/.gpg-agent-info)
fi
# Enables GPG to find gpg-agent
use-standard-socket
# Connects gpg-agent to the OSX keychain via the brew-installed
# pinentry program from GPGtools. This is the OSX 'magic sauce',
# allowing the gpg key's passphrase to be stored in the login
# keychain, enabling automatic key signing.
pinentry-program /usr/local/bin/pinentry-mac
# Uncomment within config (or add this line)
use-agent
# This silences the "you need a passphrase" message once the passphrase handling is all set.
# Use at your own discretion - may prevent the successful interactive use of some operations.
# It is working fine for my use cases though.
batch
# A quick outline of what must be done to get everything working.
# 1) Install the dependencies.
brew install gnupg gpg-agent pinentry-mac
# 2) Configure git to automatically gpgsign commits. This consists of
# pointing git to your signing key ID, and then enabling commit
# automatic signing.
git config --global user.signingkey <YOUR-SIGNING-KEY-PUB-ID>
git config --global commit.gpgsign true
# 3) Configure the GPG components (see above for relevant examples):
# ~/.gnupg/gpg.conf
# ~/.gnupg/gpg-agent.conf
# 4) Start the daemon and configure your shell (see above for example in .profile).
# ~/.bash_profile | ~/.zshrc
# Don't forget to upload your public key to Github!
# https://github.com/blog/2144-gpg-signature-verification
# Note: There needs to be a three-way match on your email for Github to show
# the commit as 'verified': The commit email, github email, & the email associated with the public key
# Learn about creating a GPG key and the knowledge behind these commands here:
# https://git-scm.com/book/en/v2/Git-Tools-Signing-Your-Work
@bmhatfield

This comment has been minimized.

Show comment Hide comment
@bmhatfield

bmhatfield Apr 6, 2016

The high level "connection diagram" for each part:

git -> gpg -> shell/env variable -> gpg-agent -> pinentry -> keychain
Owner

bmhatfield commented Apr 6, 2016

The high level "connection diagram" for each part:

git -> gpg -> shell/env variable -> gpg-agent -> pinentry -> keychain
@justindowning

This comment has been minimized.

Show comment Hide comment
@justindowning

justindowning Apr 6, 2016

Thanks for posting this! Two small suggestions/changes:

  1. I use Boxen, so Homebrew is installed in a different location. For ~/.gnupg/gpg-agent.conf I was able to use pinentry-program $HOMEBREW_ROOT/bin/pinentry-mac making the config more portable.
  2. I had to amend the gpg-agent command on startup: eval $(gpg-agent --daemon --options ~/.gnupg/gpg-agent.conf --write-env-file ~/.gnupg/.gpg-agent-info)

Thanks for posting this! Two small suggestions/changes:

  1. I use Boxen, so Homebrew is installed in a different location. For ~/.gnupg/gpg-agent.conf I was able to use pinentry-program $HOMEBREW_ROOT/bin/pinentry-mac making the config more portable.
  2. I had to amend the gpg-agent command on startup: eval $(gpg-agent --daemon --options ~/.gnupg/gpg-agent.conf --write-env-file ~/.gnupg/.gpg-agent-info)
@bcomnes

This comment has been minimized.

Show comment Hide comment
@bcomnes

bcomnes Apr 6, 2016

Why do you use gpg instead of gpg2 or gnupg21? It comes with gpg-agent, pinentry as deps.

EDIT: My bad, pinentry-mac is does not come with the pinentry package.

bcomnes commented Apr 6, 2016

Why do you use gpg instead of gpg2 or gnupg21? It comes with gpg-agent, pinentry as deps.

EDIT: My bad, pinentry-mac is does not come with the pinentry package.

@bcomnes

This comment has been minimized.

Show comment Hide comment
@bcomnes

bcomnes Apr 6, 2016

I came up with a slightly different recipe, using the latest version of gpg (2.1) and slightly less bash glue around the agent. https://gist.github.com/bcomnes/647477a3a143774069755d672cb395ca Thanks for the writeup! It was helpful :)

bcomnes commented Apr 6, 2016

I came up with a slightly different recipe, using the latest version of gpg (2.1) and slightly less bash glue around the agent. https://gist.github.com/bcomnes/647477a3a143774069755d672cb395ca Thanks for the writeup! It was helpful :)

@bmhatfield

This comment has been minimized.

Show comment Hide comment
@bmhatfield

bmhatfield Apr 7, 2016

@bcomnes - no particular reason on the gnupg choice. Just what I was used to. Thanks for sharing your workflow! Really the goal here is to highlight the pieces folks might need, so they can adapt them to their relevant approach.

Owner

bmhatfield commented Apr 7, 2016

@bcomnes - no particular reason on the gnupg choice. Just what I was used to. Thanks for sharing your workflow! Really the goal here is to highlight the pieces folks might need, so they can adapt them to their relevant approach.

@rpereira

This comment has been minimized.

Show comment Hide comment
@rpereira

rpereira Apr 8, 2016

@bmhatfield I've used this and it keeps me asking for the passphrase on every commit.

rpereira commented Apr 8, 2016

@bmhatfield I've used this and it keeps me asking for the passphrase on every commit.

@bmhatfield

This comment has been minimized.

Show comment Hide comment
@bmhatfield

bmhatfield Apr 16, 2016

@ruiafonsopereira - sorry to hear that. The goal of this was more to try to give you all the pieces you needed to make this work, since it took me a little while to find them - you may have to adapt to your local environment. I wrote comments in each file with the intent of highlighting areas where you might do that. Some ideas I had to help troubleshoot: the .profile might not be sourced, or perhaps you didn't check "save in keychain" in the pinentry program, or perhaps gpg is installed in a way that it's looking for a different path, etc. Good luck!

Owner

bmhatfield commented Apr 16, 2016

@ruiafonsopereira - sorry to hear that. The goal of this was more to try to give you all the pieces you needed to make this work, since it took me a little while to find them - you may have to adapt to your local environment. I wrote comments in each file with the intent of highlighting areas where you might do that. Some ideas I had to help troubleshoot: the .profile might not be sourced, or perhaps you didn't check "save in keychain" in the pinentry program, or perhaps gpg is installed in a way that it's looking for a different path, etc. Good luck!

@davisonio

This comment has been minimized.

Show comment Hide comment
@davisonio

davisonio Jun 18, 2016

Thank you!

Thank you!

@danieleggert

This comment has been minimized.

Show comment Hide comment
@danieleggert

danieleggert Jul 14, 2016

You can do all of this without any of this glue: https://gist.github.com/danieleggert/b029d44d4a54b328c0bac65d46ba4c65

You can do all of this without any of this glue: https://gist.github.com/danieleggert/b029d44d4a54b328c0bac65d46ba4c65

@lenage

This comment has been minimized.

Show comment Hide comment
@lenage

lenage Aug 1, 2016

Thanks @danieleggert , it works like charm! 😄

lenage commented Aug 1, 2016

Thanks @danieleggert , it works like charm! 😄

@takutaku947

This comment has been minimized.

Show comment Hide comment
@takutaku947

takutaku947 Oct 8, 2016

I countered this error on your config:
"Inappropriate ioctl for device"
Solution:
Write "export GPG_TTY=$(tty)" in ~/.profile and restart.

I countered this error on your config:
"Inappropriate ioctl for device"
Solution:
Write "export GPG_TTY=$(tty)" in ~/.profile and restart.

@pustovalov

This comment has been minimized.

Show comment Hide comment
@pustovalov

pustovalov Oct 23, 2016

Thx

Thx

@PurpleBooth

This comment has been minimized.

Show comment Hide comment
@PurpleBooth

PurpleBooth Dec 6, 2016

Thanks! This is fantastic.

Thanks! This is fantastic.

@aforty

This comment has been minimized.

Show comment Hide comment
@aforty

aforty Dec 11, 2016

This is fantastic, thank you!

aforty commented Dec 11, 2016

This is fantastic, thank you!

@loustler

This comment has been minimized.

Show comment Hide comment
@loustler

loustler Jan 26, 2017

Thanks guys.

I spent so many time to find solution for solve my problem.

Your solution is very fantastic.

loustler commented Jan 26, 2017

Thanks guys.

I spent so many time to find solution for solve my problem.

Your solution is very fantastic.

@Necmttn

This comment has been minimized.

Show comment Hide comment
@Necmttn

Necmttn Mar 11, 2017

THANK YOU !

Necmttn commented Mar 11, 2017

THANK YOU !

@lumeng

This comment has been minimized.

Show comment Hide comment
@lumeng

lumeng Mar 27, 2017

I was wondering that given that the gpg installed by Homebrew on macOS has switched to gpg2 which has some potentially important differences from gpg1, any of the above configuration can be updated and/or simplified?

lumeng commented Mar 27, 2017

I was wondering that given that the gpg installed by Homebrew on macOS has switched to gpg2 which has some potentially important differences from gpg1, any of the above configuration can be updated and/or simplified?

@abrkn

This comment has been minimized.

Show comment Hide comment
@abrkn

abrkn Apr 26, 2017

Worked like a charm!

abrkn commented Apr 26, 2017

Worked like a charm!

@loustler

This comment has been minimized.

Show comment Hide comment
@loustler

loustler Apr 28, 2017

If you use gpg 2.1 or above, then cannot use --write-env-file.

See here

If you use gpg 2.1 or above, then cannot use --write-env-file.

See here

@swernerx

This comment has been minimized.

Show comment Hide comment
@swernerx

swernerx May 7, 2017

I think we don't even need to start gpg-agent anymore - at least not together with pinentry-mac ... works flawlessly without in my setup with gpg v2 (includes gpg-agent) + pinentry-mac (installed via homebrew).

swernerx commented May 7, 2017

I think we don't even need to start gpg-agent anymore - at least not together with pinentry-mac ... works flawlessly without in my setup with gpg v2 (includes gpg-agent) + pinentry-mac (installed via homebrew).

@jakeNiemiec

This comment has been minimized.

Show comment Hide comment
@jakeNiemiec

jakeNiemiec Jul 26, 2017

@swernerx perhaps you could elaborate?

@swernerx perhaps you could elaborate?

@ewanmellor

This comment has been minimized.

Show comment Hide comment
@ewanmellor

ewanmellor Aug 2, 2017

@jakeNiemiec Echoing the comment from @swernerx:

I have pinentry-mac 0.9.4 and gnupg / gpg-agent 2.1.22 from Homebrew, and I don't need to start gpg-agent manually; pinentry-mac does it for me the first time I try to sign something. This means that I do not need use-standard-socket in .gpg-agent.conf or the .profile changes above. Also, use-agent doesn't do anything any more (GPG Configuration Options).

All I needed was:

  • brew install gnupg gpg-agent pinentry-mac (same as above)
  • pinentry-program /usr/local/bin/pinentry-mac in ~/.gnupg/gpg-agent.conf
  • The git config commands above.

ewanmellor commented Aug 2, 2017

@jakeNiemiec Echoing the comment from @swernerx:

I have pinentry-mac 0.9.4 and gnupg / gpg-agent 2.1.22 from Homebrew, and I don't need to start gpg-agent manually; pinentry-mac does it for me the first time I try to sign something. This means that I do not need use-standard-socket in .gpg-agent.conf or the .profile changes above. Also, use-agent doesn't do anything any more (GPG Configuration Options).

All I needed was:

  • brew install gnupg gpg-agent pinentry-mac (same as above)
  • pinentry-program /usr/local/bin/pinentry-mac in ~/.gnupg/gpg-agent.conf
  • The git config commands above.
@jannik-mohemian

This comment has been minimized.

Show comment Hide comment
@jannik-mohemian

jannik-mohemian Nov 16, 2017

Amazing gist! ❤️

Quick tip for oh-my-zshell users:

Simply add gpg-agent to your plugins and skip the whole .profile part.

Amazing gist! ❤️

Quick tip for oh-my-zshell users:

Simply add gpg-agent to your plugins and skip the whole .profile part.

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