<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Open Source | 2i2c</title><link>https://deploy-preview-608--2i2c-org.netlify.app/tag/open-source/</link><atom:link href="https://deploy-preview-608--2i2c-org.netlify.app/tag/open-source/index.xml" rel="self" type="application/rss+xml"/><description>Open Source</description><generator>Hugo Blox Builder (https://hugoblox.com)</generator><language>en-us</language><lastBuildDate>Mon, 04 May 2026 00:00:00 +0000</lastBuildDate><image><url>https://deploy-preview-608--2i2c-org.netlify.app/media/sharing.png</url><title>Open Source</title><link>https://deploy-preview-608--2i2c-org.netlify.app/tag/open-source/</link></image><item><title>Protecting our hubs against the CopyFail kernel exploit</title><link>https://deploy-preview-608--2i2c-org.netlify.app/blog/copyfail-mitigation/</link><pubDate>Mon, 04 May 2026 00:00:00 +0000</pubDate><guid>https://deploy-preview-608--2i2c-org.netlify.app/blog/copyfail-mitigation/</guid><description>&lt;p>The recently disclosed
&lt;a href="https://copy.fail/" target="_blank" rel="noopener" >CopyFail Linux kernel zero-day&lt;/a> (CVE-2026-31431) opens up a way for code running inside a container to break out onto the underlying node.
We took a close look at our hubs to confirm whether they were exposed, confirmed that our hubs are likely not at risk, and added another layer of protection just in case.&lt;/p>
&lt;h3 id="are-2i2cs-hubs-at-risk">
Are 2i2c&amp;rsquo;s hubs at risk?
&lt;a class="header-anchor" href="#are-2i2cs-hubs-at-risk">#&lt;/a>
&lt;/h3>&lt;p>No - based on our testing and mitigation efforts, our hubs are not vulnerable to CopyFail.&lt;/p>
&lt;h3 id="why-do-we-think-were-not-at-risk">
Why do we think we&amp;rsquo;re not at risk?
&lt;a class="header-anchor" href="#why-do-we-think-were-not-at-risk">#&lt;/a>
&lt;/h3>&lt;ul>
&lt;li>We tried to reproduce the exploit on a staging hub by following the
&lt;a href="https://github.com/Percivalll/Copy-Fail-CVE-2026-31431-Kubernetes-PoC" target="_blank" rel="noopener" >public Kubernetes proof-of-concept&lt;/a> on both AWS and EKS, and the exploit was unable to break out of the container.&lt;/li>
&lt;li>Existing JupyterHub hardening on Kubernetes from
&lt;a href="https://github.com/jupyterhub/kubespawner/pull/545" target="_blank" rel="noopener" >&lt;i class='fa-brands fa-github'>&lt;/i> jupyterhub/kubespawner#545&lt;/a> (originally added by Yuvi in 2021 in response to a different security issue) had already significantly reduced our risk exposure, and the exposure of anyone else running
&lt;a href="https://z2jh.jupyter.org" target="_blank" rel="noopener" >Z2JH&lt;/a> (the standard way to deploy JupyterHub on Kubernetes).&lt;/li>
&lt;li>As an extra layer of protection, we deployed
&lt;a href="https://github.com/iwanhae/copyfail-ebpf-k8s" target="_blank" rel="noopener" >&lt;code>copyfail-ebpf-k8s&lt;/code>&lt;/a> across our hubs in
&lt;a href="https://github.com/2i2c-org/infrastructure/pull/8227" target="_blank" rel="noopener" >&lt;i class='fa-brands fa-github'>&lt;/i> 2i2c-org/infrastructure#8227&lt;/a>. It blocks the specific kernel feature that CopyFail depends on. See
&lt;a href="https://github.com/iwanhae/copyfail-ebpf-k8s#quick-start" target="_blank" rel="noopener" >the project&amp;rsquo;s explanation&lt;/a> for how that works.&lt;/li>
&lt;li>We&amp;rsquo;ve upgraded all GKE clusters to use
&lt;a href="https://docs.cloud.google.com/kubernetes-engine/security-bulletins" target="_blank" rel="noopener" >a patched image&lt;/a> in
&lt;a href="https://github.com/2i2c-org/infrastructure/pull/8230" target="_blank" rel="noopener" >&lt;i class='fa-brands fa-github'>&lt;/i> 2i2c-org/infrastructure#8230&lt;/a>.&lt;/li>
&lt;/ul>
&lt;h3 id="what-else-did-we-look-into">
What else did we look into
&lt;a class="header-anchor" href="#what-else-did-we-look-into">#&lt;/a>
&lt;/h3>&lt;ul>
&lt;li>
&lt;a href="https://github.com/deckhouse/d8-copy-fail-mitigation" target="_blank" rel="noopener" >Deckhouse&amp;rsquo;s mitigation&lt;/a> was too platform-specific for us.&lt;/li>
&lt;li>
&lt;a href="https://blog.ovhcloud.com/copy-fail-cve-2026-31431-how-to-rapidly-protect-ovhcloud-mks-clusters-from-the-linux-kernel-zero-day/" target="_blank" rel="noopener" >OVHcloud&amp;rsquo;s &lt;code>modprobe&lt;/code> blocking&lt;/a> likely
&lt;a href="https://github.com/aws/containers-roadmap/issues/2808" target="_blank" rel="noopener" >won&amp;rsquo;t work on Amazon Linux 2023&lt;/a>, since the relevant module is built into the kernel image.&lt;/li>
&lt;li>
&lt;a href="https://alas.aws.amazon.com/alas2023.html" target="_blank" rel="noopener" >AL2023 security advisories&lt;/a> - no patched AL2023 image is available yet, so we can&amp;rsquo;t rely on a kernel-level fix from AWS for now.&lt;/li>
&lt;/ul>
&lt;h2 id="acknowledgements">
Acknowledgements
&lt;a class="header-anchor" href="#acknowledgements">#&lt;/a>
&lt;/h2>&lt;ul>
&lt;li>Huge thanks to
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/author/georgiana-dolocan/" >Georgiana&lt;/a> for the deep dive into the exploit and whether we&amp;rsquo;re exposed here.&lt;/li>
&lt;li>Thanks to
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/author/yuvaraj-yuvi/" >Yuvi&lt;/a> for the PR that reduces JupyterHub&amp;rsquo;s exposure to this back in 2021!&lt;/li>
&lt;li>Thanks to
&lt;a href="https://github.com/iwanhae/copyfail-ebpf-k8s" target="_blank" rel="noopener" >iwanhae&lt;/a> for the eBPF daemonset we deployed in Kubernetes, and to
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/jupyterhub/" >JupyterHub&lt;/a> for the upstream kubespawner hardening that lowered our exposure.&lt;/li>
&lt;li>Thanks to our collaborators at
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/nasa-veda/" >NASA VEDA&lt;/a> for the ongoing conversations about hub security.&lt;/li>
&lt;/ul></description></item><item><title>Supporting JupyterHub admins on workshop hubs with shared passwords</title><link>https://deploy-preview-608--2i2c-org.netlify.app/blog/shared-password-admin/</link><pubDate>Mon, 27 Apr 2026 00:00:00 +0000</pubDate><guid>https://deploy-preview-608--2i2c-org.netlify.app/blog/shared-password-admin/</guid><description>&lt;p>To facilitate communities using JupyterHub for a workshop, we introduced the idea of a &amp;lsquo;shared password&amp;rsquo; based authentication a few years ago.
This lets communities set a single &lt;em>global&lt;/em> password that is handed out to all workshop attendees (instead of collecting email addresses or GitHub usernames &lt;em>before&lt;/em> the workshop starts).
Users can login with their email and this shared global password, and get going immediately. We worked with
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/openscapes/" >OpenScapes&lt;/a> (which runs a lot of workshops) in developing this method, and it&amp;rsquo;s been heavily used since among other communities!&lt;/p>
&lt;p>However, until now this method required us to &lt;em>restrict admin access&lt;/em> for all users, preventing users from using admin features like group management, accessing the JupyterHub Admin dashboard (which lets you see which other users are logged in), and using the
&lt;a href="https://docs.2i2c.org/user/data/filesystem/#the-shared-directory" target="_blank" rel="noopener" >shared directory&lt;/a>.&lt;/p>
&lt;p>To mitigate these, we
&lt;a href="https://github.com/jupyterhub/jupyterhub/pull/5037" target="_blank" rel="noopener" >contributed the SharedPasswordAuthenticator&lt;/a> upstream to the JupyterHub organization, allowing hub admins to set set &lt;em>two&lt;/em> passwords instead of &lt;em>one&lt;/em>.
Hub admins can now &lt;strong>generate a special password that can be distributed just to admins&lt;/strong>, and that gives users these extra capabilities without giving up the simplicity of using a single password for all workshop participants!&lt;/p>
&lt;p>By contributing this upstream, we made sure this feature is available for everyone to use, rather than just for communities served by 2i2c.
We&amp;rsquo;re
&lt;a href="https://github.com/2i2c-org/infrastructure/issues/7864" target="_blank" rel="noopener" >rolling this&lt;/a> out to our communities now, and many communities have already benefitted from this!&lt;/p>
&lt;h2 id="acknowledgements">
Acknowledgements
&lt;a class="header-anchor" href="#acknowledgements">#&lt;/a>
&lt;/h2>&lt;ul>
&lt;li>To
&lt;a href="https://github.com/minrk" target="_blank" rel="noopener" >MinRK&lt;/a> for code review and merge of the pull requests!&lt;/li>
&lt;li>The
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/openscapes/" >OpenScapes&lt;/a> community for collaborating with us on building features that benefit themselves and everyone else!&lt;/li>
&lt;li>Support from our
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/members/" >member communities&lt;/a> gives us the capacity to invest in upstream open source engagement and build relationships like this&lt;/li>
&lt;/ul></description></item><item><title>Report from the Jupyter and AI community meetup</title><link>https://deploy-preview-608--2i2c-org.netlify.app/blog/jupyter-ai-seattle-meetup/</link><pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate><guid>https://deploy-preview-608--2i2c-org.netlify.app/blog/jupyter-ai-seattle-meetup/</guid><description>&lt;p>A small group of
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/jupyter/" >Jupyter&lt;/a> community members recently met in Seattle to demo Jupyter workflows augmented with AI tools and discuss what&amp;rsquo;s next. This is a quick report-out about what stood out.&lt;/p>
&lt;p>The conversations focused on what agentic workflows could unlock for researchers and students - with broad acknowledgement that deployment, security, authorization, and ethics still have a lot to be worked out.&lt;/p>
&lt;p>Here are a few highlights from the demos.&lt;/p>
&lt;h2 id="jupyter-ai-and-the-agent-client-protocol">
Jupyter AI and the Agent Client Protocol
&lt;a class="header-anchor" href="#jupyter-ai-and-the-agent-client-protocol">#&lt;/a>
&lt;/h2>&lt;p>
&lt;a href="https://github.com/jupyterlab/jupyter-ai" target="_blank" rel="noopener" >Jupyter AI&lt;/a> v3 is adding support for the
&lt;a href="https://agentclientprotocol.com/" target="_blank" rel="noopener" >Agent Client Protocol (ACP)&lt;/a>, enabling multi-agent collaboration within JupyterLab. We saw how a single request could be split across multiple specialized agents based on each one&amp;rsquo;s skills, similar to
&lt;a href="https://www.youtube.com/watch?v=hyzPC6moEJ0" target="_blank" rel="noopener" >this demo from JupyterCon 2025&lt;/a>.&lt;/p>
&lt;p>Some things still to figure out:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>No tool isolation yet&lt;/strong> - agents aren&amp;rsquo;t scoped by user role or security group.&lt;/li>
&lt;li>&lt;strong>Manual configuration required&lt;/strong> - agents running locally need to be registered by hand.&lt;/li>
&lt;li>A future goal is for JupyterLab to auto-detect locally installed agents, or for LLM providers to contribute integrations directly.&lt;/li>
&lt;/ul>
&lt;p>The Jupyter AI team also shared a new &amp;ldquo;Personas&amp;rdquo; abstraction that lets you define a skill-specific agent in just a few lines of Python. Personas open the door to domain-specific agents or agents with crafted &amp;ldquo;personalities&amp;rdquo;. They are written in a few lines of Python, though we discussed the possibility of using markdown instead. This seems to be evolving rapidly!&lt;/p>
&lt;p>
&lt;a href="https://github.com/jupyterlab/jupyter-ai/releases/tag/v3.0.0" target="_blank" rel="noopener" >Jupyter AI v3.0.0 has since been released&lt;/a>.&lt;/p>
&lt;h2 id="notebook-cli">
Notebook CLI
&lt;a class="header-anchor" href="#notebook-cli">#&lt;/a>
&lt;/h2>&lt;p>
&lt;a href="https://github.com/jupyter-ai-contrib/nb-cli" target="_blank" rel="noopener" >&lt;code>nb-cli&lt;/code>&lt;/a> is a Rust-based tool for interacting with notebooks from the command line - changing cells, running them, checking errors, and rendering the notebook in the console. It can also connect to remote JupyterLab instances, making it useful for headless workflows like CI pipelines or batch grading.&lt;/p>
&lt;h2 id="sidebar-comments-and-real-time-collaboration">
Sidebar comments and Real-time collaboration
&lt;a class="header-anchor" href="#sidebar-comments-and-real-time-collaboration">#&lt;/a>
&lt;/h2>&lt;p>A demo showed Google Docs-style side-panel comments for &lt;code>.ipynb&lt;/code> files. Previous collaboration efforts used
&lt;a href="https://en.wikipedia.org/wiki/Conflict-free_replicated_data_type" target="_blank" rel="noopener" >Conflict-free Replicated Data Types (CRDTs)&lt;/a> for multi-cursor editing, but the team felt that approach may not have hit the mark. Side-panel comments felt more natural, though how this extends to &lt;code>.py&lt;/code> files is still an open question.&lt;/p>
&lt;h2 id="opportunities-for-2i2c">
Opportunities for 2i2c
&lt;a class="header-anchor" href="#opportunities-for-2i2c">#&lt;/a>
&lt;/h2>&lt;p>The meeting helped us understand the role we &lt;em>could&lt;/em> play in this space.
We think there&amp;rsquo;s opportunity to help facilitate the use of agents on shared infrastructure, particularly around the upstream control planes for deployment, administration, and authorization. We can also help facilitate community conversations about the ethics and impact of AI tools on open science.&lt;/p>
&lt;h2 id="acknowledgements">
Acknowledgements
&lt;a class="header-anchor" href="#acknowledgements">#&lt;/a>
&lt;/h2>&lt;ul>
&lt;li>The
&lt;a href="https://jupyterfoundation.org" target="_blank" rel="noopener" >Jupyter Foundation&lt;/a> for supporting the event.&lt;/li>
&lt;li>
&lt;a href="https://www.linkedin.com/in/zach-sailer-8a1472151" target="_blank" rel="noopener" >Zach Sailer&lt;/a> (Apple), for organizing this meetup.&lt;/li>
&lt;li>
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/author/chris-holdgraf/" >Chris Holdgraf&lt;/a> for editing and adapting the original content for this post.&lt;/li>
&lt;/ul></description></item><item><title>BIDS joins the mybinder.org federation with help from 2i2c</title><link>https://deploy-preview-608--2i2c-org.netlify.app/blog/bids-mybinder-federation/</link><pubDate>Thu, 09 Apr 2026 00:00:00 +0000</pubDate><guid>https://deploy-preview-608--2i2c-org.netlify.app/blog/bids-mybinder-federation/</guid><description>&lt;p>The
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/bids/" >Berkeley Institute for Data Science (BIDS)&lt;/a> has joined the
&lt;a href="https://mybinder.readthedocs.io/en/latest/about/federation.html" target="_blank" rel="noopener" >mybinder.org federation&lt;/a>, contributing a new node alongside 2i2c and
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/gesis/" >GESIS&lt;/a>. BIDS is the birthplace of &lt;code>mybinder.org&lt;/code>, so it&amp;rsquo;s great to see them back as an active federation member.&lt;/p>
&lt;p>We helped out with development, setup, and operations for the new federation member on OVH.
&lt;a href="https://github.com/2i2c-org/initiatives/issues/21" target="_blank" rel="noopener" >Here&amp;rsquo;s the initiative we just closed out »&lt;/a>.&lt;/p>
&lt;p>This is a win for the resilience of mybinder.org - the BIDS node runs on a different cloud provider than the existing nodes, reducing the risk that a single provider outage takes down the whole service.&lt;/p>
&lt;p>Read the full details on the
&lt;a href="https://blog.jupyter.org/berkeley-institute-for-data-science-bids-joins-the-mybinder-org-federation-with-help-from-2i2c-f0f22d0b5ba5" target="_blank" rel="noopener" >Jupyter blog&lt;/a>.&lt;/p></description></item><item><title>Report from the Jupyter Security Working Group security tooling sprint</title><link>https://deploy-preview-608--2i2c-org.netlify.app/blog/jupyter-security-sprint/</link><pubDate>Wed, 08 Apr 2026 00:00:00 +0000</pubDate><guid>https://deploy-preview-608--2i2c-org.netlify.app/blog/jupyter-security-sprint/</guid><description>&lt;p>The
&lt;a href="https://github.com/jupyter/security" target="_blank" rel="noopener" >Jupyter Security Working Group&lt;/a> recently held a Security Tooling Sprint.
It was a timely event given the
&lt;a href="https://blog.pypi.org/posts/2026-04-02-incident-report-litellm-telnyx-supply-chain-attack/" target="_blank" rel="noopener" >recent spate&lt;/a> of software supply chain attacks across the tech world.&lt;/p>
&lt;p>The sprint covered two main areas:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Governance and strategy&lt;/strong> — conversations about responsibility and accountability in the face of AI, with emphasis on ensuring humans are ultimately responsible for code committed to
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/jupyter/" >Jupyter&lt;/a> subprojects. The group also discussed how security could benefit from working group members regularly attending subproject meetings like the
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/jupyterhub/" >JupyterHub&lt;/a> Collaboration Cafes.&lt;/li>
&lt;li>&lt;strong>Automation and tools&lt;/strong> — the group evaluated several tools for improving security posture across the Jupyter ecosystem. Here are a few that stood out:
&lt;ul>
&lt;li>
&lt;a href="https://semgrep.dev/" target="_blank" rel="noopener" >Semgrep&lt;/a> as an alternative vulnerability scanner to CodeQL&lt;/li>
&lt;li>
&lt;a href="https://github.com/anchore/grype" target="_blank" rel="noopener" >Grype&lt;/a>,
&lt;a href="https://www.checkov.io/" target="_blank" rel="noopener" >Checkov&lt;/a>, and
&lt;a href="https://kubescape.io/" target="_blank" rel="noopener" >Kubescape&lt;/a> for cloud infrastructure misconfiguration checks&lt;/li>
&lt;li>
&lt;a href="https://github.com/schemathesis/schemathesis" target="_blank" rel="noopener" >Schemathesis&lt;/a> and
&lt;a href="https://github.com/microsoft/restler-fuzzer" target="_blank" rel="noopener" >restler-fuzzer&lt;/a> for API fuzz testing&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;p>One challenge we discussed was how blindly running security scanning tools generates many false positives. There&amp;rsquo;s real effort needed to tune these tools for each project&amp;rsquo;s edge cases before they&amp;rsquo;re useful in automation. On a related note, we discussed the increase in AI-generated (or AI-assisted) vulnerability and security reports, and the challenges associated with sifting through all of those pieces of information.&lt;/p>
&lt;h2 id="acknowledgements">
Acknowledgements
&lt;a class="header-anchor" href="#acknowledgements">#&lt;/a>
&lt;/h2>&lt;ul>
&lt;li>Thanks to
&lt;a href="https://github.com/jupyter/security" target="_blank" rel="noopener" >the jupyter security working group&lt;/a> for providing leadership and organizing, in particular Joe Lucas!&lt;/li>
&lt;li>Thanks to the
&lt;a href="https://jupyterfoundation.org" target="_blank" rel="noopener" >Jupyter Foundation&lt;/a> for funding community meetings like these.&lt;/li>
&lt;/ul></description></item><item><title>Upgrading community infrastructure to Kubernetes 1.34 and JupyterHub 4.3.3</title><link>https://deploy-preview-608--2i2c-org.netlify.app/blog/infra-upgrades-k8s-jupyterhub/</link><pubDate>Wed, 08 Apr 2026 00:00:00 +0000</pubDate><guid>https://deploy-preview-608--2i2c-org.netlify.app/blog/infra-upgrades-k8s-jupyterhub/</guid><description>&lt;p>We&amp;rsquo;ve completed a major round of infrastructure upgrades across all 2i2c-managed hubs - every hub is now running
&lt;a href="https://kubernetes.io/releases/" target="_blank" rel="noopener" >Kubernetes 1.34&lt;/a> and
&lt;a href="https://z2jh.jupyter.org/en/stable/changelog.html" target="_blank" rel="noopener" >Z2JH helm chart 4.3.3&lt;/a>.&lt;/p>
&lt;p>Running up-to-date versions of both Kubernetes and the
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/jupyterhub/" >JupyterHub&lt;/a> helm chart ensures that our communities get the best support and reliability, both in terms of features and security.&lt;/p>
&lt;h2 id="a-new-approach-to-infrastructure-upgrades-upgrading-in-rounds">
A new approach to infrastructure upgrades: upgrading in rounds
&lt;a class="header-anchor" href="#a-new-approach-to-infrastructure-upgrades-upgrading-in-rounds">#&lt;/a>
&lt;/h2>&lt;p>This was the first time we rolled out JupyterHub helm chart upgrades &lt;strong>in rounds&lt;/strong> rather than all at once. By upgrading a subset of hubs at a time, we could identify and fix issues in isolation before they affected the broader network. This made the process safer and more predictable.&lt;/p>
&lt;p>We&amp;rsquo;re planning to perform these kinds of upgrades on a regular schedule for our member communities. Around &lt;strong>every 6 months&lt;/strong> we&amp;rsquo;ll create an issue to make sure nothing falls through the cracks (here&amp;rsquo;s
&lt;a href="https://github.com/2i2c-org/infrastructure/blob/main/.github/workflows/recurrent-k8s-gcp-upgrades.yaml" target="_blank" rel="noopener" >example config for creating our reminder issues&lt;/a>).&lt;/p>
&lt;p>Check out our
&lt;a href="https://compass.2i2c.org/services/interactive-computing/multiple-hub-upgrades/#making-changes-to-multiple-hubs" target="_blank" rel="noopener" >process docs for multi-hub upgrades&lt;/a> for more information.&lt;/p>
&lt;h2 id="learn-more">
Learn more
&lt;a class="header-anchor" href="#learn-more">#&lt;/a>
&lt;/h2>&lt;p>Check out these pages for what kinds of improvements we&amp;rsquo;ve brought into our clusters / hubs with these latest updates.&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://z2jh.jupyter.org/en/stable/changelog.html" target="_blank" rel="noopener" >Z2JH Helm Chart Changelog&lt;/a>&lt;/li>
&lt;li>
&lt;a href="https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG-1.34.md" target="_blank" rel="noopener" >Kubernetes 1.34 Changelog&lt;/a>&lt;/li>
&lt;/ul>
&lt;h2 id="acknowledgements">
Acknowledgements
&lt;a class="header-anchor" href="#acknowledgements">#&lt;/a>
&lt;/h2>&lt;ul>
&lt;li>Thanks to
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/author/georgiana-dolocan/" >Georgiana Dolocan&lt;/a> for leading this upgrade effort and establishing the rounds-based approach.&lt;/li>
&lt;li>Thanks to
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/author/chris-holdgraf/" >Chris Holdgraf&lt;/a> for adapting and editing Georgiana&amp;rsquo;s notes into a blog post.&lt;/li>
&lt;/ul></description></item><item><title>Combining multiple repos into one site at jupyterbook.org</title><link>https://deploy-preview-608--2i2c-org.netlify.app/blog/jupyterbook-multi-repo-site/</link><pubDate>Mon, 06 Apr 2026 00:00:00 +0000</pubDate><guid>https://deploy-preview-608--2i2c-org.netlify.app/blog/jupyterbook-multi-repo-site/</guid><description>&lt;p>As part of
&lt;a href="https://github.com/2i2c-org/initiatives/issues/28" target="_blank" rel="noopener" >an initiative to improve jupyterbook.org&amp;rsquo;s documentation&lt;/a>, we refactored the site so that multiple repositories are served under one domain. We wrote up the details on the
&lt;a href="https://jupyterbook.org/blog" target="_blank" rel="noopener" >Jupyter Book blog&lt;/a>.&lt;/p>
&lt;p>Read the full post here:&lt;/p>
&lt;p>
&lt;a href="https://jupyterbook.org/blog/posts/2026/multi-repo" target="_blank" rel="noopener" >How we combine multiple repositories into one website at jupyterbook.org&lt;/a>.&lt;/p>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img src="./featured.png" alt="The landing page of jupyterbook.org" loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;p>Along the way we made several upstream improvements to the
&lt;a href="https://mystmd.org" target="_blank" rel="noopener" >MyST Engine&lt;/a> and the
&lt;a href="https://github.com/jupyter-book/myst-theme" target="_blank" rel="noopener" >MyST theme&lt;/a>:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://github.com/jupyter-book/mystmd/issues/2126" target="_blank" rel="noopener" >&lt;code>parts:&lt;/code> support for &lt;code>extends:&lt;/code>&lt;/a> and
&lt;a href="https://github.com/jupyter-book/mystmd/issues/2127" target="_blank" rel="noopener" >URL support as well&lt;/a> so we can share a footer / navbar configuration across repositories&lt;/li>
&lt;li>
&lt;a href="https://github.com/jupyter-book/myst-theme/pull/816" target="_blank" rel="noopener" >&lt;code>internal_domains&lt;/code> option&lt;/a> so that links to another repository&amp;rsquo;s content could still be treated as internal&lt;/li>
&lt;li>
&lt;a href="https://github.com/jupyter-book/mystmd/pull/2684" target="_blank" rel="noopener" >Less aggressive citation parsing&lt;/a> so that text like &lt;code>@githubhandle&lt;/code> weren&amp;rsquo;t parsed as a citation&lt;/li>
&lt;li>
&lt;a href="https://github.com/jupyter-book/myst-theme/pull/790" target="_blank" rel="noopener" >Several mobile and UX fixes&lt;/a> (that&amp;rsquo;s one, there were many others!)&lt;/li>
&lt;/ul>
&lt;p>These all felt particularly relevant for documentation that our
&lt;a href="https://2i2c.org/members" target="_blank" rel="noopener" >member communities&lt;/a> manage, where you have content split across multiple repositories but served at a single domain.&lt;/p>
&lt;h2 id="acknowledgements">
Acknowledgements
&lt;a class="header-anchor" href="#acknowledgements">#&lt;/a>
&lt;/h2>&lt;p>Thanks to
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/pythia/" >Project Pythia&lt;/a> and
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/earthscope/" >EarthScope&lt;/a> for collaboration and feedback that helped shape this work. And thanks to our
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/members/" >member communities&lt;/a> whose memberships fund upstream contributions like these.&lt;/p>
&lt;p>Multi-repo site support is also useful for training programs that span several content repositories, including
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/nasa-open-science/" >NASA Open Science / ScienceCore&lt;/a>.&lt;/p></description></item><item><title>How regularly upgrading core infrastructure leads to upstream improvements and better infrastructure</title><link>https://deploy-preview-608--2i2c-org.netlify.app/blog/why-upgrade-regularly/</link><pubDate>Fri, 03 Apr 2026 00:00:00 +0000</pubDate><guid>https://deploy-preview-608--2i2c-org.netlify.app/blog/why-upgrade-regularly/</guid><description>&lt;p>Our collaborators at
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/nasa-veda/" >NASA VEDA&lt;/a> recently asked us about the rationale behind policies for upgrading our infrastructure relatively quickly when new versions come out. Here&amp;rsquo;s the explanation that we shared with them, in case it&amp;rsquo;s useful for others as well.&lt;/p>
&lt;p>In this case, the decision was whether to upgrade to Helm 4, and you can find our
&lt;a href="https://github.com/2i2c-org/initiatives/issues/4" target="_blank" rel="noopener" >rationale in the &lt;code>/initiatives&lt;/code> repository&lt;/a>. Here&amp;rsquo;s a brief summary from Yuvi:&lt;/p>
&lt;p>Fundamentally, it helps keep moving us and the ecosystem forward, and drive improvements upstream, in both JupyterHub and Helm.&lt;/p>
&lt;p>It has driven these PRs in
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/jupyterhub/" >JupyterHub&lt;/a>:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://github.com/jupyterhub/action-k3s-helm/pull/126" target="_blank" rel="noopener" >&lt;i class='fa-brands fa-github'>&lt;/i> jupyterhub/action-k3s-helm#126&lt;/a> (merged)&lt;/li>
&lt;li>
&lt;a href="https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/3797" target="_blank" rel="noopener" >&lt;i class='fa-brands fa-github'>&lt;/i> jupyterhub/zero-to-jupyterhub-k8s#3797&lt;/a> (validated, but not merged yet)&lt;/li>
&lt;/ul>
&lt;p>It&amp;rsquo;s also driven improvements to helm itself - see this bug report that is being worked on:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://github.com/helm/helm/issues/31919" target="_blank" rel="noopener" >&lt;i class='fa-brands fa-github'>&lt;/i> helm/helm#31919&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>Upgrading helm versions can break things (and it has for some of our other communities in the past - see
&lt;a href="https://github.com/2i2c-org/infrastructure/pull/7886#issuecomment-4031310423" target="_blank" rel="noopener" >this example&lt;/a>). So it&amp;rsquo;s important we do that on a reasonable timeframe and carefully, to avoid disruptions.&lt;/p>
&lt;p>We&amp;rsquo;re also discovering for example that potentially the new &lt;code>nginx-ingress&lt;/code> controller we had to move to has some issues working with older helm versions (ongoing WIP in
&lt;a href="https://github.com/2i2c-org/infrastructure/pull/7995%29" target="_blank" rel="noopener" >&lt;i class='fa-brands fa-github'>&lt;/i> 2i2c-org/infrastructure#7995)&lt;/a>. That feels much more tractable because we can now go &amp;lsquo;ok, let us just apply a quick fix now, and wait for the helm 4 rollout, and try again&amp;rsquo; instead of being totally stuck.&lt;/p>
&lt;p>This is similar to the other part of [/our VEDA objective] - rolling out new versions of jupyterhub. If we need to roll out security fixes, it&amp;rsquo;s much easier now because we already did the hard work of being up to date:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://github.com/2i2c-org/infrastructure/issues/7996" target="_blank" rel="noopener" >&lt;i class='fa-brands fa-github'>&lt;/i> 2i2c-org/infrastructure#7996&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>This isn&amp;rsquo;t the case quite yet for helm v3, as it&amp;rsquo;s still supported, but it&amp;rsquo;s much better to do this work earlier than wait.&lt;/p>
&lt;p>If you encounter a bug in a popular open source software, often you can just &amp;lsquo;wait&amp;rsquo; for it to be fixed. But this isn&amp;rsquo;t just about time - someone somewhere has to put in the &lt;em>effort&lt;/em> of getting it fixed, filing helpful upstream bug reports, and testing to make sure it works. This is an example of 2i2c continuing to contribute this &lt;em>effort&lt;/em> upstream wherever we can.&lt;/p>
&lt;h2 id="acknowledgements">
Acknowledgements
&lt;a class="header-anchor" href="#acknowledgements">#&lt;/a>
&lt;/h2>&lt;ul>
&lt;li>Thanks to
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/nasa-veda/" >NASA VEDA&lt;/a> for collaborating deeply with us on infrastructure questions like this.&lt;/li>
&lt;/ul></description></item><item><title>Better sharing UX with nbgitpuller and contextual error handling</title><link>https://deploy-preview-608--2i2c-org.netlify.app/blog/nbgitpuller-better-ux/</link><pubDate>Tue, 31 Mar 2026 00:00:00 +0000</pubDate><guid>https://deploy-preview-608--2i2c-org.netlify.app/blog/nbgitpuller-better-ux/</guid><description>
&lt;h2 id="tldr">
TL;DR
&lt;a class="header-anchor" href="#tldr">#&lt;/a>
&lt;/h2>&lt;p>
&lt;a href="https://github.com/jupyterhub/nbgitpuller" target="_blank" rel="noopener" >nbgitpuller&lt;/a> now has improved UX context-aware error handling. Update to
&lt;a href="https://pypi.org/project/nbgitpuller/1.3.0/" target="_blank" rel="noopener" >version 1.3.0&lt;/a> and let us know what you think by opening an
&lt;a href="https://github.com/jupyterhub/nbgitpuller/issues" target="_blank" rel="noopener" >issue&lt;/a> or via the feedback form below 🚀&lt;/p>
&lt;p>Check out the initiative we used to structure and complete this work:&lt;/p>
&lt;p>
&lt;a href="https://github.com/2i2c-org/initiatives/issues/22" target="_blank" rel="noopener" >GitHub initiative »&lt;/a>&lt;/p>
&lt;h2 id="what-is-nbgitpuller">
What is nbgitpuller?
&lt;a class="header-anchor" href="#what-is-nbgitpuller">#&lt;/a>
&lt;/h2>&lt;p>
&lt;a href="https://github.com/jupyterhub/nbgitpuller" target="_blank" rel="noopener" >nbgitpuller&lt;/a> is a way to sync &lt;em>content&lt;/em> with &lt;em>compute&lt;/em> through the click of a link. Example use cases include:&lt;/p>
&lt;ul>
&lt;li>Interactive research demos, such as
&lt;a href="https://elifesciences.org/reviewed-preprints/108089" target="_blank" rel="noopener" >Spyglass&lt;/a> (HHMI)&lt;/li>
&lt;li>Workshops and training scenarios&lt;/li>
&lt;li>University exams&lt;/li>
&lt;/ul>
&lt;p>In the case of
&lt;a href="https://elifesciences.org/reviewed-preprints/108089" target="_blank" rel="noopener" >Spyglass&lt;/a>, the &lt;em>content&lt;/em> is
&lt;a href="https://github.com/LorenFrankLab/spyglass-demo" target="_blank" rel="noopener" >&lt;i class='fa-brands fa-github'>&lt;/i> LorenFrankLab/spyglass-demo&lt;/a> hosted on GitHub, the &lt;em>compute&lt;/em> is a 2i2c cloud hub hosted at
&lt;a href="https://spyglass.hhmi.2i2c.cloud/" target="_blank" rel="noopener" >spyglass.hhmi.2i2c.cloud&lt;/a>, and by using the handy
&lt;a href="https://nbgitpuller.readthedocs.io/en/latest/link.html" target="_blank" rel="noopener" >nbgitpuller link generator&lt;/a>, you can generate
&lt;a href="https://spyglass.hhmi.2i2c.cloud/hub/user-redirect/git-pull?repo=https%3A%2F%2Fgithub.com%2FLorenFrankLab%2Fspyglass-demo&amp;amp;urlpath=lab%2Ftree%2Fspyglass-demo%2Fnotebooks%2F00_HubQuickStart.ipynb&amp;amp;branch=main" target="_blank" rel="noopener" >this nbgitpuller link&lt;/a> to share with others to seamlessly explore content on the desired compute platform with the relevant data and toolchains installed.&lt;/p>
&lt;h2 id="how-does-nbgitpuller-work">
How does nbgitpuller work?
&lt;a class="header-anchor" href="#how-does-nbgitpuller-work">#&lt;/a>
&lt;/h2>&lt;p>&lt;code>nbgitpuller&lt;/code> is installed in the compute environment. The compute environment now has an &lt;code>/git-pull&lt;/code> endpoint URL that can understand where to pull content from using URL parameters. Syncing content critically depends on &lt;code>git&lt;/code> operations to &lt;code>fetch&lt;/code>, &lt;code>checkout&lt;/code>, &lt;code>clone&lt;/code>, &lt;code>merge&lt;/code>, &lt;code>commit&lt;/code>, etc.&lt;/p>
&lt;h2 id="when-it-goes-wrong">
When it goes wrong
&lt;a class="header-anchor" href="#when-it-goes-wrong">#&lt;/a>
&lt;/h2>&lt;p>Based on the data sent through by the kind folks running the Berkeley DataHub, there were 2163 logs available, of which:&lt;/p>
&lt;ul>
&lt;li>983 (45%) were ‘merge’ conflicts&lt;/li>
&lt;li>493 (23%) were ‘fetch’ errors&lt;/li>
&lt;li>467 (22%) were ‘ls-remote’ errors&lt;/li>
&lt;/ul>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img src="./errors_common.png" alt="Bar chart showing the most common errors users faced." loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;p>The remaining errors (10%) were mostly ‘checkout’ errors. This represents most &lt;strong>frequent&lt;/strong> errors as seen by students.&lt;/p>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img src="./errors_unique.png" alt="Bar chart showing the most unique errors link authors made." loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;p>In the same set of logs, there were 172 &lt;strong>unique&lt;/strong> errors: most ‘ls-remote’ errors come from mistakes in the content repo URL. This represents most uniquely common errors made by instructors.&lt;/p>
&lt;h2 id="merge-conflicts">
Merge conflicts
&lt;a class="header-anchor" href="#merge-conflicts">#&lt;/a>
&lt;/h2>&lt;p>If the link author changes content after the link consumer clicked a link, then &lt;code>nbgitpuller&lt;/code> needs to sync updates for the consumer on subsequent link clicks. The &lt;code>nbgitpuller&lt;/code> merging strategy makes opinionated choices so that the link consumer &lt;em>never&lt;/em> has to interact with git, and will always preserve the consumer’s working changes.&lt;/p>
&lt;p>Things can go wrong when&lt;/p>
&lt;ul>
&lt;li>Consumers can diverge the git history if they perform a git commit&lt;/li>
&lt;li>Authors can diverge the git history if they perform force push commits&lt;/li>
&lt;/ul>
&lt;h2 id="error-ux-old">
Error UX (old)
&lt;a class="header-anchor" href="#error-ux-old">#&lt;/a>
&lt;/h2>&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img src="./ux_old.png" alt="Old UX for merge errors" loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;p>Problems with the old UX include:&lt;/p>
&lt;ul>
&lt;li>a scary terminal&lt;/li>
&lt;li>difficulty for the user to figure out what went wrong&lt;/li>
&lt;li>no suggestion for the user to fix the problem or signpost to continue to the compute platform&lt;/li>
&lt;/ul>
&lt;h2 id="error-ux-new">
Error UX (new)
&lt;a class="header-anchor" href="#error-ux-new">#&lt;/a>
&lt;/h2>&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img src="./ux_new.png" alt="New UX for merge errors" loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;p>New improvements to the UX include:&lt;/p>
&lt;ul>
&lt;li>terminal closed by default, but you can optionally toggle this open&lt;/li>
&lt;li>there is a copy to clipboard button to easily share the error log from the terminal&lt;/li>
&lt;li>more user-friendly and context aware helper message is displayed&lt;/li>
&lt;li>a link to the general documentation for reference&lt;/li>
&lt;li>a &amp;lsquo;Proceed without syncing&amp;rsquo; button take the user to the compute platform without making any changes&lt;/li>
&lt;li>in the case of merge errors an extra Backup and resync button option is presented&lt;/li>
&lt;/ul>
&lt;a href="https://docs.google.com/forms/d/e/1FAIpQLSff-u-sWFuwO1-VTgk2Ir7f1nfUUlLevQk_Vkk_jnmcI1nJnw/viewform?usp=pp_url&amp;amp;entry.648332035=https://deploy-preview-608--2i2c-org.netlify.app/blog/nbgitpuller-better-ux/" target="_blank" rel="noopener" class="text-decoration-none">
&lt;div class="alert alert-info d-flex align-items-start p-3" role="button" style="transition: all 0.2s ease; box-shadow: 0 2px 4px rgba(0,0,0,0.1);" onmouseover="this.style.backgroundColor='#b3e5fc'; this.style.boxShadow='0 4px 8px rgba(0,0,0,0.15)'; this.style.transform='translateY(-1px)'" onmouseout="this.style.backgroundColor=''; this.style.boxShadow='0 2px 4px rgba(0,0,0,0.1)'; this.style.transform='translateY(0)'" onfocus="this.style.backgroundColor='#b3e5fc'; this.style.boxShadow='0 4px 8px rgba(0,0,0,0.15)'; this.style.transform='translateY(-1px)'" onblur="this.style.backgroundColor=''; this.style.boxShadow='0 2px 4px rgba(0,0,0,0.1)'; this.style.transform='translateY(0)'">
&lt;div class="fw-bold mb-1">&lt;span style="font-weight:bold">Give us feedback!&lt;/span> Click here to provide feedback that will help us make this more impactful.&lt;/div>
&lt;/div>
&lt;/a>
&lt;h2 id="learn-more">
Learn more
&lt;a class="header-anchor" href="#learn-more">#&lt;/a>
&lt;/h2>&lt;ul>
&lt;li>
&lt;a href="https://nbgitpuller.readthedocs.io/en/latest/" target="_blank" rel="noopener" >nbgitpuller documentation&lt;/a>&lt;/li>
&lt;li>
&lt;a href="https://github.com/2i2c-org/initiatives/issues/22" target="_blank" rel="noopener" >Roadmap initiative&lt;/a>&lt;/li>
&lt;/ul>
&lt;h2 id="acknowledgements">
Acknowledgements
&lt;a class="header-anchor" href="#acknowledgements">#&lt;/a>
&lt;/h2>&lt;ul>
&lt;li>
&lt;a href="https://www.berkeley.edu/" target="_blank" rel="noopener" >UC Berkeley&lt;/a> and the
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/cloudbank/" >CloudBank Classroom&lt;/a> project&lt;/li>
&lt;li>
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/cal-icor/" >CAL ICOR&lt;/a> for co-funding&lt;/li>
&lt;li>
&lt;a href="https://github.com/ericvd-ucb" target="_blank" rel="noopener" >Eric Van Dusen&lt;/a> and
&lt;a href="https://github.com/sean-morris" target="_blank" rel="noopener" >Sean Morris&lt;/a> for championing this work&lt;/li>
&lt;li>
&lt;a href="https://github.com/balajialg" target="_blank" rel="noopener" >Balaji Alwar&lt;/a> for providing the data and sharing feedback&lt;/li>
&lt;li>
&lt;a href="https://github.com/nthiery" target="_blank" rel="noopener" >Nicolas M. Thiéry&lt;/a> for feedback on the UX design&lt;/li>
&lt;/ul></description></item><item><title>Jenny Wong joins the JupyterHub team</title><link>https://deploy-preview-608--2i2c-org.netlify.app/blog/jenny-jupyterhub-team/</link><pubDate>Mon, 09 Feb 2026 00:00:00 +0000</pubDate><guid>https://deploy-preview-608--2i2c-org.netlify.app/blog/jenny-jupyterhub-team/</guid><description>&lt;p>We&amp;rsquo;re excited to share that
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/author/jenny-wong" >Jenny Wong&lt;/a> has been
&lt;a href="https://github.com/jupyterhub/team-compass/pull/876" target="_blank" rel="noopener" >invited to join the JupyterHub team&lt;/a> as a contributor and maintainer.&lt;/p>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="" srcset="
/blog/jenny-jupyterhub-team/featured_hud4aa732603690fdbf1310c8591f72bcc_150634_15672feb0dbcce75ffac0028d3779d57.webp 400w,
/blog/jenny-jupyterhub-team/featured_hud4aa732603690fdbf1310c8591f72bcc_150634_ec7c3cbaf083beb3d79c7c7d6c46b398.webp 760w,
/blog/jenny-jupyterhub-team/featured_hud4aa732603690fdbf1310c8591f72bcc_150634_1200x1200_fit_q75_h2_lanczos_3.webp 1200w"
src="https://deploy-preview-608--2i2c-org.netlify.app/blog/jenny-jupyterhub-team/featured_hud4aa732603690fdbf1310c8591f72bcc_150634_15672feb0dbcce75ffac0028d3779d57.webp"
width="760"
height="398"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;p>Jenny&amp;rsquo;s contributions to
&lt;a href="https://github.com/jupyterhub/nbgitpuller" target="_blank" rel="noopener" >nbgitpuller&lt;/a> and
&lt;a href="https://github.com/jupyterhub/grafana-dashboards" target="_blank" rel="noopener" >grafana-dashboards&lt;/a>, along with her active participation in project meetings and community planning, earned her this recognition from the JupyterHub community. Being invited to a project team means that existing team members have recognized a pattern of high-quality contributions and trust in a person&amp;rsquo;s ability to steward the project.&lt;/p>
&lt;p>We&amp;rsquo;re particularly excited about this because our mission isn&amp;rsquo;t just about deploying infrastructure - it&amp;rsquo;s about being
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/blog/good-citizen/" >good citizens&lt;/a> in the open source communities we depend on. We invest in upstream contributions, participate in community governance, and aim to build the kind of relationships that strengthen the whole ecosystem. When our team members are welcomed into upstream project teams, it&amp;rsquo;s a signal that we&amp;rsquo;re doing this well.&lt;/p>
&lt;h2 id="learn-more">
Learn more
&lt;a class="header-anchor" href="#learn-more">#&lt;/a>
&lt;/h2>&lt;ul>
&lt;li>
&lt;a href="https://compass.hub.jupyter.org/en/latest/team/structure.html" target="_blank" rel="noopener" >JupyterHub team compass&lt;/a> - how the team is structured and how new members are added&lt;/li>
&lt;li>
&lt;a href="https://github.com/jupyterhub/team-compass/pull/876" target="_blank" rel="noopener" >JupyterHub proposal to add Jenny to the team&lt;/a>&lt;/li>
&lt;li>
&lt;a href="https://github.com/jupyterhub/nbgitpuller" target="_blank" rel="noopener" >nbgitpuller&lt;/a> and
&lt;a href="https://github.com/jupyterhub/grafana-dashboards" target="_blank" rel="noopener" >grafana-dashboards&lt;/a> - projects Jenny contributes to&lt;/li>
&lt;/ul>
&lt;h2 id="acknowledgements">
Acknowledgements
&lt;a class="header-anchor" href="#acknowledgements">#&lt;/a>
&lt;/h2>&lt;ul>
&lt;li>The
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/jupyterhub/" >JupyterHub&lt;/a> community for fostering an open and welcoming project culture&lt;/li>
&lt;li>Support from our
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/members/" >member communities&lt;/a> gives us the capacity to invest in upstream open source engagement and build relationships like this&lt;/li>
&lt;/ul></description></item><item><title>Introducing Jupyter Book 2 at FOSDEM 2026</title><link>https://deploy-preview-608--2i2c-org.netlify.app/blog/fosdem-jupyter-book-2/</link><pubDate>Fri, 06 Feb 2026 00:00:00 +0000</pubDate><guid>https://deploy-preview-608--2i2c-org.netlify.app/blog/fosdem-jupyter-book-2/</guid><description>&lt;p>Our teammate
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/author/angus-hollands/" >Angus Hollands&lt;/a> gave a talk at FOSDEM 2026:
&lt;a href="https://fosdem.org/2026/schedule/event/ZY9WYD-introducing-jb-2/" target="_blank" rel="noopener" >Introducing Jupyter Book 2&lt;/a>.&lt;/p>
&lt;p>The talk shares why the Jupyter Book 2 and MyST stack was rebuilt, and how it supports open, reusable computational publishing workflows.&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://video.fosdem.org/2026/aw1120/ZY9WYD-introducing-jb-2.mp4" target="_blank" rel="noopener" >Watch the recording&lt;/a>&lt;/li>
&lt;li>
&lt;a href="https://fosdem.org/2026/schedule/event/ZY9WYD-introducing-jb-2/" target="_blank" rel="noopener" >FOSDEM event page&lt;/a>&lt;/li>
&lt;/ul>
&lt;figure id="figure-slide-from-the-fosdem-2026-session-introducing-jupyter-book-2">
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="Slide from the FOSDEM 2026 session introducing Jupyter Book 2." srcset="
/blog/fosdem-jupyter-book-2/featured_huebc44838a5457ae22511d566a17f4261_473619_ce68173621cc9d0cafd80f67e5937361.webp 400w,
/blog/fosdem-jupyter-book-2/featured_huebc44838a5457ae22511d566a17f4261_473619_70e28470934a2403242eb19afd9cb036.webp 760w,
/blog/fosdem-jupyter-book-2/featured_huebc44838a5457ae22511d566a17f4261_473619_1200x1200_fit_q75_h2_lanczos_3.webp 1200w"
src="https://deploy-preview-608--2i2c-org.netlify.app/blog/fosdem-jupyter-book-2/featured_huebc44838a5457ae22511d566a17f4261_473619_ce68173621cc9d0cafd80f67e5937361.webp"
width="760"
height="383"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;figcaption>
Slide from the FOSDEM 2026 session introducing Jupyter Book 2.
&lt;/figcaption>&lt;/figure>
&lt;h2 id="learn-more">
Learn more
&lt;a class="header-anchor" href="#learn-more">#&lt;/a>
&lt;/h2>&lt;ul>
&lt;li>
&lt;a href="https://proceedings.scipy.org/articles/hwcj9957" target="_blank" rel="noopener" >Jupyter Book 2 and the MyST Document Stack (SciPy 2025 paper)&lt;/a>&lt;/li>
&lt;li>
&lt;a href="https://jupyterbook.org/" target="_blank" rel="noopener" >Jupyter Book documentation&lt;/a>&lt;/li>
&lt;li>
&lt;a href="https://github.com/jupyter-book/jupyter-book" target="_blank" rel="noopener" >Jupyter Book on GitHub&lt;/a>&lt;/li>
&lt;/ul>
&lt;h2 id="acknowledgements">
Acknowledgements
&lt;a class="header-anchor" href="#acknowledgements">#&lt;/a>
&lt;/h2>&lt;ul>
&lt;li>Thanks to
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/pythia/" >Project Pythia&lt;/a> and to
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/bids/" >BIDS&lt;/a> for supporting deeper
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/blog/fosdem-jupyter-book-2/../../2025/foundational-contributions/" >foundational contributions&lt;/a> like this in Jupyter Book.&lt;/li>
&lt;li>Thanks to the
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/jupyter-book/" >Jupyter Book&lt;/a> team for helping out with slide creation and doing all the work Angus spoke about here!&lt;/li>
&lt;/ul></description></item><item><title>New Jupyter Book / MyST stack release (Jan 2026)</title><link>https://deploy-preview-608--2i2c-org.netlify.app/blog/jupyter-book-release-jan-2026/</link><pubDate>Thu, 29 Jan 2026 00:00:00 +0000</pubDate><guid>https://deploy-preview-608--2i2c-org.netlify.app/blog/jupyter-book-release-jan-2026/</guid><description>&lt;p>The MyST/Jupyter Book stack shipped new releases this week. Release pages:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://github.com/jupyter-book/mystmd/releases/tag/mystmd%401.8.0" target="_blank" rel="noopener" >mystmd 1.8.0&lt;/a>&lt;/li>
&lt;li>
&lt;a href="https://github.com/jupyter-book/myst-theme/releases/tag/myst-to-react%401.1.0" target="_blank" rel="noopener" >myst-theme 1.1.0&lt;/a>&lt;/li>
&lt;li>
&lt;a href="https://github.com/jupyter-book/jupyter-book/releases/tag/v2.1.1" target="_blank" rel="noopener" >Jupyter Book 2.1.1&lt;/a>&lt;/li>
&lt;/ul>
&lt;h2 id="where-we-contributed">
Where we contributed
&lt;a class="header-anchor" href="#where-we-contributed">#&lt;/a>
&lt;/h2>&lt;p>We&amp;rsquo;ve spent extra time lately trying to fix bugs and generally improve stability, reliability, and UX papercuts.
Here are some of the things we focused on:&lt;/p>
&lt;ul>
&lt;li>Extra review time to get in
&lt;a href="https://github.com/jupyter-book/mystmd/pull/2428" target="_blank" rel="noopener" >concurrent executions in mystmd&lt;/a>&lt;/li>
&lt;li>Fixing broken edit URL logic so our community
&lt;a href="https://github.com/jupyter-book/mystmd/pull/2642" target="_blank" rel="noopener" >&amp;ldquo;edit buttons&amp;rdquo; worked again&lt;/a>&lt;/li>
&lt;li>
&lt;a href="https://github.com/jupyter-book/myst-theme/pull/757" target="_blank" rel="noopener" >Standardized link styles&lt;/a> so users know what to expect from links&lt;/li>
&lt;li>
&lt;a href="https://github.com/jupyter-book/myst-theme/pull/747" target="_blank" rel="noopener" >Added extra hover metadata for github issues and PRs&lt;/a> for communities that often link to their GitHub issues&lt;/li>
&lt;li>Made all of these releases and wrote up the release notes!&lt;/li>
&lt;/ul>
&lt;p>Most of our contributions were foundational in nature - we fixed a bunch of bugs, did review on the PRs of others, and managed the release process itself. Check out the changelogs for more details!&lt;/p>
&lt;h2 id="acknowledgements">
Acknowledgements
&lt;a class="header-anchor" href="#acknowledgements">#&lt;/a>
&lt;/h2>&lt;p>Thanks to our
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/members/" >member communities&lt;/a> - their memberships cover the cost of
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/blog/jupyter-book-release-jan-2026/../../2025/foundational-contributions/" >foundational upstream contributions&lt;/a> to projects like these.&lt;/p>
&lt;p>Particular thanks to
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/pythia/" >Project Pythia&lt;/a> which currently supports much of our upstream contributions in Jupyter Book.&lt;/p>
&lt;p>These releases also support training communities that author curricula in MyST, including
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/nasa-open-science/" >NASA ScienceCore&lt;/a>.&lt;/p></description></item><item><title>STRUDEL enables rapid scientific GUI prototyping in partnership with 2i2c</title><link>https://deploy-preview-608--2i2c-org.netlify.app/blog/strudel-gui-prototyping/</link><pubDate>Tue, 27 Jan 2026 00:00:00 +0000</pubDate><guid>https://deploy-preview-608--2i2c-org.netlify.app/blog/strudel-gui-prototyping/</guid><description>
&lt;h2 id="what-happened">
What happened
&lt;a class="header-anchor" href="#what-happened">#&lt;/a>
&lt;/h2>&lt;p>The STRUDEL team hosted an all-day workshop with over thirty participants prototyping web applications using the
&lt;a href="https://strudel.science/strudel-kit/docs/" target="_blank" rel="noopener" >STRUDEL Design System&lt;/a> and AI assistants in a custom hub environment designed and managed by 2i2c. By the end of the day, all of the participants had a working prototype that incorporated their own data (or dummy data) into complex flows facilitated by the STRUDEL Design System.&lt;/p>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="Workshop participants collaborating" srcset="
/blog/strudel-gui-prototyping/featured_huf7e1e9dfd2ee4f5cb694679523c404fe_1392808_0594b56342ccc72182fe3a4971930713.webp 400w,
/blog/strudel-gui-prototyping/featured_huf7e1e9dfd2ee4f5cb694679523c404fe_1392808_fb6bf1c03b7c580381cd5e8248ff08ba.webp 760w,
/blog/strudel-gui-prototyping/featured_huf7e1e9dfd2ee4f5cb694679523c404fe_1392808_1200x1200_fit_q75_h2_lanczos_3.webp 1200w"
src="https://deploy-preview-608--2i2c-org.netlify.app/blog/strudel-gui-prototyping/featured_huf7e1e9dfd2ee4f5cb694679523c404fe_1392808_0594b56342ccc72182fe3a4971930713.webp"
width="760"
height="505"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;p>After a brief introduction to STRUDEL, participants were guided on setting up their personal coding environments using the STRUDEL Hub that 2i2c managed. The hub was configured to launch a unique code repository for each participant that was set up pre-workshop on the
&lt;a href="https://github.com/strudel-workshops" target="_blank" rel="noopener" >strudel-workshops&lt;/a> GitHub organization.&lt;/p>
&lt;blockquote>
&lt;p>&amp;ldquo;Having a startup environment was very nice, as often getting a good development environment set up is half the battle for smaller projects.&amp;rdquo;&lt;/p>
&lt;/blockquote>
&lt;p>The hub used
&lt;a href="https://code.visualstudio.com/docs/editor/vscode-web" target="_blank" rel="noopener" >VS Code for the Web&lt;/a>, pre-configured with the
&lt;a href="https://cline.bot/" target="_blank" rel="noopener" >Cline AI assistant extension&lt;/a>. Participants configured Cline with a shared API key generated by the STRUDEL team via
&lt;a href="https://openrouter.ai/" target="_blank" rel="noopener" >OpenRouter&lt;/a>. OpenRouter enabled the team to load credits into a shared account and API key that, in turn, enabled participants to use premium models inside of Cline.&lt;/p>
&lt;blockquote>
&lt;p>&amp;ldquo;Super easy to set up Cline in the VM, I appreciated that&amp;rdquo;&lt;/p>
&lt;/blockquote>
&lt;p>The day was split up into four sprints during which participants worked on different parts of their user interface application, with the majority of the participants working entirely in the 2i2c environment.&lt;/p>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="Workshop activities and prototyping" srcset="
/blog/strudel-gui-prototyping/group_hud46985bb8ec1b4e2211a99b454dbc197_2234570_844578748dd8499a08b50a5adb390df7.webp 400w,
/blog/strudel-gui-prototyping/group_hud46985bb8ec1b4e2211a99b454dbc197_2234570_b4e3c4e51bf359c6e37a9f800fb7bd9b.webp 760w,
/blog/strudel-gui-prototyping/group_hud46985bb8ec1b4e2211a99b454dbc197_2234570_1200x1200_fit_q75_h2_lanczos_3.webp 1200w"
src="https://deploy-preview-608--2i2c-org.netlify.app/blog/strudel-gui-prototyping/group_hud46985bb8ec1b4e2211a99b454dbc197_2234570_844578748dd8499a08b50a5adb390df7.webp"
width="760"
height="570"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;blockquote>
&lt;p>&amp;ldquo;I just want to express my gratitude for such an awesome day today. The workshop was really well structured and facilitated, and I learned a lot. Thank you so much for letting me come!&amp;rdquo;&lt;/p>
&lt;/blockquote>
&lt;h2 id="why-were-excited-about-this">
Why we&amp;rsquo;re excited about this
&lt;a class="header-anchor" href="#why-were-excited-about-this">#&lt;/a>
&lt;/h2>&lt;p>We think it&amp;rsquo;s a great example of setting up a complex environment once, and then providing rapid access to these environments via a centralized hub.&lt;/p>
&lt;p>This setup accelerated prototyping by removing the burden of setting up a development environment. The setup enabled participants, many of whom had never coded a web application or used an AI coding assistant before, to work seamlessly towards the goals of their design and development projects. The work they produced may continue beyond the workshop and have an impact on scientific discovery and operations.&lt;/p>
&lt;p>This setup is a valuable mechanism for encouraging people to build within a pre-existing design system. Being able to launch repositories that are preconfigured with design system tools and templates is a powerful way to promote the adoption of a design system and its embedded patterns and best practices.&lt;/p>
&lt;p>It&amp;rsquo;s also an interesting example of &lt;strong>non-Jupyter interfaces&lt;/strong> orchestrated on a JupyterHub.
The combination of VS Code for the Web, Cline, and OpenRouter represent a stack that can be easily transferable to other similar workshops.
OpenRouter enabled the workshop team to manage the costs of AI usage entirely themselves.&lt;/p>
&lt;p>In all, the participants and instructors were allowed to focus on their work instead of managing and setting up their infrastructure.&lt;/p>
&lt;h2 id="links-to-learn-more">
Links to learn more
&lt;a class="header-anchor" href="#links-to-learn-more">#&lt;/a>
&lt;/h2>&lt;ul>
&lt;li>Learn more about the workshop on the STRUDEL website:
&lt;a href="https://strudel.science/engage/news/10-23-2025-building-scientific-uis-with-strudel-and-ai-assistants/" target="_blank" rel="noopener" >strudel.science/engage/news/10-23-2025-building-scientific-uis-with-strudel-and-ai-assistants/&lt;/a>&lt;/li>
&lt;li>Explore STRUDEL + AI assistant tips and tricks:
&lt;a href="https://github.com/strudel-science/strudel-kit/blob/main/docs/docs/usage-with-ai.md" target="_blank" rel="noopener" >&lt;i class='fa-brands fa-github'>&lt;/i> strudel-science/strudel-kit/blob/main/docs/docs/usage-with-ai.md&lt;/a>&lt;/li>
&lt;/ul>
&lt;h2 id="acknowledgements">
Acknowledgements
&lt;a class="header-anchor" href="#acknowledgements">#&lt;/a>
&lt;/h2>&lt;p>We would like to thank all workshop participants.
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/strudel/" >STRUDEL&lt;/a> is an open source project housed at the Berkeley Institute for Data Science (BIDS) at the University of California, Berkeley. The STRUDEL team includes members of the Lawrence Berkeley National Lab Scientific Data (SciData) Division UX team, Superbloom Design, The Carpentries, and 2i2c. The project is generously funded by the Alfred P. Sloan Foundation, Liz Vu &amp;amp; Josh Greenberg Program Officers, grants G-2022-19360, G-2023-21098, and G-2024-22557.&lt;/p></description></item><item><title>April joins the Jupyter Community Building Working Group</title><link>https://deploy-preview-608--2i2c-org.netlify.app/blog/april-jupyter-community-building/</link><pubDate>Fri, 23 Jan 2026 00:00:00 +0000</pubDate><guid>https://deploy-preview-608--2i2c-org.netlify.app/blog/april-jupyter-community-building/</guid><description>&lt;p>We&amp;rsquo;re pleased to share that our People Operations Lead,
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/author/april-johnson/" >April Johnson&lt;/a>, has joined the
&lt;a href="https://jupyter.org/governance/communitybuildingworkinggroup.html" target="_blank" rel="noopener" >Jupyter Community Building Working Group&lt;/a>!&lt;/p>
&lt;p>This kind of work reflects how we think about
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/blog/april-jupyter-community-building/../../2025/foundational-contributions/" >foundational contributions&lt;/a> and upstream support: strengthening the social infrastructure that helps open source communities grow and thrive, not just contributing code and running infrastructure. April brings deep experience building teams and communities, and we’re proud to support her upstream efforts in this way.&lt;/p>
&lt;h2 id="acknowledgements">
Acknowledgements
&lt;a class="header-anchor" href="#acknowledgements">#&lt;/a>
&lt;/h2>&lt;ul>
&lt;li>Thanks to the
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/jupyter/" >Jupyter&lt;/a> Community Building Working Group for their leadership in building a stronger Jupyter community, and for welcoming April&lt;/li>
&lt;/ul></description></item><item><title>NASA Open Science ScienceCore tutorial available at github.com/sciencecore</title><link>https://deploy-preview-608--2i2c-org.netlify.app/blog/sciencecore-github-org/</link><pubDate>Thu, 18 Dec 2025 00:00:00 +0000</pubDate><guid>https://deploy-preview-608--2i2c-org.netlify.app/blog/sciencecore-github-org/</guid><description>&lt;p>As part of the
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/nasa-open-science/" >NASA Open Science&lt;/a> initiative, we co-developed a ScienceCore curriculum module with
&lt;a href="https://www.metadocencia.org/" target="_blank" rel="noopener" >MetaDocencia&lt;/a> that teaches researchers and educators how to use NASA Earthdata in the cloud to analyze climate risk.&lt;/p>
&lt;p>You can find the material at
&lt;a href="https://github.com/sciencecore" target="_blank" rel="noopener" >&lt;i class='fa-brands fa-github'>&lt;/i> &lt;strong>github.com/sciencecore&lt;/strong>&lt;/a>:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://sciencecore.github.io/climaterisk/" target="_blank" rel="noopener" >&lt;strong>climaterisk&lt;/strong>&lt;/a>: the &lt;em>Determining Climate Risks with NASA Earthdata Cloud&lt;/em> module (
&lt;a href="https://github.com/ScienceCore/climaterisk" target="_blank" rel="noopener" >source repo&lt;/a>).&lt;/li>
&lt;li>
&lt;a href="https://github.com/ScienceCore/scipy-2024-climaterisk" target="_blank" rel="noopener" >&lt;strong>scipy-2024-climaterisk&lt;/strong>&lt;/a> and
&lt;a href="https://github.com/ScienceCore/pydata-nyc-2024-climaterisk" target="_blank" rel="noopener" >&lt;strong>pydata-nyc-2024-climaterisk&lt;/strong>&lt;/a>: conference tutorial versions of the climaterisk material.&lt;/li>
&lt;/ul>
&lt;p>We also run the shared &lt;code>sciencecore.opensci.2i2c.cloud&lt;/code> JupyterHub and an opensci BinderHub that host the hands-on exercises.
These deployments use
&lt;a href="https://jupyter.org/hub" target="_blank" rel="noopener" >JupyterHub&lt;/a> and
&lt;a href="https://binderhub.readthedocs.io/" target="_blank" rel="noopener" >BinderHub&lt;/a> for hosting live computational infrastructure, and
&lt;a href="https://jupyterbook.org" target="_blank" rel="noopener" >Jupyter Book&lt;/a> for hosting the reading materials.&lt;/p>
&lt;h2 id="acknowledgements">
Acknowledgements
&lt;a class="header-anchor" href="#acknowledgements">#&lt;/a>
&lt;/h2>&lt;p>This work was supported by a NASA TOPS-T award that funded the
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/nasa-open-science/" >ScienceCore climaterisk&lt;/a> module and shared infrastructure for the broader ScienceCore community.&lt;/p>
&lt;p>Thanks to
&lt;a href="https://metadocencia.org/" target="_blank" rel="noopener" >MetaDocencia&lt;/a> for leading translation and localization of the material into Spanish, and helping with content creation.&lt;/p>
&lt;p>Thanks to
&lt;a href="https://www.linkedin.com/in/dhavide/" target="_blank" rel="noopener" >Dhavide Arulia&lt;/a> for leading much of the content creation.&lt;/p></description></item><item><title>Faster reporting of user home directory sizes</title><link>https://deploy-preview-608--2i2c-org.netlify.app/blog/faster-home-directory-reporting/</link><pubDate>Tue, 09 Dec 2025 00:00:00 +0000</pubDate><guid>https://deploy-preview-608--2i2c-org.netlify.app/blog/faster-home-directory-reporting/</guid><description>&lt;p>Storage quotas help users avoid running out of space unexpectedly and give administrators visibility into capacity planning. However, storage usage can change rapidly, and it&amp;rsquo;s important to have quick information so that administrators know whether they are close to hitting limits.&lt;/p>
&lt;p>We&amp;rsquo;ve improved how quickly hub administrators can see user home directory sizes across our JupyterHubs. This makes monitoring more responsive and adds quota limit visibility that wasn&amp;rsquo;t possible before.&lt;/p>
&lt;h2 id="using-jupyterhub-home-nfs-for-near-instant-disk-usage-metrics">
Using &lt;code>jupyterhub-home-nfs&lt;/code> for near-instant disk usage metrics
&lt;a class="header-anchor" href="#using-jupyterhub-home-nfs-for-near-instant-disk-usage-metrics">#&lt;/a>
&lt;/h2>&lt;p>Our existing storage monitoring tool,
&lt;a href="https://github.com/2i2c-org/prometheus-dirsize-exporter" target="_blank" rel="noopener" >&lt;code>prometheus-dirsize-exporter&lt;/code>&lt;/a>, deliberately runs slowly to avoid excessive disk I/O. This meant home directory metrics could be &lt;strong>hours out of date&lt;/strong> on systems with many users or large directories. Plus, there was no way to report user quota limits at all.&lt;/p>
&lt;p>Our home directory storage is managed by
&lt;a href="https://github.com/2i2c-org/jupyterhub-home-nfs/" target="_blank" rel="noopener" >&lt;code>jupyterhub-home-nfs&lt;/code>&lt;/a>, which enforces per-user quotas. It could also expose usage and limit information as Prometheus metrics using data from the underlying filesystem quota system. Because this information is already tracked by the filesystem, it&amp;rsquo;s available immediately without scanning individual files.&lt;/p>
&lt;p>We made two key improvements:&lt;/p>
&lt;ol>
&lt;li>
&lt;p>&lt;strong>Make disk usage reporting almost instantaneous&lt;/strong>. We made &lt;code>jupyterhub-home-nfs&lt;/code> export &lt;code>total_size_bytes&lt;/code> and &lt;code>hard_limit_bytes&lt;/code> metrics to Prometheus for near-instant reporting. We used the same metric names and namespace as &lt;code>prometheus-dirsize-exporter&lt;/code> for compatibility. See
&lt;a href="https://github.com/2i2c-org/jupyterhub-home-nfs/pull/76" target="_blank" rel="noopener" >&lt;i class='fa-brands fa-github'>&lt;/i> 2i2c-org/jupyterhub-home-nfs#76&lt;/a>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Allow this to be used upstream in JupyterHub Grafana Dashboards&lt;/strong> so that it can support both types of disk usage reporting. This means users of the upstream
&lt;a href="https://github.com/jupyterhub/grafana-dashboards" target="_blank" rel="noopener" >JupyterHub Grafana dashboards&lt;/a> get the same useful view about home directory usage, regardless of whether the metric comes from &lt;code>prometheus-dirsize-exporter&lt;/code> or &lt;code>jupyterhub-home-nfs&lt;/code>. See
&lt;a href="https://github.com/2i2c-org/prometheus-dirsize-exporter/pull/29" target="_blank" rel="noopener" >&lt;i class='fa-brands fa-github'>&lt;/i> 2i2c-org/prometheus-dirsize-exporter#29&lt;/a>&lt;/p>
&lt;/li>
&lt;/ol>
&lt;p>These changes were
&lt;a href="https://github.com/2i2c-org/infrastructure/pull/7261" target="_blank" rel="noopener" >deployed across all our communities&lt;/a>, so administrators can now access current home directory information &lt;strong>within minutes&lt;/strong> regardless of directory size.&lt;/p>
&lt;figure id="figure-home-directory-usage-dashboard-showing-total-size-metrics-from-jupyterhub-home-nfs-and-other-data-from-prometheus-dirsize-exporter">
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="Home Directory Usage dashboard showing total size metrics from jupyterhub-home-nfs and other data from prometheus-dirsize-exporter" srcset="
/blog/faster-home-directory-reporting/featured_hu5e6047328de0a056370b6f6f7ca4f2f4_42503_ededa5ff37780d5501ea74e6e73f6926.webp 400w,
/blog/faster-home-directory-reporting/featured_hu5e6047328de0a056370b6f6f7ca4f2f4_42503_a995b186c4e39c1fd078545f235e8394.webp 760w,
/blog/faster-home-directory-reporting/featured_hu5e6047328de0a056370b6f6f7ca4f2f4_42503_1200x1200_fit_q75_h2_lanczos_3.webp 1200w"
src="https://deploy-preview-608--2i2c-org.netlify.app/blog/faster-home-directory-reporting/featured_hu5e6047328de0a056370b6f6f7ca4f2f4_42503_ededa5ff37780d5501ea74e6e73f6926.webp"
width="760"
height="152"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;figcaption>
Home Directory Usage dashboard showing total size metrics from jupyterhub-home-nfs and other data from prometheus-dirsize-exporter
&lt;/figcaption>&lt;/figure>
&lt;h2 id="try-it-out">
Try it out
&lt;a class="header-anchor" href="#try-it-out">#&lt;/a>
&lt;/h2>&lt;p>2i2c member organizations can try this out now. If you have access to your hub&amp;rsquo;s Grafana instance, you can see these new metrics in the &lt;em>Home Directory Usage&lt;/em> dashboard:&lt;/p>
&lt;ol>
&lt;li>Open your hub&amp;rsquo;s
&lt;a href="https://docs.2i2c.org/admin/monitoring/grafana-dashboards/" target="_blank" rel="noopener" >Grafana dashboard&lt;/a>.&lt;/li>
&lt;li>Go to &lt;code>Dashboards&lt;/code> -&amp;gt; &lt;code>JupyterHub Default Dashboards&lt;/code> -&amp;gt; &lt;code>Home Directory Usage&lt;/code>.&lt;/li>
&lt;li>Check the table for up-to-date &lt;em>total size&lt;/em> and &lt;em>quota limit&lt;/em> values.&lt;/li>
&lt;/ol>
&lt;p>For more details, see our
&lt;a href="https://docs.2i2c.org/admin/monitoring/disk-usage/" target="_blank" rel="noopener" >docs on filesystem and disk dashboards&lt;/a>.&lt;/p>
&lt;h2 id="coming-next">
Coming next
&lt;a class="header-anchor" href="#coming-next">#&lt;/a>
&lt;/h2>&lt;p>We&amp;rsquo;d like to build on this work to enable &lt;strong>alerting when individual users near their disk quotas&lt;/strong>. This will make it easier to more reliably track user disk usage across a community. See this issue for tracking:
&lt;a href="https://github.com/2i2c-org/infrastructure/issues/7166" target="_blank" rel="noopener" >&lt;i class='fa-brands fa-github'>&lt;/i> 2i2c-org/infrastructure#7166&lt;/a>&lt;/p>
&lt;h2 id="acknowledgements">
Acknowledgements
&lt;a class="header-anchor" href="#acknowledgements">#&lt;/a>
&lt;/h2>&lt;ul>
&lt;li>This was a directed contribution supported by
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/nasa-veda/" >NASA VEDA&lt;/a> to enable more proactive monitoring and alerting for hub administrators.&lt;/li>
&lt;/ul></description></item><item><title>Supporting NASA Openscapes Champions with Cloud Infrastructure</title><link>https://deploy-preview-608--2i2c-org.netlify.app/blog/nasa-openscapes-champions-2025/</link><pubDate>Sun, 30 Nov 2025 00:00:00 +0000</pubDate><guid>https://deploy-preview-608--2i2c-org.netlify.app/blog/nasa-openscapes-champions-2025/</guid><description>&lt;p>
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/openscapes/" >Openscapes&lt;/a> ran a NASA Champions program in November, bringing 30 participants together to learn about NASA Earthdata and the earthaccess Python library. We provided JupyterHub infrastructure for hands-on breakout sessions - a good example of using shared infrastructure to facilitate learning and collaboration in remote events.&lt;/p>
&lt;p>They used their JupyterHub for co-working, where participants practiced streaming techniques for accessing cloud data without downloading. Multiple NASA Data Centers (NSIDC, ORNL, ASDC, PO.DAAC) collaborated to co-teach using the shared environment, succeeding despite the event happening the day after a government shutdown.&lt;/p>
&lt;p>They also used this to grow the OpenScapes community by getting attendees to join their slack and sign up for
&lt;a href="https://openscapes.org/events/2025-12-15-earthaccess-hackday/" target="_blank" rel="noopener" >their December Earth Access hack day&lt;/a>. It&amp;rsquo;s a great example of leveraging shared community infrastructure to help newcomers learn quickly and join a science community.&lt;/p>
&lt;p>Read their
&lt;a href="https://openscapes.org/blog/2025-11-27-nasa-champions-2025-summary/" target="_blank" rel="noopener" >full event summary&lt;/a> to learn how they structured the program and engaged their community.&lt;/p></description></item><item><title>Adding User Group Insights to Cloud Cost Dashboards with Grafana</title><link>https://deploy-preview-608--2i2c-org.netlify.app/blog/cloud-cost-groups/</link><pubDate>Mon, 24 Nov 2025 00:00:00 +0000</pubDate><guid>https://deploy-preview-608--2i2c-org.netlify.app/blog/cloud-cost-groups/</guid><description>&lt;p>We are excited to announce that we have extended our cloud cost dashboards to support display costs filtered by user groups using Grafana! This new feature allows administrators to monitor and manage cloud expenses based on user group memberships in JupyterHub.&lt;/p>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="Group cloud cost dashboard showing cost breakdowns by user groups" srcset="
/blog/cloud-cost-groups/featured_hu34fd6e3a049030056ef3072c1a0427ac_131153_c2b7e8d83fe14bfbc24fc804e952e390.webp 400w,
/blog/cloud-cost-groups/featured_hu34fd6e3a049030056ef3072c1a0427ac_131153_694d12ebbde0c6b897972885357ca71d.webp 760w,
/blog/cloud-cost-groups/featured_hu34fd6e3a049030056ef3072c1a0427ac_131153_1200x1200_fit_q75_h2_lanczos_3.webp 1200w"
src="https://deploy-preview-608--2i2c-org.netlify.app/blog/cloud-cost-groups/featured_hu34fd6e3a049030056ef3072c1a0427ac_131153_c2b7e8d83fe14bfbc24fc804e952e390.webp"
width="760"
height="388"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;div class="alert alert-">
&lt;div>
Available for dedicated AWS clusters only (and excluding CloudBank managed accounts). Other deployments on GCP will be supported in the future.
&lt;/div>
&lt;/div>
&lt;h2 id="learn-more">
Learn more
&lt;a class="header-anchor" href="#learn-more">#&lt;/a>
&lt;/h2>&lt;ul>
&lt;li>Take a look at the
&lt;a href="https://docs.2i2c.org/admin/monitoring/cost-users-groups/#group-cloud-costs" target="_blank" rel="noopener" >Community Hub Guide&lt;/a> to see what&amp;rsquo;s new&lt;/li>
&lt;li>Check out the documentation of the
&lt;a href="https://jupyterhub-cost-monitoring.readthedocs.io/en/latest/" target="_blank" rel="noopener" >2i2c-org/jupyterhub-cost-monitoring&lt;/a> project to see how it all works&lt;/li>
&lt;li>
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/author/jenny-wong/" >Jenny&lt;/a> recently presented her work on the cost monitoring system at
&lt;a href="https://events.linuxfoundation.org/jupytercon/" target="_blank" rel="noopener" >JupyterCon 2025&lt;/a> earlier this month. Watch a
&lt;a href="https://youtu.be/M5x3bTgRzVs?si=P2c3Ngb8v7f4ks0I" target="_blank" rel="noopener" >video&lt;/a> or look at the
&lt;a href="https://docs.google.com/presentation/d/1N8V7dna1atpRmcbpgZ0-VL5cbOQfwYfXTstudT2ierY/edit?usp=sharing" target="_blank" rel="noopener" >slides&lt;/a>.&lt;/li>
&lt;/ul>
&lt;a href="https://docs.google.com/forms/d/e/1FAIpQLSff-u-sWFuwO1-VTgk2Ir7f1nfUUlLevQk_Vkk_jnmcI1nJnw/viewform?usp=pp_url&amp;amp;entry.648332035=https://deploy-preview-608--2i2c-org.netlify.app/blog/cloud-cost-groups/" target="_blank" rel="noopener" class="text-decoration-none">
&lt;div class="alert alert-info d-flex align-items-start p-3" role="button" style="transition: all 0.2s ease; box-shadow: 0 2px 4px rgba(0,0,0,0.1);" onmouseover="this.style.backgroundColor='#b3e5fc'; this.style.boxShadow='0 4px 8px rgba(0,0,0,0.15)'; this.style.transform='translateY(-1px)'" onmouseout="this.style.backgroundColor=''; this.style.boxShadow='0 2px 4px rgba(0,0,0,0.1)'; this.style.transform='translateY(0)'" onfocus="this.style.backgroundColor='#b3e5fc'; this.style.boxShadow='0 4px 8px rgba(0,0,0,0.15)'; this.style.transform='translateY(-1px)'" onblur="this.style.backgroundColor=''; this.style.boxShadow='0 2px 4px rgba(0,0,0,0.1)'; this.style.transform='translateY(0)'">
&lt;div class="fw-bold mb-1">&lt;span style="font-weight:bold">Give us feedback!&lt;/span> Click here to provide feedback that will help us make this more impactful.&lt;/div>
&lt;/div>
&lt;/a>
&lt;h2 id="acknowledgements">
Acknowledgements
&lt;a class="header-anchor" href="#acknowledgements">#&lt;/a>
&lt;/h2>&lt;ul>
&lt;li>
&lt;a href="https://github.com/sunu" target="_blank" rel="noopener" >Tarashish&lt;/a> @
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/devseed/" >Development Seed&lt;/a> for collaborating on this project with us.&lt;/li>
&lt;li>
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/nasa-veda/" >NASA VEDA&lt;/a> and the DSE Team at NASA MSFC ODSI for funding much of this work.&lt;/li>
&lt;li>
&lt;a href="https://github.com/kyle-lesinger" target="_blank" rel="noopener" >Kyle Lesinger&lt;/a> from the NASA MSFC Office of Data Science and Informatics for providing valuable feedback and bug reports during development.&lt;/li>
&lt;/ul></description></item><item><title>2i2c at JupyterCon 2025: Helping communities navigate the Interactive Computing ecosystem</title><link>https://deploy-preview-608--2i2c-org.netlify.app/blog/jupytercon-2025-talks/</link><pubDate>Thu, 20 Nov 2025 00:00:00 +0000</pubDate><guid>https://deploy-preview-608--2i2c-org.netlify.app/blog/jupytercon-2025-talks/</guid><description>&lt;p>This year several team members attended
&lt;a href="https://jupytercon.com" target="_blank" rel="noopener" >JupyterCon 2025&lt;/a> to show off our own work and the upstream work that we&amp;rsquo;ve been doing in open source.
JupyterCon recently shared the videos of all talks, so here&amp;rsquo;s a quick run-down of 2i2c&amp;rsquo;s contributions and where you can watch more.&lt;/p>
&lt;h2 id="building-computational-narratives-with-jupyter-book">
Building computational narratives with Jupyter Book
&lt;a class="header-anchor" href="#building-computational-narratives-with-jupyter-book">#&lt;/a>
&lt;/h2>&lt;p>
&lt;a href="https://www.youtube.com/watch?v=3MUSteQFGq8&amp;amp;t=850s" target="_blank" rel="noopener" >Introducing Jupyter Book 2: Next-generation Tools for Creating Computational Narratives&lt;/a> - Chris Holdgraf and Rowan Cockett (
&lt;a href="https://curvenote.com" target="_blank" rel="noopener" >Curvenote&lt;/a>) introduce the next generation of
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/jupyter-book/" >Jupyter Book&lt;/a>, built on modern tooling and designed for creating rich computational narratives.&lt;/p>
&lt;p>
&lt;a href="https://jupytercon2025.sched.com/event/1jNKI" target="_blank" rel="noopener" >Tutorial: Build-a-Jupyter Book With the Turing Way&lt;/a> - Angus Hollands co-led this hands-on tutorial teaching participants how to create their own Jupyter Books using examples from the Turing Way.&lt;/p>
&lt;h2 id="jupyterhubs-evolution-and-sustainable-operations">
JupyterHub&amp;rsquo;s evolution and sustainable operations
&lt;a class="header-anchor" href="#jupyterhubs-evolution-and-sustainable-operations">#&lt;/a>
&lt;/h2>&lt;p>
&lt;a href="https://www.youtube.com/watch?v=-wwia9YzHO" target="_blank" rel="noopener" >Not Just for Notebooks: JupyterHub in 2025&lt;/a> - Yuvi Panda explores how
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/jupyterhub/" >JupyterHub&lt;/a> is evolving beyond just notebooks to support a wider range of interactive computing workflows.&lt;/p>
&lt;p>
&lt;a href="https://www.youtube.com/watch?v=M5x3bTgRzVs" target="_blank" rel="noopener" >Cloudy With a Chance of Savings: Per-User Usage and Cost Monitoring for JupyterHubs in the Cloud&lt;/a> - Jenny Wong presents our recent work improving tools and approaches for monitoring per-user cloud costs in JupyterHub deployments, helping communities operate more sustainably.&lt;/p>
&lt;p>
&lt;a href="https://jupytercon2025.sched.com/event/1jNQC" target="_blank" rel="noopener" >Lightning Talk: Controlling Home Directory Costs (with User Empathy) on the Cloud&lt;/a> - Yuvi Panda shares practical strategies for managing home directory storage costs while keeping user experience in mind, using &lt;code>jupyterhub-home-nfs&lt;/code>.&lt;/p>
&lt;hr>
&lt;p>Finally, there were also several talks that weren&amp;rsquo;t &lt;em>by&lt;/em> 2i2c team members, but were partially &lt;em>enabled&lt;/em> by 2i2c&amp;rsquo;s collaboration. We&amp;rsquo;re particularly proud of these, because it&amp;rsquo;s an example of us bringing others into the ecosystem and empowering them to contribute.&lt;/p>
&lt;h2 id="understanding-the-jupyterhub-community">
Understanding the JupyterHub community
&lt;a class="header-anchor" href="#understanding-the-jupyterhub-community">#&lt;/a>
&lt;/h2>&lt;p>
&lt;a href="https://www.youtube.com/watch?v=NnsD_Ly49Z0" target="_blank" rel="noopener" >Findings from the Voices of JupyterHub report&lt;/a> - This community strategy talk shares insights from conversations with JupyterHub users and operators about their needs and challenges. It&amp;rsquo;s not given by a 2i2c team member, but many of us have been involved in guiding (and being participants in!) this project.&lt;/p>
&lt;h2 id="pythia-sharing-their-myst-journey">
Pythia sharing their MyST journey
&lt;a class="header-anchor" href="#pythia-sharing-their-myst-journey">#&lt;/a>
&lt;/h2>&lt;p>
&lt;a href="https://www.youtube.com/watch?v=SqmMoyqSU8o" target="_blank" rel="noopener" >MyST-ifying Project Pythia&lt;/a> - Julia Kent of NSF NCAR discusses
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/pythia/" >Project Pythia&lt;/a>, an open-source platform dedicated to educating geoscientists on Python for complex Earth data analysis. Learn how Project Pythia manages its expansive repository of &amp;ldquo;cookbooks&amp;rdquo; and educational content, detailing their strategic shift to MyST Markdown and
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/jupyter-book/" >Jupyter Book&lt;/a> 2 to drastically improve project sustainability and reduce maintenance overhead.&lt;/p>
&lt;h2 id="how-cryocloud-built-a-healthy-open-science-community">
How CryoCloud built a healthy open science community
&lt;a class="header-anchor" href="#how-cryocloud-built-a-healthy-open-science-community">#&lt;/a>
&lt;/h2>&lt;p>
&lt;a href="https://www.youtube.com/watch?v=XD72H0Dkhq8" target="_blank" rel="noopener" >Building a successful open science community in the cloud&lt;/a> - Tasha Snow shares key insights from running the
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/cryocloud/" >CryoCloud&lt;/a>
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/jupyterhub/" >JupyterHub&lt;/a>, emphasizing that a successful scientific community relies on both technology and social innovation. She shares data-driven results on how shared JupyterHubs can significantly reduce research computing costs and accelerate scientific iteration. She also explores the critical balance between platform capabilities and the need for &lt;em>social infrastructure&lt;/em> to overcome technical barriers and foster true collaboration.&lt;/p></description></item><item><title>Yuvi on scaling maintainer intuition to facilitate PR review with PR triage boards</title><link>https://deploy-preview-608--2i2c-org.netlify.app/blog/pr-triage-boards/</link><pubDate>Wed, 19 Nov 2025 00:00:00 +0000</pubDate><guid>https://deploy-preview-608--2i2c-org.netlify.app/blog/pr-triage-boards/</guid><description>&lt;p>Yuvi has a recent post on the
&lt;a href="https://jupyter.org" target="_blank" rel="noopener" >Jupyter blog&lt;/a> on how his &amp;ldquo;maintainer intuition&amp;rdquo; about reviewable pull requests grew into the open-source
&lt;a href="https://github.com/jupyter/pr-triage-board-bot" target="_blank" rel="noopener" >&lt;code>pr-triage-board-bot&lt;/code>&lt;/a>, a reusable workflow that keeps GitHub Project boards curated for the JupyterHub, JupyterLab, and GeoJupyter communities.
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/blog/pr-triage-boards/../foundational-contributions/" >Foundational contributions&lt;/a> are rellay important to 2i2c. This is a great example of building clever technical systems that help maintainers prioritize the social work of facilitating contributions to keep ecosystems healthy.&lt;/p>
&lt;figure id="figure-the-jupyterhub-pr-triage-boardhttpsgithubcomorgsjupyterhubprojects4views9">
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="The [JupyterHub PR Triage board](https://github.com/orgs/jupyterhub/projects/4/views/9)." srcset="
/blog/pr-triage-boards/featured_hu42e3292f220b90b3776c7d0485ebe6f6_578487_75fe5f71a89f9494562e889e6ed95a90.webp 400w,
/blog/pr-triage-boards/featured_hu42e3292f220b90b3776c7d0485ebe6f6_578487_9e48a041e2580bd24fd8576d6b78b8e3.webp 760w,
/blog/pr-triage-boards/featured_hu42e3292f220b90b3776c7d0485ebe6f6_578487_1200x1200_fit_q75_h2_lanczos_3.webp 1200w"
src="https://deploy-preview-608--2i2c-org.netlify.app/blog/pr-triage-boards/featured_hu42e3292f220b90b3776c7d0485ebe6f6_578487_75fe5f71a89f9494562e889e6ed95a90.webp"
width="760"
height="367"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;figcaption>
The
&lt;a href="https://github.com/orgs/jupyterhub/projects/4/views/9" target="_blank" rel="noopener" >JupyterHub PR Triage board&lt;/a>.
&lt;/figcaption>&lt;/figure>
&lt;p>Our favorite quote shares the vibe and cultural principles that drive this effort:&lt;/p>
&lt;blockquote class="pull-quote">
&lt;p>If the author of the PR is a newish contributor, I want to encourage them to stick around by being responsive to their gift. All PRs are gifts that we may or may not choose to accept, but should do so with grace.&lt;/p>
&lt;cite>&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/author/yuvaraj-yuvi/" >Yuvi&lt;/a>&lt;/cite>
&lt;/blockquote>
&lt;p>Yuvi frames the problem here:&lt;/p>
&lt;blockquote>
&lt;p>Reviewing PRs is a critical way that maintainers keep an open source project moving forward, but identifying PRs that can productively be merged is hard.&lt;/p>
&lt;/blockquote>
&lt;p>And notes that &lt;em>human scalability&lt;/em> is often a big bottleneck:&lt;/p>
&lt;blockquote>
&lt;p>One key bottleneck we identified in the process was Step 2. In particular, I was relying on my maintainer intuition to pick a single PR that I believe can be merged, so others in the team can do review work. I started exploring what this intuition is, and if it can be scaled.&lt;/p>
&lt;/blockquote>
&lt;p>Here&amp;rsquo;s his list of &amp;ldquo;intuitions&amp;rdquo; that he uses to choose PRs to work on:&lt;/p>
&lt;blockquote>
&lt;ol>
&lt;li>PRs that aren’t too big, and are a reasonable size that can be merged within a 2 week window&lt;/li>
&lt;li>CI tests passing, so at least our automated checks haven’t caught any issues with it
Features or bug fixes that I believe add value to the project and move us in the right direction towards being able to support our users as they need (this is the hardest!)&lt;/li>
&lt;li>If the author of the PR is a newish contributor, as I want to encourage them to stick around by being responsive to their gift. All PRs are gifts that we may or may not choose to accept, but should do so with grace.&lt;/li>
&lt;li>How long ago the PR was opened. There is such a big difference between a response to your PR 2 days after you make it vs 2 months vs 2 years. I prioritized newer PRs.&lt;/li>
&lt;li>What kind of contribution is it primarily? Different engineers on our team have different skillsets (JS, Python, etc) and I wanted to match the PR to what the engineer preferred code reviewing.&lt;/li>
&lt;/ol>
&lt;/blockquote>
&lt;p>And the board essentially tries to capture many of these intuitions by signal-boosting them in one place:&lt;/p>
&lt;blockquote>
&lt;p>we can roughly say ‘Pick a PR that looks good to you from the top of the “First Time Contributor” or “Seasoned Contributor” list’, and that relieves me from being the bottleneck quite a bit.&lt;/p>
&lt;/blockquote>
&lt;p>Read more in the original article:
&lt;a href="https://blog.jupyter.org/scaling-maintainer-intuition-with-pull-request-triage-boards-779f2387498b" target="_blank" rel="noopener" >Scaling &amp;ldquo;Maintainer Intuition&amp;rdquo; with Pull Request Triage Boards&lt;/a>.&lt;/p>
&lt;h2 id="acknowledgements">
Acknowledgements
&lt;a class="header-anchor" href="#acknowledgements">#&lt;/a>
&lt;/h2>&lt;ul>
&lt;li>
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/jupyter/" >Project Jupyter&lt;/a> for trusting us to incubate and now donate the bot code to the broader ecosystem.&lt;/li>
&lt;li>
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/jupyterhub/" >JupyterHub&lt;/a> and
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/geojupyter/" >GeoJupyter&lt;/a> contributors who tested the triage views and fed real maintainer workflows back into the design.&lt;/li>
&lt;li>
&lt;a href="https://github.com/jasongrout" target="_blank" rel="noopener" >Jason Grout&lt;/a>,
&lt;a href="https://github.com/rgaiacs" target="_blank" rel="noopener" >Raniere Silva&lt;/a>, and
&lt;a href="https://github.com/mfisher87" target="_blank" rel="noopener" >Matt Fisher&lt;/a> for spotting the experiment early and helping it land across multiple orgs.&lt;/li>
&lt;/ul></description></item><item><title>Creating a re-usable redirect generator for Jupyter Book 1 migrations</title><link>https://deploy-preview-608--2i2c-org.netlify.app/blog/jb1-redirect-generator/</link><pubDate>Wed, 12 Nov 2025 00:00:00 +0000</pubDate><guid>https://deploy-preview-608--2i2c-org.netlify.app/blog/jb1-redirect-generator/</guid><description>&lt;p>When migrating documentation from
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/jupyter-book/" >Jupyter Book&lt;/a> 1 to Jupyter Book 2, URL structures change dramatically and break external links. We spent some time createing a re-usable tool to solve this problem across multiple projects.&lt;/p>
&lt;p>You can check out the tool below:&lt;/p>
&lt;p>
&lt;a href="https://github.com/jupyter-book/jb1-redirect-generator" target="_blank" rel="noopener" >&lt;i class='fa-brands fa-github'>&lt;/i> jupyter-book/jb1-redirect-generator&lt;/a>&lt;/p>
&lt;p>It&amp;rsquo;s designed to be run in a self-contained way by putting the dependencies in &lt;code>script&lt;/code> metadata at the top.
This means you can run it like this:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">uv run https://raw.githubusercontent.com/jupyter-book/jb1-redirect-generator/main/generate_redirects.py
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>This let&amp;rsquo;s you generate redirects from JB1 -&amp;gt; JB2 URL structures and dump them in a &lt;code>_build/html&lt;/code> folder with your JB2 built pages.&lt;/p>
&lt;p>We tested this out by converting the
&lt;a href="https://jupyter.org/governance" target="_blank" rel="noopener" >Jupyter Governance docs&lt;/a> to Jupyter Book 2 and running it there.
You can find a noxfile that runs these commands here:&lt;/p>
&lt;p>
&lt;a href="https://github.com/jupyter/governance/blob/bcdae30efdecbe75bc4751ef1fe1e602fe82ee10/noxfile.py#L25-L37" target="_blank" rel="noopener" >&lt;i class='fa-brands fa-github'>&lt;/i> jupyter/governance/blob/bcdae30efdecbe75bc4751ef1fe1e602fe82ee10/noxfile.py#L25-L37&lt;/a>&lt;/p>
&lt;p>And its use in a GitHub Workflow here:&lt;/p>
&lt;p>
&lt;a href="https://github.com/jupyter/governance/blob/bcdae30efdecbe75bc4751ef1fe1e602fe82ee10/.github/workflows/deploy.yml#L39-L44" target="_blank" rel="noopener" >&lt;i class='fa-brands fa-github'>&lt;/i> jupyter/governance/blob/bcdae30efdecbe75bc4751ef1fe1e602fe82ee10/.github/workflows/deploy.yml#L39-L44&lt;/a>&lt;/p>
&lt;h2 id="learn-more">
Learn more
&lt;a class="header-anchor" href="#learn-more">#&lt;/a>
&lt;/h2>&lt;ul>
&lt;li>
&lt;a href="https://github.com/jupyter-book/jb1-redirect-generator" target="_blank" rel="noopener" >jb1-redirect-generator repository&lt;/a>&lt;/li>
&lt;li>
&lt;a href="https://github.com/jupyter/governance/pull/307" target="_blank" rel="noopener" >Jupyter governance PR using the new script&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>Community learning: Hub config to pass oauth tokens into user environments</title><link>https://deploy-preview-608--2i2c-org.netlify.app/blog/communities-learning-from-one-another/</link><pubDate>Thu, 06 Nov 2025 00:00:00 +0000</pubDate><guid>https://deploy-preview-608--2i2c-org.netlify.app/blog/communities-learning-from-one-another/</guid><description>&lt;p>One of our favorite things to see: communities learning from and building on each other&amp;rsquo;s work!&lt;/p>
&lt;p>
&lt;a href="https://ops.maap-project.org/" target="_blank" rel="noopener" >MAAP&lt;/a> recently
&lt;a href="https://github.com/2i2c-org/infrastructure/pull/7068" target="_blank" rel="noopener" >contributed infrastructure configuration&lt;/a> inspired by
&lt;a href="https://github.com/2i2c-org/infrastructure/blob/0046e14a68d7af9e353c494ee6ad39beb0ce970a/config/clusters/earthscope/common.values.yaml#L29" target="_blank" rel="noopener" >EarthScope&amp;rsquo;s approach&lt;/a> to handling authentication tokens. Both communities need to pass OAuth tokens into user environments so their SDKs can access protected data - and MAAP adapted EarthScope&amp;rsquo;s pattern to fit their needs.&lt;/p>
&lt;p>This is the kind of peer-to-peer knowledge sharing we hope to foster with our
&lt;a href="https://github.com/2i2c-org/infrastructure" target="_blank" rel="noopener" >open infrastructure model&lt;/a>. When infrastructure is open and communities can see each other&amp;rsquo;s solutions, they can adapt and build on proven approaches rather than starting from scratch.&lt;/p>
&lt;h2 id="learn-more">
Learn more
&lt;a class="header-anchor" href="#learn-more">#&lt;/a>
&lt;/h2>&lt;ul>
&lt;li>
&lt;a href="https://github.com/2i2c-org/infrastructure/pull/7068" target="_blank" rel="noopener" >MAAP&amp;rsquo;s PR&lt;/a> adapting the configuration&lt;/li>
&lt;li>
&lt;a href="https://github.com/2i2c-org/infrastructure/blob/0046e14a68d7af9e353c494ee6ad39beb0ce970a/config/clusters/earthscope/common.values.yaml#L29" target="_blank" rel="noopener" >EarthScope&amp;rsquo;s original config&lt;/a>&lt;/li>
&lt;li>
&lt;a href="https://github.com/2i2c-org/infrastructure" target="_blank" rel="noopener" >Our infrastructure repository&lt;/a> where all community configurations live&lt;/li>
&lt;/ul>
&lt;h2 id="acknowledgments">
Acknowledgments
&lt;a class="header-anchor" href="#acknowledgments">#&lt;/a>
&lt;/h2>&lt;ul>
&lt;li>
&lt;a href="https://ops.maap-project.org/" target="_blank" rel="noopener" >MAAP team&lt;/a> for adapting and contributing this configuration&lt;/li>
&lt;li>
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/earthscope/" >EarthScope Consortium&lt;/a> for the original implementation&lt;/li>
&lt;/ul></description></item><item><title>Refactoring Jupyter Book 2 documentation ahead of a major release</title><link>https://deploy-preview-608--2i2c-org.netlify.app/blog/jupyter-book-docs-refactor/</link><pubDate>Sat, 01 Nov 2025 00:00:00 +0000</pubDate><guid>https://deploy-preview-608--2i2c-org.netlify.app/blog/jupyter-book-docs-refactor/</guid><description>&lt;p>Documentation is what turns open source code into products that people actually want to use. We recently spent a few days refactoring the
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/jupyter-book/" >Jupyter Book&lt;/a> documentation to prepare for the upcoming Jupyter Book 2 release, and we&amp;rsquo;re excited about how much clearer the docs have become!&lt;/p>
&lt;h2 id="what-we-did">
What we did
&lt;a class="header-anchor" href="#what-we-did">#&lt;/a>
&lt;/h2>&lt;p>We restructured the docs using the
&lt;a href="https://diataxis.fr/" target="_blank" rel="noopener" >Diataxis framework&lt;/a> to better organize content by user type and task:&lt;/p>
&lt;ul>
&lt;li>Reorganized into clear topic areas with landing pages for easier navigation&lt;/li>
&lt;li>Added missing content like the feature voting table and contributing guides&lt;/li>
&lt;li>Created upgrade guidance to help users understand the relationship between Jupyter Book 2 and MyST&lt;/li>
&lt;/ul>
&lt;p>This work helps users find what they need faster and gives the project a stronger foundation to build on going forward.&lt;/p>
&lt;h2 id="why-were-excited-about-it">
Why we&amp;rsquo;re excited about it
&lt;a class="header-anchor" href="#why-were-excited-about-it">#&lt;/a>
&lt;/h2>&lt;p>Better documentation reduces maintainer burden by helping users answer their own questions, and it makes the project more welcoming and useful to new contributors. We hope this makes Jupyter Book more accessible to everyone and lays a good foundation for the new release!&lt;/p>
&lt;p>We&amp;rsquo;re also excited because so many others helped provide edits and comments!&lt;/p>
&lt;h2 id="learn-more">
Learn more
&lt;a class="header-anchor" href="#learn-more">#&lt;/a>
&lt;/h2>&lt;ul>
&lt;li>
&lt;a href="https://github.com/jupyter-book/jupyter-book/pull/2422" target="_blank" rel="noopener" >PR implementing the refactor&lt;/a>&lt;/li>
&lt;li>
&lt;a href="https://github.com/jupyter-book/jupyter-book/blob/next/docs/contribute/docs.md" target="_blank" rel="noopener" >Documentation principles we developed&lt;/a>&lt;/li>
&lt;li>
&lt;a href="https://next.jupyterbook.org" target="_blank" rel="noopener" >Jupyter Book 2 documentation&lt;/a>&lt;/li>
&lt;/ul>
&lt;h2 id="acknowledgements">
Acknowledgements
&lt;a class="header-anchor" href="#acknowledgements">#&lt;/a>
&lt;/h2>&lt;ul>
&lt;li>Thanks to
&lt;a href="https://github.com/rlanzafame" target="_blank" rel="noopener" >@rlanzafame&lt;/a>,
&lt;a href="https://github.com/FreekPols" target="_blank" rel="noopener" >@FreekPols&lt;/a>, and
&lt;a href="https://github.com/bsipocz" target="_blank" rel="noopener" >@bsipocz&lt;/a> for their helpful reviews, edits, and feedback on the PR!&lt;/li>
&lt;li>
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/pythia/" >Project Pythia&lt;/a>,
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/cryocloud/" >CryoCloud&lt;/a>,
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/nasa-open-science/" >NASA Open Science / ScienceCore&lt;/a>, and the Berkeley educational projects are our primary member communities using MyST and
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/jupyter-book/" >Jupyter Book&lt;/a>. Their support covers the cost of these kinds of foundational contributions.&lt;/li>
&lt;/ul></description></item><item><title>2i2c Supports the Science Platforms Coordination IHDEA Working Group</title><link>https://deploy-preview-608--2i2c-org.netlify.app/blog/ihdea-working-group/</link><pubDate>Thu, 30 Oct 2025 00:00:00 +0000</pubDate><guid>https://deploy-preview-608--2i2c-org.netlify.app/blog/ihdea-working-group/</guid><description>&lt;p>The Science Platforms Coordination IHDEA working group (which includes our own
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/author/jim-colliander/" >Jim Colliander&lt;/a>) is developing international standard software computing environments for Heliophysics. The working group recently presented their work at two major conferences:
&lt;a href="https://ml-helio.github.io/" target="_blank" rel="noopener" >ML-Helio&lt;/a> in Madrid and
&lt;a href="https://dash2025.space.swri.edu/" target="_blank" rel="noopener" >DASH/IHDEA&lt;/a> in San Antonio.&lt;/p>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="DASH conference logo featuring stylized text and heliophysics imagery" srcset="
/blog/ihdea-working-group/featured_hu27c4fd91eab23a43f3d74f7a504ce6e6_9358_17cce6b6bb18d114e8ad08af1e9ab0a8.webp 400w,
/blog/ihdea-working-group/featured_hu27c4fd91eab23a43f3d74f7a504ce6e6_9358_b6f840d8644d32a3a097fd4261692307.webp 760w,
/blog/ihdea-working-group/featured_hu27c4fd91eab23a43f3d74f7a504ce6e6_9358_1200x1200_fit_q75_h2_lanczos_3.webp 1200w"
src="https://deploy-preview-608--2i2c-org.netlify.app/blog/ihdea-working-group/featured_hu27c4fd91eab23a43f3d74f7a504ce6e6_9358_17cce6b6bb18d114e8ad08af1e9ab0a8.webp"
width="400"
height="123"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;em>The DASH/IHDEA 2025 conference brings together the heliophysics community to advance data, analysis, and software standards&lt;/em>&lt;/p>
&lt;p>When the working group received $2k from NASA SMCE for cloud infrastructure, they were already member organizations of 2i2c. This meant we could quickly stand up a
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/jupyterhub/" >JupyterHub&lt;/a> with their Heliophysics-tailored environments for the conferences:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Easy access&lt;/strong> - Shared password authentication for conference attendees&lt;/li>
&lt;li>&lt;strong>Persistent storage&lt;/strong> - Work saved across sessions&lt;/li>
&lt;li>&lt;strong>Serious compute&lt;/strong> - Up to 119 GB RAM and 15 CPUs (much more than a typical laptop!)&lt;/li>
&lt;/ul>
&lt;p>The team successfully demonstrated how cloud resources can enable computational work that laptops simply can&amp;rsquo;t handle, and conference attendees responded positively to the presentations.&lt;/p>
&lt;h2 id="why-were-excited-about-this">
Why we&amp;rsquo;re excited about this
&lt;a class="header-anchor" href="#why-were-excited-about-this">#&lt;/a>
&lt;/h2>&lt;p>This showcases a key benefit we want to create with 2i2c membership: &lt;strong>reducing the accidental complexity of leveraging the cloud&lt;/strong>. Because the working group was already a member organization, deploying and managing infrastructure for the conferences was straightforward once they secured cloud funding. No lengthy setup, no new contracts - just quick deployment of the tools they needed.&lt;/p>
&lt;h2 id="learn-more">
Learn more
&lt;a class="header-anchor" href="#learn-more">#&lt;/a>
&lt;/h2>&lt;ul>
&lt;li>
&lt;a href="https://ml-helio.github.io/" target="_blank" rel="noopener" >ML-Helio Conference&lt;/a> - Machine learning in heliophysics&lt;/li>
&lt;li>
&lt;a href="https://dash2025.space.swri.edu/" target="_blank" rel="noopener" >DASH/IHDEA Conference&lt;/a> - Data, analysis, and software in heliophysics&lt;/li>
&lt;/ul>
&lt;h2 id="acknowledgements">
Acknowledgements
&lt;a class="header-anchor" href="#acknowledgements">#&lt;/a>
&lt;/h2>&lt;ul>
&lt;li>NASA SMCE for providing $2k funding and AWS infrastructure&lt;/li>
&lt;li>Shawn Polson for being the community champion leading this effort&lt;/li>
&lt;li>The IHDEA working group for their collaborative partnership in advancing Heliophysics research infrastructure&lt;/li>
&lt;/ul></description></item><item><title>BIDS joins as 2i2c's first premier member organization</title><link>https://deploy-preview-608--2i2c-org.netlify.app/blog/bids-premier-member/</link><pubDate>Wed, 29 Oct 2025 00:00:00 +0000</pubDate><guid>https://deploy-preview-608--2i2c-org.netlify.app/blog/bids-premier-member/</guid><description>&lt;p>We&amp;rsquo;re thrilled to announce that the
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/bids/" >Berkeley Institute for Data Science (BIDS)&lt;/a> has joined as 2i2c&amp;rsquo;s first premier member organization! This partnership marks a significant milestone in our sustainability strategy and recognizes a relationship that&amp;rsquo;s been central to 2i2c&amp;rsquo;s story from the very beginning.&lt;/p>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="Kirstie Whitaker and Chris Holdgraf discussing the partnership at Berkeley on October 16, 2025" srcset="
/blog/bids-premier-member/featured_hu9acfdf60efa1473443bb55ddfe64b6ad_408900_2bd6cf429c4fe43d940e1939fc49ccd2.webp 400w,
/blog/bids-premier-member/featured_hu9acfdf60efa1473443bb55ddfe64b6ad_408900_e717758424849bad3d2ef9c4052e363a.webp 760w,
/blog/bids-premier-member/featured_hu9acfdf60efa1473443bb55ddfe64b6ad_408900_1200x1200_fit_q75_h2_lanczos.webp 1200w"
src="https://deploy-preview-608--2i2c-org.netlify.app/blog/bids-premier-member/featured_hu9acfdf60efa1473443bb55ddfe64b6ad_408900_2bd6cf429c4fe43d940e1939fc49ccd2.webp"
width="760"
height="428"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;em>BIDS Executive Director Kirstie Whitaker and 2i2c Executive Director Chris Holdgraf discuss the partnership at the
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/blog/bids-premier-member/../bids-premier-membership-event/" >membership launch event&lt;/a>.&lt;/em>&lt;/p>
&lt;h2 id="what-this-partnership-means">
What this partnership means
&lt;a class="header-anchor" href="#what-this-partnership-means">#&lt;/a>
&lt;/h2>&lt;p>As our &lt;strong>founding premier member&lt;/strong>, BIDS is financially supporting 2i2c while helping us design our member network services and relationships. Together, we&amp;rsquo;ll work on:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Co-designing member services&lt;/strong> - BIDS will provide feedback and guidance as we develop how our member network operates&lt;/li>
&lt;li>&lt;strong>Technical collaboration&lt;/strong> - Partnering on JupyterHub development, cloud infrastructure improvements, and other open source projects&lt;/li>
&lt;li>&lt;strong>Strategic input&lt;/strong> - Advising on 2i2c&amp;rsquo;s direction and approach to strengthening open source communities&lt;/li>
&lt;/ul>
&lt;p>This gives us a foundation for both technical and social collaboration, and we hope it opens doors to deeper partnerships across the Berkeley community.&lt;/p>
&lt;blockquote class="pull-quote">
&lt;p>Berkeley has long been a leader in open source software development. This partnership lets us share our knowledge and support community development of open source infrastructure across institutions.&lt;/p>
&lt;p>&lt;cite>&lt;a href="https://www.linkedin.com/in/kirstiewhitaker" target="_blank" rel="noopener" >Kirstie Whitaker&lt;/a>, BIDS Executive Director&lt;/cite>&lt;/p>
&lt;/blockquote>
&lt;h2 id="why-were-excited-about-this">
Why we&amp;rsquo;re excited about this
&lt;a class="header-anchor" href="#why-were-excited-about-this">#&lt;/a>
&lt;/h2>&lt;p>&lt;strong>For open source:&lt;/strong>
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/bids/" >BIDS&lt;/a> has been a leader in supporting open source and cross-disciplinary open science for many years - helping to shape projects like NumPy, scikit-image, NetworkX, and
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/jupyterhub/" >JupyterHub&lt;/a>. Their feedback and partnership will help us improve our impact across the entire ecosystem.&lt;/p>
&lt;p>&lt;strong>For sustainability:&lt;/strong> This is the first paying member of our new
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/join/" >membership model&lt;/a>, which is a key part of our long-term sustainability strategy. It demonstrates that organizations value what we&amp;rsquo;re building and want to invest in shared open source infrastructure.&lt;/p>
&lt;p>&lt;strong>For 2i2c:&lt;/strong>
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/bids/" >BIDS&lt;/a> has been part of our story from the beginning, and this partnership recognizes the continuing influence and support we&amp;rsquo;ve received from the organization.&lt;/p>
&lt;h2 id="learn-more">
Learn more
&lt;a class="header-anchor" href="#learn-more">#&lt;/a>
&lt;/h2>&lt;p>Read the full announcements from our partners:&lt;/p>
&lt;ul>
&lt;li>👉
&lt;a href="https://cdss.berkeley.edu/news/berkeley-institute-data-science-partners-2i2c-open-source-infrastructure" target="_blank" rel="noopener" >CDSS press release: Berkeley Institute for Data Science Partners with 2i2c&lt;/a>&lt;/li>
&lt;li>👉
&lt;a href="https://bids.berkeley.edu/news/shaping-future-open-source-2i2c-and-bids" target="_blank" rel="noopener" >BIDS press release: Shaping the Future of Open Source: 2i2c and BIDS&lt;/a>&lt;/li>
&lt;/ul>
&lt;h2 id="acknowledgements">
Acknowledgements
&lt;a class="header-anchor" href="#acknowledgements">#&lt;/a>
&lt;/h2>&lt;ul>
&lt;li>The
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/bids/" >Berkeley Institute for Data Science&lt;/a> and the entire BIDS team&lt;/li>
&lt;li>
&lt;a href="https://cdss.berkeley.edu/" target="_blank" rel="noopener" >UC Berkeley&amp;rsquo;s College of Computing, Data Science, and Society&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>NASA Openscapes mentors run airborne data machine learning workshop with 401 participants from 68 countries</title><link>https://deploy-preview-608--2i2c-org.netlify.app/blog/openscapes-workshop/</link><pubDate>Thu, 23 Oct 2025 00:00:00 +0000</pubDate><guid>https://deploy-preview-608--2i2c-org.netlify.app/blog/openscapes-workshop/</guid><description>&lt;p>NASA Openscapes mentors recently hosted a workshop attended by 401 participants from 68 countries to learn how to use airborne data and machine learning for environmental research!&lt;/p>
&lt;p>They gave participants computational environments on a community hub managed by 2i2c to teach skills in data science like image classification with airborne spectroscopy and accessing data from NASA JPL
&lt;a href="https://www.earthdata.nasa.gov/data/projects/aviris" target="_blank" rel="noopener" >AVIRIS-NG data&lt;/a> from Earthdata cloud.&lt;/p>
&lt;p>We&amp;rsquo;re proud to enable participants from all over the world to easily access standardized compute and NASA Earthdata data in the cloud for a seamless learning experience.&lt;/p>
&lt;h2 id="learn-more">
Learn more
&lt;a class="header-anchor" href="#learn-more">#&lt;/a>
&lt;/h2>&lt;p>👉 Read more at
&lt;a href="https://openscapes.org/blog/2025-09-30-ornl-arset-workshop/" target="_blank" rel="noopener" >openscapes.org/blog/2025-09-30-ornl-arset-workshop/&lt;/a>&lt;/p>
&lt;h2 id="acknowledgements">
Acknowledgements
&lt;a class="header-anchor" href="#acknowledgements">#&lt;/a>
&lt;/h2>&lt;ul>
&lt;li>
&lt;p>Thank you to the
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/openscapes/" >Openscapes&lt;/a> team for sharing this post with us, and&lt;/p>
&lt;ul>
&lt;li>Michele Thornton&lt;/li>
&lt;li>Rupesh Shrestha&lt;/li>
&lt;/ul>
&lt;p>for authoring the blog post.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>NASA Openscapes mentors for running a great workshop&lt;/p>
&lt;/li>
&lt;/ul></description></item><item><title>A thank you to CZI for its impact on 2i2c and Jupyter</title><link>https://deploy-preview-608--2i2c-org.netlify.app/blog/czi-retrospective/</link><pubDate>Wed, 22 Oct 2025 00:00:00 +0000</pubDate><guid>https://deploy-preview-608--2i2c-org.netlify.app/blog/czi-retrospective/</guid><description>&lt;p>As I attend the
&lt;a href="https://chanzuckerberg.com/science/programs-resources/open-science/" target="_blank" rel="noopener" >CZI Open Science&lt;/a> 2025 meeting, it’s a good moment to reflect on the many ways CZI has positively impacted both 2i2c and the Jupyter Project.&lt;/p>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="" srcset="
/blog/czi-retrospective/featured_hu4b15a9956c47a7ddfe5d0ed882b19b9a_35602_30c247421127bb5bc16d8121c23671f7.webp 400w,
/blog/czi-retrospective/featured_hu4b15a9956c47a7ddfe5d0ed882b19b9a_35602_c07168ca25e6e809f75147ae9cb02a3c.webp 760w,
/blog/czi-retrospective/featured_hu4b15a9956c47a7ddfe5d0ed882b19b9a_35602_1200x1200_fit_q75_h2_lanczos_3.webp 1200w"
src="https://deploy-preview-608--2i2c-org.netlify.app/blog/czi-retrospective/featured_hu4b15a9956c47a7ddfe5d0ed882b19b9a_35602_30c247421127bb5bc16d8121c23671f7.webp"
width="760"
height="421"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;p>The funders who support organizations like 2i2c and Jupyter have a difficult task. In the day-to-day work of building open infrastructure, it’s easy to focus on the next challenge or grant, and lose sight of the cumulative, long-term impact of strategic support. This post is an attempt to pause and celebrate that impact.&lt;/p>
&lt;p>CZI has played a unique role in the open source and open science ecosystem since its creation. It has taken an approach to funding and coalition-building that has genuinely changed how many think about supporting open source. Their model has driven an incredible amount of impact, and I&amp;rsquo;m very grateful for our collaboration.&lt;/p>
&lt;p>Here are a few ways their support has stood out.&lt;/p>
&lt;p>&lt;em>This was collected quickly, so please let us know of other ways we may have missed! And most importantly, we&amp;rsquo;re only trying to gather a high level view here, so we&amp;rsquo;re including many efforts where all the work was led by teams and organizations &lt;em>other&lt;/em> than 2i2c/Jupyter. The
&lt;a href="https://jupyter.org" target="_blank" rel="noopener" >Jupyter Community&lt;/a> has many leaders that are part of this effort as well.&lt;/em>&lt;/p>
&lt;h2 id="strengthening-the-foundations-of-jupyter">
Strengthening the foundations of Jupyter
&lt;a class="header-anchor" href="#strengthening-the-foundations-of-jupyter">#&lt;/a>
&lt;/h2>&lt;p>Through its Essential Open Source Software for Science (EOSS) program, CZI has funded several initiatives in the
&lt;a href="https://jupyter.org" target="_blank" rel="noopener" >Jupyter ecosystem&lt;/a> that have strengthened the project in foundational ways. Here are a few that stand out:&lt;/p>
&lt;p>&lt;strong>JupyterHub&amp;rsquo;s Contributor in Residence:&lt;/strong> Allowed JupyterHub to
&lt;a href="https://blog.jupyter.org/lessons-learned-from-jupyters-contributor-in-residence-pilot-427e2b361a7b" target="_blank" rel="noopener" >explore a new maintenance and community support model&lt;/a> and support maintainer growth. Georgiana&amp;rsquo;s journey from this program to becoming 2i2c&amp;rsquo;s first engineer shows how CZI&amp;rsquo;s investment in people creates lasting impact.&lt;/p>
&lt;p>&lt;strong>Community Strategic Lead:&lt;/strong> Focused on
&lt;a href="https://chanzuckerberg.com/eoss/proposals/jupyterhub-community-strategic-lead/" target="_blank" rel="noopener" >diversity, equity, and inclusion at a strategic level&lt;/a>. This created space for us to rethink &lt;em>how&lt;/em> we build our teams to be more accessible and equitable. It helped us create pathways for underrepresented groups to become community leaders and led to a key partnership with
&lt;a href="https://book.the-turing-way.org/" target="_blank" rel="noopener" >The Turing Way&lt;/a>.&lt;/p>
&lt;p>&lt;strong>Real-Time Collaboration:&lt;/strong> Built the foundation for
&lt;a href="https://chanzuckerberg.com/eoss/proposals/real-time-collaboration-in-jupyter/" target="_blank" rel="noopener" >collaborative notebook editing&lt;/a>, which is very useful for remote scientific collaboration. This was complex technical work that involved collaboration with many stakeholders. It laid a foundation that Jupyter continues to build upon, and may facilitate AI-based workflows in unexpected ways.&lt;/p>
&lt;p>&lt;strong>Jupyter Accessibility:&lt;/strong> Funded key improvements in
&lt;a href="https://jupyter-accessibility.readthedocs.io/en/latest/funding/czi-grant-roadmap.html" target="_blank" rel="noopener" >accessibility for JupyterLab and the broader Jupyter stack&lt;/a>, including WCAG compliance, automated testing, and documentation. This was one of the first times an open source community received significant support for accessibility and internationalization, highlighting CZI&amp;rsquo;s leadership.&lt;/p>
&lt;p>They also enabled a wide variety of contributions throughout the Jupyter ecosystem that can be traced back to the capacity that CZI&amp;rsquo;s funding provided for core support alongside broader initiatives.&lt;/p>
&lt;h2 id="enabling-2i2c-to-grow-from-an-idea-to-an-organization">
Enabling 2i2c to grow from an idea to an organization
&lt;a class="header-anchor" href="#enabling-2i2c-to-grow-from-an-idea-to-an-organization">#&lt;/a>
&lt;/h2>&lt;p>CZI also played a key role in 2i2c&amp;rsquo;s birth, growth, direction, and impact. When 2i2c was only an idea, the possibily of initial support from CZI was pivotal in helping us turn it into a reality. Then as the organization took shape and started to grow, this support gave us the strategic capacity to develop key frameworks for
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/blog/czi-retrospective/../../2025/good-citizen/" >healthy open source contribution practices&lt;/a>,
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/blog/czi-retrospective/../../2024/value-proposition/" >our value propositions&lt;/a>, and ideas around
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/blog/czi-retrospective/../../2024/funding-community-networks/" >community network funding&lt;/a>. It was a stepping stone towards building out our own
&lt;a href="https://2i2c.org/join" target="_blank" rel="noopener" >sustainability model via membership&lt;/a>.&lt;/p>
&lt;p>Here are a few milestone moments:&lt;/p>
&lt;p>&lt;strong>Our Seed funding (2020)&lt;/strong> CZI provided core support to bootstrap 2i2c from its inception, funding organizational capacity rather than just technical deliverables. This was critical, enabling strategic partnerships, community coordination, and 2i2c&amp;rsquo;s first hires (Georgiana Dolocan, formerly the CZI-funded
&lt;a href="https://blog.jupyter.org/the-jupyterhub-and-binder-contributor-in-residence-56708d1e3069" target="_blank" rel="noopener" >JupyterHub Contributor in Residence&lt;/a>, and Chris Holdgraf, 2i2c&amp;rsquo;s Executive Director). This was the primary funding that drove our creation and operations for the first three years. We
&lt;a href="https://2i2c.org/report-czi-2021" target="_blank" rel="noopener" >published a comprehensive report and retrospective&lt;/a> documenting the impact of this seed funding.&lt;/p>
&lt;p>&lt;strong>Catalyzing Global Communities (2022)&lt;/strong> This collaborative grant brought together six organizations (2i2c, The Carpentries, CSCCE, IOI, MetaDocencia, Open Life Science) to
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/blog/czi-retrospective/../../2022/czi-global-communities-proposal/" >provide cloud infrastructure and training for communities in Latin America and Africa&lt;/a>. The project emphasized &amp;ldquo;train the trainers&amp;rdquo; approaches and community co-leadership. It was a much bigger challenge than we all realized, and the relationships between our organizations grew stronger as a result.&lt;/p>
&lt;p>&lt;strong>Strategic Support for Sustainability (2024)&lt;/strong> CZI provided a
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/blog/czi-retrospective/../../2024/funding-czi/" >bridge funding gift to sustain 2i2c&amp;rsquo;s mission&lt;/a> during a critical growth phase. This gave us the runway to refine our service model and explore paths to financial sustainability. Combined with funding from
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/blog/czi-retrospective/../../2024/funding-navigation/" >The Navigation Fund&lt;/a>, this gave 2i2c approximately two years for strategic planning.&lt;/p>
&lt;h3 id="what-makes-czis-approach-different">
What Makes CZI&amp;rsquo;s Approach Different?
&lt;a class="header-anchor" href="#what-makes-czis-approach-different">#&lt;/a>
&lt;/h3>&lt;p>Here are a few things that have stood out to me about CZI&amp;rsquo;s unique approach to funding:&lt;/p>
&lt;p>&lt;strong>Funding the foundation of open infrastructure:&lt;/strong> Through its EOSS program, CZI recognized that science was building on open source infrastructure that was often under-supported. Explicitly targeting that foundation demonstrated the need to fund core technology, not just new innovation.&lt;/p>
&lt;p>&lt;strong>Funding communities, not just code:&lt;/strong> CZI made efforts to support projects that invested in social infrastructure, recognizing that building open source is a deeply social process that needs social skills and capacity to succeed.&lt;/p>
&lt;p>&lt;strong>Funding connections in a network:&lt;/strong> CZI took a network approach, actively building connections &lt;em>between&lt;/em> its grantees. It flew us together annually for its open science meeting, made targeted efforts for collaborative grants, and connected grantees to work together.&lt;/p>
&lt;p>&lt;strong>Actively growing that network:&lt;/strong> CZI made clear efforts to bring in new participants, particularly from communities in Latin America and Africa, and was thoughtful about respecting the agency and leadership of these communities.&lt;/p>
&lt;p>&lt;strong>Developing its own expertise and understanding:&lt;/strong> CZI also &lt;em>builds its own tooling&lt;/em>, often in partnership with open source projects. This gives its team empathy for our challenges and a deeper institutional understanding of the open source world, leading to more impactful contributions.&lt;/p>
&lt;h2 id="thank-you-czi">
Thank You, CZI
&lt;a class="header-anchor" href="#thank-you-czi">#&lt;/a>
&lt;/h2>&lt;p>We&amp;rsquo;re profoundly grateful to CZI for their support for 2i2c, Jupyter, and the broader open source ecosystem. Their investments have enabled Jupyter to serve millions of scientists more effectively, allowed 2i2c to grow from an idea to the organization it is today, and enabled contributions that benefit the entire open science ecosystem.&lt;/p>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="" srcset="
/blog/czi-retrospective/chris-fernando_huf9bfa379e9f41692b17413d59fb58130_29702_d8ba5a84493280f946c84c1ef523b4eb.webp 400w,
/blog/czi-retrospective/chris-fernando_huf9bfa379e9f41692b17413d59fb58130_29702_aa6fe1d6a482e250f2326a9902fb437e.webp 760w,
/blog/czi-retrospective/chris-fernando_huf9bfa379e9f41692b17413d59fb58130_29702_1200x1200_fit_q75_h2_lanczos.webp 1200w"
src="https://deploy-preview-608--2i2c-org.netlify.app/blog/czi-retrospective/chris-fernando_huf9bfa379e9f41692b17413d59fb58130_29702_d8ba5a84493280f946c84c1ef523b4eb.webp"
width="293"
height="220"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;p>Thanks, CZI, for all the work you&amp;rsquo;ve done!&lt;/p></description></item><item><title>A helpful contribution to our JupyterHub SSH README from OpenScapes</title><link>https://deploy-preview-608--2i2c-org.netlify.app/blog/openscapes-readme-contribution/</link><pubDate>Tue, 21 Oct 2025 00:00:00 +0000</pubDate><guid>https://deploy-preview-608--2i2c-org.netlify.app/blog/openscapes-readme-contribution/</guid><description>&lt;p>We love when collaborators contribute back to the tools we maintain! Andy Teucher from
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/openscapes/" >OpenScapes&lt;/a> recently
&lt;a href="https://github.com/yuvipanda/jupyter-sshd-proxy/pull/11" target="_blank" rel="noopener" >fixed a documentation issue&lt;/a> in &lt;code>jupyter-sshd-proxy&lt;/code> that benefits everyone using the tool.&lt;/p>
&lt;p>
&lt;a href="https://github.com/yuvipanda/jupyter-sshd-proxy" target="_blank" rel="noopener" >&lt;code>jupyter-sshd-proxy&lt;/code>&lt;/a> is a tool originally created by Yuvi to help 2i2c communities connect to their JupyterHub instances via SSH. Andy ran into an issue when using it with the VS Code fork that uses the
&lt;a href="https://github.com/jeanp413/open-remote-ssh" target="_blank" rel="noopener" >&lt;code>open-remote-ssh&lt;/code>&lt;/a> extension - it failed unless double quotes were used around the authorization token in the &lt;code>ProxyCommand&lt;/code>.&lt;/p>
&lt;p>Through experimentation, Andy figured out the fix and
&lt;a href="https://github.com/yuvipanda/jupyter-sshd-proxy/pull/11" target="_blank" rel="noopener" >contributed it back to the README&lt;/a>. Now everyone using this tool will have clearer documentation.&lt;/p>
&lt;p>While small, we think this is a nice example of a
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/blog/foundational-contributions/" >&amp;ldquo;Foundational contributions&amp;rdquo;&lt;/a> from a community:&lt;/p>
&lt;ul>
&lt;li>2i2c creates and maintains open source tools to help our communities&lt;/li>
&lt;li>Our communities use those tools and run into issues&lt;/li>
&lt;li>They debug, figure out solutions, and contribute improvements back&lt;/li>
&lt;li>Everyone benefits from the improvements&lt;/li>
&lt;/ul>
&lt;p>This is exactly how we want 2i2c to help our communities - by making it easy for them to contribute back to the ecosystem and strengthen the tools everyone relies on.&lt;/p>
&lt;h2 id="acknowledgements">
Acknowledgements
&lt;a class="header-anchor" href="#acknowledgements">#&lt;/a>
&lt;/h2>&lt;ul>
&lt;li>Thanks to
&lt;a href="https://github.com/ateucher" target="_blank" rel="noopener" >Andy Teucher&lt;/a> for the contribution and debugging!&lt;/li>
&lt;li>Thanks to
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/openscapes/" >OpenScapes&lt;/a> for being great collaborators places where can work with people like Andy&lt;/li>
&lt;/ul></description></item><item><title>Communities learning from one another - Project Pythia and ICESat-2 Hackweeks</title><link>https://deploy-preview-608--2i2c-org.netlify.app/blog/pythia-icesat2-synergy/</link><pubDate>Tue, 21 Oct 2025 00:00:00 +0000</pubDate><guid>https://deploy-preview-608--2i2c-org.netlify.app/blog/pythia-icesat2-synergy/</guid><description>&lt;p>We wanted to share a short vignette about two of our communities learning from one another.&lt;/p>
&lt;p>At the latest
&lt;a href="https://docs.google.com/document/d/e/2PACX-1vQWQrgHs_G5XyNH5GTFYydH_woUZcyZibdxPUWLpqFUYs20WM93kdx5onwOaizC_3-tfnbreMNQbYAp/pub" target="_blank" rel="noopener" >Project Pythia community meeting&lt;/a>,
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/pythia/" >Project Pythia&lt;/a> met with representatives from
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/cryocloud/" >ICESat-2&lt;/a> to share learning about notebooks and cookbooks in educational settings.&lt;/p>
&lt;p>Anthony Arendt from UW&amp;rsquo;s eScience Institute shared how they&amp;rsquo;ve used educational notebooks in their hackweek programs. The discussion explored ways to improve cookbooks, especially for large collections that require different computational environments, sparking ideas about higher-level abstractions for organizing educational content. There is a lot of overlap in the needs and workflows of these communities, and we&amp;rsquo;re hopeful they can find ways to re-use one another&amp;rsquo;s ideas, content, and infrastructure.&lt;/p>
&lt;p>One of our service goals is to make it easier for our member communities to &lt;em>learn from one another&lt;/em> - using standardized tools and infrastructure means we can learn what works, what doesn&amp;rsquo;t, and collectively improve our workflows more quickly. We&amp;rsquo;re working on ways to encourage this kind of interaction in our member networks, so we wanted to celebrate this little win.&lt;/p>
&lt;h2 id="learn-more-about-these-communities">
Learn more about these communities
&lt;a class="header-anchor" href="#learn-more-about-these-communities">#&lt;/a>
&lt;/h2>&lt;ul>
&lt;li>
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/pythia/" >Project Pythia&lt;/a> - An educational resource for geoscience computing with open-source Python&lt;/li>
&lt;li>
&lt;a href="https://cookbooks.projectpythia.org/" target="_blank" rel="noopener" >Project Pythia Cookbooks&lt;/a> - Domain-specific example workflows for geoscience&lt;/li>
&lt;li>
&lt;a href="https://icesat-2.hackweek.io/" target="_blank" rel="noopener" >ICESat-2 Hackweeks&lt;/a> - Collaborative learning events combining tutorials, peer learning, and team projects&lt;/li>
&lt;/ul></description></item><item><title>TIL: A few ways to track web traffic for open source projects</title><link>https://deploy-preview-608--2i2c-org.netlify.app/blog/web-traffic-tracking-open-source/</link><pubDate>Sun, 19 Oct 2025 00:00:00 +0000</pubDate><guid>https://deploy-preview-608--2i2c-org.netlify.app/blog/web-traffic-tracking-open-source/</guid><description>&lt;p>Understanding how people discover and navigate your project&amp;rsquo;s web presence is valuable for open source communities, but there are a lot of options out there and many maintainers may not know about them. Recently Chris did some research to improve the web analytics for
&lt;a href="https://jupyter.org" target="_blank" rel="noopener" >Jupyter&lt;/a>, and learned about several options for tracking web traffic&lt;sup id="fnref:1">&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref">1&lt;/a>&lt;/sup>. Here&amp;rsquo;s a quick report of what stood out.&lt;/p>
&lt;h2 id="three-analytics-tools-we-found-helpful">
Three analytics tools we found helpful
&lt;a class="header-anchor" href="#three-analytics-tools-we-found-helpful">#&lt;/a>
&lt;/h2>&lt;p>&lt;strong>
&lt;a href="https://plausible.io/" target="_blank" rel="noopener" >Plausible.io&lt;/a>&lt;/strong> - A privacy-friendly, GDPR-compliant analytics service&lt;/p>
&lt;ul>
&lt;li>Clean interface with public dashboards (see
&lt;a href="https://plausible.io/jupyter.org" target="_blank" rel="noopener" >Jupyter&amp;rsquo;s dashboard&lt;/a>)&lt;/li>
&lt;li>Paid service but offers 15% discount for open source projects&lt;/li>
&lt;li>Cost scales with traffic volume. It can get expensive for a project as big as Jupyter!&lt;/li>
&lt;li>This is the service we ultimately ended up using&amp;hellip;&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>
&lt;a href="https://docs.readthedocs.com/platform/stable/traffic-analytics.html" target="_blank" rel="noopener" >ReadTheDocs Analytics&lt;/a>&lt;/strong> - Built-in traffic tracking for documentation sites&lt;/p>
&lt;ul>
&lt;li>Available as a free add-on for ReadTheDocs projects, it provides traffic data specific to documentation pages.&lt;/li>
&lt;li>There&amp;rsquo;s no additional cost if already using ReadTheDocs, though if you&amp;rsquo;re on a business plan you may need to pay for it.&lt;/li>
&lt;li>The analytics are a bit barebones, but quite useful for learning where your readers are navigating.&lt;/li>
&lt;li>Enable in &lt;code>Settings&lt;/code> &amp;gt; &lt;code>Addons&lt;/code> &amp;gt; &lt;code>Analytics&lt;/code>.&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>
&lt;a href="https://docs.github.com/en/repositories/viewing-activity-and-data-for-your-repository/viewing-traffic-to-a-repository" target="_blank" rel="noopener" >GitHub Repository Analytics&lt;/a>&lt;/strong> - Native analytics in GitHub.&lt;/p>
&lt;ul>
&lt;li>Shows clones, views, and referring sites. This is also fairly barebones, but it&amp;rsquo;s really useful to see who is actually looking at your repository.&lt;/li>
&lt;li>Free for all GitHub repositories.&lt;/li>
&lt;li>Access via &lt;code>Insights&lt;/code> &amp;gt; &lt;code>Traffic&lt;/code> on any repository.&lt;/li>
&lt;/ul>
&lt;h2 id="learn-more">
Learn more
&lt;a class="header-anchor" href="#learn-more">#&lt;/a>
&lt;/h2>&lt;ul>
&lt;li>
&lt;a href="https://github.com/jupyter/jupyter.github.io/issues/815" target="_blank" rel="noopener" >GitHub issue coordinating Jupyter&amp;rsquo;s analytics work&lt;/a>&lt;/li>
&lt;li>
&lt;a href="https://plausible.io/jupyter.org" target="_blank" rel="noopener" >Plausible.io public dashboard for jupyter.org&lt;/a> (this might be down for now, but we&amp;rsquo;re working to bring it back up)&lt;/li>
&lt;li>
&lt;a href="https://docs.readthedocs.com/platform/stable/traffic-analytics.html" target="_blank" rel="noopener" >ReadTheDocs Analytics documentation&lt;/a>&lt;/li>
&lt;li>
&lt;a href="https://docs.github.com/en/rest/metrics/traffic?apiVersion=2022-11-28" target="_blank" rel="noopener" >GitHub Traffic Analytics API&lt;/a>&lt;/li>
&lt;/ul>
&lt;h2 id="acknowledgements">
Acknowledgements
&lt;a class="header-anchor" href="#acknowledgements">#&lt;/a>
&lt;/h2>&lt;p>Thanks in particular to
&lt;a href="https://github.com/jasongrout" target="_blank" rel="noopener" >Jason Grout&lt;/a> from the
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/jupyter/" >Jupyter Executive Council&lt;/a> for collaborating on this investigation and helping test these tools.&lt;/p>
&lt;div class="footnotes" role="doc-endnotes">
&lt;hr>
&lt;ol>
&lt;li id="fn:1">
&lt;p>Chris has been
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/blog/web-traffic-tracking-open-source/../executive-council-updates/" >serving on the Jupyter Executive Council&lt;/a> as a
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/blog/web-traffic-tracking-open-source/../foundational-contributions/" >Foundational contribution&lt;/a>. This was related to that effort!&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;/ol>
&lt;/div></description></item><item><title>Fixing the mybinder.org usage analytics archive</title><link>https://deploy-preview-608--2i2c-org.netlify.app/blog/mybinder-analytics-fix/</link><pubDate>Tue, 14 Oct 2025 00:00:00 +0000</pubDate><guid>https://deploy-preview-608--2i2c-org.netlify.app/blog/mybinder-analytics-fix/</guid><description>&lt;p>The analytics archive at &lt;code>archive.analytics.mybinder.org&lt;/code> powers the
&lt;a href="https://hub.jupyter.org/binder-data/" target="_blank" rel="noopener" >mybinder.org usage dashboards&lt;/a> and provides a
&lt;a href="https://github.com/jupyterhub/binder-data" target="_blank" rel="noopener" >daily-published dataset&lt;/a> that researchers and communities use to understand how Binder is being used across different domains and scientific communities.&lt;/p>
&lt;p>While updating our
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/blog/mybinder-analytics-fix/../binder-report-q3/" >quarterly Binder impact report&lt;/a>, we discovered the archive index page had stopped updating. The analytics publisher was writing index files to temporary storage before uploading to Google Cloud Storage, but for some reason the upload step stopped working. We
&lt;a href="https://github.com/jupyterhub/mybinder.org-deploy/pull/3462" target="_blank" rel="noopener" >deployed a fix&lt;/a> that eliminates the temporary files entirely - the code now generates the HTML index as a string in memory and uploads directly.&lt;/p>
&lt;figure id="figure-the-mybinderorg-analytics-archivehttpsarchiveanalyticsmybinderorg-shows-a-list-of-daily-usage-reports-that-anybody-can-download">
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img src="./featured.png" alt="The [mybinder.org analytics archive](https://archive.analytics.mybinder.org) shows a list of daily usage reports that anybody can download." loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;figcaption>
The
&lt;a href="https://archive.analytics.mybinder.org" target="_blank" rel="noopener" >mybinder.org analytics archive&lt;/a> shows a list of daily usage reports that anybody can download.
&lt;/figcaption>&lt;/figure>
&lt;p>Fortunately, we didn&amp;rsquo;t lose any data! Thanks to some smart design decisions, the daily analytics files were being collected properly the entire time, only the index page listing them was broken. You can find
&lt;a href="https://archive.analytics.mybinder.org" target="_blank" rel="noopener" >the full archive here&lt;/a>.&lt;/p>
&lt;h2 id="learn-more">
Learn more
&lt;a class="header-anchor" href="#learn-more">#&lt;/a>
&lt;/h2>&lt;ul>
&lt;li>
&lt;a href="https://github.com/jupyterhub/mybinder.org-deploy/pull/3462" target="_blank" rel="noopener" >Pull request with the fix&lt;/a>&lt;/li>
&lt;li>
&lt;a href="https://hub.jupyter.org/binder-data/" target="_blank" rel="noopener" >mybinder.org usage dashboards&lt;/a>&lt;/li>
&lt;li>The
&lt;a href="https://github.com/jupyterhub/binder-data" target="_blank" rel="noopener" >&lt;code>binder-data/&lt;/code> repository&lt;/a> is where we aggregate and publish archive data to be more accessible.&lt;/li>
&lt;li>
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/blog/mybinder-analytics-fix/../binder-report-q3/" >Our quarterly impact report from mybinder.org&lt;/a>&lt;/li>
&lt;/ul>
&lt;h2 id="acknowledgements">
Acknowledgements
&lt;a class="header-anchor" href="#acknowledgements">#&lt;/a>
&lt;/h2>&lt;ul>
&lt;li>Thanks to the
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/jupyterhub/" >JupyterHub community&lt;/a> for their collaboration on mybinder.org infrastructure&lt;/li>
&lt;/ul></description></item><item><title>Impact report from 2i2c's Binder federation instance</title><link>https://deploy-preview-608--2i2c-org.netlify.app/blog/binder-report/</link><pubDate>Tue, 14 Oct 2025 00:00:00 +0000</pubDate><guid>https://deploy-preview-608--2i2c-org.netlify.app/blog/binder-report/</guid><description>&lt;p>The
&lt;a href="https://mybinder.org" target="_blank" rel="noopener" >mybinder.org&lt;/a> service provides reproducible and interactive computational environments for the open science community. It is financially supported by a
&lt;a href="https://mybinder.readthedocs.io/en/latest/about/federation.html" target="_blank" rel="noopener" >federation of BinderHubs&lt;/a>.
2i2c is part of the team that manages mybinder.org, and we&amp;rsquo;re committed to supporting this critical infrastructure for open science and reproducibility.&lt;/p>
&lt;p>We developed a more
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/blog/binder-report/../binder-singlenode/" >cost-efficient process for deploying BinderHub on a single VM&lt;/a> and are now running a BinderHub at
&lt;a href="https://2i2c.mybinder.org" target="_blank" rel="noopener" >2i2c.mybinder.org&lt;/a>.
This post highlights the impact we&amp;rsquo;ve had through our support of the mybinder.org federation, we&amp;rsquo;ll update it periodically.&lt;/p>
&lt;h2 id="usage-over-time">
Usage over time
&lt;a class="header-anchor" href="#usage-over-time">#&lt;/a>
&lt;/h2>&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="Binder launches" srcset="
/blog/binder-report/featured_hu0f9f1ae8d80fa109b602b80004fe12f0_156400_500d94ee4f680fb17b90cc257a1d0aeb.webp 400w,
/blog/binder-report/featured_hu0f9f1ae8d80fa109b602b80004fe12f0_156400_1994dbb0f258605eb79d6c1c0d66a1a4.webp 760w,
/blog/binder-report/featured_hu0f9f1ae8d80fa109b602b80004fe12f0_156400_1200x1200_fit_q75_h2_lanczos_3.webp 1200w"
src="https://deploy-preview-608--2i2c-org.netlify.app/blog/binder-report/featured_hu0f9f1ae8d80fa109b602b80004fe12f0_156400_500d94ee4f680fb17b90cc257a1d0aeb.webp"
width="760"
height="673"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;p>&lt;em>Here are weekly launches on mybinder.org. Launches from &lt;code>2i2c.mybinder.org&lt;/code> are in red. Source:
&lt;a href="https://hub.jupyter.org/binder-data/" target="_blank" rel="noopener" >mybinder analytics dashboard&lt;/a>.&lt;/em>&lt;/p>
&lt;p>&lt;strong>In Q1 of 2025&lt;/strong>, &lt;code>2i2c.mybinder.org&lt;/code> launched &lt;strong>417,048 reproducible sessions&lt;/strong>. In this time, mybinder.org was primarily driven by our
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/blog/binder-report/../binder-singlenode/" >new Hetzner node&lt;/a> as we worked with GESIS to stabilize their own BinderHub instance.&lt;/p>
&lt;p>&lt;strong>In Q2 of 2025&lt;/strong>, &lt;code>2i2c.mybinder.org&lt;/code> launched &lt;strong>249,750 reproducible sessions&lt;/strong>. In this time, we worked with
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/gesis/" >GESIS&lt;/a> to deploy their BinderHub instance on the same Hetzner node setup, which let us distribute more of Binder&amp;rsquo;s load onto them.&lt;/p>
&lt;p>&lt;strong>In Q3 of 2025&lt;/strong>, &lt;code>2i2c.mybinder.org&lt;/code> launched &lt;strong>118,083 reproducible sessions&lt;/strong>. We experienced a typical summer dip in sessions, had to
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/blog/binder-report/../mybinder-analytics-fix/" >fix the analytics dashboard&lt;/a> as well as
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/blog/binder-report/../mybinder-antiabuse-scanning/" >fix a TCP scanning abuse case&lt;/a> that briefly brought down the 2i2c node.&lt;/p>
&lt;h2 id="where-weve-made-improvements">
Where we&amp;rsquo;ve made improvements
&lt;a class="header-anchor" href="#where-weve-made-improvements">#&lt;/a>
&lt;/h2>&lt;p>As part of this effort, we&amp;rsquo;ve made several improvements to the Binder and JupyterHub ecosystem. Here are a few links where you can read more:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/blog/binder-report/../binder-singlenode/" >Deploying BinderHub on a single VM with k3s&lt;/a> - Our approach to making BinderHub deployment cheaper and simpler&lt;/li>
&lt;li>
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/blog/binder-report/../jetstream-binderhub/" >Hetzner cloud infrastructure experience&lt;/a> - Cost-effective cloud hosting for mybinder.org&lt;/li>
&lt;li>
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/blog/binder-report/../mybinder-antiabuse-scanning/" >Combating TCP scanning abuse on mybinder.org&lt;/a> - Developing anti-abuse tools to prevent an abuse use-case.&lt;/li>
&lt;li>
&lt;a href="https://hub.jupyter.org/binder-data/" target="_blank" rel="noopener" >Improving Binder&amp;rsquo;s usage dashboard&lt;/a> - This helps us create posts like these and is useful to others as well.&lt;/li>
&lt;li>
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/blog/binder-report/../../2024/jupyterhub-binderhub-gesis/" >Integrating BinderHub with JupyterHub&lt;/a> - Working with
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/gesis/" >GESIS&lt;/a> to bring Binder&amp;rsquo;s dynamic image building capabilities to persistent JupyterHubs, empowering users to manage their own environments&lt;/li>
&lt;/ul>
&lt;h2 id="acknowledgements">
Acknowledgements
&lt;a class="header-anchor" href="#acknowledgements">#&lt;/a>
&lt;/h2>&lt;p>This work is made possible by:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/gesis/" >GESIS&lt;/a> for their continued support as mybinder.org federation members&lt;/li>
&lt;li>The
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/jupyterhub/" >JupyterHub community&lt;/a> for collaboration and support&lt;/li>
&lt;li>Our
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/members/" >member communities&lt;/a> whose fees support this work&lt;/li>
&lt;/ul></description></item><item><title>Combating tcp scanning on mybinder.org with the tcpflowkiller</title><link>https://deploy-preview-608--2i2c-org.netlify.app/blog/mybinder-antiabuse-scanning/</link><pubDate>Wed, 08 Oct 2025 00:00:00 +0000</pubDate><guid>https://deploy-preview-608--2i2c-org.netlify.app/blog/mybinder-antiabuse-scanning/</guid><description>&lt;p>We&amp;rsquo;ve deployed a new tool to &lt;code>mybinder.org&lt;/code> that automatically detects and stops port scanning activity, helping us maintain service reliability while being responsible citizens of the internet.&lt;/p>
&lt;p>Port scanning is a common part of network-based exploits, and many server hosts prohibit this activity (including Hetzner, where the 2i2c &lt;code>mybinder.org&lt;/code> infrastructure lives). We developed a little tool called
&lt;a href="https://github.com/cryptnono/cryptnono/pull/46" target="_blank" rel="noopener" >tcpflowkiller&lt;/a> as part of the
&lt;a href="https://github.com/cryptnono/cryptnono" target="_blank" rel="noopener" >cryptnono&lt;/a> project (our anti-abuse set of tools for hosted JupyterHub and Binder infrastructure) to automatically kill processes that exhibit port scanning behavior. This reduces the likelihood of triggering our server host&amp;rsquo;s abuse policies and helps keep &lt;code>mybinder.org&lt;/code> running reliably.&lt;/p>
&lt;h2 id="why-this-matters">
Why this matters
&lt;a class="header-anchor" href="#why-this-matters">#&lt;/a>
&lt;/h2>&lt;p>As providers of public compute, it&amp;rsquo;s our responsibility to make sure people can&amp;rsquo;t use our infrastructure to abuse others. This is part of being responsible citizens of the internet. It also saves us time in dealing with outages because cloud providers (understandably) block access when they suspect there is abuse.&lt;/p>
&lt;p>Hetzner and similar hosts have many benefits (including
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/blog/mybinder-antiabuse-scanning/../binder-singlenode/" >significant cost savings&lt;/a>), and tools like tcpflowkiller help keep hubs and binders running smoothly on such hosts, which have different abuse policies than the big commercial cloud providers.&lt;/p>
&lt;p>AWS and other cloud providers have proprietary ways to combat abuse (like
&lt;a href="https://docs.aws.amazon.com/guardduty/latest/ug/what-is-guardduty.html" target="_blank" rel="noopener" >AWS GuardDuty&lt;/a>). We could have spent our time investing in developing rules there. Instead, contributing to cryptnono helps provide the same set of features in a cloud-agnostic way, in line with
&lt;a href="https://2i2c.org/open-practices/" target="_blank" rel="noopener" >our principles&lt;/a> of supporting open infrastructure that gives communities control over their infrastructure.&lt;/p>
&lt;p>This tool
&lt;a href="https://github.com/jupyterhub/mybinder.org-deploy/pull/3436" target="_blank" rel="noopener" >has now been deployed to mybinder.org&lt;/a>, and we&amp;rsquo;ll monitor its effectiveness over time. We may roll this out to 2i2c public BinderHubs in the future based on patterns we observe.&lt;/p>
&lt;h2 id="learn-more">
Learn more
&lt;a class="header-anchor" href="#learn-more">#&lt;/a>
&lt;/h2>&lt;ul>
&lt;li>
&lt;a href="https://github.com/cryptnono/cryptnono/pull/46" target="_blank" rel="noopener" >tcpflowkiller pull request&lt;/a>&lt;/li>
&lt;li>
&lt;a href="https://github.com/jupyterhub/mybinder.org-deploy/pull/3436" target="_blank" rel="noopener" >mybinder.org deployment&lt;/a>&lt;/li>
&lt;li>
&lt;a href="https://en.wikipedia.org/wiki/Port_scanner" target="_blank" rel="noopener" >Port scanning on Wikipedia&lt;/a>&lt;/li>
&lt;/ul>
&lt;h2 id="acknowledgements">
Acknowledgements
&lt;a class="header-anchor" href="#acknowledgements">#&lt;/a>
&lt;/h2>&lt;ul>
&lt;li>Thanks to
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/gesis/" >GESIS&lt;/a> for their continued support of &lt;code>mybinder.org&lt;/code> and to
&lt;a href="https://github.com/rgaiacs" target="_blank" rel="noopener" >Raniere Silva&lt;/a> for collaborating on this deployment with us.&lt;/li>
&lt;li>More reliable Binder infrastructure is also supported by
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/nasa-open-science/" >NASA Open Science / Science Core&lt;/a>, whose tutorials run on the opensci binders that depend on this same anti-abuse stack.&lt;/li>
&lt;/ul></description></item><item><title>TIL: GitHub Action secrets are only available from non-forked repositories</title><link>https://deploy-preview-608--2i2c-org.netlify.app/blog/github-action-secrets-forked-repositories/</link><pubDate>Wed, 08 Oct 2025 00:00:00 +0000</pubDate><guid>https://deploy-preview-608--2i2c-org.netlify.app/blog/github-action-secrets-forked-repositories/</guid><description>&lt;p>If you&amp;rsquo;ve worked with GitHub Actions in open source projects, you might encounter a hard-to-debug error where repository secrets are simply &lt;em>empty&lt;/em>. That&amp;rsquo;s probably because the PR is from a forked repository! Here&amp;rsquo;s a little learning we had after losing a bunch of time figuring this out:&lt;/p>
&lt;h2 id="our-pr-from-a-fork-was-using-empty-strings-for-repository-secrets">
Our PR from a fork was using empty strings for repository secrets
&lt;a class="header-anchor" href="#our-pr-from-a-fork-was-using-empty-strings-for-repository-secrets">#&lt;/a>
&lt;/h2>&lt;p>
&lt;a href="https://github.com/executablebooks/github-activity" target="_blank" rel="noopener" >&lt;code>github-activity&lt;/code>&lt;/a> is a tool we help maintain for
&lt;a href="https://github-activity.readthedocs.io/en/latest/#how-we-define-contributors-in-the-reports" target="_blank" rel="noopener" >generating changelogs from a wider variety of contributions&lt;/a> than GitHub&amp;rsquo;s defaults. We needed to set a secret to raise the API rate limits for the tool&amp;rsquo;s tests. These tests pull data from repositories outside of the &lt;code>github-activity&lt;/code> repository itself, which quickly hit GitHub&amp;rsquo;s rate limits without authentication.&lt;/p>
&lt;p>The problem seemed straightforward at first: we added the secret, but the workflow was acting as if the secret didn&amp;rsquo;t exist at all. After updating the code to explicitly check for empty strings, we discovered the authentication token was actually &lt;em>an empty string&lt;/em>, even though it had been set.&lt;/p>
&lt;p>After some debugging, we uncovered the root cause: &lt;strong>the PR was opened from a fork of &lt;code>github-activity&lt;/code>&lt;/strong>. GitHub intentionally
&lt;a href="https://docs.github.com/en/actions/how-tos/write-workflows/choose-what-workflows-do/use-secrets" target="_blank" rel="noopener" >makes secrets appear as empty strings when a PR originates from a forked repository&lt;/a>. This is a security measure to prevent unauthorized access to sensitive credentials.&lt;/p>
&lt;h2 id="a-quick-fix-re-open-the-pr-from-the-base-repository">
A quick fix: re-open the PR from the base repository
&lt;a class="header-anchor" href="#a-quick-fix-re-open-the-pr-from-the-base-repository">#&lt;/a>
&lt;/h2>&lt;p>The immediate fix was simple: re-open the PR from a branch in the base repository rather than from the fork. This worked perfectly, but it&amp;rsquo;s not a sustainable solution for open source projects that rely on community contributions from forks.
We don&amp;rsquo;t want to create a dynamic where maintainers have different PR workflows because they&amp;rsquo;re operating on the base repository.&lt;/p>
&lt;h2 id="how-use-secrets-with-forked-repositories-in-a-safe-ish-way">
How use secrets with forked repositories in a safe-ish way
&lt;a class="header-anchor" href="#how-use-secrets-with-forked-repositories-in-a-safe-ish-way">#&lt;/a>
&lt;/h2>&lt;p>If you need to make secrets available to PRs from forks, there are a few approaches we learned about, each with security trade-offs:&lt;/p>
&lt;h3 id="the-pull_request_target-workflow">
The &lt;code>pull_request_target&lt;/code> workflow
&lt;a class="header-anchor" href="#the-pull_request_target-workflow">#&lt;/a>
&lt;/h3>&lt;p>GitHub provides a
&lt;a href="https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/enabling-features-for-your-repository/managing-github-actions-settings-for-a-repository#controlling-changes-from-forks-to-workflows-in-public-repositories" target="_blank" rel="noopener" >&lt;code>pull_request_target&lt;/code> workflow&lt;/a> that can access secrets even when triggered by forked PRs. In this case, GitHub will &lt;strong>always run the test suite on &lt;code>main&lt;/code>&lt;/strong>, instead of any changes your PR introduces.&lt;/p>
&lt;p>&lt;strong>Why this is dangerous&lt;/strong>: malicious actors could add &lt;em>code&lt;/em> to a PR that exfiltrates your secrets (for example, Python code that prints &lt;code>os.environ[&amp;quot;MY_SECRET&amp;quot;]&lt;/code>).&lt;/p>
&lt;p>As a result, &lt;strong>only use secrets that you&amp;rsquo;re OK with being public&lt;/strong>. In this case, we generated a read-only token with restricted permissions. However, this is still kinda risky so use at your own peril.&lt;/p>
&lt;p>If your repository workflows &lt;em>require&lt;/em> a secret that &lt;em>absolutely cannot be public&lt;/em> (e.g., a publishing key for a package repository), try a method like the following:&lt;/p>
&lt;h3 id="using-github-environments-for-granular-control">
Using GitHub Environments for granular control
&lt;a class="header-anchor" href="#using-github-environments-for-granular-control">#&lt;/a>
&lt;/h3>&lt;p>A safer approach is to use
&lt;a href="https://docs.github.com/en/actions/how-tos/deploy/configure-and-manage-deployments/manage-environments" target="_blank" rel="noopener" >GitHub Environments&lt;/a>, which let you restrict which secrets are available to specific jobs. This way, you can ensure that only non-critical secrets (like those needed for testing) are available to jobs that run on forked PRs, while keeping sensitive secrets (like PyPI publishing tokens) restricted to trusted contexts.&lt;/p>
&lt;p>This is the approach we implemented in &lt;code>github-activity&lt;/code>, and it provides a good balance between security and community contribution workflows. We created a separate environment for publishing to PyPI so that its secret is never available to the job that runs with &lt;code>pull_request_target&lt;/code>.&lt;/p>
&lt;h2 id="we-hope-this-saves-you-time">
We hope this saves you time!
&lt;a class="header-anchor" href="#we-hope-this-saves-you-time">#&lt;/a>
&lt;/h2>&lt;p>Hopefully this learning is useful to others who run into the same confusing behavior. We&amp;rsquo;ve added a few improvements to &lt;code>github-activity&lt;/code> to more reliably check for empty strings to surface this kind of condition, but knowing the basic behavior of GitHub environments and forked PRs is even better.&lt;/p>
&lt;h2 id="learn-more">
Learn more
&lt;a class="header-anchor" href="#learn-more">#&lt;/a>
&lt;/h2>&lt;ul>
&lt;li>
&lt;a href="https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/enabling-features-for-your-repository/managing-github-actions-settings-for-a-repository#controlling-changes-from-forks-to-workflows-in-public-repositories" target="_blank" rel="noopener" >GitHub documentation on controlling changes from forks to workflows&lt;/a>&lt;/li>
&lt;li>
&lt;a href="https://docs.github.com/en/actions/how-tos/deploy/configure-and-manage-deployments/manage-environments" target="_blank" rel="noopener" >GitHub Environments for deployment&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>Enabling transparent cloud cost monitoring with user-level dashboards</title><link>https://deploy-preview-608--2i2c-org.netlify.app/blog/cloud-cost-monitoring/</link><pubDate>Tue, 30 Sep 2025 00:00:00 +0000</pubDate><guid>https://deploy-preview-608--2i2c-org.netlify.app/blog/cloud-cost-monitoring/</guid><description>&lt;p>We are excited to announce that &lt;strong>dashboards to monitor cloud usage and costs at a per-user level&lt;/strong> are now available! See the
&lt;a href="https://docs.2i2c.org/admin/monitoring/cost-users" target="_blank" rel="noopener" >cost monitoring documentation&lt;/a> for more information.&lt;/p>
&lt;p>A key goal of 2i2c is to make the cloud safe for science. By providing transparent cost monitoring, we give communities the confidence that they won&amp;rsquo;t face unexpected bills and can better understand how their usage patterns translate to cloud costs. This visibility is especially valuable in our shared platform model, where each community gets their own independent hub while benefiting from shared infrastructure expertise.&lt;/p>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="Cloud cost monitoring dashboard showing user-level usage and cost breakdowns" srcset="
/blog/cloud-cost-monitoring/featured_huf9d99e2c2d9f92e6fb1ca11e35925122_105209_ad88b7920c8a8ef63cb6031d96b8917d.webp 400w,
/blog/cloud-cost-monitoring/featured_huf9d99e2c2d9f92e6fb1ca11e35925122_105209_cb20ec3b020712afb2b8d73e53f13db8.webp 760w,
/blog/cloud-cost-monitoring/featured_huf9d99e2c2d9f92e6fb1ca11e35925122_105209_1200x1200_fit_q75_h2_lanczos_3.webp 1200w"
src="https://deploy-preview-608--2i2c-org.netlify.app/blog/cloud-cost-monitoring/featured_huf9d99e2c2d9f92e6fb1ca11e35925122_105209_ad88b7920c8a8ef63cb6031d96b8917d.webp"
width="760"
height="427"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;p>The user-level cost breakdown allows communities to identify individual usage trends and manage their resources more effectively. Communities can now see exactly how their computational work translates to cloud spending, enabling better resource planning and budget management.&lt;/p>
&lt;a href="https://docs.google.com/forms/d/e/1FAIpQLSff-u-sWFuwO1-VTgk2Ir7f1nfUUlLevQk_Vkk_jnmcI1nJnw/viewform?usp=pp_url&amp;amp;entry.648332035=https://deploy-preview-608--2i2c-org.netlify.app/blog/cloud-cost-monitoring/" target="_blank" rel="noopener" class="text-decoration-none">
&lt;div class="alert alert-info d-flex align-items-start p-3" role="button" style="transition: all 0.2s ease; box-shadow: 0 2px 4px rgba(0,0,0,0.1);" onmouseover="this.style.backgroundColor='#b3e5fc'; this.style.boxShadow='0 4px 8px rgba(0,0,0,0.15)'; this.style.transform='translateY(-1px)'" onmouseout="this.style.backgroundColor=''; this.style.boxShadow='0 2px 4px rgba(0,0,0,0.1)'; this.style.transform='translateY(0)'" onfocus="this.style.backgroundColor='#b3e5fc'; this.style.boxShadow='0 4px 8px rgba(0,0,0,0.15)'; this.style.transform='translateY(-1px)'" onblur="this.style.backgroundColor=''; this.style.boxShadow='0 2px 4px rgba(0,0,0,0.1)'; this.style.transform='translateY(0)'">
&lt;div class="fw-bold mb-1">&lt;span style="font-weight:bold">Give us feedback!&lt;/span> Click here to provide feedback that will help us make this more impactful.&lt;/div>
&lt;/div>
&lt;/a>
&lt;h2 id="learn-more">
Learn more
&lt;a class="header-anchor" href="#learn-more">#&lt;/a>
&lt;/h2>&lt;ul>
&lt;li>
&lt;a href="https://docs.2i2c.org/admin/monitoring/cost-users" target="_blank" rel="noopener" >Cost monitoring documentation&lt;/a>&lt;/li>
&lt;/ul>
&lt;h2 id="acknowledgements">
Acknowledgements
&lt;a class="header-anchor" href="#acknowledgements">#&lt;/a>
&lt;/h2>&lt;ul>
&lt;li>Tarashish @
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/devseed/" >Development Seed&lt;/a> for working on this with us.&lt;/li>
&lt;li>
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/nasa-veda/" >NASA VEDA&lt;/a> for funding much of this work.&lt;/li>
&lt;li>Andy @
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/openscapes/" >Openscapes&lt;/a>, Alex @ Development Seed and Sarah @
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/earthscope/" >Earthscope&lt;/a> for giving us close feedback.&lt;/li>
&lt;/ul></description></item><item><title>From scattered effort to strategic impact: How we're systematizing our Foundational open source contributions</title><link>https://deploy-preview-608--2i2c-org.netlify.app/blog/foundational-contributions/</link><pubDate>Fri, 26 Sep 2025 00:00:00 +0000</pubDate><guid>https://deploy-preview-608--2i2c-org.netlify.app/blog/foundational-contributions/</guid><description>&lt;p>Over the past year we&amp;rsquo;ve experimented with being more strategic about supporting upstream communities &lt;em>as a team&lt;/em>. This post summarizes our current plan, including team targets and practices we&amp;rsquo;ll continue to pilot. We&amp;rsquo;ll revisit this as we learn more.&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>Note&lt;/strong>: This document is about the &lt;em>Foundational&lt;/em> contributions we make so that open source communities are healthier and more impactful. It is not about &lt;em>Directed&lt;/em> upstream contributions we make as part of our own product work. See
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/blog/good-citizen/" >On being a good open source citizen: supporting a healthy ecosystem through directed and foundational contributions&lt;/a>.&lt;/p>
&lt;/blockquote>
&lt;h2 id="the-challenge-why-scattered-individual-efforts-arent-enough">
The challenge: Why scattered individual efforts aren&amp;rsquo;t enough
&lt;a class="header-anchor" href="#the-challenge-why-scattered-individual-efforts-arent-enough">#&lt;/a>
&lt;/h2>&lt;p>Healthy open source communities rely on both individual and institutional contributions.
2i2c
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/blog/good-citizen/" >aims to be an &lt;em>excellent &amp;ldquo;upstream citizen&amp;rdquo;&lt;/em>&lt;/a>, so we need a structured approach with clear goals and rationale for why it&amp;rsquo;s the best use of our team&amp;rsquo;s time.&lt;/p>
&lt;p>Without a coordinated approach, we risk two problematic outcomes:&lt;/p>
&lt;p>&lt;strong>Best case&lt;/strong>: Scattered, individual efforts that are subject to the
&lt;a href="https://www.jofreeman.com/joreen/tyranny.htm" target="_blank" rel="noopener" >Tyranny of Structurelessness&lt;/a>. We help at the margins but not meaningfully.&lt;/p>
&lt;p>&lt;strong>Worst case&lt;/strong>: Our organizational capacity inadvertently dominates communities, making 2i2c the sole stakeholder capable of meaningful development and maintenance. We &lt;em>functionally take over the project&lt;/em>.&lt;/p>
&lt;p>By setting explicit goals, both our member communities and upstream projects can hold us accountable for actions that strengthen rather than undermine community health.&lt;/p>
&lt;h2 id="our-long-term-goal-multi-stakeholder-resilient-communities">
Our long-term goal: Multi-stakeholder, resilient communities
&lt;a class="header-anchor" href="#our-long-term-goal-multi-stakeholder-resilient-communities">#&lt;/a>
&lt;/h2>&lt;p>With this in mind, we&amp;rsquo;ve chosen the following &lt;em>outcomes&lt;/em> as our major goals for upstream contribution:&lt;/p>
&lt;blockquote>
&lt;p>We want the Jupyter&lt;sup id="fnref:1">&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref">1&lt;/a>&lt;/sup> community to be a &lt;em>multi-stakeholder&lt;/em>&lt;sup id="fnref:2">&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref">2&lt;/a>&lt;/sup>, &lt;em>diverse&lt;/em>&lt;sup id="fnref:3">&lt;a href="#fn:3" class="footnote-ref" role="doc-noteref">3&lt;/a>&lt;/sup> community with a very high
&lt;a href="https://en.wikipedia.org/wiki/Bus_factor" target="_blank" rel="noopener" >&lt;em>bus factor&lt;/em>&lt;/a>, because we believe this is a critical pre-requisite for advancing
&lt;a href="https://compass.2i2c.org/organization/mission/" target="_blank" rel="noopener" >our mission and value proposition&lt;/a>.&lt;/p>
&lt;/blockquote>
&lt;p>We want to build team processes that help upstream communities make progress towards this goal, so everyone can equitably participate with the support they need.&lt;/p>
&lt;h2 id="two-key-objectives">
Two key objectives
&lt;a class="header-anchor" href="#two-key-objectives">#&lt;/a>
&lt;/h2>&lt;p>Starting with
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/jupyterhub/" >JupyterHub&lt;/a>, we&amp;rsquo;ve identified two objectives that will guide our work:&lt;/p>
&lt;style>
blockquote {
font-size: 1.4em;
}
&lt;/style>
&lt;blockquote>
&lt;p>&lt;strong>Objective 1&lt;/strong>: Increase the number of casual but returning contributors to the JupyterHub community&lt;/p>
&lt;p>&lt;strong>Objective 2&lt;/strong>: Increase the number of total maintainers in the JupyterHub community&lt;/p>
&lt;/blockquote>
&lt;p>We&amp;rsquo;ve chosen these objectives because (1) they have impact, (2) we can make meaningful progress on them, and (3) we can integrate this work into our team&amp;rsquo;s workflow.&lt;/p>
&lt;p>For each activity below, we&amp;rsquo;ve brainstormed some Key Performance Indicators (KPIs) to track progress and ensure we&amp;rsquo;re learning effectively.&lt;/p>
&lt;h2 id="four-pilot-activities">
Four pilot activities
&lt;a class="header-anchor" href="#four-pilot-activities">#&lt;/a>
&lt;/h2>&lt;p>We&amp;rsquo;ll experiment with these four activities&lt;sup id="fnref:4">&lt;a href="#fn:4" class="footnote-ref" role="doc-noteref">4&lt;/a>&lt;/sup>:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="#review-prs" >&lt;strong>Review pull requests from non-maintainers&lt;/strong>&lt;/a>&lt;/li>
&lt;li>
&lt;a href="#issue-triage" >&lt;strong>Issue Triage office hours&lt;/strong>&lt;/a>&lt;/li>
&lt;li>
&lt;a href="#mentoring-maintainers" >&lt;strong>Sponsoring and Mentoring new Maintainers&lt;/strong>&lt;/a>&lt;/li>
&lt;li>
&lt;a href="#release-diversity" >&lt;strong>Increase bus factor and diversity of people making releases&lt;/strong>&lt;/a>&lt;/li>
&lt;/ul>
&lt;h3 id="review-prs">
Review Pull Requests from non-maintainers
&lt;a class="header-anchor" href="#review-prs">#&lt;/a>
&lt;/h3>&lt;p>Imagine two different scenarios:&lt;/p>
&lt;ol>
&lt;li>You casually contribute a PR to some OSS project. Someone responds the next day, you have a pleasant back and forth, and it gets merged (or rejected) within a few days.&lt;/li>
&lt;li>You casually contribute a PR to some OSS project. Nobody responds for a year. Eventually someone leaves a comment. You have forgotten everything, and don&amp;rsquo;t even respond. Much later, your PR gets closed as stale.&lt;/li>
&lt;/ol>
&lt;p>Which experience will encourage you to come back and contribute again?&lt;/p>
&lt;p>It&amp;rsquo;s clearly (1). We should use our institutional capacity to bring the community closer to (1).&lt;/p>
&lt;p>We&amp;rsquo;ll accomplish this by including the following work item in every sprint:&lt;/p>
&lt;blockquote>
&lt;p>&lt;code>Review of N PRs by non-maintainers of JupyterHub&lt;/code>&lt;/p>
&lt;/blockquote>
&lt;p>We will build skills (via pairing, training, etc) inside 2i2c, as not everyone will feel comfortable reviewing pull requests for all projects, nor have rights to merge or close PRs. We may also do additional work like new contributor drives, better documentation, and policy advocacy. We will include pull requests of all types, not just code contributions.&lt;/p>
&lt;h4 id="kpis">
KPIs
&lt;a class="header-anchor" href="#kpis">#&lt;/a>
&lt;/h4>&lt;p>We imagine two KPIs for this activity:&lt;/p>
&lt;ol>
&lt;li>Number of PRs merged (or closed) through our sprint planning activity.&lt;/li>
&lt;li>Number of &lt;em>returning&lt;/em> contributors whose PRs were reviewed by us.&lt;/li>
&lt;/ol>
&lt;h3 id="issue-triage">
Issue Triage office hours
&lt;a class="header-anchor" href="#issue-triage">#&lt;/a>
&lt;/h3>&lt;p>Issue Triage involves combing through an upstream repository&amp;rsquo;s issue tracker, engaging with new issues, refining them to be actionable, and signal boosting important ones for team action.
This is hard for newcomers, as it often requires deep knowledge of various components to understand how to direct an issue or refine it.
It&amp;rsquo;s also challenging for team members still learning open source community dynamics. We&amp;rsquo;d like to upskill our team members within 2i2c and our upstream open source communities.&lt;/p>
&lt;p>As part of our sprints, we will run regular &amp;ldquo;Issue Triage&amp;rdquo; office hours.
We&amp;rsquo;ll begin by upskilling our &lt;em>own 2i2c team members&lt;/em> in effective issue triaging. We&amp;rsquo;ll then explore opening issue triage sessions to the broader upstream community.&lt;/p>
&lt;h4 id="kpis-1">
KPIs
&lt;a class="header-anchor" href="#kpis-1">#&lt;/a>
&lt;/h4>&lt;ol>
&lt;li>Number of issues triaged by 2i2c team members.&lt;sup id="fnref:5">&lt;a href="#fn:5" class="footnote-ref" role="doc-noteref">5&lt;/a>&lt;/sup>&lt;/li>
&lt;/ol>
&lt;h3 id="mentoring-maintainers">
Sponsoring and Mentoring new Maintainers
&lt;a class="header-anchor" href="#mentoring-maintainers">#&lt;/a>
&lt;/h3>&lt;p>OSS communities must grow their &lt;em>contributors&lt;/em> into &lt;em>maintainers&lt;/em>, or they will die.&lt;/p>
&lt;figure id="figure-xkcd-comic-about-dependency">
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;a href="https://xkcd.com/2347/" target="_blank" rel="noopener">&lt;img src="https://imgs.xkcd.com/comics/dependency.png" alt="XKCD comic about dependency" loading="lazy" />&lt;/a>&lt;/div>
&lt;/div>&lt;figcaption>
XKCD comic about dependency
&lt;/figcaption>&lt;/figure>
&lt;p>Growing new maintainers takes time and effort from both the potential maintainer and existing maintainers who mentor and sponsor them. The focus on sponsorship is important, as
&lt;a href="https://larahogan.me/blog/what-sponsorship-looks-like/" target="_blank" rel="noopener" >laid out by Lara Hogan&lt;/a>. This work takes years, not months, to manifest.&lt;/p>
&lt;p>We will build structures to identify potential maintainers and create pathways for them to gain maintainership status. As JupyterHub lacks an explicit maintainer pathway, we will build our own process via these focus areas:&lt;/p>
&lt;ol>
&lt;li>Identifying potential candidates for maintainership&lt;/li>
&lt;li>Identifying potential community work they can do to help get involved (contributing bug fixes, code reviewing, issue triage, helping answer questions, contributing code / documentation, release management, etc)&lt;/li>
&lt;li>Build pathways for candidates to do (2) as appropriate.&lt;/li>
&lt;li>Iteratively continue until candidates have done &amp;rsquo;enough&amp;rsquo; work to gain maintainership status.&lt;/li>
&lt;/ol>
&lt;p>This work is nebulous but worthwhile. We will coordinate this effort closely with community leaders, recognizing it takes time to actualize.&lt;/p>
&lt;p>In the Jupyter community, maintainership status is tied to individuals, not to organizations they work for. Nobody should get maintainership status &lt;em>simply&lt;/em> because they work for a specific organization (such as 2i2c). We should look for diverse candidates, ideally funded by different organizations, who are &lt;em>interested&lt;/em> in becoming maintainers.&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>Note&lt;/strong>: We&amp;rsquo;d also like to start with individuals
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/" >in our &lt;strong>collaborator network&lt;/strong>&lt;/a>. For example, we&amp;rsquo;re using an engagement between
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/nasa-veda/" >NASA VEDA&lt;/a> and
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/devseed/" >Development Seed&lt;/a> to onboard several team members into these projects.&lt;/p>
&lt;/blockquote>
&lt;h4 id="kpi">
KPI
&lt;a class="header-anchor" href="#kpi">#&lt;/a>
&lt;/h4>&lt;p>This measurement moves slowly, but is very clearly impactful:&lt;/p>
&lt;ol>
&lt;li>Number of people who have become maintainers due to our concerted efforts.&lt;/li>
&lt;/ol>
&lt;h3 id="release-diversity">
Increase bus factor and diversity of people making releases
&lt;a class="header-anchor" href="#release-diversity">#&lt;/a>
&lt;/h3>&lt;p>Making releases is often thankless but important to community health. It involves coordinating testing, writing changelogs, and providing upgrade instructions. Institutions can help by dedicating team time to perform this task regularly. To advance the &amp;lsquo;multi-stakeholder&amp;rsquo; and &amp;lsquo;high bus factor&amp;rsquo; aspects of our goal, we will have many different people do releases, via mentorship and sponsorship. This will integrate into our regular workstreams.&lt;/p>
&lt;h4 id="kpis-2">
KPIs
&lt;a class="header-anchor" href="#kpis-2">#&lt;/a>
&lt;/h4>&lt;ol>
&lt;li>Number of releases performed by 2i2c engineers&lt;/li>
&lt;li>Number of releases performed by others with sponsorship / mentorship from 2i2c engineers&lt;/li>
&lt;/ol>
&lt;h2 id="criteria-for-upstream-projects-to-support">
Criteria for upstream projects to support
&lt;a class="header-anchor" href="#criteria-for-upstream-projects-to-support">#&lt;/a>
&lt;/h2>&lt;p>Our long-term goal applies to upstream communities that:&lt;/p>
&lt;ol>
&lt;li>We strategically &lt;em>depend&lt;/em> on to serve
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/members/" >our member communities&lt;/a> as part of
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/platform/" >our community hub service&lt;/a>&lt;/li>
&lt;li>We &lt;em>need&lt;/em> to help sustain, given upstream community dynamics&lt;/li>
&lt;li>We have the &lt;em>ability&lt;/em> to help sustain&lt;/li>
&lt;/ol>
&lt;p>For example, Kubernetes satisfies (1) but not (2) or (3), while JupyterLab meets (1) and (2) but not (3) (presently). Currently this policy only applies to JupyterHub, but may change as our organization evolves.&lt;/p>
&lt;h2 id="how-well-implement-this">
How we&amp;rsquo;ll implement this
&lt;a class="header-anchor" href="#how-well-implement-this">#&lt;/a>
&lt;/h2>
&lt;h3 id="who-is-responsible">
Who is responsible
&lt;a class="header-anchor" href="#who-is-responsible">#&lt;/a>
&lt;/h3>&lt;p>Implementation is the responsibility of
&lt;a href="https://compass.2i2c.org/product-and-services/" target="_blank" rel="noopener" >2i2c&amp;rsquo;s Product &amp;amp; Services team&lt;/a>. These activities must integrate into the team&amp;rsquo;s daily practices, not become an external shadow process for some members.&lt;/p>
&lt;h3 id="how-well-fund-this-work">
How we&amp;rsquo;ll fund this work
&lt;a class="header-anchor" href="#how-well-fund-this-work">#&lt;/a>
&lt;/h3>&lt;p>Foundational upstream support requires significant work and expertise. We plan to fund this through:&lt;/p>
&lt;ul>
&lt;li>Fees from
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/members/" >our member communities&lt;/a>. A percentage of our membership fees includes covering the cost of Foundational contributions like this.&lt;/li>
&lt;li>Targeted contributions from
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/" >some of our collaborators&lt;/a>. Some collaborators have funds and want to support open source at a foundational level, in some cases we use funds from these collaborators to cover our costs.&lt;/li>
&lt;/ul>
&lt;p>We still need to explore what these efforts cost and mechanisms to recover those costs.&lt;/p>
&lt;h2 id="next-step-learning-in-public">
Next step: Learning in public
&lt;a class="header-anchor" href="#next-step-learning-in-public">#&lt;/a>
&lt;/h2>&lt;p>We&amp;rsquo;re excited to experiment with more effective upstream contribution and eager to learn. We&amp;rsquo;ll share our experiences so others can learn from and comment on our process.&lt;/p>
&lt;h2 id="acknowledgements">
Acknowledgements
&lt;a class="header-anchor" href="#acknowledgements">#&lt;/a>
&lt;/h2>&lt;ul>
&lt;li>
&lt;a href="https://github.com/minrk" target="_blank" rel="noopener" >@MinRK&lt;/a> and -
&lt;a href="https://github.com/bsipocz" target="_blank" rel="noopener" >@bsipocz&lt;/a> for helping review a draft of this!&lt;/li>
&lt;li>
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/author/chris-holdgraf/" >@choldgraf&lt;/a> for feedback, guidance, and editing for this post and the team practices in it.&lt;/li>
&lt;li>
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/jupyterhub/" >JupyterHub&lt;/a>,
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/jupyter-book/" >JupyterBook&lt;/a>, and
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/jupyter/" >Project Jupyter&lt;/a> for teaching us a lot about open source over the years.&lt;/li>
&lt;/ul>
&lt;div class="footnotes" role="doc-endnotes">
&lt;hr>
&lt;ol>
&lt;li id="fn:1">
&lt;p>Currently this is particularly JupyterHub and Jupyter-wide leadership. We&amp;rsquo;re
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/blog/jb-for-communities/" >exploring how to incorporate JupyterBook into our service&lt;/a> and are thus investing Foundation contributions there as well.&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;li id="fn:2">
&lt;p>With different kinds and sizes of organizations (companies, non-profits, universities, etc) and individuals being stakeholders. We want to avoid a single organization monopolizing power within any community.&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;li id="fn:3">
&lt;p>Across the power spectrum - from users to bug reporters to casual contributors to maintainers to people on governance duty&amp;#160;&lt;a href="#fnref:3" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;li id="fn:4">
&lt;p>&lt;strong>Implementation note&lt;/strong>: We will not start doing &lt;strong>all&lt;/strong> these immediately! We will consult with the rest of the team, and start these 1 at a time so we can build these processes sustainably and equitably.&amp;#160;&lt;a href="#fnref:4" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;li id="fn:5">
&lt;p>This requires a definition of &amp;ldquo;an issue that has been triaged&amp;rdquo;, and to our knowledge no such definition exists. We&amp;rsquo;d like to learn how to measure something abstract like &amp;ldquo;issue triage&amp;rdquo; - perhaps it is something specific putting it on a board for further action or applying a label, or something more abstract like &amp;ldquo;increasing how clear and actionable the issue is&amp;rdquo;. We&amp;rsquo;ll explore this when we start to make progress towards this objective.&amp;#160;&lt;a href="#fnref:5" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;/ol>
&lt;/div></description></item><item><title>Updates from Chris' position on the Jupyter Executive Council and Foundation Board</title><link>https://deploy-preview-608--2i2c-org.netlify.app/blog/executive-council-updates/</link><pubDate>Tue, 23 Sep 2025 00:00:00 +0000</pubDate><guid>https://deploy-preview-608--2i2c-org.netlify.app/blog/executive-council-updates/</guid><description>&lt;p>This is a running blog post for Chris to share out community updates from his time on the
&lt;a href="https://ec.jupyter.org/" target="_blank" rel="noopener" >Jupyter Executive Council&lt;/a>. See
&lt;a href="#context" >context for this page&lt;/a>.&lt;/p>
&lt;h2 id="updates-for-the-jupyter-community-from-chris">
Updates for the Jupyter community from Chris
&lt;a class="header-anchor" href="#updates-for-the-jupyter-community-from-chris">#&lt;/a>
&lt;/h2>&lt;p>Chris aims to write monthly updates for Jupyter&amp;rsquo;s community in the
&lt;a href="https://discourse.jupyter.org/c/governance/executive-council/51" target="_blank" rel="noopener" >Jupyter Community Forum&lt;/a> to share his perspective on what the council is up to. We&amp;rsquo;ll update this index post as new posts are available.&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://discourse.jupyter.org/t/chris-update-for-september-october-november-2025-wow-three-months-passed/38204" target="_blank" rel="noopener" >November 2025&lt;/a>&lt;/li>
&lt;li>
&lt;a href="https://discourse.jupyter.org/t/chris-update-for-august-2025-community-proposals-are-live/37879" target="_blank" rel="noopener" >August 2025&lt;/a>&lt;/li>
&lt;li>
&lt;a href="https://discourse.jupyter.org/t/chris-update-for-july-2025-towards-community-led-funding-proposals/37424/2" target="_blank" rel="noopener" >July 2025&lt;/a>&lt;/li>
&lt;li>
&lt;a href="https://discourse.jupyter.org/t/chris-jec-and-board-experience-for-june-2025/36488/1" target="_blank" rel="noopener" >June 2025&lt;/a>&lt;/li>
&lt;li>
&lt;a href="https://discourse.jupyter.org/t/chris-update-for-may-2025-a-few-funding-discussions-from-the-jupyter-foundation-board/35764/3" target="_blank" rel="noopener" >May 2025&lt;/a>&lt;/li>
&lt;/ul>
&lt;h2 id="blog-posts-about-chris-experience-on-the-executive-council">
Blog posts about Chris&amp;rsquo; experience on the executive council
&lt;a class="header-anchor" href="#blog-posts-about-chris-experience-on-the-executive-council">#&lt;/a>
&lt;/h2>&lt;p>Chris blogs now and then to share his thoughts, important announcements, and provide major updates from his perspective on the executive council. Here are the posts that have come out of this effort.&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://blog.jupyter.org/your-ideas-our-support-jupyter-community-call-for-funding-proposals-f4642590ae76?source=collection_home_page----95916e268740-----0-----------------------------------" target="_blank" rel="noopener" >Your Ideas, Our Support: Jupyter Community Call For Funding Proposals&lt;/a>&lt;/li>
&lt;li>
&lt;a href="https://chrisholdgraf.com/blog/fund-systems-not-developmend" target="_blank" rel="noopener" >Why open source foundations try to fund systems, not development&lt;/a> - May 31, 2025&lt;/li>
&lt;li>
&lt;a href="https://chrisholdgraf.com/blog/more-contributors" target="_blank" rel="noopener" >Jupyter can align the needs of its community and its foundation by enabling contribution&lt;/a> - Mar 22, 2025&lt;/li>
&lt;li>
&lt;a href="https://chrisholdgraf.com/blog/jupyter-org-structure" target="_blank" rel="noopener" >The relationship between the Jupyter Executive Council, Software Steering Council, and Foundation&lt;/a> - Mar 02, 2025&lt;/li>
&lt;li>
&lt;a href="https://chrisholdgraf.com/blog/os-support" target="_blank" rel="noopener" >Ways the Jupyter Foundation could support open source projects&lt;/a> - Feb 26, 2025&lt;/li>
&lt;li>
&lt;a href="https://chrisholdgraf.com/blog/jec" target="_blank" rel="noopener" >Running for the Jupyter Executive Council&lt;/a> - Jan 14, 2025&lt;/li>
&lt;/ul>
&lt;h2 id="2i2cs-commitment-to-supporting-open-source-communities">
2i2c&amp;rsquo;s commitment to supporting open source communities
&lt;a class="header-anchor" href="#2i2cs-commitment-to-supporting-open-source-communities">#&lt;/a>
&lt;/h2>&lt;p>In early 2025, Chris was
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/blog/jupyter-executive-council/" >elected to the Jupyter Executive Council&lt;/a>.
We&amp;rsquo;re tracking these efforts because providing leadership and community support to open source projects is a
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/blog/good-citizen/" >key Foundational contribution&lt;/a> we wish to make for open source projects. 2i2c makes time for team members to contribute upstream in strategic ways like this as part of our
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/open-practices/" >commitment to open practices&lt;/a>. However, this kind of work is very difficult to track! This blog post is an attempt at putting these efforts into one place for us to track and for others to discover.&lt;/p>
&lt;h2 id="acknowledgements">
Acknowledgements
&lt;a class="header-anchor" href="#acknowledgements">#&lt;/a>
&lt;/h2>&lt;ul>
&lt;li>
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/members/" >2i2c&amp;rsquo;s member communities&lt;/a> support
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/blog/good-citizen/" >Foundation open source contributions&lt;/a> like this with their membership fees.&lt;/li>
&lt;li>
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/navigation/" >The Navigation Fund&lt;/a> provides strategic funding support for 2i2c which covers major open source leadership contributions like this.&lt;/li>
&lt;/ul></description></item><item><title>Incident report: UC Merced user throttling during class startup</title><link>https://deploy-preview-608--2i2c-org.netlify.app/blog/incident-ucmerced-user-throttling/</link><pubDate>Tue, 16 Sep 2025 00:00:00 +0000</pubDate><guid>https://deploy-preview-608--2i2c-org.netlify.app/blog/incident-ucmerced-user-throttling/</guid><description>&lt;p>On August 29, 2025 our cloud infrastructure team experienced an incident with the UC Merced community hub when students tried to login simultaneously at the start of class. For more detailed technical information about this incident, see our
&lt;a href="https://github.com/2i2c-org/incident-reports/blob/main/reports/2025-08-29-ucmerced-too-many-users-throttled.pdf" target="_blank" rel="noopener" >full incident report&lt;/a>.&lt;/p>
&lt;h2 id="what-happened">
What happened
&lt;a class="header-anchor" href="#what-happened">#&lt;/a>
&lt;/h2>&lt;ul>
&lt;li>Students experienced issues when trying to login to the hub at the same time during the start of class.&lt;/li>
&lt;li>The concurrent spawn limit was reached quickly due to the large number of users starting up simultaneously.&lt;/li>
&lt;li>New nodes had to be brought up by the autoscaler, which took roughly 10 minutes from start to end.&lt;/li>
&lt;li>Users who tried again after 1 minute weren&amp;rsquo;t guaranteed to get their servers started immediately since new nodes were still spinning up.&lt;/li>
&lt;li>This was an &amp;ldquo;expected&amp;rdquo; scale-up event but the lack of clear messaging caused users to interpret it as instability.&lt;/li>
&lt;/ul>
&lt;h2 id="what-we-learned">
What we learned
&lt;a class="header-anchor" href="#what-we-learned">#&lt;/a>
&lt;/h2>&lt;ul>
&lt;li>We need better communication so users understand when infrastructure slowness is &amp;ldquo;expected&amp;rdquo; vs. &amp;ldquo;unstable&amp;rdquo;.&lt;/li>
&lt;li>We need better alerting for concurrent user startup throttling - we found out about this issue from users rather than automated monitoring.&lt;/li>
&lt;li>We learned that JupyterHub&amp;rsquo;s metrics don&amp;rsquo;t properly expose &lt;code>429 status&lt;/code> codes in our dashboards.&lt;/li>
&lt;li>This will happen again if we don&amp;rsquo;t have proper scaling limits and node provisioning strategies for sudden user influxes.&lt;/li>
&lt;/ul>
&lt;h2 id="resolution">
Resolution
&lt;a class="header-anchor" href="#resolution">#&lt;/a>
&lt;/h2>&lt;p>We implemented several fixes:&lt;/p>
&lt;ul>
&lt;li>Increased the concurrent spawn limit from 64 to 100.&lt;/li>
&lt;li>Put UC Merced users on larger nodes to reduce the number of node spinups needed. this will cost more in cloud but result in fewer scale-up events.&lt;/li>
&lt;li>Created action items to improve logging, alerting, and monitoring for similar incidents&lt;/li>
&lt;/ul>
&lt;h2 id="acknowledgements">
Acknowledgements
&lt;a class="header-anchor" href="#acknowledgements">#&lt;/a>
&lt;/h2>&lt;ul>
&lt;li>Thanks to UC Merced students and instructors for reporting the issue through our support system.&lt;/li>
&lt;/ul></description></item><item><title>We're going to try blogging about our work more often</title><link>https://deploy-preview-608--2i2c-org.netlify.app/blog/communications-strategy/</link><pubDate>Wed, 10 Sep 2025 00:00:00 +0000</pubDate><guid>https://deploy-preview-608--2i2c-org.netlify.app/blog/communications-strategy/</guid><description>&lt;p>At 2i2c, we aim to be an exemplar organization in working openly, supporting open science, and supporting open source communities in everything that we do.
We believe that
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/open-practices/" >open science is a process, not a product&lt;/a>, and commit to following practices that align with open principles throughout our work.&lt;/p>
&lt;p>A key principle for our team has always been &lt;strong>working in the open&lt;/strong>.
We do almost all of our work in our own public repositories or in upstream community spaces.
However, still struggle to &lt;em>communicate what we&amp;rsquo;ve been up to&lt;/em>.
We can&amp;rsquo;t expect everybody to keep an eye on the spaces where 2i2c operates in order to learn whether we are actually living up to our goals.&lt;/p>
&lt;p>So, we&amp;rsquo;re going to try an expriment that is
&lt;a href="https://simonwillison.net/" target="_blank" rel="noopener" >inspired by Simon Willison&amp;rsquo;s blog&lt;/a>. In short, here&amp;rsquo;s what we aim to do:&lt;/p>
&lt;ul>
&lt;li>Use our blog any time we learn or do something that&amp;rsquo;s aligned with
&lt;a href="https://compass.2i2c.org/organization/value-proposition" target="_blank" rel="noopener" >our value proposition&lt;/a>.&lt;/li>
&lt;li>Don&amp;rsquo;t hesitate to share in-progress work and things that are still rough - this is part of working in the open.&lt;/li>
&lt;li>Occasionally, share posts that help readers navigate this stream of short impact posts. We&amp;rsquo;ll use
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/mailing-list/" >our Mailing List&lt;/a> for this, so click that link if you&amp;rsquo;d like to sign up.&lt;/li>
&lt;/ul>
&lt;p>Our hope is that this will give us a steady stream of posts that show what we&amp;rsquo;ve been up to, as well as a way to navigate those posts via our mailing lists for the folks that don&amp;rsquo;t want to spend all day combing through our blog. :-)&lt;/p>
&lt;h2 id="acknowledgments">
Acknowledgments
&lt;a class="header-anchor" href="#acknowledgments">#&lt;/a>
&lt;/h2>&lt;ul>
&lt;li>Support for organizational and strategic work like this is provided by a grant from
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/navigation/" >The Navigation Fund&lt;/a>.&lt;/li>
&lt;/ul></description></item><item><title>On being a good open source citizen: supporting a healthy ecosystem through directed and foundational contributions</title><link>https://deploy-preview-608--2i2c-org.netlify.app/blog/good-citizen/</link><pubDate>Wed, 03 Sep 2025 00:00:00 +0000</pubDate><guid>https://deploy-preview-608--2i2c-org.netlify.app/blog/good-citizen/</guid><description>&lt;p>Any organization building on open source faces a fundamental tension: how do you serve the needs of your organizational stakeholders while also acting as a responsible steward of the upstream projects you depend on?
This is harder than it looks - simply &amp;ldquo;making PRs&amp;rdquo; leaves a number of open source needs unaddressed, and can burn out both your team members and the open source maintainers. We think about this a lot at 2i2c, and want to share our framework to navigate this challenge intentionally.&lt;/p>
&lt;p>Here are a few questions we&amp;rsquo;ve been grappling with:&lt;/p>
&lt;ul>
&lt;li>How do we tie general upstream maintenance to value delivered to our user communities?&lt;/li>
&lt;li>How can we scope upstream support so that it doesn&amp;rsquo;t detract from our service needs and product strategy?&lt;/li>
&lt;li>How can we encourage team members to work on the most impactful aspects of upstream support?&lt;/li>
&lt;li>How can we intentionally and equitably support open source communities as a team, rather than a collection of individuals?&lt;/li>
&lt;/ul>
&lt;p>Along the way, we realized there are &lt;strong>two very different kinds of upstream contributions&lt;/strong>:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Directed Contributions&lt;/strong>: A contribution driven by the needs of our member communities and product roadmap. We call these &amp;ldquo;Directed&amp;rdquo; contributions because they address a targeted need driven by one stakeholder (us!).&lt;/li>
&lt;li>&lt;strong>Foundational contributions&lt;/strong>: A contribution driven by the needs of the upstream community. We call these &amp;ldquo;Foundational contributions&amp;rdquo; because they&amp;rsquo;re meant to provide the healthy foundation on which a community can operate and grow.&lt;/li>
&lt;/ol>
&lt;p>Historically we have conflated these types of contributions, but we think it&amp;rsquo;s key that we treat them differently.&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>Note&lt;/strong>: For a more practical guide that describes the systems we&amp;rsquo;ve set up to accomplish &lt;em>Foundational&lt;/em> upstream contributions, see
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/blog/foundational-contributions/" >From scattered effort to strategic impact: How we&amp;rsquo;re systematizing our Foundational open source contributions&lt;/a>.&lt;/p>
&lt;/blockquote>
&lt;h2 id="everybody-has-an-open-source-hat-and-a-stakeholder-hat">
Everybody has an open source hat and a stakeholder hat
&lt;a class="header-anchor" href="#everybody-has-an-open-source-hat-and-a-stakeholder-hat">#&lt;/a>
&lt;/h2>&lt;p>Open source teams&lt;sup id="fnref:1">&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref">1&lt;/a>&lt;/sup> are usually two kinds of teams that overlap heavily:&lt;/p>
&lt;ol>
&lt;li>A collection of &lt;em>stakeholders working together&lt;/em> on the open source project, each with their own goals and interests.&lt;/li>
&lt;li>An &lt;em>open source team&lt;/em> with a shared goal and strategy for the open source project.&lt;/li>
&lt;/ol>
&lt;p>In this case, stakeholders can be individuals or companies. They use and contribute to the open source project because it advances their own interests. For example, an enthusiast contributing to a project because it brings them joy, or a company contributing to a project because they build a product that depends on the open source technology.&lt;/p>
&lt;p>However, for open source projects to be successful they also need their own unique identity, goals, strategy for impact, and system of work. This allows a diverse collection of stakeholders to &lt;em>work together effectively&lt;/em> and &lt;em>create impactful technology&lt;/em>. This team is made up of the same stakeholders described above, but with a responsibility to lead and support the open source team, rather than just serve their individual interests as stakeholders.&lt;/p>
&lt;p>Thus, any open source stakeholder has two hats: they are both &lt;em>representatives of a stakeholder&lt;/em> and &lt;em>members of an open source team&lt;/em>. While it&amp;rsquo;s possible to &lt;em>align the interests&lt;/em> of these two groups, we think it&amp;rsquo;s still important to &lt;em>distinguish between them&lt;/em>.&lt;/p>
&lt;h2 id="directed-contributions-benefit-the-stakeholder-you-represent">
Directed Contributions benefit the stakeholder you represent
&lt;a class="header-anchor" href="#directed-contributions-benefit-the-stakeholder-you-represent">#&lt;/a>
&lt;/h2>&lt;p>A &lt;em>Directed Contribution&lt;/em> is primarily driven by the needs of a stakeholder in an open source project. To use 2i2c as an example, let&amp;rsquo;s take a quote from 2i2c&amp;rsquo;s value proposition:&lt;/p>
&lt;blockquote>
&lt;p>2i2c serves a global network of community hubs for interactive learning and discovery&lt;/p>
&lt;/blockquote>
&lt;p>&lt;em>Community&lt;/em> here does &lt;strong>not&lt;/strong> refer to open source upstream software provider communities (like JupyterHub or Kubernetes), but instead to downstream &lt;em>user communities&lt;/em> (like
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/cryocloud/" >CryoCloud&lt;/a>,
&lt;a href="https://openscapes.org" target="_blank" rel="noopener" >Openscapes&lt;/a>, or
&lt;a href="https://www.earthdata.nasa.gov/data/tools/veda" target="_blank" rel="noopener" >NASA VEDA&lt;/a>).&lt;/p>
&lt;p>When 2i2c makes a Directed Contribution, it means we are trying to &lt;em>deliver value to one or more of our member communities&lt;/em> by making an upstream contribution.&lt;/p>
&lt;p>Satisfying community needs often involves directly working on the software they use. Driven by our
&lt;a href="https://2i2c.org/right-to-replicate/" target="_blank" rel="noopener" >right to replicate&lt;/a> principles, this means we mostly work on software that is not proprietary to 2i2c nor solely owned by us permanently - but by contributing to an upstream software community. These are all Directed Contributions.&lt;/p>
&lt;p>Some illustrative examples:&lt;/p>
&lt;ol>
&lt;li>
&lt;a href="https://github.com/jupyterhub/oauthenticator/pull/719" target="_blank" rel="noopener" >Allow login to be gated on OAuth2 granted scopes&lt;/a> was a feature we added to support one of our communities&amp;rsquo; auth flow (
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/earthscope/" >EarthScope&lt;/a>)&lt;/li>
&lt;li>
&lt;a href="https://github.com/pangeo-data/pangeo-docker-images/pull/426" target="_blank" rel="noopener" >Changing how &lt;code>.pyc&lt;/code> files are kept in images&lt;/a> was work we did as a result of a support ticket investigating spawn timeout issues in the
&lt;a href="https://leap.columbia.edu/" target="_blank" rel="noopener" >LEAP&lt;/a> hub.&lt;/li>
&lt;li>
&lt;a href="https://github.com/jupyter-book/myst-theme/pull/531" target="_blank" rel="noopener" >Adding landing pages functionality to Jupyter Book and MyST&lt;/a> was work we did to support member communities like
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/cryocloud/" >CryoCloud&lt;/a> and
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/pythia/" >Project Pythia&lt;/a>.&lt;/li>
&lt;/ol>
&lt;p>The fact that these are open source contributions is &lt;em>incidental&lt;/em>. We are &lt;em>primarily&lt;/em> doing this work to deliver value to &lt;em>our community network&lt;/em>.&lt;/p>
&lt;h3 id="we-plan-directed-contributions-according-to-our-roadmap-and-member-feedback">
We plan Directed Contributions according to our roadmap and member feedback
&lt;a class="header-anchor" href="#we-plan-directed-contributions-according-to-our-roadmap-and-member-feedback">#&lt;/a>
&lt;/h3>&lt;p>Directed Contributions naturally align with 2i2c&amp;rsquo;s overall goals and strategy, so we use our
&lt;a href="https://compass.2i2c.org/product-and-services/" target="_blank" rel="noopener" >product processes&lt;/a> for planning and delivering on them. However, we also want to provide transparency to upstream communities so that they understand who is driving the contributions that we&amp;rsquo;re making.&lt;/p>
&lt;p>With that in mind, here are a few ways that Directed Contributions relate to our practices:&lt;/p>
&lt;ul>
&lt;li>Directed Contributions should be defined by our product roadmap and prioritization processes.&lt;/li>
&lt;li>We allocate engineering time for these upstream contributions as part of our product lifecycle, &lt;em>including the extra coordination and communication work needed to work at the pace of the upstream community&lt;/em>.&lt;/li>
&lt;li>We cross-link 2i2c product initiatives to upstream issues and pull-requests wherever we can to provide transparency about why we&amp;rsquo;re making a contribution.&lt;/li>
&lt;li>We communicate this work via our blog so that 2i2c&amp;rsquo;s member communities know about the contributions we&amp;rsquo;ve made on their behalf.&lt;/li>
&lt;/ul>
&lt;h2 id="foundational-contributions-support-a-healthy-open-source-community">
Foundational Contributions support a healthy open source community
&lt;a class="header-anchor" href="#foundational-contributions-support-a-healthy-open-source-community">#&lt;/a>
&lt;/h2>&lt;p>However, contributions can&amp;rsquo;t always be driven by a stakeholder&amp;rsquo;s needs or the open source team will not have an identity or support structure of its own. Here&amp;rsquo;s another excerpt from our value proposition:&lt;/p>
&lt;blockquote>
&lt;p>We need infrastructure services that are driven by community needs and values, that follow the same open source science practices we wish to see in others, and that believe in the power of shared community resources and knowledge.&lt;/p>
&lt;/blockquote>
&lt;p>Being a &amp;ldquo;healthy upstream citizen&amp;rdquo; is core to 2i2c&amp;rsquo;s mission, and is also a way to help communities we rely on remain healthy. Some of our contributions should be &lt;em>Foundational&lt;/em> rather than &lt;em>Directed&lt;/em>. This means doing things that keep the overall ecosystem healthy even if it does not &lt;em>directly&lt;/em> address a specific member community need. The &lt;em>presence&lt;/em> of a healthy open source ecosystem is a value to our member communities in-and-of itself.&lt;/p>
&lt;p>Defining &amp;ldquo;Foundational&amp;rdquo; needs is difficult, because open source teams tend to have less structure and formally-stated goals and needs than most organizations. In 2i2c&amp;rsquo;s case, we focus our Foundational Contributions around &lt;em>maintaining the health of the open source ecosystem&lt;/em>.&lt;/p>
&lt;p>It includes things like:&lt;/p>
&lt;ol>
&lt;li>Grow and guide new contributors to grow team capacity&lt;/li>
&lt;li>Help making releases&lt;/li>
&lt;li>Provide code review&lt;/li>
&lt;li>Fix broken CI&lt;/li>
&lt;li>Write documentation and tutorials&lt;/li>
&lt;li>Manage and run meetings&lt;/li>
&lt;li>Align open source teams on goals and strategy&lt;/li>
&lt;/ol>
&lt;p>However, the real point is that these actions need to be driven by &lt;em>the upstream project&amp;rsquo;s goals and needs&lt;/em>, not by 2i2c&amp;rsquo;s needs.&lt;/p>
&lt;p>Here are a few common examples of contributions that are &lt;em>not considered&lt;/em> Foundational for our team:&lt;/p>
&lt;ol>
&lt;li>Opening a PR to add a major feature to an upstream project.&lt;/li>
&lt;li>Creating a brand new project in an open source organization in order to scratch your own itch.&lt;/li>
&lt;li>Engaging in reactive open-source work that isn&amp;rsquo;t driven by a clear strategy or goal (e.g., randomly responding to the last few GitHub issue comments you happened to notice)&lt;/li>
&lt;/ol>
&lt;h3 id="we-plan-foundational-contributions-alongside-our-engineering-roadmap">
We plan Foundational Contributions alongside our engineering roadmap
&lt;a class="header-anchor" href="#we-plan-foundational-contributions-alongside-our-engineering-roadmap">#&lt;/a>
&lt;/h3>&lt;p>Foundational Contributions are important to 2i2c both for strategic and tactical reasons. However, when left as unstructured time (as we have historically), it runs into all the problems of unstructured work - it happens in non-strategic ways, it isn&amp;rsquo;t evenly balanced across team members, it is more or less accessible depending on your personal comfort level and skills, etc.&lt;/p>
&lt;p>With that in mind, here are a few ways that Foundational Contributions relate to our practices:&lt;/p>
&lt;ul>
&lt;li>We need to &lt;em>own Foundational Contributions as a team&lt;/em>, rather than asking individuals to identify and do this work on their own.&lt;/li>
&lt;li>We need to define team &lt;em>goals&lt;/em> and &lt;em>strategy&lt;/em> to define the impact we want to have, and what kind of work leads to that impact.&lt;/li>
&lt;li>We need a team system for identifying and prioritizing the most impactful Foundational Contributions to perform.&lt;/li>
&lt;li>This system must spread the responsibility of Foundational Contributions across our whole product team.&lt;/li>
&lt;li>It means we need to give people support and training to do this effectively. For example, helping team members grow into roles that involve upstream work, rotating certain types of contributions across team members, etc.&lt;/li>
&lt;/ul>
&lt;p>To ensure this work is intentional and equitable across our team, we encourage Foundational contributions to happen within this framework. Contributions that falls outside of it is treated as a valued, but separate, personal contribution.&lt;/p>
&lt;h2 id="whats-next">
What&amp;rsquo;s next
&lt;a class="header-anchor" href="#whats-next">#&lt;/a>
&lt;/h2>&lt;p>By distinguishing between Directed and Foundational contributions, we can align and balance our immediate product needs with our long-term commitment to community health. We believe this framework allows organizations like ours to be better partners. We&amp;rsquo;d love feedback about this process, how we can improve it, and what others have learned along the way.&lt;/p>
&lt;div class="footnotes" role="doc-endnotes">
&lt;hr>
&lt;ol>
&lt;li id="fn:1">
&lt;p>By &amp;ldquo;open source&amp;rdquo; we are focusing on multi-stakeholder open source projects with participatory and inclusive leadership and contributions. This wouldn&amp;rsquo;t apply to an organization- or person-specific open source project.&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;/ol>
&lt;/div></description></item><item><title>Sharing JupyterHub's vision for more flexible application deployment at the doepy talk series.</title><link>https://deploy-preview-608--2i2c-org.netlify.app/blog/doepy-yuvi/</link><pubDate>Wed, 03 Sep 2025 00:00:00 +0000</pubDate><guid>https://deploy-preview-608--2i2c-org.netlify.app/blog/doepy-yuvi/</guid><description>&lt;p>Our Technical Lead
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/blog/doepy-yuvi/../../authors/yuvi-panda/_index.md" >Yuvi Panda&lt;/a> recently gave a talk at the
&lt;a href="https://meetup.doepy.org/" target="_blank" rel="noopener" >doepy meetup&lt;/a> about JupyterHub&amp;rsquo;s interest in moving beyond the &amp;ldquo;single-user notebook application&amp;rdquo; and towards a more flexible approach to enabling administrators to deploy many different types of applications and environments.&lt;/p>
&lt;p>Check out a video of the talk here:&lt;/p>
&lt;div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;">
&lt;iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen="allowfullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/vsbHMvvsFw8?autoplay=0&amp;controls=1&amp;end=0&amp;loop=0&amp;mute=0&amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"
>&lt;/iframe>
&lt;/div>
&lt;p>This is an important step for the JupyterHub project in order to support the many different kinds of workflows that data scientists need to use in their work. We hope that this generates more interest in the JupyterHub project and gives us useful feedback to guide the team&amp;rsquo;s understanding of this direction.&lt;/p>
&lt;h2 id="learn-more">
Learn more
&lt;a class="header-anchor" href="#learn-more">#&lt;/a>
&lt;/h2>&lt;ul>
&lt;li>
&lt;a href="https://www.youtube.com/watch?v=vsbHMvvsFw8" target="_blank" rel="noopener" >YouTube video of this talk&lt;/a>&lt;/li>
&lt;li>
&lt;a href="https://jupyter.zulipchat.com/#narrow/channel/469744-jupyterhub/topic/JupyterHub.20in.202025.3A.20Not.20just.20for.20Jupyter.20Notebooks/near/537708184" target="_blank" rel="noopener" >Jupyter Chat about this talk&lt;/a>&lt;/li>
&lt;li>
&lt;a href="https://www.linkedin.com/feed/update/urn:li:activity:7364763956525092868" target="_blank" rel="noopener" >LinkedIn post announcing the talk&lt;/a>&lt;/li>
&lt;li>
&lt;a href="https://www.linkedin.com/posts/cameron-riddell_we-dont-use-this-code-loved-having-yuvi-activity-7369421556516601859-qOxw?utm_medium=ios_app&amp;amp;rcm=ACoAADSgbM8BXeDyQi3bGVtD7qmmJg9b20KhG6A&amp;amp;utm_source=social_share_send&amp;amp;utm_campaign=copy_link" target="_blank" rel="noopener" >LinkedIn post describing the talk&lt;/a>&lt;/li>
&lt;/ul>
&lt;h2 id="acknowledgements">
Acknowledgements
&lt;a class="header-anchor" href="#acknowledgements">#&lt;/a>
&lt;/h2>&lt;ul>
&lt;li>
&lt;a href="https://meetup.doepy.org/" target="_blank" rel="noopener" >The doepy team&lt;/a> for inviting Yuvi to give this talk.&lt;/li>
&lt;li>
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/jupyterhub/" >The JupyterHub team&lt;/a> for working with us on this strategy.&lt;/li>
&lt;li>
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/members/" >2i2c&amp;rsquo;s network of member communities&lt;/a> whose fees support our Foundational open source engagement.&lt;/li>
&lt;/ul></description></item><item><title>Overhauling repo2docker's documentation</title><link>https://deploy-preview-608--2i2c-org.netlify.app/blog/repo2docker-docs/</link><pubDate>Fri, 01 Aug 2025 00:00:00 +0000</pubDate><guid>https://deploy-preview-608--2i2c-org.netlify.app/blog/repo2docker-docs/</guid><description>&lt;p>Documentation is incredibly important for open source projects to communicate their value and show users how to make the most of their tools. However, it&amp;rsquo;s one of those things that often gets de-prioritized with all of the other work that needs to happen in a project.&lt;/p>
&lt;p>We are heavy users of the
&lt;a href="https://repo2docker.readthedocs.io" target="_blank" rel="noopener" >repo2docker project&lt;/a> in 2i2c&amp;rsquo;s service. It allows you to dynamically build an environment image that can by hosted in a cloud service like JupyterHub. It&amp;rsquo;s the underlying tool used by
&lt;a href="https://binderhub.readthedocs.io" target="_blank" rel="noopener" >BinderHub&lt;/a>, and is the focus of recent work on enabling
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/blog/q1-product-goals/" >dynamic image building in a JupyterHub&lt;/a> (more on that to come).&lt;/p>
&lt;p>As part of this work, we decided to do a small
&lt;a href="https://github.com/jupyterhub/repo2docker/pull/1433" target="_blank" rel="noopener" >overhaul of repo2docker&amp;rsquo;s documentation&lt;/a>, with the goal of making it easier to discover, navigate, and learn from. Here&amp;rsquo;s how the landing page looks now!&lt;/p>
&lt;p>
&lt;figure id="figure-the-new-repo2docker-landing-page-now-looks-more-like-an-actual-landing-page">
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img src="./featured.png" alt="Repo2Docker documentation overhaul" loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;figcaption>
The new repo2docker landing page now looks more like an actual landing page!
&lt;/figcaption>&lt;/figure>
&lt;/p>
&lt;p>We hope this makes repo2docker a more useful tool for everybody, and also gives us more confidence pointing our communities to the repo2docker documentation in their community workflows.&lt;/p>
&lt;h2 id="acknowledgements">
Acknowledgements
&lt;a class="header-anchor" href="#acknowledgements">#&lt;/a>
&lt;/h2>&lt;ul>
&lt;li>Thanks to the
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/nasa-veda/" >NASA VEDA project&lt;/a> and to
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/nasa-open-science/" >NASA Open Science&lt;/a> for providing funding and collaboration for this work.&lt;/li>
&lt;li>Thanks to the
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/jupyterhub/" >JupyterHub community&lt;/a> for collaboration and review of this work.&lt;/li>
&lt;/ul></description></item><item><title>2i2c's submissions to JupyterCon 2025</title><link>https://deploy-preview-608--2i2c-org.netlify.app/blog/jupytercon-2025-submissions/</link><pubDate>Sat, 19 Jul 2025 00:00:00 +0000</pubDate><guid>https://deploy-preview-608--2i2c-org.netlify.app/blog/jupytercon-2025-submissions/</guid><description>&lt;p>&lt;em>&lt;strong>Update&lt;/strong>: The talks are now live! See this
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/blog/jupytercon-2025-talks/" >blog post with links to our videos&lt;/a>.&lt;/em>&lt;/p>
&lt;p>We were excited to hear that
&lt;a href="https://jupytercon.com" target="_blank" rel="noopener" >JupyterCon is happening again in 2025&lt;/a>. The Call for Proposals just wrapped up, and our team was involved in preparing and submitting several directly from 2i2c as well as from the ecosystem in general.&lt;/p>
&lt;p>Enjoy brief summaries of the proposals we contributed to below.
&lt;a href="https://forms.fillout.com/t/uQHVMkgvsuus" target="_blank" rel="noopener" >Let us know&lt;/a> if you have ideas for future talks you want to hear from us?&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>Note&lt;/strong>: Many of these submissions were written in collaboration with others in the open-source projects we participate in. Particularly, in
&lt;a href="https://compass.hub.jupyter.org" target="_blank" rel="noopener" >JupyterHub&lt;/a> and
&lt;a href="https://compass.jupyterbook.org" target="_blank" rel="noopener" >JupyterBook&lt;/a>.&lt;/p>
&lt;/blockquote>
&lt;h2 id="jupyterhub-a-multi-user-server-for-jupyter-notebooks">
JupyterHub: A multi-user server for Jupyter notebooks
&lt;a class="header-anchor" href="#jupyterhub-a-multi-user-server-for-jupyter-notebooks">#&lt;/a>
&lt;/h2>&lt;p>This is how JupyterHub was described when it was announced in 2015, 10 years ago. The focus was on bringing Jupyter Notebooks to multiple users on shared infrastructure. The Jupyter Notebooks focus was so strong that Jupyter was even in the name of the project! Fast forward 10 years, &amp;amp; this is still the most common perception of JupyterHub.&lt;/p>
&lt;p>However, this has not been true for a &lt;em>long&lt;/em> time now. Instead of setting up 5 different kinds of infrastructure to support your users based on what kind of &lt;em>interface&lt;/em> they like to use (
&lt;a href="https://jupyterlab.readthedocs.io/" target="_blank" rel="noopener" >JupyterLab&lt;/a>,
&lt;a href="https://posit.co/products/open-source/rstudio/" target="_blank" rel="noopener" >RStudio&lt;/a>, Linux Desktop tools like
&lt;a href="https://qgis.org/" target="_blank" rel="noopener" >QGIS&lt;/a> or
&lt;a href="https://napari.org/" target="_blank" rel="noopener" >Napari&lt;/a>,
&lt;a href="https://code.visualstudio.com/" target="_blank" rel="noopener" >Visual Studio Code&lt;/a>, full &lt;code>ssh&lt;/code> (!?), etc) for their interactive computing, you can set up a JupyterHub that supports all of those! Meet your users where they are, rather than force them to conform to using only a specific set of tools.&lt;/p>
&lt;p>Come to this talk to:&lt;/p>
&lt;ul>
&lt;li>See cool demos of various popular applications running on JupyterHub seamlessly&lt;/li>
&lt;li>Understand the security model of JupyterHub &amp;amp; how that enables these cool demos&lt;/li>
&lt;li>Learn how you can set up your own application to run in JupyterHub&lt;/li>
&lt;li>Influence the future of how JupyterHub is marketed&lt;/li>
&lt;/ul>
&lt;h2 id="cloudy-with-a-chance-of-savings-per-user-usage-and-cost-monitoring-for-jupyterhubs-in-the-cloud">
Cloudy with a Chance of Savings: Per-User Usage and Cost Monitoring for JupyterHubs in the Cloud
&lt;a class="header-anchor" href="#cloudy-with-a-chance-of-savings-per-user-usage-and-cost-monitoring-for-jupyterhubs-in-the-cloud">#&lt;/a>
&lt;/h2>&lt;p>Cloud cost monitoring is moving beyond just preventing runaway cost explosions – it&amp;rsquo;s about empowering JupyterHub administrators with the guardrails they need to run efficient, transparent, and sustainable infrastructures. A cloud cost bill can show a broad view of services and machines provisioned, but how can we provide granular insights into each user and the value they are deriving from the hub on an application level?&lt;/p>
&lt;p>We&amp;rsquo;ve developed several open-source components towards answering this question:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Metric Collection&lt;/strong> –
&lt;a href="https://prometheus.io/" target="_blank" rel="noopener" >Prometheus&lt;/a> collects resource usage metrics (including CPU, memory, and storage) from individual user pods via standard and custom exporters.&lt;/li>
&lt;li>&lt;strong>Cost Estimation&lt;/strong> – Usage is correlated with AWS cost data to estimate per-user costs.&lt;/li>
&lt;li>&lt;strong>Visualization&lt;/strong> –
&lt;a href="https://grafana.com/" target="_blank" rel="noopener" >Grafana&lt;/a> dashboards display rich, interactive views of usage and cost data, making it easy to monitor trends, identify high-cost workloads, and generate reports for funders and decision-makers.&lt;/li>
&lt;/ul>
&lt;p>This approach delivers cloud observability and cost transparency that can be reliably deployed using
&lt;a href="https://kubernetes.io/" target="_blank" rel="noopener" >Kubernetes&lt;/a> and integrated with
&lt;a href="https://z2jh.jupyter.org/" target="_blank" rel="noopener" >Zero to JupyterHub&lt;/a> distributions.&lt;/p>
&lt;h2 id="controlling-home-directory-costs-with-user-empathy-on-the-cloud-with-jupyterhub-home-nfs">
Controlling home directory costs (with user empathy) on the cloud with jupyterhub-home-nfs
&lt;a class="header-anchor" href="#controlling-home-directory-costs-with-user-empathy-on-the-cloud-with-jupyterhub-home-nfs">#&lt;/a>
&lt;/h2>&lt;p>User home directories on JupyterHubs deployed in cloud providers has been a pain point for both end users and administrators. Administrators feel the pain of cloud costs for home directory storage (sometimes higher than compute!). No user wants to receive an email saying &amp;ldquo;well, this code you copy pasted downloaded 3TB of netcdf files into your home directory, and now we have used up our entire team&amp;rsquo;s cloud budget for the next 2 years&amp;rdquo; (true story).&lt;/p>
&lt;p>The
&lt;a href="https://github.com/2i2c-org/jupyterhub-home-nfs" target="_blank" rel="noopener" >jupyterhub-home-nfs&lt;/a> open source project is a JupyterHub native, cloud agnostic solution to these problems. Administrators can do per user limits, tune performance, report on usage and make cloud cost conscious choices around overprovisioning. It provides users empathetic guardrails to prevent them from overuse, rather than punitive gates that zap them after the fact.&lt;/p>
&lt;p>In this short talk, we will:&lt;/p>
&lt;ul>
&lt;li>Describe the core of the problem, and how it manifests for users and admins.&lt;/li>
&lt;li>Review current solutions and their limitations&lt;/li>
&lt;li>Introduce jupyterhub-home-nfs and how it moves the solution space forward&lt;/li>
&lt;li>Demo how this looks like for an end user&lt;/li>
&lt;li>Talk about future direction, and opportunities for collaboration&lt;/li>
&lt;/ul>
&lt;h2 id="rebuilding-user-trust-in-mybinderorg">
Rebuilding user trust in &lt;code>mybinder.org&lt;/code>
&lt;a class="header-anchor" href="#rebuilding-user-trust-in-mybinderorg">#&lt;/a>
&lt;/h2>&lt;p>Have you clicked a
&lt;a href="https://mybinder.org/" target="_blank" rel="noopener" >mybinder.org&lt;/a> link, waited for it to start and gave up after it took far too long to start? Or just failed?&lt;/p>
&lt;p>Have you stopped using mybinder.org for your tutorials, repositories and presentations because you could no longer rely on it to work each time?&lt;/p>
&lt;p>mybinder.org is open infrastructure run by incredible volunteers (who go above and beyond constantly) in the Jupyter community. Is &amp;lsquo;slow fade into unreliability&amp;rsquo; just the fate of all openly run infrastructure?&lt;/p>
&lt;p>But perhaps maybe, just maybe, you have tried doing that again recently, &amp;amp; noticed improvements! Launches are more reliable. Faster. The UI looks better. Maybe things are getting better?&lt;/p>
&lt;p>This talk will go through the problems facing mybinder.org &amp;amp; what we are doing about it. Come to this talk to find out:&lt;/p>
&lt;ol>
&lt;li>How is mybinder.org run?&lt;/li>
&lt;li>What are the structural issues facing open infrastructure services like mybinder.org?&lt;/li>
&lt;li>What sustainability experiments are we running to improve reliability and rebuild user trust?&lt;/li>
&lt;li>Has reliability actually improved?&lt;/li>
&lt;li>How can I help?&lt;/li>
&lt;/ol>
&lt;h2 id="can-your-jupyterhub-handle-your-workload-performance-testing-with-jupyterhub-simulator">
Can your JupyterHub handle your workload? Performance testing with &lt;code>jupyterhub-simulator&lt;/code>
&lt;a class="header-anchor" href="#can-your-jupyterhub-handle-your-workload-performance-testing-with-jupyterhub-simulator">#&lt;/a>
&lt;/h2>&lt;p>Your JupyterHub is all set up, and you&amp;rsquo;re excited to use it for your workshop of 60 students. Or your class of 600 students. Or your research group of 5 people with complex workflows.&lt;/p>
&lt;p>You &lt;em>feel&lt;/em> your infrastructure should hold up fine, but do you &lt;em>know&lt;/em> if your infrastructure will hold up fine? Is that just excitement, or is there a little bit of nervousness in there too? Wouldn&amp;rsquo;t it be nice to test and know for sure?&lt;/p>
&lt;p>&lt;code>jupyterhub-simulator&lt;/code> is an open source project that allows you to describe what you expect your users to be doing - starting servers, clicking on
&lt;a href="https://github.com/jupyterhub/nbgitpuller" target="_blank" rel="noopener" >nbgitpuller&lt;/a> links, running notebooks, etc. Once you have described it, you can then simulate any number of users doing that workflow simultaneously, and verify that your JupyterHub can handle that workload. If it can&amp;rsquo;t, tweak your infrastructure and try again until it does!&lt;/p>
&lt;p>In this talk you will learn:&lt;/p>
&lt;ul>
&lt;li>What is &lt;code>jupyterhub-simulator&lt;/code>?&lt;/li>
&lt;li>How can I describe my expected workflow?&lt;/li>
&lt;li>How can I test if N users can do this workflow all simultaneously?&lt;/li>
&lt;li>How can I visualize the performance of my infrastructure so I can tweak its configuration and try the simulation again?&lt;/li>
&lt;/ul>
&lt;h2 id="not-just-for-notebooks-jupyterhub-in-2025">
Not just for notebooks: JupyterHub in 2025
&lt;a class="header-anchor" href="#not-just-for-notebooks-jupyterhub-in-2025">#&lt;/a>
&lt;/h2>&lt;blockquote>
&lt;p>JupyterHub: A multi-user server for Jupyter notebooks&lt;/p>
&lt;/blockquote>
&lt;p>This is how JupyterHub was described when it was announced in 2015, 10 years ago. The focus was on bringing Jupyter Notebooks to multiple users on shared infrastructure. The Jupyter Notebooks focus was so strong that Jupyter was even in the name of the project! Fast forward 10 years, &amp;amp; this is still the most common perception of JupyterHub.&lt;/p>
&lt;p>However, this has not been true for a &lt;em>long&lt;/em> time now. Instead of setting up 5 different kinds of infrastructure to support your users based on what kind of &lt;em>interface&lt;/em> they like to use (
&lt;a href="https://jupyterlab.readthedocs.io/" target="_blank" rel="noopener" >JupyterLab&lt;/a>,
&lt;a href="https://posit.co/products/open-source/rstudio/" target="_blank" rel="noopener" >RStudio&lt;/a>, Linux Desktop tools like
&lt;a href="https://qgis.org/" target="_blank" rel="noopener" >QGIS&lt;/a> or
&lt;a href="https://napari.org/" target="_blank" rel="noopener" >Napari&lt;/a>,
&lt;a href="https://code.visualstudio.com/" target="_blank" rel="noopener" >Visual Studio Code&lt;/a>, full &lt;code>ssh&lt;/code> (!?), etc) for their interactive computing, you can set up a JupyterHub that supports all of those! Meet your users where they are, rather than force them to conform to using only a specific set of tools.&lt;/p>
&lt;p>Come to this talk to:&lt;/p>
&lt;ul>
&lt;li>See cool demos of various popular applications running on JupyterHub seamlessly&lt;/li>
&lt;li>Understand the security model of JupyterHub &amp;amp; how that enables these cool demos&lt;/li>
&lt;li>Learn how you can set up your own application to run in JupyterHub&lt;/li>
&lt;li>Influence the future of how JupyterHub is marketed&lt;/li>
&lt;/ul>
&lt;h2 id="introducing-jupyter-book-20">
Introducing Jupyter Book 2.0
&lt;a class="header-anchor" href="#introducing-jupyter-book-20">#&lt;/a>
&lt;/h2>&lt;p>This is a community talk from the
&lt;a href="https://compass.jupyterbook.org/team" target="_blank" rel="noopener" >Jupyter Book team&lt;/a>, detailing the principles behind the new
&lt;a href="https://mystmd.org/" target="_blank" rel="noopener" >MyST Document Engine&lt;/a> and
&lt;a href="https://next.jupyterbook.org" target="_blank" rel="noopener" >Jupyter Book 2&amp;rsquo;s upcoming release&lt;/a>. We&amp;rsquo;ll share the text when the Jupyter Book team posts it publicly.&lt;/p>
&lt;h2 id="you-dont-need-to-contribute-more-to-open-source-you-need-to-go-to-therapy">
You don&amp;rsquo;t need to contribute more to open source, you need to go to therapy
&lt;a class="header-anchor" href="#you-dont-need-to-contribute-more-to-open-source-you-need-to-go-to-therapy">#&lt;/a>
&lt;/h2>&lt;p>Open source communities can be incredible and irreplaceable sources of human connection in our lives, offering a unique kind of fulfillment hard to find elsewhere. This feeling of fulfillment and approval can, for some people, be a soothing balm in an otherwise rough life. However, it has the be part of a healthy, balanced ecosystem of different kinds of connections offering different kinds of fulfillment . If a significant chunk of fulfillment in your life comes from the open source work you do, unbalanced by other sources, that can quickly become unhealthy for both you and the community. Disagreements are more likely to become high stakes. Interactions can quickly become emotionally charged and filled with hard to interpret subtext. This can both burn you out, and drive away potential new community members.&lt;/p>
&lt;p>This talk explores the why &lt;em>emotional regulation&lt;/em> is a critical skill for participating in open source communities, and how therapy can be a tool for learning that skill. Come to learn:&lt;/p>
&lt;ol>
&lt;li>What is &lt;em>emotional regulation&lt;/em>?&lt;/li>
&lt;li>Why should I care?&lt;/li>
&lt;li>What is therapy and how can I access it?&lt;/li>
&lt;li>Wait that&amp;rsquo;s not what I thought therapy was! Are you telling me Missy Armitage lied in &lt;em>Get Out&lt;/em>?!&lt;/li>
&lt;li>What negative effects do &lt;em>communities&lt;/em> feel?&lt;/li>
&lt;/ol>
&lt;h2 id="what-2i2c-has-learned-while-trying-to-build-sustainable-relationships-with-jupyters-community">
What 2i2c has learned while trying to build sustainable relationships with Jupyter&amp;rsquo;s community.
&lt;a class="header-anchor" href="#what-2i2c-has-learned-while-trying-to-build-sustainable-relationships-with-jupyters-community">#&lt;/a>
&lt;/h2>&lt;p>2i2c is a non-profit organization that fosters co-creation and collaboration between science communities and open source communities. We are deeply embedded in an international network of research and education communities, as well as open source communities that underlie their infrastructure (particularly in the Jupyter ecosystem). Our technical infrastructure is built entirely with open source components that we contribute to, but do not control. This is a really hard problem to solve!&lt;/p>
&lt;p>We&amp;rsquo;ve learned a lot in the first four years of our existence. This talk will describe how our organization approaches a healthy and productive open source relationship with the Jupyter (and broader scientific python) ecosystem. It&amp;rsquo;ll cover some of the major mistakes we&amp;rsquo;ve made, lessons learned, and where we think we&amp;rsquo;ve had impact. We aim to make this talk full of practical learnings that others can follow in building sustainable open science organizations that contribute to a healthy and vibrant open source ecosystem. Our goal will be to provide inspiration to others that are interested in building on top of open source projects like Jupyter, and want to do so in a way that is healthy and sustainable.&lt;/p></description></item><item><title>Open slides: Jupyter Book 2 and MyST at the UC Berkeley Data Science Education Summit</title><link>https://deploy-preview-608--2i2c-org.netlify.app/blog/jb2-berkeley-dsep/</link><pubDate>Tue, 01 Jul 2025 00:00:00 +0000</pubDate><guid>https://deploy-preview-608--2i2c-org.netlify.app/blog/jb2-berkeley-dsep/</guid><description>&lt;p>Chris gave a talk about Jupyter Book 2 and MyST at the
&lt;a href="https://data.berkeley.edu/dsep" target="_blank" rel="noopener" >UC Berkeley Data Science Education Program&lt;/a>&amp;rsquo;s annual meeting. It covered the next direction for the Jupyter Book project, and its recent adoption of the
&lt;a href="https://mystmd.org" target="_blank" rel="noopener" >MyST Document Engine&lt;/a> for Jupyter Book 2.&lt;/p>
&lt;p>You can
&lt;a href="https://docs.google.com/presentation/d/1rHQudFtfk8ATu3Pmc1lFGDDAlCmAo8KGIk7ybTbTw6c/edit?slide=id.g2f14b3524cb_0_886#slide=id.g2f14b3524cb_0_886" target="_blank" rel="noopener" >view the full slide deck here&lt;/a>.&lt;/p>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="Slide from the presentation showing Jupyter Book 2 and MyST overview" srcset="
/blog/jb2-berkeley-dsep/featured_hu8430e0e9c10e10455f83c8ebe9d339d9_187852_44f0286415556d6afc711732dd104164.webp 400w,
/blog/jb2-berkeley-dsep/featured_hu8430e0e9c10e10455f83c8ebe9d339d9_187852_e08f8cdf1fd014b04e776593546c4dee.webp 760w,
/blog/jb2-berkeley-dsep/featured_hu8430e0e9c10e10455f83c8ebe9d339d9_187852_1200x1200_fit_q75_h2_lanczos_3.webp 1200w"
src="https://deploy-preview-608--2i2c-org.netlify.app/blog/jb2-berkeley-dsep/featured_hu8430e0e9c10e10455f83c8ebe9d339d9_187852_44f0286415556d6afc711732dd104164.webp"
width="760"
height="424"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;h2 id="learn-more">
Learn more
&lt;a class="header-anchor" href="#learn-more">#&lt;/a>
&lt;/h2>&lt;ul>
&lt;li>
&lt;a href="https://docs.google.com/presentation/d/1rHQudFtfk8ATu3Pmc1lFGDDAlCmAo8KGIk7ybTbTw6c/edit?slide=id.g2f14b3524cb_0_886#slide=id.g2f14b3524cb_0_886" target="_blank" rel="noopener" >View the full slide deck&lt;/a>&lt;/li>
&lt;li>
&lt;a href="https://blog.jupyterbook.org/posts/2024-11-15-jupyter-book-2-alpha/" target="_blank" rel="noopener" >Learn about Jupyter Book 2&lt;/a>&lt;/li>
&lt;li>
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/blog/jb-for-communities/" >See how we&amp;rsquo;re using Jupyter Book for communities&lt;/a>&lt;/li>
&lt;li>
&lt;a href="https://next.jupyterbook.org/" target="_blank" rel="noopener" >Jupyter Book 2 documentation&lt;/a>&lt;/li>
&lt;/ul>
&lt;h2 id="acknowledgements">
Acknowledgements
&lt;a class="header-anchor" href="#acknowledgements">#&lt;/a>
&lt;/h2>&lt;ul>
&lt;li>Thanks to
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/pythia/" >Project Pythia&lt;/a> for funding some of our work on the Jupyter Book and MyST ecosystem&lt;/li>
&lt;li>Thanks to
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/cloudbank/" >CloudBank&lt;/a> for collaborating with us on adapting and deploying Jupyter Book for education and organizing this summit&lt;/li>
&lt;li>Thanks to the
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/jupyter-book/" >Jupyter Book project&lt;/a> for collaborating with us on these strategic efforts over the last years&lt;/li>
&lt;/ul></description></item><item><title>Jupyter Book at the Scientific Python 2025 Developer Summit</title><link>https://deploy-preview-608--2i2c-org.netlify.app/blog/scientific-python-summit/</link><pubDate>Fri, 23 May 2025 00:00:00 +0000</pubDate><guid>https://deploy-preview-608--2i2c-org.netlify.app/blog/scientific-python-summit/</guid><description>&lt;p>Chris and Angus recently attended the Scientific Python 2025 Developer Summit on behalf of
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/jupyter-book/" >Jupyter Book&lt;/a>, here&amp;rsquo;s
&lt;a href="https://blog.jupyterbook.org/posts/2025-05-23-scientific-python-dev-summit" target="_blank" rel="noopener" >a brief blog post about their experience&lt;/a> written with the Jupyter Book team.&lt;/p></description></item><item><title>Offering Jetstream2-powered hub support at 2i2c</title><link>https://deploy-preview-608--2i2c-org.netlify.app/blog/jetstream2-persistent-hub/</link><pubDate>Mon, 28 Apr 2025 00:00:00 +0000</pubDate><guid>https://deploy-preview-608--2i2c-org.netlify.app/blog/jetstream2-persistent-hub/</guid><description>&lt;p>When we first committed to offer
&lt;a href="https://jetstream-cloud.org/index.html" target="_blank" rel="noopener" >Jetstream2&lt;/a> support at 2i2c, Jetstream2,
&lt;a href="https://docs.openstack.org/magnum/latest/" target="_blank" rel="noopener" >Magnum&lt;/a>,
&lt;a href="https://www.openstack.org/" target="_blank" rel="noopener" >OpenStack&lt;/a>,
&lt;a href="https://cluster-api.sigs.k8s.io/" target="_blank" rel="noopener" >ClusterAPI&lt;/a> were all new concepts that we hadn&amp;rsquo;t used at 2i2c before.
And although the initial exercise of reading about each of them independently was confusing, learning how they actually glued together was the key.
This post is about Jetstream2, 2i2c persistent hub offerings, and the learning that took place in the process.&lt;/p>
&lt;blockquote>
&lt;p>⭐ &lt;strong>Members of 2i2c&amp;rsquo;s community network&lt;/strong> can determine their eligibility and learn about JetStream2 in
&lt;a href="https://docs.2i2c.org/community-lead/about/cloud-providers#jetstream2" target="_blank" rel="noopener" >our supported cloud providers documentation&lt;/a>. If needed,
&lt;a href="https://docs.2i2c.org/support" target="_blank" rel="noopener" >reach out to 2i2c for support&lt;/a>.&lt;/p>
&lt;/blockquote>
&lt;h2 id="context">
Context
&lt;a class="header-anchor" href="#context">#&lt;/a>
&lt;/h2>&lt;p>At 2i2c, we want to be able to deploy k8s clusters on different cloud providers. In a very simplistic way, for this we use:&lt;/p>
&lt;ul>
&lt;li>&lt;code>Infrastructure as code&lt;/code> to describe, deploy and manage the actual physical infrastructure from the cloud providers&lt;/li>
&lt;li>Cloud specific CLI to authenticate to this infrastructure&lt;/li>
&lt;li>
&lt;a href="https://helm.sh/" target="_blank" rel="noopener" >&lt;code>Helm&lt;/code>&lt;/a> to deploy and manage k8s resources onto this infrastructure&lt;/li>
&lt;li>And finally
&lt;a href="https://kubernetes.io/docs/reference/kubectl/" target="_blank" rel="noopener" >&lt;code>kubectl&lt;/code>&lt;/a> to interact with all of these k8s resources&lt;/li>
&lt;/ul>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img src="./2i2c-generic-infra.png" alt="image" loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
(Main tools used at 2i2c to deploy and manage k8s clusters on different cloud providers)&lt;/p>
&lt;p>On cloud providers like GCP, AWS, Azure, the Kubernetes support feels like an atomic feature of the cloud provider and works out of the box. But on Jetstream2, k8s support is not such a solid feature anymore.&lt;/p>
&lt;h2 id="jetstream2-kubernetes-support-stack">
Jetstream2 Kubernetes support stack
&lt;a class="header-anchor" href="#jetstream2-kubernetes-support-stack">#&lt;/a>
&lt;/h2>&lt;p>Jetstream2 is a collection of supercomputers that are part of the
&lt;a href="https://access-ci.org/" target="_blank" rel="noopener" >ACCESS cyberinfrastructure&lt;/a>. This ACCESS infrastructure groups together super computers like Jetstream2 (but not limited to it), into a mesh that creates the impression of a single, virtual system that scientists can openly access and interactively use.&lt;/p>
&lt;p>It offers Infrastructure as a Service (IaaS), that allows users to deploy VMs and manage environments dynamically. And the piece that enables this Infrastructure as a Service feature is OpenStack.&lt;/p>
&lt;h3 id="openstack-and-magnum">
OpenStack and Magnum
&lt;a class="header-anchor" href="#openstack-and-magnum">#&lt;/a>
&lt;/h3>&lt;p>OpenStack is an open source platform made of multiple projects that help build and manage both private and public cloud infrastructure.&lt;/p>
&lt;p>For our use-case, one of the most relevant OpenStack sub-project is Magnum. Magnum offers container orchestration engines for deploying and managing containers, like Kubernetes, but not limited to it.&lt;/p>
&lt;p>Initially, Kubernetes support was provided through a project called
&lt;a href="https://wiki.openstack.org/wiki/Heat" target="_blank" rel="noopener" >HEAT&lt;/a>. However that has proven harder to manage and maintain, and it was extremely hard to upgrade a cluster. So, they’ve migrated towards a new driver called
&lt;a href="https://docs.openstack.org/magnum-capi-helm/latest/user_docs/index.html" target="_blank" rel="noopener" >Cluster API magnum driver&lt;/a>, which offers a more native k8s integration.&lt;/p>
&lt;h3 id="cluster-api-and-capi-helm-driver">
Cluster API and CAPI helm driver
&lt;a class="header-anchor" href="#cluster-api-and-capi-helm-driver">#&lt;/a>
&lt;/h3>&lt;p>CAPI itself is k8s project that allows declaring k8s clusters in an easy way.&lt;/p>
&lt;p>The helm driver on the other hand is what acts like a bridge between OpenStack’s Magnum and Kubernetes’ Cluster API (CAPI). Its main goal is to to manage the lifecycle (create, scale, upgrade, destroy) of Kubernetes-conformant clusters using a declarative API.&lt;/p>
&lt;p>In order to do this, Cluster API provides an API for being able to manage the various components of a Kubernetes cluster. This conceptually looks like a Kubernetes cluster managing other Kubernetes clusters; the former, named the ‘CAPI management cluster’, is the one providing the API for managing the latter workload clusters.&lt;/p>
&lt;h3 id="decomposing-the-previous-atomic-feature">
Decomposing the previous atomic feature
&lt;a class="header-anchor" href="#decomposing-the-previous-atomic-feature">#&lt;/a>
&lt;/h3>&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img src="./Jetstream2-and-tent.png" alt="image" loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
(Comparison between Jetstream2 and other cloud providers when it comes to k8s support)&lt;/p>
&lt;p>Magnum is part of the OpenStack tent and it’s the first layer on top of Jetstream2 towards achieving k8s support.&lt;/p>
&lt;p>The CAPI helm driver is what’s offering CAPI support. This is the last piece that’s needed to link a k8s cluster down to the hardware where it’s deployed, on Jetstream2.&lt;/p>
&lt;h2 id="challenges">
Challenges
&lt;a class="header-anchor" href="#challenges">#&lt;/a>
&lt;/h2>&lt;p>The Jetstream2-OpenStack stack is not a simple one. It’s a complex stack of technologies and each of the connection points can be challenging to debug and fix when something doesn&amp;rsquo;t work. Especially when you are one of the first ones that pilots this new magnum driver setup.&lt;/p>
&lt;p>So, it was expected that we faced some issues along the way. However, we were able to go around them and add Jetstream2 to our service menu. Below is a list of some of the issues that we faced:&lt;/p>
&lt;ol>
&lt;li>We have to create terraform resource in sequence which takes longer because of a race condition that makes concurrent nodegroups creation requests to fail&lt;/li>
&lt;/ol>
&lt;ul>
&lt;li>
&lt;a href="https://bugs.launchpad.net/magnum/&amp;#43;bug/2097946" target="_blank" rel="noopener" >bugs.launchpad.net/magnum/+bug/2097946&lt;/a>&lt;/li>
&lt;/ul>
&lt;ol start="2">
&lt;li>The role and labels of the nodegroups don&amp;rsquo;t get propagated to the actual nodes, so we cannot put our own labels on nodes at once&lt;/li>
&lt;/ol>
&lt;ul>
&lt;li>
&lt;a href="https://github.com/azimuth-cloud/capi-helm-charts/issues/84" target="_blank" rel="noopener" >&lt;i class='fa-brands fa-github'>&lt;/i> azimuth-cloud/capi-helm-charts#84&lt;/a>&lt;/li>
&lt;/ul>
&lt;ol start="3">
&lt;li>The node count and min node count cannot be set to 0 and each nodegroup has to have at least 1 node&lt;/li>
&lt;/ol>
&lt;ul>
&lt;li>
&lt;a href="https://bugs.launchpad.net/magnum/&amp;#43;bug/2098002" target="_blank" rel="noopener" >bugs.launchpad.net/magnum/+bug/2098002&lt;/a>&lt;/li>
&lt;/ul>
&lt;ol start="4">
&lt;li>A default-worker is created apart from the default-control plane nodegroup and we cannot delete it due to the same issue as in 2.&lt;/li>
&lt;li>Latest CAPI helm chart version causes autoscaling to stop working in a persistent hub setup, so we had to downgrade it to a previous version&lt;/li>
&lt;/ol>
&lt;ul>
&lt;li>
&lt;a href="https://github.com/2i2c-org/infrastructure/issues/5601" target="_blank" rel="noopener" >&lt;i class='fa-brands fa-github'>&lt;/i> 2i2c-org/infrastructure#5601&lt;/a>&lt;/li>
&lt;/ul>
&lt;h2 id="conclusion">
Conclusion
&lt;a class="header-anchor" href="#conclusion">#&lt;/a>
&lt;/h2>&lt;p>The biggest plus, is the people. We got support from
&lt;a href="https://github.com/julianpistorius" target="_blank" rel="noopener" >Julian Pistorius&lt;/a>, which has helped us a lot to both fix and validate some of the behaviours we were experiencing. Also, going through the
&lt;a href="https://jetstream-cloud.org/contact/index.html" target="_blank" rel="noopener" >Jetstream2 support process&lt;/a> was also a pleasant experience because they were super prompt in answering and they were very nice.&lt;/p>
&lt;p>Jetstream2 has a big plus over the other cloud providers with its openness thought the ACCESS program. This is something very handy to researchers and less costly than other cloud providers. 2i2c being able to offer hubs though this ACCESS program makes things more accessible to more researchers and more cost efficient.&lt;/p>
&lt;p>Higher complexity comes also with more control over the infrastructure which has its advantages.&lt;/p>
&lt;p>Leaving the challenges apart, the experience was a nice one and the outcome was positive -&amp;gt; 2i2c is now able to deploy both mybinder.org-like hubs as well as persistent storage hubs on Jetstream2 hardware, from the same cloud-agnostic infrastructure.&lt;/p>
&lt;h2 id="acknowledgements">
Acknowledgements
&lt;a class="header-anchor" href="#acknowledgements">#&lt;/a>
&lt;/h2>&lt;p>Thanks to
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/pythia/" >Project Pythia&lt;/a> for funding and collaborating with us on this work.&lt;/p></description></item><item><title>Harnessing Marine Open Data Science for Ocean Sustainability in Africa, South Asia and Latin America</title><link>https://deploy-preview-608--2i2c-org.netlify.app/blog/hackweek-shoutout/</link><pubDate>Tue, 11 Mar 2025 00:00:00 +0000</pubDate><guid>https://deploy-preview-608--2i2c-org.netlify.app/blog/hackweek-shoutout/</guid><description>&lt;p>&lt;em>Thank you to Emilio Mayorga for sharing this publication.&lt;/em>&lt;/p>
&lt;p>Several community members, including
&lt;a href="https://github.com/paigem" target="_blank" rel="noopener" >Paige Martin&lt;/a> (Australian Climate Simulator),
&lt;a href="https://github.com/eeholmes" target="_blank" rel="noopener" >Eli Holmes&lt;/a> (NOAA Fisheries), and
&lt;a href="https://github.com/emiliom/" target="_blank" rel="noopener" >Emilio Mayorga&lt;/a> (University of Washington) published case studies in
&lt;a href="https://tos.org/oceanography/issue/volume-38-issue-1" target="_blank" rel="noopener" >Oceanography magazine&amp;rsquo;s &amp;ldquo;Vision for Capacity Sharing&amp;rdquo; issue&lt;/a>.&lt;/p>
&lt;p>Their article
&lt;a href="https://tos.org/oceanography/article/harnessing-marine-open-data-science-for-ocean-sustainability-in-africa-south-asia-and-latin-america" target="_blank" rel="noopener" >Harnessing Marine Open Data Science for Ocean Sustainability in Africa, South Asia, and Latin America&lt;/a> highlights the benefits of hackweek-style collaboration and learning events to build capacity in underrepresented communities, using 2i2c-supported JupyterHub for seamless set up and effective data sharing.&lt;/p>
&lt;p>More on these three specific initiatives is available at their respective websites:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://coessing.org" target="_blank" rel="noopener" >COESSING&lt;/a>, Coastal Ocean Environment Summer School In Nigeria and Ghana.&lt;/li>
&lt;li>
&lt;a href="https://intercoonecta.github.io" target="_blank" rel="noopener" >OHWe&lt;/a> - OceanHackWeek en Español (in Spanish).&lt;/li>
&lt;li>
&lt;a href="https://hackweek-itcoocean.github.io/2023-Hackbook/" target="_blank" rel="noopener" >ITCOocean Hack2Week&lt;/a> (an Indian Ocean program). Training Course &amp;amp; HackWeek On Machine Learning Based Species Distribution Modeling.&lt;/li>
&lt;/ul>
&lt;p>We&amp;rsquo;re happy to see these communities extend their impact and make interactive computing more accessible to participants around the world.&lt;/p></description></item><item><title>Chris is joining Project Jupyter's Executive Council</title><link>https://deploy-preview-608--2i2c-org.netlify.app/blog/jupyter-executive-council/</link><pubDate>Mon, 10 Mar 2025 00:00:00 +0000</pubDate><guid>https://deploy-preview-608--2i2c-org.netlify.app/blog/jupyter-executive-council/</guid><description>&lt;p>We are proud to announce that 2i2c&amp;rsquo;s Executive Director, Chris Holdgraf, was
&lt;a href="https://blog.jupyter.org/project-jupyters-2025-executive-council-elections-605b183ec64c" target="_blank" rel="noopener" >recently elected to Jupyter&amp;rsquo;s Executive Council&lt;/a>. The 2i2c team discussed whether Chris should run for this position last year, and concluded that it was a way for our non-profit to both support Jupyter&amp;rsquo;s mission at a strategic level, and represent the interests of research and education communities in Jupyter&amp;rsquo;s direction. Chris wrote
&lt;a href="https://chrisholdgraf.com/blog/jupyter-org-structure" target="_blank" rel="noopener" >a blog post about his reasons for running&lt;/a> with more information.&lt;/p>
&lt;p>One of Chris&amp;rsquo; goals is to be a transparent source of information about what the council is working on, where its priorities lie, and what are the major challenges it is trying to tackle. He&amp;rsquo;s written two blog posts that describe some of his experiences so far, at the links below:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://chrisholdgraf.com/blog/os-support" target="_blank" rel="noopener" >On the ways that the Jupyter Foundation could support the Jupyter Project with its funds&lt;/a>&lt;/li>
&lt;li>
&lt;a href="https://chrisholdgraf.com/blog/jupyter-org-structure" target="_blank" rel="noopener" >A high-level overview of Jupyter&amp;rsquo;s structure&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>We&amp;rsquo;re hopeful that this is a way for 2i2c to scale its impact and lean into its
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/open-technology/" >commitment to open technology&lt;/a>. Chris intends to keep writing about his personal experience via
&lt;a href="https://chrisholdgraf.com" target="_blank" rel="noopener" >his blog&lt;/a>, and we&amp;rsquo;ll provide updates here for major developments that are relevant to 2i2c&amp;rsquo;s network of communities.
We&amp;rsquo;re proud to have Chris in this role, and excited for his contributions to the Jupyter community!&lt;/p>
&lt;h2 id="acknowledgements">
Acknowledgements
&lt;a class="header-anchor" href="#acknowledgements">#&lt;/a>
&lt;/h2>&lt;ul>
&lt;li>Strategic open source support like this is supported by a grant from
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/navigation/" >The Navigation Fund&lt;/a> and fees from
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/members/" >our member organizations&lt;/a>.&lt;/li>
&lt;/ul></description></item><item><title>Simplifying and speeding up Binder builds with BuildKit</title><link>https://deploy-preview-608--2i2c-org.netlify.app/blog/binder-buildkit/</link><pubDate>Mon, 03 Mar 2025 00:00:00 +0000</pubDate><guid>https://deploy-preview-608--2i2c-org.netlify.app/blog/binder-buildkit/</guid><description>&lt;p>Chris and Yuvi recently wrote
&lt;a href="https://blog.jupyter.org/simplifying-and-speeding-up-binder-builds-with-buildkit-d44f96582994" target="_blank" rel="noopener" >a blog post on the Jupyter blog&lt;/a> about a recent experiment to significantly reduce the cost of running a node on the mybinder.org federation.&lt;/p>
&lt;h2 id="acknowledgements">
Acknowledgements
&lt;a class="header-anchor" href="#acknowledgements">#&lt;/a>
&lt;/h2>&lt;ul>
&lt;li>
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/pythia/" >Project Pythia&lt;/a> and
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/nasa-open-science/" >NASA Open Science / ScienceCore&lt;/a> provide support for some of our work with the Binder project.&lt;/li>
&lt;li>
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/jupyterhub/" >JupyterHub&lt;/a> for working with us to get this new node deployed for mybinder.org.&lt;/li>
&lt;/ul></description></item><item><title>Enforcing per-user storage quotas now available on GCP</title><link>https://deploy-preview-608--2i2c-org.netlify.app/blog/per-user-storage-quota-gcp/</link><pubDate>Tue, 25 Feb 2025 14:18:04 +0000</pubDate><guid>https://deploy-preview-608--2i2c-org.netlify.app/blog/per-user-storage-quota-gcp/</guid><description>&lt;p>Building upon our previous work developing
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/blog/per-user-storage-quota/" >per-user storage quotas for our AWS infrastructure&lt;/a>, we are pleased to announce that this feature is now available for GCP-hosted hubs!&lt;/p>
&lt;p>To provide this feature on this vendor, we have updated our infrastructure provisioning system to create persistent disks, and enable automatic backups of the disk for disaster recovery purposes. However, the systems we had already developed for AWS, such as
&lt;a href="https://github.com/2i2c-org/jupyterhub-home-nfs" target="_blank" rel="noopener" >&lt;code>jupyterhub-home-nfs&lt;/code>&lt;/a> and our alerting system through
&lt;a href="https://prometheus.io/docs/alerting/latest/alertmanager/" target="_blank" rel="noopener" >Prometheus Alertmanager&lt;/a>, are vendor agnostic and work right out of the box with the new architecture!&lt;/p>
&lt;p>If you would like to try this feature on your 2i2c-managed JupyterHub,
&lt;a href="https://docs.2i2c.org/support" target="_blank" rel="noopener" >please get in touch&lt;/a>.&lt;/p>
&lt;h2 id="acknowledgements">
Acknowledgements
&lt;a class="header-anchor" href="#acknowledgements">#&lt;/a>
&lt;/h2>&lt;p>This project was developed and deployed in collaboration with
&lt;a href="https://developmentseed.org/team/tarashish-mishra/" target="_blank" rel="noopener" >Tarashish Mishra&lt;/a> from
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/devseed/" >Development Seed&lt;/a>, funded through the
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/nasa-veda/" >NASA VEDA project&lt;/a>.&lt;/p></description></item><item><title>Open infrastructure for collaborative geoscience with Project Pythia: Learning how to deploy a BinderHub on Jetstream2</title><link>https://deploy-preview-608--2i2c-org.netlify.app/blog/jetstream-binderhub/</link><pubDate>Wed, 12 Feb 2025 00:00:00 +0000</pubDate><guid>https://deploy-preview-608--2i2c-org.netlify.app/blog/jetstream-binderhub/</guid><description>
&lt;h2 id="project-pythia-and-the-jupyter-notebook-obsolescence-problem">
Project Pythia and the &amp;ldquo;Jupyter notebook obsolescence&amp;rdquo; problem
&lt;a class="header-anchor" href="#project-pythia-and-the-jupyter-notebook-obsolescence-problem">#&lt;/a>
&lt;/h2>&lt;p>
&lt;a href="https://projectpythia.org/" target="_blank" rel="noopener" >Project Pythia&lt;/a> provides educational resources for essential software tools that enable open, reproducible and scalable geoscience, such as the
&lt;a href="https://pangeo.io" target="_blank" rel="noopener" >Pangeo&lt;/a> stack of packages (Xarray, Dask, Jupyter). Their &lt;em>Cookbooks&lt;/em> are crowdsourced, community-curated, and open-source collections of Jupyter notebooks that demonstrate how to use these tools for cloud-native, geoscientific workflows (see our
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/contentblog/2024/project-pythia-cookoff/index.md" >Project Pythia Cookoff&lt;/a> blog post). However, &amp;ldquo;Jupyter notebook obsolescence&amp;rdquo; is a common problem: tutorials that were created a few years ago may no longer work due to changes in the software ecosystem and hampers the reproducibility of scientific results. A reproducible execution environment and the infrastructure to support it are essential for the long-term sustainability of these educational resources.&lt;/p>
&lt;h2 id="leveraging-nsf-funded-cyberinfrastructure-for-binderhub">
Leveraging NSF-funded cyberinfrastructure for BinderHub
&lt;a class="header-anchor" href="#leveraging-nsf-funded-cyberinfrastructure-for-binderhub">#&lt;/a>
&lt;/h2>&lt;p>A
&lt;a href="https://binderhub.readthedocs.io/en/latest/" target="_blank" rel="noopener" >BinderHub&lt;/a> allows users to dynamically create custom computing environments from
&lt;a href="https://mybinder.readthedocs.io/en/latest/introduction.html#what-is-a-binder" target="_blank" rel="noopener" >Binder-ready&lt;/a> repositories containing computational notebooks and configuration files that describe the software environment required to run them. A public Binder service exists at
&lt;a href="https://mybinder.org/" target="_blank" rel="noopener" >mybinder.org&lt;/a> (see our blog post about
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/blog/binder-singlenode/" >joining the mybinder federation&lt;/a> 🎉) and is a successful example of how open cloud infrastructure can accommodate reproducible execution environments.&lt;/p>
&lt;p>The resources available on such a public service are limited therefore 2i2c, together with Project Pythia, have been exploring how to deploy a BinderHub backed by larger resources from the NSF-funded cloud computing platform
&lt;a href="https://jetstream-cloud.org/" target="_blank" rel="noopener" >Jetstream2&lt;/a>. This allows for larger simultaneous user loads, such as at workshops, as well as access to more powerful distributed and parallelized workflows required to process large geoscientific datasets, under a persistent resource allocation.&lt;/p>
&lt;h2 id="learning-how-to-deploy-on-openstack">
Learning how to deploy on OpenStack
&lt;a class="header-anchor" href="#learning-how-to-deploy-on-openstack">#&lt;/a>
&lt;/h2>&lt;p>Jetstream2 uses
&lt;a href="https://www.openstack.org" target="_blank" rel="noopener" >OpenStack&lt;/a> in order to manage pools of compute, storage and networking resources, and for our purposes we specifically make use of OpenStack
&lt;a href="https://docs.openstack.org/magnum/latest/" target="_blank" rel="noopener" >Magnum&lt;/a>
&lt;a href="https://specs.openstack.org/openstack//magnum-specs/specs/bobcat/clusterapi-driver.html" target="_blank" rel="noopener" >Cluster API driver&lt;/a> to manage Kubernetes for our deployment.&lt;/p>
&lt;p>Cluster API needs a &lt;code>CAPI management cluster&lt;/code> in order to manage other Kubernetes clusters, called workload clusters. On Jetstream2, this management cluster is gracefully created and operated by the Jetstream2 team, which means that the only task to worry about is creating and configuring the workload cluster.&lt;/p>
&lt;p>For the workload cluster we used the
&lt;a href="https://registry.terraform.io/providers/terraform-provider-openstack/openstack/latest/docs" target="_blank" rel="noopener" >Openstack Terraform provider&lt;/a> to define the cluster template, the cluster itself and the node groups in a reproducible way.&lt;/p>
&lt;p>After the cluster infrastructure was successfully created on Jetstream2, thanks to the 2i2c hub infrastructure being cloud agnostic as well, deploying BinderHub to Jetstream2, was a seamless experience and it was no different than on other cloud providers that we already supported.&lt;/p>
&lt;p>We also learnt about some limitations of the Openstack Magnum driver project, which were expected given it being a relatively recent project, slowly being adopted, but they were all reported upstream and hopefully will soon be fixed.&lt;/p>
&lt;h2 id="acknowledgements">
Acknowledgements
&lt;a class="header-anchor" href="#acknowledgements">#&lt;/a>
&lt;/h2>&lt;ul>
&lt;li>
&lt;a href="https://jetstream-cloud.org/" target="_blank" rel="noopener" >Jetstream2&lt;/a>: Explore ACCESS allocation and Julian Pistorius for technical support&lt;/li>
&lt;li>Thanks to
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/pythia/" >Project Pythia&lt;/a> for funding and collaborating with us on this work.&lt;/li>
&lt;li>
&lt;a href="https://www.zonca.dev/posts/2024-12-11-jetstream_kubernetes_magnum" target="_blank" rel="noopener" >Andrea Zonca&lt;/a> for preliminary work on Kubernetes deployments on Jetstream 2&lt;/li>
&lt;/ul></description></item><item><title>Announcing backups for GCP-hosted hubs!</title><link>https://deploy-preview-608--2i2c-org.netlify.app/blog/gcp-filestore-backups/</link><pubDate>Fri, 07 Feb 2025 13:08:22 +0000</pubDate><guid>https://deploy-preview-608--2i2c-org.netlify.app/blog/gcp-filestore-backups/</guid><description>&lt;p>2i2c are pleased to announce the development and deployment of automated backups of home directories on GCP-hosted hubs!&lt;/p>
&lt;p>We have developed the
&lt;a href="https://github.com/2i2c-org/gcp-filestore-backups" target="_blank" rel="noopener" >&lt;code>gcp-filestore-backups&lt;/code> project&lt;/a> that regularly creates backups of JupyterHub home directories for disaster recovery purposes. The project is a Python wrapper around the
&lt;a href="https://cloud.google.com/sdk/gcloud" target="_blank" rel="noopener" >&lt;code>gcloud&lt;/code> tool&lt;/a> to regularly request backups be made of the Filestore hosting JupyterHub&amp;rsquo;s user home directories, by default on a daily basis. The script also manages retention of these backups by checking how recently the last backup was made, and the age of existing backups, by default deleting any backup older than 5 days.&lt;/p>
&lt;p>Having these backups enabled means that, in the unlikely and unfortunate case of data loss or corruption, we can reinstate the home directories of the hub to a relatively recent state that is at a maximum of 1 day prior to the incident.&lt;/p>
&lt;p>We have deployed &lt;code>gcp-filestore-backups&lt;/code> to all our GCP hubs presently running, with a retention period of 2 days. If you would like to discuss this further with us,
&lt;a href="https://docs.2i2c.org/support" target="_blank" rel="noopener" >please get in touch!&lt;/a>&lt;/p>
&lt;p>As ever, this project has been developed openly in line with our
&lt;a href="https://2i2c.org/right-to-replicate/" target="_blank" rel="noopener" >Right to Replicate&lt;/a> so you can deploy it against your own infrastructure!&lt;/p></description></item><item><title>Our product goals for Q1 2025</title><link>https://deploy-preview-608--2i2c-org.netlify.app/blog/q1-product-goals/</link><pubDate>Sat, 01 Feb 2025 00:00:00 +0000</pubDate><guid>https://deploy-preview-608--2i2c-org.netlify.app/blog/q1-product-goals/</guid><description>&lt;p>&lt;em>This quarterly post is coming out a little bit late - our goal was to post this in early January, but the year has been more complicated than we bargained for :-)&lt;/em>&lt;/p>
&lt;p>Over the past year, 2i2c has made team-wide efforts to improve our product planning and delivery. A key part of this is re-organizing an integrated
&lt;a href="https://compass.2i2c.org/product-and-services/" target="_blank" rel="noopener" >Product and Services team&lt;/a> that brings our strategic planning, engineering, and service delivery closer together. We&amp;rsquo;ve also built systems for planning and measuring progress within the P&amp;amp;S team, and a product initiatives system for planning major work.&lt;/p>
&lt;p>Our goal is to &lt;strong>organize our product work around a small set of core themes&lt;/strong> to help us focus and prioritize. As part of this, we’d like to share platform enhancement goals for roughly each quarter. These are not guarantees, but we share them to be transparent about where we think we can be the most impactful in the next few months. Here are the major areas we hope to improve 2i2c’ platform in Q1 2025.&lt;/p>
&lt;h2 id="expand-access-to-cloud-providers-and-improve-data-safety">
Expand access to cloud providers and improve data safety
&lt;a class="header-anchor" href="#expand-access-to-cloud-providers-and-improve-data-safety">#&lt;/a>
&lt;/h2>&lt;p>One of 2i2c&amp;rsquo;s goals is to showcase the ability of open infrastructure to be deployed on a variety of infrastructure proiders. This includes user-facing features, as well as guardrails and safety measures.&lt;/p>
&lt;p>&lt;strong>In Q1 2025&lt;/strong> we are working to bring closer feature parity between hub deployments on AWS and GCP, while enabling disaster recovery with automated home directory backups.&lt;/p>
&lt;h2 id="explore-deploying-on-public-infrastructure-providers">
Explore deploying on public infrastructure providers
&lt;a class="header-anchor" href="#explore-deploying-on-public-infrastructure-providers">#&lt;/a>
&lt;/h2>&lt;p>Many communities in research and education are interested in leveraging publicly-owned infrastructure providers like
&lt;a href="https://jetstream-cloud.org/index.html" target="_blank" rel="noopener" >JetStream 2&lt;/a> and the
&lt;a href="https://nationalresearchplatform.org/" target="_blank" rel="noopener" >National Research Platform&lt;/a>. While 2i2c has historically focused on commercial cloud due to their highly-reliable Kubernetes platforms, we think it is important to explore publicly-owned infrastructure providers as well.&lt;/p>
&lt;p>&lt;strong>In Q1 2025&lt;/strong> we&amp;rsquo;ll begin this expansion by deploying JupyterHubs and BinderHubs on JetStream 2, which will give communities access to publicly-funded computing resources. We will use this experience to decide whether it&amp;rsquo;s sustainable for us to deploy on this and other publicly-owned infrastructure providers.&lt;/p>
&lt;h2 id="enable-enhanced-community-knowledge-bases-with-jupyter-book-2">
Enable enhanced community knowledge bases with Jupyter Book 2
&lt;a class="header-anchor" href="#enable-enhanced-community-knowledge-bases-with-jupyter-book-2">#&lt;/a>
&lt;/h2>&lt;p>A key theme we aim to enable is &lt;strong>sharing&lt;/strong> within and between community hubs. This is a critical part of the data science workflow because it allows people to collaborate on the same ideas, and build on top of one another&amp;rsquo;s ideas. An early target for this is to facilitate lightweight sharing of computational content so that community members can learn from one another more effectively.&lt;/p>
&lt;p>&lt;strong>In Q1 2025&lt;/strong> we want to help get
&lt;a href="https://next.jupyterbook.org" target="_blank" rel="noopener" >Jupyter Book 2&amp;rsquo;s beta&lt;/a> released, and provide an out-of-the-box configuration for our communities to use it with their hubs. This includes adding landing pages and better integration with JupyterHub via launch buttons to create a more seamless experience between documentation and interactive computing.&lt;/p>
&lt;h2 id="enable-sharing-reproducible-environments-on-a-hub">
Enable sharing reproducible environments on a hub
&lt;a class="header-anchor" href="#enable-sharing-reproducible-environments-on-a-hub">#&lt;/a>
&lt;/h2>&lt;p>Another key aspect of sharing is &lt;strong>sharing the computational environment as well&lt;/strong>. This would allow communities to not only sheir their content, but also live infrastructure that allows others to reproduce and interact with their work. We think that investing more time into imiproving and deploying
&lt;a href="https://binderhub.readthedocs.io/en/latest/" target="_blank" rel="noopener" >BinderHubs&lt;/a> (the technology behind
&lt;a href="https://mybinder.org" target="_blank" rel="noopener" >mybinder.org&lt;/a>) will help us learn more about how to make this a reality.&lt;/p>
&lt;p>&lt;strong>In Q1 2025&lt;/strong> we plan to grow our capacity to deploy BinderHubs across multiple cloud providers. This will allow hub users to build their own Binder environments on the fly and make it possible to share these environments with others, enabling better reproducibility and collaboration within communities.&lt;/p>
&lt;h2 id="give-communities-more-visibility-and-control-over-their-hub-setup-and-costs">
Give communities more visibility and control over their hub setup and costs
&lt;a class="header-anchor" href="#give-communities-more-visibility-and-control-over-their-hub-setup-and-costs">#&lt;/a>
&lt;/h2>&lt;p>Perhaps the biggest perceived risk to using cloud infrastructure is the possibility of &lt;strong>runaway costs&lt;/strong>. Community leaders are often nervous that something unexpected will happen and they&amp;rsquo;ll have to foot a giant bill at the end of the month. We think that reducing this risk is a key way to make cloud infrastructure safer and more useful for research and education communities.&lt;/p>
&lt;p>&lt;strong>In Q1 2025&lt;/strong> we are aim to add more &lt;strong>visibility into hub usage&lt;/strong> and &lt;strong>more controls over resources via quotas&lt;/strong>. This will allow more fine control over resource budgets such as CPU, memory, and storage. We&amp;rsquo;ll also work on &lt;strong>assigning users to groups&lt;/strong>, allowing communities greater control over resource allocation across large user bases.&lt;/p>
&lt;h2 id="standardize-our-hub-service-menu-of-options-and-prices">
Standardize our hub service menu of options and prices
&lt;a class="header-anchor" href="#standardize-our-hub-service-menu-of-options-and-prices">#&lt;/a>
&lt;/h2>&lt;p>A key goal of our
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/blog/q1-product-goals/../2024/funding-navigation/index.md" >Navigation Fund grant&lt;/a> is to streamline ourselves into a few repeatable, scalable service offerings at different price points. This will allow us to more easily support new communities and provide a more consistent experience for users.&lt;/p>
&lt;p>&lt;strong>In Q1 2025&lt;/strong> we&amp;rsquo;d like to define a starting point that we can begin to iterate on. We&amp;rsquo;ll define a new set of pricing based around a tiered service model, and decide on an initial set of features and services to include with each. Our goal will be to have something defined quickly so that we can iterate a few times with community feedback before the quarter is over.&lt;/p>
&lt;h2 id="standardize-our-community-support-services">
Standardize our community support services
&lt;a class="header-anchor" href="#standardize-our-community-support-services">#&lt;/a>
&lt;/h2>&lt;p>Finally, we&amp;rsquo;ve audited our ongoing support practices and realized that we aren&amp;rsquo;t always delivering them in an efficient way. We often share the same information one-on-one conversations, and aren&amp;rsquo;t effectively leveraging our community network to support and learn from one another. We&amp;rsquo;d like to standardize and boost the scalability of our support services.&lt;/p>
&lt;p>&lt;strong>In Q1 2025&lt;/strong> we want to explore how we can more scalably and efficiently provide hands-on guidance, expert co-creation, and support to communities. Our goal is to define a starting point for these services so that we can offer this support in a sustainable way and begin to learn from our experiences. We also want to build a mechanism for scoping (and pricing) additional capacity that is needed beyond standard community services.&lt;/p>
&lt;h2 id="another-update-coming-in-q2">
Another update coming in Q2
&lt;a class="header-anchor" href="#another-update-coming-in-q2">#&lt;/a>
&lt;/h2>&lt;p>Our aim is to use this blog post as a guide for the quarter, and to make progress in as many areas above as we can. As part of our Q2 planning process, we&amp;rsquo;ll provide a retrospective on the accomplishments we&amp;rsquo;ve made towards this effort, and will provide an update for our community on our progress. Stay tuned for more!&lt;/p>
&lt;h2 id="acknowledgements">
Acknowledgements
&lt;a class="header-anchor" href="#acknowledgements">#&lt;/a>
&lt;/h2>&lt;ul>
&lt;li>Our strategic and organization-level work is supported by a grant from
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/navigation/" >The Navigation Fund&lt;/a> and fees from
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/members/" >our member organizations&lt;/a>.&lt;/li>
&lt;/ul></description></item><item><title>2i2c joins the mybinder.org federation with a cheaper and faster way to deploy Binderhub</title><link>https://deploy-preview-608--2i2c-org.netlify.app/blog/binder-singlenode/</link><pubDate>Wed, 29 Jan 2025 00:00:00 +0000</pubDate><guid>https://deploy-preview-608--2i2c-org.netlify.app/blog/binder-singlenode/</guid><description>&lt;div class="alert alert-note">
&lt;div>
If you&amp;rsquo;re interested in supporting &lt;code>mybinder.org&lt;/code> with cloud resources, financial resources, or human resources, please see the
&lt;p>&lt;a href="https://mybinder.readthedocs.io/en/latest/about/support.html" target="_blank" rel="noopener" >Support Binder&lt;/a> page for how you can help.&lt;/p>
&lt;/div>
&lt;/div>
&lt;blockquote>
&lt;p>&lt;code>tl;dr&lt;/code>: The 2i2c team is joining the mybinder.org federation with a
&lt;a href="https://github.com/jupyterhub/mybinder.org-deploy/pull/3169/" target="_blank" rel="noopener" >single-node BinderHub instance at &lt;code>2i2c.mybinder.org&lt;/code>&lt;/a>. It should be much cheaper to run than auto-scaling Kubernetes clusters, and might be a good way to support &lt;code>mybinder.org&lt;/code> more sustainably. For questions or comments, join
&lt;a href="https://jupyter.zulipchat.com/#narrow/channel/469744-jupyterhub/topic/ANN.3A.202i2c.20joins.20mybinder.2Eorg.20federation.20with.20new.20strategy/near/496811301" target="_blank" rel="noopener" >this Jupyter Zulip thread&lt;/a>.&lt;/p>
&lt;/blockquote>
&lt;p>
&lt;a href="https://mybinder.org" target="_blank" rel="noopener" >&lt;code>mybinder.org&lt;/code>&lt;/a> is a massive public service for creating and sharing reproducible computational environments. It is managed by the JupyterHub team and
&lt;a href="https://mybinder.readthedocs.io/en/latest/about/federation.html" target="_blank" rel="noopener" >members of the &lt;code>mybinder.org&lt;/code> federation&lt;/a>. One challenge in running
&lt;a href="https://mybinder.org" target="_blank" rel="noopener" >&lt;code>mybinder.org&lt;/code>&lt;/a> is identifying cloud credits or financial resources to support the cloud infrastructure that runs the service. Two years ago,
&lt;a href="https://medium.com/jupyter-blog/mybinder-org-reducing-capacity-c93ccfc6413f" target="_blank" rel="noopener" >Google stopped supporting &lt;code>mybinder.org&lt;/code> federation with cloud credits&lt;/a>, and last month
&lt;a href="https://discourse.jupyter.org/t/mybinder-org-reduced-capacity-stability/31750" target="_blank" rel="noopener" >the federation lost more capacity&lt;/a>, leaving only
&lt;a href="https://www.gesis.org/en/home" target="_blank" rel="noopener" >GESIS&lt;/a> and
&lt;a href="https://us.ovhcloud.com/" target="_blank" rel="noopener" >OVH&lt;/a> as remaining federation members&lt;sup id="fnref:1">&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref">1&lt;/a>&lt;/sup>. This makes &lt;code>mybinder.org&lt;/code> less reliable, slower, and generally less useful to the world.&lt;/p>
&lt;p>The landscape of cloud infrastructure technology and services has changed considerably, and we think that there&amp;rsquo;s a way to deploy BinderHub instances with lower costs and less complexity. We&amp;rsquo;ve accomplished this by deploying a &lt;strong>single-node Kubernetes cluster&lt;/strong> on a VM provider that is much cheaper, now running at &lt;code>2i2c.mybinder.org&lt;/code>. This both relieves Binder&amp;rsquo;s short-term capacity shortage and may provide an easier pathway for others to support the project in the future.&lt;/p>
&lt;p>Below, we&amp;rsquo;ll describe what has changed to enable this, what we&amp;rsquo;re deploying, and what the impact should be.&lt;/p>
&lt;h2 id="cloud-infrastructure-has-become-cheaper-and-more-commodified">
Cloud infrastructure has become cheaper and more commodified
&lt;a class="header-anchor" href="#cloud-infrastructure-has-become-cheaper-and-more-commodified">#&lt;/a>
&lt;/h2>&lt;p>A key theory of mybinder.org (and 2i2c) is that commercial cloud infrastructure will be commidified over time &amp;ndash; what begins as cutting-edge functionality will become commonplace and offered across all cloud providers. As a result, costs will go down over time. Abstractions like
&lt;a href="https://kubernetes.io/" target="_blank" rel="noopener" >Kubernetes&lt;/a> will allow you to easily migrate workflows and infrastructure between cloud providers. As a result, you&amp;rsquo;ll be able to easily &lt;em>follow those costs&lt;/em> where there are better options. That&amp;rsquo;s essentially what is happening here.&lt;/p>
&lt;p>There are two key changes that make it much easier to deploy a BinderHub instance at a fraction of the cost:&lt;/p>
&lt;p>First, &lt;strong>Kubernetes has matured and become easier to deploy&lt;/strong>. When mybinder.org started, it was using the cutting-edge of Kubernetes functionality. This meant that we needed to use cloud providers that provided a &lt;em>managed Kubernetes service&lt;/em> to deal with this complexity. A managed Kubernetes offering tends to be expensive, offered by only a few cloud providers, and thus raises costs across-the-board for the provider that offers it.&lt;/p>
&lt;p>However, this was almost a decade ago, and Kubernetes has become both more functional and more stable. There are now many more ways of running Kubernetes, especially for simpler workflows that don&amp;rsquo;t require autoscaling. In the last several months, we&amp;rsquo;ve been experimenting with &lt;strong>single-node Kubernetes workflows&lt;/strong> via
&lt;a href="https://k3s.io/" target="_blank" rel="noopener" >K3s&lt;/a>&lt;sup id="fnref:2">&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref">2&lt;/a>&lt;/sup>.
&lt;a href="https://k3s.io/" target="_blank" rel="noopener" >K3s&lt;/a> is a lightweight Kubernetes distribution that is much easier to deploy and manage. It&amp;rsquo;s designed for things like edge computing and low-resource environments, and it can be deployed with a single script!&lt;/p>
&lt;p>By running a Kubernetes cluster on a single node, we don&amp;rsquo;t need a &amp;ldquo;managed Kubernetes service&amp;rdquo;, which means &lt;strong>we can choose from a much larger pool of infrastructure / cloud providers&lt;/strong>. If all we need is a running VM, this is something the tech industry has been doing for decades.&lt;/p>
&lt;p>Second, &lt;strong>Managed Object Storage services have more open source options, and are more commodified and cheaper&lt;/strong>. In addition to Kubernetes, the other thing that BinderHub needs is a way to store and retrieve images for the environments that it builds. This also used to be a fairly complex problem, and thus required managed solutions from cloud providers that charged a premium for their service. However, a number of open source object storage solutions have emerged and made it much easier for providers to support this workflow.&lt;sup id="fnref:3">&lt;a href="#fn:3" class="footnote-ref" role="doc-noteref">3&lt;/a>&lt;/sup>. Because these are open source, infrastructure providers can provide managed object storage at a fraction of the cost.&lt;/p>
&lt;p>Because of these two things, we&amp;rsquo;ve learned that we can run a BinderHub instance on a single VM from a much larger pool of infrastructure providers. This means &lt;strong>we should be able to run BinderHub instances at a fraction of the cost&lt;/strong>.&lt;sup id="fnref:4">&lt;a href="#fn:4" class="footnote-ref" role="doc-noteref">4&lt;/a>&lt;/sup>&lt;/p>
&lt;h2 id="deploying-binderhub-on-a-single-node-vm-is-cheaper-and-simpler">
Deploying BinderHub on a single-node VM is cheaper and simpler
&lt;a class="header-anchor" href="#deploying-binderhub-on-a-single-node-vm-is-cheaper-and-simpler">#&lt;/a>
&lt;/h2>&lt;p>Last week, we
&lt;a href="https://github.com/jupyterhub/mybinder.org-deploy/pull/3169" target="_blank" rel="noopener" >deployed 2i2c.mybinder.org&lt;/a>, a single-node Kubernetes instance on
&lt;a href="https://hetzner.com/cloud" target="_blank" rel="noopener" >Hetzner&lt;/a> cloud using
&lt;a href="https://k3s.io/" target="_blank" rel="noopener" >K3s&lt;/a>. This will run on a single node VM, with a Kubernetes instance that is entirely managed by us, and with managed object storage from Hetzner. Compared to other cloud providers, it is &lt;strong>around 5x cheaper per month&lt;/strong>.&lt;/p>
&lt;figure id="figure-comparison-of-rough-monthly-costs-across-different-cloud-providers-for-similar-vm-instances-these-are-rough-estimates-based-on-cloud-provider-pricing-pages-for-an-on-demand-vm-with-around-190gb-ram-pricing-pages-hetzner-cloudhttpswwwhetznercomcloud-300-microsoft-azurehttpsazurecomeda6294b08dfa49639f74caad1630bbe4-1300-google-cloud-platformhttpscloudgooglecomproductscalculatorhlendlcjhdavjrwlrbevpeumpnqzawtvrrmkxuumtnalv0t0rnnu5pmhpav1eywlrnmfphsxppve1rqve9praigirdrtq3qtywqy1dnum5ltq3qkqtqtm3ms05mjbcqju1qjngrjg-1500-amazon-web-serviceshttpscalculatorawsestimateida3bddb8bdbfa2058b941b669e408141e7fd18da4-1600">
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="Comparison of rough monthly costs across different cloud providers for similar VM instances. These are rough estimates based on cloud provider pricing pages for an on-demand VM with around 190GB RAM. Pricing pages: [Hetzner Cloud](https://www.hetzner.com/cloud) ~$300, [Microsoft Azure](https://azure.com/e/da6294b08dfa49639f74caad1630bbe4) ~$1,300, [Google Cloud Platform](https://cloud.google.com/products/calculator?hl=en&amp;amp;dl=CjhDaVJrWlRBeVpEUmpNQzAwTVRrMkxUUmtNalV0T0RnNU5pMHpaV1EyWlRnMFpHSXpPVE1RQVE9PRAIGiRDRTQ3QTYwQy1DNUM5LTQ3QkQtQTM3MS05MjBCQjU1QjNGRjg) ~$1,500, [Amazon Web Services](https://calculator.aws/#/estimate?id=a3bddb8bdbfa2058b941b669e408141e7fd18da4) ~$1,600." srcset="
/blog/binder-singlenode/featured_hu5599e630254656f9a400bcb8f9798a4e_195115_f1bc2f9ecf0ebdbd21595b574119a81a.webp 400w,
/blog/binder-singlenode/featured_hu5599e630254656f9a400bcb8f9798a4e_195115_79d88c8c7dddbe75eeb374dc7b9a0c75.webp 760w,
/blog/binder-singlenode/featured_hu5599e630254656f9a400bcb8f9798a4e_195115_1200x1200_fit_q75_h2_lanczos_3.webp 1200w"
src="https://deploy-preview-608--2i2c-org.netlify.app/blog/binder-singlenode/featured_hu5599e630254656f9a400bcb8f9798a4e_195115_f1bc2f9ecf0ebdbd21595b574119a81a.webp"
width="760"
height="540"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;figcaption>
Comparison of rough monthly costs across different cloud providers for similar VM instances. These are rough estimates based on cloud provider pricing pages for an on-demand VM with around 190GB RAM. Pricing pages:
&lt;a href="https://www.hetzner.com/cloud" target="_blank" rel="noopener" >Hetzner Cloud&lt;/a> ~$300,
&lt;a href="https://azure.com/e/da6294b08dfa49639f74caad1630bbe4" target="_blank" rel="noopener" >Microsoft Azure&lt;/a> ~$1,300,
&lt;a href="https://cloud.google.com/products/calculator?hl=en&amp;amp;dl=CjhDaVJrWlRBeVpEUmpNQzAwTVRrMkxUUmtNalV0T0RnNU5pMHpaV1EyWlRnMFpHSXpPVE1RQVE9PRAIGiRDRTQ3QTYwQy1DNUM5LTQ3QkQtQTM3MS05MjBCQjU1QjNGRjg" target="_blank" rel="noopener" >Google Cloud Platform&lt;/a> ~$1,500,
&lt;a href="https://calculator.aws/#/estimate?id=a3bddb8bdbfa2058b941b669e408141e7fd18da4" target="_blank" rel="noopener" >Amazon Web Services&lt;/a> ~$1,600.
&lt;/figcaption>&lt;/figure>
&lt;!-- Machines for the figure above:
Hetzner: CCX63
Amazon Web Services: m8g.12xlarge
Google Cloud Platform: n2-standard-48
Microsoft Azure: D48as v5
-->
&lt;p>Running a single-node Kubernetes instance will be a cheap and effective way to handle a lot of &lt;code>mybinder.org&lt;/code>&amp;rsquo;s capacity needs. Because it&amp;rsquo;s a single node cluster, there is no auto-scaling (one reason it is so cheap), which reduces a lot of the complexity we&amp;rsquo;ll have to manage. These are acceptable tradeoffs for a service like &lt;code>mybinder.org&lt;/code>, which runs entirely ephemeral sessions with very limited resources and no promises about uptime, persistence, etc.&lt;/p>
&lt;p>You might be wondering: &amp;ldquo;I thought Kubernetes was supposed to &lt;em>save money&lt;/em>.&amp;rdquo; Normally, running Kubernetes for scalable workflows does save costs because you can scale infrastructure to match your capacity needs. Without scaling, you&amp;rsquo;d need to provide a VM that can &lt;em>always&lt;/em> handle your &lt;em>maximum capacity&lt;/em> needs (and pay for the costs the entire time). With Kubernetes, you can request and remove nodes to grow your capacity as-needed (and save money doing so). It looks something like this:&lt;/p>
&lt;figure id="figure-the-cost-difference-between-a-single-large-vm-vs-scalable-nodes-given-variable-usage-over-time-kubernetes-allows-you-to-scale-your-cost-up-and-down-with-need-which-is-more-efficient-than-paying-for-a-single-vm-that-can-withstand-your-maximum-capacity">
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="The cost difference between a single large VM vs scalable nodes. Given variable usage over time, kubernetes allows you to scale your cost up and down with need, which is more efficient than paying for a single VM that can withstand your maximum capacity."
src="https://deploy-preview-608--2i2c-org.netlify.app/blog/binder-singlenode/images/scalable.excalidraw.svg"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;figcaption>
The cost difference between a single large VM vs scalable nodes. Given variable usage over time, kubernetes allows you to scale your cost up and down with need, which is more efficient than paying for a single VM that can withstand your maximum capacity.
&lt;/figcaption>&lt;/figure>
&lt;p>However, there is a built-in cost you pay when you use a service that provides managed Kubernetes. &lt;strong>Managed Kubernetes services are complex and expensive&lt;/strong>, and this is reflected across-the-board in the provider&amp;rsquo;s costs. What if we could achieve the same outcome with a much simpler cloud offering like a single VM?&lt;/p>
&lt;p>We did a bit of research and discovered that the Kubernetes and object storage landscape has indeed evolved significantly since the early days of mybinder.org. For example,
&lt;a href="https://www.hetzner.com/cloud/" target="_blank" rel="noopener" >Hetzner&lt;/a> is a cloud provider that has been around for a long time. It has single-node VMs that are about &lt;code>4x&lt;/code> cheaper than their counterparts in Google Cloud or AWS, and provides managed object storage that uses
&lt;a href="https://min.io/" target="_blank" rel="noopener" >MinIO&lt;/a> in a cost-effective way. Using
&lt;a href="https://k3s.io/" target="_blank" rel="noopener" >K3s&lt;/a>, we can run a lightweight, single-node Kubernetes runtime on this node, and deploy a BinderHub with the same infrastructure as any other BinderHub federation member.&lt;/p>
&lt;p>By our estimate, we could fit around &lt;strong>400 simultaneous sessions&lt;/strong> on &lt;code>mybinder.org&lt;/code> (because each session uses very few cloud resources). This is already the majority of mybinder.org&amp;rsquo;s capacity needs, and at a much lower cost than using a scalable Kubernetes cluster. The cost picture looks something like this:&lt;/p>
&lt;figure id="figure-if-your-single-vm-is-much-cheaper-it-might-still-be-the-cheapest-option-in-the-case-of-a-hetzner-vm-it-has-roughly-the-same-capacity-as-another-cloud-providers-vm-but-at-14-of-the-cost">
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="If your single VM is much cheaper, it might still be the cheapest option. In the case of a Hetzner VM, it has roughly the same capacity as another cloud provider&amp;#39;s VM, but at 1/4 of the cost."
src="https://deploy-preview-608--2i2c-org.netlify.app/blog/binder-singlenode/images/single.excalidraw.svg"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;figcaption>
If your single VM is much cheaper, it might still be the cheapest option. In the case of a Hetzner VM, it has roughly the same capacity as another cloud provider&amp;rsquo;s VM, but at 1/4 of the cost.
&lt;/figcaption>&lt;/figure>
&lt;h2 id="2i2cmybinderorg-now-serves-70-of-the-mybinderorg-federation">
2i2c.mybinder.org now serves 70% of the mybinder.org federation
&lt;a class="header-anchor" href="#2i2cmybinderorg-now-serves-70-of-the-mybinderorg-federation">#&lt;/a>
&lt;/h2>&lt;p>About a week ago, we launched
&lt;a href="https://2i2c.mybinder.org" target="_blank" rel="noopener" >2i2c.mybinder.org&lt;/a> running via the methodology we described above. We intended to run this as a longer experiment, but believe that it has already proven useful enough to consider &amp;ldquo;ready for production&amp;rdquo;. We recently
&lt;a href="https://github.com/jupyterhub/mybinder.org-deploy/pull/3196" target="_blank" rel="noopener" >increased 2i2c.mybinder.org&amp;rsquo;s load to 70%&lt;/a> and will continue to monitor its performance over time. Here&amp;rsquo;s a plot of where each mybinder.org session has been run over the past ten days - you can see the moment where we turn on &lt;code>2i2c.mybinder.org&lt;/code> to the left:&lt;/p>
&lt;figure id="figure-sessions-launched-on-mybinderorgs-federation-over-the-past-ten-days-the-yellow-area-represents-sessions-run-on-2i2cmybinderorg-they-now-make-up-the-majority-of-launches-on-mybinderorg-prior-to-this-gesismybinderorg-was-the-only-remaining-federation-member">
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="Sessions launched on mybinder.org&amp;#39;s federation over the past ten days. The yellow area represents sessions run on `2i2c.mybinder.org`. They now make up the majority of launches on mybinder.org. Prior to this, `gesis.mybinder.org` was the only remaining federation member." srcset="
/blog/binder-singlenode/images/grafana_hu475853c06f9a32183866c212d09dafeb_419800_275a545bcca83f88b60067016558d1a1.webp 400w,
/blog/binder-singlenode/images/grafana_hu475853c06f9a32183866c212d09dafeb_419800_48678307c04cb5aa3d312f2d025029ad.webp 760w,
/blog/binder-singlenode/images/grafana_hu475853c06f9a32183866c212d09dafeb_419800_1200x1200_fit_q75_h2_lanczos_3.webp 1200w"
src="https://deploy-preview-608--2i2c-org.netlify.app/blog/binder-singlenode/images/grafana_hu475853c06f9a32183866c212d09dafeb_419800_275a545bcca83f88b60067016558d1a1.webp"
width="760"
height="455"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;figcaption>
Sessions launched on mybinder.org&amp;rsquo;s federation over the past ten days. The yellow area represents sessions run on &lt;code>2i2c.mybinder.org&lt;/code>. They now make up the majority of launches on mybinder.org. Prior to this, &lt;code>gesis.mybinder.org&lt;/code> was the only remaining federation member.
&lt;/figcaption>&lt;/figure>
&lt;p>For now, 2i2c is sponsoring a max of €350 a month (with some currency conversion noise) to run this service. We&amp;rsquo;ll provide in-kind labor to run this node, and treat it as an organizational investment in supporting open science, as well as learning new Kubernetes and cloud infrastructure workflows. We&amp;rsquo;re going to use funds recovered from communities in our
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/platform/" >community hub network&lt;/a>, along with in-kind labor to build out this experiment.&lt;/p>
&lt;p>In six months, we&amp;rsquo;ll evaluate how much effort it was to run this node for &lt;code>mybinder.org&lt;/code>, whether it meaningfully helped with &lt;code>mybinder.org&lt;/code>&amp;rsquo;s capacity, and whether it was sustainable for us from a time and labor perspective.&lt;/p>
&lt;h2 id="others-can-join-the-mybinderorg-federation-using-this-approach-as-well">
Others can join the mybinder.org federation using this approach as well
&lt;a class="header-anchor" href="#others-can-join-the-mybinderorg-federation-using-this-approach-as-well">#&lt;/a>
&lt;/h2>&lt;p>We think that developing this single-node BinderHub workflow will make it much easier for others to join the mybinder.org federation, because it lowers the infrastructure and skills complexity needed to join.
&lt;a href="https://github.com/jupyterhub/mybinder.org-deploy/blob/72a1a34509e2c43aec788f602250c58d9d849a13/docs/source/deployment/k3s.md" target="_blank" rel="noopener" >Here is a brief guide we&amp;rsquo;ve written for deploying a BinderHub with K3s&lt;/a>. We are helping a few interested organizations deploy their own BinderHubs in this way in order to validate the idea, and are hopeful that this makes it much easier to grow mybinder.org&amp;rsquo;s capacity via new federation members.&lt;sup id="fnref:5">&lt;a href="#fn:5" class="footnote-ref" role="doc-noteref">5&lt;/a>&lt;/sup>&lt;/p>
&lt;p>We&amp;rsquo;re excited to experiment with new ways to support &lt;code>mybinder.org&lt;/code>. We think this is an excellent example of how open standards and technology lead to cloud workflows with lower costs and more flexibility. We also think it&amp;rsquo;s a good example of how it is valuable to have organizations aligned with open science (like 2i2c!) acting in this space. If you have any questions or comments, please join
&lt;a href="https://jupyter.zulipchat.com/#narrow/channel/469744-jupyterhub/topic/ANN.3A.202i2c.20joins.20mybinder.2Eorg.20federation.20with.20new.20strategy/near/496811301" target="_blank" rel="noopener" >this Jupyter Zulip thread&lt;/a>&lt;/p>
&lt;h2 id="anybody-want-to-fund-this">
Anybody want to fund this?
&lt;a class="header-anchor" href="#anybody-want-to-fund-this">#&lt;/a>
&lt;/h2>&lt;p>If you&amp;rsquo;re interested in making open science infrastructure like Binder more scalable and sustainable, we&amp;rsquo;d love to find more resources to both sustain this node and cover more development time to run this experiment.
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/blog/binder-singlenode/mailto:hello@2i2c.org" >Feel free to reach out here&lt;/a>.&lt;/p>
&lt;p>If you have access to VMs and object storage, and are interested in running a mybinder.org federation member using the methods described here, check out
&lt;a href="https://github.com/jupyterhub/mybinder.org-deploy/blob/72a1a34509e2c43aec788f602250c58d9d849a13/docs/source/deployment/k3s.md" target="_blank" rel="noopener" >our brief guide for deploying a BinderHub with K3s&lt;/a>.&lt;/p>
&lt;p>If you&amp;rsquo;re generally interested in supporting &lt;code>mybinder.org&lt;/code> with cloud resources, financial resources, or human resources, please see the
&lt;a href="https://mybinder.readthedocs.io/en/latest/about/support.html" target="_blank" rel="noopener" >Support Binder&lt;/a> page for how you can help.&lt;/p>
&lt;div class="alert alert-note">
&lt;div>
If you&amp;rsquo;re interested in supporting &lt;code>mybinder.org&lt;/code> with cloud resources, financial resources, or human resources, please see the
&lt;p>&lt;a href="https://mybinder.readthedocs.io/en/latest/about/support.html" target="_blank" rel="noopener" >Support Binder&lt;/a> page for how you can help.&lt;/p>
&lt;/div>
&lt;/div>
&lt;h2 id="acknowledgements">
Acknowledgements
&lt;a class="header-anchor" href="#acknowledgements">#&lt;/a>
&lt;/h2>&lt;ul>
&lt;li>Thanks to the
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/jupyterhub/" >JupyterHub community&lt;/a> for helping us set up this new node.&lt;/li>
&lt;li>Thanks to
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/members/" >our member communities&lt;/a> whose fees currently support this work.&lt;/li>
&lt;/ul>
&lt;div class="footnotes" role="doc-endnotes">
&lt;hr>
&lt;ol>
&lt;li id="fn:1">
&lt;p>Many thanks to
&lt;a href="https://www.gesis.org/en/home" target="_blank" rel="noopener" >GESIS&lt;/a> and
&lt;a href="https://us.ovhcloud.com/" target="_blank" rel="noopener" >OVH&lt;/a> for their continued support of mybinder.org, your contributions to keeping this service running are critical!&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;li id="fn:2">
&lt;p>thanks to
&lt;a href="https://carlboettiger.info/" target="_blank" rel="noopener" >Carl Boettiger&lt;/a> for collaborating on this with us!&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;li id="fn:3">
&lt;p>One example is
&lt;a href="https://min.io/" target="_blank" rel="noopener" >MinIO&lt;/a>, which is used by
&lt;a href="https://hetzner.com/cloud" target="_blank" rel="noopener" >Hetzner&lt;/a> to provide managed object storage for their single-node VMs.&amp;#160;&lt;a href="#fnref:3" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;li id="fn:4">
&lt;p>For example,
&lt;a href="https://hetzner.com/cloud" target="_blank" rel="noopener" >Hetzner&lt;/a> provides a single-VM option with managed object storage that is roughly 25% of the cost of other cloud providers that also offer autoscaling Kubernetes services. There are many other infrastructure providers who could be used in this way.&amp;#160;&lt;a href="#fnref:4" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;li id="fn:5">
&lt;p>We&amp;rsquo;re also experimenting with a few other ways to reduce the complexity and costs of running a BinderHub even further, but will have more on that later as we learn more :-).&amp;#160;&lt;a href="#fnref:5" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;/ol>
&lt;/div></description></item><item><title>Enforcing per-user storage quotas with `jupyterhub-home-nfs`</title><link>https://deploy-preview-608--2i2c-org.netlify.app/blog/per-user-storage-quota/</link><pubDate>Tue, 28 Jan 2025 09:57:28 +0000</pubDate><guid>https://deploy-preview-608--2i2c-org.netlify.app/blog/per-user-storage-quota/</guid><description>&lt;p>When sharing a storage disk between users, as is usually the case in a JupyterHub deployment, it is important to put in guardrails so that one user cannot eat up the whole storage capacity from the rest of the users.
To this end, 2i2c in close collaboration with
&lt;a href="https://developmentseed.org" target="_blank" rel="noopener" >Development Seed&lt;/a> have developed the
&lt;a href="https://github.com/2i2c-org/jupyterhub-home-nfs" target="_blank" rel="noopener" >&lt;code>jupyterhub-home-nfs&lt;/code> project&lt;/a> which is a Helm chart that permits enforcing per-user quotas on the storage space.&lt;/p>
&lt;div class="alert alert-note">
&lt;div>
Note that this feature is currently available to AWS hosted hubs only and will be rolled out to other cloud providers in the future.
&lt;/div>
&lt;/div>
&lt;p>Under the hood, the Helm chart runs
&lt;a href="https://github.com/nfs-ganesha/nfs-ganesha" target="_blank" rel="noopener" >NFS Ganesha&lt;/a> as an in-cluster NFS server, backed by
&lt;a href="https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/7/html/storage_administration_guide/ch-xfs" target="_blank" rel="noopener" >XFS&lt;/a> as the underlying filesystem. Storage quota is enforced through XFS&amp;rsquo;s native quota management utility &lt;code>xfs_quota&lt;/code>.&lt;/p>
&lt;p>Since this feature moves our infrastructure away from managed filesystems (such as AWS&amp;rsquo;s Elastic File System) that cannot support per-user storage quotas, we have also developed monitoring and alerting mechanisms that will let us know when the disks are getting full, and automated back-ups for disaster recovery.&lt;/p>
&lt;p>If you would like to try this on your 2i2c-managed hub,
&lt;a href="https://docs.2i2c.org/support" target="_blank" rel="noopener" >please get in touch&lt;/a>.&lt;/p>
&lt;p>This project can also be used with &lt;em>any&lt;/em> Kubernetes-based JupyterHub, as per our
&lt;a href="https://2i2c.org/right-to-replicate/" target="_blank" rel="noopener" >Right to Replicate policy&lt;/a>, so please try it out on your own deployment and let us know what you think!&lt;/p>
&lt;h2 id="acknowledgements">
Acknowledgements
&lt;a class="header-anchor" href="#acknowledgements">#&lt;/a>
&lt;/h2>&lt;p>This project was developed and deployed in collaboration with
&lt;a href="https://developmentseed.org/team/tarashish-mishra/" target="_blank" rel="noopener" >Tarashish Mishra&lt;/a> from
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/devseed/" >Development Seed&lt;/a>, funded through the
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/nasa-veda/" >NASA VEDA project&lt;/a>.&lt;/p></description></item><item><title>Designing for an ecosystem: a case study in cross-project open source contribution</title><link>https://deploy-preview-608--2i2c-org.netlify.app/blog/jupyter-book-cors/</link><pubDate>Tue, 21 Jan 2025 00:00:00 +0000</pubDate><guid>https://deploy-preview-608--2i2c-org.netlify.app/blog/jupyter-book-cors/</guid><description>&lt;p>A key challenge in the open source space is that projects are often independent and autonomous, with relatively few formal ways to collaborate and coordinate efforts. While this usually isn&amp;rsquo;t a big deal, it means that there is a missed opportunity to grow the impact of an ecosystem because it requires coordinated development among multiple stakeholders within it.&lt;/p>
&lt;p>This is one of the reasons we created 2i2c&amp;rsquo;s open community hub platform. By deploying a single platform that utilizes entirely open infrastructure that we contribute back to, we have visibility over a variety of projects along with the need to combine them together for a specific end-user outcome. One-such development scenario recently came up involving
&lt;a href="https://next.jupyterbook.org/" target="_blank" rel="noopener" >Jupyter Book 2&lt;/a> and
&lt;a href="https://jupyterhub.org/" target="_blank" rel="noopener" >JupyterHub&lt;/a>.&lt;/p>
&lt;h2 id="allowing-readers-to-bring-their-own-binders">
Allowing readers to &amp;ldquo;bring their own Binders&amp;rdquo;
&lt;a class="header-anchor" href="#allowing-readers-to-bring-their-own-binders">#&lt;/a>
&lt;/h2>&lt;p>We&amp;rsquo;ve recently been working to integrate
&lt;a href="https://next.jupyterbook.org/" target="_blank" rel="noopener" >Jupyter Book 2&lt;/a> workflows with our community hubs for a more seamless experience (for example, having book pages link back to interactive cloud sessions that allow users to interact with the content). We imagine a network of Jupyter Books that all build upon the same core infrastructures (JupyterHub, Binder, etc) for cloud-based computing. Our hope is to allow a user to &lt;em>bring their own Binder&lt;/em> with them so that they can interact with another book&amp;rsquo;s content with their own cloud infrastructure. For example:&lt;/p>
&lt;ul>
&lt;li>A student with access to &lt;code>binder.myuniversity.edu&lt;/code> could read a Jupyter Book created by a professor at &lt;code>otheruniversity.edu&lt;/code>.&lt;/li>
&lt;li>The Jupyter Book is defined with a
&lt;a href="https://repo2docker.readthedocs.io/en/latest/specification.html" target="_blank" rel="noopener" >Binder specification&lt;/a> that has a recipe for re-building the environment needed to run te book&amp;rsquo;s content.&lt;/li>
&lt;li>From the professor&amp;rsquo;s book, the student can choose to launch an interactive Binder sessions on &lt;em>their university&amp;rsquo;s Binder&lt;/em>, allowing them to interact with the book&amp;rsquo;s content on their own infrastructure.&lt;/li>
&lt;/ul>
&lt;p>We want a workflow like this to be as seamless and un-complicated as possible. We also want it to follow the same fundamental workflow as the
&lt;a href="https://docs.2i2c.org/user/sharing/files" target="_blank" rel="noopener" >nbgitpuller-based launch buttons&lt;/a>. Along the way, we realized that we needed to coordinate development across
&lt;a href="https://next.jupyterbook.org/" target="_blank" rel="noopener" >Jupyter Book 2&lt;/a>,
&lt;a href="https://jupyter.readthedocs.io" target="_blank" rel="noopener" >JupyterHub&lt;/a>, and
&lt;a href="https://binderhub.readthedocs.io" target="_blank" rel="noopener" >BinderHub&lt;/a>.&lt;/p>
&lt;figure id="figure-the-three-projects-jupyter-book-binderhub-and-jupyterhub-that-needed-to-work-together-to-enable-bring-your-own-binderhub-workflows">
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img src="./featured.png" alt="The three projects (Jupyter Book, BinderHub, and JupyterHub) that needed to work together to enable &amp;#39;bring your own binderhub&amp;#39; workflows." loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;figcaption>
The three projects (Jupyter Book, BinderHub, and JupyterHub) that needed to work together to enable &amp;lsquo;bring your own binderhub&amp;rsquo; workflows.
&lt;/figcaption>&lt;/figure>
&lt;h2 id="getting-jupyter-book-to-discover-jupyter-hub">
Getting Jupyter Book to discover Jupyter Hub
&lt;a class="header-anchor" href="#getting-jupyter-book-to-discover-jupyter-hub">#&lt;/a>
&lt;/h2>&lt;p>As we began developing this workflow, we realized that there was a blocker in the JupyterHub and BinderHub ecosystem that needed to be fixed. We needed a way to &lt;strong>ask a JupyterHub whether it had an unauthenticated end-point for service discovery&lt;/strong>. Basically, a way to ask a hub &amp;ldquo;what kind of hub are you, and how can we launch an interactive session on you?&amp;rdquo; Doing this is simple-enough - JupyterHub already has a way of reporting its version and application type, which allows us to infer how to launch interactive sessions. But, we hit a snag in an HTML context.&lt;/p>
&lt;p>By default, JupyterHub disallows certain kinds of
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS" target="_blank" rel="noopener" >Cross-Origin Resource Sharing&lt;/a> (CORS) requests, in order to restrict other applications from abusing a JupyterHub&amp;rsquo;s API. If you hit parts of a JupyterHub API from &lt;em>the command line&lt;/em>, things work fine. But if you do the same thing via JavaScript from a website, the request is disallowed. This was a problem if we want Jupyter Book (a web application) to be able to make requests of JupyterHub&amp;rsquo;s API.&lt;/p>
&lt;p>So, we realized that we needed to make an &lt;strong>upstream contribution in JupyterHub&lt;/strong> in order to &lt;strong>enable an interaction between JupyterHub and Jupyter Book&lt;/strong>. In this case, it was a relatively simple fix: allowing CORS requests for the specific API endpoint we needed (which is a very lightweight endpoint that is not vulnerable to security risks, and is broadly useful to make accessible)&lt;sup id="fnref:1">&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref">1&lt;/a>&lt;/sup>. That resulted in two PRs:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://github.com/jupyterhub/jupyterhub/pull/4966" target="_blank" rel="noopener" >&lt;i class='fa-brands fa-github'>&lt;/i> jupyterhub/jupyterhub#4966&lt;/a> allows CORS requests for the API that was needed for service discovery in JupyterHub.&lt;/li>
&lt;li>
&lt;a href="https://github.com/jupyterhub/binderhub/pull/1906" target="_blank" rel="noopener" >&lt;i class='fa-brands fa-github'>&lt;/i> jupyterhub/binderhub#1906&lt;/a> enables this workflow on a BinderHub so that its services can be discovered.&lt;/li>
&lt;li>
&lt;a href="https://github.com/jupyter-book/myst-theme/pull/503" target="_blank" rel="noopener" >&lt;i class='fa-brands fa-github'>&lt;/i> jupyter-book/myst-theme#503&lt;/a> adds new launch button functionality to
&lt;a href="https://next.jupyterbook.org/" target="_blank" rel="noopener" >Jupyter Book 2&lt;/a> that allows readers to bring their own Binder / JupyterHub links for launching. (this is what necessitated the above two PRs)&lt;/li>
&lt;/ul>
&lt;p>As a result of this upstream contribution loop, JupyterHub can now accept API requests at its &amp;ldquo;service discovery&amp;rdquo; endpoint, which means that Jupyter Book (and any other web application) can more easily learn about a hub&amp;rsquo;s capabilities and version.&lt;/p>
&lt;p>We wanted to share this short vignette because it&amp;rsquo;s a good reflection of the kind of value that 2i2c tries to provide, given its role in helping to build and enhance networks of infrastructure, domain communities, and open source communities. In this case, we enabled a &lt;em>cross-project&lt;/em> workflow that required knowledge of each project, and a vision for how they could be used together in a way that exceeded the sum of their parts.&lt;/p>
&lt;p>We think there&amp;rsquo;s a lot more potential in these kinds of workflows, and are eager to continue our work to identify and enhance community-centric infrastructure for interactive computing.&lt;/p>
&lt;h2 id="acknowledgements">
Acknowledgements
&lt;a class="header-anchor" href="#acknowledgements">#&lt;/a>
&lt;/h2>&lt;p>Thanks to the
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/jupyterhub/" >JupyterHub&lt;/a> and
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/jupyter-book/" >Jupyter Book&lt;/a> communities for collaboration and review on this work.&lt;/p>
&lt;p>This &amp;ldquo;bring your own Binder&amp;rdquo; workflow benefits NASA training communities including
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/nasa-open-science/" >NASA Open Science / ScienceCore&lt;/a>, which partially supports this work.&lt;/p>
&lt;div class="footnotes" role="doc-endnotes">
&lt;hr>
&lt;ol>
&lt;li id="fn:1">
&lt;p>This actually required an interesting bit of team discussion that was much easier with a few 2i2c staff on the JupyterHub team. The original request from Angus was interpreted as opening up the &lt;em>entire hub API&lt;/em> to external requests (which is a bad idea!) but we were able to quickly discuss this with the JupyterHub team to clarify that this was only about a very specific API endpoint. This is the kind of communication loop that often goes haywire when you have people contributing to a project without historical relationships to the project&amp;rsquo;s maintainers.&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;/ol>
&lt;/div></description></item><item><title>Announcing our formal commitment to open technology</title><link>https://deploy-preview-608--2i2c-org.netlify.app/blog/community-ownership/</link><pubDate>Wed, 15 Jan 2025 00:00:00 +0000</pubDate><guid>https://deploy-preview-608--2i2c-org.netlify.app/blog/community-ownership/</guid><description>&lt;p>In this post, we&amp;rsquo;re sharing our
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/open-technology/" >Commitment to Open Technology&lt;/a>. It is focused on &lt;em>software licenses&lt;/em> for reasons we&amp;rsquo;ll describe below. We hope that it clarifies what kind of licenses we&amp;rsquo;ll use, and assures our communities that we will not change our stance towards open source technology in the future. This ensures 2i2c&amp;rsquo;s long-term commitment to community-owned and open infrastructure.&lt;/p>
&lt;p>Being a platform and service provider gives us a lot of power, and also introduces a potential source of &lt;em>lock-in&lt;/em> for our member communities. While 2i2c&amp;rsquo;s organizational mission and culture are strongly aligned with open infrastructure, we believe it&amp;rsquo;s important to encode commitments like these in a formal way to provide both transparency and accountability to our member communities.&lt;/p>
&lt;h2 id="our-commitment-to-open-technology">
Our commitment to open technology
&lt;a class="header-anchor" href="#our-commitment-to-open-technology">#&lt;/a>
&lt;/h2>&lt;p>Below we copy the original language of this policy from our
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/open-technology/" >Commitment to Open Technology&lt;/a>:&lt;/p>
&lt;!-- TODO: When we switch to MyST, we should embed this rather than copy/paste -->
&lt;p>&lt;em>Definitions of MUST, MUST NOT, SHOULD, MAY, etc are defined in
&lt;a href="https://tools.ietf.org/html/rfc2119" target="_blank" rel="noopener" >RFC 2119&lt;/a>&lt;/em>&lt;/p>
&lt;ol>
&lt;li>All engineering artifacts (code, documentation, etc) produced by 2i2c&amp;rsquo;s engineering team MUST be licensed under an open source license approved by a non-profit organization that is not 2i2c.&lt;/li>
&lt;li>Open Source Projects originating at 2i2c, or stewarded by 2i2c, MUST NOT require a
&lt;a href="https://en.wikipedia.org/wiki/Contributor_License_Agreement" target="_blank" rel="noopener" >Contributor Licensing Agreement&lt;/a> that includes Copyright Assignment to 2i2c.&lt;/li>
&lt;li>The list of external organizations that define licenses we accept are
&lt;ol>
&lt;li>
&lt;a href="https://opensource.org/" target="_blank" rel="noopener" >the Open Source Initiative&lt;/a>&lt;/li>
&lt;li>the
&lt;a href="https://ethicalsource.dev/" target="_blank" rel="noopener" >Organization for Ethical Source&lt;/a>.&lt;/li>
&lt;/ol>
&lt;/li>
&lt;li>Modifying (1), (2), or (3) MUST be done through a 2/3 majority vote of 2i2c staff.&lt;/li>
&lt;/ol>
&lt;h2 id="what-does-this-commitment-mean">
What does this commitment mean?
&lt;a class="header-anchor" href="#what-does-this-commitment-mean">#&lt;/a>
&lt;/h2>&lt;p>In plain language, here&amp;rsquo;s what this commitment means:&lt;/p>
&lt;ol>
&lt;li>We&amp;rsquo;ll only use open source licenses that have been approved by standard non-profits that are broadly recognized by the tech industry.&lt;/li>
&lt;li>For anything we build, we won&amp;rsquo;t require contributors to give up the rights to their contributions via CLAs, so that it is much harder for 2i2c to change our licenses in the future.&lt;/li>
&lt;li>Changing this policy will require organization-wide agreement, and in the future we&amp;rsquo;ll give authority over this policy to a group of people representing our member communities.&lt;/li>
&lt;/ol>
&lt;h2 id="why-are-licenses-and-clas-important">
Why are licenses and CLAs important?
&lt;a class="header-anchor" href="#why-are-licenses-and-clas-important">#&lt;/a>
&lt;/h2>&lt;p>Many organizations claim to be committed to open infrastructure, while retaining the ability to &lt;em>change this commitment in the future when it is in their interests&lt;/em>. A classic example of this is a &amp;ldquo;bait and switch&amp;rdquo; that looks something like this:&lt;/p>
&lt;ol>
&lt;li>A company releases software under an open source license and professes to build an open source community around it.&lt;/li>
&lt;li>However, they retain the rights to all of the code in their projects through a
&lt;a href="https://en.wikipedia.org/wiki/Contributor_License_Agreement" target="_blank" rel="noopener" >Contributor License Agreement&lt;/a> (CLA) with copyright assignment. This generally means that contributors must &lt;em>give up the rights to their contribution&lt;/em> in order to make that contribution.&lt;/li>
&lt;li>Once their product has gained traction and it is in their interests, the company can &lt;em>change the license&lt;/em> to whatever they wish (even one that is not open source) because they retain the rights to all contributions in the codebase.&lt;/li>
&lt;li>They then leverage this new position as owners of a proprietary project to extract business value or grow their position in a market.&lt;/li>
&lt;/ol>
&lt;p>Think this sounds unlikely? Here are just a few recent examples of companies that have switched their license after many years of releasing their technology under an open source license:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://redis.io/blog/redis-adopts-dual-source-available-licensing/" target="_blank" rel="noopener" >Redis&lt;/a>&lt;/li>
&lt;li>
&lt;a href="https://www.hashicorp.com/blog/hashicorp-adopts-business-source-license" target="_blank" rel="noopener" >Hashicorp / Terraform&lt;/a>&lt;/li>
&lt;li>
&lt;a href="https://en.wikipedia.org/wiki/Elasticsearch#Licensing_changes" target="_blank" rel="noopener" >Elastic Search&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>We want to ensure our communities that 2i2c is not headed down this path, in order to give them confidence in treating us as a long-term service partner.&lt;/p>
&lt;h2 id="what-does-this-change-about-2i2cs-open-source-commitment">
What does this change about 2i2c&amp;rsquo;s open source commitment?
&lt;a class="header-anchor" href="#what-does-this-change-about-2i2cs-open-source-commitment">#&lt;/a>
&lt;/h2>&lt;p>In short: nothing. These are already the principles that 2i2c was committed to from its inception, and already implied via our
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/right-to-replicate/" >Right to Replicate&lt;/a>. However, we wanted to make these commitments more formally in order to give ourselves more accountability to sticking with them, and to provide more transparency for our community members and stakeholders.&lt;/p>
&lt;h2 id="who-is-this-for">
Who is this for?
&lt;a class="header-anchor" href="#who-is-this-for">#&lt;/a>
&lt;/h2>&lt;p>We imagine three audiences for this policy:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>2i2c present and future staff&lt;/strong> who want to ensure that their organization remains committed to our open principles. This document provides a sense of psychological safety to have bold discussions about structuring our approach to open source.&lt;/li>
&lt;li>&lt;strong>Member communities and 2i2c stakeholders&lt;/strong> who need to have an understanding of the guarantees that we provide in order to trust 2i2c as a service developer and provider. This is similar to the effect our
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/right-to-replicate/" >Right to Replicate&lt;/a> has.&lt;/li>
&lt;li>&lt;strong>Open source communities&lt;/strong> who need to understand our long-term commitment and goals around open technology in order to trust as a peer and collaborator within open source communities.&lt;/li>
&lt;/ol>
&lt;h2 id="wed-love-feedback">
We&amp;rsquo;d love feedback
&lt;a class="header-anchor" href="#wed-love-feedback">#&lt;/a>
&lt;/h2>&lt;p>We hope that these ideas both clarify our intent and the reason that we think it&amp;rsquo;s important. We&amp;rsquo;d love feedback about early refinements to these principles in order to make them more effective, as well as ways that we can provide more community oversight and participation in evolving these policies moving forward. If you have any thoughts to share, please send feedback via e-mail
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/blog/community-ownership/mailto:hello@2i2c.org" >hello@2i2c.org&lt;/a>.&lt;/p>
&lt;hr>
&lt;p>&lt;strong>Acknowledgements&lt;/strong>: &lt;em>The creation of this policy and the rationale behind it was led by
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/author/yuvaraj-yuvi/" >Yuvi Panda&lt;/a> with feedback from 2i2c&amp;rsquo;s team. This blog post was co-written with
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/author/chris-holdgraf/" >Chris Holdgraf&lt;/a>. Strategic work like this is supported by a grant from
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/navigation/" >The Navigation Fund&lt;/a>&lt;/em>.&lt;/p></description></item><item><title>NASA VEDA &amp; 2i2c Update for Q4 2024 (Oct-Dec 2024)</title><link>https://deploy-preview-608--2i2c-org.netlify.app/blog/veda-update-q4-2024/</link><pubDate>Tue, 07 Jan 2025 15:18:37 -0800</pubDate><guid>https://deploy-preview-608--2i2c-org.netlify.app/blog/veda-update-q4-2024/</guid><description>&lt;p>A non-exhaustive list of things 2i2c and
&lt;a href="https://developmentseed.org/" target="_blank" rel="noopener" >Development Seed&lt;/a> did with the
&lt;a href="https://www.earthdata.nasa.gov/data/tools/veda" target="_blank" rel="noopener" >NASA VEDA&lt;/a> project last quarter!&lt;/p>
&lt;h2 id="automated-backups-and-alerting-with-jupyterhub-home-nfs">
Automated backups and alerting with &lt;code>jupyterhub-home-nfs&lt;/code>
&lt;a class="header-anchor" href="#automated-backups-and-alerting-with-jupyterhub-home-nfs">#&lt;/a>
&lt;/h2>&lt;p>
&lt;a href="https://github.com/NASA-IMPACT/veda-jupyterhub/issues/56" target="_blank" rel="noopener" >Tracking Issue&lt;/a>&lt;/p>
&lt;p>
&lt;a href="https://github.com/2i2c-org/jupyterhub-home-nfs/" target="_blank" rel="noopener" >jupyterhub-home-nfs&lt;/a> is a young project to provide flexible per-user home directory limits on JupyterHub - an important feature for controlling cloud costs.
&lt;a href="https://sunu.in/" target="_blank" rel="noopener" >Tarashish Mishra&lt;/a> and
&lt;a href="https://sgibson91.github.io/cv/" target="_blank" rel="noopener" >Sarah Gibson&lt;/a> have been leading this project for the last few months. Since we are moving away from
&lt;a href="https://aws.amazon.com/efs/" target="_blank" rel="noopener" >AWS Managed EFS&lt;/a> here, we had to do some work to recreate some of the benefits EFS gives us out of the box. During this quarter, we:&lt;/p>
&lt;ol>
&lt;li>Set up automated backups so we can recover files in cases of disaster&lt;/li>
&lt;li>Set up automated alerting (via prometheus and pagerduty) to know if our backing EBS device is getting full and we need to perform a manual intervention&lt;/li>
&lt;li>Deployed this to a few other communities (
&lt;a href="https://www.cryocloud.io/" target="_blank" rel="noopener" >CryoCloud&lt;/a> and
&lt;a href="https://nmfs-openscapes.github.io/" target="_blank" rel="noopener" >NMFS Openscapes&lt;/a>) to broaden adoption.&lt;/li>
&lt;/ol>
&lt;p>We will continue doing work on &lt;code>jupyterhub-home-nfs&lt;/code> in the upcoming quarter! If this is functionality you are interested in deploying, please reach out to us to collaborate!&lt;/p>
&lt;h2 id="enable-users-to-dynamically-build-environments-with-jupyterhub-fancy-profiles">
Enable users to dynamically build environments with &lt;code>jupyterhub-fancy-profiles&lt;/code>
&lt;a class="header-anchor" href="#enable-users-to-dynamically-build-environments-with-jupyterhub-fancy-profiles">#&lt;/a>
&lt;/h2>&lt;p>
&lt;a href="https://github.com/NASA-IMPACT/veda-jupyterhub/issues/58" target="_blank" rel="noopener" >Tracking Issue&lt;/a>&lt;/p>
&lt;p>We covered this more extensively in
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/blog/jupyterhub-fancy-profiles-rollout/" >another blog post&lt;/a>, so go read that!&lt;/p>
&lt;p>This work in particular is a good demonstrator of 2i2c&amp;rsquo;s value - it started off with a
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/blog/jupyterhub-binderhub-gesis/" >grant from GESIS&lt;/a>, and now with support from
&lt;a href="https://impact.earthdata.nasa.gov/" target="_blank" rel="noopener" >NASA IMPACT&lt;/a> we are able to bring it to a &lt;em>lot&lt;/em> of communities, not just the ones that funded it.&lt;/p>
&lt;p>Ongoing work here will focus on improving the UX as well as better documentation so users can actually use it!&lt;/p>
&lt;h2 id="open-in-qgis-from-veda-ui">
&amp;ldquo;Open in QGIS&amp;rdquo; from VEDA UI
&lt;a class="header-anchor" href="#open-in-qgis-from-veda-ui">#&lt;/a>
&lt;/h2>&lt;p>
&lt;a href="https://github.com/NASA-IMPACT/veda-jupyterhub/issues/59" target="_blank" rel="noopener" >Tracking Issue&lt;/a>&lt;/p>
&lt;p>We had worked in the past with many communities in enabling
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/blog/qgis-greenland/" >QGIS on the Cloud&lt;/a>, and this quarter we got closer to enabling a contextual &amp;lsquo;Open in QGIS&amp;rsquo; button in the
&lt;a href="https://www.earthdata.nasa.gov/dashboard/" target="_blank" rel="noopener" >VEDA Dashboard&lt;/a>! Here is a quick demo:&lt;/p>
&lt;p>&lt;video src="./open-in-qgis.mp4" muted controls>&lt;/video>&lt;/p>
&lt;p>(This shows the workflow when user is already logged into the JupyterHub and had started the server)&lt;/p>
&lt;p>You can play with this in
&lt;a href="https://deploy-preview-688--ghg-demo.netlify.app/exploration" target="_blank" rel="noopener" >this preview&lt;/a>, although you need to have access to the NASA VEDA hub to fully try it out at this point.&lt;/p>
&lt;p>Tarashish from Development Seed is again responsible for most of the work here, available in
&lt;a href="https://github.com/sunu/jupyter-remote-qgis-proxy" target="_blank" rel="noopener" >jupyter-remote-qgis-proxy&lt;/a>. You can use it to create &amp;lsquo;magic links&amp;rsquo; that will open QGIS in a desktop environment in your browser, and add a specific layer to it! Our hope is that this allows primarily GIS folks to better use tools they already are familiar with in cloud based contexts.&lt;/p>
&lt;h2 id="other-updates">
Other updates
&lt;a class="header-anchor" href="#other-updates">#&lt;/a>
&lt;/h2>&lt;ul>
&lt;li>We participated heavily in an evaluation process for the authentication and authorization solution to be used across NASA VEDA!
&lt;a href="https://github.com/NASA-IMPACT/veda-jupyterhub/issues/57" target="_blank" rel="noopener" >Tracking Issue&lt;/a>&lt;/li>
&lt;li>We are very close to
&lt;a href="https://github.com/2i2c-org/infrastructure/issues/5209" target="_blank" rel="noopener" >rolling out JupyterHub 5.0&lt;/a> and associated changes across all our hubs, which will enable us to eventually offer per-group shared directories!
&lt;a href="https://github.com/NASA-IMPACT/veda-jupyterhub/issues/61" target="_blank" rel="noopener" >Tracking Issue&lt;/a>&lt;/li>
&lt;/ul>
&lt;h2 id="acknowledgements">
Acknowledgements
&lt;a class="header-anchor" href="#acknowledgements">#&lt;/a>
&lt;/h2>&lt;ul>
&lt;li>Thanks to the
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/nasa-veda/" >NASA VEDA project&lt;/a> for thir ongoing support for this work.&lt;/li>
&lt;li>Thanks to
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/devseed/" >DevSeet&lt;/a> for their collaboration and leadership on this project.&lt;/li>
&lt;/ul></description></item><item><title>`frx-challenges`: A new tool to host data challenges for Frictionless Research Exchanges</title><link>https://deploy-preview-608--2i2c-org.netlify.app/blog/frx/</link><pubDate>Fri, 06 Dec 2024 00:00:00 +0000</pubDate><guid>https://deploy-preview-608--2i2c-org.netlify.app/blog/frx/</guid><description>&lt;p>2i2c is pleased to announce the &lt;code>frx-challenges&lt;/code> project, a new open source tool to help communities host data challenges on shared infrastructure:&lt;/p>
&lt;p>
&lt;a href="https://github.com/2i2c-org/frx-challenges" target="_blank" rel="noopener" >&lt;i class='fa-brands fa-github'>&lt;/i> 2i2c-org/frx-challenges&lt;/a>&lt;/p>
&lt;p>This project aims to make it easier for administrators to provide a service that enables users to &lt;strong>submit code and data&lt;/strong> that are &lt;strong>evaluated on secure infrastructure with access to private data and resources&lt;/strong>. It also provides a leaderboard that helps users compare their performance against others.&lt;/p>
&lt;figure id="figure-an-example-leaderboard-for-a-data-challenge-taken-from-the-cellmap-challengehttpscellmapchallengejaneliaorg-users-make-submissions-that-are-run-against-secure-and-private-infrastructure-and-data-and-provides-feedback-about-the-submissions-performance-learn-more-about-the-frx-challenges-project-here-https2i2corgfrx-challenges">
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="An example leaderboard for a data challenge, taken from the [Cellmap Challenge](https://cellmapchallenge.janelia.org/). Users make submissions that are run against secure and private infrastructure and data, and provides feedback about the submission&amp;#39;s performance. Learn more about the FRX challenges project here: https://2i2c.org/frx-challenges/" srcset="
/blog/frx/images/leaderboard_hu1c5275577555814ddf920c106a29e815_883850_e8cf5edfc5977cc915c200d3d338ce2b.webp 400w,
/blog/frx/images/leaderboard_hu1c5275577555814ddf920c106a29e815_883850_64bd6d34f7f589cd624b5702b3fc5904.webp 760w,
/blog/frx/images/leaderboard_hu1c5275577555814ddf920c106a29e815_883850_1200x1200_fit_q75_h2_lanczos_3.webp 1200w"
src="https://deploy-preview-608--2i2c-org.netlify.app/blog/frx/images/leaderboard_hu1c5275577555814ddf920c106a29e815_883850_e8cf5edfc5977cc915c200d3d338ce2b.webp"
width="75%"
height="417"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;figcaption>
An example leaderboard for a data challenge, taken from the
&lt;a href="https://cellmapchallenge.janelia.org/" target="_blank" rel="noopener" >Cellmap Challenge&lt;/a>. Users make submissions that are run against secure and private infrastructure and data, and provides feedback about the submission&amp;rsquo;s performance. Learn more about the FRX challenges project here:
&lt;a href="https://2i2c.org/frx-challenges/" target="_blank" rel="noopener" >2i2c.org/frx-challenges/&lt;/a>
&lt;/figcaption>&lt;/figure>
&lt;p>It is designed to be lightweight and flexible, and can be run on a variety of shared infrastructure. For those who wish to run this project on cloud infrastructure, we&amp;rsquo;ve also published a
&lt;a href="https://2i2c.org/frx-challenges-helm-chart/" target="_blank" rel="noopener" >Helm Chart to help you deploy &lt;code>frx-challenges&lt;/code> with Kubernetes&lt;/a>.&lt;/p>
&lt;p>While it can be run on its own, we believe that it naturally complements other tools and services for interactive computing and data, such as &lt;strong>JupyterHub&lt;/strong>, &lt;strong>Jupyter Book&lt;/strong>, and &lt;strong>Binder&lt;/strong>. More on that below.&lt;/p>
&lt;p>Below is a brief description of the motivation behind this project.&lt;/p>
&lt;h2 id="what-are-frictionless-research-exchanges">
What are Frictionless Research Exchanges
&lt;a class="header-anchor" href="#what-are-frictionless-research-exchanges">#&lt;/a>
&lt;/h2>&lt;p>The project is heavily inspired by David Donoho&amp;rsquo;s vision of &lt;strong>Frictionless Research Exchanges&lt;/strong> (FRX) as described in
&lt;a href="https://arxiv.org/abs/2310.00865" target="_blank" rel="noopener" >&lt;em>Data Science at the Singularity&lt;/em>&lt;/a>.&lt;/p>
&lt;p>In this article, Donoho describes three key pillars for Frictionless Research Exchanges:&lt;/p>
&lt;blockquote>
&lt;p>The three initiatives are related but separate; and all three have to come together, and in a particularly strong way, to provide the conditions for the new era. Here they are:&lt;/p>
&lt;ul>
&lt;li>[FR-1: Data] datafication of everything, with a culture of research data sharing. One can now find datasets publicly available online on a bewildering variety of topics, from chest x-rays to cosmic microwave background measurements to uber routes to geospatial crop identifications.&lt;/li>
&lt;li>[FR-2: Re-execution] research code sharing including the ability to exactly re-execute the same complete workflow by different researchers.&lt;/li>
&lt;li>[FR-3: Challenges] adopting challenge problems as a new paradigm powering scientific research. The paradigm includes: a shared public dataset, a prescribed and quantified task performance metric, a set of enrolled competitors seeking to outperform each other on the task, and a public leaderboard. Thousands of such challenges with millions of entries have now taken place, across many fields.&lt;/li>
&lt;/ul>
&lt;/blockquote>
&lt;p>We considered the landscape of tools and services, and felt that [FR-1] and [FR-2] were already well-served by a variety of tools and services for community workspace infrastructure (e.g., JupyterHub:
&lt;a href="https://jupyterhub.readthedocs.io" target="_blank" rel="noopener" >jupyterhub.readthedocs.io&lt;/a>), sharable computational environments (e.g., BinderHub:
&lt;a href="https://binderhub.readthedocs.io" target="_blank" rel="noopener" >binderhub.readthedocs.io&lt;/a>), authoring and reading computational narratives (e.g., Jupyter Book:
&lt;a href="https://jupyterbook.org" target="_blank" rel="noopener" >jupyterbook.org&lt;/a> and MyST:
&lt;a href="https://mystmd.org" target="_blank" rel="noopener" >mystmd.org&lt;/a>), and data I/O tools and standards (e.g., Zarr:
&lt;a href="https://zarr.readthedocs.io" target="_blank" rel="noopener" >zarr.readthedocs.io&lt;/a> and Intake:
&lt;a href="https://intake.readthedocs.io" target="_blank" rel="noopener" >intake.readthedocs.io&lt;/a>).&lt;/p>
&lt;p>However there was a natural missing piece for &lt;strong>[FR-3 Challenges]&lt;/strong>, and we could not identify any community-managed infrastructure that facilitated data challenges. This is the goal of &lt;code>frx-challenges&lt;/code>.&lt;/p>
&lt;h2 id="why-facilitate-data-challenges">
Why facilitate data challenges?
&lt;a class="header-anchor" href="#why-facilitate-data-challenges">#&lt;/a>
&lt;/h2>&lt;p>Data challenges are harder than you think! While it is simple enough to run somebody else&amp;rsquo;s code locally, data challenges require a systematic, secure, and automated approach to accepting and evaluating submissions in a fair and repeatable way. Here are some of the big challenges to tackle:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Submissions must retain user and team identity&lt;/strong>, which means that we must keep track of users and their submissions over time, since data challenges are designed to encourage iterative improvement and optimization.&lt;/li>
&lt;li>&lt;strong>Evaluations must use potentially complex resources and data&lt;/strong> since many data challenges operate by publicly sharing a small dataset, and then running it against a much more complex dataset.&lt;/li>
&lt;li>&lt;strong>Evaluations must be totally secure&lt;/strong>, so that submissions can&amp;rsquo;t do nefarious things like mine cryptocurrency or extract the challenge&amp;rsquo;s private data in unintended ways.&lt;/li>
&lt;li>&lt;strong>Evaluations must be automated&lt;/strong>, so that running the challenge does not require extensive human intervention and can scale to many users.&lt;/li>
&lt;li>&lt;strong>Evaluation must be flexible&lt;/strong>, so that the infrastructure can accept a variety of types of submissions (e.g. code, data, model weights, etc), run them with arbitrary environments designed by the organizers, and run them with the right hardware to get the job done.&lt;/li>
&lt;/ul>
&lt;p>These are just a few of the major challenges that we&amp;rsquo;ve tried to address with &lt;code>frx-challenges&lt;/code>, and we&amp;rsquo;re excited to see how it goes with our first assisted community challenge: the
&lt;a href="https://cellmapchallenge.janelia.org/" target="_blank" rel="noopener" >Cellmap Challenge&lt;/a>.&lt;/p>
&lt;p>If you&amp;rsquo;re interested in learning more or participating in this project, follow along at its GitHub repository:&lt;/p>
&lt;p>
&lt;a href="https://github.com/2i2c-org/frx-challenges" target="_blank" rel="noopener" >&lt;i class='fa-brands fa-github'>&lt;/i> 2i2c-org/frx-challenges&lt;/a>&lt;/p>
&lt;p>This is still the &lt;strong>very early stages&lt;/strong> of the project, and we imagine it will evolve significantly. We welcome feedback for how it can more effectively serve a variety of communities.&lt;/p>
&lt;h2 id="acknowledgements">
Acknowledgements
&lt;a class="header-anchor" href="#acknowledgements">#&lt;/a>
&lt;/h2>&lt;p>Thanks to the
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/hhmi/" >Howard Hughes Medical Institute&lt;/a> (HHMI) for collaborating with us on the
&lt;a href="https://cellmapchallenge.janelia.org/" target="_blank" rel="noopener" >Cellmap Challenge&lt;/a>, which led to the creation of this project.&lt;/p>
&lt;p>Thanks to Kristen Ratan and
&lt;a href="https://strategiesos.org/about/" target="_blank" rel="noopener" >Strategies for Open Science&lt;/a> (Stratos) for enabling this collaboration, and providing strategic guidance and support.&lt;/p></description></item><item><title>Improving the logged in home page experience in JupyterHub with `jupyterhub-fancy-profiles`</title><link>https://deploy-preview-608--2i2c-org.netlify.app/blog/jupyterhub-fancy-profiles-rollout/</link><pubDate>Mon, 18 Nov 2024 12:55:20 -0800</pubDate><guid>https://deploy-preview-608--2i2c-org.netlify.app/blog/jupyterhub-fancy-profiles-rollout/</guid><description>&lt;p>On most research oriented JupyterHub installations, users would like to customize their server (the environment, resources available, etc) after logging in. In Kubernetes based JupyterHub environments, a
&lt;a href="https://z2jh.jupyter.org/en/latest/jupyterhub/customizing/user-environment.html#using-multiple-profiles-to-let-users-select-their-environment" target="_blank" rel="noopener" >profile list&lt;/a> provides this functionality.&lt;/p>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img src="./classic-profiles.png" alt="image" loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
(Profile List for the NASA VEDA JupyterHub with the default implementation from KubeSpawner)&lt;/p>
&lt;p>The profile list is the de-facto &amp;ldquo;logged in homepage&amp;rdquo; for these users, as that is what they see after they have logged in.&lt;/p>
&lt;p>In collaboration with
&lt;a href="https://developmentseed.org/" target="_blank" rel="noopener" >Development Seed&lt;/a>, funded by our
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/blog/jupyterhub-binderhub-gesis/" >earlier grant&lt;/a> from
&lt;a href="https://www.gesis.org/home" target="_blank" rel="noopener" >GESIS&lt;/a> as well as the
&lt;a href="https://www.earthdata.nasa.gov/data/tools/veda" target="_blank" rel="noopener" >NASA VEDA project&lt;/a>, we have been building the
&lt;a href="https://github.com/2i2c-org/jupyterhub-fancy-profiles" target="_blank" rel="noopener" >&lt;code>jupyterhub-fancy-profiles&lt;/code>&lt;/a> project to improve this experience.&lt;/p>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img src="./fancy-profiles.png" alt="image" loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
(Profile List for the NASA VEDA JupyterHub with &lt;code>jupyterhub-fancy-profiles&lt;/code>)&lt;/p>
&lt;p>Last week, we rolled this new experience out to all 2i2c managed JupyterHubs! Here&amp;rsquo;s a quick rundown of what this enables:&lt;/p>
&lt;ol>
&lt;li>
&lt;p>Descriptions for choices in the dropdowns, making it much easier for users to know what they are getting with each environment (or resource selection).&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Fully backwards compatible with the existing KubeSpawner profile list implementation. In our PR to
&lt;a href="https://github.com/2i2c-org/infrastructure/pull/5083" target="_blank" rel="noopener" >roll this out&lt;/a> to all hubs, you notice that we didn&amp;rsquo;t have to change the structure of any profile lists! So you can safely roll this out to your hubs too without needing to fundamentally change how your profiles are set up.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>It is a modern web app (built with
&lt;a href="https://react.dev/" target="_blank" rel="noopener" >react&lt;/a>), just like the JupyterHub admin panel. This allows us to evolve and satisfy user needs much faster, as well as expanding the pool of people who can contribute to the project!&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Support for dynamically building images using
&lt;a href="https://mybinder.org" target="_blank" rel="noopener" >mybinder.org&lt;/a> style repositories! It talks to the
&lt;a href="https://github.com/jupyterhub/binderhub/" target="_blank" rel="noopener" >binderhub&lt;/a> API so users can build reproducible environments as they wish without admin involvement nor needing to fully understand how docker and containers work. Our
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/blog/jupyterhub-binderhub-gesis/" >earlier blog post&lt;/a> has more information.&lt;/p>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img src="./fancy-profiles-build.png" alt="image" loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;/li>
&lt;/ol>
&lt;p>This is just the start, and thanks to ongoing funding from the
&lt;a href="https://www.earthdata.nasa.gov/data/tools/veda" target="_blank" rel="noopener" >NASA VEDA&lt;/a> project, we are going to continue making improvements to this experience.&lt;/p>
&lt;h2 id="use-this-in-your-jupyterhub">
Use this in your JupyterHub
&lt;a class="header-anchor" href="#use-this-in-your-jupyterhub">#&lt;/a>
&lt;/h2>&lt;p>As with everything we build at 2i2c (per our
&lt;a href="https://2i2c.org/right-to-replicate/" target="_blank" rel="noopener" >right to replicate&lt;/a> policy), this project can be used with &lt;em>any&lt;/em> JupyterHub installation that uses Kubernetes. There are
&lt;a href="https://github.com/2i2c-org/jupyterhub-fancy-profiles/?tab=readme-ov-file#how-to-use" target="_blank" rel="noopener" >instructions&lt;/a> in the README. Please try it out on yours and let us know what you think!&lt;/p>
&lt;h2 id="credit">
Credit
&lt;a class="header-anchor" href="#credit">#&lt;/a>
&lt;/h2>&lt;ul>
&lt;li>The project was initiated with funding generously provided by
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/gesis/" >GESIS&lt;/a> (see our
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/blog/jupyterhub-binderhub-gesis/" >earlier blog post&lt;/a>).&lt;/li>
&lt;li>
&lt;a href="https://developmentseed.org/team/sanjay-bhangar/" target="_blank" rel="noopener" >Sanjay Bhangar&lt;/a> and
&lt;a href="https://oliverroick.net/" target="_blank" rel="noopener" >Oliver Roick&lt;/a> from
&lt;a href="https://developmentseed.org/" target="_blank" rel="noopener" >Development Seed&lt;/a> for advocating for this project and contributing heavily to it.&lt;/li>
&lt;li>The
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/nasa-veda/" >NASA VEDA&lt;/a> project (in particular,
&lt;a href="https://github.com/freitagb/" target="_blank" rel="noopener" >Brian Freitag&lt;/a> and
&lt;a href="https://github.com/wildintellect" target="_blank" rel="noopener" >Alex Mandel&lt;/a>), for continued funding (in the form of engineering time) plus being early adopters!&lt;/li>
&lt;/ul></description></item><item><title>Announcing the Jupyter Book 2 alpha</title><link>https://deploy-preview-608--2i2c-org.netlify.app/blog/jupyter-book-2/</link><pubDate>Mon, 18 Nov 2024 00:00:00 +0000</pubDate><guid>https://deploy-preview-608--2i2c-org.netlify.app/blog/jupyter-book-2/</guid><description>&lt;p>&lt;em>Cross-posted from the
&lt;a href="https://blog.jupyterbook.org/" target="_blank" rel="noopener" >Jupyter Book blog&lt;/a>. Note that some MyST functionality is not supported on the 2i2c website – please see the original post for previews.&lt;/em>&lt;/p>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="Jupyter Book 2 logo" srcset="
/blog/jupyter-book-2/featured_hu9397abb9dc215fd1bcc8d6a18f27fb4c_8272_05bc5dc8042431294b2f182578411095.webp 400w,
/blog/jupyter-book-2/featured_hu9397abb9dc215fd1bcc8d6a18f27fb4c_8272_681e12830606d8090069f4767618787c.webp 760w,
/blog/jupyter-book-2/featured_hu9397abb9dc215fd1bcc8d6a18f27fb4c_8272_1200x1200_fit_q75_h2_lanczos_3.webp 1200w"
src="https://deploy-preview-608--2i2c-org.netlify.app/blog/jupyter-book-2/featured_hu9397abb9dc215fd1bcc8d6a18f27fb4c_8272_05bc5dc8042431294b2f182578411095.webp"
width="461"
height="105"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;p>Over the last ten months, the Jupyter Book team have been hard at work; Jupyter Book has
&lt;a href="https://github.com/jupyter/governance/pull/229" target="_blank" rel="noopener" >become a Jupyter subproject&lt;/a>, and the team&lt;sup id="fnref:1">&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref">1&lt;/a>&lt;/sup> announced a
&lt;a href="https://executablebooks.org/en/latest/blog/2024-05-20-jupyter-book-myst/" target="_blank" rel="noopener" >plan to release Jupyter Book 2&lt;/a>. This post announces the &lt;strong>alpha release of Jupyter Book 2.0&lt;/strong>, which has been re-written from the ground up to use the new MyST-MD engine.&lt;/p>
&lt;p>Over the next few months, we will work in preparation for the full release of Jupyter Book 2. Stay tuned for more! The initial documentation for the alpha release can be found at:&lt;/p>
&lt;p>
&lt;a href="https://next.jupyterbook.org/" target="_blank" rel="noopener" >next.jupyterbook.org/&lt;/a>&lt;/p>
&lt;h2 id="install-the-jupyter-book-2-alpha">
Install the Jupyter Book 2 Alpha
&lt;a class="header-anchor" href="#install-the-jupyter-book-2-alpha">#&lt;/a>
&lt;/h2>&lt;p>The Jupyter Book 2 alpha is available from PyPI.org. You can install it with &lt;code>pip&lt;/code>, using&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">pip install -U jupyter-book&lt;span class="o">==&lt;/span>2.0.0a0
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>If you use &lt;code>pipx&lt;/code>, it&amp;rsquo;s recommened to run Jupyter Book 2 using&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">pipx run jupyter-book&lt;span class="o">==&lt;/span>2.0.0a0
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Jupyter Book 2 needs Node.js installed on your computer. If this is not the case, running &lt;code>jupyter book&lt;/code> will prompt you to install it using the &lt;code>nodeenv&lt;/code> package that ships with Jupyter Book 2:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">❗ Node.js (node) is required to run Jupyter Book, but could not be found`.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">❔ Install Node.js in &amp;#39;...&amp;#39;? (y/N):
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Press &lt;code>y&lt;/code> and &lt;code>Enter&lt;/code> to proceed.&lt;/p>
&lt;div class="alert alert-note">
&lt;div>
&lt;p>The Jupyter Book 2 project is a complete re-write of Jupyter Book. We expect there to be bugs and breakages! Please use our support channels to keep us up to date with your findings!&lt;/p>
&lt;ul>
&lt;li>
&lt;p>&lt;a href="https://discord.mystmd.org/" target="_blank" rel="noopener" >Discord&lt;/a>&lt;/li>&lt;/p>
&lt;li>
&lt;p>&lt;a href="https://github.com/jupyter-book/jupyter-book/issues/new?template=prerelease.yml" target="_blank" rel="noopener" >GitHub Issues&lt;/a>&lt;/li>&lt;/p>
&lt;/ul>
&lt;/div>
&lt;/div>
&lt;h2 id="new-features-in-20-alpha">
New Features in &lt;code>2.0 alpha&lt;/code>
&lt;a class="header-anchor" href="#new-features-in-20-alpha">#&lt;/a>
&lt;/h2>
&lt;h3 id="rich-hover-previews">
Rich Hover Previews
&lt;a class="header-anchor" href="#rich-hover-previews">#&lt;/a>
&lt;/h3>&lt;p>The new MyST book and article themes provide useful hover previews for links to other MyST content, Wikipedia, GitHub issues, and many more.&lt;/p>
&lt;video width="100%" autoplay>
&lt;source src="https://github.com/jupyter-book/blog/raw/refs/heads/main/media/hover-previews.mp4" type="video/mp4">
&lt;/video>
&lt;h3 id="share--embed-content">
Share &amp;amp; Embed Content
&lt;a class="header-anchor" href="#share--embed-content">#&lt;/a>
&lt;/h3>&lt;p>Content from other websites built with the MyST engine can be embedded in your own sites and PDFs:&lt;/p>
&lt;p>
&lt;figure id="figure-cross-referenced-content-can-easily-be-embedded-and-re-captioned-into-other-pages-and-projects-such-as-this-figure-to-">
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img src="https://cdn.curvenote.com/0192bff5-9c9d-722f-92bf-e702aa8e1f46/public/c8830546aa82907becb6cd46c414a80c.webp" alt="Image of a mountain range." loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;figcaption>
Cross-referenced content can easily be embedded and re-captioned into other pages and projects, such as this figure to
&lt;a href="https://mystmd.org/guide/embed#mylabel" target="_blank" rel="noopener" >mystmd.org/guide/embed#mylabel&lt;/a>.
&lt;/figcaption>&lt;/figure>
&lt;/p>
&lt;h3 id="simple-instant-search">
Simple Instant Search
&lt;a class="header-anchor" href="#simple-instant-search">#&lt;/a>
&lt;/h3>&lt;p>A new client-side search uses a simple, modern algorithm for fast &lt;em>local&lt;/em> search that finds the results that you care about.&lt;/p>
&lt;p>
&lt;figure id="figure-client-side-search-uses-simple-modern-algoliahttpsalgoliacom-inspired-search-algorithm-to-provide-_useful_-search-results-we-will-be-iterating-on-this-in-the-near-future-for-even-richer-search-results">
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img src="https://github.com/jupyter-book/blog/blob/main/media/search.png?raw=true" alt="Screenshot of a search bar." loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;figcaption>
Client-side search uses simple, modern,
&lt;a href="https://algolia.com" target="_blank" rel="noopener" >Algolia&lt;/a>-inspired search algorithm to provide &lt;em>useful&lt;/em> search results. We will be iterating on this in the near future for even richer search results!
&lt;/figcaption>&lt;/figure>
&lt;/p>
&lt;h3 id="high-quality-pdfs">
High Quality PDFs
&lt;a class="header-anchor" href="#high-quality-pdfs">#&lt;/a>
&lt;/h3>&lt;p>PDF documents can now be built with Typst, a high-quality typesetting engine that produces readable error messages and beautiful documents. This feature was the basis for the 2024
&lt;a href="https://proceedings.scipy.org" target="_blank" rel="noopener" >SciPy proceedings&lt;/a>, which is now built on MyST Markdown and will be accepting Jupyter Notebooks in 2025.&lt;/p>
&lt;p>
&lt;figure id="figure-example-of-the-lapreprint-typst-template-for-rendering-pdfs-from-jupyter-book-via-the-myst-engine">
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img src="https://raw.githubusercontent.com/rowanc1/LaPreprint/68f5ccbf1e1e26819149bcea1d547dfdfc5ceecd/example/files/screenshot.png" alt="An example preprint using the LaPreprint template." loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;figcaption>
Example of the LaPreprint Typst template for rendering PDFs from Jupyter Book (via the MyST Engine).
&lt;/figcaption>&lt;/figure>
&lt;/p>
&lt;h2 id="coming-soon-in-20-beta">
Coming Soon in &lt;code>2.0 beta&lt;/code>
&lt;a class="header-anchor" href="#coming-soon-in-20-beta">#&lt;/a>
&lt;/h2>
&lt;h3 id="custom-styles--scrips">
Custom Styles &amp;amp; Scrips
&lt;a class="header-anchor" href="#custom-styles--scrips">#&lt;/a>
&lt;/h3>&lt;p>Jupyter Book 2 will make it easy to tweak your website styles, and add new website behaviors.&lt;/p>
&lt;h3 id="generate-markdown-from-code-cells">
Generate Markdown from Code Cells
&lt;a class="header-anchor" href="#generate-markdown-from-code-cells">#&lt;/a>
&lt;/h3>&lt;p>The MyST engine is on-track to support the inclusion of references and other markup features generated by code cells.&lt;/p>
&lt;h3 id="control-cell-visibility-with-tags">
Control Cell Visibility with Tags
&lt;a class="header-anchor" href="#control-cell-visibility-with-tags">#&lt;/a>
&lt;/h3>&lt;p>In the beta release, Jupyter Book 2 will once-again be able to show and hide content according to cell tags.&lt;/p>
&lt;h2 id="jupyter-book-2-vs-myst-md">
Jupyter Book 2 vs MyST-MD
&lt;a class="header-anchor" href="#jupyter-book-2-vs-myst-md">#&lt;/a>
&lt;/h2>&lt;p>At this early stage, the new Jupyter Book application &lt;code>jupyter book&lt;/code> behaves identically to the &lt;code>mystmd&lt;/code> engine that it is built upon; as outlined in
&lt;a href="https://executablebooks.org/en/latest/blog/2024-05-20-jupyter-book-myst/" target="_blank" rel="noopener" >our Jupyter Book 2 plan&lt;/a>, we intend for Jupyter Book to be an &amp;ldquo;opinionated distribution&amp;rdquo; of &lt;code>mystmd&lt;/code> that shares the same configuration format and CLI. This contrasts with Jupyter Book 1, which was built on top of the Sphinx documentation engine, but offered its own CLI and configuration files. In future, the &lt;code>jupyter book&lt;/code> and &lt;code>mystmd&lt;/code> CLIs may diverge from one another, but we expect that this will be handled in a graceful manner: &lt;code>mystmd&lt;/code> commands should always be compatible with the &lt;code>jupyter book&lt;/code> application.&lt;/p>
&lt;h2 id="acknowledgements">
Acknowledgements
&lt;a class="header-anchor" href="#acknowledgements">#&lt;/a>
&lt;/h2>&lt;ul>
&lt;li>Thanks to
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/pythia/" >Project Pythia&lt;/a> for funding some of our ongoing work on Jupyter Book.&lt;/li>
&lt;li>Thanks to the
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/jupyter-book/" >Jupyter Book community&lt;/a> for their collaboration.&lt;/li>
&lt;/ul>
&lt;div class="footnotes" role="doc-endnotes">
&lt;hr>
&lt;ol>
&lt;li id="fn:1">
&lt;p>Jupyter Book project has historically been a &lt;em>technical&lt;/em> project of the Executable Books organisation. In 2024, the establishment of a Jupyter subproject means that the Jupyter Book project now has its own identity outside of Executable Books.&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;/ol>
&lt;/div></description></item><item><title>Openscapes goes to the White House!</title><link>https://deploy-preview-608--2i2c-org.netlify.app/blog/external-openscapes-whitehouse/</link><pubDate>Mon, 23 Sep 2024 00:00:00 +0000</pubDate><guid>https://deploy-preview-608--2i2c-org.netlify.app/blog/external-openscapes-whitehouse/</guid><description>&lt;p>Our partner
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/openscapes/" >OpenScapes&lt;/a> recently took a trip to the White House to advocate for Open Science and the Open Source ecosystem, check out
&lt;a href="https://openscapes.org/events/2024-09-26-openscapes-whitehouse/" target="_blank" rel="noopener" >their blog post&lt;/a> about the experience.&lt;/p></description></item><item><title>MyST Mini-Hackathon with the DeepLabCut Team</title><link>https://deploy-preview-608--2i2c-org.netlify.app/blog/deeplabcut-myst-hackathon/</link><pubDate>Mon, 02 Sep 2024 00:00:00 +0000</pubDate><guid>https://deploy-preview-608--2i2c-org.netlify.app/blog/deeplabcut-myst-hackathon/</guid><description>
&lt;h2 id="the-deeplabcut-team">
The DeepLabCut Team
&lt;a class="header-anchor" href="#the-deeplabcut-team">#&lt;/a>
&lt;/h2>&lt;p>
&lt;figure id="figure-animal-pose-estimation-using-deep-neural-networks-courtesy-of-the-deeplabcut-jupyter-bookhttpsdeeplabcutgithubiodeeplabcutreadmehtml">
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img src="https://images.squarespace-cdn.com/content/v1/57f6d51c9f74566f55ecf271/daed7f16-527f-4150-8bdd-cbb20e267451/cheetah-ezgif.com-video-to-gif-converter.gif?format=180w" alt="Animal pose estimation using deep neural networks. Courtesy of the DeepLabCut Jupyter Book" loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;figcaption>
Animal pose estimation using deep neural networks. Courtesy of the
&lt;a href="https://deeplabcut.github.io/DeepLabCut/README.html" target="_blank" rel="noopener" >DeepLabCut Jupyter Book&lt;/a>
&lt;/figcaption>&lt;/figure>
&lt;/p>
&lt;p>The
&lt;a href="http://www.mackenziemathislab.org/deeplabcut" target="_blank" rel="noopener" >DeepLabCut team&lt;/a> is a group of researchers and developers who are working on open source tools for analyzing animal pose estimation by training deep neural networks on videos.&lt;/p>
&lt;p>Chris Holdgraf visited the lab in early August to learn more about how the group were using open-source tools to document and share their work.&lt;/p>
&lt;h2 id="jupyter-book-and-myst">
Jupyter Book and MyST
&lt;a class="header-anchor" href="#jupyter-book-and-myst">#&lt;/a>
&lt;/h2>&lt;p>Extensive documentation for using the DeepLabCut software package is already available as a
&lt;a href="https://deeplabcut.github.io/DeepLabCut/README.html" target="_blank" rel="noopener" >Jupyter Book&lt;/a>. The group was interested in adopting MyST Markdown to stay ahead of the curve and upgrade their Jupyter Book (see the related announcement
&lt;a href="https://executablebooks.org/en/latest/blog/2024-05-20-jupyter-book-myst/" target="_blank" rel="noopener" >Jupyter Book 2 will be build upon the MyST-MD engine&lt;/a>).&lt;/p>
&lt;p>Chris led a mini-hackathon to introduce the group to MyST and collect feedback on where enhancement features could be made in the future. Here&amp;rsquo;s a summary of the outcomes:&lt;/p>
&lt;ul>
&lt;li>Many improvements were made to the
&lt;a href="https://mystmd.org/guide/" target="_blank" rel="noopener" >MyST documentation&lt;/a> 📖
&lt;ul>
&lt;li>The
&lt;a href="https://mystmd.org/guide/quickstart" target="_blank" rel="noopener" >MyST Quick Start Guide&lt;/a> was used to onboard new users. Amendments were
&lt;a href="https://github.com/jupyter-book/mystmd/pull/1433" target="_blank" rel="noopener" >upstreamed to the MyST docs directly&lt;/a> and were immediately available to all.&lt;/li>
&lt;li>A
&lt;a href="https://mystmd.org/guide/quickstart-executable-documents" target="_blank" rel="noopener" >tutorial on executable documents&lt;/a> was added to the collection of MyST tutorials.&lt;/li>
&lt;li>MyST-MD installation instructions were
&lt;a href="https://github.com/jupyter-book/mystmd/pull/1454" target="_blank" rel="noopener" >simplified using &lt;code>mamba&lt;/code>&lt;/a>.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>A bunch of enhancement features were requested ✨
&lt;ul>
&lt;li>
&lt;a href="https://github.com/jupyter-book/mystmd/issues/1455" target="_blank" rel="noopener" >Using cell tags for labelling notebook cells&lt;/a>&lt;/li>
&lt;li>
&lt;a href="https://github.com/jupyter-book/myst-theme/issues/321" target="_blank" rel="noopener" >Support for loading user-defined CSS stylesheets for theming&lt;/a>&lt;/li>
&lt;li>
&lt;a href="https://github.com/jupyter-book/mystmd/issues/1458" target="_blank" rel="noopener" >Better UX for multi-versioned documentation&lt;/a>&lt;/li>
&lt;li>
&lt;a href="https://github.com/jupyter-book/mystmd/issues/1462" target="_blank" rel="noopener" >Bibliography styling in HTML&lt;/a>&lt;/li>
&lt;li>
&lt;a href="https://github.com/DeepLabCut/DeepLabCut/pull/2712" target="_blank" rel="noopener" >Automatic API documentation generation&lt;/a>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>And we found a bug in the
&lt;a href="https://github.com/jupyter-book/mystmd/issues/1456" target="_blank" rel="noopener" >table of contents validation&lt;/a> 🐞&lt;/li>
&lt;/ul>
&lt;h2 id="summary">
Summary
&lt;a class="header-anchor" href="#summary">#&lt;/a>
&lt;/h2>&lt;p>Hackathons are a great way for quickly imparting knowledge and gathering feedback in a short space of time. The event spurred rapid contributions to the MyST ecosystem – embracing reuse of the MyST quick start guides saved time and effort, while engaging with users directly closed a tight feedback loop for enhancements.&lt;/p>
&lt;h2 id="acknowledgments">
Acknowledgments
&lt;a class="header-anchor" href="#acknowledgments">#&lt;/a>
&lt;/h2>&lt;ul>
&lt;li>Thank to the
&lt;a href="http://www.mackenziemathislab.org/" target="_blank" rel="noopener" >Mackenzie Mathis Lab&lt;/a> for hosting Chris Holdgraf at EPFL, Lausanne, Switzerland.&lt;/li>
&lt;li>Thanks to the
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/jupyter-book/" >Jupyter Book team&lt;/a> for collaborating on this with us.&lt;/li>
&lt;/ul></description></item><item><title>Collaborating with Development Seed to deliver cyberinfrastructure for NASA VEDA</title><link>https://deploy-preview-608--2i2c-org.netlify.app/blog/veda-devseed-collab/</link><pubDate>Fri, 12 Jul 2024 00:00:00 +0000</pubDate><guid>https://deploy-preview-608--2i2c-org.netlify.app/blog/veda-devseed-collab/</guid><description>&lt;p>&lt;em>Thank you to Sajjad Anwar and Sanjay Bhangar for contributing to this post.&lt;/em>&lt;/p>
&lt;p>
&lt;figure id="figure-the-veda-dashboardhttpswwwearthdatanasagovdashboard">
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="Landing page of the public-facing NASA VEDA dashboard" srcset="
/blog/veda-devseed-collab/featured_hu24026c3ba79339d6cab1fefe6f955a05_2636756_4b1df029ea65c7f3b4b044426866fb24.webp 400w,
/blog/veda-devseed-collab/featured_hu24026c3ba79339d6cab1fefe6f955a05_2636756_323a794370493087e930f822be2e27ba.webp 760w,
/blog/veda-devseed-collab/featured_hu24026c3ba79339d6cab1fefe6f955a05_2636756_1200x1200_fit_q75_h2_lanczos_3.webp 1200w"
src="https://deploy-preview-608--2i2c-org.netlify.app/blog/veda-devseed-collab/featured_hu24026c3ba79339d6cab1fefe6f955a05_2636756_4b1df029ea65c7f3b4b044426866fb24.webp"
width="760"
height="490"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;figcaption>
The
&lt;a href="https://www.earthdata.nasa.gov/dashboard/" target="_blank" rel="noopener" >VEDA dashboard&lt;/a>
&lt;/figcaption>&lt;/figure>
&lt;/p>
&lt;p>The 2i2c team are proud to continue our strong working collaboration with
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/devseed/" >Development Seed&lt;/a>, following our previous work on launching the
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/blog/veda-devseed-collab/../2023/us-ghg-center-launches/index.md" >US GHG center&lt;/a> (also see the
&lt;a href="https://developmentseed.org/blog/2023-12-14-ghg-center" target="_blank" rel="noopener" >Development Seed blog post&lt;/a>). Together with scientists at NASA in our regular sync touchpoints, we have recently delivered a tranche of improvements to
&lt;a href="https://www.earthdata.nasa.gov/esds/veda" target="_blank" rel="noopener" >the Visualization, Exploration and Data Analysis (VEDA) project&lt;/a>.&lt;/p>
&lt;p>This platform is designed to thread open-source components together to consolidate GIS delivery mechanisms, processing, analysis and visualization tools, and presented in a collaborative interactive computing environment. All code repositories and associated resources stemming from this work are available on the
&lt;a href="https://github.com/NASA-IMPACT/VEDA/wiki" target="_blank" rel="noopener" >VEDA GitHub page&lt;/a>.&lt;/p>
&lt;p>In the spirit of fully open development, you can
&lt;a href="https://github.com/NASA-IMPACT/veda-jupyterhub/issues?q=is%3Aissue&amp;#43;jh&amp;#43;is%3Aclosed&amp;#43;label%3A%22PI&amp;#43;24.3%22&amp;#43;" target="_blank" rel="noopener" >see the objectives&lt;/a>
the combined 2i2c and Development Seed team had for the last quarter. In this blog post, we will describe some of the significant ones!&lt;/p>
&lt;h2 id="better-image-management-and-testing">
Better image management and testing
&lt;a class="header-anchor" href="#better-image-management-and-testing">#&lt;/a>
&lt;/h2>&lt;p>The
&lt;a href="https://github.com/jupyterhub/repo2docker-action" target="_blank" rel="noopener" >repo2docker-action&lt;/a> is a GitHub action simplifying image building and testing for use with JupyterHub, using either a &lt;code>Dockerfile&lt;/code> or various
&lt;a href="https://repo2docker.readthedocs.io/en/latest/config_files.html" target="_blank" rel="noopener" >configuration files&lt;/a> (like &lt;code>requirements.txt&lt;/code>, &lt;code>environment.yml&lt;/code>, etc) supported by
&lt;a href="https://github.com/jupyterhub/repo2docker" target="_blank" rel="noopener" >repo2docker&lt;/a>. We migrated our image building pipeline from a somewhat homegrown solution to this upstream action, making image updates and testing &lt;em>much&lt;/em> easier. In particular, we can
&lt;a href="https://github.com/NASA-IMPACT/pangeo-notebook-veda-image/pull/4" target="_blank" rel="noopener" >automatically run test notebooks&lt;/a> on every change we make to the image! This way, we can easily catch any breaking changes in library versions or other package installs without disrupting users. We also debugged and
&lt;a href="https://github.com/jupyterhub/repo2docker-action/pull/124" target="_blank" rel="noopener" >contributed upstream&lt;/a> fixes to the testing infrastructure so everyone could benefit from this, rather than just us.&lt;/p>
&lt;h2 id="automatically-pulling-example-notebooks-on-startup">
Automatically pulling example notebooks on startup
&lt;a class="header-anchor" href="#automatically-pulling-example-notebooks-on-startup">#&lt;/a>
&lt;/h2>&lt;p>When a user logs into a JupyterHub, it is very helpful if we could have a bunch of example notebooks and other content pre-populated for them so they can get started right away.
&lt;a href="https://nbgitpuller.readthedocs.io/" target="_blank" rel="noopener" >nbgitpuller&lt;/a> is heavily used for this particular use case. However, it requires that nbgitpuller is installed inside the image the user is using - and not all images have it installed. In particular, we wanted to continue using the (wonderful)
&lt;a href="https://rocker-project.org/" target="_blank" rel="noopener" >Rocker images&lt;/a> maintained upstream for R users, however they do not have nbgitpuller installed. To solve this problem we built
&lt;a href="https://github.com/NASA-IMPACT/jupyterhub-gitpuller-init" target="_blank" rel="noopener" >jupyterhub-gitpuller-init&lt;/a>, which can be used as an
&lt;a href="https://kubernetes.io/docs/concepts/workloads/pods/init-containers/" target="_blank" rel="noopener" >init container&lt;/a> to pre-populate user content on persistent home directories regardless of the image used. We also made sure to build this in a way that &lt;em>anyone&lt;/em> can use it, and it is not tied into either 2i2c or VEDA infrastructure!&lt;/p>
&lt;h2 id="opening-specific-visualizations-in-qgis-via-url">
Opening specific visualizations in QGIS via URL
&lt;a class="header-anchor" href="#opening-specific-visualizations-in-qgis-via-url">#&lt;/a>
&lt;/h2>&lt;p>
&lt;a href="https://www.qgis.org/" target="_blank" rel="noopener" >QGIS&lt;/a> is the world&amp;rsquo;s most used open source GIS software, and previously 2i2c had
&lt;a href="https://blog.jupyter.org/desktop-gis-software-in-the-cloud-with-jupyterhub-ddced297019a" target="_blank" rel="noopener" >worked with Openscapes and QGreenland&lt;/a> to bring this &lt;em>desktop&lt;/em> software to JupyterHub. We had previously worked on a
&lt;a href="https://github.com/2i2c-org/nasa-qgis-image" target="_blank" rel="noopener" >container image&lt;/a> that allows users to access large datasets stored in the cloud directly through QGIS on the JupyterHub, allowing users to work with much larger datasets than they could on their desktops by bringing cloud compute adjacent to the data. As a continuation of this work, we developed
&lt;a href="https://github.com/sunu/jupyter-remote-qgis-proxy" target="_blank" rel="noopener" >jupyter-remote-qgis-proxy&lt;/a>, which builds QGIS specific features on top of
&lt;a href="https://github.com/jupyterhub/jupyter-remote-desktop-proxy" target="_blank" rel="noopener" >jupyter-remote-desktop-proxy&lt;/a>. In particular, it allows creation of shareable links that when clicked, opens specific datasets and layers in QGIS in a JupyterHub! You can see this in action:&lt;/p>
&lt;figure>
&lt;video mute autoplay loop >
&lt;source src="https://deploy-preview-608--2i2c-org.netlify.app/blog/veda-devseed-collab/qgis.mp4" type="video/mp4">
&lt;/video>
&lt;figcaption>Launching QGIS on a Linux desktop served by the VEDA JupyterHub&lt;/figcaption>
&lt;/figure>
&lt;p>This opens up exciting future possibilities. Imagine this
&lt;a href="https://www.earthdata.nasa.gov/dashboard/data-catalog/campfire_ndvi_difference_2015_2022" target="_blank" rel="noopener" >exploration of the Camp Fire&lt;/a> having an &amp;lsquo;Open in QGIS&amp;rsquo; button that enables further exploration of the data without the user needing to download or install anything! Work will continue in the coming quarter towards achieving this vision.&lt;/p>
&lt;p>We are also excited to see recent work in this space
&lt;a href="https://blog.jupyter.org/jupytergis-d63b7adf9d0c" target="_blank" rel="noopener" >from QuantStack and Simula Labs&lt;/a>, and will follow up to ensure an orderly transition to more web native workflows for existing users of QGIS in due time.&lt;/p>
&lt;h2 id="better-profile-selection">
Better Profile Selection
&lt;a class="header-anchor" href="#better-profile-selection">#&lt;/a>
&lt;/h2>&lt;p>This is a continuation of our
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/blog/jupyterhub-binderhub-gesis/" >GESIS collaboration&lt;/a>. In the path to deploying dynamic image building to end users, we wanted to stabilize
&lt;a href="https://github.com/yuvipanda/jupyterhub-fancy-profiles" target="_blank" rel="noopener" >jupyterhub-fancy-profiles&lt;/a> enough to deploy to users of VEDA (and eventually everyone else). This is the primary interface users see &lt;em>after&lt;/em> they log in to JupyterHub, and was ripe for UX improvements. The default interface looks like this:&lt;/p>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="Default profile list page" srcset="
/blog/veda-devseed-collab/old-profile_hu10b987728cacc6727099b87fdcffde73_116187_3ba716304cf974b6f820c2d01db2a898.webp 400w,
/blog/veda-devseed-collab/old-profile_hu10b987728cacc6727099b87fdcffde73_116187_5d665939450b0139d1cacccecd3c15e3.webp 760w,
/blog/veda-devseed-collab/old-profile_hu10b987728cacc6727099b87fdcffde73_116187_1200x1200_fit_q75_h2_lanczos_3.webp 1200w"
src="https://deploy-preview-608--2i2c-org.netlify.app/blog/veda-devseed-collab/old-profile_hu10b987728cacc6727099b87fdcffde73_116187_3ba716304cf974b6f820c2d01db2a898.webp"
width="734"
height="760"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;p>The revamped one is much more streamlined and looks like this:&lt;/p>
&lt;figure>
&lt;video mute autoplay loop >
&lt;source src="https://deploy-preview-608--2i2c-org.netlify.app/blog/veda-devseed-collab/new-profile.mp4" type="video/mp4">
&lt;/video>
&lt;figcaption>Revamped Profile Screen&lt;/figcaption>
&lt;/figure>
&lt;p>This is currently deployed to a staging hub and has helped us shake out a lot of bugs! We expect the improved interface will be rolled out to all users in the near future. We are also planning further development to make the user experience even better and smoother for everyone.&lt;/p>
&lt;h2 id="supporting-workshops">
Supporting workshops
&lt;a class="header-anchor" href="#supporting-workshops">#&lt;/a>
&lt;/h2>&lt;p>End users benefiting from our work is what ultimately gives meaning to our work. To that end, we were very happy to support running workshops during this collaboration – see our related blog post
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/blog/ghg-summer-school/" >US Greenhouse Gas Center supports summer school at CIRA&lt;/a> for more information.&lt;/p>
&lt;h2 id="ongoing-collaboration">
Ongoing Collaboration
&lt;a class="header-anchor" href="#ongoing-collaboration">#&lt;/a>
&lt;/h2>&lt;p>Delivering on these objectives in a timely way heavily depended on the success of the team collaboration.
&lt;a href="https://developmentseed.org/team/sanjay-bhangar" target="_blank" rel="noopener" >Sanjay Bhangar&lt;/a> of Development Seed commented&lt;/p>
&lt;blockquote>
&lt;p>Working closely with the 2i2c team on growing features to support users on the VEDA and GHG Center hubs has been absolutely amazing. With 2i2c’s deep experience in the Jupyter ecosystem, we have been able to implement some fairly complex features quite easily, and their strong open-source roots have ensured that whatever we work on is broadly useful to the wider Jupyter and scientific computing communities.&lt;/p>
&lt;/blockquote>
&lt;p>Take a look at the companion
&lt;a href="https://developmentseed.org/blog/2024-07-12-jupyter-geospatial" target="_blank" rel="noopener" >Development Seed blog post&lt;/a> of this work.&lt;/p>
&lt;p>This collaboration continues, and we have now
&lt;a href="https://github.com/NASA-IMPACT/veda-jupyterhub/issues?q=is%3Aissue&amp;#43;jh%3A&amp;#43;label%3A%22PI&amp;#43;24.4%22&amp;#43;" target="_blank" rel="noopener" >published our objectives for the coming quarter&lt;/a>. Watch this space!&lt;/p>
&lt;h2 id="acknowledgements">
Acknowledgements
&lt;a class="header-anchor" href="#acknowledgements">#&lt;/a>
&lt;/h2>&lt;ul>
&lt;li>
&lt;a href="https://developmentseed.org/" target="_blank" rel="noopener" >Development Seed&lt;/a>&lt;/li>
&lt;li>
&lt;a href="https://impact.earthdata.nasa.gov/" target="_blank" rel="noopener" >NASA IMPACT&lt;/a>&lt;/li>
&lt;li>
&lt;a href="https://sunu.in/" target="_blank" rel="noopener" >Tarashish Mishra&lt;/a>,
&lt;a href="https://jsignell.github.io/" target="_blank" rel="noopener" >Julia Signell&lt;/a>,
&lt;a href="https://oliverroick.net/" target="_blank" rel="noopener" >Oliver Roick&lt;/a>,
&lt;a href="https://slesa.com.np/" target="_blank" rel="noopener" >Slesa Adhikari&lt;/a> and
&lt;a href="https://developmentseed.org/team/sanjay-bhangar" target="_blank" rel="noopener" >Sanjay Bhangar&lt;/a> for various code contributions towards these objectives&lt;/li>
&lt;/ul></description></item><item><title>Enabling neuroscience in the cloud with HHMI Spyglass and MySQL on JupyterHub</title><link>https://deploy-preview-608--2i2c-org.netlify.app/blog/hhmi-spyglass-mysql/</link><pubDate>Fri, 05 Jul 2024 00:00:00 +0000</pubDate><guid>https://deploy-preview-608--2i2c-org.netlify.app/blog/hhmi-spyglass-mysql/</guid><description>&lt;p>
&lt;figure id="figure-the-hhmi-spyglass-tutorialhttpsspyglasshhmi2i2ccloud">
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="HHMI Spyglass tutorial" srcset="
/blog/hhmi-spyglass-mysql/featured_huda5696297f7fdc49904c82761adc3edf_243308_bd8374537df26d753cf207ce605828be.webp 400w,
/blog/hhmi-spyglass-mysql/featured_huda5696297f7fdc49904c82761adc3edf_243308_6bf7febe689cf7ab6de5a884d311f33f.webp 760w,
/blog/hhmi-spyglass-mysql/featured_huda5696297f7fdc49904c82761adc3edf_243308_1200x1200_fit_q75_h2_lanczos_3.webp 1200w"
src="https://deploy-preview-608--2i2c-org.netlify.app/blog/hhmi-spyglass-mysql/featured_huda5696297f7fdc49904c82761adc3edf_243308_bd8374537df26d753cf207ce605828be.webp"
width="760"
height="498"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;figcaption>
The
&lt;a href="https://spyglass.hhmi.2i2c.cloud/" target="_blank" rel="noopener" >HHMI Spyglass tutorial&lt;/a>
&lt;/figcaption>&lt;/figure>
&lt;/p>
&lt;h2 id="spyglass">
Spyglass
&lt;a class="header-anchor" href="#spyglass">#&lt;/a>
&lt;/h2>&lt;p>
&lt;a href="https://github.com/LorenFrankLab/spyglass" target="_blank" rel="noopener" >Spyglass&lt;/a> is a framework for reproducible and shareable neuroscience research produced by
&lt;a href="https://github.com/LorenFrankLab" target="_blank" rel="noopener" >Loren Frank’s lab&lt;/a> at the University of California, San Francisco. Check out our
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/blog/hhmi-spyglass/" >blog post about the release of their preprint&lt;/a> to read more about the methods.&lt;/p>
&lt;p>This post focuses on the complex data storage needed for the project, which can be difficult to set up locally or at scale in the cloud. In particular, the analysis needed a MySQL database for reproducibility. This is a fairly common task across many fields. The aim of 2i2c is to enable researchers to focus on the essential complexity of what they were doing, i.e. the science, without managing the accidental complexity of how to do it &amp;ndash; in this case, setting up databases.&lt;/p>
&lt;p>We describe how you can do this too for your own JupyterHubs. Since 2i2c commits to running our infrastructure in line with open-source values as much as possible, you can also directly see the
&lt;a href="https://github.com/2i2c-org/infrastructure/blob/99071c38712ef8e6bed6609117ca4b894b89ae5c/config/clusters/hhmi/spyglass.values.yaml#L76" target="_blank" rel="noopener" >configuration for the hub&lt;/a> referenced in the paper.&lt;/p>
&lt;h2 id="what-is-a-sidecar-container">
What is a &amp;ldquo;sidecar container&amp;rdquo;?
&lt;a class="header-anchor" href="#what-is-a-sidecar-container">#&lt;/a>
&lt;/h2>&lt;p>The Kubernetes definition of a
&lt;a href="https://kubernetes.io/docs/concepts/workloads/pods/sidecar-containers/" target="_blank" rel="noopener" >sidecar container&lt;/a> is&lt;/p>
&lt;blockquote>
&lt;p>Sidecar containers are the secondary containers that run along with the main application container within the same Pod. These containers are used to enhance or to extend the functionality of the primary app container by providing additional services, or functionality such as logging, monitoring, security, or data synchronization, without directly altering the primary application code.&lt;/p>
&lt;/blockquote>
&lt;p>In this case, the &lt;em>primary&lt;/em> app container is the JupyterLab instance where people are interactively running code and doing science. We want to provide a MySQL database as a sidecar so that each user server gets their own independent MySQL server instance (that is not accessible to anyone else). We can then run code such as&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">%%bash
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">mysql -h 127.0.0.1 -u root --password=tutorial &amp;lt; path-to-sql-file-with-data
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>to load data into the database. Note the IP address &lt;code>127.0.0.1&lt;/code> - the MySQL server is listening on localhost, even though it is not running in the &lt;em>same container&lt;/em>! Thanks to the magic of
&lt;a href="https://lwn.net/Articles/580893/" target="_blank" rel="noopener" >Linux Network Namespaces&lt;/a>, the sidecar and main app container can share &lt;code>127.0.0.1&lt;/code>. This allows you to write code that works &lt;strong>in the exact same way&lt;/strong> on a user&amp;rsquo;s local computers as on the JupyterHub, making transitions and replication easier.&lt;/p>
&lt;h2 id="setting-up-sidecars-in-jupyterhub-on-kubernetes">
Setting up sidecars in JupyterHub on Kubernetes
&lt;a class="header-anchor" href="#setting-up-sidecars-in-jupyterhub-on-kubernetes">#&lt;/a>
&lt;/h2>&lt;p>We&amp;rsquo;re leveraging multiple tools from the open-source ecosystem - JupyterHub, Kubernetes, Linux as well as MySQL itself.&lt;/p>
&lt;p>Since this is a &lt;em>Kubernetes&lt;/em> feature, we can pass through config to it. There are
two layers here, which are&lt;/p>
&lt;ol>
&lt;li>
&lt;a href="https://z2jh.jupyter.org/en/latest/resources/reference.html#singleuser-extracontainers" target="_blank" rel="noopener" >singleuser.extraContainers&lt;/a> in
&lt;a href="https://z2jh.jupyter.org/en/stable/" target="_blank" rel="noopener" >z2jh&lt;/a> configuration&lt;/li>
&lt;li>
&lt;a href="https://jupyterhub-kubespawner.readthedocs.io/en/latest/spawner.html#kubespawner.KubeSpawner.extra_containers" target="_blank" rel="noopener" >KubeSpawner.extra_containers&lt;/a> in
&lt;a href="https://jupyterhub-kubespawner.readthedocs.io/en/latest/spawner.html" target="_blank" rel="noopener" >KubeSpawner&lt;/a> configuration&lt;/li>
&lt;/ol>
&lt;p>The hub configuration looks like&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">singleuser&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">extraContainers&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">mysql&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">image&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">datajoint/mysql:8.0&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c"># following the spyglass tutorial at https://lorenfranklab.github.io/spyglass/latest/notebooks/00_Setup/#existing-database&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">ports&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">mysql&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">containerPort&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">3306&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">resources&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">limits&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># Best effort only. No more than 1 CPU, and if mysql uses more than 4G, restart it&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">memory&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">4Gi&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">cpu&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">1.0&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">requests&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># If we don&amp;#39;t set requests, k8s sets requests == limits!&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># So we set something tiny&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">memory&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">64Mi&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">cpu&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">0.01&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">env&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># Configured using the env vars documented in https://lorenfranklab.github.io/spyglass/latest/notebooks/00_Setup/#existing-database&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">MYSQL_ROOT_PASSWORD&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">value&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;tutorial&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>By setting this up, we allow users to insert the code snippet above&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">%%bash
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">mysql -h 127.0.0.1 -u root --password=tutorial &amp;lt; path-to-sql-file-with-data
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>into their
&lt;a href="https://github.com/LorenFrankLab/spyglass-demo/blob/main/notebooks/00_HubQuickStart.ipynb" target="_blank" rel="noopener" >Jupyter Notebooks&lt;/a>, which gives access to their MySQL database in the hub!&lt;/p>
&lt;p>However, this configuration does not include permanently store the database itself between hub server sessions. Thanks to a pilot in a prior collaboration with University of Texas, Austin, we do have
&lt;a href="https://github.com/2i2c-org/infrastructure/blob/main/docs/howto/features/per-user-db.md" target="_blank" rel="noopener" >some documentation&lt;/a> on how you can enable that as well!&lt;/p>
&lt;h2 id="acknowledgements">
Acknowledgements
&lt;a class="header-anchor" href="#acknowledgements">#&lt;/a>
&lt;/h2>&lt;ul>
&lt;li>
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/hhmi/" >Howard Hughes Medical Institute&lt;/a>&lt;/li>
&lt;li>National Institute of Mental Health (NIMH), grant number RF1MH130623&lt;/li>
&lt;li>
&lt;a href="https://github.com/jupyterhub/kubespawner" target="_blank" rel="noopener" >kubespawner&lt;/a>&lt;/li>
&lt;li>
&lt;a href="https://github.com/jupyterhub/zero-to-jupyterhub-k8s/" target="_blank" rel="noopener" >zero-to-jupyterhub-k8s&lt;/a> and the
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/jupyterhub/" >JupyterHub community&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>Hacking the Project Pythia Cook-off with MyST Markdown</title><link>https://deploy-preview-608--2i2c-org.netlify.app/blog/project-pythia-cookoff/</link><pubDate>Tue, 18 Jun 2024 00:00:00 +0000</pubDate><guid>https://deploy-preview-608--2i2c-org.netlify.app/blog/project-pythia-cookoff/</guid><description>&lt;p>
&lt;figure id="figure-photo-courtesy-of-dr-debanjana-das">
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img src="./cover-featured.png" alt="Group selfie of Project Pythia Cook-off participants." loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;figcaption>
Photo courtesy of Dr Debanjana Das
&lt;/figcaption>&lt;/figure>
&lt;/p>
&lt;h2 id="what-is-project-pythia">
What is Project Pythia?
&lt;a class="header-anchor" href="#what-is-project-pythia">#&lt;/a>
&lt;/h2>&lt;p>
&lt;a href="https://projectpythia.org/" target="_blank" rel="noopener" >Project Pythia&lt;/a> is the education working group for
&lt;a href="https://pangeo.io/index.html" target="_blank" rel="noopener" >Pangeo&lt;/a>, a community platform for Big Data geoscience in which 2i2c operates a cloud hub. The core aim of Project Pythia is to spearhead the creation and curation of community-driven, open-source documentation, in the form of &amp;ldquo;cookbooks&amp;rdquo;, to enable the adoption of &lt;em>open&lt;/em>, &lt;em>scalable&lt;/em> and &lt;em>reproducible&lt;/em> workflows for geoscientists.&lt;/p>
&lt;h2 id="what-did-2i2c-do">
What did 2i2c do?
&lt;a class="header-anchor" href="#what-did-2i2c-do">#&lt;/a>
&lt;/h2>&lt;p>Jenny, James and Angus from the 2i2c team participated in the annual
&lt;a href="https://projectpythia.org/pythia-cookoff-2024/" target="_blank" rel="noopener" >Project Pythia Cook-off 2024&lt;/a>, a hackathon where cookbook authors and collaborators can spend dedicated time on creating and maintaining their content using
&lt;a href="https://jupyterbook.org/en/stable/intro.html" target="_blank" rel="noopener" >Jupyter Book&lt;/a> and deploying their cookbooks with GitHub actions.&lt;/p>
&lt;p>2i2c teamed up with the infrastructure breakout group during the hackathon, led by Katelyn FitzGerald (
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/pythia/" >UCAR&lt;/a>) and Kevin Tyle (
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/pythia/" >University at Albany&lt;/a>), and members of the
&lt;a href="https://curvenote.com" target="_blank" rel="noopener" >Curvenote&lt;/a> team also joined the group.&lt;/p>
&lt;h2 id="day-1">
Day 1
&lt;a class="header-anchor" href="#day-1">#&lt;/a>
&lt;/h2>&lt;p>2i2c deployed and demonstrated a dedicated BinderHub service for Project Pythia that allowed hackathon participants to &amp;ldquo;self-serve&amp;rdquo; images of their software environment, which were specified by including a list of packages in an &lt;code>environment.yml&lt;/code> file placed in their GitHub cookbook repository. Participants could then pull the image from a container registry into their 2i2c hub (or indeed, any other JupyterHub server) to share and reproduce their computational environments with ease.&lt;/p>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="Screenshot of Project Pythia BinderHub service" srcset="
/blog/project-pythia-cookoff/binder_huace4be54dd679dccbefe8a204243ae9f_316548_910c0edf3df8ee944ca59a76f07cbceb.webp 400w,
/blog/project-pythia-cookoff/binder_huace4be54dd679dccbefe8a204243ae9f_316548_4c49b1ac76e6399844adddf8a1c200f3.webp 760w,
/blog/project-pythia-cookoff/binder_huace4be54dd679dccbefe8a204243ae9f_316548_1200x1200_fit_q75_h2_lanczos_3.webp 1200w"
src="https://deploy-preview-608--2i2c-org.netlify.app/blog/project-pythia-cookoff/binder_huace4be54dd679dccbefe8a204243ae9f_316548_910c0edf3df8ee944ca59a76f07cbceb.webp"
width="760"
height="498"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;h2 id="day-2">
Day 2
&lt;a class="header-anchor" href="#day-2">#&lt;/a>
&lt;/h2>&lt;p>During the first half of the day, we quickly identified a number of issues that were proving to be a maintenance headache for the Project Pythia infrastructure group:&lt;/p>
&lt;ul>
&lt;li>&lt;input disabled="" type="checkbox"> Configuration files for each cookbook were difficult to update at scale. Project Pythia currently have a gallery of over 30 cookbooks!&lt;/li>
&lt;li>&lt;input disabled="" type="checkbox"> Changes to Sphinx-based themes inherited from upstream were prone to breaking custom Project Pythia branding downstream.&lt;/li>
&lt;li>&lt;input disabled="" type="checkbox"> Executable content was not able to run on the Project Pythia&amp;rsquo;s dedicated BinderHub hosted on
&lt;a href="https://jetstream-cloud.org/index.html" target="_blank" rel="noopener" >JetStream2&lt;/a> (operated by NSF).&lt;/li>
&lt;li>&lt;input disabled="" type="checkbox"> Cookbooks frequently cross-referenced materials from other cookbooks to build upon pre-existing knowledge, but this was not easy to author and the reader experience was not as smooth as it could be.&lt;/li>
&lt;/ul>
&lt;p>Following the announcement that
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/blog/project-pythia-cookoff/../myst-jupyter-book/index" >Jupyter Book 2.0 will use MyST&lt;/a> last month, Rowan (Curvenote) and Angus (2i2c) delivered a compelling demonstration of the
&lt;a href="https://mystmd.org/" target="_blank" rel="noopener" >MyST&lt;/a> ecosystem centered around modern web-first technologies (JavaScript/TypeScript) that offers improved interactivity and accessibility.&lt;/p>
&lt;p>In the second half of the day, we decided to use the hackathon to explore migrating the Pythia cookbooks from using a Sphinx-based to a MyST-based document structure and engine. Within one afternoon, the group migrated four cookbooks to use MyST MD&lt;/p>
&lt;ol>
&lt;li>
&lt;a href="https://projectpythia-mystmd.github.io/pythia-foundations/" target="_blank" rel="noopener" >Pythia Foundations&lt;/a>&lt;/li>
&lt;li>
&lt;a href="https://projectpythia-mystmd.github.io/HRRR-AWS-cookbook/" target="_blank" rel="noopener" >High Resolution Rapid Refresh on AWS&lt;/a>&lt;/li>
&lt;li>
&lt;a href="https://projectpythia-mystmd.github.io/radar-cookbook/" target="_blank" rel="noopener" >Radar Cookbook&lt;/a>&lt;/li>
&lt;li>
&lt;a href="https://projectpythia-mystmd.github.io/advanced-viz-cookbook/" target="_blank" rel="noopener" >Advanced Visualization&lt;/a>.&lt;/li>
&lt;/ol>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="Screenshot of a side by side comparison of the Sphinx (left) and MyST (right) based cookbook." srcset="
/blog/project-pythia-cookoff/side-by-side_hu9cd3b350a3f864d97093bd955d197fa3_1447042_e593e37e5e427b324ce4522a66502926.webp 400w,
/blog/project-pythia-cookoff/side-by-side_hu9cd3b350a3f864d97093bd955d197fa3_1447042_d492501d5a4784b6e56aea2179e4e4d5.webp 760w,
/blog/project-pythia-cookoff/side-by-side_hu9cd3b350a3f864d97093bd955d197fa3_1447042_1200x1200_fit_q75_h2_lanczos_3.webp 1200w"
src="https://deploy-preview-608--2i2c-org.netlify.app/blog/project-pythia-cookoff/side-by-side_hu9cd3b350a3f864d97093bd955d197fa3_1447042_e593e37e5e427b324ce4522a66502926.webp"
width="760"
height="438"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;p>This moment was palpably exciting! It was evident that MyST MD supported backwards compatible content out of the box, which alleviated fears of sunk cost into existing Sphinx-based cookbooks. The migration workflow was as simple as executing the following commands&lt;/p>
&lt;p>&lt;code>conda install mystmd&lt;/code>&lt;/p>
&lt;p>&lt;code>myst&lt;/code>.&lt;/p>
&lt;h2 id="day-3">
Day 3
&lt;a class="header-anchor" href="#day-3">#&lt;/a>
&lt;/h2>&lt;p>We spent this day tackling support for managing a gallery of Project Pythia cookbooks at scale. See the
&lt;a href="https://executablebooks.org/en/latest/blog/2024-06-14-project-pythia-mystmd/" target="_blank" rel="noopener" >Executable Books blog post&lt;/a> for technical details on how we&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://github.com/projectpythia-mystmd/pythia-config" target="_blank" rel="noopener" >Centralized configuration&lt;/a>&lt;/li>
&lt;li>Prototyped a
&lt;a href="https://projectpythia-mystmd.github.io/" target="_blank" rel="noopener" >gallery&lt;/a> plugin in Python&lt;/li>
&lt;li>Fixed a number of bugs related to integrated computation with
&lt;a href="https://mystmd.org/guide/integrating-jupyter#connecting-to-a-binder" target="_blank" rel="noopener" >Binder&lt;/a> and
&lt;a href="https://mystmd.org/guide/integrating-jupyter#jupyterlite" target="_blank" rel="noopener" >JupyterLite&lt;/a>&lt;/li>
&lt;li>Embraced the referencing and reuse of content with
&lt;a href="https://mystmd.org/guide/external-references#tbl-syntax-xref" target="_blank" rel="noopener" >simple markdown syntax for hover-references&lt;/a>.&lt;/li>
&lt;/ul>
&lt;video mute autoplay loop >
&lt;source src="https://deploy-preview-608--2i2c-org.netlify.app/blog/project-pythia-cookoff/hover-ref.mp4" type="video/mp4">
&lt;/video>
&lt;h2 id="day-4">
Day 4
&lt;a class="header-anchor" href="#day-4">#&lt;/a>
&lt;/h2>&lt;p>Looking to the future, we spent time reflecting on our experiences and discussing the potential, transformative impact MyST MD tooling could have in the hands of the scientific community at large, including the communities served by 2i2c. Knowledge-sharing based on static figures and PDFs would fall obsolete and give way to a dynamic, web-first approach to sharing interactive narratives backed by compute from a Jupyter server.&lt;/p>
&lt;p>Throughout the course of the hackathon, the rate of iterated development for both end users of the community cookbook and the developers of the open-source tooling was astounding. For example, we were able to quickly expose small bugs (
&lt;a href="https://github.com/executablebooks/mystmd/issues/1297" target="_blank" rel="noopener" >e.g. support for HTML video tags&lt;/a>) in the MyST MD tooling, which were immediately fixed upstream and released within minutes. The feedback loop that connected the user experience with the software tooling was incredibly synergistic, with immediate impact both upstream and downstream that 2i2c hopes to continue replicating across many facets of their operations.&lt;/p>
&lt;p>Beyond the Project Pythia Cook-off, the breakout group will continue conversations around strengthening their community of practice and hopefully advocating for wider adoption of MyST MD amongst the scientific community (say hello to some of our group members at
&lt;a href="https://www.scipy2024.scipy.org/" target="_blank" rel="noopener" >SciPy 2024&lt;/a> in July!).&lt;/p>
&lt;h2 id="acknowledgements">
Acknowledgements
&lt;a class="header-anchor" href="#acknowledgements">#&lt;/a>
&lt;/h2>&lt;ul>
&lt;li>
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/pythia/" >University at Albany&lt;/a> (NSF award 2324302): Led the funding acquisition, helped organize and facilitate the event&lt;/li>
&lt;li>
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/pythia/" >UCAR&lt;/a> (NSF award 2324303): Led the planning and logistics for the event&lt;/li>
&lt;li>
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/pythia/" >Project Pythia&lt;/a> for organizing this workshop.&lt;/li>
&lt;li>
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/jupyter-book/" >Jupyter Book&lt;/a> for providing development and collaboration at this workshop.&lt;/li>
&lt;li>2i2c / Code for Science and Society (NSF award 2324304): Provided tailored compute services and on-site support&lt;/li>
&lt;li>
&lt;a href="https://curvenote.com" target="_blank" rel="noopener" >Curvenote&lt;/a>: Contributed engineering cycles to MyST MD development.&lt;/li>
&lt;/ul></description></item><item><title>Jupyter Book 2.0 will use MyST</title><link>https://deploy-preview-608--2i2c-org.netlify.app/blog/myst-jupyter-book/</link><pubDate>Tue, 21 May 2024 00:00:00 +0000</pubDate><guid>https://deploy-preview-608--2i2c-org.netlify.app/blog/myst-jupyter-book/</guid><description>&lt;p>See
&lt;a href="https://executablebooks.org/en/latest/blog/2024-05-20-jupyter-book-myst/" target="_blank" rel="noopener" >the Executable Books blog&lt;/a> for a post on the future directions of the Jupyter Book project, which will be built on top of the
&lt;a href="https://mystmd.org" target="_blank" rel="noopener" >MyST Markdown engine&lt;/a>.&lt;/p>
&lt;h2 id="acknowledgements">
Acknowledgements
&lt;a class="header-anchor" href="#acknowledgements">#&lt;/a>
&lt;/h2>&lt;ul>
&lt;li>This post relates to our ongoing collaboration with the
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/jupyter-book/" >Jupyter Book&lt;/a> project.&lt;/li>
&lt;li>Thanks to
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/pythia/" >Project Pythia&lt;/a> for funding part of our work on Jupyter Book.&lt;/li>
&lt;/ul></description></item><item><title>Security report for jupyter-server-proxy: CVE-2024-28179</title><link>https://deploy-preview-608--2i2c-org.netlify.app/blog/cve-jupyter-server-proxy/</link><pubDate>Tue, 19 Mar 2024 00:00:00 +0000</pubDate><guid>https://deploy-preview-608--2i2c-org.netlify.app/blog/cve-jupyter-server-proxy/</guid><description>
&lt;h2 id="what-happened">
What happened?
&lt;a class="header-anchor" href="#what-happened">#&lt;/a>
&lt;/h2>&lt;p>A few weeks ago, the JupyterHub team discovered a security vulnerability in
&lt;a href="https://jupyter-server-proxy.readthedocs.io/en/latest/" target="_blank" rel="noopener" >the &lt;code>jupyter-server-proxy&lt;/code> package&lt;/a> that would allow potential unauthenticated access to a JupyterHub via WebSockets, allowing unauthenticated users to run arbitrary code on the JupyterHub.
&lt;code>jupyter-server-proxy&lt;/code> is used by many communities to provide alternative user interfaces like RStudio and remote desktops.&lt;/p>
&lt;p>This vulnerability was detected by the JupyterHub team, with leadership from 2i2c&amp;rsquo;s engineers. It was resolved through upstream contributions to the JupyterHub project, and we have deployed a fix that mitigates this vulnerability for all the hubs 2i2c manages.&lt;/p>
&lt;h2 id="does-this-impact-my-2i2c-community-hub">
Does this impact my 2i2c community hub?
&lt;a class="header-anchor" href="#does-this-impact-my-2i2c-community-hub">#&lt;/a>
&lt;/h2>&lt;p>We do not believe that any of 2i2c&amp;rsquo;s communities were impacted by this vulnerability, and
&lt;a href="https://github.com/2i2c-org/infrastructure/blob/f86d128a0d045163e72802f6df287a6f46d4b738/helm-charts/basehub/values.yaml#L296" target="_blank" rel="noopener" >a patch&lt;/a> has now been pushed to all community hubs to resolve this issue.&lt;/p>
&lt;p>If your community was vulnerable to this problem, you might experience slightly slower startup latency while we work out a long-term solution.&lt;/p>
&lt;p>Since this is a vulnerability in the docker image used by our communities, we will be reaching out over the next few weeks to put a more permanent fix in place.&lt;/p>
&lt;h2 id="where-can-i-learn-more">
Where can I learn more?
&lt;a class="header-anchor" href="#where-can-i-learn-more">#&lt;/a>
&lt;/h2>&lt;p>See
&lt;a href="https://github.com/jupyterhub/jupyter-server-proxy/security/advisories/GHSA-w3vc-fx9p-wp4v" target="_blank" rel="noopener" >the JupyterHub security advisory for CVE-2024-28179&lt;/a> for more information about the security vulnerability, including details on the mitigation we have put in place to protect our communities.&lt;/p>
&lt;h2 id="conclusion">
Conclusion
&lt;a class="header-anchor" href="#conclusion">#&lt;/a>
&lt;/h2>&lt;p>We&amp;rsquo;re grateful that the JupyterHub community was quick to acknowledge, respond, and resolve this security vulnerability after it was brought to their attention.
We&amp;rsquo;re also proud that 2i2c&amp;rsquo;s engineers helped the JupyterHub team throughout the process.&lt;/p>
&lt;p>This allowed our team to resolve the problem before it impacted any of 2i2c&amp;rsquo;s communities.
Because 2i2c community infrastructure is managed in a central location, we were able to resolve this for over 80 communities with a single team rather than expecting each community to learn about and fix this problem on their own.&lt;/p>
&lt;p>We also believe this reflects the healthy upstream relationships that we hope to encourage with our team&amp;rsquo;s
&lt;a href="https://compass.2i2c.org/open-source/" target="_blank" rel="noopener" >Open Source strategy and practices&lt;/a>.
By working with the JupyterHub community and pushing changes upstream, we&amp;rsquo;ve resolved this issue for &lt;em>any&lt;/em> user of &lt;code>jupyter-server-proxy&lt;/code>, not just 2i2c&amp;rsquo;s own ecosystem.
In particular, because of 2i2c&amp;rsquo;s position running hubs for many communities via Kubernetes, we were able to identify a solution that did not require every user image to be updated (as described in section &lt;strong>For JupyterHub admins of Z2JH installations&lt;/strong>).&lt;/p>
&lt;p>We believe that all of these lead to a healthier, safer ecosystem of open source tools ❤️.&lt;/p></description></item><item><title>Integrating BinderHub with JupyterHub: Empowering users to manage their own environments</title><link>https://deploy-preview-608--2i2c-org.netlify.app/blog/jupyterhub-binderhub-gesis/</link><pubDate>Wed, 03 Jan 2024 16:56:14 -0800</pubDate><guid>https://deploy-preview-608--2i2c-org.netlify.app/blog/jupyterhub-binderhub-gesis/</guid><description>&lt;p>&lt;em>Thanks to
&lt;a href="https://www.gesis.org/en/institute/staff/person/arnim.bleier" target="_blank" rel="noopener" >Arnim Bleier&lt;/a>,
&lt;a href="https://jnywong.github.io/" target="_blank" rel="noopener" >Jenny Wong&lt;/a>,
&lt;a href="https://github.com/GeorgianaElena" target="_blank" rel="noopener" >Georgiana Elena&lt;/a>,
&lt;a href="https://github.com/damianavila" target="_blank" rel="noopener" >Damián Avila&lt;/a>,
&lt;a href="https://colliand.com/" target="_blank" rel="noopener" >Jim Colliander&lt;/a> and
&lt;a href="https://github.com/jmunroe" target="_blank" rel="noopener" >James Munroe&lt;/a> for contributing to this blog post&lt;/em>&lt;/p>
&lt;p>
&lt;a href="https://mybinder.org" target="_blank" rel="noopener" >mybinder.org&lt;/a> is a very popular service that allows end users to specify and share the environment (languages, packages, etc) required for their notebooks to run correctly by placing
&lt;a href="https://repo2docker.readthedocs.io/en/latest/config_files.html#config-files" target="_blank" rel="noopener" >configuration files&lt;/a> they are already familiar with (like &lt;code>requirements.txt&lt;/code> or &lt;code>environment.yml&lt;/code>) along with their notebooks. While not without its own set of challenges, this is extremely powerful because it puts control of the &lt;em>environment&lt;/em> in the hands of the people who write the code. They can customize the environment to fit the needs of their code, instead of having to fit their code into the environment that admins have made available.&lt;/p>
&lt;p>But, mybinder.org (and the
&lt;a href="https://github.com/jupyterhub/binderhub/" target="_blank" rel="noopener" >BinderHub&lt;/a> software that powers it) is built for &lt;em>sharing&lt;/em> your work after you are done with it, &lt;em>not&lt;/em> for actively doing work. BinderHubs often do not have persistent storage nor persistent user identity, and UX is centered around &lt;em>ephemeral&lt;/em> interactivity that can be shared with others (via a link), rather than &lt;em>persistent&lt;/em> interactivity that a single user repeatedly comes back to.
&lt;a href="https://jupyter.org/hub" target="_blank" rel="noopener" >JupyterHub&lt;/a> is more commonly used for this kinda workflow, but doesn&amp;rsquo;t currently have the ability for users to easily build their own environments. Admins who are &lt;em>running&lt;/em> the JupyterHub can make
&lt;a href="https://z2jh.jupyter.org/en/stable/jupyterhub/customizing/user-environment.html#using-multiple-profiles-to-let-users-select-their-environment" target="_blank" rel="noopener" >multiple environments&lt;/a> available for users to choose from, but this still puts admins in the critical path for environment customization.&lt;/p>
&lt;p>Our
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/blog/gesis-2i2c-collaboration-update/" >collaboration&lt;/a> with
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/gesis/" >GESIS&lt;/a>,
&lt;a href="https://www.nfdi4datascience.de" target="_blank" rel="noopener" >NFDI4DS&lt;/a>, and
&lt;a href="https://www.cessda.eu" target="_blank" rel="noopener" >CESSDA&lt;/a>, aims to bring this flexibility to JupyterHub directly. We aim to empower users to decide for themselves which applications and dependencies are installed on a per-project basis. Our work enables communities with heterogeneous requirements to share a single Hub. Our approach frees administrators from being overwhelmed by installation requests and transforms the JupyterHub platform into a platform for collaborative computational reproducibility. In this update, we report on our progress and upcoming steps in this project.&lt;/p>
&lt;h2 id="what-does-a-binderhub-do-exactly">
What does a BinderHub do, exactly?
&lt;a class="header-anchor" href="#what-does-a-binderhub-do-exactly">#&lt;/a>
&lt;/h2>&lt;p>It is helpful to understand that BinderHub primarily has 3 responsibilities:&lt;/p>
&lt;ol>
&lt;li>Present a UI to the end user for them to provide details on what to build (this is what you see when you go to mybinder.org)&lt;/li>
&lt;li>Call out to
&lt;a href="https://github.com/jupyterhub/repo2docker" target="_blank" rel="noopener" >repo2docker&lt;/a> in a scalable way to actually &lt;em>build and push&lt;/em> an image containing the environment for the given repository, and show the user logs as this build process happens. This also allows users to debug issues with their build more easily.&lt;/li>
&lt;li>Talk to a JupyterHub instance to launch a user server with the built docker image, and redirect the user to this.&lt;/li>
&lt;/ol>
&lt;p>(2) is really the &lt;em>core&lt;/em> feature of BinderHub, and we settled on figuring out how to make that available to JupyterHub users. It was really important to us that this was also done in a way that can be sustainably used by &lt;em>everyone&lt;/em>, not just 2i2c. This blog post discusses the various improvements to the broad ecosystem of projects in the Jupyter ecosystem to get this done.&lt;/p>
&lt;h2 id="demo">
Demo
&lt;a class="header-anchor" href="#demo">#&lt;/a>
&lt;/h2>&lt;p>But first, a very quick demo of how this looks like right now now!&lt;/p>
&lt;!-- generated from original .mov screen recording with `ffmpeg -i screencast.mov -c:v libx264 screencast.mp4` -->
&lt;p>&lt;video src="./screencast.mp4" autoplay muted controls>&lt;/video>&lt;/p>
&lt;p>This is very much a work in progress, but the basic flow can be seen clearly. Users see a Server Options menu after they log into JupyterHub. They can specify the two primary things that determine the server configuration:&lt;/p>
&lt;ol>
&lt;li>
&lt;p>The resources allocated (RAM, CPU and maybe GPU)&lt;/p>
&lt;/li>
&lt;li>
&lt;p>The environment (container image) used, which can be specified in one of 3 ways:&lt;/p>
&lt;p>a. A pre-selected list of environments (container images), provided by the administrators who set up this JupyterHub
b. A blank text box where you can enter any publicly available docker image they want
c. A mybinder.org style way to specify a GitHub repository, which will be then dynamically built into a docker image for the user!&lt;/p>
&lt;/li>
&lt;/ol>
&lt;p>So what did we need to do to accomplish this, in a way that&amp;rsquo;s very upstream friendly and usable by everyone (and not just 2i2c)?&lt;/p>
&lt;h2 id="a-standalone-binderhub-service-helm-chart">
A Standalone &lt;code>binderhub-service&lt;/code> helm chart
&lt;a class="header-anchor" href="#a-standalone-binderhub-service-helm-chart">#&lt;/a>
&lt;/h2>&lt;p>The default upstream
&lt;a href="https://github.com/jupyterhub/binderhub/tree/main/helm-chart" target="_blank" rel="noopener" >BinderHub helm chart&lt;/a> &lt;em>includes&lt;/em> a JupyterHub as a dependency, and configures itself to be used primarily in a manner similar to
&lt;a href="https://mybinder.org" target="_blank" rel="noopener" >mybinder.org&lt;/a>. As the person who helped make that choice early on, I can tell you why it was made - for convenience! And it &lt;em>was&lt;/em> very convenient, as it allowed us to get mybinder.org going fast. However, it makes it difficult to install a BinderHub service &lt;em>alongside&lt;/em> an existing JupyterHub. To this end, we have created a standalone
&lt;a href="https://github.com/2i2c-org/binderhub-service/" target="_blank" rel="noopener" >BinderHub helm chart&lt;/a>, designed to be installed &lt;em>alongside&lt;/em> an existing JupyterHub, so we can use it &lt;em>purely&lt;/em> to build images. This allows the BinderHub instance to be used as a
&lt;a href="https://jupyterhub.readthedocs.io/en/stable/reference/services.html" target="_blank" rel="noopener" >JupyterHub Service&lt;/a>, which is what we want.&lt;/p>
&lt;p>While this helm chart is currently under the 2i2c GitHub org, the hope is that it can eventually migrate to a
&lt;a href="https://github.com/jupyterhub/team-compass/issues/519" target="_blank" rel="noopener" >jupyterhub-contrib&lt;/a> organization (once it is created), or it can become the upstream helm chart for BinderHub if enough work can be done in BinderHub to allow it to serve use cases like mybinder.org.&lt;/p>
&lt;p>As part of this work, we also added a way for BinderHub to run in
&lt;a href="https://github.com/jupyterhub/binderhub/pull/1647" target="_blank" rel="noopener" >API only mode&lt;/a>, so we can fully turn off the UI &lt;em>and&lt;/em> launching ability of BinderHub. This change decoupled the
&lt;a href="#what-does-a-binderhub-do-exactly" >three responsibilities of BinderHub&lt;/a> we discussed previously, allowing us to bring our own UI and JupyterHub. BinderHub could now be used &lt;em>purely&lt;/em> for its scalable image building features, which is exactly what we want!&lt;/p>
&lt;h2 id="sustainably-extending-kubespawners-profilelist">
Sustainably extending KubeSpawner&amp;rsquo;s &lt;code>profileList&lt;/code>
&lt;a class="header-anchor" href="#sustainably-extending-kubespawners-profilelist">#&lt;/a>
&lt;/h2>&lt;p>We identified KubeSpawner&amp;rsquo;s &lt;code>profileList&lt;/code> feature as the ideal location for UI to dynamically build environments (container images), making it just another &amp;rsquo;environment choice&amp;rsquo; people can choose, along with picking the resources their server needs. From an end-user perspective, it was also the logical place for them to specify a repository to build into an environment, as they could already choose some pre-built environments from here. They can also select other arbitrary resources they want (such as memory, GPU, etc) from here as well. From a maintainer perspective, it helps with long-term maintenance of the JupyterHub projects.&lt;/p>
&lt;p>The implementation of &lt;code>profileList&lt;/code> however, was not easy to extend at this point. So
&lt;a href="https://github.com/jupyterhub/kubespawner/pull/724" target="_blank" rel="noopener" >this PR&lt;/a> improved how easy it was to extend it in more complex ways, without making the implementation in KubeSpawner itself complicated. Even though this had &lt;em>no&lt;/em> visible end-user effects, it was an extremely important step in allowing us to experiment with UI in a &lt;em>sustainable&lt;/em> way without having to rely on upstream. These kinds of changes can sometimes be hard to sell to stakeholders but are extremely important in ensuring a continuous and sustainable relationship with upstream.&lt;/p>
&lt;h2 id="implementing-unlisted_choice-feature-in-kubespawner">
Implementing &lt;code>unlisted_choice&lt;/code> feature in KubeSpawner
&lt;a class="header-anchor" href="#implementing-unlisted_choice-feature-in-kubespawner">#&lt;/a>
&lt;/h2>&lt;p>The profileList feature was built to allow JupyterHub &lt;em>admins&lt;/em> to specify an explicit list of container images the end-user can choose from. It did not have a way for any choice that was &lt;em>not&lt;/em> pre-approved by the admin to be used. We needed this feature since the BinderHub API will build a new docker image for each environment the user wants, and so this can not be chosen from a pre-approved list. We had to safely add this feature to KubeSpawner in such a way that it was generally useful to everyone. Many other communities had been asking for such a feature anyway - the ability to simply &amp;rsquo;type in&amp;rsquo; an image and have that be used.&lt;/p>
&lt;p>
&lt;a href="https://www.earthdata.nasa.gov/esds/veda" target="_blank" rel="noopener" >NASA VEDA&lt;/a> was one such community, so we partnered with
&lt;a href="https://github.com/batpad/" target="_blank" rel="noopener" >Sanjay Bhangar&lt;/a> from
&lt;a href="https://developmentseed.org/" target="_blank" rel="noopener" >Development Seed&lt;/a> (an organization that helps run NASA VEDA) to implement this feature. Engineers from 2i2c contributed heavily to this feature as well, and after &lt;em>several&lt;/em> PRs (
&lt;a href="https://github.com/jupyterhub/kubespawner/pull/735" target="_blank" rel="noopener" >1&lt;/a>,
&lt;a href="https://github.com/jupyterhub/kubespawner/pull/766" target="_blank" rel="noopener" >2&lt;/a>,
&lt;a href="https://github.com/jupyterhub/kubespawner/pull/773" target="_blank" rel="noopener" >3&lt;/a>,
&lt;a href="https://github.com/jupyterhub/kubespawner/pull/774" target="_blank" rel="noopener" >4&lt;/a> and
&lt;a href="https://github.com/jupyterhub/kubespawner/pull/777" target="_blank" rel="noopener" >5&lt;/a>), this feature is now available for everyone to use!&lt;/p>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img src="./screenshot-featured.png" alt="Screenshot of Kubernetes Profiles with Unlisted Choice" loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;p>A key component of doing &lt;em>sustainable&lt;/em> upstream work is that every addition needs to be useful by itself for a broad group of people. This change was very helpful for many communities that wanted to allow their users the freedom to pick whatever image they want to use, regardless of wether they wanted to use dynamic image building or not. The broad interest allowed us to build a coalition with other interested parties, and get the change accepted upstream more easily!&lt;/p>
&lt;h2 id="jupyterhub-fancy-profiles">
&lt;code>jupyterhub-fancy-profiles&lt;/code>
&lt;a class="header-anchor" href="#jupyterhub-fancy-profiles">#&lt;/a>
&lt;/h2>&lt;p>Once we had all these pieces in place, it was time to actually work on the frontend UI that would allow users to build images dynamically and launch them. Since this will replace the &amp;lsquo;profileList&amp;rsquo; feature, it should also allow them to select different resources (RAM, CPU, etc) as needed, as well as type in an existing image if they desire. So it was a full re-implementation of the &lt;code>profileList&lt;/code> frontend.&lt;/p>
&lt;p>This is ongoing now at the
&lt;a href="https://github.com/yuvipanda/jupyterhub-fancy-profiles" target="_blank" rel="noopener" >jupyterhub-fancy-profiles&lt;/a> project. It is a pure frontend web application, using modern frontend tooling (
&lt;a href="https://react.dev/" target="_blank" rel="noopener" >React&lt;/a>,
&lt;a href="https://webpack.js.org/" target="_blank" rel="noopener" >webpack&lt;/a>,
&lt;a href="https://babeljs.io/" target="_blank" rel="noopener" >Babel&lt;/a>, etc) and written in JavaScript. It&amp;rsquo;s gone through a few revisions, but the demo provided earlier in the blog post is in its current state. Because the default profileList implementation is pure HTML / CSS with very &lt;em>minimal&lt;/em> JS, it is limited in what kind of UX it could have. &lt;code>jupyterhub-fancy-profiles&lt;/code> aims to be very helpful &lt;em>even&lt;/em> when dynamic image-building features are not enabled on a JupyterHub. We hope to roll this out to a few JupyterHubs and improve it over time based on feedback.&lt;/p>
&lt;h2 id="jupyterhubbinderhub-clienthttpswwwnpmjscompackagejupyterhubbinderhub-client-npm-package">
&lt;a href="https://www.npmjs.com/package/@jupyterhub/binderhub-client" target="_blank" rel="noopener" >&lt;code>jupyterhub/@binderhub-client&lt;/code>&lt;/a> npm package
&lt;a class="header-anchor" href="#jupyterhubbinderhub-clienthttpswwwnpmjscompackagejupyterhubbinderhub-client-npm-package">#&lt;/a>
&lt;/h2>&lt;p>While building &lt;code>jupyterhub-fancy-profiles&lt;/code>, we wanted to use the &lt;em>same&lt;/em> javascript code used by BinderHub frontend to interact with the BinderHub API, instead of re-implementing it. However, the existing BinderHub JavaScript code was not easily consumable by external projects. We refactored the code, added tests, migrated to use modern JS practices and published the
&lt;a href="https://www.npmjs.com/package/@jupyterhub/binderhub-client" target="_blank" rel="noopener" >&lt;code>jupyterhub/@binderhub-client&lt;/code> NPM package&lt;/a> that can be used not just by &lt;code>jupyerhub-fancy-profiles&lt;/code> but any external project for talking to the BinderHub API.&lt;/p>
&lt;p>This had to be done in such a way that current BinderHub installations (such as mybinder.org) do not break. That took quite a few pull requests:
&lt;a href="https://github.com/jupyterhub/binderhub/pull/1689" target="_blank" rel="noopener" >1&lt;/a>,
&lt;a href="https://github.com/jupyterhub/binderhub/pull/1693" target="_blank" rel="noopener" >2&lt;/a>,
&lt;a href="https://github.com/jupyterhub/binderhub/pull/1694" target="_blank" rel="noopener" >3&lt;/a>,
&lt;a href="https://github.com/jupyterhub/binderhub/pull/1741" target="_blank" rel="noopener" >4&lt;/a>,
&lt;a href="https://github.com/jupyterhub/binderhub/pull/1742" target="_blank" rel="noopener" >5&lt;/a>,
&lt;a href="https://github.com/jupyterhub/binderhub/pull/1758" target="_blank" rel="noopener" >6&lt;/a>,
&lt;a href="https://github.com/jupyterhub/binderhub/pull/1761" target="_blank" rel="noopener" >7&lt;/a>,
&lt;a href="https://github.com/jupyterhub/binderhub/pull/1771" target="_blank" rel="noopener" >8&lt;/a>,
&lt;a href="https://github.com/jupyterhub/binderhub/pull/1773" target="_blank" rel="noopener" >9&lt;/a>,
&lt;a href="https://github.com/jupyterhub/binderhub/pull/1775" target="_blank" rel="noopener" >10&lt;/a>,
&lt;a href="https://github.com/jupyterhub/binderhub/pull/1778" target="_blank" rel="noopener" >11&lt;/a>,
&lt;a href="https://github.com/jupyterhub/binderhub/pull/1779" target="_blank" rel="noopener" >12&lt;/a>,
&lt;a href="https://github.com/jupyterhub/binderhub/pull/1781" target="_blank" rel="noopener" >13&lt;/a>,
&lt;a href="https://github.com/jupyterhub/binderhub/pull/1782" target="_blank" rel="noopener" >14&lt;/a>,
&lt;a href="https://github.com/jupyterhub/binderhub/pull/1783" target="_blank" rel="noopener" >15&lt;/a>. This refactoring work was very helpful to us, and also appreciated by the broader community.&lt;/p>
&lt;h2 id="defending-against-cryptojacking-with-cryptnono">
Defending against cryptojacking with &lt;code>cryptnono&lt;/code>
&lt;a class="header-anchor" href="#defending-against-cryptojacking-with-cryptnono">#&lt;/a>
&lt;/h2>&lt;p>For Open Science to flourish, we need to allow access to resources without login / paywalls wherever possible. A new menace against this has been
&lt;a href="https://www.interpol.int/en/Crimes/Cybercrime/Cryptojacking" target="_blank" rel="noopener" >cryptojacking&lt;/a> - where attackers use up any and all available free compute to mine cryptocurrencies. This has affected &lt;em>many&lt;/em> folks on the internet, including
&lt;a href="https://www.bleepingcomputer.com/news/security/github-actions-being-actively-abused-to-mine-cryptocurrency-on-github-servers/" target="_blank" rel="noopener" >GitHub Actions&lt;/a> and mybinder.org, the primary public BinderHub installation. mybinder.org has some extra protections against cryptojacking that aren&amp;rsquo;t easily usable elsewhere, and this has unfortunately meant that the demo JupyterHubs we have with these features enabled have been behind a login wall. I personally believe login walls are long term antithetical to open science, and so this was an important problem to solve.&lt;/p>
&lt;p>
&lt;a href="https://github.com/cryptnono/cryptnono" target="_blank" rel="noopener" >cryptnono&lt;/a> is an open source project designed to help fight cryptojacking, and as part of this grant we ported some of this functionality out of mybinder.org specific code into cryptnono, so other deployments may also benefit from it! We also migrated to using the super efficient
&lt;a href="https://ebpf.io/" target="_blank" rel="noopener" >ebpf&lt;/a> Linux Kernel subsystem, allowing for more complex heuristics to catch a much broader range of cryptomining activity. We have been slowly tweaking the config on mybinder.org, and it has proven to be very effective! This will be very helpful for &lt;em>anyone&lt;/em> who wants to provide a JupyterHub (or any other computational service) without a login wall. If you are interested in using cryptnono in this fashion, please
&lt;a href="https://github.com/cryptnono/cryptnono/issues" target="_blank" rel="noopener" >reach out to us&lt;/a> so we can work together!&lt;/p>
&lt;h2 id="explored-pathways-that-were-then-discarded">
Explored pathways that were then discarded
&lt;a class="header-anchor" href="#explored-pathways-that-were-then-discarded">#&lt;/a>
&lt;/h2>&lt;p>List of things that were tried and then decided as not good pathways:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://github.com/consideRatio/repo2docker-service" target="_blank" rel="noopener" >repo2docker-service&lt;/a>, a separate JupyterHub service that could &lt;em>only&lt;/em> build images. As we worked on it, we realized that it was replicating a lot of features that BinderHub already has, so we pivoted to working on BinderHub directly instead.&lt;/li>
&lt;li>Building off of
&lt;a href="https://github.com/plasmabio/tljh-repo2docker" target="_blank" rel="noopener" >tljh-repo2docker&lt;/a>. While this already had a nice UI, it would be hard to port it to run on a distributed Kubernetes environment without it becoming a &amp;lsquo;hard fork&amp;rsquo;.&lt;/li>
&lt;/ul>
&lt;p>While these did slow down the implementation of the project, it has allowed us to be very confident that the methods we have chosen are long-term sustainable.&lt;/p>
&lt;h2 id="want-to-try-this-out">
Want to try this out?
&lt;a class="header-anchor" href="#want-to-try-this-out">#&lt;/a>
&lt;/h2>&lt;p>We have a demo of this running at
&lt;a href="https://imagebuilding-demo.2i2c.cloud" target="_blank" rel="noopener" >imagebuilding-demo.2i2c.cloud&lt;/a>, but unfortunately as we are still fine-tuning &lt;code>cryptnono&lt;/code> config, at this moment it is not open to the public. Please
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/blog/jupyterhub-binderhub-gesis/mailto:yuvipanda@2i2c.org" >contact me&lt;/a> with your GitHub account if you want access, and promise to not be a cryptominer and you shall be granted access.&lt;/p>
&lt;p>Want to set this up on your own JupyterHub? There is some
&lt;a href="https://github.com/2i2c-org/binderhub-service/pull/72" target="_blank" rel="noopener" >work in progress&lt;/a> documentation and more is being worked on. Drop a line in the linked pull request and we&amp;rsquo;ll be happy to help. The eventual goal is for &lt;em>anyone&lt;/em> to be able to simply follow documentation and set this up for themselves.&lt;/p>
&lt;p>We also have user facing documentation on using this service on
&lt;a href="https://docs.2i2c.org/user/environment/dynamic-imagebuilding#dynamic-image-building" target="_blank" rel="noopener" >docs.2i2c.org&lt;/a>.&lt;/p>
&lt;h2 id="future-work">
Future work
&lt;a class="header-anchor" href="#future-work">#&lt;/a>
&lt;/h2>&lt;p>This is not complete of course, and there is a lot of future work to be done.&lt;/p>
&lt;ol>
&lt;li>mybinder.org also helps you distribute your &lt;em>content&lt;/em>, not just the environment for your code to run in. Since JupyterHub usually comes with a persistent home directory for the user,
&lt;a href="https://github.com/jupyterhub/nbgitpuller/" target="_blank" rel="noopener" >nbgitpuller&lt;/a> is commonly used for this purpose instead. We should explore ways to integrate nbgitpuller (and other ways to distribute content) in the future.&lt;/li>
&lt;li>More thorough documentation for how you can recreate what is in the demo for yourself in your own JupyterHub installation.&lt;/li>
&lt;li>Better UX for specifying images, including figuring out how to &amp;lsquo;save&amp;rsquo; them for future reuse.&lt;/li>
&lt;li>Better compatibility with mybinder.org, particularly in allowing other sources of environments (not just GitHub, but Zenodo, raw git repositories, etc) and URL compatibility.&lt;/li>
&lt;li>Better authentication workflow between the frontend and the BinderHub API.&lt;/li>
&lt;/ol>
&lt;h2 id="credit">
Credit
&lt;a class="header-anchor" href="#credit">#&lt;/a>
&lt;/h2>&lt;p>All this work would not be possible without a large group of collaborators!&lt;/p>
&lt;ul>
&lt;li>From 2i2c:
&lt;a href="https://github.com/consideRatio" target="_blank" rel="noopener" >Erik Sundell&lt;/a>,
&lt;a href="https://github.com/GeorgianaElena" target="_blank" rel="noopener" >Georgiana Elena&lt;/a>,
&lt;a href="https://words.yuvi.in/" target="_blank" rel="noopener" >Yuvi&lt;/a>,
&lt;a href="https://github.com/jmunroe" target="_blank" rel="noopener" >James Munroe&lt;/a>, and
&lt;a href="https://github.com/damianavila" target="_blank" rel="noopener" >Damián Avila&lt;/a>.&lt;/li>
&lt;li>The
&lt;a href="https://github.com/gesiscss/persistent_BinderHub/" target="_blank" rel="noopener" >persistent BinderHub&lt;/a> project was the direct inspiration for all this work, with particular thanks to
&lt;a href="https://github.com/bitnik" target="_blank" rel="noopener" >Kenan Erdogan&lt;/a>.&lt;/li>
&lt;li>The
&lt;a href="https://github.com/plasmabio/tljh-repo2docker" target="_blank" rel="noopener" >tljh-repo2docker&lt;/a> project, which explores similar ideas in the context of running only on a single node.&lt;/li>
&lt;li>The broad JupyterHub and MyBinder.org community, particularly
&lt;a href="https://github.com/manics" target="_blank" rel="noopener" >Simon Li&lt;/a> and
&lt;a href="https://github.com/minrk/" target="_blank" rel="noopener" >MinRK&lt;/a>.&lt;/li>
&lt;li>Funding generously provided by
&lt;a href="http://gesis.org" target="_blank" rel="noopener" >GESIS&lt;/a> in cooperation with NFDI4DS (project number:
&lt;a href="https://gepris.dfg.de/gepris/projekt/460234259?context=projekt&amp;amp;task=showDetail&amp;amp;id=460234259&amp;amp;" target="_blank" rel="noopener" >460234259&lt;/a>) and
&lt;a href="https://www.cessda.eu" target="_blank" rel="noopener" >CESSDA&lt;/a>.&lt;/li>
&lt;li>
&lt;a href="https://www.gesis.org/en/institute/staff/person/arnim.bleier" target="_blank" rel="noopener" >Arnim Bleier&lt;/a> from GESIS was &lt;em>instrumental&lt;/em> in making this project happen.&lt;/li>
&lt;/ul></description></item><item><title>2i2c supports Jupyter Docker Stacks ARM builds</title><link>https://deploy-preview-608--2i2c-org.netlify.app/blog/docker-stacks-support/</link><pubDate>Fri, 01 Dec 2023 00:00:00 +0000</pubDate><guid>https://deploy-preview-608--2i2c-org.netlify.app/blog/docker-stacks-support/</guid><description>&lt;p>The
&lt;a href="https://jupyter-docker-stacks.readthedocs.io/" target="_blank" rel="noopener" >Jupyter Docker Stacks&lt;/a> project provides a collection of ready-to-use Docker images for Jupyter environments. These images are used by many in the Jupyter community, including 2i2c which uses them as base images for our JupyterHub deployments.&lt;/p>
&lt;p>The project recently began publishing
&lt;a href="https://github.com/jupyter/docker-stacks/issues/1019" target="_blank" rel="noopener" >ARM-compatible images&lt;/a> alongside the standard x86 images, making it easier for users with ARM-based systems (like M1 Macs) to use these environments. However, building and hosting these ARM images comes with additional cloud computing costs that were being personally covered by
&lt;a href="https://github.com/mathbunnyru" target="_blank" rel="noopener" >@mathbunnyru&lt;/a>, one of the project&amp;rsquo;s maintainers.&lt;/p>
&lt;p>A part of 2i2c&amp;rsquo;s mission is supporting upstream communities that we rely on, especially where the upstream project has limited resources. For this reason, we&amp;rsquo;ve decided to support Jupyter Docker Stack&amp;rsquo;s ARM building costs, with a total budget of &lt;code>$2000&lt;/code> (approximately &lt;code>$150&lt;/code> per month). As a regular user and beneficiary of the Jupyter Docker Stacks, we believe it&amp;rsquo;s important to contribute to the maintenance and sustainability of this crucial piece of infrastructure that benefits the entire Jupyter community.&lt;/p>
&lt;p>We hope this support helps the Docker Stacks project remain healthy, and continue providing high-quality, multi-architecture images that work across different computing platforms. We&amp;rsquo;ll revisit this decision as the landscape of technology providers changes and other options arise.&lt;/p>
&lt;h2 id="acknowledgments">
Acknowledgments
&lt;a class="header-anchor" href="#acknowledgments">#&lt;/a>
&lt;/h2>&lt;ul>
&lt;li>Thanks to
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/jupyter/" >Project Jupyter&lt;/a> (particularly the &lt;code>jupyter-stacks&lt;/code> team) for this project.&lt;/li>
&lt;/ul></description></item><item><title>A QGIS desktop in the cloud with JupyterHub</title><link>https://deploy-preview-608--2i2c-org.netlify.app/blog/qgis-greenland/</link><pubDate>Sat, 05 Aug 2023 00:00:00 +0000</pubDate><guid>https://deploy-preview-608--2i2c-org.netlify.app/blog/qgis-greenland/</guid><description>&lt;p>
&lt;figure id="figure-the-qgreenland-researcher-workshophttpsqgreenland-workshop-2023-researchergithubio">
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="QGreenland Researcher Workshop" srcset="
/blog/qgis-greenland/featured_hu9562f6f382c010541578bd7b61c7cb4a_187505_a085d691b13f577db24aead3ae21385c.webp 400w,
/blog/qgis-greenland/featured_hu9562f6f382c010541578bd7b61c7cb4a_187505_9bd1833b93cf6052c08ff407d4528940.webp 760w,
/blog/qgis-greenland/featured_hu9562f6f382c010541578bd7b61c7cb4a_187505_1200x1200_fit_q75_h2_lanczos_3.webp 1200w"
src="https://deploy-preview-608--2i2c-org.netlify.app/blog/qgis-greenland/featured_hu9562f6f382c010541578bd7b61c7cb4a_187505_a085d691b13f577db24aead3ae21385c.webp"
width="760"
height="498"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;figcaption>
The
&lt;a href="https://qgreenland-workshop-2023-researcher.github.io/" target="_blank" rel="noopener" >QGreenland Researcher Workshop&lt;/a>
&lt;/figcaption>&lt;/figure>
&lt;/p>
&lt;p>JupyterHub is a versatile platform that can serve a desktop with Geospatial Information Systems (GIS) software in the cloud. This was demonstrated by the QGreenland Researcher Workshop that was hosted by the NASA
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/cryocloud/" >CryoCloud&lt;/a> hub. The hands-on workshop trained 25-30 researchers, from Germany, India, France, Canada, Poland and the United States, on how to work with geospatial data in an open science framework.&lt;/p>
&lt;h2 id="qgreenland-overview">
QGreenland Overview
&lt;a class="header-anchor" href="#qgreenland-overview">#&lt;/a>
&lt;/h2>&lt;p>
&lt;a href="https://qgreenland.org/" target="_blank" rel="noopener" >QGreenland&lt;/a> is an open-source geospatial data package designed for QGIS, a community-owned GIS platform. It focuses on Greenland, offering researchers and educators a comprehensive toolset for FAIR (findable, accessible, interoperable and reproducible) data analysis. The package integrates a variety of datasets into a single, easy-to-use data-viewing and analysis platform, supporting both offline and online use. This makes it particularly valuable for remote fieldwork and areas with limited internet access.&lt;/p>
&lt;h2 id="workshop-success">
Workshop Success
&lt;a class="header-anchor" href="#workshop-success">#&lt;/a>
&lt;/h2>&lt;p>The QGreenland workshop demonstrated several key benefits of using JupyterHub for cloud-based GIS:&lt;/p>
&lt;ul>
&lt;li>Accessibility: Participants from across the world could access the same powerful GIS tools through a web browser, eliminating the need for complex local installations while enhancing reproducibility&lt;/li>
&lt;li>Cloud block storage: Using a JupyterHub in the cloud allowed for faster data access than a traditional NFS file store by provisioning each user with an elastic block store disk, reducing load times from 5 minutes to under 3 seconds.&lt;/li>
&lt;li>Cost Efficiency: Utilizing the
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/cryocloud/" >CryoCloud&lt;/a> JupyterHub instance managed by 2i2c drastically cut down setup costs and time, with only minimal cloud operating expenses of roughly $1/person/day.&lt;/li>
&lt;/ul>
&lt;h2 id="conclusion">
Conclusion
&lt;a class="header-anchor" href="#conclusion">#&lt;/a>
&lt;/h2>&lt;p>The success of the QGreenland workshop underscores the potential of integrating interactive software applications in JupyterHub. This approach not only democratizes access to advanced geospatial tools but also fosters a collaborative research environment. We look forward to supporting more workshops for QGreenland in the future!&lt;/p>
&lt;p>&lt;em>Want to know more? Check out the companion post by QGreenland on the
&lt;a href="https://blog.jupyter.org/desktop-gis-software-in-the-cloud-with-jupyterhub-ddced297019a" target="_blank" rel="noopener" >Jupyter Blog&lt;/a>&lt;/em>&lt;/p>
&lt;h2 id="acknowledgements">
Acknowledgements
&lt;a class="header-anchor" href="#acknowledgements">#&lt;/a>
&lt;/h2>&lt;ul>
&lt;li>
&lt;a href="https://cires.colorado.edu/people/trey-stafford" target="_blank" rel="noopener" >Trey Stafford&lt;/a>
&lt;a href="https://cires.colorado.edu/" target="_blank" rel="noopener" >(CIRES)&lt;/a>&lt;/li>
&lt;li>
&lt;a href="https://cires.colorado.edu/people/matthew-fisher" target="_blank" rel="noopener" >Matthew Fisher&lt;/a>
&lt;a href="https://cires.colorado.edu/" target="_blank" rel="noopener" >(CIRES)&lt;/a>&lt;/li>
&lt;li>*Fisher, M., *T. Stafford, T. Moon, and A. Thurber (2023). QGreenland (v3) [software], National Snow and Ice Data Center.&lt;/li>
&lt;li>Snow, Tasha, Millstein, Joanna, Scheick, Jessica, Sauthoff, Wilson, Leong, Wei Ji, Colliander, James, Pérez, Fernando, James Munroe, Felikson, Denis, Sutterley, Tyler, &amp;amp; Siegfried, Matthew. (2023).
&lt;a href="https://book.cryointhecloud.com" target="_blank" rel="noopener" >CryoCloud JupyterBook&lt;/a> (2023.01.26). Zenodo.
&lt;a href="https://doi.org/10.5281/zenodo.7576602" target="_blank" rel="noopener" >10.5281/zenodo.7576602&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>* Denotes co-equal lead authorship&lt;/p></description></item><item><title>On the Jupyter Blog: From intern to mentor.</title><link>https://deploy-preview-608--2i2c-org.netlify.app/blog/external-jupyter-georgiana-mentor/</link><pubDate>Fri, 30 Jun 2023 00:00:00 +0000</pubDate><guid>https://deploy-preview-608--2i2c-org.netlify.app/blog/external-jupyter-georgiana-mentor/</guid><description>
&lt;h2 id="6------1-----------------------">
6&amp;mdash;&amp;mdash;1&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;&amp;mdash;&amp;ndash;
&lt;a class="header-anchor" href="#6------1-----------------------">#&lt;/a>
&lt;/h2></description></item><item><title>CILogon usage at 2i2c</title><link>https://deploy-preview-608--2i2c-org.netlify.app/blog/cilogon-integration/</link><pubDate>Fri, 24 Feb 2023 00:00:00 +0000</pubDate><guid>https://deploy-preview-608--2i2c-org.netlify.app/blog/cilogon-integration/</guid><description>
&lt;h2 id="about-cilogon">
About CILogon
&lt;a class="header-anchor" href="#about-cilogon">#&lt;/a>
&lt;/h2>&lt;p>
&lt;a href="https://www.cilogon.org" target="_blank" rel="noopener" >CILogon&lt;/a> is an open source service provider that allows users to log in against over 4000 various identity providers, including campus identity providers. The available identity providers are members of
&lt;a href="https://incommon.org/federation/" target="_blank" rel="noopener" >InCommon&lt;/a>, a federation of universities and other organizations that provide single sign-on access to various resources.&lt;/p>
&lt;h2 id="cilogon-and-2i2c">
CILogon and 2i2c
&lt;a class="header-anchor" href="#cilogon-and-2i2c">#&lt;/a>
&lt;/h2>&lt;p>For the past year, 2i2c has been successfully using CILogon for more than fifteen of the hubs it manages.&lt;/p>
&lt;p>Currently, most of the hubs that use it are hubs for communities in education that want to manage their hub access through their own institutional providers.&lt;/p>
&lt;p>With using a tool like CILogon, we allow hub access to be managed both through the communities&amp;rsquo; institutional providers, but also through social providers like GitHub and Google. Because both authentication mechanisms can coexist, there&amp;rsquo;s no need to provide specific credentials for 2i2c staff in order to have access to the hub. This reduces both the burden on institution&amp;rsquo;s IT departments, but also the complexity of a hub deployment.&lt;/p>
&lt;p>Moreover, as we migrate away from our current Auth0 setup, the number of hubs using CILogon will further increase in the following year.&lt;/p>
&lt;h2 id="the-setup">
The setup
&lt;a class="header-anchor" href="#the-setup">#&lt;/a>
&lt;/h2>&lt;p>The setup that 2i2c uses, is based on two important tools, the CILogon administrative client and the JupyterHub CILogonOAuthenticator.&lt;/p>
&lt;h3 id="the-cilogon-administrative-client">
The CILogon administrative client
&lt;a class="header-anchor" href="#the-cilogon-administrative-client">#&lt;/a>
&lt;/h3>&lt;p>The
&lt;a href="https://cilogon.github.io/oa4mp/server/manuals/dynamic-client-registration.html" target="_blank" rel="noopener" >2i2c administrative client&lt;/a> provided by CILogon allowed us to automatically manage the CILogon OAuth applications needed for authenticating into the hub.&lt;/p>
&lt;p>For each hub that uses CILogon, we dynamically create an OAuth
&lt;a href="https://cilogon.github.io/oa4mp/server/manuals/dynamic-client-registration.html" target="_blank" rel="noopener" >client application&lt;/a> in CILogon and store the credentials safely, using the script at
&lt;a href="https://github.com/2i2c-org/infrastructure/blob/3312f373f0aa59fbc98dc1c8161aa9623b68726b/deployer/cilogon_app.py" target="_blank" rel="noopener" >cilogon_app.py&lt;/a>. The script can also used for &lt;code>updating&lt;/code> the callback URLs of an existing OAuth application, &lt;code>deleting&lt;/code> a CILogon OAuth application when a hub is removed or changes authentication methods, &lt;code>getting&lt;/code> details about an existing OAuth application, &lt;code>getting all&lt;/code> existing 2i2c CILogon OAuth applications.&lt;/p>
&lt;h3 id="the-jupyterhub-cilogonoauthenticator">
The JupyterHub CILogonOAuthenticator
&lt;a class="header-anchor" href="#the-jupyterhub-cilogonoauthenticator">#&lt;/a>
&lt;/h3>&lt;p>For CILogon&amp;rsquo;s integration with JupyterHub&amp;rsquo;s authentication workflow, we&amp;rsquo;re using the
&lt;a href="https://github.com/jupyterhub/oauthenticator/blob/main/oauthenticator/cilogon.py" target="_blank" rel="noopener" >&lt;strong>CILogonOAuthenticator&lt;/strong>&lt;/a>, which is part of the
&lt;a href="https://oauthenticator.readthedocs.io/en/latest/" target="_blank" rel="noopener" >JupyterHub OAuthenticator project&lt;/a>. This is what allows JupyterHub to use common OAuth providers for authentication, and it&amp;rsquo;s also a base for writing other Authenticators with any OAuth 2.0 provider.&lt;/p>
&lt;p>As part of this 2i2c integration with the JupyterHub CILogonOAuthenticator some important upstream fixes and enhancements to the
&lt;a href="https://github.com/jupyterhub/oauthenticator" target="_blank" rel="noopener" >&lt;code>oauthenticator&lt;/code>&lt;/a> were identified and performed. For example, the
&lt;a href="https://github.com/jupyterhub/oauthenticator/security/advisories/GHSA-r7v4-jwx9-wx43" target="_blank" rel="noopener" >GHSA-r7v4-jwx9-wx43&lt;/a> vulnerability was reported and fixed, and a
&lt;a href="https://oauthenticator.readthedocs.io/en/latest/how-to/migrations/upgrade-to-15.html" target="_blank" rel="noopener" >migration guide&lt;/a> containing a description of the breaking changes that were made, together with a step by step guide for the users on how to update their usage of JupyterHub CILogonOAuthenticator was provided.&lt;/p>
&lt;p>Read more about how CILogon is setup for use at 2i2c from
&lt;a href="https://infrastructure.2i2c.org/hub-deployment-guide/configure-auth/cilogon.html" target="_blank" rel="noopener" >the docs&lt;/a>.&lt;/p>
&lt;h2 id="celebration">
Celebration
&lt;a class="header-anchor" href="#celebration">#&lt;/a>
&lt;/h2>&lt;p>Thanks to the 2i2c - CILogon partnership, during this past year we were able to integrate CILogon into 2i2c&amp;rsquo;s infrastructure and to observe its importance, usefulness and great support for 2i2c and the communities we server.&lt;/p>
&lt;p>We are now happy to announce that the 2i2c - CILogon partnership has been expanded to another year!&lt;/p>
&lt;p>&lt;strong>Acknowledgements&lt;/strong>: The upstream
&lt;a href="https://oauthenticator.readthedocs.io/en/latest" target="_blank" rel="noopener" >&lt;code>jupyterhub-oauthenticator&lt;/code>&lt;/a> project mentioned in this post as being used at 2i2c is a JupyterHub package, kindly developed and maintained by the
&lt;a href="https://discourse.jupyter.org/c/jupyterhub/" target="_blank" rel="noopener" >JupyterHub community&lt;/a> and the 2i2c integration described was developed by
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/organization/" >the 2i2c engineering team&lt;/a>. Also, this post was edited by
&lt;a href="https://jbasney.net/" target="_blank" rel="noopener" >Jim Basney&lt;/a>.&lt;/p></description></item><item><title>GESIS - 2i2c collaborate to build a persistent BinderHub experience</title><link>https://deploy-preview-608--2i2c-org.netlify.app/blog/gesis-2i2c-collaboration-update/</link><pubDate>Mon, 28 Nov 2022 00:00:00 +0000</pubDate><guid>https://deploy-preview-608--2i2c-org.netlify.app/blog/gesis-2i2c-collaboration-update/</guid><description>
&lt;h1 id="introduction">
Introduction
&lt;a class="header-anchor" href="#introduction">#&lt;/a>
&lt;/h1>&lt;p>
&lt;a href="https://mybinder.org" target="_blank" rel="noopener" >Mybinder.org&lt;/a> enables researchers across the world to replicate computational environments in the cloud. It allows researchers to turn static code into interactive literate coding environments with a click of a button within seconds. The
&lt;a href="https://mybinder.org" target="_blank" rel="noopener" >mybinder.org&lt;/a> service is powered by
&lt;a href="https://binderhub.readthedocs.io" target="_blank" rel="noopener" >BinderHub&lt;/a>, an open-source tool developed by
&lt;a href="https://jupyter.org" target="_blank" rel="noopener" >the Jupyter Project&lt;/a> that many organizations have deployed for their own communities. It does this by _dynamically building _the software environment needed to reproduce a computation (using a tool called
&lt;a href="https://repo2docker.readthedocs.io" target="_blank" rel="noopener" >repo2docker&lt;/a>), and making this environment available to users.&lt;/p>
&lt;p>BinderHub was developed for use-cases that are &lt;em>temporary&lt;/em> and &lt;em>fully open&lt;/em> by design. BinderHub sessions are destroyed after a fixed amount of time and there is no persistent storage or authentication. However, many research institutions also need more “standard” service features like authentication and persistent storage.&lt;/p>
&lt;p>Over the past several years, the
&lt;a href="http://notebooks.gesis.org" target="_blank" rel="noopener" >GESIS Notebooks&lt;/a> team made the first steps towards bridging this gap through their
&lt;a href="https://github.com/gesiscss/persistent_binderhub" target="_blank" rel="noopener" >Persistent BinderHub&lt;/a> implementation. This was a modified and authenticated BinderHub that &lt;em>included&lt;/em> persistent storage across sessions. The Persistent BinderHub service was very successful at GESIS and with its partner communities, and the team wishes to build this functionality into the JupyterHub community’s core technology so that these features can be enjoyed for more use-cases and by many communities.&lt;/p>
&lt;p>To enable this vision, we have partnered with GESIS in cooperation with
&lt;a href="https://www.nfdi4datascience.de/" target="_blank" rel="noopener" >NFDI4DS&lt;/a> (GAN: 460234259),
&lt;a href="https://www.cessda.eu/" target="_blank" rel="noopener" >CESSDA&lt;/a>, and members of the
&lt;a href="https://jupytearth.org/" target="_blank" rel="noopener" >JMTE&lt;/a> project. This collaboration has three primary goals:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Generalize the Persistent BinderHub functionality/experience to run on cloud-agnostic infrastructure&lt;/strong>, so that other stakeholders in NFDI, CESSDA, and the broader scientific community may benefit from this functionality and experience.&lt;/li>
&lt;li>&lt;strong>Upstream this functionality by making contributions into Jupyter community projects&lt;/strong>, so that it will be maintained and improved by a community moving forward, thus improving its reliability and sustainability.&lt;/li>
&lt;li>&lt;strong>Improve the implementation and user experience around Persistent BinderHub&lt;/strong>, in order to make it more reliable, scalable, productive, and enjoyable to use.&lt;/li>
&lt;/ul>
&lt;p>We began this collaboration several months ago, and have focused our efforts on exploring potential implementation pathways for this functionality. We believe that we now have a path forward for this functionality, and this blog post is a brief report of our efforts and future plans as we undertake this effort. See
&lt;a href="https://github.com/orgs/2i2c-org/projects/33" target="_blank" rel="noopener" >this GitHub Projects Board for issues that implement this effort&lt;/a>.&lt;/p>
&lt;h3 id="exploration-1-adding-persistent-storage-directly-into-binderhub">
Exploration 1: Adding persistent storage directly into BinderHub
&lt;a class="header-anchor" href="#exploration-1-adding-persistent-storage-directly-into-binderhub">#&lt;/a>
&lt;/h3>&lt;p>Our initial intention was to incorporate persistent storage and authentication from the GESIS Persistent BinderHub into the
&lt;a href="http://binderhub.readthedocs.io/" target="_blank" rel="noopener" >BinderHub codebase&lt;/a>. We began by holding a series of meetings to discuss technical requirements from our experience in the JupyterHub/BinderHub ecosystem, and also conducted an audit of the
&lt;a href="https://www.google.com/url?q=https://github.com/gesiscss/persistent_binderhub/blob/9936fc2251abafd00921b3b53954fb60c8640347/persistent_binderhub/values.yaml" target="_blank" rel="noopener" >Persistent BinderHub codebase&lt;/a>. The Persistent BinderHub implementation is a
&lt;a href="https://github.com/gesiscss/persistent_binderhub/blob/9936fc2251abafd00921b3b53954fb60c8640347/persistent_binderhub/values.yaml" target="_blank" rel="noopener" >modified Helm Chart&lt;/a> that configures a JupyterHub to expose its authentication and persistent storage functionality, overriding the BinderHub default behavior. We were concerned that building this functionality &lt;em>natively&lt;/em> into BinderHub would be challenging given that the BinderHub codebase was designed for ephemeral user sessions.&lt;/p>
&lt;p>So, we decided to take another approach:&lt;/p>
&lt;h3 id="exploration-2-add-dynamic-image-building-to-jupyterhub">
Exploration 2: Add dynamic image building to JupyterHub
&lt;a class="header-anchor" href="#exploration-2-add-dynamic-image-building-to-jupyterhub">#&lt;/a>
&lt;/h3>&lt;p>We realized that there is a way to make this functionality more broadly useful and more maintainable, while still achieving the end-user experience that the GESIS team needed. Instead of modifying BinderHub to incorporate JupyterHub’s storage and authentication features, &lt;strong>we would give JupyterHub the ability do dynamically generate user environments using
&lt;a href="http://repo2docker.readthedocs.io/" target="_blank" rel="noopener" >repo2docker&lt;/a>&lt;/strong>.&lt;/p>
&lt;p>This would give JupyterHub users more flexibility over the environments served by their hub, and expose Binder-style workflows to the “typical” JupyterHub workflow. BinderHub could then be simplified to re-use JupyterHub’s image building functionality as a part of its own service. We also identified a prototype of this functionality in the
&lt;a href="https://github.com/plasmabio/tljh-repo2docker" target="_blank" rel="noopener" >tljh-repo2docker&lt;/a> project that
&lt;a href="https://quantstack.net/" target="_blank" rel="noopener" >QuantStack&lt;/a> had built for the
&lt;a href="https://plasmabio.org/" target="_blank" rel="noopener" >PlasmaBio project&lt;/a>. This implementation was seen as successful, and something others in the community had wanted to generalize for some time.&lt;/p>
&lt;h1 id="our-implementation-plan">
Our implementation plan
&lt;a class="header-anchor" href="#our-implementation-plan">#&lt;/a>
&lt;/h1>
&lt;h2 id="two-phases-of-implementation">
Two phases of implementation
&lt;a class="header-anchor" href="#two-phases-of-implementation">#&lt;/a>
&lt;/h2>&lt;p>With this alternative implementation route in place, we identified two major steps to accomplish this project:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Build a back-end for dynamic environment building&lt;/strong>. JupyterHub needs to understand how to call repo2docker’s image generation from a Docker-based environment. It needs to expose this ability via APIs that others can build interfaces on top of.&lt;/li>
&lt;li>**Build a front-end that is user-friendly and accessible. **Once the back-end is functional, we must build a front-end experience that feels familiar to BinderHub users and is easy and intuitive to use.&lt;/li>
&lt;/ol>
&lt;p>Here are a few tasks that we’re carrying out next to make progress on the above two items.&lt;/p>
&lt;ul>
&lt;li>Build a working prototype for image generation via a &lt;em>JupyterHub Service&lt;/em> (see below for current status)&lt;/li>
&lt;li>Research the &lt;code>tljh-repo2docker&lt;/code> code base to understand how we could build upon its UX and functionality.&lt;/li>
&lt;li>Understand the typical process that GESIS and NFDI users follow in their BinderHub workflows, to ensure that it can be replicated via this new implementation.&lt;/li>
&lt;li>Perform UI/UX research validation to inform the implementation from a user’s perspective.&lt;/li>
&lt;/ul>
&lt;p>As a follow-up, we’ll likely re-work the BinderHub codebase to utilize JupyterHub’s new repo2docker service, rather than defining its own custom repo2docker functionality.&lt;/p>
&lt;h2 id="back-end-implementation-as-a-jupyterhub-service">
Back-end implementation as a JupyterHub Service
&lt;a class="header-anchor" href="#back-end-implementation-as-a-jupyterhub-service">#&lt;/a>
&lt;/h2>&lt;p>We’re planning to use
&lt;a href="https://jupyterhub.readthedocs.io/en/stable/reference/services.html" target="_blank" rel="noopener" >JupyterHub Services&lt;/a> to add the back-end functionality for dynamic image building to a JupyterHub. Services are a way to expose functionality via a JupyterHub REST API, and would allow us to expose basic image generation on-the-fly with
&lt;a href="https://repo2docker.readthedocs.io/" target="_blank" rel="noopener" >repo2docker&lt;/a>. We aim for basic functionality to be as close as possible to repo2docker’s default behavior, but to make this functionality _composable and customizable _if a JupyterHub administrator wants to provide different out-of-the-box functionality.&lt;/p>
&lt;p>While details may still change, we believe that the major architectural plan has now been settled. We have
&lt;a href="https://github.com/consideratio/repo2docker-service" target="_blank" rel="noopener" >an experimental codebase&lt;/a> with a basic implementation of the repo2docker service described above. As part of this effort, this team has also made a number of improvements to repo2docker’s codebase and project infrastructure. We hope that this effort will continue to push resources and attention to repo2docker by growing the number of users and stakeholders that rely on the project for their success.&lt;/p>
&lt;h2 id="front-end-implementation-that-uses-this-service">
Front-end implementation that uses this service
&lt;a class="header-anchor" href="#front-end-implementation-that-uses-this-service">#&lt;/a>
&lt;/h2>&lt;p>Once the back-end setup exists, we can use it to begin prototyping user interactions that can trigger and use repo2docker’s image generation. Bringing dynamic environment image building into JupyterHub is a significant improvement in its functionality, and may introduce new kinds of workflows that we hadn’t initially imagined. Understanding, interpreting, and extending the original “Persistent BinderHub” workflow will require a more thorough understanding of user stories and needs in order to identify new workflows that feel natural not only in a JupyterHub scenario but also in a Binder-like scenario.&lt;/p>
&lt;p>For example, here are a few major UI/UX questions we must answer:&lt;/p>
&lt;ul>
&lt;li>When a user builds an image, should it also become available to &lt;em>other users&lt;/em> as well?&lt;/li>
&lt;li>How can a user store, find, and delete old images that they’ve built?&lt;/li>
&lt;li>What about new versions of the same image?&lt;/li>
&lt;li>Should we simply mimic the mybinder.org UX, or should this be improved as well?&lt;/li>
&lt;/ul>
&lt;p>We must answer these and several other questions next. With that vision in place, we’d like to &lt;strong>expand our efforts in UI/UX and user research&lt;/strong>. This will help inform the technical implementation of this work as we expand on our prototype, and help us choose the right way to expose this functionality to users. We welcome collaboration around this work - if you know of an organization that is interested in collaboration, please reach out.&lt;/p>
&lt;h1 id="collaborate-and-follow-along">
Collaborate and follow along
&lt;a class="header-anchor" href="#collaborate-and-follow-along">#&lt;/a>
&lt;/h1>&lt;p>Below you’ll find a rough project plan to give an idea for the major actions needed and a timeline for when we hope they’ll be completed. We’ll track further updates and progress on this project in this
&lt;a href="https://github.com/2i2c-org/infrastructure/issues/1382" target="_blank" rel="noopener" >dedicated GitHub issue&lt;/a> and this
&lt;a href="https://github.com/orgs/2i2c-org/projects/33/views/1" target="_blank" rel="noopener" >dedicated GitHub project board&lt;/a>.&lt;/p>
&lt;p>
&lt;figure >
&lt;div class="d-flex justify-content-center">
&lt;div class="w-100" >&lt;img alt="Timeline" srcset="
/blog/gesis-2i2c-collaboration-update/timeline_hudeeefb93f7f3a1e165384e58a83520c2_38800_21a687e7152e2210ac0364dd9bbebe77.webp 400w,
/blog/gesis-2i2c-collaboration-update/timeline_hudeeefb93f7f3a1e165384e58a83520c2_38800_79cccb54bbb7759b752440b6de06e285.webp 760w,
/blog/gesis-2i2c-collaboration-update/timeline_hudeeefb93f7f3a1e165384e58a83520c2_38800_1200x1200_fit_q75_h2_lanczos_3.webp 1200w"
src="https://deploy-preview-608--2i2c-org.netlify.app/blog/gesis-2i2c-collaboration-update/timeline_hudeeefb93f7f3a1e165384e58a83520c2_38800_21a687e7152e2210ac0364dd9bbebe77.webp"
width="760"
height="555"
loading="lazy" data-zoomable />&lt;/div>
&lt;/div>&lt;/figure>
&lt;/p>
&lt;p>After a few months working on this project, we are even more excited about the potential for dynamically building environments in a JupyterHub. We believe that it adds a new class of workflows to JupyterHubs that were not possible before, and will be immediately useful to the hundreds of communities that deploy JupyterHub for their communities.&lt;/p></description></item><item><title>The why, what, and how of our NASA Openscapes cloud infrastructure: 2i2c JupyterHub and corn environment</title><link>https://deploy-preview-608--2i2c-org.netlify.app/blog/external-openscapes-corn/</link><pubDate>Thu, 17 Nov 2022 00:00:00 +0000</pubDate><guid>https://deploy-preview-608--2i2c-org.netlify.app/blog/external-openscapes-corn/</guid><description>&lt;p>We recently shared a demo of our infrastructure stack with the
&lt;a href="https://deploy-preview-608--2i2c-org.netlify.app/collaborators/openscapes/" >OpenScapes community&lt;/a>. Check out
&lt;a href="https://openscapes.org/blog/2022-11-17-nasa-earthdata-cloud-infrastructure/" target="_blank" rel="noopener" >the blog post about it here&lt;/a>.&lt;/p></description></item><item><title>Enabling / creating / X outcome by doing Y thing</title><link>https://deploy-preview-608--2i2c-org.netlify.app/blog/impact-post/</link><pubDate>Wed, 01 Jan 1000 00:00:00 +0000</pubDate><guid>https://deploy-preview-608--2i2c-org.netlify.app/blog/impact-post/</guid><description>&lt;p>One or two sentences about what happened and who did it. Link to the appropriate people, orgs, etc!&lt;/p>
&lt;p>One or two sentences describing why this is important, why it&amp;rsquo;s valuable, or what it means.&lt;/p>
&lt;p>&lt;em>Embed any images, videos, or youtube videos that are relevant. Put images in a file in the same folder called &lt;code>featured.png&lt;/code> so it shows up as a feature preview.&lt;/em>&lt;/p>
&lt;h2 id="learn-more">
Learn more
&lt;a class="header-anchor" href="#learn-more">#&lt;/a>
&lt;/h2>&lt;ul>
&lt;li>Bulleted list of URLs where readers can learn more or follow along.&lt;/li>
&lt;/ul>
&lt;h2 id="acknowledgements">
Acknowledgements
&lt;a class="header-anchor" href="#acknowledgements">#&lt;/a>
&lt;/h2>&lt;ul>
&lt;li>Bulleted list of people and organizations to thank, with links to their spaces.&lt;/li>
&lt;/ul>
&lt;h2 id="extra-examples">
EXTRA EXAMPLES
&lt;a class="header-anchor" href="#extra-examples">#&lt;/a>
&lt;/h2>&lt;ul>
&lt;li>Service post: blog/2025/status-page/index.md&lt;/li>
&lt;li>Impact post: blog/2025/hackweek-shoutout/index.md&lt;/li>
&lt;/ul></description></item><item><title>TIL: How to do XYZ thing for Y outcome</title><link>https://deploy-preview-608--2i2c-org.netlify.app/blog/learning-post/</link><pubDate>Wed, 01 Jan 1000 00:00:00 +0000</pubDate><guid>https://deploy-preview-608--2i2c-org.netlify.app/blog/learning-post/</guid><description>&lt;p>One or two sentences setting context about a common problem.&lt;/p>
&lt;p>One to many sections describing something we&amp;rsquo;ve tried and what we&amp;rsquo;ve learned in solving that problem.&lt;/p>
&lt;p>&lt;em>Embed any images, videos, or youtube videos that are relevant. Put images in a file in the same folder called &lt;code>featured.png&lt;/code> so it shows up as a feature preview.&lt;/em>&lt;/p>
&lt;h2 id="learn-more">
Learn more
&lt;a class="header-anchor" href="#learn-more">#&lt;/a>
&lt;/h2>&lt;ul>
&lt;li>Bulleted list of URLs where readers can learn more or follow along.&lt;/li>
&lt;/ul>
&lt;h2 id="acknowledgements">
Acknowledgements
&lt;a class="header-anchor" href="#acknowledgements">#&lt;/a>
&lt;/h2>&lt;ul>
&lt;li>Bulleted list of people and organizations to thank, with links to their spaces.&lt;/li>
&lt;/ul>
&lt;h2 id="extra-examples">
EXTRA EXAMPLES
&lt;a class="header-anchor" href="#extra-examples">#&lt;/a>
&lt;/h2>&lt;p>Here&amp;rsquo;s a blog post with an example of what we&amp;rsquo;re looking for: contentblog/2025/github-action-secrets-forked-repositories/index.mdindex.md&lt;/p></description></item></channel></rss>