diff --git a/playbooks/roles/user/defaults/main.yml b/playbooks/roles/user/defaults/main.yml
index ba99bec..f8a9f61 100644
--- a/playbooks/roles/user/defaults/main.yml
+++ b/playbooks/roles/user/defaults/main.yml
@@ -35,3 +35,6 @@ user_rbash_links:
 # will take precedence over the paramter
 user_info: []
 
+user_debian_pkgs:
+  # Need this to get keys.
+  - curl
diff --git a/playbooks/roles/user/tasks/main.yml b/playbooks/roles/user/tasks/main.yml
index bb66738..7776ed3 100644
--- a/playbooks/roles/user/tasks/main.yml
+++ b/playbooks/roles/user/tasks/main.yml
@@ -45,7 +45,6 @@
 #       # run manage.py commands
 #       - name: automator
 #         type: restricted
-#         state: present
 #         # The sudoers file is optional.
 #         sudoers_template: '99-edxapp-manage-cmds.j2'
 #         authorized_keys:
@@ -57,7 +56,6 @@
 #       - name: frank
 #         github: true
 #         type: admin
-#         state: present
 #
 #       # This user is a normal login user without sudo, with
 #       # a couple keys passed in as parameters
@@ -71,69 +69,90 @@
 # which can be passed in as a parameter to the role.
 #
 
-- debug: 
-    var: user_info
+- debug: var=user_info
 
 - name: create the edxadmin group
-  group: 
-    name: edxadmin 
+  group: name=edxadmin state=present
+
+- name: Install role-independent useful system packages
+  # do this before log dir setup; rsyslog package guarantees syslog user present
+  apt:
+    pkg: "{{ item }}"
+    install_recommends: yes
     state: present
+    update_cache: yes
+  with_items: user_debian_pkgs
 
 # some AMIs (such as EMR master nodes) don't read the config files out of /etc/sudoers.d by default
 - name: ensure sudoers.d is read
-  lineinfile:
-    dest: /etc/sudoers 
-    state: present
-    regexp: '^#includedir /etc/sudoers.d' 
-    line: '#includedir /etc/sudoers.d'
-    validate: 'visudo -cf %s'
+  lineinfile: >
+    dest=/etc/sudoers state=present
+    regexp='^#includedir /etc/sudoers.d' line='#includedir /etc/sudoers.d'
+    validate='visudo -cf %s'
 
 # give full sudo admin access to the edxadmin group
 - name: grant full sudo access to the edxadmin group
-  copy: 
-    content: "%edxadmin ALL=(ALL) NOPASSWD:ALL"
-    dest: /etc/sudoers.d/edxadmin 
-    owner: root 
-    group: root
-    mode: 0440 
-    validate: 'visudo -cf %s'
+  copy: >
+    content="%edxadmin ALL=(ALL) NOPASSWD:ALL"
+    dest=/etc/sudoers.d/edxadmin owner=root group=root
+    mode=0440 validate='visudo -cf %s'
 
 - name: create the users
-  user:
-    name: "{{ item.name }}"
-    shell: /bin/bash
-    state: "{{ item.state | default('present') }}"
+  user: >
+    name={{ item.name }}
+    shell=/bin/bash
+    state={{ item.state | default('present') }}
+  with_items: user_info
+
+- name: create .ssh directory
+  file: >
+    path=/home/{{ item.name }}/.ssh state=directory mode=0750
+    owner={{ item.name }}
+  when: item.get('state', 'present') == 'present'
   with_items: user_info
 
 - name: assign admin role to admin users
-  user:
-    name: "{{ item.name }}"
-    groups: edxadmin
+  user: >
+    name={{ item.name }}
+    groups=edxadmin
   when: item.type is defined and item.type == 'admin' and item.get('state', 'present') == 'present'
   with_items: user_info
 
-- name: get github key(s) and update the authorized_keys file
-  authorized_key:
-    user: "{{ item.name }}"
-    key: "https://github.com/{{ item.name }}.keys"
+# authorized_keys2 used here so that personal
+# keys can be copied to authorized_keys
+# 2014/10/14 - using curl instead of get_url because
+# get_url was failing due to certificate verification errors
+
+- name: get github key[s]
+  shell: >
+    curl https://github.com/{{ item.name }}.keys
+  sudo_user: "{{ item.name }}"
   when: item.github is defined and item.get('state', 'present') == 'present'
   with_items: user_info
