Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
Simple set of bash scripts for uploading public keys to remote servers via GitHub usernames


A method for managing and giving team members access to remote servers without needing to pass around the master .pem key. Generates and sends authorized key files to a list of hosts based on a set of permissions.

Generates a new keys/*.txt file for each user defined in permissions.txt when one doesn't already exist. Gets the list by calling out to<user>.keys. After first fetching a set of keys, the list can be paired down if necessary before running


  1. Runs through each group defined in hosts/. ex:
  2. Reads the permissions.txt file to find out which users have permission to that host
  3. Generates a master authorized keys file for those users using their keys from keys/<user>.txt
  4. Uploads it to ~/.ssh/authorized_keys_sh for each host in that group. This avoids overwriting the server default authorized_keys file.


Specifies each user and which groups of hosts they should have permissions for. The format for each line is a GitHub username followed by a dash, then a comma-delimited list of groups they belong to. Each group should correspond to a file with a list of servers in hosts/. Example below:

ifightcrime - web,mygroup,othergroup


This directory houses a user specific set of keys for each user defined in permissions.txt.


Each file (group) contains a list of associated hosts that we want to push the keys to. A separate user@host is defined on each line.

Adding support for new hosts

Modify the host's /etc/ssh/sshd_config file to add support for our new authorized_keys_sh file. Change the AuthorizedKeysFile directive to match the following (and uncomment if commented):

AuthorizedKeysFile     %h/.ssh/authorized_keys %h/.ssh/authorized_keys_sh

Don't forget to reload ssh after you make the change.

/etc/init.d/ssh reload
function fetch_keys_from_github () {
for user in $(awk '{print $1}' permissions.txt); do
# only fetch if the file doesn't exist
if [[ ! -f $file ]] ; then
echo "Fetching ssh keys for ${user}..."
curl -sf${user}.keys > $file
readonly REMOTE_KEY_PATH="~/.ssh/authorized_keys_sh"
function users_for_group () {
# group must start after '-' with space/comma, and end with comma/newline
users=$(grep "\-.*\(\s\|,\)${1}\(,\|$\)" permissions.txt | awk '{print $1;}')
if [[ -z $users ]]; then
echo -e " \e[31mno permissions defined for this group\e[0m" 1>&2
echo $users
function generate_key_file () {
for user in $(users_for_group $1); do
if [[ ! -f $file ]]; then
# skip this user if they have no key file
echo -e " \e[31mkeys for user '${user}' are missing\e[0m" 1>&2
key_file="${key_file}\n# ${user}"
key_file="${key_file}\n$(cat $file)\n"
# -e and quotes to preserve line breaks
echo -e "$key_file"
function send_keys_to_hosts () {
for file in hosts/*.txt; do
group=$(basename ${file%.txt})
echo "Generating key file for '${group}'..."
key_file=$(mktemp /tmp/${group}_${host}.XXXXXX)
echo -e "$(generate_key_file $group)" > $key_file
if [[ -z $(cat $key_file) ]]; then
# generated file is empty, which means there are no keys to send
echo -e " \e[31mno keys generated for this group, skipping...\e[0m" 1>&2
for host in $(<${file}); do
echo " uploading to '${host}'"
scp -i ~/.ssh/upcounsel20130307.pem ${key_file} ${host}:${REMOTE_KEY_PATH} > /dev/null
rm $key_file
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.