For quite some time now, I’ve been trying to get SageMath to run on my JupyterHub server (which has an arm64-based CPU). For some reason, this just did not seem to work, whatever I tried. Every time I started a kernel, it would not connect and just die off.
After quite a bit of trial-and-error, I finally managed to find a solution today. For those looking for the quick answer, scroll to the bottom. Before I give the solution, I want to spend a little time explaining how I managed to find this solution.
I’ve already looked into many webpages earlier when trying to solve this problem. For instance, I found this page, which suggested adding an environment variable to explicitly specify the root directory of the SageMath installation to the kernel specification of the Jupyter SageMath kernel. However, this did not seem to solve the issue; the kernel kept dying before I could do anything with it.
At some point, I decided it might be worthwhile to install a more recent version of SageMath; my JupyterHub VM’s Ubuntu version only comes with SageMath 9.0, while the latest version is 9.7, as of writing this post.
But, sadly, this did not help much; the kernel kept refusing to connect. As I did not have much useful debugging information (I was mainly looking at the syslog of the VM), I decided to try something different: since Jupyter outputs quite a bit of information when it is executed from the command line, I decided it might be useful to try running SageMath from there instead of from JupyterHub. This can easily be done using the following command:
sage -n jupyter
However, this introduced a new problem: since all (TCP) ports are blocked by default for incoming traffic on my VM by a firewall, I had to find a way to access the notebook server I was running from the command line. For this, it turns out you can use SSH tunnels; these forward traffic which arrives on a port on your local PC to a port on the remote PC. Thus, we can run the following:
ssh -L 8888:localhost:8888 xander@jupyterhub.smeets.re
This command does the following: it creates an SSH session to xander@jupyterhub.smeets.re, as usual. However, it also states that any traffic arriving at port 8888 on the computer from which this SSH session is running should be forwarded to whatever the remote PC (that is, jupyterhub.smeets.re) can access at localhost:8888. In effect, this means that accessing localhost:8888 from my own PC will show the webpage I would arrive at when I would access localhost:8888 from the remote PC. Since Jupyter is running at port 8888 on the remote PC, this means I can access the SageMath Jupyter server I started above by going to localhost:8888 on my own PC.
From this point, solving the issue was relatively straightforward. When starting a SageMath kernel in Jupyter, the following error showed up almost immediately:
ImportError: /lib/aarch64-linux-gnu/libgomp.so.1: cannot allocate memory in static TLS block
At this point, I did what I usually do: just copy-and-paste the error straight into a search engine (in my case, DuckDuckGo). I found the following answer on StackOverflow: https://stackoverflow.com/a/63560767/2378368.
The error already indicated that something was wrong with a library. The StackOverflow answer indicates an easy solution: by specifying the path to that library in an environment variable, it can be loaded properly.
Luckily, from the page I linked to earlier, we already know how to make Juptyter kernels load with an environment variable set to a certain value; this requires simply adding that environment variable to the kernel specification, which can be done as follows:
{
"argv": ["/usr/bin/sage", "--python", "-m", "sage.repl.ipython_kernel", "-f", "{connection_file}"],
"display_name": "SageMath 9.0",
"language": "sage",
"env": {
"LD_PRELOAD": "/usr/lib/aarch64-linux-gnu/libgomp.so.1"
}
}
I placed the above in the file /usr/share/jupyter/kernels/sagemath/kernel.json. (Note: only the part with the env key was added to this file; the rest is mainly re-formatting to make it more readable.) After doing this, the SageMath kernel started almost immediately after attempting to do so from JupyterHub. Now, I can happily look forward to the cryptology exam I will soon be taking, in which SageMath can be quite useful to me.