+  register: github_keys
+
+- name: update the authorized_keys file
+  template:
+    src="authorized_keys.j2"
+    dest="/home/{{ item.name }}/.ssh/authorized_keys"
+    owner="{{ item.name }}"
+    mode="600"
+  when: item.get('state', 'present') == 'present'
+  with_items: user_info
 
 - name: create bashrc file for normal users
-  template: 
-    src: default.bashrc.j2
-    dest: "/home/{{ item.name }}/.bashrc" 
-    mode: 0640
-    owner: "{{ item.name }}"
+  template: >
+    src=default.bashrc.j2
+    dest=/home/{{ item.name }}/.bashrc mode=0640
+    owner={{ item.name }}
   when: not (item.type is defined and item.type == 'restricted') and item.get('state', 'present') == 'present'
   with_items: user_info
 
 - name: create .profile for all users
-  template:
-    src: default.profile.j2
-    dest: "/home/{{ item.name }}/.profile" 
-    mode: 0640
-    owner: "{{ item.name }}"
+  template: >
+    src=default.profile.j2
+    dest=/home/{{ item.name }}/.profile mode=0640
+    owner={{ item.name }}
   when: item.get('state', 'present') == 'present'
   with_items: user_info
 
@@ -141,29 +160,25 @@
 # All tasks below this line are for restricted users
 
 - name: modify shell for restricted users
-  user:
-    name: "{{ item.name }}"
-    shell: /bin/rbash
+  user: >
+    name={{ item.name }}
+    shell=/bin/rbash
   when: item.type is defined and item.type == 'restricted' and item.get('state', 'present') == 'present'
   with_items: user_info
 
 - name: create bashrc file for restricted users
-  template:
-    src: restricted.bashrc.j2
-    dest: "/home/{{ item.name }}/.bashrc" 
-    mode: 0640
-    owner: "{{ item.name }}"
+  template: >
+    src=restricted.bashrc.j2
+    dest=/home/{{ item.name }}/.bashrc mode=0640
+    owner={{ item.name }}
   when: item.type is defined and item.type == 'restricted' and item.get('state', 'present') == 'present'
   with_items: user_info
 
 - name: create sudoers file from template
-  template:
-    dest: /etc/sudoers.d/99-restricted
-    src: restricted.sudoers.conf.j2 
-    owner: root
-    group: root 
-    mode: 0440 
-    validate: 'visudo -cf %s'
+  template: >
+    dest=/etc/sudoers.d/99-restricted
+    src=restricted.sudoers.conf.j2 owner="root"
+    group="root" mode=0440 validate='visudo -cf %s'
 
   # Prevent restricted user from updating their PATH and
   # environment by ensuring root ownership
@@ -174,12 +189,9 @@
   with_items: user_info
 
 - name: create ~/bin directory
-  file:
-    path: "/home/{{ item.name }}/bin" 
-    state: directory 
-    mode: 0750
-    owner: root 
-    group: "{{ item.name }}"
+  file: >
+    path=/home/{{ item.name }}/bin state=directory mode=0750
+    owner="root" group={{ item.name }}
   when: item.type is defined and item.type == 'restricted' and item.get('state', 'present') == 'present'
   with_items: user_info
 
diff --git a/playbooks/roles/user/templates/authorized_keys.j2 b/playbooks/roles/user/templates/authorized_keys.j2
new file mode 100644
index 0000000..e889881
--- /dev/null
+++ b/playbooks/roles/user/templates/authorized_keys.j2
@@ -0,0 +1,14 @@
+# Keys from github
+{% for github_key in github_keys.results -%}
+  {# None is lowercase in jinja... #}
+  {%- if github_key.changed -%}
+    {%- if github_key.item.name == item.name -%}
+      {{ github_key.stdout }}
+    {%- endif -%}
+  {%- endif -%}
+{% endfor %}
+
+{% if item.get('authorized_keys') %}
+# Explicitly specified keys
+{{ '\n'.join(item.authorized_keys) }}
+{% endif %}