I am struggling hard to get my JupyterHub working again. After an update (longer ago), JupyterHub often requires a manual database migration and refuses to start:
❯ journalctl -efu jupyterhub
...
Jun 04 22:10:41 yann-desktop-nixos jupyterhub[1038575]: Found database schema version 0eee8c825d24 != 4621fec11365. Backup your database and run `jupyterhub upgrade-db` to upgrade to the latest schema.
...
Jun 04 22:10:42 yann-desktop-nixos systemd[1]: Failed to start Jupyterhub development server.
So far so good, no problemo, on other distros it’s literally just sudo jupyterhub upgrade-db --db=/var/lib/jupyterhub/jupyterhub.sqlite
and off you go. But of course not on NixOS, where Python has to be a massive pain
Join me on a typical journey of NixOS pain
❯ nix run nixpkgs#python3Packages.jupyterhub -- upgrade-db --db /var/lib/jupyterhub/jupyterhub.sqlite
# ...
# PermissionError: [Errno 13] Permission denied: '/var/lib/jupyterhub/jupyterhub.sqlite.2025-06-04-230501'
Right, owned by root, I’ll just
sudo
it:
❯ sudo nix run nixpkgs#python3Packages.jupyterhub -- upgrade-db --db /var/lib/jupyterhub/jupyterhub.sqlite
error: flake 'flake:nixpkgs' does not provide attribute 'apps.x86_64-linux.python3Packages.jupyterhub', 'packages.x86_64-linux.python3Packages.jupyterhub', 'legacyPackages.x86_64-linux.python3Packages.jupyterhub' or 'python3Packages.jupyterhub'
… Apparently root’s registry needs to be handled manually (why!?), so we do that first:
❯ sudo nix registry pin nixpkgs github:NixOS/nixpkgs/nixos-25.05
Surely, now it’ll work?
❯ sudo nix run nixpkgs#python3Packages.jupyterhub -- upgrade-db --db /var/lib/jupyterhub/jupyterhub.sqlite
...
ModuleNotFoundError: No module named 'jupyterhub'
...
subprocess.CalledProcessError: Command '['alembic', '-c', '/tmp/tmpvpu5qs5i/alembic.ini', 'upgrade', 'head']' returned non-zero exit status 1.
Full error
❯ sudo nix run nixpkgs#python3Packages.jupyterhub -- upgrade-db --db /var/lib/jupyterhub/jupyterhub.sqlite
[sudo] Passwort für yann:
[I 2025-06-04 23:23:10.248 JupyterHub dbutil:129] Upgrading sqlite:////var/lib/jupyterhub/jupyterhub.sqlite
[I 2025-06-04 23:23:10.248 JupyterHub dbutil:100] Backing up /var/lib/jupyterhub/jupyterhub.sqlite => /var/lib/jupyterhub/jupyterhub.sqlite.2025-06-04-232310
Traceback (most recent call last):
File "/nix/store/svl690bn2mdg1q5va9g9cddn8xww6gnl-python3.12-alembic-1.15.2/bin/.alembic-wrapped", line 9, in <module>
sys.exit(main())
^^^^^^
File "/nix/store/svl690bn2mdg1q5va9g9cddn8xww6gnl-python3.12-alembic-1.15.2/lib/python3.12/site-packages/alembic/config.py", line 636, in main
CommandLine(prog=prog).main(argv=argv)
File "/nix/store/svl690bn2mdg1q5va9g9cddn8xww6gnl-python3.12-alembic-1.15.2/lib/python3.12/site-packages/alembic/config.py", line 626, in main
self.run_cmd(cfg, options)
File "/nix/store/svl690bn2mdg1q5va9g9cddn8xww6gnl-python3.12-alembic-1.15.2/lib/python3.12/site-packages/alembic/config.py", line 603, in run_cmd
fn(
File "/nix/store/svl690bn2mdg1q5va9g9cddn8xww6gnl-python3.12-alembic-1.15.2/lib/python3.12/site-packages/alembic/command.py", line 408, in upgrade
script.run_env()
File "/nix/store/svl690bn2mdg1q5va9g9cddn8xww6gnl-python3.12-alembic-1.15.2/lib/python3.12/site-packages/alembic/script/base.py", line 586, in run_env
util.load_python_file(self.dir, "env.py")
File "/nix/store/svl690bn2mdg1q5va9g9cddn8xww6gnl-python3.12-alembic-1.15.2/lib/python3.12/site-packages/alembic/util/pyfiles.py", line 95, in load_python_file
module = load_module_py(module_id, path)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/nix/store/svl690bn2mdg1q5va9g9cddn8xww6gnl-python3.12-alembic-1.15.2/lib/python3.12/site-packages/alembic/util/pyfiles.py", line 113, in load_module_py
spec.loader.exec_module(module) # type: ignore
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "<frozen importlib._bootstrap_external>", line 999, in exec_module
File "<frozen importlib._bootstrap>", line 488, in _call_with_frames_removed
File "/nix/store/8iv8w6j6rhfwhp22fgawv17i2g7rr9ww-python3.12-jupyterhub-5.3.0/lib/python3.12/site-packages/jupyterhub/alembic/env.py", line 32, in <module>
fileConfig(config.config_file_name)
File "/nix/store/8w718rm43x7z73xhw9d6vh8s4snrq67h-python3-3.12.10/lib/python3.12/logging/config.py", line 83, in fileConfig
formatters = _create_formatters(cp)
^^^^^^^^^^^^^^^^^^^^^^
File "/nix/store/8w718rm43x7z73xhw9d6vh8s4snrq67h-python3-3.12.10/lib/python3.12/logging/config.py", line 132, in _create_formatters
c = _resolve(class_name)
^^^^^^^^^^^^^^^^^^^^
File "/nix/store/8w718rm43x7z73xhw9d6vh8s4snrq67h-python3-3.12.10/lib/python3.12/logging/config.py", line 101, in _resolve
found = __import__(used)
^^^^^^^^^^^^^^^^
ModuleNotFoundError: No module named 'jupyterhub'
[E 2025-06-04 23:23:10.576 JupyterHub app:3920]
Traceback (most recent call last):
File "/nix/store/8iv8w6j6rhfwhp22fgawv17i2g7rr9ww-python3.12-jupyterhub-5.3.0/lib/python3.12/site-packages/jupyterhub/app.py", line 3918, in launch_instance_async
await self.start()
File "/nix/store/8iv8w6j6rhfwhp22fgawv17i2g7rr9ww-python3.12-jupyterhub-5.3.0/lib/python3.12/site-packages/jupyterhub/app.py", line 3675, in start
self.subapp.start()
File "/nix/store/8iv8w6j6rhfwhp22fgawv17i2g7rr9ww-python3.12-jupyterhub-5.3.0/lib/python3.12/site-packages/jupyterhub/app.py", line 241, in start
dbutil.upgrade_if_needed(hub.db_url, log=self.log)
File "/nix/store/8iv8w6j6rhfwhp22fgawv17i2g7rr9ww-python3.12-jupyterhub-5.3.0/lib/python3.12/site-packages/jupyterhub/dbutil.py", line 134, in upgrade_if_needed
upgrade(db_url)
File "/nix/store/8iv8w6j6rhfwhp22fgawv17i2g7rr9ww-python3.12-jupyterhub-5.3.0/lib/python3.12/site-packages/jupyterhub/dbutil.py", line 85, in upgrade
check_call(['alembic', '-c', alembic_ini, 'upgrade', revision])
File "/nix/store/8w718rm43x7z73xhw9d6vh8s4snrq67h-python3-3.12.10/lib/python3.12/subprocess.py", line 413, in check_call
raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command '['alembic', '-c', '/tmp/tmpw2j4gw82/alembic.ini', 'upgrade', 'head']' returned non-zero exit status 1.
what’s this
alembic
thing now? Apparently a database migration tool or something. Apparently somewhere down the line, jupyterhub upgrade-db
calls this alembic
executable, and this alembic
then itself wants to import the jupyterhub module, which it for some reason doesn’t see
Surely, a shell with both will work:
❯ sudo nix shell nixpkgs#python3Packages.jupyterhub nixpkgs#python3Packages.alembic --command jupyterhub upgrade-db --db=/var/lib/jupyterhub/jupyterhub.sqlite
(spoiler alert: no 😑)
Surely, more wizardry will solve it.
❯ sudo nix shell --impure --expr 'with import <nixpkgs> {}; python3.withPackages (ps: [ ps.jupyterhub ps.alembic ])' --command jupyterhub upgrade-db --db=/var/lib/jupyterhub/jupyterhub.sqlite
(spoiler alert: no 😑)
Now what…
It feels like this alembic
needs to be wrapped to somehow “see” the jupyterhub
module…
I find it very curious that I can’t find anything on this topic. Nothing about this error message. Apparently nobody uses services.jupyterhub.enable=true
. Or everybody just gave up