# Starting single-user notebook with our custom ldap docker image

**URL:** <https://discourse.jupyter.org/t/starting-single-user-notebook-with-our-custom-ldap-docker-image/881>\
**Category:** JupyterHub\
**Tags:** how-to\
**Created:** [April 26, 2019, 7:39am UTC](https://discourse.jupyter.org/t/starting-single-user-notebook-with-our-custom-ldap-docker-image/881 "2019-04-26T07:39:06Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![maverick](https://yyz1.discourse-cdn.com/flex031/user_avatar/discourse.jupyter.org/maverick/32/449_2.png) [@maverick](https://discourse.jupyter.org/u/maverick)\
**Post date:** [April 26, 2019, 7:39am UTC](https://discourse.jupyter.org/t/starting-single-user-notebook-with-our-custom-ldap-docker-image/881/1 "2019-04-26T07:39:06Z")

</div>

Hi,

We are having some problems because our user homes are in a NFS storage and, for them to write there their work, we need to “impersonate” them. On regular machines we are using LDAP (with TLS, PAM and SSSD) to authenticate the users, and so is jupyter-hub.

We are using Kubernetes -\> z2jh and a Docker image based on the notebook single-user image with all the necessary files and packages to connect to LDAP.

The idea we originally had was using the variable ‘{username}’ and modify the “start.sh” script, so once we had the real $NB\_USER we could set up $NB\_UID, $NB\_GID and so on. We created a docker container where we could copy the necessary files (I know it would be better to binding them on the host) and we did, but we have to keep running SSSD in the background for the container to be able to connect to LDAP.

[jovyan@jupyter-rcruz ~]$ id rcruz  
uid=63200(rcruz) gid=50030(x) groups=50030(x),1405(x),1403(x)

Before having to add supervisord or something similar to run SSSD as a background process, we would like to know if there is a better/easier way to impersonate the user that logged into jupyter hub. For instance, using token id login from hub or something else?

We don’t discard adding to /etc/passwd the user with its username, UID and GID, but we don’t know if we can get that from the login in jupyterhub.

Thanks in advance!

---

<div class="post-metadata">

**Author:** ![manics](https://yyz1.discourse-cdn.com/flex031/user_avatar/discourse.jupyter.org/manics/32/85_2.png) [@manics](https://discourse.jupyter.org/u/manics)\
**Post date:** [April 26, 2019, 7:50am UTC](https://discourse.jupyter.org/t/starting-single-user-notebook-with-our-custom-ldap-docker-image/881/2 "2019-04-26T07:50:15Z")

</div>

Is the only requirement to write to NFS as the logged in LDAP user? Would it be sufficient to run Jupyter as that UID?

---

<div class="post-metadata">

**Author:** ![maverick](https://yyz1.discourse-cdn.com/flex031/user_avatar/discourse.jupyter.org/maverick/32/449_2.png) [@maverick](https://discourse.jupyter.org/u/maverick)\
**Post date:** [April 26, 2019, 7:54am UTC](https://discourse.jupyter.org/t/starting-single-user-notebook-with-our-custom-ldap-docker-image/881/3 "2019-04-26T07:54:18Z")

</div>

Yes, every single user should be able to write on that NFS with its own UID.

---

<div class="post-metadata">

**Author:** ![manics](https://yyz1.discourse-cdn.com/flex031/user_avatar/discourse.jupyter.org/manics/32/85_2.png) [@manics](https://discourse.jupyter.org/u/manics)\
**Post date:** [April 26, 2019, 9:57am UTC](https://discourse.jupyter.org/t/starting-single-user-notebook-with-our-custom-ldap-docker-image/881/4 "2019-04-26T09:57:39Z")

</div>

I’ve done this before. It requires [this change to the LDAPAuthenticator](https://github.com/jupyterhub/ldapauthenticator/pull/103).

You can then configure JupyterHub to extract the required LDAP attributes (username, UID), and pass them to the singleuser server by setting appropriate environment variables. If you start the singleuser server as root it will switch to that UID, which means it should be able to write to NFS as that user. I’ve written up some brief instructions:

> <https://gist.github.com/manics/c4bcf53a210d444db9e64db7673e8580>

---

<div class="post-metadata">

**Author:** ![maverick](https://yyz1.discourse-cdn.com/flex031/user_avatar/discourse.jupyter.org/maverick/32/449_2.png) [@maverick](https://discourse.jupyter.org/u/maverick)\
**Post date:** [April 26, 2019, 6:47pm UTC](https://discourse.jupyter.org/t/starting-single-user-notebook-with-our-custom-ldap-docker-image/881/5 "2019-04-26T18:47:44Z")

</div>

Wow!. This is exactly what we want.

I’ve problems in order to get group id, but I don’t worry about it right now.

 ![image](https://canada1.discourse-cdn.com/flex031/uploads/jupyter/original/1X/b44d7df72f5d7e9b16aaa5b5efadff73849eb27f.png)

Thanks a lot 🙂 !!

---

<div class="post-metadata">

**Author:** ![pazzumpazzutu](https://avatars.discourse-cdn.com/v4/letter/p/aeb1de/32.png) [@pazzumpazzutu](https://discourse.jupyter.org/u/pazzumpazzutu)\
**Post date:** [July 30, 2019, 2:36pm UTC](https://discourse.jupyter.org/t/starting-single-user-notebook-with-our-custom-ldap-docker-image/881/6 "2019-07-30T14:36:44Z")

</div>

Hello @manics,

thanks very much for the changes you made to LDAP Authenticator. They are exactly what I need in my setup to let users access their home folder mounted via NFS.  
I am having no luck with setting this up, so maybe you could have some hints.

I am running Jupyterhub 0.9.6 and deploying it with zero-to-jupyterhub-k8s.  
Instead of embedding the change in the config file I am installing your [fork](https://github.com/manics/ldapauthenticator/tree/ldap-user-info) of LDAP authenticator in the hub container environment. All good until this step.

In my jupyterhub config I embed the following to make sure the uid is propagated to the singleuser container:

```
class MyLDAPAuthenticator(LDAPAuthenticator):
    @gen.coroutine
    def pre_spawn_start(self, user, spawner):
        auth_state = yield user.get_auth_state()
        self.log.error('pre_spawn_start auth_state:%s' % auth_state)
        if not auth_state:
            return
        # setup environment
        spawner.environment['NB_UID'] = str(
            auth_state['uidNumber'][0])
        spawner.environment['NB_USER'] = auth_state['uid'][0]

```

and this to select the authentication method:

```
c.JupyterHub.authenticator_class = 'MyLDAPAuthenticator'
c.LDAPAuthenticator.server_address = get_config('auth.ldap.server.address')
c.LDAPAuthenticator.user_info_attributes = ['uid', 'uidNumber']
set_config_if_not_none(c.LDAPAuthenticator, 'server_port', 'auth.ldap.server.port')
set_config_if_not_none(c.LDAPAuthenticator, 'use_ssl', 'auth.ldap.server.ssl')
set_config_if_not_none(c.LDAPAuthenticator, 'allowed_groups', 'auth.ldap.allowed-groups')
c.LDAPAuthenticator.bind_dn_template = get_config('auth.ldap.dn.templates')
set_config_if_not_none(c.LDAPAuthenticator, 'lookup_dn', 'auth.ldap.dn.lookup')
set_config_if_not_none(c.LDAPAuthenticator, 'lookup_dn_search_filter', 'auth.ldap.dn.search.filter')
set_config_if_not_none(c.LDAPAuthenticator, 'lookup_dn_search_user', 'auth.ldap.dn.search.user')
set_config_if_not_none(c.LDAPAuthenticator, 'lookup_dn_search_password', 'auth.ldap.dn.search.password')
set_config_if_not_none(c.LDAPAuthenticator, 'lookup_dn_user_dn_attribute', 'auth.ldap.dn.user.dn-attribute')
set_config_if_not_none(c.LDAPAuthenticator, 'escape_userdn', 'auth.ldap.dn.user.escape')
set_config_if_not_none(c.LDAPAuthenticator, 'valid_username_regex', 'auth.ldap.dn.user.valid-regex')
set_config_if_not_none(c.LDAPAuthenticator, 'user_search_base', 'auth.ldap.dn.user.search-base')
set_config_if_not_none(c.LDAPAuthenticator, 'user_attribute', 'auth.ldap.dn.user.attribute')

```

However at hub startup I get the following error:

```
[C 2019-07-30 14:17:00.347 JupyterHub application:90] Bad config encountered during initialization:
[C 2019-07-30 14:17:00.347 JupyterHub application:91] The 'authenticator_class' trait of <jupyterhub.app.JupyterHub object at 0x3fffb082af98> instance must be a type, but 'MyLDAPAuthenticator' could not be imported

```

Any Idea why this is happening? I really can’t see why the **MyLDAPAuthenticator** cannot be found at hub instantiation time.

Any help or suggestion is highly appreciated.

Thanks in Advance,

Christian

---

<div class="post-metadata">

**Author:** ![manics](https://yyz1.discourse-cdn.com/flex031/user_avatar/discourse.jupyter.org/manics/32/85_2.png) [@manics](https://discourse.jupyter.org/u/manics)\
**Post date:** [July 30, 2019, 5:06pm UTC](https://discourse.jupyter.org/t/starting-single-user-notebook-with-our-custom-ldap-docker-image/881/7 "2019-07-30T17:06:22Z")

</div>

Try removing the quotes:

```auto
c.JupyterHub.authenticator_class = MyLDAPAuthenticator

```

---

<div class="post-metadata">

**Author:** ![pazzumpazzutu](https://avatars.discourse-cdn.com/v4/letter/p/aeb1de/32.png) [@pazzumpazzutu](https://discourse.jupyter.org/u/pazzumpazzutu)\
**Post date:** [July 31, 2019, 12:14pm UTC](https://discourse.jupyter.org/t/starting-single-user-notebook-with-our-custom-ldap-docker-image/881/8 "2019-07-31T12:14:15Z")

</div>

Hi @manics,

I solved by embedding the pre\_spawn\_start directly in the main LDAPAuthenticator class.  
It works perfectly now.

Thanks

---

<div class="post-metadata">

**Author:** ![Atul\_Yadav](https://yyz1.discourse-cdn.com/flex031/user_avatar/discourse.jupyter.org/atul_yadav/32/1535_2.png) [@Atul\_Yadav](https://discourse.jupyter.org/u/Atul_Yadav)\
**Post date:** [June 16, 2020, 8:26am UTC](https://discourse.jupyter.org/t/starting-single-user-notebook-with-our-custom-ldap-docker-image/881/9 "2020-06-16T08:26:25Z")

</div>

Hi,

Please share the dockerfile and config.yaml to replicate the same environment.  
We are also having the same requirement.

Thank You  
Atul

---

<div class="post-metadata">

**Author:** ![gdelris](https://yyz1.discourse-cdn.com/flex031/user_avatar/discourse.jupyter.org/gdelris/32/9457_2.png) [@gdelris](https://discourse.jupyter.org/u/gdelris)\
**Post date:** [March 22, 2023, 4:09pm UTC](https://discourse.jupyter.org/t/starting-single-user-notebook-with-our-custom-ldap-docker-image/881/10 "2023-03-22T16:09:41Z")

</div>

Hi @manics  
I have this same problem and I don’t know how to solve it, I’m new to this type of implementation.  
Why when I log in authenticating against ldap, the user is not created? On the other hand, why is “jovyan” set and not the ldap user id, and why does it look like this?  
 ![image](https://canada1.discourse-cdn.com/flex031/uploads/jupyter/original/2X/c/c42592ddc9453a270c6353f6036e14fcfcbb1113.png)  
Thank you for helping me, I need it to be as follows:  
gdelris@jupyter-gdelris

This is mi config.yaml, It works for authentication:  
hub:  
config:  
Authenticator:  
enable\_auth\_state: true  
JupyterHub:  
authenticator\_class: ldapauthenticator.LDAPAuthenticator  
LDAPAuthenticator:  
server\_address: 10.72.134.241  
server\_port: 389  
lookup\_dn: true  
auth\_state\_attributes: [uidNumber,gidNumber,uid]  
lookup\_dn\_search\_user:  
lookup\_dn\_search\_password:  
user\_search\_base: ou=Usuarios,dc=ambientesbc,dc=lab  
user\_attribute: sAMAccountName  
lookup\_dn\_user\_dn\_attribute: cn  
escape\_userdn: false  
create\_user\_home\_dir: True  
create\_user\_home\_dir\_cmd: mkhomedir\_helper

scheduling:  
userScheduler:  
enabled: false

singleuser:  
defaultUrl: “/lab”

THANKS A LOTTTTTTTTTTT
