Issues with Serving JupyterBook via JupyterHub Using a Custom Service - Persistent 404 Errors

Hi JupyterHub Community,

I’m currently working to deploy a JupyterBook through JupyterHub on an AWS EC2 instance. I’m encountering persistent 404 errors when trying to access the JupyterBook service via JupyterHub. I’ve tried a few things myself and have come to a deadend. I’ve tried to find a similar problem on here, and found one similar but the suggestions didn’t solve my problem. Apologies if I’ve just missed something. Any help is greatly appreciated.

Goal: Serve a JupyterBook through JupyterHub, allowing users to authenticate via JupyterHub and be directly taken to the homepage of the JupyterBook where users (students) can utilse the JupyterHub resources to run notebooks and run through taught material.

Set-up

  • TLJH (The Littlest JupyterHub) on an AWS EC2 instance using Ubuntu 24.04
  • Jupyterbook loaded loaded from my local machine into the /srv/jupyterhub/jupyterbook/ folder in my VM. I have the JB build which under jupyterbook I have _build/html/index.html

JupyterHub Configuration

I’ve added a custom service in the JupyterHub configuration to serve the JupyterBook. This is set in /opt/tljh/config/jupyterhub_config.d/jupyterhub_config.py (along with my other configs):

c.JupyterHub.services = [
        {
            'name': 'jupyterbook',
            'url': 'http://127.0.0.1:8000',
            'command': ['python3', '-m', 'http.server', '--bind', '127.0.0.1', '8000'],
            'cwd': '/srv/jupyterhub/jupyterbook/_build/html/',
            'admin': True,
        }
    ]

c.Spawner.default_url = '/services/jupyterbook/'
c.JupyterHub.authenticator_class = 'jupyterhub.auth.PAMAuthenticator'

c.LocalAuthenticator.create_system_users = True

c.JupyterHub.log_level = 'DEBUG'

Observed Behavior

  • When accessing the root of the service (http://127.0.0.1:8000/), I am redirected to the index.html correctly.
  • However, when trying to access the service through JupyterHub using the path /services/jupyterbook/, I consistently receive a 404 error.
  • Logs show the following:
Aug 25 16:55:37 ip-xxx-xx-xx-xxx python3[7099]: 127.0.0.1 - - [25/Aug/2024 16:55:37] code 404, message File not found
Aug 25 16:55:37 ip-xxx-xx-xx-xxx python3[7099]: 127.0.0.1 - - [25/Aug/2024 16:55:37] "GET /services/jupyterbook/ HTTP/1.1" 404 -

What I’ve Tried So Far

  • Ensuring the path has a trailing slash as mentioned in a related discussion.
  • Verified that the JupyterHub and Traefik services are running and correctly configured.
  • Tested accessing the service directly via curl with both the base path and the /services/jupyterbook/ path.

Questions

  1. Path Resolution: Could there be an issue with how the paths are being resolved between JupyterHub, Traefik, and the underlying HTTP server?
  2. File Location: Is there a possibility that the configuration file locations might be causing conflicts (e.g., /opt/tljh/state/traefik.toml vs. /opt/tljh/config/traefik_config.d/custom_traefik.toml)?
  3. Have I set something up wrong with Traefik (it’s myfirst time using this tool)?

Any advice or pointers on how to troubleshoot this would be greatly appreciated!

Thank you!

Could there be an issue with how the paths are being resolved between JupyterHub, Traefik, and the underlying HTTP server?

Yes, this is the issue if I am right. If you create sub directories services/jupyterbook inside /srv/jupyterhub/jupyterbook/_build/html/, it should work. So, if the cwd of your service is /srv/jupyterhub/jupyterbook/_build/html then the static content of your jupyterbook must be placed in /srv/jupyterhub/jupyterbook/_build/html/services/jupyterbook/ folder. When you make a request to JupyterHub like http://myjupyterhub.example.com/services/jupyterbook, it will proxy that request to underlying service as http://127.0.0.1/services/jupyterbook. Since with the current config you are running your Python web server at the root, there is nothing to find at /services/jupyterbook and hence 404.

Setting admin to true is not very safe for production as your end users will inherit those privileges. Look at examples section in JupyterHub repo and there are plenty of examples on how to configure services.

1 Like