From 8147e1bb98b4bc9a16d94fec8e777e882bb9d7d8 Mon Sep 17 00:00:00 2001 From: alhendrickson <159636032+alhendrickson@users.noreply.github.com.> Date: Fri, 27 Feb 2026 16:29:36 +0000 Subject: [PATCH 1/3] feat(helm): Run jupyterhub in the CE helm chart --- .../charts/cogstack-helm-ce/Chart.lock | 7 +- .../charts/cogstack-helm-ce/Chart.yaml | 4 + .../charts/jupyterhub/Chart.lock | 6 ++ .../charts/jupyterhub/Chart.yaml | 11 +++ .../charts/jupyterhub/values.yaml | 95 +++++++++++++++++++ .../cogstack-helm-ce/templates/NOTES.txt | 12 ++- .../charts/cogstack-helm-ce/values.yaml | 22 +++++ 7 files changed, 153 insertions(+), 4 deletions(-) create mode 100644 deployment/kubernetes/charts/cogstack-helm-ce/charts/jupyterhub/Chart.lock create mode 100644 deployment/kubernetes/charts/cogstack-helm-ce/charts/jupyterhub/Chart.yaml create mode 100644 deployment/kubernetes/charts/cogstack-helm-ce/charts/jupyterhub/values.yaml diff --git a/deployment/kubernetes/charts/cogstack-helm-ce/Chart.lock b/deployment/kubernetes/charts/cogstack-helm-ce/Chart.lock index 3fe0e11..3ce5072 100644 --- a/deployment/kubernetes/charts/cogstack-helm-ce/Chart.lock +++ b/deployment/kubernetes/charts/cogstack-helm-ce/Chart.lock @@ -14,5 +14,8 @@ dependencies: - name: opensearch-dashboards repository: https://opensearch-project.github.io/helm-charts/ version: 3.5.0 -digest: sha256:5c0bf142e8060c45f3045a9a925a3801813f23b7f0a37d100ffe2a3ab3d387e7 -generated: "2026-02-27T14:25:01.321704435Z" +- name: jupyterhub + repository: file://charts/jupyterhub + version: 0.1.0 +digest: sha256:0dbf6980653337af2efa16bb340d0a04dca9ed517bf4ab3c87044da348e8a84c +generated: "2026-02-27T16:13:56.822297965Z" diff --git a/deployment/kubernetes/charts/cogstack-helm-ce/Chart.yaml b/deployment/kubernetes/charts/cogstack-helm-ce/Chart.yaml index 3d6d513..03167f7 100644 --- a/deployment/kubernetes/charts/cogstack-helm-ce/Chart.yaml +++ b/deployment/kubernetes/charts/cogstack-helm-ce/Chart.yaml @@ -50,3 +50,7 @@ dependencies: condition: opensearch-dashboards.enabled version: "3.5.0" repository: "https://opensearch-project.github.io/helm-charts/" + - name: cogstack-jupyterhub + condition: cogstack-jupyterhub.enabled + version: "0.1.0" + repository: "file://charts/cogstack-jupyterhub" diff --git a/deployment/kubernetes/charts/cogstack-helm-ce/charts/jupyterhub/Chart.lock b/deployment/kubernetes/charts/cogstack-helm-ce/charts/jupyterhub/Chart.lock new file mode 100644 index 0000000..403e589 --- /dev/null +++ b/deployment/kubernetes/charts/cogstack-helm-ce/charts/jupyterhub/Chart.lock @@ -0,0 +1,6 @@ +dependencies: +- name: jupyterhub + repository: https://hub.jupyter.org/helm-chart/ + version: 4.3.2 +digest: sha256:a95c93fe87aa2b61ac544065409bf8ef8b11a5603f0bf08b7280550a36982f2a +generated: "2026-02-27T15:41:44.85321781Z" diff --git a/deployment/kubernetes/charts/cogstack-helm-ce/charts/jupyterhub/Chart.yaml b/deployment/kubernetes/charts/cogstack-helm-ce/charts/jupyterhub/Chart.yaml new file mode 100644 index 0000000..66562d3 --- /dev/null +++ b/deployment/kubernetes/charts/cogstack-helm-ce/charts/jupyterhub/Chart.yaml @@ -0,0 +1,11 @@ +apiVersion: v2 +name: cogstack-jupyterhub +description: A Helm chart for CogStack Jupyter Hub using official JupyterHub chart +type: application +version: 0.1.0 +appVersion: "latest" + +dependencies: + - name: jupyterhub + version: 4.3.2 + repository: https://hub.jupyter.org/helm-chart/ diff --git a/deployment/kubernetes/charts/cogstack-helm-ce/charts/jupyterhub/values.yaml b/deployment/kubernetes/charts/cogstack-helm-ce/charts/jupyterhub/values.yaml new file mode 100644 index 0000000..c0740e5 --- /dev/null +++ b/deployment/kubernetes/charts/cogstack-helm-ce/charts/jupyterhub/values.yaml @@ -0,0 +1,95 @@ +# Default values for the community jupyterhub helm chart +jupyterhub: + hub: + image: + name: cogstacksystems/jupyter-hub + tag: "2.2.2" + pullPolicy: IfNotPresent + extraConfig: + 00-log-level: | + c.Application.log_level = 'DEBUG' + config: + JupyterHub: + authenticator_class: dummy + Authenticator: + admin_users: + - admin + DummyAuthenticator: + password: "SuperSecret" + + KubeSpawner: + uid: 0 + fs_gid: 0 + start_timeout: 300 + http_timeout: 120 + notebook_dir: /home/jovyan/work + + Spawner: + default_url: /lab/ + notebook_dir: /home/jovyan/work + + # Extra hub configuration for custom spawner settings + extraConfig: + 00-custom-spawner: | + # Custom environment variables for user pods + c.KubeSpawner.environment = { + 'GRANT_SUDO': '1', + 'CHOWN_HOME': 'yes', + 'CHOWN_HOME_OPTS': '-R', + } + # Allow root in notebooks + c.KubeSpawner.args = ['--allow-root'] + proxy: + service: + type: ClusterIP + + singleuser: + image: + name: cogstacksystems/jupyter-singleuser + tag: "2.2.2" + pullPolicy: IfNotPresent + # Lifecycle hook to copy notebooks from image to PVC on first run + lifecycleHooks: + postStart: + exec: + command: + - "sh" + - "-c" + - > + if [ ! -f /home/jovyan/work/.notebooks_initialized ]; then + echo "First run - copying notebooks and medcat-scripts..."; + cp -r /srv/jupyterhub/notebooks/* /home/jovyan/work/; + cp -r /srv/jupyterhub/medcat-scripts /home/jovyan/work/; + touch /home/jovyan/work/.notebooks_initialized; + echo "Notebooks initialized successfully"; + else + echo "Notebooks already initialized - skipping"; + fi + networkPolicy: + enabled: false + + # User pod configuration + uid: 0 + fsGid: 0 + cmd: ["jupyterhub-singleuser"] + + # Extra arguments passed to jupyterhub-singleuser + extraPodConfig: + securityContext: + runAsUser: 0 + runAsGroup: 0 + + storage: + capacity: 5Gi + + + cull: + enabled: false + scheduling: + userScheduler: + replicas: 1 + prePuller: + hook: + enabled: false + continuous: + enabled: false \ No newline at end of file diff --git a/deployment/kubernetes/charts/cogstack-helm-ce/templates/NOTES.txt b/deployment/kubernetes/charts/cogstack-helm-ce/templates/NOTES.txt index 28a9062..a872767 100644 --- a/deployment/kubernetes/charts/cogstack-helm-ce/templates/NOTES.txt +++ b/deployment/kubernetes/charts/cogstack-helm-ce/templates/NOTES.txt @@ -29,8 +29,16 @@ export OPENSEARCH_DASHBOARD_PORT={{ index .Values "opensearch-dashboards" "servi kubectl --namespace {{ .Release.Namespace }} port-forward svc/$OPENSEARCH_DASHBOARD_SERVICE 5601:$OPENSEARCH_DASHBOARD_PORT & {{- end }} + +{{- if index .Values "cogstack-jupyterhub" "enabled" }} +export JUPYTERHUB_PROXY_PUBLIC_SERVICE={{ template "jupyterhub.proxy-public.fullname" (index .Subcharts "cogstack-jupyterhub") }} +export JUPYTERHUB_PROXY_SERVICE_PORT=$(kubectl get svc $JUPYTERHUB_PROXY_PUBLIC_SERVICE -o jsonpath="{.spec.ports[0].port}" ) +kubectl --namespace {{ .Release.Namespace }} port-forward svc/$JUPYTERHUB_PROXY_PUBLIC_SERVICE 8000:$JUPYTERHUB_PROXY_SERVICE_PORT & +{{- end }} + echo "Visit http://127.0.0.1:5000 to use MedCAT Service" echo "Visit http://127.0.0.1:5001 to use AnonCAT" echo "Visit http://127.0.0.1:8000 to use MedCAT Trainer" -{{ if .Values.opensearch.enabled }}echo "Call https://127.0.0.1:9200 to use OpenSearch"{{- end }} -{{ if index .Values "opensearch-dashboards" "enabled" }}echo "Visit http://127.0.0.1:5601 to use OpenSearch Dashboards"{{- end }} \ No newline at end of file +{{ if .Values.opensearch.enabled }}echhttps://127.0.0.1:9200 to use OpenSearch"{{- end }} +{{ if index .Values "opensearch-dashboards" "enabled" }}echo "Visit http://127.0.0.1:5601 to use OpenSearch Dashboards"{{- end }} +{{ if index .Values "cogstack-jupyterhub" "enabled" }}echo "Visit http://127.0.0.1:8000 to use jupyterhub"{{- end }} diff --git a/deployment/kubernetes/charts/cogstack-helm-ce/values.yaml b/deployment/kubernetes/charts/cogstack-helm-ce/values.yaml index 200ca98..8c861f2 100644 --- a/deployment/kubernetes/charts/cogstack-helm-ce/values.yaml +++ b/deployment/kubernetes/charts/cogstack-helm-ce/values.yaml @@ -32,3 +32,25 @@ opensearch: opensearch-dashboards: enabled: true + +cogstack-jupyterhub: + enabled: true + jupyterhub: + hub: + image: + name: cogstacksystems/jupyter-hub + tag: "2.2.2" + config: + JupyterHub: + authenticator_class: dummy + # - Authenticator set to hardcoded user/password + Authenticator: + admin_users: + - admin + DummyAuthenticator: + password: "SuperSecret" + singleuser: + image: + name: cogstacksystems/jupyter-singleuser + tag: "2.2.2" + pullPolicy: IfNotPresent From 25a9757dc0b06dba9f9fa41bfe1573fc346f69b1 Mon Sep 17 00:00:00 2001 From: alhendrickson <159636032+alhendrickson@users.noreply.github.com.> Date: Fri, 27 Feb 2026 16:31:43 +0000 Subject: [PATCH 2/3] feat(helm): Run jupyterhub in the CE helm chart --- deployment/kubernetes/charts/cogstack-helm-ce/Chart.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deployment/kubernetes/charts/cogstack-helm-ce/Chart.yaml b/deployment/kubernetes/charts/cogstack-helm-ce/Chart.yaml index 03167f7..0f67497 100644 --- a/deployment/kubernetes/charts/cogstack-helm-ce/Chart.yaml +++ b/deployment/kubernetes/charts/cogstack-helm-ce/Chart.yaml @@ -53,4 +53,4 @@ dependencies: - name: cogstack-jupyterhub condition: cogstack-jupyterhub.enabled version: "0.1.0" - repository: "file://charts/cogstack-jupyterhub" + repository: "file://charts/jupyterhub" From 7343e8da5a481e60aea42025b92a2e3447b6cd6d Mon Sep 17 00:00:00 2001 From: alhendrickson <159636032+alhendrickson@users.noreply.github.com.> Date: Fri, 27 Feb 2026 16:36:02 +0000 Subject: [PATCH 3/3] feat(helm): Run jupyterhub in the CE helm chart - notes --- .../kubernetes/charts/cogstack-helm-ce/templates/NOTES.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/deployment/kubernetes/charts/cogstack-helm-ce/templates/NOTES.txt b/deployment/kubernetes/charts/cogstack-helm-ce/templates/NOTES.txt index a872767..88b65d8 100644 --- a/deployment/kubernetes/charts/cogstack-helm-ce/templates/NOTES.txt +++ b/deployment/kubernetes/charts/cogstack-helm-ce/templates/NOTES.txt @@ -29,9 +29,9 @@ export OPENSEARCH_DASHBOARD_PORT={{ index .Values "opensearch-dashboards" "servi kubectl --namespace {{ .Release.Namespace }} port-forward svc/$OPENSEARCH_DASHBOARD_SERVICE 5601:$OPENSEARCH_DASHBOARD_PORT & {{- end }} - +# 5. Jupyterhub {{- if index .Values "cogstack-jupyterhub" "enabled" }} -export JUPYTERHUB_PROXY_PUBLIC_SERVICE={{ template "jupyterhub.proxy-public.fullname" (index .Subcharts "cogstack-jupyterhub") }} +export JUPYTERHUB_PROXY_PUBLIC_SERVICE=proxy-public export JUPYTERHUB_PROXY_SERVICE_PORT=$(kubectl get svc $JUPYTERHUB_PROXY_PUBLIC_SERVICE -o jsonpath="{.spec.ports[0].port}" ) kubectl --namespace {{ .Release.Namespace }} port-forward svc/$JUPYTERHUB_PROXY_PUBLIC_SERVICE 8000:$JUPYTERHUB_PROXY_SERVICE_PORT & {{- end }} @@ -39,6 +39,6 @@ kubectl --namespace {{ .Release.Namespace }} port-forward svc/$JUPYTERHUB_PROXY_ echo "Visit http://127.0.0.1:5000 to use MedCAT Service" echo "Visit http://127.0.0.1:5001 to use AnonCAT" echo "Visit http://127.0.0.1:8000 to use MedCAT Trainer" -{{ if .Values.opensearch.enabled }}echhttps://127.0.0.1:9200 to use OpenSearch"{{- end }} +{{ if .Values.opensearch.enabled }}echo "Visit https://127.0.0.1:9200 to use OpenSearch"{{- end }} {{ if index .Values "opensearch-dashboards" "enabled" }}echo "Visit http://127.0.0.1:5601 to use OpenSearch Dashboards"{{- end }} {{ if index .Values "cogstack-jupyterhub" "enabled" }}echo "Visit http://127.0.0.1:8000 to use jupyterhub"{{- end }}