JupyterHub+nbgrader with LDAPAuthenticator and DockerSpawner setup

I am a system admin for a cluster. I am trying to setup a node with JupyterHub for a data science course.
I followed the JupyterHub the hard way instructions at jupyterhub-the-hard-way/installation-guide-hard.md at 35ddfb49ad81771551c6549696ccec960564d5e4 · jupyterhub/jupyterhub-the-hard-way · GitHub. I want to use nbgrader to manage the assignments and the grading.

The current problem is that I cannot configure nbgrader correctly to make it work. The nbgrader tab is not available either in JupyterLab (xxxx/lab) or classic notebook interface (xxxx/tree). It pops up after I install it manually once again in the launched lab. But it keeps saying c.Exchange.root is not configured for my_ldap_account.
I deleted the docker container yesterday and try to clean things up a bit. Now the formgrader tab in JupyterLab gives me a 404 error. Classic notebook page responds with a 500 internal server error.

Here is my jupyter_config.py

## General JupyterHub configuration
c.Spawner.mem_limit = '2G'
c.Authenticator.admin_users = {'my_ldap_account', 'instructor_ldap_account', 'admin_local_account'}
c.Authenticator.delete_invalid_users = True

## network interface configuration
c.JupyterHub.hub_ip = '0.0.0.0'
c.JupyterHub.hub_connect_ip = '172.17.0.1'

## ldapauthenticator configuration
c.JupyterHub.authenticator_class = 'ldapauthenticator.LDAPAuthenticator'
c.LDAPAuthenticator.server_address = '10.0.0.11'
c.LDAPAuthenticator.lookup_dn = False
c.LDAPAuthenticator.bind_dn_template = [
    "uid={username},ou=students,ou=people,dc=my,dc=edu",
    "uid={username},ou=faculties,ou=people,dc=my,dc=edu",
    ]

## DockerSpawner configuration
c.JupyterHub.spawner_class = 'dockerspawner.DockerSpawner'
c.DockerSpawner.allowed_images = {
    "jupyterhub/singleuser": "jupyterhub/singleuser",
    "datascience-cpu (Python+Julia+R)": "jupyter/datascience-notebook",
    }
#c.DockerSpawner.remove = True
#c.DockerSpawner.debug = True
import os
import shutil
notebook_dir = '/home/jovyan/work'
c.DockerSpawner.notebook_dir = notebook_dir
c.DockerSpawner.volumes = { '/home/{username}/jupyterhub': notebook_dir }

## NBGrader configuration
c.Authenticator.allowed_users = {'admin_local_account'}
c.Exchange.course_id = "courseid"
c.Exchange.root = "/home/nbgrader_exchange"
c.ConfigurableHTTPProxy.auth_token = ''
c.Spawner.environment = { 'JUPYTERHUB_API_TOKEN_CUSTOM': '0123456789abcdef0123456789abcdef' }
c.JupyterHub.load_groups = {
    'formgrade-courseid': ['my_ldap_account', 'instructor_ldap_account', 'admin_local_account'],
    'nbgrader-courseid': []
    }
c.JupyterHub.services = [
    {
      'name': 'courseid',
      'url': 'http://127.0.0.1:8101',
      'command': [
        '/opt/jupyterhub/bin/jupyterhub-singleuser',
        '--group=formgrade-courseid',
        '--debug',
        ],
      'user': 'admin_local_account',
      'cwd': '/home/admin_local_account',
      'api_token': '0123456789abcdef0123456789abcdef',
            # api_token can be removed (not tested)
        'environment': { 'JUPYTERHUB_API_TOKEN_CUSTOM':
                         '0123456789abcdef0123456789abcdef' }
      },
    {
      'name': 'nbgrader_token_service',
      'api_token': '0123456789abcdef0123456789abcdef'
      },
    {
      'name': 'idle-culler',
      'admin': True,
      'command': [sys.executable, '-m', 'jupyterhub_idle_culler', '--timeout=3600'],
      }
    ]
c.JupyterHub.load_roles = [
    {
      'name': 'formgrader-courseid-role',
      'groups': ['formgrade-courseid'],
      'scopes': ['access:services!service=courseid']
      },
    {
      'name': 'nbgrader_token_role',
        'scopes': ['read:users:groups', 'list:services',
                   'groups', 'admin:users'],
        'services': ['nbgrader_token_service']
    }
    ]

I also followed the article at JupyterHub and nbgrader in a small multi-class lab environment to ‘fix’ some nbgrader issue. Basically what I did in addition to the JupyterHub the hard way was disabling nbgrader for all users first and re-enable it to promoted admin and instructor account.

Here are something that I want to highlight that might be associated with the issue

  1. OS: Ubuntu 18.04.6, Python: 3.6, JupyterHub: 2.3.1, JupyterLab: 3.2.9, nbgrader: 0.8.0, docker: 20.10.17
  2. The home directories of all LDAP users are on a NFS mounted at /home. Only me has the root privilege permission on the node. Neither the instructor nor any students are in sudoers.
  3. The node is shared by all the students and the instructor for only one course.\
  4. I cannot login JupyterHub with the admin_local_account. Only LDAP accounts work for now.
  5. I do not have the password for instructor_ldap_account. I am testing it pretending myself (my_ldap_account) as the instructor.