DockerSpawner / SystemUserSpawner - manually set the user's home directory?

Hi community,

JupyterHub’s DockerSwarmer / SystemUserSpawner assumes that the user’s home directory is /home/$NB_USER.

The Linux host I’m running JupyterHub on unfortunately doesn’t follow this convention. Usernames are <user>@<domain.com> and home directories are /home/<user>. For example, a username might be foo@bar.com and their home directory is /home/foo. I have no way of changing this behavior. In case it matters, I’m using the AzureAdOAuthenticator authenticator.

Is there an easy, straightforward way to manually configure the home directory or workaround this issue?

I feel confident I can make this change by heavily modifying start scripts and such, but I’m hoping to avoid that if possible. I’ve also considered symlinking /home/foo@bar.com to /home/foo but that feels very hacky too.

Thanks and best wishes!

There is a normalize_username method on Authenticator class of JupyterHub. You can use it to change the username from foo@bar.com to foo in the JupyterHub context. A sample code will be

class MyAzureAdOAuthenticator(AzureAdOAuthenticator):

    def normalize_username(self, username):
        return username.split('@')[0]

c.JupyterHub.authenticator_class = 'MyAzureAdOAuthenticator'

Now the usernames in the JupuyterHub will be without domains in the email ids and it should work out of the box in creating home dirs.

Thanks mahendrapaipuri! Will this not mess with the way SystemUserSpawner works, though, because the username differs between the Linux host and the container? I’ll give it a try nonetheless.

Ahh! Sorry! I misread your question. I thought your authenticator is passing the usernames as email ids and linux machine has plain usernames without email domains. So, the solution I proposed is not relevant to your issue. Sorry about that!

Maybe you can override the host_homedir in SystemUserSpawner to get correct home dirs for your machine?

No worries! I’ve overridden both host_homedir and homedir, which solved part of the problem but not all of the problem. With that change, the user’s $HOME env variable is still incorrect as is their entry in /etc/passwd. Looking more closely at the code, I don’t see a way to modify the home directory without changing start.sh as well. I’ll start experimenting with that. Thanks for your help!

Okay I have a solution that appears to be working.

I subclassed SystemUserSpawner like so:

def get_username_no_domain(username):
    return username.split('@')[0].lower()

class CustomSystemUserSpawner(SystemUserSpawner):
    def _get_home_dir(self):
        return '/home/' + get_username_no_domain(self.user.name)

    @property
    def host_homedir(self):
        return self._get_home_dir()

    @property
    def homedir(self):
        return self._get_home_dir()

    def get_env(self):
        env = super().get_env()
        env["HOME"] = self.homedir
        return env

Then I needed to heavily modify the start.sh script in the Docker container that runs individual servers. I more-or-less replaced every occurrence of /home/${USER} with ${HOME}.

I’ll report back if I notice any issues with this approach.

Make sure your users are only coming from one domain, or you will have a huge security issue!