docs: def github_setup(self):
          """Set up authentication keys and API tokens."""
          github_auth = self.authenticate()
          github_username = github_auth[0]
  
          expt_name = self.config.get('name', self.expt.name)
          expt_description = self.expt.config.get('description')
          if not expt_description:
              expt_description = input('Briefly describe the experiment: ')
              assert isinstance(expt_description, str)
          expt_private = self.config.get('private', False)
  
          # 1. Create the organisation if needed
          github_api_url = 'https://api.github.com'
          org_name = self.config.get('organization')
          if org_name:
              repo_target = org_name
  
              # Check if org exists
              org_query_url = os.path.join(github_api_url, 'orgs', org_name)
              org_req = requests.get(org_query_url)
  
              if org_req.status_code == 404:
                  # NOTE: Orgs cannot be created via the API
                  print('payu: github organization {org} does not exist.'
                        ''.format(org=org_name))
                  print('      You must first create this on the website.')
  
              elif org_req.status_code == 200:
                  # TODO: Confirm that the user can interact with the repo
                  pass
  
              else:
                  # TODO: Exit with grace
                  print('payu: abort!')
                  sys.exit(-1)
  
              repo_query_url = os.path.join(github_api_url, 'orgs', org_name,
                                            'repos')
              repo_api_url = os.path.join(github_api_url, 'repos', org_name,
                                          expt_name)
          else:
              repo_target = github_username
  
              # Create repo in user account
              repo_query_url = os.path.join(github_api_url, 'user', 'repos')
              repo_api_url = os.path.join(github_api_url, 'repos',
                                          github_username, expt_name)
  
          # 2. Create the remote repository
          user_repos = []
          page = 1
          while True:
              repo_params = {'page': page, 'per_page': 100}
              repo_query = requests.get(repo_query_url, auth=github_auth,
                                        params=repo_params)
              assert repo_query.status_code == 200
              if repo_query.json():
                  user_repos.extend(list(r['name'] for r in repo_query.json()))
                  page += 1
              else:
                  break
  
          if expt_name not in user_repos:
              repo_config = {
                  'name': expt_name,
                  'description': expt_description,
                  'private': expt_private,
                  'has_issues': True,
                  'has_downloads': True,
                  'has_wiki': False
              }
  
              repo_gen = requests.post(repo_query_url, json.dumps(repo_config),
                                       auth=github_auth)
  
              assert repo_gen.status_code == 201
  
          # 3. Check if remote is set
          git_remote_out = subprocess.check_output(shlex.split('git remote -v'),
                                                   cwd=self.expt.control_path)
  
          git_remotes = dict([(r.split()[0], r.split()[1])
                              for r in git_remote_out.split('\n') if r])
  
          remote_name = self.config.get('remote', 'payu')
          remote_url = os.path.join('ssh://git@github.com', repo_target,
                                    self.expt.name + '.git')
  
          if remote_name not in git_remotes:
              cmd = ('git remote add {name} {url}'
                     ''.format(name=remote_name, url=remote_url))
              subprocess.check_call(shlex.split(cmd), cwd=self.expt.control_path)
          elif git_remotes[remote_name] != remote_url:
              print('payu: error: Existing remote URL does not match '
                    'the proposed URL.')
              print('payu: error: To delete the old remote, type '
                    '`git remote rm {name}`.'.format(name=remote_name))
              sys.exit(-1)
  
          # 4. Generate a payu-specific SSH key
          default_ssh_key = 'id_rsa_payu_' + expt_name
          ssh_key = self.config.get('sshid', default_ssh_key)
          ssh_dir = os.path.join(os.path.expanduser('~'), '.ssh', 'payu')
          mkdir_p(ssh_dir)
  
          ssh_keypath = os.path.join(ssh_dir, ssh_key)
          if not os.path.isfile(ssh_keypath):
              cmd = 'ssh-keygen -t rsa -f {key} -q -P ""'.format(key=ssh_key)
              subprocess.check_call(shlex.split(cmd), cwd=ssh_dir)
  
          # 5. Deploy key to repo
          with open(ssh_keypath + '.pub') as keyfile:
              pubkey = ' '.join(keyfile.read().split()[:-1])
  
          # TODO: Get this from github?
          repo_keys_url = os.path.join(repo_api_url, 'keys')
          keys_req = requests.get(repo_keys_url, auth=github_auth)
          assert keys_req.status_code == 200
  
          if not any(k['key'] == pubkey for k in keys_req.json()):
              add_key_param = {'title': 'payu', 'key': pubkey}
              add_key_req = requests.post(repo_keys_url, auth=github_auth,
                                          json=add_key_param)
              assert add_key_req.status_code == 201