keychain(1) | https://www.funtoo.org | keychain(1) |
NAME
keychain - Manager for ssh-agent, gpg-agent and private keys. Compatible with POSIX systems.
SYNOPSIS
keychain [ -hklQqV ] [ --clear --confhost --confallhosts --debug --extended --gpg2 --help --ignore-missing --list --noask --nocolor --nogui --noinherit --nolock --quick --quiet --ssh-allow-forwarded --ssh-rm --ssh-spawn-gpg --systemd --version ] [ --ssh-agent-socket path ] [ --dir dirname ] [ --host name ] [ --lockwait seconds ] [ --stop which ] [ --timeout minutes ] [ --wipe which ] [ keys... ]
INTRODUCTION
Keychain helps you to manage SSH and GPG keys in a convenient and secure manner. It acts as a frontend to "ssh-agent" and "ssh-add", but allows you to easily have one long running "ssh-agent" process per system, rather than the norm of one "ssh-agent" per login session.
This dramatically reduces the number of times you need to enter your passphrase. With "keychain", you only need to enter a passphrase once every time your local machine is rebooted. Keychain also makes it easy for remote cron jobs to securely "hook in" to a long running "ssh-agent" process, allowing your scripts to take advantage of key-based logins.
Keychain also supports GnuPG 2.1 and later, and will automatically start gpg-agent if any GPG keys are referenced on the command-line, and will ensure these credentials are cached in memory and available for use.
Keychain supports most UNIX-like operating systems. It supports integration with Bourne-compatible, csh-compatible and fish shells.
Additional documentation for Keychain can be found on "https://www.funtoo.org/Funtoo:Keychain" in the Keychain wiki page.
LIFECYCLE
Typically, you configure keychain to run when you first log in to a system. If you are using Bourne shell or bash, you will create a "~/.profile" or "~/.bash_profile" file and include the following line in it:
eval "$(keychain --eval id_rsa)"
Keychain will start ssh-agent if one isn't already running. Keychain then checks to make sure your private keys (in this example, "id_rsa") are loaded into the agent. If they are not, you are prompted for any passphrase necessary to decrypt them, so that they are cached in memory and available for use.
In addition to printing some user-friendly output to your terminal, keychain will also output important ssh-agent environment variables, which the "$( )" (you can also use "` `") captures, and the "eval" evaluates, setting these variables in your current shell.
These ssh-agent environment variables are also written to "~/.keychain/${HOSTNAME}-sh", so that subsequent logins and non-interactive shells such as cron jobs can source the file to access the running ssh-agent and make passwordless ssh connections using the cached private keys -- even when you are logged out. These files are collectively called pidfiles.
The key files specified on the command-line will be searched for in the "~/.ssh/" directory, and keychain will expect to find the private key file with the same name, as well as a ".pub" public key. Keychain will also see if any GPG keys are specified, and if so, prompt for any passphrases to cache these keys into "gpg-agent".
Typically, private SSH key files are specified by filename only,
without path, although it is possible to specify an absolute or relative
path to the private key file as well. Private key files can be symlinks to
the actual key as long as your system has the
"readlink" command available. More
advanced features are available for specifying keys as well -- see the
--extended and --confallhosts options for more information.
In addition, for GPG keys specified, similar steps will be taken to ensure that gpg-agent has the GPG key cached in memory and ready for use.
STREAMLINING AND SIMPLIFICATION
Keychain 2.9.0 has been streamlined, and with this maintenance several command-line options have been retired as they are not completely necessary. This simplifies the use of the tool by making it more intuitive to use. The files created in ~/.keychain have also been cleaned up. This section details all the important changes.
PIDFILE CHANGES
"Pidfile" is the nickname for files created in "~/.keychain" which can then be sourced by your scripts to access a running agent.
When using gpg-agent for GPG keys, keychain will no longer create a "~/.keychain/${HOSTNAME}-sh-gpg" pidfile. This file is no longer needed as the canonical GPG socket inside "~/.gnupg/" will be used to detect the running gpg-agent, which is the modern convention. GnuPG 2.1 and later have stopped using environment variables to find the agent, so we follow this upstream change.
IMPROVED DEBUGGING
A new --debug option is now available which will print additional information related to keychain's decisions regarding why and how an agent was found -- or not.
NEW (AND DEPRECATED) OPTIONS
This section provides an overview of new and deprecated command-line options. For full details on each option, see the respective option definition under "OPTIONS".
Keychain 2.9.2
The "--confhost" option has been deprecated. Instead of "--confhost hostname", use "--extended host:hostname". This extended format allows multiple keys of multiple types (SSH, GPG and SSH-from-hostname) to be specified on the command-line together. This is also fully compatible with "--confallhosts", and keychain now de-duplicates the list of keys to be loaded.
Keychain 2.9.1
The short-lived "--ssh-wipe" and "--gpg-wipe" options that appeared only in version 2.9.0 were replaced with "--wipe which" to work similarly to the "--stop" option, and allows you to specify "ssh", "gpg" or "all".
Keychain 2.9.0
The "--agents" option is now deprecated. Keychain will always ensure an ssh-agent or equivalent is running, or if "--ssh-spawn-gpg" is used, potentially a gpg-agent for the purpose of storing SSH keys if no running ssh-agent is available. To simply use a gpg-agent if one is already running, falling back to launching ssh-agent if no agent is available, use the "--ssh-allow-gpg" option.
Specifying a GPG key on the command-line will instruct keychain to enable gpg-agent functionality automatically. This eliminates an option that you need to specify ("--agents ssh,gpg") when invoking keychain, and for many will avoid spawning a GPG agent you may not be using.
Specifying the "--agents" option will now display a warning that it's deprecated, but keychain will not abort.
The "--inherit" option, which took one of four arguments, has been deprecated. Keychain's default behavior remains that of preferring to use an ssh-agent or equivalent referenced by its pidfile, falling back to finding an ssh-agent in its environment. By default, keychain will not use a gpg-agent socket for SSH keys unless at least "--ssh-allow-gpg" is specified. Similarly, the use of any forwarded SSH agent connection is disabled by default and can be enabled via "--ssh-allow-forwarded". Again, see the full documentation for each option in the "OPTIONS" section.
You can still influence keychain's behavior via the still-present "--noinherit" option which will prevent all detection of existing SSH agents via the environment.
The "--clear" option is still available, but isn't intended to be a "standalone" option, meaning that it is used to perform an initial clearing of cached keys before loading any specified keys when Keychain is run. To perform the sole action of wiping all cached keys, use the "--wipe" action. To remove an individual cached SSH private key or keys, use the "--ssh-rm" keyfile option.
The "--stop" option will now only stop any running ssh-agent processes, and still supports three possible options: "mine", "others" and "all". It no longer stops gpg-agent processes, which tend to get auto-respawned by GPG tools, so killing gpg-agent typically doesn't make a lot of sense.
BETTER GNUPG INTEGRATION
Keychain can now use an existing gpg-agent that has been started in your environment to store ssh keys, rather than spawning its own ssh-agent, by using the "--ssh-allow-gpg" option.
If you would like keychain to spawn gpg-agent instead of ssh-agent, and use it to store SSH keys, specify the "--ssh-spawn-gpg" option.
Without either option, keychain will not use an SSH_AUTH_SOCK that is provided by gpg-agent, and will spawn an official ssh-agent process.
In addition, behind the scenes, keychain now uses the gpg-connect-agent executable to restart the agent, get official PID and socket information, etc.
Please note that while gpg-agent provides full compatibility with ssh-agent, its password prompt is handled by pinentry and its store may encrypt your in-memory keys. For this reason, consider this new feature experimental, and use GitHub issues to report back any anomalies or suggested improvements for gpg-agent integration.
DISPLAY CHANGES
When keychain uses gpg-agent for either GnuPG or SSH support, then keychain will display the GnuPG socket file in its output, rather than the PID. Since the socket file has the "~/.gnupg" path in it, this communicates to you that gpg-agent, not ssh-agent, is active. If you see an integer PID, this means that ssh-agent is being used. =head2 STREAMLINED STARTUP
By default, keychain will always ensure that an ssh-agent should be started. It will only start a gpg-agent if a GPG key is referenced on the command-line.
Modern versions of gpg-agent also support the caching of SSH keys, allowing it to be a drop-in replacement for ssh-agent. With keychain 2.9.0, a new "--ssh-spawn-gpg" option has been added, which when specified will give keychain permission to spawn a gpg-agent in place of ssh-agent.
CODE OPTIMIZATION
With keychain 2.9.0, there has been significant code cleanup, reducing the size of the script from 1500 lines to about 1100 lines. In addition, the script is now fully compliant with ShellCheck https://shellcheck.net, which will be hugely helpful to ensure continued POSIX shell compatibility moving forward.
AGENT DETECTION AND STARTUP ALGORITHM
This section documents the official algorithm used for detecting and if necessary starting ssh-agent, to facilitate understanding as well as developer maintenance of the codebase.
DEFINITIONS
There are several important definition related to the algorithm:
- 1. The agent, "ssh-agent", which is a long-running daemon. This can also in some cases be "gpg-agent", depending on command-line options.
- 2. The inherited agent, which is the agent or forwarded agent that was not started by keychain, but is detected in the environment or by other means.
- 3. The adopted agent, which is an inherited agent whose information has been persisted by being written to the pidfiles (see below).
- 4. The environment variables "SSH_AUTH_SOCK", which points to the socket file used to communicate with ssh-agent, and optionally "SSH_AGENT_PID", which indicates its process ID if running locally (although gpg-agent does not define "SSH_AGENT_PID", even if running locally.)
- 5. The file "~/.keychain/${HOSTNAME}-sh" and related files, which are collectively referred to as "pidfiles". Pidfiles are used to persistently store "SSH_AUTH_SOCK" and "SSH_AGENT_PID" environment variables for use by other scripts, as well as by keychain itself, formatted so that they can be "sourced" by shells of various types.
- 6. Relevant command-line options affecting behavior, which include --noinherit, --ssh-allow-gpg, --ssh-spawn-gpg, and --ssh-allow-forwarded.
ALGORITHM OVERVIEW
When the keychain script is run, it will first attempt to find a running ssh-agent.
- Phase 1: pidfile: To do this, it will first look for an existing pidfile. If one exists, it will be inspected and used to find a running agent, in alignment with specified command-line options. If this process is successful, a "keychain-spawned" agent is found and this process is complete. Otherwise, we continue to the next step.
- Phase 2: environment: If keychain's pidfile did not yield a running agent, keychain looks at environment variables defined in the current environment. This step will be skipped if the --noinherit option is specified. If an agent is found that is in alignment with specified command-line options, it is considered "inherited" by keychain, and the process is complete. Otherwise, we continue to the next step.
- Phase 3: spawn agent: In the absence of finding a keychain-spawned or existing agent that can be adopted, keychain will spawn a new ssh-agent, or a new gpg-agent if --ssh-spawn-gpg is specified and gpg-agent is available.
- Final Phase: update pidfile: In addition, the pidfiles will be updated to reflect the keychain-spawned or "inherited" agent. An "inherited" agent, once written to the pidfile, is now considered to be "adopted".
- Pidfile update exception: If the --ssh-allow-forwarded option was specified, and a forwarded SSH socket was found -- which is identified as a valid SSH socket defined in a "SSH_AUTH_SOCK" variable, which has no associated or valid "SSH_AGENT_PID" also defined in the environment and is also determined to not be the socket of any running gpg-agent -- then this agent will simply be used, but not persisted in any pidfile. This is because this SSH-supplied socket will disappear when the underlying SSH connection terminates, and thus it cannot be relied on to be available persistently.
THE QUICK SHORT-CIRCUIT
When the --quick option is specified, a special algorithm will run prior to the main agent-detection algorithm listed above. A pidfile, if it exists, will be evaluated as per Phase 1 of the main algorithm. If a valid running agent is found, it will be queried for valid keys. If at least one valid key is loaded into the agent, the quick start is considered successful, and keychain will skip the regular agent startup algorithm, and will use this found agent.
SUMMARY AND RATIONALE
The keychain ssh-agent detection and startup algorithm is somewhat sophisticated for a reason. There is an intention behind its behavior.
The algorithm has been specifically designed to prefer an agent spawned by keychain, or previously adopted, if that agent is currently available. This is by design, because other system software could spawn ssh-agent and/or gpg-agent processes, and we want keychain to not coerced into using these new agents which may suddenly appear in the environment unexpectedly when new desktop sessions start and in other circumstances. If keychain is too "suggestible", it will lose track of the agent which currently holds valid keys, which can result in unncessary prompting for passphrases, and general confusion.
OPTIONS
- --absolute
- This option can be used with the --dir option, if you would like to specify a non-default directory to store pidfiles (defaults to "~/.keychain"). When this option is used, the script does not automatically append "/.keychain" to the path, allowing you to use any arbitrary directory name for the storing of pidfiles. Please note that Keychain 2.9.3 adds some extra security checks related to directory and file permissions -- you must have exclusive ownership of any directory that keychain uses to store pidfiles, or keychain will abort.
- --clear
- When specified, this option adds an initial step prior to adding any keys to the agents of wiping all existing cached keys/passphrases. This is intended to be used alongside keychain --eval to ensure that only the specified keys are loaded, and that keychain should assume that you are an intruder until proven otherwise and force all interactive logins to specify valid passphrases. This option increases security and still allows your cron jobs to use your ssh keys when you're logged out.
- --confallhosts
- In addition to any keys specified on the command-line, this option will tell keychain to scour "~/.ssh/config" for all private keys referenced in all "IdentityFile" lines, and load all keys for all hosts.
- --confirm
- Keys are subject to interactive confirmation by the SSH_ASKPASS program before being used for authentication. See the -c option for ssh-add(1).
- --debug
- Keychain 2.9.0 introduces the --debug option, which will output additional information related to how Keychain makes its agent-selection process. Specifically, it will output when an SSH_AUTH_SOCK is rejected because it is being supplied by gpg-agent -- and this is not allowed due to no --ssh-allow-gpg option, or when it is rejected because it appears to be from a forwarded SSH connection, and --ssh-allow-forwarded was not supplied.
- --dir dirname
- This option allows you to use another directory besides "$HOME/.keychain". for the storing of pidfiles. Please note that Keychain 2.9.3 adds some extra security checks related to directory and file permissions -- you must have exclusive ownership of any directory that keychain uses to store pidfiles, or the script will abort. Also see the --absolute option.
- --env filename
- After parsing options, keychain will load additional environment settings from "filename". By default, if "--env" is not given, then keychain will attempt to load from ~/.keychain/[hostname]-env or alternatively ~/.keychain/env. The purpose of this file is to override settings such as PATH, in case ssh is stored in a non-standard place.
- --eval
- Keychain will print lines to be evaluated in the shell on stdout. It respects the SHELL environment variable to determine if Bourne shell or C shell output is expected.
- --extended
- This enables extended command-line key processing with more features, and is a replacement for the old "--confhost" option. When specified, each key specified on the command-line must have a prefix to explictly. categorize it. SSH keys must have a prefix of "sshk:" immediately followed by the path or key name (the part after the "sshk:" is processed just like a SSH key is without the "--extended" option). GPG keys must be in the format "gpgk:" immediately followed by the 8 or 16-character fingerprint. If "host:<hostname>" is specified, then Keychain will extract the SSH configuration for the specified hostname, grab all identityfile options (private keys) specified, and these keys will be included in the set of keys to be loaded by keychain. This allows multiple keys of multiple types, including SSH-keys-by-host, to be specified together, which wasn't possible with "--confhost".
- --gpg2
- This option changes the default gpg calls to use gpg2 instead to support distributions such as Ubuntu which has both gpg and gpg2
- --help -h
- Show help that looks remarkably like this man-page. As of 2.6.10, help is sent to stdout so it can be easily piped to a pager.
- --host name
- Set alternate hostname for creation of pidfiles
- --ignore-missing
- Don't warn if some keys on the command-line can't be found. This is useful for situations where you have a shared .bash_profile, but your keys might not be available on every machine where keychain is run.
- -l --list
- List signatures of all active SSH keys, and exit, similar to "ssh-add -l".
- -L --list-fp
- List fingerprints of all active SSH keys, and exit, similar to "ssh-add -L".
- --lockwait seconds
- How long to wait for the lock to become available. Defaults to 5 seconds. Specify a value of zero or more. If the lock cannot be acquired within the specified number of seconds, then this keychain process will forcefully acquire the lock.
- --noask
- This option tells keychain do everything it normally does (ensure ssh-agent is running, set up the ~/.keychain/[hostname]-{c}sh files) except that it will not prompt you to add any of the keys you specified if they haven't yet been added to ssh-agent.
- --nocolor
- Disable color highlighting for non ANSI-compatible terms.
- --nogui
- Don't honor SSH_ASKPASS, if it is set. This will cause ssh-add to prompt on the terminal instead of using a graphical program.
- --noinherit
- Don't inherit any agent processes, overriding the default behavior of inheriting all non-forwarded ssh-agent and any existing gpg-agent processes. Also see "AGENT DETECTION AND STARTUP ALGORITHM".
- --nolock
- Don't attempt to use a lockfile while manipulating files, pids and keys.
- --query
- Keychain will print lines in KEY=value format representing the values which are set by the agents.
- --quick -Q
- If an ssh-agent process is running then use it. Don't verify the list of keys, other than making sure it's non-empty. This option avoids locking when possible so that multiple terminals can be opened simultaneously without waiting on each other. See the "THE QUICK SHORT-CIRCUIT" section for more information regarding how this fits into the overall startup algorithm.
- --quiet -q
- Only print messages in case of warning, error or required interactivity. As of version 2.6.10, this also suppresses "Identities added" messages for ssh-agent.
- --stop -k which
- Kill currently running ssh-agent processes and exit.
Note that previous versions of keychain (2.8.5 and earlier) allowed killing of gpg-agent as well. This functionality was removed as ssh-agent and gpg-agent have a bit different design philosophies and you almost always only have at most one gpg-agent running at a time. Use "killall gpg-agent" if you really want to kill gpg-agent. However, since this option also removes pidfiles, it will remove any gpg-agent processes adopted by keychain that were being used to store ssh keys.
The following values are valid for "which" which controls which ssh-agents to target:
- all
- Kill all ssh-agent processes and quit keychain immediately. Prior to keychain-2.5.0, this was the behavior of the bare "--stop" option.
- others
- Kill agent processes other than the ones keychain is providing. Prior to keychain-2.5.0, keychain would do this automatically. The new behavior requires that you specify it explicitly if you want it.
- mine
- Kill keychain's agent processes, leaving other agents alone.
- --ssh-agent-socket path
- Use this option to specify the path to the socket file that you would like ssh-agent to create and use as its official socket. By default, ssh-agent will create its own socket file, typically in /tmp.
- --ssh-allow-forwarded
- By default, keychain will not use a forwarded ssh-agent connection, which is a ssh-agent socket created by SSH that has no associated local process. To permit keychain to use a forwarded ssh-agent connection, specify this option. If a SSH-forwarded socket is used, it will not be persisted in the pidfiles, as it is not likely to be available outside of the currently-active SSH session.
- --ssh-allow-gpg
- Would you like to have keychain use an already-running gpg-agent to store
your SSH keys, rather than spawning a new ssh-agent? This option does just
that. When this option is specified, keychain will accept an SSH_AUTH_SOCK
environment variable in its environment, even if it was created by
gpg-agent. Modern versions of gpg-agent are also able to store SSH keys.
By default, keychain has a special check to avoid using a gpg-agent that
has set the SSH_AUTH_SOCK environment variable, and will instead spawn its
own ssh-agent. With this option enabled, this restriction is turned off.
Please note that this option does not actually instruct keychain to
spawn a gpg-agent for storing SSH keys if no agent is available --
if you want that, see the --ssh-spawn-gpg option, below.
ALSO NOTE: When a gpg-agent is adopted for ssh-agent duties in this way, the "~/.keychain/${HOSTNAME}-sh" pidfile will be updated to reference the gpg-agent socket, so it will be seamlessly used by future cron jobs needing an ssh-agent, as well as by future invocations of keychain, as long as the --ssh-allow-gpg or --ssh-spawn-gpg (which implies --ssh-allow-gpg) are specified.
- --ssh-spawn-gpg
- This is the option to use if you're really on-board with using gpg-agent as a replacement for ssh-agent. Not only will keychain use a running gpg-agent if found as per the --ssh-allow-gpg, but if it needs to spawn a new ssh-agent, it will go ahead and spawn a gpg-agent in its place, and use it instead. Also see notes for the --ssh-allow-gpg option, as this option also implies --ssh-allow-gpg.
- --ssh-rm -r keys
- Only perform the single action of removing the specified cached keys from the running ssh-agent, and then exit.
- --systemd
- Inject environment variables into the systemd --user session.
- --timeout minutes
- Allows a timeout to be set for identities added to ssh-agent. When this
option is used with a keychain invocation that starts ssh-agent itself,
then keychain uses the appropriate ssh-agent option to set the default
timeout for ssh-agent. The --timeout option also gets passed to ssh-add
invocations, so any keys added to a running ssh-agent will be individually
configured to have the timeout specified, overriding any ssh-agent
default.
Most users can simply use the timeout setting they desire and get the result they want -- with all identities having the specified timeout, whether added by keychain or not. More advanced users can use one invocation of keychain to set the default timeout, and optionally set different timeouts for keys added by using a subsequent invocation of keychain.
- --version -V
- Show version information.
- --wipe which
- Only perform the single action of wiping all agent's cached keys. Specify 'ssh', 'gpg' or 'all' for SSH keys, GPG keys and all agents respectively. Also see the "--ssh-rm" action and the "--clear" option.
EXAMPLES
This snippet should work in most shells to load two ssh keys and one gpg key:
eval `keychain --eval id_rsa id_dsa 0123ABCD`
For the fish shell, use the following format:
if status --is-interactive keychain --eval --quiet -Q id_rsa | source end
If you have trouble with that in csh:
setenv SHELL /bin/csh eval `keychain --eval id_rsa id_dsa 0123ABCD`
This is equivalent for Bourne shells (including bash and zsh) but doesn't use keychain's --eval feature:
keychain id_rsa id_dsa 0123ABCD [ -z "$HOSTNAME" ] && HOSTNAME=`uname -n` [ -f $HOME/.keychain/$HOSTNAME-sh ] && \ . $HOME/.keychain/$HOSTNAME-sh
This is equivalent for C shell (including tcsh):
keychain id_rsa id_dsa 0123ABCD host=`uname -n` if (-f $HOME/.keychain/$host-csh) then source $HOME/.keychain/$host-csh endif
Likewise, the following commands can be used in fish:
keychain id_rsa id_dsa 0123ABCD test -z "$hostname"; and set hostname (uname -n) if test -f "$HOME/.keychain/$hostname-fish" source $HOME/.keychain/$hostname-fish end
To load keychain variables from a script (for example from cron) and abort unless id_dsa is available:
# Load keychain variables and check for id_dsa [ -z "$HOSTNAME" ] && HOSTNAME=`uname -n` . $HOME/.keychain/$HOSTNAME-sh 2>/dev/null ssh-add -l 2>/dev/null | grep -q id_dsa || exit 1
SEE ALSO
NOTES
Keychain was created and is currently maintained by Daniel Robbins. If you need to report a bug or request an enhancement, please report it to the GitHub project page at https://github.com/funtoo/keychain. For more information about keychain, please visit https://www.funtoo.org/Funtoo:Keychain.
2025-05-17 | 2.9.5 |