├── deployer ├── __init__.py ├── dev_commands │ └── generate │ │ ├── __init__.py │ │ ├── hub_asset │ │ ├── hub_asset_app.py │ │ └── cluster_entry.py │ │ ├── dedicated_cluster │ │ └── dedicated_cluster_app.py │ │ └── resource_allocation │ │ └── resource_allocation_app.py ├── health_check_tests │ ├── __init__.py │ └── conftest.py ├── commands │ └── __init__.py ├── __main__.py └── utils │ ├── env_vars_management.py │ └── helm.py ├── docs ├── _static │ └── custom.css ├── images │ ├── config-flow.png │ ├── 403-forbidden.png │ ├── aws-billing-ui.jpg │ ├── gcp-billing-ui.png │ ├── gcp-run-in-shell.png │ ├── gcp-k8s-dashboard.png │ ├── cilogon-clear-cookies.png │ ├── helm-charts-hierarchy.png │ ├── status-page-pagerduty.png │ ├── changed-files-from-logs.png │ ├── manually-delete-outage.png │ ├── staging-hub-login-page.png │ ├── azure-scale-node-pool-window.png │ ├── grafana-grant-access_step-3a.jpg │ ├── grafana-grant-access_step-3b.jpg │ ├── grafana-grant-access_step-4a.jpg │ ├── grafana-grant-access_step-4b.jpg │ ├── grafana-grant-access_step-5.jpg │ ├── grafana-grant-access_step-6.jpg │ ├── grafana-grant-access_step-7.jpg │ ├── infrastructure-storage-layer.png │ ├── cilogon-remember-this-selection.png │ └── granting-org-access-to-oauth-app.jpg ├── hub-deployment-guide │ ├── hubs │ │ ├── move-hubs │ │ │ └── index.md │ │ └── index.md │ ├── deploy-support │ │ └── index.md │ ├── runbooks │ │ ├── index.md │ │ └── phase3 │ │ │ └── index.md │ └── configure-auth │ │ └── index.md ├── howto │ ├── image-management │ │ └── index.md │ ├── manage-domains │ │ └── index.md │ ├── troubleshoot │ │ ├── index.md │ │ ├── logs │ │ │ └── index.md │ │ └── prometheus.md │ ├── budgeting-billing │ │ ├── index.md │ │ └── cost-monitoring │ │ │ └── index.md │ ├── filesystem-management │ │ ├── index.md │ │ └── filesystem-backups │ │ │ └── index.md │ ├── features │ │ ├── index.md │ │ └── image.md │ └── prepare-for-events │ │ └── index.md ├── reference │ └── cli.md ├── requirements.txt ├── topic │ ├── billing │ │ └── index.md │ ├── access-creds │ │ └── index.md │ ├── monitoring-alerting │ │ ├── index.md │ │ └── prometheus.md │ └── infrastructure │ │ ├── index.md │ │ └── network.md ├── sre-guide │ ├── support │ │ └── index.md │ └── manage-k8s │ │ └── index.md └── Makefile ├── terraform ├── .gitignore ├── uptime-checks │ ├── variables.tf │ ├── pagerduty.tf │ └── main.tf ├── aws │ ├── projects │ │ ├── strudel.tfvars │ │ ├── oceanhackweek.tfvars │ │ ├── ubc-eoas.tfvars │ │ ├── berkeley-geojupyter.tfvars │ │ ├── victor.tfvars │ │ ├── jupyter-health.tfvars │ │ └── smithsonian.tfvars │ └── ebs-volumes.tf ├── openstack │ ├── main.tf │ ├── projects │ │ ├── projectpythia-binder.tfvars │ │ └── 2i2c-jetstream2.tfvars │ └── persistent-disks.tf ├── internaltools │ ├── prometheus.yaml │ └── main.tf ├── gcp │ ├── filestore.tf │ └── projects │ │ └── dubois.tfvars └── azure │ ├── budget-alerts.tf │ └── secret │ └── enc-pagerduty-service-integration-keys.secret.yaml ├── helm-charts ├── daskhub │ ├── values.jsonnet │ ├── Chart.yaml │ └── .helmignore ├── images │ └── hub │ │ ├── requirements.txt │ │ └── pkce-requirements.txt ├── support │ ├── README.md │ ├── templates │ │ ├── prometheus-ingres-auth │ │ │ └── secret.yaml │ │ ├── issuer.yaml │ │ ├── calico.yaml │ │ ├── storageclass │ │ │ └── gke.yaml │ │ └── redirects.yaml │ └── .helmignore ├── basehub │ ├── templates │ │ ├── serviceaccount-user.yaml │ │ ├── dex │ │ │ ├── pvc.yaml │ │ │ ├── _helpers.tpl │ │ │ ├── service.yaml │ │ │ └── secret.yaml │ │ ├── ingress-auth │ │ │ └── secret.yaml │ │ ├── incluster-nfs.yaml │ │ ├── configmap-hub-templates.yaml │ │ ├── configurator.yaml │ │ ├── static │ │ │ ├── service.yaml │ │ │ ├── secret.yaml │ │ │ ├── configmap.yaml │ │ │ └── ingress.yaml │ │ ├── configmap-cluster-info.yaml │ │ └── nfs.yaml │ └── .helmignore └── chartpress.yaml ├── eksctl ├── ssh-keys │ ├── temple.key.pub │ ├── berkeley-geojupyter.key.pub │ ├── reflective.key.pub │ ├── gridsst.key.pub │ └── victor.key.pub ├── jupyter-health.jsonnet ├── oceanhackweek.jsonnet ├── ubc-eoas.jsonnet ├── strudel.jsonnet ├── berkeley-geojupyter.jsonnet ├── nasa-ghg.jsonnet ├── reflective.jsonnet ├── projectpythia.jsonnet ├── bnext-bio.jsonnet ├── maap.jsonnet ├── disasters.jsonnet ├── nasa-cryo.jsonnet ├── smithsonian.jsonnet ├── aimatx-2i2c-hub.jsonnet ├── nasa-veda.jsonnet ├── temple.jsonnet ├── victor.jsonnet ├── opensci.jsonnet ├── template.jsonnet ├── 2i2c-aws-us.jsonnet ├── openscapeshub.jsonnet ├── nmfs-openscapes.jsonnet ├── catalystproject-africa.jsonnet └── earthscope.jsonnet ├── config └── clusters │ ├── templates │ ├── common │ │ ├── support.secret.values.yaml │ │ ├── cluster-entry.yaml │ │ └── hub.values.yaml │ └── aws │ │ └── cluster.yaml │ ├── 2i2c │ ├── basehub-common.values.yaml │ ├── daskhub-common.values.yaml │ └── enc-grafana-token.secret.yaml │ ├── strudel │ ├── staging.values.yaml │ ├── prod.values.yaml │ ├── support.values.yaml │ ├── enc-grafana-token.secret.yaml │ ├── enc-prod.secret.values.yaml │ └── enc-staging.secret.values.yaml │ ├── utoronto │ ├── r-prod.values.yaml │ ├── default-common.values.yaml │ ├── highmem.values.yaml │ ├── r-staging.values.yaml │ ├── default-staging.values.yaml │ ├── r-common.values.yaml │ └── enc-grafana-token.secret.yaml │ ├── temple │ ├── common-teaching.values.yaml │ ├── prod.values.yaml │ ├── enc-grafana-token.secret.yaml │ ├── staging.values.yaml │ ├── advanced.values.yaml │ └── support.values.yaml │ ├── opensci │ ├── common.values.yaml │ ├── support.values.yaml │ └── enc-grafana-token.secret.yaml │ ├── ubc-eoas │ ├── prod.values.yaml │ ├── staging.values.yaml │ ├── support.values.yaml │ ├── cluster.yaml │ └── enc-grafana-token.secret.yaml │ ├── 2i2c-jetstream2 │ ├── cluster.yaml │ ├── support.values.yaml │ └── enc-grafana-token.secret.yaml │ ├── 2i2c-aws-us │ ├── basehub-common.values.yaml │ ├── daskhub-common.values.yaml │ ├── cluster.yaml │ ├── support.values.yaml │ └── enc-grafana-token.secret.yaml │ ├── projectpythia-binder │ ├── cluster.yaml │ ├── support.values.yaml │ └── enc-grafana-token.secret.yaml │ ├── 2i2c-uk │ ├── support.values.yaml │ ├── cluster.yaml │ └── enc-grafana-token.secret.yaml │ ├── hhmi │ ├── support.values.yaml │ └── enc-grafana-token.secret.yaml │ ├── dubois │ ├── support.values.yaml │ ├── ephemeral.values.yaml │ └── enc-grafana-token.secret.yaml │ ├── projectpythia │ ├── staging.values.yaml │ ├── prod.values.yaml │ ├── support.values.yaml │ └── enc-grafana-token.secret.yaml │ ├── awi-ciroh │ ├── support.values.yaml │ ├── enc-workshop.secret.values.yaml │ └── enc-grafana-token.secret.yaml │ ├── oceanhackweek │ ├── prod.values.yaml │ ├── staging.values.yaml │ ├── cluster.yaml │ ├── support.values.yaml │ └── enc-grafana-token.secret.yaml │ ├── cloudbank │ ├── support.values.yaml │ ├── enc-grafana-token.secret.yaml │ └── common.values.yaml │ ├── leap │ ├── support.values.yaml │ ├── staging.values.yaml │ └── enc-grafana-token.secret.yaml │ ├── reflective │ ├── support.values.yaml │ ├── enc-grafana-token.secret.yaml │ └── enc-workshop.secret.values.yaml │ ├── smithsonian │ ├── prod.values.yaml │ ├── staging.values.yaml │ ├── cluster.yaml │ ├── support.values.yaml │ └── enc-grafana-token.secret.yaml │ ├── nasa-ghg-hub │ ├── support.values.yaml │ └── enc-grafana-token.secret.yaml │ ├── victor │ ├── cluster.yaml │ └── enc-grafana-token.secret.yaml │ ├── catalystproject-latam │ ├── staging.values.yaml │ ├── gita.values.yaml │ ├── support.values.yaml │ ├── iner.values.yaml │ ├── cabana.values.yaml │ ├── nnb-ccg.values.yaml │ └── enc-grafana-token.secret.yaml │ ├── bnext-bio │ ├── cluster.yaml │ └── enc-grafana-token.secret.yaml │ ├── aimatx-2i2c-hub │ ├── enc-grafana-token.secret.yaml │ └── cluster.yaml │ ├── berkeley-geojupyter │ ├── enc-grafana-token.secret.yaml │ ├── prod.values.yaml │ ├── staging.values.yaml │ └── support.values.yaml │ ├── catalystproject-africa │ ├── support.values.yaml │ ├── aibst.values.yaml │ ├── molerhealth.values.yaml │ ├── wits.values.yaml │ ├── enc-grafana-token.secret.yaml │ ├── kush.values.yaml │ ├── bon.values.yaml │ └── uvri.values.yaml │ ├── disasters │ ├── support.values.yaml │ ├── enc-grafana-token.secret.yaml │ └── cluster.yaml │ ├── maap │ ├── cluster.yaml │ └── enc-grafana-token.secret.yaml │ ├── openscapeshub │ └── enc-workshop.secret.values.yaml │ ├── nasa-cryo │ ├── support.values.yaml │ └── cluster.yaml │ ├── jupyter-health │ ├── support.values.yaml │ ├── enc-grafana-token.secret.yaml │ └── cluster.yaml │ ├── earthscope │ └── enc-grafana-token.secret.yaml │ ├── nasa-veda │ └── enc-grafana-token.secret.yaml │ └── nmfs-openscapes │ └── enc-grafana-token.secret.yaml ├── .github ├── ISSUE_TEMPLATE │ └── config.yml └── workflows │ ├── autolink-readthedocs-previews-to-prs.yaml │ ├── doc-links.yml │ ├── terraform-lint.yaml │ ├── comment-dependabot-prs.yaml │ ├── test-deployer-code.yaml │ └── test-docs.yaml ├── MANIFEST.in ├── .git-blame-ignore-revs ├── tests ├── test-clusters │ ├── cluster2 │ │ └── cluster.yaml │ ├── cluster3 │ │ └── cluster.yaml │ └── cluster1 │ │ └── cluster.yaml └── README.md ├── dev-requirements.txt ├── .readthedocs.yaml ├── .flake8 ├── .prettierignore └── .sops.yaml /deployer/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/_static/custom.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /terraform/.gitignore: -------------------------------------------------------------------------------- 1 | .terraform 2 | -------------------------------------------------------------------------------- /deployer/dev_commands/generate/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /deployer/health_check_tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /helm-charts/daskhub/values.jsonnet: -------------------------------------------------------------------------------- 1 | ../basehub/values.jsonnet -------------------------------------------------------------------------------- /docs/images/config-flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2i2c-org/infrastructure/HEAD/docs/images/config-flow.png -------------------------------------------------------------------------------- /docs/images/403-forbidden.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2i2c-org/infrastructure/HEAD/docs/images/403-forbidden.png -------------------------------------------------------------------------------- /docs/images/aws-billing-ui.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2i2c-org/infrastructure/HEAD/docs/images/aws-billing-ui.jpg -------------------------------------------------------------------------------- /docs/images/gcp-billing-ui.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2i2c-org/infrastructure/HEAD/docs/images/gcp-billing-ui.png -------------------------------------------------------------------------------- /docs/images/gcp-run-in-shell.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2i2c-org/infrastructure/HEAD/docs/images/gcp-run-in-shell.png -------------------------------------------------------------------------------- /helm-charts/images/hub/requirements.txt: -------------------------------------------------------------------------------- 1 | # Image lives at quay.io/2i2c/pilot-hub 2 | 3 | jupyterhub-fancy-profiles==0.4.1 -------------------------------------------------------------------------------- /docs/images/gcp-k8s-dashboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2i2c-org/infrastructure/HEAD/docs/images/gcp-k8s-dashboard.png -------------------------------------------------------------------------------- /eksctl/ssh-keys/temple.key.pub: -------------------------------------------------------------------------------- 1 | ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIL6KpQ1Ye9u4ohK5X6hENUirESSVtMYSfYyHMYzzg6HE angus@nixos 2 | -------------------------------------------------------------------------------- /docs/images/cilogon-clear-cookies.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2i2c-org/infrastructure/HEAD/docs/images/cilogon-clear-cookies.png -------------------------------------------------------------------------------- /docs/images/helm-charts-hierarchy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2i2c-org/infrastructure/HEAD/docs/images/helm-charts-hierarchy.png -------------------------------------------------------------------------------- /docs/images/status-page-pagerduty.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2i2c-org/infrastructure/HEAD/docs/images/status-page-pagerduty.png -------------------------------------------------------------------------------- /docs/images/changed-files-from-logs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2i2c-org/infrastructure/HEAD/docs/images/changed-files-from-logs.png -------------------------------------------------------------------------------- /docs/images/manually-delete-outage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2i2c-org/infrastructure/HEAD/docs/images/manually-delete-outage.png -------------------------------------------------------------------------------- /docs/images/staging-hub-login-page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2i2c-org/infrastructure/HEAD/docs/images/staging-hub-login-page.png -------------------------------------------------------------------------------- /eksctl/ssh-keys/berkeley-geojupyter.key.pub: -------------------------------------------------------------------------------- 1 | ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIuyiqguy+4Jbm5EWaQN8KxdLdn+9agi6/SCIf3I5Vtz angus@nixos 2 | -------------------------------------------------------------------------------- /eksctl/ssh-keys/reflective.key.pub: -------------------------------------------------------------------------------- 1 | ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIE8DG68W+eHIX0MVhJd4hUAbv6GaADfE3YHgodA+Vbv6 sgibson@Athena.local 2 | -------------------------------------------------------------------------------- /docs/images/azure-scale-node-pool-window.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2i2c-org/infrastructure/HEAD/docs/images/azure-scale-node-pool-window.png -------------------------------------------------------------------------------- /docs/images/grafana-grant-access_step-3a.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2i2c-org/infrastructure/HEAD/docs/images/grafana-grant-access_step-3a.jpg -------------------------------------------------------------------------------- /docs/images/grafana-grant-access_step-3b.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2i2c-org/infrastructure/HEAD/docs/images/grafana-grant-access_step-3b.jpg -------------------------------------------------------------------------------- /docs/images/grafana-grant-access_step-4a.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2i2c-org/infrastructure/HEAD/docs/images/grafana-grant-access_step-4a.jpg -------------------------------------------------------------------------------- /docs/images/grafana-grant-access_step-4b.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2i2c-org/infrastructure/HEAD/docs/images/grafana-grant-access_step-4b.jpg -------------------------------------------------------------------------------- /docs/images/grafana-grant-access_step-5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2i2c-org/infrastructure/HEAD/docs/images/grafana-grant-access_step-5.jpg -------------------------------------------------------------------------------- /docs/images/grafana-grant-access_step-6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2i2c-org/infrastructure/HEAD/docs/images/grafana-grant-access_step-6.jpg -------------------------------------------------------------------------------- /docs/images/grafana-grant-access_step-7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2i2c-org/infrastructure/HEAD/docs/images/grafana-grant-access_step-7.jpg -------------------------------------------------------------------------------- /docs/images/infrastructure-storage-layer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2i2c-org/infrastructure/HEAD/docs/images/infrastructure-storage-layer.png -------------------------------------------------------------------------------- /config/clusters/templates/common/support.secret.values.yaml: -------------------------------------------------------------------------------- 1 | prometheusIngressAuthSecret: 2 | username: {{ username }} 3 | password: {{ password }} -------------------------------------------------------------------------------- /docs/hub-deployment-guide/hubs/move-hubs/index.md: -------------------------------------------------------------------------------- 1 | # Moving Hubs 2 | 3 | ```{toctree} 4 | :maxdepth: 2 5 | new-url.md 6 | across-clusters.md 7 | ``` 8 | -------------------------------------------------------------------------------- /docs/images/cilogon-remember-this-selection.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2i2c-org/infrastructure/HEAD/docs/images/cilogon-remember-this-selection.png -------------------------------------------------------------------------------- /docs/images/granting-org-access-to-oauth-app.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/2i2c-org/infrastructure/HEAD/docs/images/granting-org-access-to-oauth-app.jpg -------------------------------------------------------------------------------- /config/clusters/2i2c/basehub-common.values.yaml: -------------------------------------------------------------------------------- 1 | nfs: 2 | enabled: true 3 | pv: 4 | enabled: true 5 | mountOptions: 6 | - soft 7 | - noatime 8 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | contact_links: 2 | - name: Looking for Support? 3 | url: https://docs.2i2c.org/en/latest/support.html 4 | about: Ask for help through our support process 5 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | # Include everything we put in the deployer/ dir 2 | recursive-include deployer * 3 | # But exclude .pyc files, as these are just compiled caches 4 | recursive-exclude deployer *.pyc 5 | -------------------------------------------------------------------------------- /terraform/uptime-checks/variables.tf: -------------------------------------------------------------------------------- 1 | variable "project_id" { 2 | type = string 3 | default = "two-eye-two-see" 4 | description = <<-EOT 5 | GCP project id containing all our uptime checks 6 | EOT 7 | } 8 | -------------------------------------------------------------------------------- /docs/howto/image-management/index.md: -------------------------------------------------------------------------------- 1 | (image-management)= 2 | # Manage Images 3 | 4 | This documentation covers tasks related to image management. 5 | 6 | ```{toctree} 7 | custom-jupyterhub-image 8 | update-env 9 | ``` 10 | -------------------------------------------------------------------------------- /.git-blame-ignore-revs: -------------------------------------------------------------------------------- 1 | # Ignore these revs while doing git blame, as they are autoformats 2 | # Run `git config blame.ignoreRevsFile .git-blame-ignore-revs` 3 | b59cf3bb16b61531ec4620737f61a74b0f47d7a5 4 | 6f3886ba818bccbe33d700cab34b51bd65552b6e 5 | -------------------------------------------------------------------------------- /helm-charts/support/README.md: -------------------------------------------------------------------------------- 1 | ## Per-Cluster Support Chart 2 | 3 | This Chart deploys *almost* everything we deploy once per cluster. There are a few exceptions 4 | that don't like being subcharts, which are deployed directly by the `deployer` script. 5 | -------------------------------------------------------------------------------- /terraform/aws/projects/strudel.tfvars: -------------------------------------------------------------------------------- 1 | region = "us-west-2" 2 | cluster_name = "strudel" 3 | cluster_nodes_location = "us-west-2a" 4 | 5 | enable_jupyterhub_cost_monitoring = true 6 | disable_cluster_wide_filestore = true 7 | -------------------------------------------------------------------------------- /deployer/commands/__init__.py: -------------------------------------------------------------------------------- 1 | import deployer.commands.deploy_dashboards # noqa: F401 2 | import deployer.commands.deployer # noqa: F401 3 | import deployer.commands.plan_upgrade.jobs # noqa: F401 4 | import deployer.commands.validate.config # noqa: F401 5 | -------------------------------------------------------------------------------- /helm-charts/basehub/templates/serviceaccount-user.yaml: -------------------------------------------------------------------------------- 1 | {{ if .Values.userServiceAccount.enabled -}} 2 | apiVersion: v1 3 | kind: ServiceAccount 4 | metadata: 5 | name: user-sa 6 | annotations: {{ .Values.userServiceAccount.annotations | toJson }} 7 | {{- end }} 8 | -------------------------------------------------------------------------------- /docs/howto/manage-domains/index.md: -------------------------------------------------------------------------------- 1 | # Manage domains of hubs 2 | 3 | These sections cover different scenarios where we may wish to change the URL 4 | of our hubs and how to go about achieving that. 5 | 6 | ```{toctree} 7 | :maxdepth: 2 8 | override-domain.md 9 | ``` 10 | -------------------------------------------------------------------------------- /docs/howto/troubleshoot/index.md: -------------------------------------------------------------------------------- 1 | # Troubleshoot 2 | 3 | We have many different tools at our disposal to troubleshoot 4 | issues that may arise. 5 | 6 | ```{toctree} 7 | :maxdepth: 2 8 | logs/index.md 9 | ssh.md 10 | prometheus.md 11 | cilogon-user-accounts.md 12 | ``` 13 | -------------------------------------------------------------------------------- /helm-charts/daskhub/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | appVersion: "1.0" 3 | description: Deployment Chart for a dask-enabled JupyterHub 4 | name: daskhub 5 | version: "0.1.0" 6 | dependencies: 7 | - name: basehub 8 | version: "0.1.0" 9 | repository: file://../basehub 10 | -------------------------------------------------------------------------------- /config/clusters/strudel/staging.values.yaml: -------------------------------------------------------------------------------- 1 | jupyterhub: 2 | ingress: 3 | hosts: [staging.strudel.2i2c.cloud] 4 | tls: 5 | - hosts: [staging.strudel.2i2c.cloud] 6 | secretName: https-auto-tls 7 | singleuser: 8 | nodeSelector: 9 | 2i2c/hub-name: staging 10 | -------------------------------------------------------------------------------- /docs/howto/budgeting-billing/index.md: -------------------------------------------------------------------------------- 1 | (budgeting-billing)= 2 | # Manage Budgets and Billing 3 | 4 | This documentation covers tasks relating to budgeting and billing of 2i2c hubs. 5 | 6 | ```{toctree} 7 | :maxdepth: 2 8 | bill 9 | budget-alerts 10 | cost-monitoring/index 11 | ``` 12 | -------------------------------------------------------------------------------- /docs/reference/cli.md: -------------------------------------------------------------------------------- 1 | # CLI Reference 2 | 3 | The `deployer` CLI contains a set of useful tools for deploying and maintaining our infrastructure. 4 | 5 | :::{typer} deployer.__main__:app 6 | :prog: deployer 7 | :show-nested: 8 | :make-sections: 9 | :markup-mode: markdown 10 | ::: 11 | -------------------------------------------------------------------------------- /helm-charts/basehub/templates/dex/pvc.yaml: -------------------------------------------------------------------------------- 1 | {{ if .Values.dex.enabled -}} 2 | apiVersion: v1 3 | kind: PersistentVolumeClaim 4 | metadata: 5 | name: dex 6 | spec: 7 | accessModes: 8 | - ReadWriteOnce 9 | resources: 10 | requests: 11 | storage: 1Gi 12 | {{- end }} 13 | -------------------------------------------------------------------------------- /docs/requirements.txt: -------------------------------------------------------------------------------- 1 | myst-parser[linkify] 2 | pandas 3 | pyyaml 4 | python-hcl2 5 | requests 6 | sphinx-autobuild 7 | sphinx-copybutton 8 | sphinx-design 9 | git+https://github.com/2i2c-org/sphinx-2i2c-theme 10 | sphinxcontrib-mermaid 11 | sphinxcontrib-jquery 12 | sphinxcontrib-typer 13 | sphinx-last-updated-by-git 14 | -------------------------------------------------------------------------------- /docs/topic/billing/index.md: -------------------------------------------------------------------------------- 1 | # Cloud Billing 2 | 3 | These topics provide us foundational common shared knowledge and 4 | terminology to talk about cloud billing. 5 | 6 | ```{toctree} 7 | :maxdepth: 2 8 | chargeable-resources 9 | accounts 10 | reports 11 | tools 12 | budget-alerts 13 | cost-monitoring-system 14 | ``` 15 | -------------------------------------------------------------------------------- /docs/topic/access-creds/index.md: -------------------------------------------------------------------------------- 1 | # Access and credentials 2 | 3 | These sections discuss our policies and conventions around granting access to 4 | resources and how we handle sensitive information that needs to live in the 5 | repository. 6 | 7 | ```{toctree} 8 | :maxdepth: 2 9 | cloud-auth.md 10 | secrets.md 11 | ``` 12 | -------------------------------------------------------------------------------- /helm-charts/basehub/templates/ingress-auth/secret.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.ingressBasicAuth.enabled -}} 2 | apiVersion: v1 3 | kind: Secret 4 | metadata: 5 | name: ingress-basic-auth 6 | type: Opaque 7 | data: 8 | auth: {{ htpasswd .Values.ingressBasicAuth.username .Values.ingressBasicAuth.password | b64enc | quote }} 9 | {{- end }} 10 | -------------------------------------------------------------------------------- /deployer/__main__.py: -------------------------------------------------------------------------------- 1 | # Import the various subcommands here, they will be automatically 2 | # registered into the app 3 | 4 | from . import commands, dev_commands # noqa: F401 5 | from .cli_app import app 6 | from .utils.jsonnet import validate_jsonnet_version 7 | 8 | 9 | def main(): 10 | validate_jsonnet_version() 11 | app() 12 | -------------------------------------------------------------------------------- /docs/howto/filesystem-management/index.md: -------------------------------------------------------------------------------- 1 | (filesystem-management)= 2 | # Manage Filesystems 3 | 4 | This documentation covers tasks related to managing filesystems. 5 | 6 | ```{toctree} 7 | :maxdepth: 2 8 | data-transfer 9 | data-transfer-external 10 | filesystem-backups/index 11 | decrease-size-gcp-filestore 12 | increase-disk-size 13 | ``` 14 | -------------------------------------------------------------------------------- /helm-charts/basehub/templates/incluster-nfs.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.inClusterNFS.enabled -}} 2 | apiVersion: v1 3 | kind: PersistentVolumeClaim 4 | metadata: 5 | name: home-nfs 6 | spec: 7 | accessModes: 8 | - ReadWriteMany 9 | storageClassName: "nfs" 10 | resources: 11 | requests: 12 | storage: {{ .Values.inClusterNFS.size }} 13 | {{- end }} 14 | -------------------------------------------------------------------------------- /helm-charts/basehub/templates/configmap-hub-templates.yaml: -------------------------------------------------------------------------------- 1 | kind: ConfigMap 2 | apiVersion: v1 3 | metadata: 4 | name: hub-custom-templates-config 5 | labels: 6 | app: jupyterhub 7 | data: 8 | {{- with .Values.jupyterhub.custom.homepage }} 9 | GIT_REPO_URL: {{ .gitRepoUrl | quote }} 10 | GIT_REPO_BRANCH: {{ .gitRepoBranch | quote }} 11 | {{- end }} 12 | -------------------------------------------------------------------------------- /terraform/openstack/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = "~> 1.5" 3 | 4 | required_providers { 5 | openstack = { 6 | source = "terraform-provider-openstack/openstack" 7 | version = "~> 3.0" 8 | } 9 | } 10 | backend "gcs" { 11 | bucket = "two-eye-two-see-org-terraform-state" 12 | prefix = "terraform/state/pilot-hubs" 13 | } 14 | } -------------------------------------------------------------------------------- /helm-charts/basehub/templates/configurator.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: configurator 5 | labels: 6 | app: jupyterhub 7 | component: configurator 8 | spec: 9 | type: ClusterIP 10 | ports: 11 | - name: http 12 | port: 10101 13 | targetPort: 10101 14 | selector: 15 | app: jupyterhub 16 | component: hub 17 | -------------------------------------------------------------------------------- /docs/hub-deployment-guide/hubs/index.md: -------------------------------------------------------------------------------- 1 | # Other hub-related operations 2 | 3 | These sections cover other operations around deploying, migrating, and removing hubs from Kubernetes clusters. 4 | They also cover more specific use-cases for special infrastructure set-ups. 5 | 6 | ```{toctree} 7 | :maxdepth: 2 8 | manual-deploy.md 9 | move-hubs/index.md 10 | delete-hub.md 11 | ``` 12 | -------------------------------------------------------------------------------- /docs/topic/monitoring-alerting/index.md: -------------------------------------------------------------------------------- 1 | # Monitoring and alerting 2 | 3 | These sections discuss different ways we monitor the infrastructure we run, 4 | and the alerting mechanisms we implement for when something goes wrong. 5 | 6 | ```{toctree} 7 | :maxdepth: 2 8 | grafana.md 9 | prometheus.md 10 | alerting.md 11 | escalation-policies.md 12 | uptime-checks-alerts.md 13 | ``` 14 | -------------------------------------------------------------------------------- /helm-charts/basehub/templates/static/service.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.staticWebsite.enabled -}} 2 | apiVersion: v1 3 | kind: Service 4 | metadata: 5 | name: static-sites 6 | labels: 7 | app: static-sites 8 | spec: 9 | type: ClusterIP 10 | ports: 11 | - name: http 12 | port: 80 13 | targetPort: nginx 14 | selector: 15 | app: static-sites 16 | {{- end }} 17 | -------------------------------------------------------------------------------- /helm-charts/images/hub/pkce-requirements.txt: -------------------------------------------------------------------------------- 1 | # Image lives at quay.io/2i2c/pkce-experiment 2 | # install oauthenticator 17.3, 3 | # which adds PKCE and refresh_token support 4 | # experiment no longer needed when base chart is updated to z2jh 4.1.0 5 | oauthenticator>=17.3,<18 6 | 7 | # Brings in https://github.com/yuvipanda/jupyterhub-fancy-profiles 8 | jupyterhub-fancy-profiles==0.3.10 9 | -------------------------------------------------------------------------------- /tests/test-clusters/cluster2/cluster.yaml: -------------------------------------------------------------------------------- 1 | name: cluster2 2 | provider: aws 3 | support: 4 | helm_chart_values_files: 5 | - support.values.yaml 6 | hubs: 7 | - name: hub1 8 | helm_chart_values_files: 9 | - hub1.values.yaml 10 | - name: hub2 11 | helm_chart_values_files: 12 | - hub2.values.yaml 13 | - name: hub3 14 | helm_chart_values_files: 15 | - hub3.values.yaml 16 | -------------------------------------------------------------------------------- /config/clusters/templates/common/cluster-entry.yaml: -------------------------------------------------------------------------------- 1 | hubs: 2 | - name: {{ hub_name }} 3 | display_name: {{ cluster_name }} {{ hub_name }} 4 | domain: {{ hub_name }}.{{ cluster_name }}.2i2c.cloud 5 | helm_chart: "basehub" 6 | helm_chart_values_files: 7 | - common.values.yaml 8 | - {{ hub_name }}.values.yaml 9 | - enc-{{ hub_name }}.secret.values.yaml 10 | -------------------------------------------------------------------------------- /docs/topic/infrastructure/index.md: -------------------------------------------------------------------------------- 1 | # Infrastructure 2 | 3 | These topics delve into the mechanics of the infrastructure we run, our 4 | conventions around configuration, and the tools we use for management. 5 | 6 | ```{toctree} 7 | :maxdepth: 2 8 | config.md 9 | cluster-design.md 10 | terraform.md 11 | hub-helm-charts.md 12 | network.md 13 | storage-layer.md 14 | cryptnono.md 15 | ``` 16 | -------------------------------------------------------------------------------- /helm-charts/support/templates/prometheus-ingres-auth/secret.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.prometheusIngressAuthSecret.enabled -}} 2 | apiVersion: v1 3 | kind: Secret 4 | metadata: 5 | name: prometheus-ingress-auth-basic 6 | type: Opaque 7 | data: 8 | auth: {{ htpasswd .Values.prometheusIngressAuthSecret.username .Values.prometheusIngressAuthSecret.password | b64enc | quote}} 9 | {{- end }} 10 | -------------------------------------------------------------------------------- /tests/test-clusters/cluster3/cluster.yaml: -------------------------------------------------------------------------------- 1 | name: cluster3 2 | provider: gcp 3 | support: 4 | helm_chart_values_files: 5 | - support.values.yaml 6 | hubs: 7 | - name: staging1 8 | helm_chart_values_files: 9 | - staging1.values.yaml 10 | - name: staging2 11 | helm_chart_values_files: 12 | - staging2.values.yaml 13 | - name: prod 14 | helm_chart_values_files: 15 | - prod.values.yaml 16 | -------------------------------------------------------------------------------- /config/clusters/2i2c/daskhub-common.values.yaml: -------------------------------------------------------------------------------- 1 | basehub: 2 | nfs: 3 | enabled: true 4 | pv: 5 | enabled: true 6 | mountOptions: 7 | - soft 8 | - noatime 9 | dask-gateway: 10 | enabled: true 11 | jupyterhub: 12 | custom: 13 | daskhubSetup: 14 | enabled: true 15 | singleuser: 16 | cloudMetadata: 17 | blockWithIptables: false 18 | -------------------------------------------------------------------------------- /docs/topic/infrastructure/network.md: -------------------------------------------------------------------------------- 1 | # Network policy 2 | 3 | 2i2c-managed hubs have a permissive network policy for the user servers that allows all outbound access to the internet, but restricts traffic within the cluster. 4 | 5 | The policy is [defined in the `basehub` chart](https://github.com/2i2c-org/infrastructure/tree/HEAD/helm-charts/basehub/values.yaml#L153) and is inherited by the `daskhub` chart. 6 | -------------------------------------------------------------------------------- /helm-charts/basehub/templates/dex/_helpers.tpl: -------------------------------------------------------------------------------- 1 | # Until https://github.com/Masterminds/sprig/issues/282 is fixed 2 | {{- define "randHex" -}} 3 | {{- $result := "" }} 4 | {{- range $i := until . }} 5 | {{- $rand_hex_char := mod (randNumeric 4 | atoi) 16 | printf "%x" }} 6 | {{- $result = print $result $rand_hex_char }} 7 | {{- end }} 8 | {{- $result }} 9 | {{- end }} 10 | -------------------------------------------------------------------------------- /dev-requirements.txt: -------------------------------------------------------------------------------- 1 | # These requirements represents the needs for doing various tasks in this git 2 | # repo besides using the deployer script. 3 | # 4 | 5 | # chartpress is relevant to build and push helm-charts/images/hub/Dockerfile and 6 | # update basehub's default values to reference the new image. 7 | chartpress==2.* 8 | 9 | # requests is used by scripts in the /extra-scripts folder 10 | requests==2.* 11 | -------------------------------------------------------------------------------- /.readthedocs.yaml: -------------------------------------------------------------------------------- 1 | # https://docs.readthedocs.io/en/stable/config-file/v2.html 2 | version: 2 3 | 4 | build: 5 | os: ubuntu-24.04 6 | tools: 7 | python: '3.13' 8 | jobs: 9 | post_checkout: 10 | - git fetch --unshallow || true 11 | 12 | python: 13 | install: 14 | - path: . 15 | - requirements: docs/requirements.txt 16 | 17 | sphinx: 18 | configuration: docs/conf.py 19 | builder: dirhtml 20 | -------------------------------------------------------------------------------- /config/clusters/templates/common/hub.values.yaml: -------------------------------------------------------------------------------- 1 | jupyterhub: 2 | ingress: 3 | hosts: [{{ hub_name }}.{{ cluster_name }}.2i2c.cloud] 4 | tls: 5 | - hosts: [{{ hub_name }}.{{ cluster_name }}.2i2c.cloud] 6 | secretName: https-auto-tls 7 | hub: 8 | config: 9 | GitHubOAuthenticator: 10 | oauth_callback_url: https://{{ hub_name }}.{{ cluster_name }}.2i2c.cloud/hub/oauth_callback 11 | -------------------------------------------------------------------------------- /helm-charts/basehub/templates/dex/service.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.dex.enabled -}} 2 | apiVersion: v1 3 | kind: Service 4 | metadata: 5 | name: dex 6 | labels: 7 | app: dex 8 | spec: 9 | type: ClusterIP 10 | ports: 11 | - name: dex 12 | port: 5556 13 | targetPort: dex 14 | - name: oauth2-proxy 15 | port: 9000 16 | targetPort: oauth2-proxy 17 | selector: 18 | app: dex 19 | {{- end }} 20 | -------------------------------------------------------------------------------- /config/clusters/strudel/prod.values.yaml: -------------------------------------------------------------------------------- 1 | jupyterhub: 2 | ingress: 3 | hosts: [strudel.2i2c.cloud] 4 | tls: 5 | - hosts: [strudel.2i2c.cloud] 6 | secretName: https-auto-tls 7 | singleuser: 8 | nodeSelector: 9 | 2i2c/hub-name: prod 10 | hub: 11 | config: 12 | JupyterHub: 13 | authenticator_class: dummy 14 | Authenticator: 15 | # No admins for dummy authenticator 16 | admin_users: [] 17 | -------------------------------------------------------------------------------- /config/clusters/utoronto/r-prod.values.yaml: -------------------------------------------------------------------------------- 1 | jupyterhub: 2 | ingress: 3 | hosts: [r.datatools.utoronto.ca] 4 | tls: 5 | - hosts: [r.datatools.utoronto.ca] 6 | secretName: https-auto-tls 7 | hub: 8 | db: 9 | pvc: 10 | # prod stores logs, so let's make it big 11 | storage: 60Gi 12 | config: 13 | CILogonOAuthenticator: 14 | oauth_callback_url: https://r.datatools.utoronto.ca/hub/oauth_callback 15 | -------------------------------------------------------------------------------- /config/clusters/temple/common-teaching.values.yaml: -------------------------------------------------------------------------------- 1 | jupyterhub: 2 | singleuser: 3 | image: 4 | name: laserchemist/datascience 5 | tag: v13 6 | # Taken from `deployer generate resource-allocation choices r5.xlarge:5` 7 | memory: 8 | guarantee: 1951419879 9 | limit: 1951419879 10 | cpu: 11 | guarantee: 0.22815625 12 | limit: 3.6505 13 | nodeSelector: 14 | node.kubernetes.io/instance-type: r5.xlarge 15 | -------------------------------------------------------------------------------- /terraform/internaltools/prometheus.yaml: -------------------------------------------------------------------------------- 1 | alertmanager: 2 | enabled: false 3 | 4 | prometheus-pushgateway: 5 | enabled: false 6 | 7 | kube-state-metrics: 8 | enabled: false 9 | 10 | prometheus-node-exporter: 11 | enabled: false 12 | 13 | server: 14 | retention: 1098d # 3 years 15 | 16 | strategy: 17 | type: Recreate 18 | 19 | persistentVolume: 20 | existingClaim: federated-prometheus-disk 21 | 22 | service: 23 | type: ClusterIP 24 | -------------------------------------------------------------------------------- /tests/test-clusters/cluster1/cluster.yaml: -------------------------------------------------------------------------------- 1 | name: cluster1 2 | provider: gcp 3 | support: 4 | helm_chart_values_files: 5 | - support.values.yaml 6 | hubs: 7 | - name: staging 8 | helm_chart_values_files: 9 | - staging.values.yaml 10 | - name: hub1 11 | helm_chart_values_files: 12 | - hub1.values.yaml 13 | - name: hub2 14 | helm_chart_values_files: 15 | - hub2.values.yaml 16 | - name: hub3 17 | helm_chart_values_files: 18 | - hub3.values.yaml 19 | -------------------------------------------------------------------------------- /eksctl/jupyter-health.jsonnet: -------------------------------------------------------------------------------- 1 | local cluster = import './libsonnet/cluster.jsonnet'; 2 | 3 | local c = cluster.makeCluster( 4 | name='jupyter-health', 5 | region='us-east-2', 6 | nodeAz='us-east-2a', 7 | version='1.34', 8 | coreNodeInstanceType='r8i-flex.large', 9 | notebookCPUInstanceTypes=[ 10 | 'r5.xlarge', 11 | 'r5.4xlarge', 12 | 'r5.16xlarge', 13 | ], 14 | hubs=['staging', 'prod'], 15 | nodeGroupGenerations=['c'] 16 | ); 17 | c 18 | -------------------------------------------------------------------------------- /terraform/openstack/projects/projectpythia-binder.tfvars: -------------------------------------------------------------------------------- 1 | prefix = "binder-pythia" 2 | 3 | notebook_nodes = { 4 | "m3.large" : { 5 | min : 1, 6 | max : 100, 7 | # 16 CPU, 60 RAM 8 | # https://docs.jetstream-cloud.org/general/instance-flavors/#jetstream2-cpu 9 | machine_type : "m3.large", 10 | labels = { 11 | "hub.jupyter.org/node-purpose" = "user", 12 | "k8s.dask.org/node-purpose" = "scheduler", 13 | } 14 | }, 15 | } 16 | -------------------------------------------------------------------------------- /config/clusters/utoronto/default-common.values.yaml: -------------------------------------------------------------------------------- 1 | jupyterhub: 2 | singleuser: 3 | image: 4 | name: quay.io/2i2c/utoronto-image 5 | tag: 063892275af8 6 | hub: 7 | config: 8 | Authenticator: 9 | admin_users: 10 | # 2i2c staff below, a list maintained in default-common r-common 11 | - yuvi.panda@utoronto.ca 12 | - georgiana.elena@utoronto.ca 13 | - chris.holdgraf@utoronto.ca 14 | - davidy.liu@utoronto.ca 15 | -------------------------------------------------------------------------------- /docs/hub-deployment-guide/deploy-support/index.md: -------------------------------------------------------------------------------- 1 | (support-components)= 2 | # Deploy support components 3 | 4 | 2i2c have collated a selection of common tools that are deployed once per cluster and assist with actions such as load-balancing and monitoring. 5 | The following sections describe how to deploy and configure this support infrastructure. 6 | 7 | ```{toctree} 8 | :maxdepth: 2 9 | configure-support.md 10 | setup-grafana-dashboards.md 11 | register-central-grafana.md 12 | ``` 13 | -------------------------------------------------------------------------------- /docs/hub-deployment-guide/runbooks/index.md: -------------------------------------------------------------------------------- 1 | (hub-deployment-guide:runbooks)= 2 | # Runbooks on how to handle new hub turn-up requests 3 | 4 | The following sections contain step-by-step runbooks that must be followed in order to drive to completion each phase of a new hub deployment. 5 | 6 | ```{warning} 7 | This is still a work in progress and this contents might change. 8 | ``` 9 | 10 | ```{toctree} 11 | :maxdepth: 2 12 | phase1/index.md 13 | phase2/index.md 14 | phase3/index.md 15 | ``` 16 | -------------------------------------------------------------------------------- /config/clusters/opensci/common.values.yaml: -------------------------------------------------------------------------------- 1 | nfs: 2 | enabled: true 3 | pv: 4 | enabled: true 5 | # from https://docs.aws.amazon.com/efs/latest/ug/mounting-fs-nfs-mount-settings.html 6 | mountOptions: 7 | - rsize=1048576 8 | - wsize=1048576 9 | - timeo=600 10 | - soft # We pick soft over hard, so NFS lockups don't lead to hung processes 11 | - retrans=2 12 | - noresvport 13 | 14 | jupyterhub: 15 | scheduling: 16 | userScheduler: 17 | enabled: true 18 | -------------------------------------------------------------------------------- /eksctl/oceanhackweek.jsonnet: -------------------------------------------------------------------------------- 1 | local cluster = import './libsonnet/cluster.jsonnet'; 2 | 3 | local c = cluster.makeCluster( 4 | name='oceanhackweek', 5 | region='us-west-2', 6 | nodeAz='us-west-2a', 7 | version='1.33', 8 | coreNodeInstanceType='r8i-flex.large', 9 | notebookCPUInstanceTypes=[ 10 | 'r5.xlarge', 11 | 'r5.4xlarge', 12 | 'r5.16xlarge', 13 | ], 14 | hubs=['staging', 'prod'], 15 | notebookGPUNodeGroups=[], 16 | nodeGroupGenerations=['b'] 17 | ); 18 | 19 | c 20 | -------------------------------------------------------------------------------- /.github/workflows/autolink-readthedocs-previews-to-prs.yaml: -------------------------------------------------------------------------------- 1 | name: Add readthedocs preview link to pull requests 2 | 3 | on: 4 | pull_request_target: 5 | paths: 6 | - docs/** 7 | 8 | jobs: 9 | autolink-rtd-previews: 10 | runs-on: ubuntu-latest 11 | permissions: 12 | pull-requests: write 13 | steps: 14 | - uses: readthedocs/actions/preview@v1 15 | with: 16 | # The project slug in RTD still has the old repo name 17 | project-slug: 2i2c-pilot-hubs 18 | -------------------------------------------------------------------------------- /eksctl/ubc-eoas.jsonnet: -------------------------------------------------------------------------------- 1 | local cluster = import './libsonnet/cluster.jsonnet'; 2 | 3 | local c = cluster.makeCluster( 4 | name='ubc-eoas', 5 | region='ca-central-1', 6 | nodeAz='ca-central-1a', 7 | version='1.34', 8 | coreNodeInstanceType='r8i-flex.large', 9 | notebookCPUInstanceTypes=[ 10 | 'r5.xlarge', 11 | 'r5.2xlarge', 12 | 'r5.4xlarge', 13 | 'r5.16xlarge', 14 | ], 15 | hubs=[ 16 | 'staging', 17 | 'prod', 18 | ], 19 | nodeGroupGenerations=['a'] 20 | ); 21 | c 22 | -------------------------------------------------------------------------------- /docs/howto/troubleshoot/logs/index.md: -------------------------------------------------------------------------------- 1 | # Look at logs to troubleshoot issues 2 | 3 | Looking at and interpreting logs produced by various components is the easiest 4 | way to debug most issues, and should be the first place to look at when issues 5 | are reported. 6 | 7 | This page describes how to look at various logs in different cloud providers or 8 | by using cloud-agnostic kubectl and deployer commands. 9 | 10 | ```{toctree} 11 | :maxdepth: 2 12 | cloud-logs 13 | kubectl-logs 14 | common-errors 15 | ``` 16 | -------------------------------------------------------------------------------- /eksctl/strudel.jsonnet: -------------------------------------------------------------------------------- 1 | local cluster = import './libsonnet/cluster.jsonnet'; 2 | 3 | local c = cluster.makeCluster( 4 | name='strudel', 5 | region='us-west-2', 6 | nodeAz='us-west-2a', 7 | version='1.34', 8 | coreNodeInstanceType='r8i-flex.large', 9 | notebookCPUInstanceTypes=[ 10 | 'r5.xlarge', 11 | 'r5.4xlarge', 12 | 'r5.16xlarge', 13 | ], 14 | daskInstanceTypes=[], 15 | hubs=['staging', 'prod', 'workshop'], 16 | notebookGPUNodeGroups=[], 17 | nodeGroupGenerations=['a'] 18 | ); 19 | c 20 | -------------------------------------------------------------------------------- /docs/howto/filesystem-management/filesystem-backups/index.md: -------------------------------------------------------------------------------- 1 | (howto:filesystem-backups)= 2 | # Filesystem Backups 3 | 4 | The filesystem is where our users keep a lot of critical files, such as code. 5 | Hence if the filesystem is lost, for some reason, this is a disastrous event. 6 | These documents describe how to enable automated backups of the filesystems for 7 | various cloud providers, and recover filesystems from those backups. 8 | 9 | ```{toctree} 10 | :maxdepth: 2 11 | enable-backups 12 | restore-filesystem 13 | ``` 14 | -------------------------------------------------------------------------------- /docs/sre-guide/support/index.md: -------------------------------------------------------------------------------- 1 | # Support tasks 2 | 3 | This section lists various tasks that engineers might do as part of support 4 | requests. 5 | 6 | There is also a wiki with [per-cluster support notes](https://github.com/2i2c-org/infrastructure/wiki/Per-Cluster-Support-Notes). 7 | 8 | ```{toctree} 9 | :maxdepth: 2 10 | home-dir 11 | simple-python-package 12 | decrypt-age 13 | build-image-remotely 14 | credits 15 | grafana-account 16 | admin-users 17 | community-domains 18 | reset-shared-password 19 | reset-hub 20 | ``` 21 | -------------------------------------------------------------------------------- /deployer/dev_commands/generate/hub_asset/hub_asset_app.py: -------------------------------------------------------------------------------- 1 | """ 2 | Creates a new typer application, which is then 3 | nested as a sub-command named "hub-asset" 4 | under the `generate` sub-command of the deployer. 5 | """ 6 | 7 | import typer 8 | 9 | from deployer.cli_app import generate_app 10 | 11 | hub_asset_app = typer.Typer(pretty_exceptions_show_locals=False) 12 | generate_app.add_typer( 13 | hub_asset_app, 14 | name="hub-asset", 15 | help="Generate various hub assets to make deploying a new hub easier", 16 | ) 17 | -------------------------------------------------------------------------------- /docs/howto/budgeting-billing/cost-monitoring/index.md: -------------------------------------------------------------------------------- 1 | (howto:cost-monitoring)= 2 | # Enable cost monitoring system 3 | 4 | This documentation is about enabling automatic cost monitoring systems for 5 | various cloud providers. This is different from the manual accounting we've 6 | performed for shared and dedicated clusters that we pay the cloud bill for. 7 | 8 | Currently we only have a automatic cost monitoring system for AWS, with other providers to come in the future. 9 | 10 | ```{toctree} 11 | :maxdepth: 2 12 | aws 13 | ``` 14 | -------------------------------------------------------------------------------- /config/clusters/ubc-eoas/prod.values.yaml: -------------------------------------------------------------------------------- 1 | jupyterhub: 2 | ingress: 3 | hosts: [ubc-eoas.2i2c.cloud] 4 | tls: 5 | - hosts: [ubc-eoas.2i2c.cloud] 6 | secretName: https-auto-tls 7 | hub: 8 | config: 9 | CILogonOAuthenticator: 10 | oauth_callback_url: https://ubc-eoas.2i2c.cloud/hub/oauth_callback 11 | singleuser: 12 | nodeSelector: 13 | 2i2c/hub-name: prod 14 | jupyterhub-home-nfs: 15 | eks: 16 | volumeId: vol-084a510095d5b3b9b 17 | 18 | nfs: 19 | pv: 20 | serverIP: 10.100.213.235 21 | -------------------------------------------------------------------------------- /tests/README.md: -------------------------------------------------------------------------------- 1 | # Tests for `deployer` package 2 | 3 | This directory contains tests dedicated to ensuring the `deployer` package is behaving in the manner the 2i2c Engineering team designed and expect it to behave. 4 | 5 | To run this test suite, **from the root of the repo**, install the requirements, and then activate the tests using `pytest`. 6 | (You may wish to create a virtual environment first before executing these commands using `venv` or `conda`.) 7 | 8 | ```bash 9 | pip install --editable . 10 | python -m pytest -vvv 11 | ``` 12 | -------------------------------------------------------------------------------- /.github/workflows/doc-links.yml: -------------------------------------------------------------------------------- 1 | name: Build documentation and check links 2 | 3 | on: 4 | workflow_dispatch: 5 | schedule: 6 | # Runs at 1am each day. 7 | - cron: 0 1 * * * 8 | 9 | jobs: 10 | # ref: https://github.com/2i2c-org/.github/blob/main/.github/workflows/documentation-link-check.yaml 11 | linkcheck: 12 | permissions: 13 | issues: write 14 | uses: 2i2c-org/.github/.github/workflows/documentation-link-check.yaml@main 15 | with: 16 | docs_path: docs 17 | requirements_path: docs/requirements.txt 18 | -------------------------------------------------------------------------------- /.github/workflows/terraform-lint.yaml: -------------------------------------------------------------------------------- 1 | name: Lint terraform 2 | 3 | on: 4 | pull_request: 5 | paths: 6 | - terraform/** 7 | 8 | jobs: 9 | lint: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: actions/checkout@v6 13 | - uses: hashicorp/setup-terraform@v3 14 | - uses: terraform-linters/setup-tflint@v6 15 | - name: Run terraform linter 16 | run: | 17 | cd terraform 18 | tflint --recursive 19 | - name: Check terraform formatting 20 | run: terraform fmt -check -diff terraform/ 21 | -------------------------------------------------------------------------------- /config/clusters/utoronto/highmem.values.yaml: -------------------------------------------------------------------------------- 1 | jupyterhub: 2 | ingress: 3 | hosts: [highmem.datatools.utoronto.ca] 4 | tls: 5 | - hosts: [highmem.datatools.utoronto.ca] 6 | secretName: https-auto-tls 7 | hub: 8 | db: 9 | pvc: 10 | # prod stores logs, so let's make it big 11 | storage: 60Gi 12 | config: 13 | CILogonOAuthenticator: 14 | oauth_callback_url: https://highmem.datatools.utoronto.ca/hub/oauth_callback 15 | singleuser: 16 | memory: 17 | limit: 8G 18 | guarantee: 8G 19 | -------------------------------------------------------------------------------- /.flake8: -------------------------------------------------------------------------------- 1 | [flake8] 2 | # Ignore style and complexity 3 | # E: style errors 4 | # W: style warnings 5 | # C: complexity 6 | # E402: module level import not at top of file 7 | # I100: Import statements are in the wrong order 8 | # I101: Imported names are in the wrong order. Should be 9 | # F841: local variable ... is assigned to but never used 10 | ignore = E, C, W, I100, I101, D400, F841 11 | builtins = c 12 | exclude = 13 | # This is a `.py` file but is encrypted with sops 14 | deployer/dev_commands/generate/cryptnono_config/enc-blocklist-generator.secret.py 15 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | # Helm chart's templates aren't pure YAML files 2 | **/templates/ 3 | 4 | # It would be trouble if we had two automatic formatters on the same files. This 5 | # could happen if we would auto-format the sops generated files with prettier. 6 | enc-* 7 | *secret* 8 | 9 | # To create a minimal change suggestion, prettier was introduced to auto-format 10 | # the YAML files only. It is absolutely reasonable to auto-format markdown files 11 | # and json files as well, but for now, let's make prettier only auto-format 12 | # YAML. 13 | **/*.md 14 | **/*.json 15 | -------------------------------------------------------------------------------- /docs/hub-deployment-guide/runbooks/phase3/index.md: -------------------------------------------------------------------------------- 1 | (hub-deployment-guide:runbooks:phase3)= 2 | # Phase 3: Hub setup 3 | 4 | This phase assumes that a cluster to deploy the hub to already exists or it was created following the previous two runbooks. 5 | 6 | It contains five sub-phases that should be executed in the order listed below. 7 | 8 | ```{toctree} 9 | :maxdepth: 1 10 | initial-hub-setup.md 11 | ``` 12 | 13 | Phase 3.2: Object storage access 14 | 15 | Phase 3.3: Profile List 16 | 17 | Phase 3.4: Authentication tuning 18 | 19 | Phase 3.5: Profile List finetuning -------------------------------------------------------------------------------- /config/clusters/2i2c-jetstream2/cluster.yaml: -------------------------------------------------------------------------------- 1 | name: 2i2c-jetstream2 2 | provider: kubeconfig # allocation CIS250031_IU in https://js2.jetstream-cloud.org/project/ 3 | kubeconfig: 4 | file: enc-deployer-credentials.secret.yaml 5 | support: 6 | helm_chart_values_files: 7 | - support.values.yaml 8 | - enc-support.secret.values.yaml 9 | hubs: 10 | - name: staging 11 | display_name: 2i2c Jetstream2 staging 12 | domain: staging.js.2i2c.cloud 13 | helm_chart: basehub 14 | helm_chart_values_files: 15 | - staging.values.yaml 16 | - enc-staging.secret.values.yaml 17 | -------------------------------------------------------------------------------- /config/clusters/ubc-eoas/staging.values.yaml: -------------------------------------------------------------------------------- 1 | jupyterhub: 2 | ingress: 3 | hosts: [staging.ubc-eoas.2i2c.cloud] 4 | tls: 5 | - hosts: [staging.ubc-eoas.2i2c.cloud] 6 | secretName: https-auto-tls 7 | hub: 8 | config: 9 | CILogonOAuthenticator: 10 | oauth_callback_url: https://staging.ubc-eoas.2i2c.cloud/hub/oauth_callback 11 | singleuser: 12 | nodeSelector: 13 | 2i2c/hub-name: staging 14 | jupyterhub-home-nfs: 15 | eks: 16 | volumeId: vol-09051a9e20963690a 17 | 18 | nfs: 19 | pv: 20 | serverIP: 10.100.188.202 21 | -------------------------------------------------------------------------------- /eksctl/berkeley-geojupyter.jsonnet: -------------------------------------------------------------------------------- 1 | local cluster = import './libsonnet/cluster.jsonnet'; 2 | 3 | local c = cluster.makeCluster( 4 | name='berkeley-geojupyter', 5 | region='us-west-2', 6 | nodeAz='us-west-2a', 7 | version='1.33', 8 | coreNodeInstanceType='r8i-flex.large', 9 | notebookCPUInstanceTypes=[ 10 | 'r5.xlarge', 11 | 'r5.4xlarge', 12 | 'r5.16xlarge', 13 | ], 14 | daskInstanceTypes=[ 15 | 'r5.4xlarge', 16 | ], 17 | hubs=['staging', 'prod'], 18 | notebookGPUNodeGroups=[], 19 | nodeGroupGenerations=['b'] 20 | ); 21 | 22 | c 23 | -------------------------------------------------------------------------------- /deployer/dev_commands/generate/dedicated_cluster/dedicated_cluster_app.py: -------------------------------------------------------------------------------- 1 | """ 2 | Creates a new typer application, which is then 3 | nested as a sub-command named "dedicated-cluster" 4 | under the `generate` sub-command of the deployer. 5 | """ 6 | 7 | import typer 8 | 9 | from deployer.cli_app import generate_app 10 | 11 | dedicated_cluster_app = typer.Typer(pretty_exceptions_show_locals=False) 12 | generate_app.add_typer( 13 | dedicated_cluster_app, 14 | name="dedicated-cluster", 15 | help="Generate the initial files needed for a new cluster on GCP or AWS.", 16 | ) 17 | -------------------------------------------------------------------------------- /eksctl/ssh-keys/gridsst.key.pub: -------------------------------------------------------------------------------- 1 | ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDLEZ/WEyT1lrUd/5lpXHQo09ANoVEi3W+dQV+v4tqxb6mbQk9V/WhI4R8ljNjsEUhT9CyrPQ0PSuqWcvwggpKW/LFhmwO2S2kQl5BlYGA0w8YlawSpTYIJ/b1kLJ6miZERUZc5GJEkFBdfdKqp/KDFrAwMyCxM2pkmKANW/o6/z+gBd1BBeiTLzZiVFDj+ympLdb0yZYR6DAENlqwv4xB/UdMs6ZJ7Q0rq3aZ9sEHL8Zmzm64dI1lUj381YrDnsGduVi6mCkSesb034PoHYVaKn20HsMSQ50y0quPueceq5u1tYP0iV1V/u/av3UlDjo0DCVSpAXGN8i0+U/do1rgPaM/aVwFCbc9wCiN/5VDO1kmk2uFTVIWjdrtsBlKlAYIuL6kqujeOS6uCBvc4t8CLOrKaFmJfZIC8VE1Y6A9BWJQWs7jtpuV/0sA0ljX4zIk00Hj9e80Rm2dNmBEDBF7ERsRFQxnLREFT2vF5hUNRqMOoZq+wy5YeJvmPRTz3R4U= georgiana@192.168.1.9 2 | -------------------------------------------------------------------------------- /eksctl/ssh-keys/victor.key.pub: -------------------------------------------------------------------------------- 1 | ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDoQjCUh7E9s0NxEi7cuUJU5M+UXbhEjn/Fi1bZ/rry11Xbq6dFLyJcYzII0YvMO3XUKJj3mzAayI+eXOl9F4nfRb++2XHhKucKKdKHd/cz3u9pje7OpgkiBcxFzGNE2amLiEDSm32z93F3j5q5wkKTP6Ftnj2NT12C1llAB0OoegPaYGWS11jSo+KfprTo6/p1xsmVgwKxJjtbUw6DOr8lf6PJzLN1VUiHy+O06EEELtWM4WGWJP0U0DoRd/sNS6a5y3LBRzByXyL/wxUspO159ClrK81n9X1gtJblqfHIgaBlvuhP20lchnLBQIDXVz4sx1EIT4Ad9u9f3e4yxZYd41IvAxP3OGyyR6vePaUcfm9AeHO1DMkDTINKv5Yth94bxG+XUqHL9jKRWOgnExIcWUup4ka1boCQDQfGIDOcofwk9v2bVLK8Rr9lD1ALTbogWssPjCLLtNT8s/hoCUt2nyVWKgFJJP8L059pbkF96iGKaer7DbafhuEvLtIyVG8= georgiana@192.168.1.12 2 | -------------------------------------------------------------------------------- /config/clusters/utoronto/r-staging.values.yaml: -------------------------------------------------------------------------------- 1 | jupyterhub: 2 | singleuser: 3 | image: 4 | name: quay.io/2i2c/utoronto-r-image 5 | tag: 56d60b40210a 6 | 7 | ingress: 8 | hosts: [r-staging.datatools.utoronto.ca] 9 | tls: 10 | - hosts: [r-staging.datatools.utoronto.ca] 11 | secretName: https-auto-tls 12 | hub: 13 | db: 14 | pvc: 15 | # prod stores logs, so let's make it big 16 | storage: 10Gi 17 | config: 18 | CILogonOAuthenticator: 19 | oauth_callback_url: https://r-staging.datatools.utoronto.ca/hub/oauth_callback 20 | -------------------------------------------------------------------------------- /config/clusters/2i2c-aws-us/basehub-common.values.yaml: -------------------------------------------------------------------------------- 1 | nfs: 2 | enabled: true 3 | pv: 4 | enabled: true 5 | # from https://docs.aws.amazon.com/efs/latest/ug/mounting-fs-nfs-mount-settings.html 6 | mountOptions: 7 | - rsize=1048576 8 | - wsize=1048576 9 | - timeo=600 10 | - soft # We pick soft over hard, so NFS lockups don't lead to hung processes 11 | - retrans=2 12 | - noresvport 13 | 14 | jupyterhub: 15 | scheduling: 16 | userScheduler: 17 | enabled: true 18 | hub: 19 | config: 20 | JupyterHub: 21 | authenticator_class: github 22 | -------------------------------------------------------------------------------- /config/clusters/projectpythia-binder/cluster.yaml: -------------------------------------------------------------------------------- 1 | name: projectpythia-binder 2 | provider: kubeconfig # allocation SEE240014_IU in https://js2.jetstream-cloud.org/project/ 3 | kubeconfig: 4 | file: enc-deployer-credentials.secret.yaml 5 | support: 6 | helm_chart_values_files: 7 | - support.values.yaml 8 | - enc-support.secret.values.yaml 9 | hubs: 10 | - name: binderhub 11 | display_name: Project Pythia BinderHub on Jetstream2 12 | domain: hub.projectpythia.org 13 | helm_chart: basehub 14 | helm_chart_values_files: 15 | - binderhub.values.yaml 16 | - enc-binderhub.secret.values.yaml 17 | -------------------------------------------------------------------------------- /eksctl/nasa-ghg.jsonnet: -------------------------------------------------------------------------------- 1 | local cluster = import './libsonnet/cluster.jsonnet'; 2 | 3 | local c = cluster.makeCluster( 4 | name='nasa-ghg-hub', 5 | region='us-west-2', 6 | nodeAz='us-west-2a', 7 | version='1.34', 8 | coreNodeInstanceType='r8i-flex.large', 9 | notebookCPUInstanceTypes=[ 10 | 'r5.xlarge', 11 | 'r5.4xlarge', 12 | 'r5.16xlarge', 13 | ], 14 | daskInstanceTypes=[ 15 | // Allow for a range of spot instance types 16 | ['r5.4xlarge', 'r7i.4xlarge', 'r6i.4xlarge'], 17 | ], 18 | hubs=['staging', 'prod', 'binder'], 19 | nodeGroupGenerations=['b'] 20 | ); 21 | c 22 | -------------------------------------------------------------------------------- /helm-charts/support/templates/issuer.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: cert-manager.io/v1 2 | kind: ClusterIssuer 3 | metadata: 4 | name: letsencrypt-prod 5 | spec: 6 | acme: 7 | # The ACME server URL 8 | server: https://acme-v02.api.letsencrypt.org/directory 9 | # Email address used for ACME registration 10 | email: yuvipanda@gmail.com 11 | # Name of a secret used to store the ACME account private key 12 | privateKeySecretRef: 13 | name: letsencrypt-prod 14 | # Enable the HTTP-01 challenge provider 15 | solvers: 16 | - http01: 17 | ingress: 18 | class: nginx 19 | -------------------------------------------------------------------------------- /eksctl/reflective.jsonnet: -------------------------------------------------------------------------------- 1 | local cluster = import './libsonnet/cluster.jsonnet'; 2 | 3 | local c = cluster.makeCluster( 4 | name='reflective', 5 | region='us-west-2', 6 | nodeAz='us-west-2a', 7 | version='1.34', 8 | coreNodeInstanceType='r8i-flex.large', 9 | notebookCPUInstanceTypes=[ 10 | 'r5.xlarge', 11 | 'r5.4xlarge', 12 | 'r5.16xlarge', 13 | ], 14 | daskInstanceTypes=[ 15 | // Allow for a range of spot instance types 16 | ['r5.4xlarge', 'r7i.4xlarge', 'r6i.4xlarge'], 17 | ], 18 | hubs=['staging', 'prod', 'workshop'], 19 | nodeGroupGenerations=['a'] 20 | ); 21 | c 22 | -------------------------------------------------------------------------------- /eksctl/projectpythia.jsonnet: -------------------------------------------------------------------------------- 1 | local cluster = import './libsonnet/cluster.jsonnet'; 2 | 3 | local c = cluster.makeCluster( 4 | name='projectpythia', 5 | region='us-west-2', 6 | nodeAz='us-west-2a', 7 | version='1.34', 8 | coreNodeInstanceType='r8i-flex.large', 9 | notebookCPUInstanceTypes=[ 10 | 'r5.xlarge', 11 | 'r5.4xlarge', 12 | 'r5.16xlarge', 13 | ], 14 | daskInstanceTypes=[], 15 | hubs=['staging', 'prod', 'pythia-binder'], 16 | notebookGPUNodeGroups=[ 17 | { 18 | instanceType: 'g4dn.xlarge', 19 | }, 20 | ], 21 | nodeGroupGenerations=['a'], 22 | ); 23 | 24 | c 25 | -------------------------------------------------------------------------------- /eksctl/bnext-bio.jsonnet: -------------------------------------------------------------------------------- 1 | local cluster = import './libsonnet/cluster.jsonnet'; 2 | 3 | local c = cluster.makeCluster( 4 | name='bnext-bio', 5 | region='us-west-2', 6 | nodeAz='us-west-2a', 7 | version='1.34', 8 | coreNodeInstanceType='r8i-flex.large', 9 | notebookCPUInstanceTypes=[ 10 | 'r5.xlarge', 11 | 'r5.4xlarge', 12 | 'r5.16xlarge', 13 | ], 14 | daskInstanceTypes=[ 15 | 'r5.4xlarge', 16 | ], 17 | hubs=['staging', 'prod'], 18 | notebookGPUNodeGroups=[ 19 | { 20 | instanceType: 'g4dn.xlarge', 21 | }, 22 | ], 23 | nodeGroupGenerations=['c'] 24 | ); 25 | 26 | c 27 | -------------------------------------------------------------------------------- /terraform/openstack/persistent-disks.tf: -------------------------------------------------------------------------------- 1 | resource "openstack_blockstorage_volume_v3" "nfs_home_dirs" { 2 | for_each = var.persistent_disks 3 | 4 | name = each.value.name_suffix == null ? "hub-nfs-homedirs" : "hub-nfs-homedirs-${each.value.name_suffix}" 5 | size = each.value.size 6 | metadata = each.value.tags 7 | enable_online_resize = true 8 | 9 | lifecycle { 10 | prevent_destroy = true 11 | } 12 | } 13 | 14 | output "persistent_disk_id_map" { 15 | value = { for vol in values(openstack_blockstorage_volume_v3.nfs_home_dirs)[*] : vol.name => vol.id } 16 | } 17 | 18 | -------------------------------------------------------------------------------- /deployer/dev_commands/generate/resource_allocation/resource_allocation_app.py: -------------------------------------------------------------------------------- 1 | """ 2 | Creates a new typer application, which is then 3 | nested as a sub-command named "resource-allocation" 4 | under the `generate` sub-command of the deployer. 5 | """ 6 | 7 | import typer 8 | 9 | from deployer.cli_app import generate_app 10 | 11 | resource_allocation_app = typer.Typer(pretty_exceptions_show_locals=False) 12 | generate_app.add_typer( 13 | resource_allocation_app, 14 | name="resource-allocation", 15 | help="Generate the choices for a resource allocation strategy of an instance type and additional helper information", 16 | ) 17 | -------------------------------------------------------------------------------- /helm-charts/basehub/templates/static/secret.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.staticWebsite.enabled -}} 2 | {{- if .Values.staticWebsite.githubAuth.enabled -}} 3 | apiVersion: v1 4 | kind: Secret 5 | metadata: 6 | name: static-sites 7 | type: Opaque 8 | stringData: 9 | gitconfig: | 10 | [credential "https://github.com"] 11 | helper = !git-credential-github-app --app-key-file /etc/github/github-app-private-key.pem --app-id {{ .Values.staticWebsite.githubAuth.githubApp.id }} 12 | useHttpPath = true 13 | github-app-private-key.pem: | 14 | {{ .Values.staticWebsite.githubAuth.githubApp.privateKey | nindent 4 }} 15 | {{- end }} 16 | {{- end }} 17 | -------------------------------------------------------------------------------- /deployer/utils/env_vars_management.py: -------------------------------------------------------------------------------- 1 | import os 2 | from contextlib import contextmanager 3 | 4 | 5 | @contextmanager 6 | def unset_env_vars(vars): 7 | """ 8 | Temporarily unset env vars in vars if they exist 9 | """ 10 | orig_values = {} 11 | for e in vars: 12 | if e in os.environ: 13 | orig_values[e] = os.environ[e] 14 | # Clear values from os.environ if they are present! 15 | del os.environ[e] 16 | 17 | try: 18 | yield 19 | finally: 20 | for e in orig_values: 21 | # Put values back into os.environ when contextmanager returns 22 | os.environ[e] = orig_values[e] 23 | -------------------------------------------------------------------------------- /docs/topic/monitoring-alerting/prometheus.md: -------------------------------------------------------------------------------- 1 | (prometheus)= 2 | # Prometheus 3 | 4 | Each 2i2c Hub is set up with [a Prometheus server](https://prometheus.io/) to 5 | collect metrics and information about activity on the hub 6 | 7 | The prometheus server runs in the support namespace. 8 | 9 | (prometheus:access-prometheus)= 10 | ## Logging in 11 | 12 | Kubernetes port forwarding can be used to access the prometheus dashboard which 13 | can be used to check scrape targets and the metrics explorer to examine 14 | available metrics. 15 | 16 | ``` 17 | deployer use-cluster-credentials $CLUSTER_NAME 18 | kubectl port-forward -n support deploy/support-prometheus-server 9090:9090 19 | ``` 20 | -------------------------------------------------------------------------------- /helm-charts/support/templates/calico.yaml: -------------------------------------------------------------------------------- 1 | {{ if .Values.calico.enabled }} 2 | # Configures the CRD used by tigera-operator to install calico 3 | # https://docs.tigera.io/calico/latest/reference/installation/api#operator.tigera.io/v1.Installation 4 | apiVersion: operator.tigera.io/v1 5 | kind: Installation 6 | metadata: 7 | # Installation objects *must* be named 'default' 8 | # https://docs.tigera.io/calico/latest/reference/installation/api#operator.tigera.io%2fv1.Installation 9 | # Enforces there can only be one per cluster 10 | name: default 11 | spec: 12 | kubernetesProvider: EKS 13 | cni: 14 | type: AmazonVPC 15 | calicoNetwork: 16 | bgp: Disabled 17 | {{- end }} -------------------------------------------------------------------------------- /config/clusters/2i2c-uk/support.values.yaml: -------------------------------------------------------------------------------- 1 | prometheusIngressAuthSecret: 2 | enabled: true 3 | 4 | prometheus: 5 | server: 6 | ingress: 7 | enabled: true 8 | hosts: 9 | - prometheus.uk.2i2c.cloud 10 | tls: 11 | - secretName: prometheus-tls 12 | hosts: 13 | - prometheus.uk.2i2c.cloud 14 | 15 | grafana: 16 | grafana.ini: 17 | server: 18 | root_url: https://grafana.uk.2i2c.cloud/ 19 | auth.github: 20 | enabled: true 21 | allowed_organizations: 2i2c-org 22 | ingress: 23 | hosts: 24 | - grafana.uk.2i2c.cloud 25 | tls: 26 | - secretName: grafana-tls 27 | hosts: 28 | - grafana.uk.2i2c.cloud 29 | -------------------------------------------------------------------------------- /eksctl/maap.jsonnet: -------------------------------------------------------------------------------- 1 | local cluster = import './libsonnet/cluster.jsonnet'; 2 | 3 | local c = cluster.makeCluster( 4 | name='maap', 5 | region='us-west-2', 6 | nodeAz='us-west-2a', 7 | version='1.34', 8 | coreNodeInstanceType='r8i-flex.large', 9 | notebookCPUInstanceTypes=[ 10 | 'r5.xlarge', 11 | 'r5.4xlarge', 12 | 'r5.16xlarge', 13 | ], 14 | daskInstanceTypes=[ 15 | // Allow for a range of spot instance types 16 | ['r5.4xlarge', 'r7i.4xlarge', 'r6i.4xlarge'], 17 | ], 18 | hubs=['staging', 'prod'], 19 | notebookGPUNodeGroups=[ 20 | { 21 | instanceType: 'g4dn.xlarge', 22 | }, 23 | ], 24 | nodeGroupGenerations=['b'], 25 | ); 26 | 27 | c 28 | -------------------------------------------------------------------------------- /config/clusters/hhmi/support.values.yaml: -------------------------------------------------------------------------------- 1 | prometheusIngressAuthSecret: 2 | enabled: true 3 | 4 | prometheus: 5 | server: 6 | ingress: 7 | enabled: true 8 | hosts: 9 | - prometheus.hhmi.2i2c.cloud 10 | tls: 11 | - secretName: prometheus-tls 12 | hosts: 13 | - prometheus.hhmi.2i2c.cloud 14 | 15 | grafana: 16 | grafana.ini: 17 | server: 18 | root_url: https://grafana.hhmi.2i2c.cloud/ 19 | auth.github: 20 | enabled: true 21 | allowed_organizations: 2i2c-org 22 | ingress: 23 | hosts: 24 | - grafana.hhmi.2i2c.cloud 25 | tls: 26 | - secretName: grafana-tls 27 | hosts: 28 | - grafana.hhmi.2i2c.cloud 29 | -------------------------------------------------------------------------------- /eksctl/disasters.jsonnet: -------------------------------------------------------------------------------- 1 | local cluster = import './libsonnet/cluster.jsonnet'; 2 | 3 | local c = cluster.makeCluster( 4 | name='disasters', 5 | region='us-west-2', 6 | nodeAz='us-west-2a', 7 | version='1.34', 8 | coreNodeInstanceType='r8i-flex.large', 9 | notebookCPUInstanceTypes=[ 10 | 'r5.xlarge', 11 | 'r5.4xlarge', 12 | 'r5.16xlarge', 13 | ], 14 | daskInstanceTypes=[ 15 | // Allow for a range of spot instance types 16 | ['r5.4xlarge', 'r7i.4xlarge', 'r6i.4xlarge'], 17 | ], 18 | hubs=['staging', 'prod'], 19 | notebookGPUNodeGroups=[ 20 | { 21 | instanceType: 'g4dn.xlarge', 22 | }, 23 | ], 24 | nodeGroupGenerations=['a'] 25 | ); 26 | c 27 | -------------------------------------------------------------------------------- /eksctl/nasa-cryo.jsonnet: -------------------------------------------------------------------------------- 1 | local cluster = import './libsonnet/cluster.jsonnet'; 2 | 3 | local c = cluster.makeCluster( 4 | name='nasa-cryo', 5 | region='us-west-2', 6 | nodeAz='us-west-2a', 7 | version='1.34', 8 | coreNodeInstanceType='r8i-flex.large', 9 | notebookCPUInstanceTypes=[ 10 | 'r5.xlarge', 11 | 'r5.4xlarge', 12 | 'r5.16xlarge', 13 | ], 14 | daskInstanceTypes=[ 15 | // Allow for a range of spot instance types 16 | ['r5.4xlarge', 'r7i.4xlarge', 'r6i.4xlarge'], 17 | ], 18 | hubs=['staging', 'prod'], 19 | notebookGPUNodeGroups=[ 20 | { 21 | instanceType: 'g4dn.xlarge', 22 | }, 23 | ], 24 | nodeGroupGenerations=['f'] 25 | ); 26 | c 27 | -------------------------------------------------------------------------------- /eksctl/smithsonian.jsonnet: -------------------------------------------------------------------------------- 1 | local cluster = import './libsonnet/cluster.jsonnet'; 2 | 3 | local c = cluster.makeCluster( 4 | name='smithsonian', 5 | region='us-east-2', 6 | nodeAz='us-east-2b', 7 | version='1.34', 8 | coreNodeInstanceType='r8i-flex.large', 9 | notebookCPUInstanceTypes=[ 10 | 'r5.xlarge', 11 | 'r5.4xlarge', 12 | 'r5.16xlarge', 13 | ], 14 | daskInstanceTypes=[ 15 | // Allow for a range of spot instance types 16 | ['r5.4xlarge', 'r7i.4xlarge', 'r6i.4xlarge'], 17 | ], 18 | hubs=['staging', 'prod'], 19 | notebookGPUNodeGroups=[ 20 | { 21 | instanceType: 'g4dn.xlarge', 22 | }, 23 | ], 24 | nodeGroupGenerations=['c'] 25 | ); 26 | c 27 | -------------------------------------------------------------------------------- /config/clusters/dubois/support.values.yaml: -------------------------------------------------------------------------------- 1 | prometheusIngressAuthSecret: 2 | enabled: true 3 | 4 | prometheus: 5 | server: 6 | ingress: 7 | enabled: true 8 | hosts: 9 | - prometheus.dubois.2i2c.cloud 10 | tls: 11 | - secretName: prometheus-tls 12 | hosts: 13 | - prometheus.dubois.2i2c.cloud 14 | 15 | grafana: 16 | grafana.ini: 17 | server: 18 | root_url: https://grafana.dubois.2i2c.cloud/ 19 | auth.github: 20 | enabled: true 21 | allowed_organizations: 2i2c-org 22 | ingress: 23 | hosts: 24 | - grafana.dubois.2i2c.cloud 25 | tls: 26 | - secretName: grafana-tls 27 | hosts: 28 | - grafana.dubois.2i2c.cloud 29 | -------------------------------------------------------------------------------- /config/clusters/projectpythia/staging.values.yaml: -------------------------------------------------------------------------------- 1 | nfs: 2 | pv: 3 | serverIP: 10.100.17.202 4 | jupyterhub-home-nfs: 5 | eks: 6 | volumeId: vol-039e18f9304722450 7 | 8 | 9 | jupyterhub: 10 | ingress: 11 | hosts: [staging.projectpythia.2i2c.cloud] 12 | tls: 13 | - hosts: [staging.projectpythia.2i2c.cloud] 14 | secretName: https-auto-tls 15 | custom: 16 | homepage: 17 | templateVars: 18 | org: 19 | name: projectpythia staging 20 | singleuser: 21 | nodeSelector: 22 | 2i2c/hub-name: staging 23 | hub: 24 | config: 25 | GitHubOAuthenticator: 26 | oauth_callback_url: https://staging.projectpythia.2i2c.cloud/hub/oauth_callback 27 | -------------------------------------------------------------------------------- /eksctl/aimatx-2i2c-hub.jsonnet: -------------------------------------------------------------------------------- 1 | local cluster = import './libsonnet/cluster.jsonnet'; 2 | 3 | local c = cluster.makeCluster( 4 | name='aimatx-2i2c-hub', 5 | region='us-west-2', 6 | nodeAz='us-west-2a', 7 | version='1.34', 8 | coreNodeInstanceType='r8i-flex.large', 9 | notebookCPUInstanceTypes=[ 10 | 'r5.xlarge', 11 | 'r5.4xlarge', 12 | 'r5.16xlarge', 13 | ], 14 | daskInstanceTypes=[ 15 | // Allow for a range of spot instance types 16 | ['r5.4xlarge', 'r7i.4xlarge', 'r6i.4xlarge'], 17 | ], 18 | hubs=['staging', 'prod'], 19 | notebookGPUNodeGroups=[ 20 | { 21 | instanceType: 'g4dn.xlarge', 22 | }, 23 | ], 24 | nodeGroupGenerations=['a'], 25 | ); 26 | 27 | c 28 | -------------------------------------------------------------------------------- /eksctl/nasa-veda.jsonnet: -------------------------------------------------------------------------------- 1 | local cluster = import './libsonnet/cluster.jsonnet'; 2 | 3 | local c = cluster.makeCluster( 4 | name='nasa-veda', 5 | region='us-west-2', 6 | nodeAz='us-west-2a', 7 | version='1.34', 8 | coreNodeInstanceType='r8i-flex.large', 9 | notebookCPUInstanceTypes=[ 10 | 'r5.xlarge', 11 | 'r5.4xlarge', 12 | 'r5.16xlarge', 13 | ], 14 | daskInstanceTypes=[ 15 | // Allow for a range of spot instance types 16 | ['r5.4xlarge', 'r7i.4xlarge', 'r6i.4xlarge'], 17 | ], 18 | hubs=['staging', 'prod', 'binder'], 19 | notebookGPUNodeGroups=[ 20 | { 21 | instanceType: 'g4dn.xlarge', 22 | }, 23 | ], 24 | nodeGroupGenerations=['d'], 25 | ); 26 | 27 | c 28 | -------------------------------------------------------------------------------- /eksctl/temple.jsonnet: -------------------------------------------------------------------------------- 1 | local cluster = import './libsonnet/cluster.jsonnet'; 2 | 3 | local c = cluster.withNodeGroupConfigOverride( 4 | cluster.makeCluster( 5 | name='temple', 6 | region='us-west-2', 7 | nodeAz='us-west-2a', 8 | version='1.34', 9 | coreNodeInstanceType='r8i-flex.large', 10 | notebookCPUInstanceTypes=[ 11 | 'r5.xlarge', 12 | 'r5.4xlarge', 13 | 'r5.16xlarge', 14 | ], 15 | hubs=['staging', 'prod', 'advanced', 'research'], 16 | notebookGPUNodeGroups=[ 17 | { 18 | instanceType: 'g4dn.xlarge', 19 | }, 20 | ], 21 | nodeGroupGenerations=['a'] 22 | ), 23 | kind='core', 24 | overrides={ maxSize: 2 } 25 | ); 26 | 27 | c 28 | -------------------------------------------------------------------------------- /eksctl/victor.jsonnet: -------------------------------------------------------------------------------- 1 | local cluster = import './libsonnet/cluster.jsonnet'; 2 | 3 | local c = cluster.makeCluster( 4 | name='victor', 5 | region='us-west-2', 6 | nodeAz='us-west-2a', 7 | version='1.34', 8 | coreNodeInstanceType='r8i-flex.large', 9 | notebookCPUInstanceTypes=[ 10 | 'r5.xlarge', 11 | 'r5.4xlarge', 12 | 'r5.16xlarge', 13 | ], 14 | daskInstanceTypes=[ 15 | // Allow for a range of spot instance types 16 | ['r5.4xlarge', 'r7i.4xlarge', 'r6i.4xlarge'], 17 | ], 18 | hubs=[ 19 | 'staging', 20 | 'prod', 21 | ], 22 | notebookGPUNodeGroups=[ 23 | { 24 | instanceType: 'g4dn.xlarge', 25 | }, 26 | ], 27 | nodeGroupGenerations=['b'] 28 | ); 29 | c 30 | -------------------------------------------------------------------------------- /config/clusters/utoronto/default-staging.values.yaml: -------------------------------------------------------------------------------- 1 | jupyterhub: 2 | singleuser: 3 | image: 4 | name: quay.io/2i2c/utoronto-image 5 | tag: fbad32f53fb4 6 | ingress: 7 | hosts: [staging.utoronto.2i2c.cloud] 8 | tls: 9 | - hosts: [staging.utoronto.2i2c.cloud] 10 | secretName: https-auto-tls 11 | hub: 12 | config: 13 | CILogonOAuthenticator: 14 | oauth_callback_url: https://staging.utoronto.2i2c.cloud/hub/oauth_callback 15 | db: 16 | pvc: 17 | # limit was increased because of https://github.com/2i2c-org/infrastructure/issues/2288 18 | # should be removed once https://github.com/2i2c-org/infrastructure/issues/1860 is fixed 19 | storage: 5Gi 20 | -------------------------------------------------------------------------------- /config/clusters/awi-ciroh/support.values.yaml: -------------------------------------------------------------------------------- 1 | prometheusIngressAuthSecret: 2 | enabled: true 3 | 4 | grafana: 5 | grafana.ini: 6 | server: 7 | root_url: https://grafana.ciroh.awi.2i2c.cloud/ 8 | auth.github: 9 | enabled: true 10 | allowed_organizations: 2i2c-org 11 | ingress: 12 | hosts: 13 | - grafana.ciroh.awi.2i2c.cloud 14 | tls: 15 | - secretName: grafana-tls 16 | hosts: 17 | - grafana.ciroh.awi.2i2c.cloud 18 | 19 | prometheus: 20 | server: 21 | ingress: 22 | enabled: true 23 | hosts: 24 | - prometheus.ciroh.awi.2i2c.cloud 25 | tls: 26 | - secretName: prometheus-tls 27 | hosts: 28 | - prometheus.ciroh.awi.2i2c.cloud 29 | -------------------------------------------------------------------------------- /eksctl/opensci.jsonnet: -------------------------------------------------------------------------------- 1 | local cluster = import './libsonnet/cluster.jsonnet'; 2 | 3 | local c = cluster.makeCluster( 4 | name='opensci', 5 | region='us-west-2', 6 | nodeAz='us-west-2a', 7 | version='1.34', 8 | coreNodeInstanceType='r8i-flex.large', 9 | notebookCPUInstanceTypes=[ 10 | 'r5.xlarge', 11 | 'r5.4xlarge', 12 | 'r5.16xlarge', 13 | ], 14 | daskInstanceTypes=[ 15 | // Allow for a range of spot instance types 16 | ['r5.4xlarge', 'r7i.4xlarge', 'r6i.4xlarge'], 17 | ], 18 | hubs=[ 19 | 'staging', 20 | 'sciencecore', 21 | 'climaterisk', 22 | 'small-binder', 23 | 'big-binder', 24 | ], 25 | notebookGPUNodeGroups=[], 26 | nodeGroupGenerations=['b'] 27 | ); 28 | 29 | c 30 | -------------------------------------------------------------------------------- /eksctl/template.jsonnet: -------------------------------------------------------------------------------- 1 | local cluster = import './libsonnet/cluster.jsonnet'; 2 | 3 | local c = cluster.makeCluster( 4 | name='<< cluster_name >>', 5 | region='<< cluster_region >>', 6 | nodeAz='<< cluster_region >>a', 7 | version='1.34', 8 | coreNodeInstanceType='r8i-flex.large', 9 | notebookCPUInstanceTypes=[ 10 | 'r5.xlarge', 11 | 'r5.4xlarge', 12 | 'r5.16xlarge', 13 | ], 14 | daskInstanceTypes=[ 15 | // Allow for a range of spot instance types 16 | ['r5.4xlarge', 'r7i.4xlarge', 'r6i.4xlarge'], 17 | ], 18 | hubs=[ 19 | <%- for hub in hubs -%> 20 | '<< hub >>', 21 | <%- endfor -%> 22 | ], 23 | notebookGPUNodeGroups=[], 24 | nodeGroupGenerations=['a'] 25 | ); 26 | 27 | c 28 | -------------------------------------------------------------------------------- /helm-charts/basehub/templates/configmap-cluster-info.yaml: -------------------------------------------------------------------------------- 1 | kind: ConfigMap 2 | apiVersion: v1 3 | metadata: 4 | name: basehub-cluster-info 5 | labels: 6 | helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} 7 | app.kubernetes.io/name: basehub 8 | app.kubernetes.io/instance: {{ .Release.Name }} 9 | app.kubernetes.io/managed-by: {{ .Release.Service }} 10 | data: 11 | {{- $k8s_dist := "" }} 12 | {{- if (.Capabilities.KubeVersion.Version | contains "gke") }} 13 | {{- $k8s_dist = "gke" }} 14 | {{- else if (.Capabilities.KubeVersion.Version | contains "eks") }} 15 | {{- $k8s_dist = "eks" }} 16 | {{- else }} 17 | {{- $k8s_dist = "aks" }} 18 | {{- end }} 19 | K8S_DIST: {{ $k8s_dist }} 20 | -------------------------------------------------------------------------------- /config/clusters/2i2c-jetstream2/support.values.yaml: -------------------------------------------------------------------------------- 1 | prometheusIngressAuthSecret: 2 | enabled: true 3 | 4 | prometheus: 5 | server: 6 | ingress: 7 | enabled: true 8 | hosts: 9 | - prometheus.staging.js.2i2c.cloud 10 | tls: 11 | - secretName: prometheus-tls 12 | hosts: 13 | - prometheus.staging.js.2i2c.cloud 14 | 15 | grafana: 16 | grafana.ini: 17 | server: 18 | root_url: https://grafana.staging.js.2i2c.cloud/ 19 | auth.github: 20 | enabled: true 21 | allowed_organizations: 2i2c-org 22 | ingress: 23 | hosts: 24 | - grafana.staging.js.2i2c.cloud 25 | tls: 26 | - secretName: grafana-tls 27 | hosts: 28 | - grafana.staging.js.2i2c.cloud 29 | -------------------------------------------------------------------------------- /eksctl/2i2c-aws-us.jsonnet: -------------------------------------------------------------------------------- 1 | local cluster = import './libsonnet/cluster.jsonnet'; 2 | 3 | local c = cluster.makeCluster( 4 | name='2i2c-aws-us', 5 | region='us-west-2', 6 | nodeAz='us-west-2a', 7 | version='1.34', 8 | coreNodeInstanceType='r8i-flex.large', 9 | notebookCPUInstanceTypes=[ 10 | 'r5.xlarge', 11 | 'r5.4xlarge', 12 | 'r5.16xlarge', 13 | ], 14 | daskInstanceTypes=[ 15 | // Allow for a range of spot instance types 16 | ['r5.4xlarge', 'r7i.4xlarge', 'r6i.4xlarge'], 17 | ], 18 | hubs=[ 19 | 'staging', 20 | 'showcase', 21 | ], 22 | notebookGPUNodeGroups=[ 23 | { 24 | instanceType: 'g4dn.xlarge', 25 | }, 26 | ], 27 | nodeGroupGenerations=['b'] 28 | ); 29 | 30 | c 31 | -------------------------------------------------------------------------------- /.sops.yaml: -------------------------------------------------------------------------------- 1 | creation_rules: 2 | - path_regex: .*secret.* 3 | gcp_kms: projects/two-eye-two-see/locations/global/keyRings/sops-keys/cryptoKeys/similar-hubs 4 | - path_regex: .*/eksctl/ssh-keys/.* 5 | gcp_kms: projects/two-eye-two-see/locations/global/keyRings/sops-keys/cryptoKeys/similar-hubs 6 | - path_regex: deployer/keys/.*key.* 7 | gcp_kms: projects/two-eye-two-see/locations/global/keyRings/sops-keys/cryptoKeys/similar-hubs 8 | 9 | # stores configuration is supported by sops 3.9.0+ only 10 | stores: 11 | # By configuring json indent, we get spaces instead of tabs for json files, 12 | # which makes them valid YAML files as well. 13 | json: 14 | indent: 4 15 | json_binary: 16 | indent: 4 17 | yaml: 18 | indent: 2 19 | -------------------------------------------------------------------------------- /config/clusters/oceanhackweek/prod.values.yaml: -------------------------------------------------------------------------------- 1 | nfs: 2 | pv: 3 | serverIP: 10.100.253.138 4 | shareCreator: 5 | enabled: false 6 | 7 | userServiceAccount: 8 | annotations: 9 | eks.amazonaws.com/role-arn: arn:aws:iam::221106934874:role/oceanhackweek-prod 10 | 11 | jupyterhub: 12 | singleuser: 13 | nodeSelector: 14 | 2i2c/hub-name: prod 15 | ingress: 16 | hosts: [oceanhackweek.2i2c.cloud] 17 | tls: 18 | - hosts: [oceanhackweek.2i2c.cloud] 19 | secretName: https-auto-tls 20 | hub: 21 | config: 22 | GitHubOAuthenticator: 23 | oauth_callback_url: https://oceanhackweek.2i2c.cloud/hub/oauth_callback 24 | 25 | jupyterhub-home-nfs: 26 | eks: 27 | volumeId: vol-0977ec2bf457215f0 28 | 29 | -------------------------------------------------------------------------------- /helm-charts/support/templates/storageclass/gke.yaml: -------------------------------------------------------------------------------- 1 | # https://cloud.google.com/kubernetes-engine/docs/how-to/persistent-volumes/gce-pd-csi-driver#create_a_storageclass 2 | # has more information about setting up StorageClass for GCP PD CSI Driver, 3 | # for use in GKE environments. 4 | {{- if .Values.prometheusStorageClass.gke.enabled }} 5 | allowVolumeExpansion: true 6 | apiVersion: storage.k8s.io/v1 7 | kind: StorageClass 8 | metadata: 9 | name: {{ .Values.prometheusStorageClass.gke.name }} 10 | parameters: {{ .Values.prometheusStorageClass.gke.parameters | toJson }} 11 | provisioner: pd.csi.storage.gke.io 12 | # Don't delete the backing disk when the PVC is deleted 13 | reclaimPolicy: Retain 14 | volumeBindingMode: WaitForFirstConsumer 15 | {{- end }} 16 | -------------------------------------------------------------------------------- /config/clusters/projectpythia/prod.values.yaml: -------------------------------------------------------------------------------- 1 | nfs: 2 | pv: 3 | serverIP: 10.100.18.124 4 | jupyterhub-home-nfs: 5 | eks: 6 | volumeId: vol-0cdc25a68ca0303ce 7 | quotaEnforcer: 8 | config: 9 | QuotaManager: 10 | hard_quota: 2 # in GiB 11 | jupyterhub: 12 | ingress: 13 | hosts: [projectpythia.2i2c.cloud] 14 | tls: 15 | - hosts: [projectpythia.2i2c.cloud] 16 | secretName: https-auto-tls 17 | custom: 18 | homepage: 19 | templateVars: 20 | org: 21 | name: ProjectPythia 22 | singleuser: 23 | nodeSelector: 24 | 2i2c/hub-name: prod 25 | hub: 26 | config: 27 | GitHubOAuthenticator: 28 | oauth_callback_url: https://projectpythia.2i2c.cloud/hub/oauth_callback 29 | -------------------------------------------------------------------------------- /config/clusters/dubois/ephemeral.values.yaml: -------------------------------------------------------------------------------- 1 | jupyterhub: 2 | ingress: 3 | hosts: [dubois.2i2c.cloud] 4 | tls: 5 | - hosts: [dubois.2i2c.cloud] 6 | secretName: https-auto-tls 7 | hub: 8 | config: 9 | JupyterHub: 10 | authenticator_class: tmp 11 | Authenticator: 12 | allow_all: true 13 | custom: 14 | singleuserAdmin: 15 | # Turn off trying to mount shared-readwrite folder for admins 16 | extraVolumeMounts: [] 17 | singleuser: 18 | initContainers: [] 19 | storage: 20 | # No persistent storage should be kept to reduce any potential data 21 | # retention & privacy issues. 22 | type: none 23 | extraVolumeMounts: [] 24 | 25 | jupyterhub-home-nfs: 26 | enabled: false 27 | -------------------------------------------------------------------------------- /terraform/gcp/filestore.tf: -------------------------------------------------------------------------------- 1 | resource "google_filestore_instance" "homedirs" { 2 | for_each = var.filestores 3 | 4 | name = each.value.name_suffix == null ? "${var.prefix}-homedirs" : "${var.prefix}-homedirs-${each.value.name_suffix}" 5 | location = var.zone 6 | tier = each.value.tier 7 | project = var.project_id 8 | 9 | lifecycle { 10 | # Additional safeguard against deleting the filestore 11 | # as this causes irreversible data loss! 12 | prevent_destroy = true 13 | } 14 | 15 | file_shares { 16 | capacity_gb = each.value.capacity_gb 17 | name = "homes" 18 | source_backup = each.value.source_backup 19 | } 20 | 21 | networks { 22 | network = "default" 23 | modes = ["MODE_IPV4"] 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /terraform/openstack/projects/2i2c-jetstream2.tfvars: -------------------------------------------------------------------------------- 1 | prefix = "two-eye-two-see" 2 | 3 | notebook_nodes = { 4 | "m3.quad" : { 5 | min : 1, 6 | max : 100, 7 | # 4 CPU, 15 RAM 8 | # https://docs.jetstream-cloud.org/general/instance-flavors/#jetstream2-cpu 9 | machine_type : "m3.quad", 10 | # We list the required labels here but unfortunately they have no effect 11 | # because of a bug in the Magnum CAPI driver 12 | labels = { 13 | "hub.jupyter.org/node-purpose" = "user", 14 | "k8s.dask.org/node-purpose" = "scheduler", 15 | } 16 | }, 17 | } 18 | 19 | persistent_disks = { 20 | "staging" = { 21 | size = 100 # in GB 22 | name_suffix = "staging" 23 | tags = { "2i2c:hub-name" : "staging" } 24 | } 25 | } -------------------------------------------------------------------------------- /config/clusters/cloudbank/support.values.yaml: -------------------------------------------------------------------------------- 1 | prometheusIngressAuthSecret: 2 | enabled: true 3 | 4 | prometheus: 5 | server: 6 | persistentVolume: 7 | size: 750Gi 8 | ingress: 9 | enabled: true 10 | hosts: 11 | - prometheus.cloudbank.2i2c.cloud 12 | tls: 13 | - secretName: prometheus-tls 14 | hosts: 15 | - prometheus.cloudbank.2i2c.cloud 16 | 17 | grafana: 18 | grafana.ini: 19 | server: 20 | root_url: https://grafana.cloudbank.2i2c.cloud/ 21 | auth.github: 22 | enabled: true 23 | allowed_organizations: 2i2c-org 24 | ingress: 25 | hosts: 26 | - grafana.cloudbank.2i2c.cloud 27 | tls: 28 | - secretName: grafana-tls 29 | hosts: 30 | - grafana.cloudbank.2i2c.cloud 31 | -------------------------------------------------------------------------------- /config/clusters/oceanhackweek/staging.values.yaml: -------------------------------------------------------------------------------- 1 | nfs: 2 | pv: 3 | serverIP: 10.100.126.145 4 | shareCreator: 5 | enabled: false 6 | 7 | userServiceAccount: 8 | annotations: 9 | eks.amazonaws.com/role-arn: arn:aws:iam::221106934874:role/oceanhackweek-staging 10 | 11 | jupyterhub: 12 | singleuser: 13 | nodeSelector: 14 | 2i2c/hub-name: staging 15 | ingress: 16 | hosts: [staging.oceanhackweek.2i2c.cloud] 17 | tls: 18 | - hosts: [staging.oceanhackweek.2i2c.cloud] 19 | secretName: https-auto-tls 20 | hub: 21 | config: 22 | GitHubOAuthenticator: 23 | oauth_callback_url: https://staging.oceanhackweek.2i2c.cloud/hub/oauth_callback 24 | 25 | jupyterhub-home-nfs: 26 | eks: 27 | volumeId: vol-059030d09d8f3ddf7 28 | 29 | -------------------------------------------------------------------------------- /docs/hub-deployment-guide/configure-auth/index.md: -------------------------------------------------------------------------------- 1 | (enable-auth-provider)= 2 | # Enable authentication 3 | 4 | This section describes how to set up various authentication providers for the 2i2c JupyterHubs. 5 | 6 | ```{admonition} Switching auth 7 | Switching authentication providers (e.g. from GitHub to Google) for a pre-existing hub will simply create new usernames. Any pre-existing users will no longer be able to access their accounts (although administrators will be able to do so). If you have pre-existing users and want to switch the hub authentication, rename the users to the new auth pattern (e.g. convert github handles to emails). 8 | ``` 9 | 10 | ```{toctree} 11 | :maxdepth: 2 12 | :caption: Authentication Providers 13 | github-orgs 14 | cilogon 15 | auth0 16 | shared-password 17 | ``` 18 | -------------------------------------------------------------------------------- /helm-charts/basehub/templates/static/configmap.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.staticWebsite.enabled -}} 2 | kind: ConfigMap 3 | apiVersion: v1 4 | metadata: 5 | name: static-sites 6 | labels: 7 | app: static-sites 8 | data: 9 | nginx.conf: | 10 | server { 11 | listen 8080; 12 | absolute_redirect off; 13 | 14 | # We enforce path to *not* have a trailing slash via the helm chart schema 15 | location {{ .Values.staticWebsite.ingress.path }}/ { 16 | index index.html; 17 | alias /srv/content/repo/; 18 | } 19 | 20 | # If there's no trailing slash, just redirect it to trailing slash 21 | location {{ .Values.staticWebsite.ingress.path }} { 22 | return 301 {{ .Values.staticWebsite.ingress.path }}/; 23 | } 24 | } 25 | {{- end }} 26 | -------------------------------------------------------------------------------- /helm-charts/basehub/templates/nfs.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.nfs.enabled -}} 2 | apiVersion: v1 3 | kind: PersistentVolume 4 | metadata: 5 | name: {{ .Release.Name }}-home-nfs 6 | spec: 7 | capacity: 8 | storage: 1Mi 9 | accessModes: 10 | - ReadWriteMany 11 | nfs: 12 | server: {{ .Values.nfs.pv.serverIP | quote }} 13 | path: "{{ .Values.nfs.pv.baseShareName }}{{ .Values.nfs.pv.shareNameOverride | default .Release.Name }}" 14 | mountOptions: {{ .Values.nfs.pv.mountOptions | toJson }} 15 | --- 16 | apiVersion: v1 17 | kind: PersistentVolumeClaim 18 | metadata: 19 | name: home-nfs 20 | spec: 21 | accessModes: 22 | - ReadWriteMany 23 | volumeName: {{ .Release.Name }}-home-nfs 24 | storageClassName: "" 25 | resources: 26 | requests: 27 | storage: 1Mi 28 | {{- end }} 29 | -------------------------------------------------------------------------------- /config/clusters/utoronto/r-common.values.yaml: -------------------------------------------------------------------------------- 1 | jupyterhub: 2 | custom: 3 | homepage: 4 | templateVars: 5 | # This sets the default selected interface option 6 | default_url: /rstudio 7 | hub: 8 | config: 9 | KubeSpawner: 10 | # Ensures container working dir is homedir 11 | # https://github.com/2i2c-org/infrastructure/issues/2559 12 | working_dir: /home/rstudio 13 | Authenticator: 14 | admin_users: 15 | # 2i2c staff below, a list maintained in default-common r-common 16 | - yuvi.panda@utoronto.ca 17 | - georgiana.elena@utoronto.ca 18 | - chris.holdgraf@utoronto.ca 19 | singleuser: 20 | defaultUrl: /rstudio 21 | image: 22 | name: quay.io/2i2c/utoronto-r-image 23 | tag: c1a912491c87 24 | -------------------------------------------------------------------------------- /helm-charts/basehub/templates/dex/secret.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.dex.enabled -}} 2 | apiVersion: v1 3 | kind: Secret 4 | metadata: 5 | name: dex 6 | type: Opaque 7 | stringData: 8 | {{- $k8sState := lookup "v1" "Secret" .Release.Namespace "dex" | default (dict "data" (dict)) }} 9 | 10 | {{- if hasKey $k8sState.data "oauth2Proxy.clientSecret" }} 11 | oauth2Proxy.clientSecret: {{ index $k8sState.data "oauth2Proxy.clientSecret" | b64dec }} 12 | {{- else }} 13 | oauth2Proxy.clientSecret: {{ include "randHex" 64 }} 14 | {{- end }} 15 | 16 | {{- if hasKey $k8sState.data "oauth2Proxy.cookieSecret" }} 17 | oauth2Proxy.cookieSecret: {{ index $k8sState.data "oauth2Proxy.cookieSecret" | b64dec }} 18 | {{- else }} 19 | oauth2Proxy.cookieSecret: {{ include "randHex" 16 }} 20 | {{- end }} 21 | {{- end }} 22 | -------------------------------------------------------------------------------- /eksctl/openscapeshub.jsonnet: -------------------------------------------------------------------------------- 1 | local cluster = import './libsonnet/cluster.jsonnet'; 2 | 3 | local c = cluster.withNodeGroupConfigOverride( 4 | cluster.makeCluster( 5 | name='openscapeshub', 6 | region='us-west-2', 7 | nodeAz='us-west-2b', 8 | version='1.34', 9 | coreNodeInstanceType='r8i-flex.large', 10 | notebookCPUInstanceTypes=[ 11 | 'r5.xlarge', 12 | 'r5.4xlarge', 13 | 'r5.16xlarge', 14 | ], 15 | daskInstanceTypes=[ 16 | // Allow for a range of spot instance types 17 | ['r5.4xlarge', 'r7i.4xlarge', 'r6i.4xlarge'], 18 | ], 19 | hubs=[ 20 | 'staging', 21 | 'prod', 22 | 'workshop', 23 | ], 24 | notebookGPUNodeGroups=[], 25 | nodeGroupGenerations=['d'] 26 | ), kind='core', overrides={ maxSize: 2 } 27 | ); 28 | c 29 | -------------------------------------------------------------------------------- /config/clusters/temple/prod.values.yaml: -------------------------------------------------------------------------------- 1 | nfs: 2 | pv: 3 | serverIP: 10.100.192.99 4 | jupyterhub-home-nfs: 5 | eks: 6 | volumeId: vol-0e89a2ab60575e25a 7 | jupyterhub: 8 | hub: 9 | config: 10 | CILogonOAuthenticator: 11 | oauth_callback_url: https://temple.2i2c.cloud/hub/oauth_callback 12 | singleuser: 13 | nodeSelector: 14 | 2i2c/hub-name: prod 15 | ingress: 16 | hosts: 17 | - temple.2i2c.cloud 18 | tls: 19 | - secretName: https-auto-tls 20 | hosts: 21 | - temple.2i2c.cloud 22 | binderhub-service: 23 | dockerApi: 24 | nodeSelector: 25 | 2i2c/hub-name: prod 26 | config: 27 | KubernetesBuildExecutor: 28 | node_selector: 29 | 2i2c/hub-name: prod 30 | BinderHub: 31 | image_prefix: quay.io/imagebuilding-non-gcp-hubs/temple-prod- 32 | -------------------------------------------------------------------------------- /docs/howto/features/index.md: -------------------------------------------------------------------------------- 1 | (hub-features)= 2 | 3 | # Enable specific hub features 4 | 5 | There are several extra features and services that can be enabled on the 2i2c JupyterHubs. 6 | These add extra functionality, connect with cloud services, etc. 7 | See the sections below for more details. 8 | 9 | ```{toctree} 10 | :maxdepth: 2 11 | allow-unlisted-profile-choice.md 12 | profile-list-restrict.md 13 | anonymized-usernames.md 14 | binderhub-ui.md 15 | buckets.md 16 | cloud-access.md 17 | cryptnono.md 18 | dask.md 19 | dedicated-nodepool.md 20 | ephemeral.md 21 | github.md 22 | git-pull.md 23 | gpu.md 24 | identity-provider.md 25 | image.md 26 | imagebuilding.md 27 | login-page.md 28 | per-user-db.md 29 | private-nbgitpuller.md 30 | rocker.md 31 | shared-db.md 32 | static-sites.md 33 | storage-quota.md 34 | community-docs.md 35 | ``` 36 | -------------------------------------------------------------------------------- /config/clusters/2i2c-aws-us/daskhub-common.values.yaml: -------------------------------------------------------------------------------- 1 | basehub: 2 | nfs: 3 | enabled: true 4 | pv: 5 | enabled: true 6 | # from https://docs.aws.amazon.com/efs/latest/ug/mounting-fs-nfs-mount-settings.html 7 | mountOptions: 8 | - rsize=1048576 9 | - wsize=1048576 10 | - timeo=600 11 | - soft # We pick soft over hard, so NFS lockups don't lead to hung processes 12 | - retrans=2 13 | - noresvport 14 | 15 | dask-gateway: 16 | enabled: true 17 | 18 | jupyterhub: 19 | scheduling: 20 | userScheduler: 21 | enabled: true 22 | custom: 23 | daskhubSetup: 24 | enabled: true 25 | singleuser: 26 | cloudMetadata: 27 | blockWithIptables: false 28 | hub: 29 | config: 30 | JupyterHub: 31 | authenticator_class: github 32 | -------------------------------------------------------------------------------- /config/clusters/leap/support.values.yaml: -------------------------------------------------------------------------------- 1 | prometheusIngressAuthSecret: 2 | enabled: true 3 | 4 | prometheus: 5 | server: 6 | ingress: 7 | enabled: true 8 | hosts: 9 | - prometheus.leap.2i2c.cloud 10 | tls: 11 | - secretName: prometheus-tls 12 | hosts: 13 | - prometheus.leap.2i2c.cloud 14 | persistentVolume: 15 | size: 500Gi 16 | resources: 17 | requests: 18 | memory: 20Gi 19 | limits: 20 | memory: 20Gi 21 | 22 | grafana: 23 | grafana.ini: 24 | server: 25 | root_url: https://grafana.leap.2i2c.cloud/ 26 | auth.github: 27 | enabled: true 28 | allowed_organizations: 2i2c-org 29 | ingress: 30 | hosts: 31 | - grafana.leap.2i2c.cloud 32 | tls: 33 | - secretName: grafana-tls 34 | hosts: 35 | - grafana.leap.2i2c.cloud 36 | -------------------------------------------------------------------------------- /helm-charts/basehub/.helmignore: -------------------------------------------------------------------------------- 1 | # Non default entries manually added by basehub developers 2 | 3 | # Ignore the .yaml that generates the .json, only the .json is relevant to 4 | # bundle with the Helm chart when it is packaged or "helm dep up" is used to 5 | # copy it over to another location where it is referenced. 6 | values.schema.yaml 7 | 8 | # ----------------------------------------------------------------------------- 9 | 10 | # Patterns to ignore when building packages. 11 | # This supports shell glob matching, relative path matching, and 12 | # negation (prefixed with !). Only one pattern per line. 13 | .DS_Store 14 | # Common VCS dirs 15 | .git/ 16 | .gitignore 17 | .bzr/ 18 | .bzrignore 19 | .hg/ 20 | .hgignore 21 | .svn/ 22 | # Common backup files 23 | *.swp 24 | *.bak 25 | *.tmp 26 | *~ 27 | # Various IDEs 28 | .project 29 | .idea/ 30 | *.tmproj 31 | -------------------------------------------------------------------------------- /helm-charts/daskhub/.helmignore: -------------------------------------------------------------------------------- 1 | # Non default entries manually added by basehub developers 2 | 3 | # Ignore the .yaml that generates the .json, only the .json is relevant to 4 | # bundle with the Helm chart when it is packaged or "helm dep up" is used to 5 | # copy it over to another location where it is referenced. 6 | values.schema.yaml 7 | 8 | # ----------------------------------------------------------------------------- 9 | 10 | # Patterns to ignore when building packages. 11 | # This supports shell glob matching, relative path matching, and 12 | # negation (prefixed with !). Only one pattern per line. 13 | .DS_Store 14 | # Common VCS dirs 15 | .git/ 16 | .gitignore 17 | .bzr/ 18 | .bzrignore 19 | .hg/ 20 | .hgignore 21 | .svn/ 22 | # Common backup files 23 | *.swp 24 | *.bak 25 | *.tmp 26 | *~ 27 | # Various IDEs 28 | .project 29 | .idea/ 30 | *.tmproj 31 | -------------------------------------------------------------------------------- /helm-charts/support/.helmignore: -------------------------------------------------------------------------------- 1 | # Non default entries manually added by support developers 2 | 3 | # Ignore the .yaml that generates the .json, only the .json is relevant to 4 | # bundle with the Helm chart when it is packaged or "helm dep up" is used to 5 | # copy it over to another location where it is referenced. 6 | values.schema.yaml 7 | 8 | # ----------------------------------------------------------------------------- 9 | 10 | # Patterns to ignore when building packages. 11 | # This supports shell glob matching, relative path matching, and 12 | # negation (prefixed with !). Only one pattern per line. 13 | .DS_Store 14 | # Common VCS dirs 15 | .git/ 16 | .gitignore 17 | .bzr/ 18 | .bzrignore 19 | .hg/ 20 | .hgignore 21 | .svn/ 22 | # Common backup files 23 | *.swp 24 | *.bak 25 | *.tmp 26 | *~ 27 | # Various IDEs 28 | .project 29 | .idea/ 30 | *.tmproj 31 | -------------------------------------------------------------------------------- /.github/workflows/comment-dependabot-prs.yaml: -------------------------------------------------------------------------------- 1 | # From https://docs.github.com/en/actions/managing-issues-and-pull-requests/commenting-on-an-issue-when-a-label-is-added 2 | name: Comment dependabot PRs with specific label 3 | on: 4 | pull_request_target: 5 | types: 6 | - labeled 7 | jobs: 8 | add-comment: 9 | if: github.event.label.name == 'requires follow-up' 10 | runs-on: ubuntu-latest 11 | permissions: 12 | pull-requests: write 13 | steps: 14 | - name: Add comment 15 | uses: peter-evans/create-or-update-comment@v5 16 | with: 17 | issue-number: ${{ github.event.number }} 18 | body: | 19 | After merging this PR, remember to take the additional manual steps described in https://infrastructure.2i2c.org/howto/image-management/custom-jupyterhub-image/#how-to-build-and-push-a-new-version-of-the-available-hub-images 20 | -------------------------------------------------------------------------------- /eksctl/nmfs-openscapes.jsonnet: -------------------------------------------------------------------------------- 1 | local cluster = import './libsonnet/cluster.jsonnet'; 2 | 3 | local c = cluster.withNodeGroupConfigOverride( 4 | cluster.makeCluster( 5 | name='nmfs-openscapes', 6 | region='us-west-2', 7 | nodeAz='us-west-2b', 8 | version='1.34', 9 | coreNodeInstanceType='r8i-flex.large', 10 | notebookCPUInstanceTypes=[ 11 | 'r5.xlarge', 12 | 'r5.4xlarge', 13 | 'r5.16xlarge', 14 | ], 15 | daskInstanceTypes=[ 16 | // Allow for a range of spot instance types 17 | ['r5.4xlarge', 'r7i.4xlarge', 'r6i.4xlarge'], 18 | ], 19 | hubs=['staging', 'prod', 'workshop', 'noaa-only'], 20 | notebookGPUNodeGroups=[ 21 | { 22 | instanceType: 'g4dn.xlarge', 23 | }, 24 | ], 25 | nodeGroupGenerations=['a', 'b'], 26 | ), 27 | kind='core', 28 | overrides={ maxSize: 2 } 29 | ); 30 | 31 | c 32 | -------------------------------------------------------------------------------- /config/clusters/reflective/support.values.yaml: -------------------------------------------------------------------------------- 1 | prometheusIngressAuthSecret: 2 | enabled: true 3 | 4 | prometheus: 5 | server: 6 | ingress: 7 | enabled: true 8 | hosts: 9 | - prometheus.reflective.2i2c.cloud 10 | tls: 11 | - secretName: prometheus-tls 12 | hosts: 13 | - prometheus.reflective.2i2c.cloud 14 | grafana: 15 | grafana.ini: 16 | server: 17 | root_url: https://grafana.reflective.2i2c.cloud/ 18 | auth.github: 19 | enabled: true 20 | allowed_organizations: 2i2c-org 21 | ingress: 22 | hosts: 23 | - grafana.reflective.2i2c.cloud 24 | tls: 25 | - secretName: grafana-tls 26 | hosts: 27 | - grafana.reflective.2i2c.cloud 28 | 29 | cluster-autoscaler: 30 | enabled: true 31 | autoDiscovery: 32 | clusterName: reflective 33 | awsRegion: us-west-2 34 | 35 | calico: 36 | enabled: true 37 | -------------------------------------------------------------------------------- /config/clusters/ubc-eoas/support.values.yaml: -------------------------------------------------------------------------------- 1 | cluster-autoscaler: 2 | enabled: true 3 | autoDiscovery: 4 | clusterName: ubc-eoas 5 | awsRegion: ca-central-1 6 | 7 | prometheusIngressAuthSecret: 8 | enabled: true 9 | 10 | grafana: 11 | grafana.ini: 12 | server: 13 | root_url: https://grafana.ubc-eoas.2i2c.cloud/ 14 | auth.github: 15 | enabled: true 16 | allowed_organizations: 2i2c-org 17 | ingress: 18 | hosts: 19 | - grafana.ubc-eoas.2i2c.cloud 20 | tls: 21 | - secretName: grafana-tls 22 | hosts: 23 | - grafana.ubc-eoas.2i2c.cloud 24 | 25 | prometheus: 26 | server: 27 | ingress: 28 | enabled: true 29 | hosts: 30 | - prometheus.ubc-eoas.2i2c.cloud 31 | tls: 32 | - secretName: prometheus-tls 33 | hosts: 34 | - prometheus.ubc-eoas.2i2c.cloud 35 | 36 | calico: 37 | enabled: true 38 | -------------------------------------------------------------------------------- /terraform/aws/ebs-volumes.tf: -------------------------------------------------------------------------------- 1 | resource "aws_ebs_volume" "nfs_home_dirs" { 2 | for_each = var.ebs_volumes 3 | 4 | availability_zone = var.cluster_nodes_location 5 | size = each.value.size 6 | type = each.value.type 7 | iops = each.value.iops 8 | encrypted = true 9 | 10 | tags = merge(each.value.tags, { 11 | Name = each.value.name_suffix == null ? "hub-nfs-home-dirs" : "hub-nfs-home-dirs-${each.value.name_suffix}" 12 | "2i2c:volume-purpose" = "home-nfs" 13 | NFSBackup = var.enable_nfs_backup ? "true" : "false" # Tag to identify volumes to backup by Data Lifecycle Manager (DLM) 14 | }) 15 | 16 | lifecycle { 17 | prevent_destroy = true 18 | } 19 | } 20 | 21 | output "ebs_volume_id_map" { 22 | value = { for vol in values(aws_ebs_volume.nfs_home_dirs)[*] : vol.tags["Name"] => vol.id } 23 | } 24 | -------------------------------------------------------------------------------- /terraform/uptime-checks/pagerduty.tf: -------------------------------------------------------------------------------- 1 | data "sops_file" "pagerduty_integration_key" { 2 | # Read sops encrypted file containing integration key for pagerduty 3 | source_file = "secret/enc-pagerduty-service-key.secret.yaml" 4 | } 5 | 6 | resource "google_monitoring_notification_channel" "pagerduty_hubs" { 7 | project = var.project_id 8 | display_name = "PagerDuty Managed JupyterHub service" 9 | type = "pagerduty" 10 | sensitive_labels { 11 | service_key = data.sops_file.pagerduty_integration_key.data["pagerduty.hubs"] 12 | } 13 | } 14 | 15 | resource "google_monitoring_notification_channel" "pagerduty_prometheus" { 16 | project = var.project_id 17 | display_name = "PagerDuty Prometheus services" 18 | type = "pagerduty" 19 | sensitive_labels { 20 | service_key = data.sops_file.pagerduty_integration_key.data["pagerduty.prometheus"] 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /config/clusters/smithsonian/prod.values.yaml: -------------------------------------------------------------------------------- 1 | basehub: 2 | nfs: 3 | pv: 4 | serverIP: 10.100.232.25 5 | jupyterhub-home-nfs: 6 | eks: 7 | volumeId: vol-0f45c2be7f71f07f8 8 | 9 | jupyterhub: 10 | ingress: 11 | hosts: [smithsonian.2i2c.cloud] 12 | tls: 13 | - hosts: [smithsonian.2i2c.cloud] 14 | secretName: https-auto-tls 15 | hub: 16 | config: 17 | GitHubOAuthenticator: 18 | oauth_callback_url: https://smithsonian.2i2c.cloud/hub/oauth_callback 19 | singleuser: 20 | nodeSelector: 21 | 2i2c/hub-name: prod 22 | dask-gateway: 23 | gateway: 24 | backend: 25 | scheduler: 26 | extraPodConfig: 27 | nodeSelector: 28 | 2i2c/hub-name: prod 29 | worker: 30 | extraPodConfig: 31 | nodeSelector: 32 | 2i2c/hub-name: prod 33 | -------------------------------------------------------------------------------- /helm-charts/chartpress.yaml: -------------------------------------------------------------------------------- 1 | # This is the configuration for chartpress, a CLI for Helm chart management. 2 | # 3 | # chartpress can be used to: 4 | # - Build images 5 | # - Update Chart.yaml (version) and values.yaml (image tags) 6 | # - Package and publish Helm charts to a GitHub based Helm chart repository 7 | # 8 | # For more information about chartpress, see the projects README.md file: 9 | # https://github.com/jupyterhub/chartpress 10 | # 11 | charts: 12 | - name: basehub 13 | imagePrefix: quay.io/2i2c/pilot- 14 | images: 15 | hub: 16 | valuesPath: jupyterhub.hub.image 17 | buildArgs: 18 | REQUIREMENTS_FILE: requirements.txt 19 | pkce-experiment: 20 | imageName: quay.io/2i2c/pkce-experiment 21 | buildArgs: 22 | REQUIREMENTS_FILE: pkce-requirements.txt 23 | contextPath: images/hub 24 | dockerfilePath: images/hub/Dockerfile 25 | -------------------------------------------------------------------------------- /config/clusters/nasa-ghg-hub/support.values.yaml: -------------------------------------------------------------------------------- 1 | prometheusIngressAuthSecret: 2 | enabled: true 3 | 4 | cluster-autoscaler: 5 | enabled: true 6 | autoDiscovery: 7 | clusterName: nasa-ghg-hub 8 | awsRegion: us-west-2 9 | 10 | grafana: 11 | grafana.ini: 12 | server: 13 | root_url: https://grafana.nasa-ghg.2i2c.cloud/ 14 | auth.github: 15 | enabled: true 16 | allowed_organizations: 2i2c-org us-ghg-center 17 | ingress: 18 | hosts: 19 | - grafana.nasa-ghg.2i2c.cloud 20 | tls: 21 | - secretName: grafana-tls 22 | hosts: 23 | - grafana.nasa-ghg.2i2c.cloud 24 | 25 | prometheus: 26 | server: 27 | ingress: 28 | enabled: true 29 | hosts: 30 | - prometheus.nasa-ghg.2i2c.cloud 31 | tls: 32 | - secretName: prometheus-tls 33 | hosts: 34 | - prometheus.nasa-ghg.2i2c.cloud 35 | 36 | calico: 37 | enabled: true 38 | -------------------------------------------------------------------------------- /config/clusters/ubc-eoas/cluster.yaml: -------------------------------------------------------------------------------- 1 | name: ubc-eoas 2 | provider: aws 3 | provider_url: https://2i2c.awsapps.com/start#/ 4 | aws: 5 | account: 259060176665 6 | key: enc-deployer-credentials.secret.json 7 | clusterType: eks 8 | clusterName: ubc-eoas 9 | region: ca-central-1 10 | billing: 11 | paid_by_us: true 12 | support: 13 | helm_chart_values_files: 14 | - support.values.yaml 15 | - enc-support.secret.values.yaml 16 | hubs: 17 | - name: staging 18 | display_name: UBC EOAS (staging) 19 | domain: staging.ubc-eoas.2i2c.cloud 20 | helm_chart: basehub 21 | helm_chart_values_files: 22 | - common.values.yaml 23 | - staging.values.yaml 24 | - enc-staging.secret.values.yaml 25 | - name: prod 26 | display_name: UBC EOAS 27 | domain: ubc-eoas.2i2c.cloud 28 | helm_chart: basehub 29 | helm_chart_values_files: 30 | - common.values.yaml 31 | - prod.values.yaml 32 | - enc-prod.secret.values.yaml 33 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line, and also 5 | # from the environment for the first two. 6 | SPHINXOPTS ?= 7 | SPHINXBUILD ?= sphinx-build 8 | SOURCEDIR = . 9 | BUILDDIR = _build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # keep --ignore entries in sync with content in noxfile.py 18 | live: 19 | sphinx-autobuild --ignore "*/_build/*" --ignore "*/tmp/*" --ignore "*/*.json" --ignore "*/*.csv" -b dirhtml -n . _build/dirhtml 20 | 21 | # Catch-all target: route all unknown targets to Sphinx using the new 22 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 23 | %: Makefile 24 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 25 | -------------------------------------------------------------------------------- /docs/howto/prepare-for-events/index.md: -------------------------------------------------------------------------------- 1 | # Manage events on 2i2c hubs 2 | 3 | A hub's specific setup is usually optimized based on the day to day usage expectations. But because events usually imply a different usage pattern, the infrastructure might need to be adjusted in order to accommodate the spikes in activity. 4 | 5 | ```{important} 6 | The communities we serve have the responsibility to notify us about an event they have planned on a 2i2c hub [at least three weeks before](https://docs.2i2c.org/community/events/#notify-the-2i2c-team-about-the-event) the event will start. This should allow us enough time to plan and prepare the infrastructure for the event properly if needed. 7 | ``` 8 | 9 | The events might vary in type, so the following list is not complete and does not cover all of them (yet). Most common event types are exams, workshops etc. 10 | 11 | ```{toctree} 12 | :maxdepth: 2 13 | event-prep.md 14 | exam.md 15 | ``` 16 | -------------------------------------------------------------------------------- /config/clusters/smithsonian/staging.values.yaml: -------------------------------------------------------------------------------- 1 | basehub: 2 | nfs: 3 | pv: 4 | serverIP: 10.100.136.128 5 | jupyterhub-home-nfs: 6 | eks: 7 | volumeId: vol-0ec551895e93e4d59 8 | 9 | jupyterhub: 10 | ingress: 11 | hosts: [staging.smithsonian.2i2c.cloud] 12 | tls: 13 | - hosts: [staging.smithsonian.2i2c.cloud] 14 | secretName: https-auto-tls 15 | hub: 16 | config: 17 | GitHubOAuthenticator: 18 | oauth_callback_url: https://staging.smithsonian.2i2c.cloud/hub/oauth_callback 19 | singleuser: 20 | nodeSelector: 21 | 2i2c/hub-name: staging 22 | dask-gateway: 23 | gateway: 24 | backend: 25 | scheduler: 26 | extraPodConfig: 27 | nodeSelector: 28 | 2i2c/hub-name: staging 29 | worker: 30 | extraPodConfig: 31 | nodeSelector: 32 | 2i2c/hub-name: staging 33 | -------------------------------------------------------------------------------- /config/clusters/victor/cluster.yaml: -------------------------------------------------------------------------------- 1 | name: victor 2 | provider: aws 3 | provider_url: https://129856558350.signin.aws.amazon.com/console 4 | aws: 5 | account: 129856558350 6 | key: enc-deployer-credentials.secret.json 7 | clusterType: eks 8 | clusterName: victor 9 | region: us-west-2 10 | billing: 11 | paid_by_us: true 12 | support: 13 | helm_chart_values_files: 14 | - support.values.yaml 15 | - enc-support.secret.values.yaml 16 | hubs: 17 | - name: staging 18 | display_name: Victor (staging) 19 | domain: staging.hub.victorproject.org 20 | helm_chart: daskhub 21 | helm_chart_values_files: 22 | - common.values.yaml 23 | - staging.values.yaml 24 | - enc-staging.secret.values.yaml 25 | - name: prod 26 | display_name: Victor 27 | domain: hub.victorproject.org 28 | helm_chart: daskhub 29 | helm_chart_values_files: 30 | - common.values.yaml 31 | - prod.values.yaml 32 | - enc-prod.secret.values.yaml 33 | -------------------------------------------------------------------------------- /docs/sre-guide/manage-k8s/index.md: -------------------------------------------------------------------------------- 1 | # Manage cloud and Kubernetes infrastructure 2 | 3 | There are some cases where you need to inspect or modify actively-running Kubernetes infrastructure, or make changes to the Kubernetes cluster on which our hubs are running. 4 | This is a more manual step than [modifying a hub's configuration](/topic/infrastructure/config) and requires some extra tools, setup, and expertise. 5 | These sections cover how to do this. 6 | 7 | ## Get started 8 | 9 | First off, you'll need to gain access to the Kubernetes cluster. 10 | See the following section for instructions on how to do so. 11 | 12 | ```{toctree} 13 | :maxdepth: 2 14 | /topic/access-creds/cloud-auth.md 15 | ``` 16 | 17 | ## Common operations with Kubernetes 18 | 19 | The following sections cover common things that you might need to do using Kubernetes directly. 20 | 21 | ```{toctree} 22 | :maxdepth: 2 23 | node-administration.md 24 | culling.md 25 | ``` 26 | -------------------------------------------------------------------------------- /config/clusters/smithsonian/cluster.yaml: -------------------------------------------------------------------------------- 1 | name: smithsonian 2 | provider: aws 3 | provider_url: https://2i2c.awsapps.com/start#/ 4 | aws: 5 | account: 969396938818 6 | key: enc-deployer-credentials.secret.json 7 | clusterType: eks 8 | clusterName: smithsonian 9 | region: us-east-2 10 | billing: 11 | paid_by_us: true 12 | support: 13 | helm_chart_values_files: 14 | - support.values.yaml 15 | - enc-support.secret.values.yaml 16 | hubs: 17 | - name: staging 18 | display_name: Smithsonian (staging) 19 | domain: staging.smithsonian.2i2c.cloud 20 | helm_chart: daskhub 21 | helm_chart_values_files: 22 | - common.values.yaml 23 | - staging.values.yaml 24 | - enc-staging.secret.values.yaml 25 | - name: prod 26 | display_name: Smithsonian 27 | domain: smithsonian.2i2c.cloud 28 | helm_chart: daskhub 29 | helm_chart_values_files: 30 | - common.values.yaml 31 | - prod.values.yaml 32 | - enc-prod.secret.values.yaml 33 | -------------------------------------------------------------------------------- /config/clusters/catalystproject-latam/staging.values.yaml: -------------------------------------------------------------------------------- 1 | jupyterhub: 2 | ingress: 3 | hosts: [staging.latam.catalystproject.2i2c.cloud] 4 | tls: 5 | - hosts: [staging.latam.catalystproject.2i2c.cloud] 6 | secretName: https-auto-tls 7 | custom: 8 | homepage: 9 | templateVars: 10 | org: 11 | name: Catalyst Project, LatAm - Staging 12 | hub: 13 | config: 14 | JupyterHub: 15 | authenticator_class: github 16 | GitHubOAuthenticator: 17 | oauth_callback_url: https://staging.latam.catalystproject.2i2c.cloud/hub/oauth_callback 18 | allowed_organizations: 19 | - czi-catalystproject 20 | - CatalystProject-Hubs:staging 21 | jupyterhub-home-nfs: 22 | gke: 23 | volumeId: projects/catalystproject-392106/zones/southamerica-east1-c/disks/hub-nfs-homedirs-staging 24 | 25 | nfs: 26 | pv: 27 | serverIP: storage-quota-home-nfs.staging.svc.cluster.local 28 | -------------------------------------------------------------------------------- /terraform/uptime-checks/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = "~> 1.5" 3 | backend "gcs" { 4 | # This is a separate GCS bucket than what we use for our other terraform state 5 | # This is less sensitive, so let's keep it separate 6 | bucket = "two-eye-two-see-uptime-checks-tfstate" 7 | prefix = "terraform/state/uptime-checks" 8 | } 9 | required_providers { 10 | google = { 11 | # FIXME: upgrade to v6, see https://registry.terraform.io/providers/hashicorp/google/latest/docs/guides/version_6_upgrade 12 | # ref: https://registry.terraform.io/providers/hashicorp/google/latest 13 | source = "google" 14 | version = "~> 5.43" 15 | } 16 | 17 | # Used to decrypt sops encrypted secrets containing PagerDuty keys 18 | sops = { 19 | # ref: https://registry.terraform.io/providers/carlpett/sops/latest 20 | source = "carlpett/sops" 21 | version = "~> 1.1" 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /.github/workflows/test-deployer-code.yaml: -------------------------------------------------------------------------------- 1 | name: Run tests on the deployer code 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | paths: 8 | - deployer/** 9 | - tests/** 10 | - requirements.txt 11 | - dev-requirements.txt 12 | - pyproject.toml 13 | tags: 14 | - '**' 15 | pull_request: 16 | branches: 17 | - main 18 | paths: 19 | - deployer/** 20 | - tests/** 21 | - requirements.txt 22 | - dev-requirements.txt 23 | - pyproject.toml 24 | workflow_dispatch: 25 | 26 | jobs: 27 | test-deployer: 28 | runs-on: ubuntu-latest 29 | steps: 30 | - uses: actions/checkout@v6 31 | - uses: actions/setup-python@v6 32 | with: 33 | python-version: '3.13' 34 | - name: Install dependencies 35 | run: | 36 | pip install -U pip 37 | pip install --editable . 38 | - name: Run tests 39 | run: | 40 | python -m pytest -vvv --color=yes 41 | -------------------------------------------------------------------------------- /config/clusters/bnext-bio/cluster.yaml: -------------------------------------------------------------------------------- 1 | name: bnext-bio 2 | provider: aws 3 | provider_url: https://2i2c.awsapps.com/start#/ 4 | aws: 5 | account: 882437028641 6 | key: enc-deployer-credentials.secret.json 7 | clusterType: eks 8 | clusterName: bnext-bio 9 | region: us-west-2 10 | billing: 11 | paid_by_us: true 12 | support: 13 | helm_chart_values_files: 14 | - support.values.yaml 15 | - enc-support.secret.values.yaml 16 | hubs: 17 | - name: staging 18 | display_name: bnext-bio - staging 19 | domain: staging.beta-hub.nucleus.engineering 20 | helm_chart: basehub 21 | helm_chart_values_files: 22 | - common.values.yaml 23 | - staging.values.yaml 24 | - enc-staging.secret.values.yaml 25 | - name: prod 26 | display_name: bnext-bio - prod 27 | domain: beta-hub.nucleus.engineering 28 | helm_chart: basehub 29 | helm_chart_values_files: 30 | - common.values.yaml 31 | - prod.values.yaml 32 | - enc-prod.secret.values.yaml 33 | -------------------------------------------------------------------------------- /config/clusters/oceanhackweek/cluster.yaml: -------------------------------------------------------------------------------- 1 | name: oceanhackweek 2 | provider: aws # https://2i2c.awsapps.com/start#/ 3 | aws: 4 | account: 221106934874 5 | key: enc-deployer-credentials.secret.json 6 | clusterType: eks 7 | clusterName: oceanhackweek 8 | region: us-west-2 9 | billing: 10 | paid_by_us: true 11 | support: 12 | helm_chart_values_files: 13 | - support.values.yaml 14 | - enc-support.secret.values.yaml 15 | hubs: 16 | - name: staging 17 | display_name: Oceanhackweek (Staging) 18 | domain: staging.oceanhackweek.2i2c.cloud 19 | helm_chart: basehub 20 | helm_chart_values_files: 21 | - common.values.yaml 22 | - staging.values.yaml 23 | - enc-staging.secret.values.yaml 24 | 25 | - name: prod 26 | display_name: Oceanhackweek (Prod) 27 | domain: oceanhackweek.2i2c.cloud 28 | helm_chart: basehub 29 | helm_chart_values_files: 30 | - common.values.yaml 31 | - prod.values.yaml 32 | - enc-prod.secret.values.yaml 33 | -------------------------------------------------------------------------------- /terraform/internaltools/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = "~> 1.5" 3 | backend "gcs" { 4 | # This is a separate GCS bucket than what we use for our other terraform state 5 | bucket = "two-eye-two-see-internal-tools-tfstate" 6 | prefix = "terraform/state/internal-tools" 7 | } 8 | required_providers { 9 | google = { 10 | # FIXME: upgrade to v6, see https://registry.terraform.io/providers/hashicorp/google/latest/docs/guides/version_6_upgrade 11 | # ref: https://registry.terraform.io/providers/hashicorp/google/latest 12 | source = "google" 13 | version = "~> 5.43" 14 | } 15 | 16 | sops = { 17 | source = "carlpett/sops" 18 | version = "~> 1.1" 19 | } 20 | 21 | helm = { 22 | source = "hashicorp/helm" 23 | version = "3.1.1" 24 | } 25 | 26 | kubernetes = { 27 | source = "hashicorp/kubernetes" 28 | version = "2.38.0" 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /config/clusters/bnext-bio/enc-grafana-token.secret.yaml: -------------------------------------------------------------------------------- 1 | grafana_token: ENC[AES256_GCM,data:TbV5xrBo5zGwjQQ0MMe+u95K7YMS05gW4oFo9bkg96IKpwpIQYDy0NHgcBwTyQ==,iv:XBEiErgp4CqaqkUkUjmxk6gDfEWyTXcNG+bWDT6zGxs=,tag:VfnwdgEL/SSCI0KFVBL7Mw==,type:str] 2 | sops: 3 | gcp_kms: 4 | - resource_id: projects/two-eye-two-see/locations/global/keyRings/sops-keys/cryptoKeys/similar-hubs 5 | created_at: '2025-10-22T12:31:55Z' 6 | enc: CiUA4OM7eHQsgJEyvtN9kccgG80+RS+rFCMz50AnAZwxiBZBtMfREkkAXpa10EwMVzI2dHcNG1rT6coUVryLOGfE3wyka5L/zhamM1MDG62Gs46TJ48AhedUs3qigbMvWXBhHpaZRWhCzfJToGLOts+7 7 | lastmodified: '2025-10-22T12:31:56Z' 8 | mac: ENC[AES256_GCM,data:3ASq8BgC9Sv7cJvsLP0oE6fUrtVFuhjfIrmf4DLXUCaN8lGNdc5dIavoMZ5D8j+MiAOAfntgQisITzZlz3JjF7eCY+1lDZv0qww6mD6In+fE0kdh8Jh4+kJ01vVxIML7/u9zpioHnuV5wNeBNabTLWMoEfLJp1otubHeUskwrqY=,iv:2/8mkVWz4ytw48w6lU/k+GdrE3zTTlqLAIngFZ7KB2M=,tag:kUTed27TNpYilKda/BJ+lQ==,type:str] 9 | unencrypted_suffix: _unencrypted 10 | version: 3.10.2 11 | -------------------------------------------------------------------------------- /config/clusters/temple/enc-grafana-token.secret.yaml: -------------------------------------------------------------------------------- 1 | grafana_token: ENC[AES256_GCM,data:28Yx+ujxbSFRDo1D+kGa/dAJFYxmm0RK5vzrj0IzvNmy4M9qaqQ6Tafy5FDRgg==,iv:hceLwXpbHvBefl4bQKk2XHAGyak3dEAR9v5xoxHbWSA=,tag:BSOzQj8yvtnFT1Su7KEGLA==,type:str] 2 | sops: 3 | gcp_kms: 4 | - resource_id: projects/two-eye-two-see/locations/global/keyRings/sops-keys/cryptoKeys/similar-hubs 5 | created_at: '2025-08-12T11:57:25Z' 6 | enc: CiUA4OM7eHrSKOsN5H1MHE7t5nkbZh+vd5HHwfV3sOumBLNejAaLEkkAXpa10HB3vvc1WZfcobE0nPIguQRclj7eSvOWjhEKgrcPaN7TtVZKKspPPgQW5RdTXvWzpwfGYqttXwaLv5QBicdXMm0CjLZM 7 | lastmodified: '2025-08-12T11:57:25Z' 8 | mac: ENC[AES256_GCM,data:hvx6CQYdQMPvWyhvo64JgsWUr3mWAnsO1XX+rJuYnz+O849kOlUfqM9YU1WsatBdc3OQUxiDerxdsM6RwenhI8mSpGUc8OV31JUIAlRHXIHacp3D44spJTNM+6h78xrUq34tN948/1p5nG9e3bkQNJ7ZUr6f02RiyEtz/DfkUsE=,iv:YyWnxVi9vR/LpxQCE6qARkd3M5RwWBB7PKSR1HwL+zY=,tag:KPBwlG4Rc6IlxaDrXfJ32A==,type:str] 9 | unencrypted_suffix: _unencrypted 10 | version: 3.10.2 11 | -------------------------------------------------------------------------------- /config/clusters/aimatx-2i2c-hub/enc-grafana-token.secret.yaml: -------------------------------------------------------------------------------- 1 | grafana_token: ENC[AES256_GCM,data:Rlfe2CU66oCaKBT+D865JsDeavauX20TOP44tfOwT0nRpumZ1YnOojKaCgHf5A==,iv:wl4mW3mvvIwlqmGf9W8bOKOLO2ERHykAgzUpqQVoy0A=,tag:o0Fvbp8PTWr2n7K31zVNAg==,type:str] 2 | sops: 3 | gcp_kms: 4 | - resource_id: projects/two-eye-two-see/locations/global/keyRings/sops-keys/cryptoKeys/similar-hubs 5 | created_at: '2025-10-23T15:54:28Z' 6 | enc: CiUA4OM7eDuZDEfmOExxlyS0V04qjBz8kupd/yxv6sYfyT+U546XEkkAXpa10BAVvtij2+97uZrnOP2xwXNKrRAaHYwiizoJ4XldxGJNV9OrhxwYnGDqg+pZcC5Dcl7YS23BL8ByBvIfcCfZ1gNkfuBb 7 | lastmodified: '2025-10-23T15:54:29Z' 8 | mac: ENC[AES256_GCM,data:7gWGRhYe2kG+AX+dBxsekEDBpS0e4n59RLzE0tjndJq1tFQXs9mbswzhUylka6JlE359Gp7gt6Nc2wPWLpzR+VL9V2BIiOc8emYxh+P0CQuap1DZ2/RHUqYdQRDZABXshanUCgxZV0r07fBMUzjh3G5t8F8Kw9IDpWmIjVC5wWw=,iv:tApvrGyYCluuZgh1hthqHF1aKCOW9yyI8c9m8/o3VGQ=,tag:Yr+TTihjv4WaMxEeeivEyQ==,type:str] 9 | unencrypted_suffix: _unencrypted 10 | version: 3.10.2 11 | -------------------------------------------------------------------------------- /config/clusters/berkeley-geojupyter/enc-grafana-token.secret.yaml: -------------------------------------------------------------------------------- 1 | grafana_token: ENC[AES256_GCM,data:rPT4CxI9cYFiRud8Hdwn5mBrey9jGxyEytpsoO4h8gF50t9PgPd9jjV6/w5IuA==,iv:4PUzpEwLHpWO7HkcJkSZ9L2OHuNAVDOyU10JtbOGWLA=,tag:u+RX+xG2oAswquUJQYwgbA==,type:str] 2 | sops: 3 | gcp_kms: 4 | - resource_id: projects/two-eye-two-see/locations/global/keyRings/sops-keys/cryptoKeys/similar-hubs 5 | created_at: '2025-07-30T19:02:18Z' 6 | enc: CiUA4OM7eE9OgkaRLX3DrNalucO4kPtkDG3YI4JM8iksxvc1SgAbEkkAlCBy9voW5BUILBQ7o5fKAjAgMZtMS5De1WyiSUiT5e75yDjX2/8EpEw9WH7a/rICuP/TE4CEx5JxoRwH78HMy2ewaoiXX/eM 7 | lastmodified: '2025-07-30T19:02:18Z' 8 | mac: ENC[AES256_GCM,data:FvpyAQYWenGB0F//UuVOnat86VENlYdPsUj2b839Oap5H37UHM/txJJj5FKTaazXdL+jM5RhEXamDjdToAqQ1v7KDFSf4VBac61J+CcfjSorj+TamlerOLiX1RlKmQjFygxS7Uzu9dUXg/BvGVwZZ6Th5+N709i2qVILJYwESfE=,iv:4SA6ljMyD2fcH9Gjjxb8+siFd1gT/w0WIm5PVv96m7Y=,tag:57OgvxLO2s6DlFQwZlrQ8Q==,type:str] 9 | unencrypted_suffix: _unencrypted 10 | version: 3.10.1 11 | -------------------------------------------------------------------------------- /config/clusters/catalystproject-africa/support.values.yaml: -------------------------------------------------------------------------------- 1 | cluster-autoscaler: 2 | enabled: true 3 | autoDiscovery: 4 | clusterName: catalystproject-africa 5 | awsRegion: af-south-1 6 | 7 | prometheusIngressAuthSecret: 8 | enabled: true 9 | 10 | grafana: 11 | grafana.ini: 12 | server: 13 | root_url: https://grafana.af.catalystproject.2i2c.cloud/ 14 | auth.github: 15 | enabled: true 16 | allowed_organizations: 2i2c-org 17 | ingress: 18 | hosts: 19 | - grafana.af.catalystproject.2i2c.cloud 20 | tls: 21 | - secretName: grafana-tls 22 | hosts: 23 | - grafana.af.catalystproject.2i2c.cloud 24 | 25 | prometheus: 26 | server: 27 | ingress: 28 | enabled: true 29 | hosts: 30 | - prometheus.af.catalystproject.2i2c.cloud 31 | tls: 32 | - secretName: prometheus-tls 33 | hosts: 34 | - prometheus.af.catalystproject.2i2c.cloud 35 | 36 | calico: 37 | enabled: true 38 | -------------------------------------------------------------------------------- /config/clusters/catalystproject-latam/gita.values.yaml: -------------------------------------------------------------------------------- 1 | nfs: 2 | pv: 3 | serverIP: storage-quota-home-nfs.gita.svc.cluster.local 4 | jupyterhub: 5 | ingress: 6 | hosts: [gita.latam.catalystproject.2i2c.cloud] 7 | tls: 8 | - hosts: [gita.latam.catalystproject.2i2c.cloud] 9 | secretName: https-auto-tls 10 | custom: 11 | homepage: 12 | templateVars: 13 | org: 14 | name: Catalyst Project, LatAm - GITA 15 | hub: 16 | config: 17 | JupyterHub: 18 | authenticator_class: github 19 | GitHubOAuthenticator: 20 | oauth_callback_url: https://gita.latam.catalystproject.2i2c.cloud/hub/oauth_callback 21 | allowed_organizations: 22 | - CatalystProject-Hubs:gita 23 | Authenticator: 24 | admin_users: 25 | - rafaelorozco511 26 | jupyterhub-home-nfs: 27 | gke: 28 | volumeId: projects/catalystproject-392106/zones/southamerica-east1-c/disks/hub-nfs-homedirs-gita 29 | 30 | -------------------------------------------------------------------------------- /config/clusters/catalystproject-latam/support.values.yaml: -------------------------------------------------------------------------------- 1 | prometheusIngressAuthSecret: 2 | enabled: true 3 | 4 | redirects: 5 | rules: 6 | # From https://2i2c.freshdesk.com/a/tickets/1591 7 | - from: plnc.latam.catalystproject.2i2c.cloud 8 | to: hub.pln.villena.cl 9 | 10 | prometheus: 11 | server: 12 | ingress: 13 | enabled: true 14 | hosts: 15 | - prometheus.latam.catalystproject.2i2c.cloud 16 | tls: 17 | - secretName: prometheus-tls 18 | hosts: 19 | - prometheus.latam.catalystproject.2i2c.cloud 20 | 21 | grafana: 22 | grafana.ini: 23 | server: 24 | root_url: https://grafana.latam.catalystproject.2i2c.cloud/ 25 | auth.github: 26 | enabled: true 27 | allowed_organizations: 2i2c-org 28 | ingress: 29 | hosts: 30 | - grafana.latam.catalystproject.2i2c.cloud 31 | tls: 32 | - secretName: grafana-tls 33 | hosts: 34 | - grafana.latam.catalystproject.2i2c.cloud 35 | -------------------------------------------------------------------------------- /terraform/aws/projects/oceanhackweek.tfvars: -------------------------------------------------------------------------------- 1 | region = "us-west-2" 2 | cluster_name = "oceanhackweek" 3 | cluster_nodes_location = "us-west-2a" 4 | 5 | ebs_volumes = { 6 | "staging" = { 7 | size = 1 8 | type = "gp3" 9 | name_suffix = "staging" 10 | tags = { "2i2c:hub-name" : "staging" } 11 | }, 12 | "prod" = { 13 | size = 300 14 | type = "gp3" 15 | name_suffix = "prod" 16 | tags = { "2i2c:hub-name" : "prod" } 17 | }, 18 | } 19 | 20 | enable_nfs_backup = true 21 | 22 | budget_alerts = { 23 | "monthly" : { 24 | time_period = "MONTHLY", 25 | emails = [ 26 | "emiliomayorga@gmail.com" 27 | ], 28 | # They have a total of $1000, and two events (one in Oct, one in Nov) to spend it on 29 | max_cost = 500 30 | }, 31 | } 32 | 33 | # Setup IAM creds but no buckets 34 | hub_cloud_permissions = { 35 | "staging" : { 36 | }, 37 | "prod" : { 38 | } 39 | } -------------------------------------------------------------------------------- /config/clusters/2i2c-aws-us/cluster.yaml: -------------------------------------------------------------------------------- 1 | name: 2i2c-aws-us 2 | provider: aws 3 | # two-eye-two-see 4 | provider_url: https://2i2c.awsapps.com/start 5 | aws: 6 | account: 790657130469 7 | key: enc-deployer-credentials.secret.json 8 | clusterType: eks 9 | clusterName: 2i2c-aws-us 10 | region: us-west-2 11 | billing: 12 | paid_by_us: true 13 | support: 14 | helm_chart_values_files: 15 | - support.values.yaml 16 | - enc-support.secret.values.yaml 17 | hubs: 18 | - name: staging 19 | display_name: 2i2c AWS staging 20 | domain: staging.aws.2i2c.cloud 21 | helm_chart: basehub 22 | helm_chart_values_files: 23 | - basehub-common.values.yaml 24 | - staging.values.yaml 25 | - enc-staging.secret.values.yaml 26 | - name: showcase 27 | display_name: 2i2c Showcase 28 | domain: showcase.2i2c.cloud 29 | helm_chart: daskhub 30 | helm_chart_values_files: 31 | - daskhub-common.values.yaml 32 | - showcase.values.yaml 33 | - enc-showcase.secret.values.yaml 34 | -------------------------------------------------------------------------------- /config/clusters/berkeley-geojupyter/prod.values.yaml: -------------------------------------------------------------------------------- 1 | nfs: 2 | pv: 3 | serverIP: 10.100.90.206 4 | userServiceAccount: 5 | annotations: 6 | eks.amazonaws.com/role-arn: arn:aws:iam::622703418259:role/berkeley-geojupyter-prod 7 | 8 | jupyterhub: 9 | ingress: 10 | hosts: [berkeley-geojupyter.2i2c.cloud] 11 | tls: 12 | - hosts: [berkeley-geojupyter.2i2c.cloud] 13 | secretName: https-auto-tls 14 | hub: 15 | config: 16 | JupyterHub: 17 | authenticator_class: github 18 | GitHubOAuthenticator: 19 | oauth_callback_url: https://berkeley-geojupyter.2i2c.cloud/hub/oauth_callback 20 | 21 | singleuser: 22 | extraEnv: 23 | SCRATCH_BUCKET: s3://berkeley-geojupyter-scratch/$(JUPYTERHUB_USER) 24 | 25 | jupyterhub-home-nfs: 26 | eks: 27 | volumeId: vol-03eed37ae04a744e2 28 | 29 | 30 | binderhub-service: 31 | config: 32 | BinderHub: 33 | image_prefix: quay.io/imagebuilding-non-gcp-hubs/berkeley-geojupyter-prod- 34 | -------------------------------------------------------------------------------- /config/clusters/catalystproject-africa/aibst.values.yaml: -------------------------------------------------------------------------------- 1 | jupyterhub: 2 | ingress: 3 | hosts: [aibst.af.catalystproject.2i2c.cloud] 4 | tls: 5 | - hosts: [aibst.af.catalystproject.2i2c.cloud] 6 | secretName: https-auto-tls 7 | custom: 8 | homepage: 9 | templateVars: 10 | org: 11 | name: Catalyst Project, Africa - African Institute of Biomedical Sciences and Technology 12 | hub: 13 | config: 14 | JupyterHub: 15 | authenticator_class: github 16 | GitHubOAuthenticator: 17 | oauth_callback_url: https://aibst.af.catalystproject.2i2c.cloud/hub/oauth_callback 18 | allowed_organizations: 19 | - CatalystProject-Hubs:aibst 20 | Authenticator: 21 | admin_users: 22 | - zchikwambi 23 | singleuser: 24 | nodeSelector: 25 | 2i2c/hub-name: aibst 26 | jupyterhub-home-nfs: 27 | eks: 28 | volumeId: vol-05810452a41759168 29 | nfs: 30 | pv: 31 | serverIP: 10.100.88.97 32 | -------------------------------------------------------------------------------- /config/clusters/catalystproject-africa/molerhealth.values.yaml: -------------------------------------------------------------------------------- 1 | jupyterhub: 2 | ingress: 3 | hosts: [molerhealth.af.catalystproject.2i2c.cloud] 4 | tls: 5 | - hosts: [molerhealth.af.catalystproject.2i2c.cloud] 6 | secretName: https-auto-tls 7 | custom: 8 | homepage: 9 | templateVars: 10 | org: 11 | name: Catalyst Project, Africa - MolerHealth 12 | hub: 13 | config: 14 | JupyterHub: 15 | authenticator_class: github 16 | GitHubOAuthenticator: 17 | oauth_callback_url: https://molerhealth.af.catalystproject.2i2c.cloud/hub/oauth_callback 18 | allowed_organizations: 19 | - CatalystProject-Hubs:molerhealth 20 | Authenticator: 21 | admin_users: 22 | - Monsurat-Onabajo 23 | singleuser: 24 | nodeSelector: 25 | 2i2c/hub-name: molerhealth 26 | jupyterhub-home-nfs: 27 | eks: 28 | volumeId: vol-0818b363dec5d022f 29 | nfs: 30 | pv: 31 | serverIP: 10.100.220.50 32 | -------------------------------------------------------------------------------- /config/clusters/opensci/support.values.yaml: -------------------------------------------------------------------------------- 1 | prometheusIngressAuthSecret: 2 | enabled: true 3 | 4 | cluster-autoscaler: 5 | enabled: true 6 | autoDiscovery: 7 | clusterName: opensci 8 | awsRegion: us-west-2 9 | 10 | prometheus: 11 | server: 12 | ingress: 13 | enabled: true 14 | hosts: 15 | - prometheus.opensci.2i2c.cloud 16 | tls: 17 | - secretName: prometheus-tls 18 | hosts: 19 | - prometheus.opensci.2i2c.cloud 20 | grafana: 21 | grafana.ini: 22 | server: 23 | root_url: https://grafana.opensci.2i2c.cloud/ 24 | auth.github: 25 | enabled: true 26 | allowed_organizations: 2i2c-org 27 | ingress: 28 | hosts: 29 | - grafana.opensci.2i2c.cloud 30 | tls: 31 | - secretName: grafana-tls 32 | hosts: 33 | - grafana.opensci.2i2c.cloud 34 | 35 | calico: 36 | enabled: true 37 | 38 | # FIXME: remove this once eksctl is fixed 39 | nvidiaDevicePlugin: 40 | aws: 41 | enabled: true 42 | -------------------------------------------------------------------------------- /config/clusters/strudel/support.values.yaml: -------------------------------------------------------------------------------- 1 | prometheusIngressAuthSecret: 2 | enabled: true 3 | 4 | prometheus: 5 | server: 6 | ingress: 7 | enabled: true 8 | hosts: 9 | - prometheus.strudel.2i2c.cloud 10 | tls: 11 | - secretName: prometheus-tls 12 | hosts: 13 | - prometheus.strudel.2i2c.cloud 14 | 15 | grafana: 16 | grafana.ini: 17 | server: 18 | root_url: https://grafana.strudel.2i2c.cloud/ 19 | auth.github: 20 | enabled: true 21 | allowed_organizations: 2i2c-org 22 | ingress: 23 | hosts: 24 | - grafana.strudel.2i2c.cloud 25 | tls: 26 | - secretName: grafana-tls 27 | hosts: 28 | - grafana.strudel.2i2c.cloud 29 | 30 | cluster-autoscaler: 31 | enabled: true 32 | autoDiscovery: 33 | clusterName: strudel 34 | awsRegion: us-west-2 35 | 36 | calico: 37 | enabled: true 38 | 39 | # FIXME: remove this once eksctl is fixed 40 | nvidiaDevicePlugin: 41 | aws: 42 | enabled: true 43 | -------------------------------------------------------------------------------- /config/clusters/catalystproject-latam/iner.values.yaml: -------------------------------------------------------------------------------- 1 | nfs: 2 | pv: 3 | serverIP: storage-quota-home-nfs.iner.svc.cluster.local 4 | jupyterhub: 5 | ingress: 6 | hosts: [iner.latam.catalystproject.2i2c.cloud] 7 | tls: 8 | - hosts: [iner.latam.catalystproject.2i2c.cloud] 9 | secretName: https-auto-tls 10 | custom: 11 | homepage: 12 | templateVars: 13 | org: 14 | name: Catalyst Project, LatAm - INER 15 | hub: 16 | config: 17 | JupyterHub: 18 | authenticator_class: github 19 | GitHubOAuthenticator: 20 | oauth_callback_url: https://iner.latam.catalystproject.2i2c.cloud/hub/oauth_callback 21 | allowed_organizations: 22 | - CatalystProject-Hubs:iner 23 | Authenticator: 24 | admin_users: 25 | - Gabo8611 26 | - Yalbibalderas 27 | jupyterhub-home-nfs: 28 | gke: 29 | volumeId: projects/catalystproject-392106/zones/southamerica-east1-c/disks/hub-nfs-homedirs-iner 30 | 31 | -------------------------------------------------------------------------------- /config/clusters/oceanhackweek/support.values.yaml: -------------------------------------------------------------------------------- 1 | prometheusIngressAuthSecret: 2 | enabled: true 3 | 4 | prometheus: 5 | server: 6 | persistentVolume: 7 | size: 100Gi 8 | ingress: 9 | enabled: true 10 | hosts: 11 | - prometheus.oceanhackweek.2i2c.cloud 12 | tls: 13 | - secretName: prometheus-tls 14 | hosts: 15 | - prometheus.oceanhackweek.2i2c.cloud 16 | 17 | grafana: 18 | grafana.ini: 19 | server: 20 | root_url: https://grafana.oceanhackweek.2i2c.cloud/ 21 | persistence: 22 | # We don't need 10Gi on the Grafana persistent directory 23 | size: 1Gi 24 | ingress: 25 | hosts: 26 | - grafana.oceanhackweek.2i2c.cloud 27 | tls: 28 | - secretName: grafana-tls 29 | hosts: 30 | - grafana.oceanhackweek.2i2c.cloud 31 | 32 | 33 | cluster-autoscaler: 34 | enabled: true 35 | autoDiscovery: 36 | clusterName: oceanhackweek 37 | awsRegion: us-west-2 38 | 39 | calico: 40 | enabled: true 41 | -------------------------------------------------------------------------------- /deployer/dev_commands/generate/hub_asset/cluster_entry.py: -------------------------------------------------------------------------------- 1 | import jinja2 2 | import typer 3 | 4 | from deployer.utils.file_acquisition import REPO_ROOT_PATH 5 | 6 | from .hub_asset_app import hub_asset_app 7 | 8 | 9 | @hub_asset_app.command() 10 | def cluster_entry( 11 | cluster_name: str = typer.Option( 12 | ..., prompt="The name of the cluster where the hub will live" 13 | ), 14 | hub_name: str = typer.Option(..., prompt="The name of the hub"), 15 | ): 16 | """ 17 | Outputs the relevant cluster.yaml hub entry that the engineer can then manually copy-paste into the relevant cluster.yaml file. 18 | """ 19 | 20 | vars = { 21 | "cluster_name": cluster_name, 22 | "hub_name": hub_name, 23 | } 24 | 25 | with open( 26 | REPO_ROOT_PATH / "config/clusters/templates/common/cluster-entry.yaml" 27 | ) as f: 28 | cluster_hub_entry_template = jinja2.Template(f.read()) 29 | print(cluster_hub_entry_template.render(**vars)) 30 | -------------------------------------------------------------------------------- /config/clusters/catalystproject-latam/cabana.values.yaml: -------------------------------------------------------------------------------- 1 | nfs: 2 | pv: 3 | serverIP: storage-quota-home-nfs.cabana.svc.cluster.local 4 | jupyterhub: 5 | ingress: 6 | hosts: [cabana.latam.catalystproject.2i2c.cloud] 7 | tls: 8 | - hosts: [cabana.latam.catalystproject.2i2c.cloud] 9 | secretName: https-auto-tls 10 | custom: 11 | homepage: 12 | templateVars: 13 | org: 14 | name: Catalyst Project, LatAm - CABANA 15 | hub: 16 | config: 17 | JupyterHub: 18 | authenticator_class: github 19 | GitHubOAuthenticator: 20 | oauth_callback_url: https://cabana.latam.catalystproject.2i2c.cloud/hub/oauth_callback 21 | allowed_organizations: 22 | - CatalystProject-Hubs:cabana 23 | Authenticator: 24 | admin_users: 25 | - rebcamsan 26 | - l-g-g 27 | jupyterhub-home-nfs: 28 | gke: 29 | volumeId: projects/catalystproject-392106/zones/southamerica-east1-c/disks/hub-nfs-homedirs-cabana 30 | 31 | -------------------------------------------------------------------------------- /config/clusters/disasters/support.values.yaml: -------------------------------------------------------------------------------- 1 | prometheusIngressAuthSecret: 2 | enabled: true 3 | 4 | prometheus: 5 | server: 6 | ingress: 7 | enabled: true 8 | hosts: 9 | - prometheus.disasters.2i2c.cloud 10 | tls: 11 | - secretName: prometheus-tls 12 | hosts: 13 | - prometheus.disasters.2i2c.cloud 14 | 15 | grafana: 16 | grafana.ini: 17 | server: 18 | root_url: https://grafana.disasters.2i2c.cloud/ 19 | auth.github: 20 | enabled: true 21 | allowed_organizations: 2i2c-org 22 | ingress: 23 | hosts: 24 | - grafana.disasters.2i2c.cloud 25 | tls: 26 | - secretName: grafana-tls 27 | hosts: 28 | - grafana.disasters.2i2c.cloud 29 | 30 | cluster-autoscaler: 31 | enabled: true 32 | autoDiscovery: 33 | clusterName: disasters 34 | awsRegion: us-west-2 35 | 36 | calico: 37 | enabled: true 38 | 39 | # FIXME: remove this once eksctl is fixed 40 | nvidiaDevicePlugin: 41 | aws: 42 | enabled: true 43 | -------------------------------------------------------------------------------- /helm-charts/basehub/templates/static/ingress.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.staticWebsite.enabled -}} 2 | apiVersion: networking.k8s.io/v1 3 | kind: Ingress 4 | metadata: 5 | annotations: 6 | # Authenticate with oauth2-proxy so only hub logged-in users see this 7 | # https://kubernetes.github.io/ingress-nginx/examples/auth/oauth-external-auth/ 8 | nginx.ingress.kubernetes.io/auth-url: "http://dex.{{ .Release.Namespace }}.svc.cluster.local:9000/services/oauth2-proxy/oauth2/auth" 9 | nginx.ingress.kubernetes.io/auth-signin: "https://$host/services/oauth2-proxy/oauth2/start?rd=$escaped_request_uri" 10 | name: static-sites 11 | spec: 12 | ingressClassName: nginx 13 | rules: 14 | - host: {{ .Values.staticWebsite.ingress.host }} 15 | http: 16 | paths: 17 | - path: {{ .Values.staticWebsite.ingress.path }} 18 | pathType: Prefix 19 | backend: 20 | service: 21 | name: static-sites 22 | port: 23 | number: 80 24 | {{- end }} 25 | -------------------------------------------------------------------------------- /config/clusters/catalystproject-latam/nnb-ccg.values.yaml: -------------------------------------------------------------------------------- 1 | nfs: 2 | pv: 3 | serverIP: storage-quota-home-nfs.nnb-ccg.svc.cluster.local 4 | jupyterhub: 5 | ingress: 6 | hosts: [nnb-ccg.latam.catalystproject.2i2c.cloud] 7 | tls: 8 | - hosts: [nnb-ccg.latam.catalystproject.2i2c.cloud] 9 | secretName: https-auto-tls 10 | custom: 11 | homepage: 12 | templateVars: 13 | org: 14 | name: Catalyst Project, LatAm - NNB-CCG 15 | hub: 16 | config: 17 | JupyterHub: 18 | authenticator_class: github 19 | GitHubOAuthenticator: 20 | oauth_callback_url: https://nnb-ccg.latam.catalystproject.2i2c.cloud/hub/oauth_callback 21 | allowed_organizations: 22 | - CatalystProject-Hubs:nnb-ccg 23 | Authenticator: 24 | admin_users: 25 | - alfredojosehernandezalvarez 26 | jupyterhub-home-nfs: 27 | gke: 28 | volumeId: projects/catalystproject-392106/zones/southamerica-east1-c/disks/hub-nfs-homedirs-nnb-ccg 29 | 30 | -------------------------------------------------------------------------------- /config/clusters/maap/cluster.yaml: -------------------------------------------------------------------------------- 1 | name: maap 2 | provider: aws 3 | provider_url: https://916098889494.signin.aws.amazon.com/console 4 | aws: 5 | account: 916098889494 6 | key: enc-deployer-credentials.secret.json 7 | clusterType: eks 8 | clusterName: maap 9 | region: us-west-2 10 | billing: 11 | paid_by_us: false 12 | support: 13 | helm_chart_values_files: 14 | - support.values.yaml 15 | - enc-support.secret.values.yaml 16 | hubs: 17 | - name: staging 18 | display_name: MAAP - staging 19 | domain: staging.hub.maap-project.org 20 | helm_chart: basehub 21 | helm_chart_values_files: 22 | - common.values.yaml 23 | - staging.values.yaml 24 | - enc-common.secret.values.yaml 25 | - enc-staging.secret.values.yaml 26 | - name: prod 27 | display_name: MAAP - prod 28 | domain: hub.maap-project.org 29 | helm_chart: basehub 30 | helm_chart_values_files: 31 | - common.values.yaml 32 | - prod.values.yaml 33 | - enc-common.secret.values.yaml 34 | - enc-prod.secret.values.yaml 35 | -------------------------------------------------------------------------------- /deployer/health_check_tests/conftest.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | 4 | def pytest_addoption(parser): 5 | """ 6 | Define the commandline params that can be passed to pytest. 7 | """ 8 | parser.addoption("--hub-url", action="store") 9 | parser.addoption( 10 | "--api-token", 11 | action="store", 12 | ) 13 | parser.addoption( 14 | "--hub-type", 15 | action="store", 16 | ) 17 | parser.addoption( 18 | "--check-dask-scaling", 19 | action="store_true", 20 | ) 21 | 22 | 23 | @pytest.fixture 24 | def hub_url(request): 25 | return request.config.getoption("--hub-url") 26 | 27 | 28 | @pytest.fixture 29 | def hub_type(request): 30 | return request.config.getoption("--hub-type") 31 | 32 | 33 | @pytest.fixture() 34 | def api_token(request): 35 | return request.config.getoption("--api-token") 36 | 37 | 38 | @pytest.fixture() 39 | def check_dask_scaling(request): 40 | return request.config.getoption("--check-dask-scaling") 41 | -------------------------------------------------------------------------------- /config/clusters/leap/staging.values.yaml: -------------------------------------------------------------------------------- 1 | basehub: 2 | nfs: 3 | pv: 4 | serverIP: storage-quota-home-nfs.staging.svc.cluster.local 5 | userServiceAccount: 6 | annotations: 7 | iam.gke.io/gcp-service-account: leap-staging@leap-pangeo.iam.gserviceaccount.com 8 | jupyterhub: 9 | ingress: 10 | hosts: [staging.leap.2i2c.cloud] 11 | tls: 12 | - hosts: [staging.leap.2i2c.cloud] 13 | secretName: https-auto-tls 14 | singleuser: 15 | extraEnv: 16 | SCRATCH_BUCKET: gs://leap-scratch-staging/$(JUPYTERHUB_USER) 17 | PERSISTENT_BUCKET: gs://leap-persistent-staging/$(JUPYTERHUB_USER) 18 | PANGEO_SCRATCH: gs://leap-scratch-staging/$(JUPYTERHUB_USER) 19 | hub: 20 | config: 21 | GitHubOAuthenticator: 22 | oauth_callback_url: https://staging.leap.2i2c.cloud/hub/oauth_callback 23 | 24 | jupyterhub-home-nfs: 25 | gke: 26 | volumeId: projects/leap-pangeo/zones/us-central1-c/disks/hub-nfs-homedirs-staging 27 | 28 | -------------------------------------------------------------------------------- /eksctl/catalystproject-africa.jsonnet: -------------------------------------------------------------------------------- 1 | local cluster = import './libsonnet/cluster.jsonnet'; 2 | 3 | // Turn up maxSize 4 | local c = cluster.withNodeGroupConfigOverride( 5 | // Increase volumeSize 6 | cluster.withNodeGroupConfigOverride( 7 | cluster.makeCluster( 8 | name='catalystproject-africa', 9 | region='af-south-1', 10 | nodeAz='af-south-1a', 11 | version='1.34', 12 | coreNodeInstanceType='r5.large', 13 | notebookCPUInstanceTypes=[ 14 | 'r5.xlarge', 15 | 'r5.4xlarge', 16 | 'r5.16xlarge', 17 | ], 18 | hubs=[ 19 | 'staging', 20 | 'nm-aist', 21 | 'must', 22 | 'uvri', 23 | 'wits', 24 | 'kush', 25 | 'molerhealth', 26 | 'aibst', 27 | 'bhki', 28 | 'bon', 29 | ], 30 | nodeGroupGenerations=['b'] 31 | ), 32 | kind='notebook', 33 | overrides={ volumeSize: 400 } 34 | ), 35 | kind='core', 36 | overrides={ maxSize: 4 } 37 | ); 38 | 39 | c 40 | -------------------------------------------------------------------------------- /config/clusters/projectpythia-binder/support.values.yaml: -------------------------------------------------------------------------------- 1 | prometheusIngressAuthSecret: 2 | enabled: true 3 | 4 | prometheus: 5 | server: 6 | ingress: 7 | enabled: true 8 | hosts: 9 | - prometheus.binder-pythia.jetstream2.2i2c.cloud 10 | tls: 11 | - secretName: prometheus-tls 12 | hosts: 13 | - prometheus.binder-pythia.jetstream2.2i2c.cloud 14 | 15 | grafana: 16 | grafana.ini: 17 | server: 18 | root_url: https://grafana.binder-pythia.jetstream2.2i2c.cloud/ 19 | auth.github: 20 | enabled: true 21 | allowed_organizations: 2i2c-org 22 | ingress: 23 | hosts: 24 | - grafana.binder-pythia.jetstream2.2i2c.cloud 25 | tls: 26 | - secretName: grafana-tls 27 | hosts: 28 | - grafana.binder-pythia.jetstream2.2i2c.cloud 29 | 30 | redirects: 31 | rules: 32 | - from: binder-pythia.jetstream2.2i2c.cloud 33 | to: binder.projectpythia.org 34 | - from: hub.binder-pythia.jetstream2.2i2c.cloud 35 | to: hub.projectpythia.org 36 | -------------------------------------------------------------------------------- /config/clusters/temple/staging.values.yaml: -------------------------------------------------------------------------------- 1 | nfs: 2 | pv: 3 | serverIP: 10.100.153.248 4 | jupyterhub-home-nfs: 5 | eks: 6 | volumeId: vol-09652a5540fdbd50f 7 | jupyterhub: 8 | hub: 9 | config: 10 | CILogonOAuthenticator: 11 | oauth_callback_url: https://staging.temple.2i2c.cloud/hub/oauth_callback 12 | singleuser: 13 | extraEnv: 14 | GH_SCOPED_CREDS_CLIENT_ID: Iv23libKsm2tlJzjYplj 15 | GH_SCOPED_CREDS_APP_URL: https://github.com/apps/temple-advanced-staging-push 16 | nodeSelector: 17 | 2i2c/hub-name: staging 18 | ingress: 19 | hosts: [staging.temple.2i2c.cloud] 20 | tls: 21 | - hosts: [staging.temple.2i2c.cloud] 22 | secretName: https-auto-tls 23 | binderhub-service: 24 | dockerApi: 25 | nodeSelector: 26 | 2i2c/hub-name: staging 27 | config: 28 | KubernetesBuildExecutor: 29 | node_selector: 30 | 2i2c/hub-name: staging 31 | BinderHub: 32 | image_prefix: quay.io/imagebuilding-non-gcp-hubs/temple-staging- 33 | -------------------------------------------------------------------------------- /eksctl/earthscope.jsonnet: -------------------------------------------------------------------------------- 1 | local cluster = import './libsonnet/cluster.jsonnet'; 2 | 3 | local c = cluster.withNodeGroupConfigOverride( 4 | cluster.makeCluster( 5 | name='earthscope', 6 | region='us-east-2', 7 | nodeAz='us-east-2a', 8 | version='1.34', 9 | coreNodeInstanceType='r8i-flex.large', 10 | notebookCPUInstanceTypes=[ 11 | 'r5.xlarge', 12 | 'r5.4xlarge', 13 | 'r5.16xlarge', 14 | ], 15 | daskInstanceTypes=[ 16 | // Allow for a range of spot instance types 17 | ['r5.4xlarge', 'r7i.4xlarge', 'r6i.4xlarge'], 18 | ], 19 | hubs=['staging', 'prod', 'binder'], 20 | notebookGPUNodeGroups=[ 21 | { 22 | instanceType: 'g4dn.xlarge', 23 | }, 24 | ], 25 | nodeGroupGenerations=['a'] 26 | ), 27 | // Add provenence of resources 28 | overrides={ 29 | tags+: { 30 | 'earthscope:application:name': 'geolab', 31 | 'earthscope:application:owner': 'research-onramp-to-the-cloud', 32 | }, 33 | } 34 | ); 35 | c 36 | -------------------------------------------------------------------------------- /helm-charts/support/templates/redirects.yaml: -------------------------------------------------------------------------------- 1 | {{- /* 2 | The template renders a set of Ingress resources to redirect incoming requests 3 | made to one domain (from) to another (to). 4 | 5 | ref: https://kubernetes.github.io/ingress-nginx/examples/rewrite/ 6 | */}} 7 | {{- range .Values.redirects.rules }} 8 | apiVersion: networking.k8s.io/v1 9 | kind: Ingress 10 | metadata: 11 | name: ingress-redirect-{{ .from }} 12 | annotations: 13 | cert-manager.io/cluster-issuer: letsencrypt-prod 14 | nginx.ingress.kubernetes.io/configuration-snippet: | 15 | rewrite "^\/(?!\.well-known\/acme-challenge)(.*)$" "$scheme://{{ .to }}/$1" {{ .type | default "redirect" }}; 16 | spec: 17 | ingressClassName: nginx 18 | tls: 19 | - hosts: 20 | - {{ .from }} 21 | secretName: redirect-{{ .from }}-tls 22 | rules: 23 | - host: {{ .from }} 24 | {{- /* 25 | A YAML document separator is used below as the template could render multiple 26 | separate k8s resources. 27 | */}} 28 | --- 29 | {{- end }} 30 | -------------------------------------------------------------------------------- /config/clusters/berkeley-geojupyter/staging.values.yaml: -------------------------------------------------------------------------------- 1 | nfs: 2 | pv: 3 | serverIP: 10.100.89.64 4 | 5 | userServiceAccount: 6 | annotations: 7 | eks.amazonaws.com/role-arn: arn:aws:iam::622703418259:role/berkeley-geojupyter-staging 8 | 9 | jupyterhub: 10 | ingress: 11 | hosts: [staging.berkeley-geojupyter.2i2c.cloud] 12 | tls: 13 | - hosts: [staging.berkeley-geojupyter.2i2c.cloud] 14 | secretName: https-auto-tls 15 | hub: 16 | config: 17 | JupyterHub: 18 | authenticator_class: github 19 | GitHubOAuthenticator: 20 | oauth_callback_url: https://staging.berkeley-geojupyter.2i2c.cloud/hub/oauth_callback 21 | singleuser: 22 | extraEnv: 23 | SCRATCH_BUCKET: s3://berkeley-geojupyter-scratch-staging/$(JUPYTERHUB_USER) 24 | 25 | jupyterhub-home-nfs: 26 | eks: 27 | volumeId: vol-018ab2eba48b7d895 28 | 29 | 30 | binderhub-service: 31 | config: 32 | BinderHub: 33 | image_prefix: quay.io/imagebuilding-non-gcp-hubs/berkeley-geojupyter-staging- 34 | -------------------------------------------------------------------------------- /config/clusters/berkeley-geojupyter/support.values.yaml: -------------------------------------------------------------------------------- 1 | prometheusIngressAuthSecret: 2 | enabled: true 3 | 4 | 5 | 6 | prometheus: 7 | server: 8 | persistentVolume: 9 | size: 100Gi 10 | ingress: 11 | enabled: true 12 | hosts: 13 | - prometheus.berkeley-geojupyter.2i2c.cloud 14 | tls: 15 | - secretName: prometheus-tls 16 | hosts: 17 | - prometheus.berkeley-geojupyter.2i2c.cloud 18 | 19 | grafana: 20 | grafana.ini: 21 | server: 22 | root_url: https://grafana.berkeley-geojupyter.2i2c.cloud/ 23 | auth.github: 24 | enabled: true 25 | allowed_organizations: 2i2c-org 26 | ingress: 27 | hosts: 28 | - grafana.berkeley-geojupyter.2i2c.cloud 29 | tls: 30 | - secretName: grafana-tls 31 | hosts: 32 | - grafana.berkeley-geojupyter.2i2c.cloud 33 | 34 | cluster-autoscaler: 35 | enabled: true 36 | autoDiscovery: 37 | clusterName: berkeley-geojupyter 38 | awsRegion: us-west-2 39 | 40 | calico: 41 | enabled: true 42 | -------------------------------------------------------------------------------- /config/clusters/openscapeshub/enc-workshop.secret.values.yaml: -------------------------------------------------------------------------------- 1 | basehub: 2 | jupyterhub: 3 | hub: 4 | config: 5 | DummyAuthenticator: 6 | password: ENC[AES256_GCM,data:/ufxRsGU1TLI1HR3VA==,iv:tiq/xX3Wuc/iltOyk+1i+S8CXItGyykgDwCyEV77lpo=,tag:BYJE6EbqGndK/31yAcG6iw==,type:str] 7 | sops: 8 | gcp_kms: 9 | - resource_id: projects/two-eye-two-see/locations/global/keyRings/sops-keys/cryptoKeys/similar-hubs 10 | created_at: '2025-08-07T13:17:08Z' 11 | enc: CiUA4OM7eK/VsLTEtsrCh8V+s/m56JPwDsKI3mIE2+sMDVgsZRstEkkAXpa10DqAg6p8ZMfa5mZpJHr9S+C7Nj3FEh1eb5d0a1jju6HzcHi01x0rLTa2DB2b5sVthiKLT5l4SpkKBW0iPAwl3rXOBmNB 12 | lastmodified: '2025-11-30T16:32:27Z' 13 | mac: ENC[AES256_GCM,data:CyMeF39wl6w+jzYzMyxdL7MFluqlcHWvWt5O0O9CzMvBfkoLZ5lOGNMPaKuAQzbOfwMjasVugDLD6b7ikgYqsX4FKUsmlVyIIcDJsno0RIUckgiRHViSyOYxkX5GK8MQrLiSt6dwGMJ6582rZR53TF47doegJKpbT5LTCNVOcSw=,iv:jBwQfMZpPIn+ZcEAUmvTCl3g8nDef9yxKHPLiuVrAUw=,tag:r8A2XTXa8RhBPx6QeRoAPg==,type:str] 14 | unencrypted_suffix: _unencrypted 15 | version: 3.10.2 16 | -------------------------------------------------------------------------------- /config/clusters/smithsonian/support.values.yaml: -------------------------------------------------------------------------------- 1 | cluster-autoscaler: 2 | enabled: true 3 | autoDiscovery: 4 | clusterName: smithsonian 5 | awsRegion: us-east-2 6 | 7 | prometheusIngressAuthSecret: 8 | enabled: true 9 | 10 | grafana: 11 | grafana.ini: 12 | server: 13 | root_url: https://grafana.smithsonian.2i2c.cloud/ 14 | auth.github: 15 | enabled: true 16 | allowed_organizations: 2i2c-org 17 | ingress: 18 | hosts: 19 | - grafana.smithsonian.2i2c.cloud 20 | tls: 21 | - secretName: grafana-tls 22 | hosts: 23 | - grafana.smithsonian.2i2c.cloud 24 | 25 | prometheus: 26 | server: 27 | ingress: 28 | enabled: true 29 | hosts: 30 | - prometheus.smithsonian.2i2c.cloud 31 | tls: 32 | - secretName: prometheus-tls 33 | hosts: 34 | - prometheus.smithsonian.2i2c.cloud 35 | 36 | calico: 37 | enabled: true 38 | 39 | # FIXME: remove this once eksctl is fixed 40 | nvidiaDevicePlugin: 41 | aws: 42 | enabled: true 43 | -------------------------------------------------------------------------------- /config/clusters/temple/advanced.values.yaml: -------------------------------------------------------------------------------- 1 | nfs: 2 | pv: 3 | serverIP: 10.100.225.18 4 | jupyterhub-home-nfs: 5 | eks: 6 | volumeId: vol-0b5fc915293bd5bec 7 | jupyterhub: 8 | hub: 9 | config: 10 | CILogonOAuthenticator: 11 | oauth_callback_url: https://advanced.temple.2i2c.cloud/hub/oauth_callback 12 | singleuser: 13 | extraEnv: 14 | GH_SCOPED_CREDS_CLIENT_ID: Iv23liL9VT25MVvo3RYq 15 | GH_SCOPED_CREDS_APP_URL: https://github.com/apps/temple-advanced-github-push-access 16 | nodeSelector: 17 | 2i2c/hub-name: advanced 18 | ingress: 19 | hosts: [advanced.temple.2i2c.cloud] 20 | tls: 21 | - hosts: [advanced.temple.2i2c.cloud] 22 | secretName: https-auto-tls 23 | binderhub-service: 24 | dockerApi: 25 | nodeSelector: 26 | 2i2c/hub-name: advanced 27 | config: 28 | KubernetesBuildExecutor: 29 | node_selector: 30 | 2i2c/hub-name: advanced 31 | BinderHub: 32 | image_prefix: quay.io/imagebuilding-non-gcp-hubs/temple-advanced- 33 | -------------------------------------------------------------------------------- /config/clusters/2i2c-aws-us/support.values.yaml: -------------------------------------------------------------------------------- 1 | prometheusIngressAuthSecret: 2 | enabled: true 3 | 4 | grafana: 5 | grafana.ini: 6 | server: 7 | root_url: https://grafana.aws.2i2c.cloud/ 8 | auth.github: 9 | enabled: true 10 | allowed_organizations: 2i2c-org 11 | ingress: 12 | hosts: 13 | - grafana.aws.2i2c.cloud 14 | tls: 15 | - secretName: grafana-tls 16 | hosts: 17 | - grafana.aws.2i2c.cloud 18 | 19 | prometheus: 20 | server: 21 | ingress: 22 | enabled: true 23 | hosts: 24 | - prometheus.aws.2i2c.cloud 25 | tls: 26 | - secretName: prometheus-tls 27 | hosts: 28 | - prometheus.aws.2i2c.cloud 29 | persistentVolume: 30 | size: 500Gi 31 | 32 | cluster-autoscaler: 33 | enabled: true 34 | autoDiscovery: 35 | clusterName: 2i2c-aws-us 36 | awsRegion: us-west-2 37 | 38 | redirects: 39 | rules: 40 | - from: researchdelight.2i2c.cloud 41 | to: showcase.2i2c.cloud 42 | 43 | calico: 44 | enabled: true 45 | -------------------------------------------------------------------------------- /config/clusters/awi-ciroh/enc-workshop.secret.values.yaml: -------------------------------------------------------------------------------- 1 | basehub: 2 | jupyterhub: 3 | hub: 4 | config: 5 | DummyAuthenticator: 6 | password: ENC[AES256_GCM,data:Ha1wNRLwH57huak2WqyRAjr6GTV0Yeo=,iv:D1JTLMRWb3/zz9WE0rQ+261g8dDJHAaiTBbvL2EqIQM=,tag:gJOrSlL5IINis2l9QRd1lA==,type:str] 7 | sops: 8 | gcp_kms: 9 | - resource_id: projects/two-eye-two-see/locations/global/keyRings/sops-keys/cryptoKeys/similar-hubs 10 | created_at: '2025-05-07T08:07:12Z' 11 | enc: CiUA4OM7eIHDivZcDvslLg3elkX0T4pYR0gVADUKsPLIdE9tM0IOEkkAWOWv8DPVHy3QKWEx9fdZ4KRPWJMSG8CKO+gfeqYiy+AOSoLZZpF4r3PXiCOkQIImX3yZbe2IrxHN0asSXzsJop8A2JMaTAkn 12 | lastmodified: '2025-05-07T08:08:22Z' 13 | mac: ENC[AES256_GCM,data:Sj1Go2kNtwDXRlCp6iHm4zlG7butJk4DXViZ4nXW0klrbpYbzwn93OJG+QFs/2w+v+WYAvgGJKBp9qhuP27Rj8QuX2TBw41VZ1j9/WH3h0fDmUKxg8xAkInGpPN7qDVY7X6k+ltvaTuTsa9mpi3xkVBZ0ug07ZB/E38xaOLQnyI=,iv:2TYHyWQVEYRFOLzr+QpA9E+Mw8p8pVABlynHO4gPknI=,tag:OIeC5yWJ23lTlyIJ3QGhdA==,type:str] 14 | unencrypted_suffix: _unencrypted 15 | version: 3.10.2 16 | -------------------------------------------------------------------------------- /config/clusters/catalystproject-africa/wits.values.yaml: -------------------------------------------------------------------------------- 1 | jupyterhub: 2 | ingress: 3 | hosts: [wits.af.catalystproject.2i2c.cloud] 4 | tls: 5 | - hosts: [wits.af.catalystproject.2i2c.cloud] 6 | secretName: https-auto-tls 7 | custom: 8 | homepage: 9 | templateVars: 10 | org: 11 | name: Catalyst Project, Africa - WITS 12 | hub: 13 | config: 14 | JupyterHub: 15 | authenticator_class: github 16 | GitHubOAuthenticator: 17 | oauth_callback_url: https://wits.af.catalystproject.2i2c.cloud/hub/oauth_callback 18 | allowed_organizations: 19 | - CatalystProject-Hubs:wits 20 | Authenticator: 21 | admin_users: 22 | - gentlelab2016 23 | singleuser: 24 | nodeSelector: 25 | 2i2c/hub-name: wits 26 | jupyterhub-home-nfs: 27 | quotaEnforcer: 28 | config: 29 | QuotaManager: 30 | hard_quota: 1 # in GiB 31 | eks: 32 | volumeId: vol-0c891ce78c5d76b2b 33 | nfs: 34 | pv: 35 | serverIP: 10.100.176.128 36 | -------------------------------------------------------------------------------- /config/clusters/nasa-cryo/support.values.yaml: -------------------------------------------------------------------------------- 1 | prometheusIngressAuthSecret: 2 | enabled: true 3 | 4 | cluster-autoscaler: 5 | enabled: true 6 | autoDiscovery: 7 | clusterName: nasa-cryo 8 | awsRegion: us-west-2 9 | 10 | grafana: 11 | grafana.ini: 12 | server: 13 | root_url: https://grafana.cryointhecloud.2i2c.cloud/ 14 | auth.github: 15 | enabled: true 16 | allowed_organizations: 2i2c-org 17 | ingress: 18 | hosts: 19 | - grafana.cryointhecloud.2i2c.cloud 20 | tls: 21 | - secretName: grafana-tls 22 | hosts: 23 | - grafana.cryointhecloud.2i2c.cloud 24 | 25 | prometheus: 26 | server: 27 | ingress: 28 | enabled: true 29 | hosts: 30 | - prometheus.cryointhecloud.2i2c.cloud 31 | tls: 32 | - secretName: prometheus-tls 33 | hosts: 34 | - prometheus.cryointhecloud.2i2c.cloud 35 | 36 | calico: 37 | enabled: true 38 | 39 | # FIXME: remove this once eksctl is fixed 40 | nvidiaDevicePlugin: 41 | aws: 42 | enabled: true 43 | -------------------------------------------------------------------------------- /config/clusters/projectpythia/support.values.yaml: -------------------------------------------------------------------------------- 1 | prometheusIngressAuthSecret: 2 | enabled: true 3 | 4 | prometheus: 5 | server: 6 | ingress: 7 | enabled: true 8 | hosts: 9 | - prometheus.projectpythia.2i2c.cloud 10 | tls: 11 | - secretName: prometheus-tls 12 | hosts: 13 | - prometheus.projectpythia.2i2c.cloud 14 | 15 | grafana: 16 | grafana.ini: 17 | server: 18 | root_url: https://grafana.projectpythia.2i2c.cloud/ 19 | auth.github: 20 | enabled: true 21 | allowed_organizations: 2i2c-org 22 | ingress: 23 | hosts: 24 | - grafana.projectpythia.2i2c.cloud 25 | tls: 26 | - secretName: grafana-tls 27 | hosts: 28 | - grafana.projectpythia.2i2c.cloud 29 | 30 | cluster-autoscaler: 31 | enabled: true 32 | autoDiscovery: 33 | clusterName: projectpythia 34 | awsRegion: us-west-2 35 | 36 | calico: 37 | enabled: true 38 | 39 | # FIXME: remove this once eksctl is fixed 40 | nvidiaDevicePlugin: 41 | aws: 42 | enabled: true 43 | -------------------------------------------------------------------------------- /config/clusters/2i2c/enc-grafana-token.secret.yaml: -------------------------------------------------------------------------------- 1 | grafana_token: ENC[AES256_GCM,data:f9nWjAA8g/hi3MKkqzixcbH+zGb1sfqJh49wPzEeaCb1W/1YsuYruNRgD6/plw==,iv:27PzO+ddxgz1fVYm0NI7P8Y+WO2W8J6fs5KB4QkbYxY=,tag:DIBR/OvCiXa9GUPllZCJyA==,type:str] 2 | sops: 3 | kms: [] 4 | gcp_kms: 5 | - resource_id: projects/two-eye-two-see/locations/global/keyRings/sops-keys/cryptoKeys/similar-hubs 6 | created_at: '2022-11-24T10:34:05Z' 7 | enc: CiUA4OM7eBAHhaKVbZJro2FrKbODaPJxdIgIn/7pDtBgAR+lCzpVEkkA+0T9hQHmRTK5npHdXaTR4vYp/ELzOcREmwQmdfpk4bAJivTCV6k23L5H83EU9T6Gz7QPNjcIsdrUjjAVpv/oczZ0ZlDfON8e 8 | azure_kv: [] 9 | hc_vault: [] 10 | age: [] 11 | lastmodified: '2022-11-24T10:34:06Z' 12 | mac: ENC[AES256_GCM,data:qT9F6OBi/PtlN5Iuc2fulYi0nDGFzXkvWcpiVsXYrOB2nE5+Oebx0vxgqYT9SMD36LKZ/qqivPVTp0TTMuDNmzasVeDi3JV1JdXBkNBBZBG21/VterVU/kLWXqar9whg5Oz/9e1KOatmSZfUqmnLyJ5mzpaKPWoeqqWp3JdDS4s=,iv:/MNVMXPC9R+8EHcoWOzfbfqJG5+JhwunquihwD8J2pI=,tag:33etiMoGdMD7rxDioMsvYw==,type:str] 13 | pgp: [] 14 | unencrypted_suffix: _unencrypted 15 | version: 3.7.3 16 | -------------------------------------------------------------------------------- /config/clusters/aimatx-2i2c-hub/cluster.yaml: -------------------------------------------------------------------------------- 1 | name: aimatx-2i2c-hub 2 | provider: aws 3 | provider_url: https://426578051359.signin.aws.amazon.com/console 4 | aws: 5 | account: 426578051359 6 | key: enc-deployer-credentials.secret.json 7 | clusterType: eks 8 | clusterName: aimatx-2i2c-hub 9 | region: us-west-2 10 | billing: 11 | paid_by_us: false 12 | support: 13 | helm_chart_values_files: 14 | - support.values.yaml 15 | - enc-support.secret.values.yaml 16 | hubs: 17 | - name: staging 18 | display_name: AIMATX staging 19 | domain: staging.aimatx.2i2c.cloud 20 | helm_chart: basehub 21 | helm_chart_values_files: 22 | - common.values.yaml 23 | - enc-common.secret.values.yaml 24 | - staging.values.yaml 25 | - enc-staging.secret.values.yaml 26 | - name: prod 27 | display_name: AIMATX 28 | domain: aimatx.2i2c.cloud 29 | helm_chart: basehub 30 | helm_chart_values_files: 31 | - common.values.yaml 32 | - enc-common.secret.values.yaml 33 | - prod.values.yaml 34 | - enc-prod.secret.values.yaml 35 | 36 | -------------------------------------------------------------------------------- /config/clusters/dubois/enc-grafana-token.secret.yaml: -------------------------------------------------------------------------------- 1 | grafana_token: ENC[AES256_GCM,data:0uqxsWcRDOl3OomMDVTHNdbSIs1L+jygqny4QM6fqP0IA3zqZu58vBbZNcjpQg==,iv:I5WnTdphpgYNPsQvn0GdSSNYWS0kHwEkmYYTpcevcTw=,tag:k84weMOdjbhLDB855Y5eIA==,type:str] 2 | sops: 3 | kms: [] 4 | gcp_kms: 5 | - resource_id: projects/two-eye-two-see/locations/global/keyRings/sops-keys/cryptoKeys/similar-hubs 6 | created_at: '2024-10-03T16:28:51Z' 7 | enc: CiUA4OM7eLpznvClzv6bk6n8MpAmvCvUEW9tQvoL5gcjdakBOdrREkkA5dG1Q0RHL3oiarOHnTDJCxadiZj0UHIMTe2zTjx57RR3ggvkLAiTS3Xz6xqhydNIDLtmyhEyRJJA+T3OBpnCN4Dvn+rYEoHT 8 | azure_kv: [] 9 | hc_vault: [] 10 | age: [] 11 | lastmodified: '2024-10-03T16:28:51Z' 12 | mac: ENC[AES256_GCM,data:3/kY8oB32I+Yvo+i653H6OLui1E0f01bEtuzPdOQwnnV21u/CjX45w3rETlv7/srEOTABZxs+KAeGFyOSbptdfoSKA+TsHaA+4eQaShlqxlGenm75iTfNjVfTUTD7FjmaKow29H4gXBXFuH6tstYqc9s3Klj0v3/RiiZyueDihI=,iv:/fNSJSaRoGuZbuA4PKHC9NJVc7tVVtyYPCnESkIkkW4=,tag:qUIJNI/Eq4atu+y19kZI2g==,type:str] 13 | pgp: [] 14 | unencrypted_suffix: _unencrypted 15 | version: 3.9.0 16 | -------------------------------------------------------------------------------- /config/clusters/hhmi/enc-grafana-token.secret.yaml: -------------------------------------------------------------------------------- 1 | grafana_token: ENC[AES256_GCM,data:DdJZ/CI4C0sF+kWR+HUsH+I6HSvjCGYCT/lUC+okzqjcpsddvR50rJDGA+L+Bg==,iv:HrRNa7/7f/9zoA8fzqWzPk7/Jq3990xEJCOUS4pZZw8=,tag:X+kVdvTxwFo+g3FVehqhag==,type:str] 2 | sops: 3 | kms: [] 4 | gcp_kms: 5 | - resource_id: projects/two-eye-two-see/locations/global/keyRings/sops-keys/cryptoKeys/similar-hubs 6 | created_at: '2023-09-14T10:18:17Z' 7 | enc: CiUA4OM7eO1Rw450WCGtZyiKk4grJ6527D9LymHLUWohgFkXcXnqEkkAq2nhVWNyylLfBvnpbRatur/Jc86LzDUwof7E6Yk3V+4HiVPr5IuttGYdHPPMhCcIWrWmVqSY4LhrEOkyLxxIcPb664T8+4M1 8 | azure_kv: [] 9 | hc_vault: [] 10 | age: [] 11 | lastmodified: '2023-09-14T10:18:17Z' 12 | mac: ENC[AES256_GCM,data:oDQgvzOjA6BrE74KMuosLER1en8N9szYfUDTzk2EnJGQ1owoqOzNAWfzCdKOE6uAcXtOARK8BuXGEH/YdqVMtey6W9tyjKgdpw92u+eeWU3oOUNuFIERs0uswQq6zlnyB6CUTezjxKo5yyTFPozhVjnmXiGV6IsGSXfA0zDfP7M=,iv:kVNuLyyHtTuybl23ytnGU6BvWRZR1ToHs4wB4PZgK1k=,tag:Nfr2mzcOf7ED6nZRT+AcZg==,type:str] 13 | pgp: [] 14 | unencrypted_suffix: _unencrypted 15 | version: 3.7.3 16 | -------------------------------------------------------------------------------- /config/clusters/jupyter-health/support.values.yaml: -------------------------------------------------------------------------------- 1 | prometheusIngressAuthSecret: 2 | enabled: true 3 | 4 | prometheus: 5 | server: 6 | ingress: 7 | enabled: true 8 | hosts: 9 | - prometheus.jupyter-health.2i2c.cloud 10 | tls: 11 | - secretName: prometheus-tls 12 | hosts: 13 | - prometheus.jupyter-health.2i2c.cloud 14 | 15 | grafana: 16 | grafana.ini: 17 | server: 18 | root_url: https://grafana.jupyter-health.2i2c.cloud/ 19 | auth.github: 20 | enabled: true 21 | allowed_organizations: 2i2c-org 22 | ingress: 23 | hosts: 24 | - grafana.jupyter-health.2i2c.cloud 25 | tls: 26 | - secretName: grafana-tls 27 | hosts: 28 | - grafana.jupyter-health.2i2c.cloud 29 | 30 | cluster-autoscaler: 31 | enabled: true 32 | autoDiscovery: 33 | clusterName: jupyter-health 34 | awsRegion: us-east-2 35 | 36 | calico: 37 | enabled: true 38 | 39 | # FIXME: remove this once eksctl is fixed 40 | nvidiaDevicePlugin: 41 | aws: 42 | enabled: true 43 | -------------------------------------------------------------------------------- /config/clusters/maap/enc-grafana-token.secret.yaml: -------------------------------------------------------------------------------- 1 | grafana_token: ENC[AES256_GCM,data:JK3SCP6n4xnVIrfHNshsBa9jZ3du/cJMHtjVfCUyyGR3suJiu//vbcNI+F0f4g==,iv:usVO4kJ2h6h+AKtjpvx7yIHlf1luhZxkpN4S1eN5SbI=,tag:8Yx3e2VmZFnQvg0SfOGbrA==,type:str] 2 | sops: 3 | kms: [] 4 | gcp_kms: 5 | - resource_id: projects/two-eye-two-see/locations/global/keyRings/sops-keys/cryptoKeys/similar-hubs 6 | created_at: '2024-12-05T09:01:44Z' 7 | enc: CiUA4OM7eGy0RJQC6pst8e8nNBK+GLL7dLDYCLmAdHvG9G/cG9WHEkkAnGhyNggsDFpcnzfY2IFQeB4c6IIJDwWTFxyIZ+G6W9S2ZSnG1cySSzAIgABqr5C285Zj1IXKYxtqNsr5tyhssXNhNTLhY3aZ 8 | azure_kv: [] 9 | hc_vault: [] 10 | age: [] 11 | lastmodified: '2024-12-05T09:01:44Z' 12 | mac: ENC[AES256_GCM,data:pBAmQAHXVZiXA8uB0ZZfYaJVRPNOOkEgc9MQHO/3YYuPwuc8hb0EP7IZREpkTxD7cRosAlTPovWq8++MROmsj/LI4M9XuQn1PwrKtMS0tBdDZnm8z2KHdnwwzEqpKB1wkyVLSNleqJHLDChuGjylhltFmSWoNrX2srTebgxqAe4=,iv:Lhc2RRqthvjEwSBOYMJmdCDz7C6If5kLwKPxBHW8dWc=,tag:AfeasGMp2P6uf9YhlZbNrw==,type:str] 13 | pgp: [] 14 | unencrypted_suffix: _unencrypted 15 | version: 3.8.1 16 | -------------------------------------------------------------------------------- /config/clusters/victor/enc-grafana-token.secret.yaml: -------------------------------------------------------------------------------- 1 | grafana_token: ENC[AES256_GCM,data:OTBQAgpyShzEm+eHfQJVtEr83tJf8psaFPkjqTPozEaRpMqCGG7a3hE4+h79/g==,iv:hN3AirWeW8IdHG76reiCyUl/91PgQyBWpCU8qZGiuMQ=,tag:e+QQnBwSz4sAO4bXSjJ8Wg==,type:str] 2 | sops: 3 | kms: [] 4 | gcp_kms: 5 | - resource_id: projects/two-eye-two-see/locations/global/keyRings/sops-keys/cryptoKeys/similar-hubs 6 | created_at: '2024-02-29T21:51:08Z' 7 | enc: CiUA4OM7eNjdvopHWnFtTnpID9wlVgIAwCva6LeATWpgvbD6J7VREkkAXoW3JpUHvVrB4am3g31cx/R/jYY/fzECxMnu2Q74CsSj6ZBQnogOpebaoFniyFkxFOTkoJKjC7FggJEufVHYcVOtpEwZjE3P 8 | azure_kv: [] 9 | hc_vault: [] 10 | age: [] 11 | lastmodified: '2024-02-29T21:51:08Z' 12 | mac: ENC[AES256_GCM,data:h1MwQnXBeF6ge1BUhSfFLpicY3YLg2WK1wAVztEv6yfXf8kAVboPOFy0TBzToUXRmMqgSjcjXLOBoEIuuTjUNkseZjaZ1dRC3/z7XF8n2OzvaCaW6vR19LoKA4IrmWh4Agh8ImQ7ISFabN3MDpeJVOjx1xW83/pC4b1qYG+l88I=,iv:jqQ4U+ZZ22We+kbUFP/ZkOWEviybAZXDvou7pjEiPv0=,tag:0RK4MbWsJtUIHpxBw5BLJQ==,type:str] 13 | pgp: [] 14 | unencrypted_suffix: _unencrypted 15 | version: 3.8.1 16 | -------------------------------------------------------------------------------- /config/clusters/awi-ciroh/enc-grafana-token.secret.yaml: -------------------------------------------------------------------------------- 1 | grafana_token: ENC[AES256_GCM,data:UTHTVgKtNU8OXvFV7/51oQcd80LLLj1SQUtpyWOVJq8d7ibXsXzkdBU7Bj9nSw==,iv:IRuglWBq0A6dqGL48HkrNjLY4HAzYp1JAZcf/6zq474=,tag:2vZahtVJp0MmkLJ3AU55nw==,type:str] 2 | sops: 3 | kms: [] 4 | gcp_kms: 5 | - resource_id: projects/two-eye-two-see/locations/global/keyRings/sops-keys/cryptoKeys/similar-hubs 6 | created_at: '2024-06-21T11:56:23Z' 7 | enc: CiUA4OM7eM6LkVOLepgcOQJRevV+XPgBT09zYjc1EhQwu3U571QTEkkAWX/fcclxlynzzCh21eqcBBh4PamxpV72nsxSNfUuoHBHZ+gAQaNll0juOwbI+KqRuWXdexvVZgL7m50Bh/ghdLYMA4K2O5vK 8 | azure_kv: [] 9 | hc_vault: [] 10 | age: [] 11 | lastmodified: '2024-06-21T11:56:23Z' 12 | mac: ENC[AES256_GCM,data:uKUAbHfnb8vEZekCTEoC3XHwg5hBWr+Sw3e5vZeQGfGESaA+D8zGN4DkyhHut5sK4mBCbmFzgZhJ3mjD17JlDWc9/y2V1wR4vhTAMKi2ucrQTLfHE5NmxjYcbXhJPWi4qVm35UZhHlDk/teYGIvQpJRUYGBadi9mOCUl5G2XnBk=,iv:PoyNRaFHJXfHvDdl2iOdM8rgKoA6FI6IulPlX/gZOV8=,tag:AIVbRC07UZZE6lid81pM8g==,type:str] 13 | pgp: [] 14 | unencrypted_suffix: _unencrypted 15 | version: 3.8.1 16 | -------------------------------------------------------------------------------- /config/clusters/cloudbank/enc-grafana-token.secret.yaml: -------------------------------------------------------------------------------- 1 | grafana_token: ENC[AES256_GCM,data:FDda8p/5Tz4VvkgWGCZk8cwDiX+9F3OHisT7nw7ZdjZBgMelkYXJDfFFJvHSAA==,iv:mKOjnCIQh3MNDsASeVLuElBWUwcGsPrwkLUGS4r6/UI=,tag:/V23t2GS1S/ES1BybFTSyQ==,type:str] 2 | sops: 3 | kms: [] 4 | gcp_kms: 5 | - resource_id: projects/two-eye-two-see/locations/global/keyRings/sops-keys/cryptoKeys/similar-hubs 6 | created_at: '2022-11-24T11:51:01Z' 7 | enc: CiUA4OM7eM8ZZjs2Fy6vQtthKqGTGwGZtY1BQJv4TOZsuQLLwN9JEkkA+0T9hU3I8X7F44PALC4Jbu4vGdZ4yM4i6vvTvKISacgMgWrk00BqSsdldLYvFYh4MuDT6ZQVS5vJnxMP4dN9ipqjeRnoYYK3 8 | azure_kv: [] 9 | hc_vault: [] 10 | age: [] 11 | lastmodified: '2022-11-24T11:51:02Z' 12 | mac: ENC[AES256_GCM,data:D9F/sQAhSErBE5ZM5Aoa0gjiSv8mzuFcH16e5hiz6LdJs+v1k4nIDBFA9gyF2o9Fk/liPlvwyObWIN8gv5lucoLnL+q8Oq2V3i/ExgA7huQrstsbIH1bZCpJmozeAInBX2TdCKjPmifBLEmlEMHkVSEZu+JlnXloNrCBLu2DMYA=,iv:D7/rh8rcQXLnsBIgeUzVNZsqM4vQSEH96uItpCaKlgs=,tag:ugpNjNVTxscTTLwpSZ4X0A==,type:str] 13 | pgp: [] 14 | unencrypted_suffix: _unencrypted 15 | version: 3.7.3 16 | -------------------------------------------------------------------------------- /config/clusters/disasters/enc-grafana-token.secret.yaml: -------------------------------------------------------------------------------- 1 | grafana_token: ENC[AES256_GCM,data:is6ggfQ924wQua/zOre7M6Kj8AcPQUIvqqTJ7KcuZRVProFr7zJ7brLURqAt/Q==,iv:fd40rMcGLf74cWyx3IWkxDb5wA+OZdMR4rLZVTUjsXk=,tag:z7xqp/t0rS41pjI1hmsBIA==,type:str] 2 | sops: 3 | kms: [] 4 | gcp_kms: 5 | - resource_id: projects/two-eye-two-see/locations/global/keyRings/sops-keys/cryptoKeys/similar-hubs 6 | created_at: '2025-03-20T14:50:01Z' 7 | enc: CiUA4OM7eOb0DvbHkWI2rgu0LJJcDNn8exrShalKeHA8FGMW10qVEkgAWOWv8IVAV8hw2ULGW29EojWTjPQQxvwYxnGOXUZmShwKcmD/Q4BK+M4Ra1B8LutEuNZ2Fc8nBolJQOsi8XnS+5zmcvZ9QhU= 8 | azure_kv: [] 9 | hc_vault: [] 10 | age: [] 11 | lastmodified: '2025-03-20T14:50:01Z' 12 | mac: ENC[AES256_GCM,data:Y/xKdxB2MIa8697lB5r23SJWJFWgi4tMs0H0RogHKrp1HT7B8lRAfXk4gTZQdfI+AeW4GDbfPOORL6KOc2SMOmLNgyhYeIaIAngFd1+tKA+FffLgnRoTkzpR9vNUVas2fauTKzwVEfVSJhFL4kmciW+nnr+oHmU7GhauCPslsFA=,iv:aNKPJyz/4gmPoCjyue2dBvQrGsvlo4QCrsG39YkEXjM=,tag:Cvf4uhgZuF//kPy77z0ElQ==,type:str] 13 | pgp: [] 14 | unencrypted_suffix: _unencrypted 15 | version: 3.8.1 16 | -------------------------------------------------------------------------------- /config/clusters/earthscope/enc-grafana-token.secret.yaml: -------------------------------------------------------------------------------- 1 | grafana_token: ENC[AES256_GCM,data:uS1p6t0OxZUH3ScuGU5JEuqPDEt41mLRPIDFTKcPT/du77G7+Rjn+a44P3GGmg==,iv:8W+Qp/fEu1Hb3yM5V0QyGMxb6buNfwGZBTfa0nLJ60Y=,tag:H8XGNFfYkqyT2TfD8MoWWA==,type:str] 2 | sops: 3 | kms: [] 4 | gcp_kms: 5 | - resource_id: projects/two-eye-two-see/locations/global/keyRings/sops-keys/cryptoKeys/similar-hubs 6 | created_at: '2024-06-25T12:43:28Z' 7 | enc: CiUA4OM7eLjVt43HHUBC/bXJmQ4BJQCU57/5jVI3DYnhu/TEQSh5EkkAWX/fcZ9r2PAgFe4AFefRPUf31LfneWgwWgGnOl57vxaC14WsD4xh8RsjET8mFxDCZIYjfWx0z9OqkoCOnSOFYXecUa6o5R9g 8 | azure_kv: [] 9 | hc_vault: [] 10 | age: [] 11 | lastmodified: '2024-06-25T12:43:28Z' 12 | mac: ENC[AES256_GCM,data:92CbFOHiRi/cu3aje2AOTCFKoXudpRvfH0+j7JTnhSZwR2eYY22IwYUGj3frRftevkh6IC6eVC8sf8YecxgNvIhrHVgl9ScSbWo24P92qTx4Zro1OLQiw55nBR00X22sJ8354QG8M1jHGOe8VonfEnOppLXv5pTUI4MzHmKHInw=,iv:Fnty/1xzKg4DisrWBxdmdKNgSjIzQZclVXAFnbDRnjM=,tag:DaNZ0YyK3khRa35XOVMGsw==,type:str] 13 | pgp: [] 14 | unencrypted_suffix: _unencrypted 15 | version: 3.8.1 16 | -------------------------------------------------------------------------------- /config/clusters/nasa-cryo/cluster.yaml: -------------------------------------------------------------------------------- 1 | name: nasa-cryo 2 | provider: aws 3 | provider_url: https://2i2c.awsapps.com/start#/ 4 | aws: 5 | account: 574251165169 6 | key: enc-deployer-credentials.secret.json 7 | clusterType: eks 8 | clusterName: nasa-cryo 9 | region: us-west-2 10 | billing: 11 | paid_by_us: true 12 | support: 13 | helm_chart_values_files: 14 | - support.values.yaml 15 | - enc-support.secret.values.yaml 16 | hubs: 17 | - name: staging 18 | display_name: NASA Cryo in the Cloud (staging) 19 | domain: staging.hub.cryointhecloud.com 20 | helm_chart: daskhub 21 | helm_chart_values_files: 22 | - common.values.yaml 23 | - enc-common.secret.values.yaml 24 | - staging.values.yaml 25 | - enc-staging.secret.values.yaml 26 | - name: prod 27 | display_name: NASA Cryo in the Cloud (prod) 28 | domain: hub.cryointhecloud.com 29 | helm_chart: daskhub 30 | helm_chart_values_files: 31 | - common.values.yaml 32 | - enc-common.secret.values.yaml 33 | - prod.values.yaml 34 | - enc-prod.secret.values.yaml 35 | -------------------------------------------------------------------------------- /config/clusters/nasa-veda/enc-grafana-token.secret.yaml: -------------------------------------------------------------------------------- 1 | grafana_token: ENC[AES256_GCM,data:b3/JtIGNkIJhk7CPbKZV0DOO1xiBEMEmJQ7mZtXJWGvi+vHqd7RiDdk1ohaqhw==,iv:vrLtA/5QdU0tKRtiRef5MgtXnv/Fv2zsenTWom3LIbU=,tag:m9k0rK6SIcbjN54g+5WJRA==,type:str] 2 | sops: 3 | kms: [] 4 | gcp_kms: 5 | - resource_id: projects/two-eye-two-see/locations/global/keyRings/sops-keys/cryptoKeys/similar-hubs 6 | created_at: '2023-01-26T15:06:25Z' 7 | enc: CiUA4OM7eBm4d/vDAZ621HhIsfEkXZVDnEIUWyxsogMfrhfTuG6oEkkA+0T9hVuBSbt2GAwg2RLtE5U2ZWhUE3QyblPCcEN2Y/EP2GQaBzDAw5yZ8MGXV7SYtjMjcReOdMENg6P+QC9T9NEuNBvXSvqI 8 | azure_kv: [] 9 | hc_vault: [] 10 | age: [] 11 | lastmodified: '2023-01-26T15:06:25Z' 12 | mac: ENC[AES256_GCM,data:4/ksvtJugnsABvCAADyw2BpE6oGCeU5a0WD+PZUSb5YRa1iJMrJg7WyX5FRvtaBhfBIDUK5S5Z5ZQvUNM1+YsPoA3wavXvOjIXRu95BnBcZUYzqICQRhB9dBgztlzKIH5wSDVE/89bwy//05ml7zSOyWBwnXUgpeH9Pm3CB5X7I=,iv:+JJ48BLtWv6xRLjiqxNwbwRuWEk1oOXT89XOHqyyBTQ=,tag:qDmNvo48202MPQ/sd9ihgw==,type:str] 13 | pgp: [] 14 | unencrypted_suffix: _unencrypted 15 | version: 3.7.3 16 | -------------------------------------------------------------------------------- /config/clusters/opensci/enc-grafana-token.secret.yaml: -------------------------------------------------------------------------------- 1 | grafana_token: ENC[AES256_GCM,data:FUDyTxRjgJ3FrEzZ4FJeNCVOYtfAVGtz82Xjzlq0JSDrcDSdcOVc5VRZAixo6g==,iv:wP1WsvpXh4T6i0zKQatAmYS/+GRa5vwmRtOUz82VUWY=,tag:WY1AuW4YhYE54ij6pIjmZQ==,type:str] 2 | sops: 3 | kms: [] 4 | gcp_kms: 5 | - resource_id: projects/two-eye-two-see/locations/global/keyRings/sops-keys/cryptoKeys/similar-hubs 6 | created_at: '2024-02-27T08:21:10Z' 7 | enc: CiUA4OM7eJwLqe0B1wFs4I0fTW9ca4t9EVaupRu6drh9jlu2BMxSEkkAXoW3JoVJBEtoW1U21/GHpWilS78im8nQUr/+YbIpFgHLJO1hsEbVqIjhJQ82ZfYryz9ozn/4/Fwxlzx6XymhncSnR/1KllE1 8 | azure_kv: [] 9 | hc_vault: [] 10 | age: [] 11 | lastmodified: '2024-02-27T08:21:11Z' 12 | mac: ENC[AES256_GCM,data:dgsHlAhpVrM3246Mmk+Hiemmh4MVrkd75LYNx7ffyw0ojThJ8/wTLL8Bio25Py7vzQR10r3qVtj1+TNnDXE3cGHPTpXBuBS4RfdI63/+SAdoONL8T0J0zUM58opWfkhp3XaB5JAKJH4JTP+WGVDGmYWiyRC6kbxvn7fhLqq509U=,iv:SZ+s+LU+EJHNPbfGpHpkOzS4aTUWT0fHGyX5om0jH2w=,tag:F0vuPTXtXVUqlpCOKcLaAA==,type:str] 13 | pgp: [] 14 | unencrypted_suffix: _unencrypted 15 | version: 3.7.3 16 | -------------------------------------------------------------------------------- /config/clusters/reflective/enc-grafana-token.secret.yaml: -------------------------------------------------------------------------------- 1 | grafana_token: ENC[AES256_GCM,data:8VACeefUnaaKEMXIEDo/3OBjXY0A2ddleR6DHAlt0jxjFjyfvasvJC3CQdkYhA==,iv:hu886m5a0ML7zA3sgPlhuPNgs1y+nQGeSU3j/3wL5wk=,tag:yt5OUD38oyT/ig9F8mvFJg==,type:str] 2 | sops: 3 | kms: [] 4 | gcp_kms: 5 | - resource_id: projects/two-eye-two-see/locations/global/keyRings/sops-keys/cryptoKeys/similar-hubs 6 | created_at: '2025-04-09T13:08:33Z' 7 | enc: CiUA4OM7eI/OVq/yFtdXPMS8wmxHsLACSlVly5ZDHCihY/dOZeGCEkkAWOWv8Nydee83vNd3uuTs5uwgM+r+HogTVUJ1zxzVhMr5rHxfWCoK/Te/PoiR8NSSTuIUgkRybvFQyH+0vIFwxZlyQ6vEV1H5 8 | azure_kv: [] 9 | hc_vault: [] 10 | age: [] 11 | lastmodified: '2025-04-09T13:08:34Z' 12 | mac: ENC[AES256_GCM,data:W0pjJhvowuoTXOCNOSjksp84Catsz9rd0X4kZ2yoYps5vGGowF9EwVLUX4kPt1O5rW/hlv7voSI5WjoJQVmeMxsaRDjCz0l/Rp+wrhQVJzHOnLyWchx8HfD8eaxYCSV+s0y+hKisX7JVIdfKQ2OgZIfm75YQuofyUMi/E+81jPc=,iv:n1oyFb/wsenB72539P7yaoA+n+4SQ1tzcYDDGWY/wIw=,tag:OVAAeKstcM/xVH2ThssWBg==,type:str] 13 | pgp: [] 14 | unencrypted_suffix: _unencrypted 15 | version: 3.9.1 16 | -------------------------------------------------------------------------------- /config/clusters/smithsonian/enc-grafana-token.secret.yaml: -------------------------------------------------------------------------------- 1 | grafana_token: ENC[AES256_GCM,data:P8TRLJP0yPIiCNHQ5Ucg0mfOf0QQngZLWI01RN7sGU72T6j3XOMncfeMxEM9hA==,iv:bypdfN2NCFXPwFxXuzxsFi5uVgluJk99v3QXdEIB8FE=,tag:s9nL7rlLtgncTU9+M6Mm5w==,type:str] 2 | sops: 3 | kms: [] 4 | gcp_kms: 5 | - resource_id: projects/two-eye-two-see/locations/global/keyRings/sops-keys/cryptoKeys/similar-hubs 6 | created_at: '2023-04-12T15:07:49Z' 7 | enc: CiUA4OM7eNbotNIlYlAvr98lut5KmeOpiXr7hYPE0sEdHEwAzBMoEkkALQgViPbgV3x3apboiOkHki4gKKCEMhuwxiCvfpDg4cHWsCOey8sF+F0W3gVem1aZuW19yjPMNy3NrvSb2NNrXgatO/7eVFgr 8 | azure_kv: [] 9 | hc_vault: [] 10 | age: [] 11 | lastmodified: '2023-04-12T15:07:49Z' 12 | mac: ENC[AES256_GCM,data:J4VwOq/MkIebyLxe9ZpNYBn/PDFW1zV45sWpvIU8AevPrdT9U7WQO5XrVoc4zfy1b8VZ7BhI6jcyhlSb0wWhGbvnyCXDrx4Tuluql0glgaywFgBxXaLv3M51RfAfWMkZMHMbZd3ErYYJixf2fvf3CF4hp44G7jk1NHLn6/Tkqho=,iv:5LbDpb8x60IWWh9TI0HoslT/PFywhgEQbiA2rYA6Wwc=,tag:SVuB8Qn/bNfZ74oDsshhgw==,type:str] 13 | pgp: [] 14 | unencrypted_suffix: _unencrypted 15 | version: 3.7.2 16 | -------------------------------------------------------------------------------- /config/clusters/strudel/enc-grafana-token.secret.yaml: -------------------------------------------------------------------------------- 1 | grafana_token: ENC[AES256_GCM,data:irWWJLHCQeeaW37qi0BHDiLfFdJ9vctBjEI0owv+2xSY1MerlE3MY+Mmi20lTg==,iv:5KPENEOcETgtEkVti1prJ0qsmm5+lSepUTZ/5O3TIvA=,tag:OgeLAIgFpek4zyG5rhtY7w==,type:str] 2 | sops: 3 | kms: [] 4 | gcp_kms: 5 | - resource_id: projects/two-eye-two-see/locations/global/keyRings/sops-keys/cryptoKeys/similar-hubs 6 | created_at: '2024-10-01T12:59:53Z' 7 | enc: CiUA4OM7eNrdiaLiPocfJTCLBwuM9YbI9qK1iBBp8+xYLziPl3ncEkkA5dG1Q93A5dIvMNu3945Iw/yUFQLgEofvzwhJYfegRLvKywnyzPmRHo2IfphssdM5Pe0JXpxywt0jv2nXEGyX+z2z+iYuGDD0 8 | azure_kv: [] 9 | hc_vault: [] 10 | age: [] 11 | lastmodified: '2024-10-01T12:59:53Z' 12 | mac: ENC[AES256_GCM,data:oNJ6wS4gCnMYyGOcWnDcP3X5HWT7bHPNjA/CTrljKEftzp0HtZJab66rJe94jgNnti007HfV34BD+tkikYPXo/8MAEcKROJ++Hj/JbUDOR0vYpcYQuOJTlYKGH52g41WlsENgRSxulO+wb7OQykokQNR98ihOCrrq0mmLXj3fG4=,iv:/xfa4gtfSakXKTz+8To4PeARl1U84p0EjWaXTbGtN8M=,tag:kq71ofPuXPpGnop38HDw4Q==,type:str] 13 | pgp: [] 14 | unencrypted_suffix: _unencrypted 15 | version: 3.8.1 16 | -------------------------------------------------------------------------------- /config/clusters/temple/support.values.yaml: -------------------------------------------------------------------------------- 1 | prometheusIngressAuthSecret: 2 | enabled: true 3 | 4 | 5 | 6 | prometheus: 7 | server: 8 | persistentVolume: 9 | size: 100Gi 10 | ingress: 11 | enabled: true 12 | hosts: 13 | - prometheus.temple.2i2c.cloud 14 | tls: 15 | - secretName: prometheus-tls 16 | hosts: 17 | - prometheus.temple.2i2c.cloud 18 | 19 | grafana: 20 | grafana.ini: 21 | server: 22 | root_url: https://grafana.temple.2i2c.cloud/ 23 | auth.github: 24 | enabled: true 25 | allowed_organizations: 2i2c-org 26 | ingress: 27 | hosts: 28 | - grafana.temple.2i2c.cloud 29 | tls: 30 | - secretName: grafana-tls 31 | hosts: 32 | - grafana.temple.2i2c.cloud 33 | 34 | cluster-autoscaler: 35 | enabled: true 36 | autoDiscovery: 37 | clusterName: temple 38 | awsRegion: us-west-2 39 | 40 | calico: 41 | enabled: true 42 | 43 | # FIXME: remove this once eksctl is fixed 44 | nvidiaDevicePlugin: 45 | aws: 46 | enabled: true 47 | -------------------------------------------------------------------------------- /config/clusters/ubc-eoas/enc-grafana-token.secret.yaml: -------------------------------------------------------------------------------- 1 | grafana_token: ENC[AES256_GCM,data:F3/Wa/LJ53XazQacP3YaXFf9Avl/4A0ZPCf4wgu4uU3Snq33w2UPDFh2wPLZIw==,iv:Em8otKknoInuN1IAw+/edNjExJDsF1SaIlxy4mnl8h8=,tag:NMJcBocV7CNG3fu2KivyQQ==,type:str] 2 | sops: 3 | kms: [] 4 | gcp_kms: 5 | - resource_id: projects/two-eye-two-see/locations/global/keyRings/sops-keys/cryptoKeys/similar-hubs 6 | created_at: '2023-01-11T18:20:16Z' 7 | enc: CiUA4OM7eJDGCW4KXRljBZFNS3LolWckEW6jQJ+Fv4pW1eRH8m5UEkkA+0T9half6VTOYH4EEIlrbvVunwfOT8lYOM02fet7DlB4gQkdAZdh13EVwGOS1iwlH3lorWvn1EStyU73aBk30kOw9A3b32Il 8 | azure_kv: [] 9 | hc_vault: [] 10 | age: [] 11 | lastmodified: '2023-01-11T18:20:16Z' 12 | mac: ENC[AES256_GCM,data:cABnpH/miorK7cXOXnlHLHmlUL3/M/mFZal1ZwI2Xpx7UuIiix/LFo/CNYe9wlOX/6bJfQnPHbvJfGJV0e9CniPfn6tPi5BUEEn+WMw5w3ZGIo+t4PDAelasH3YDg+YAOoRyBJp/yqZAxKwiDLFv82RNtg8/Fw6jAivYFaXRzJ0=,iv:BdkV7sRdBzPg4zd6RSJ+ojc4nL7c81EiF/7gWp3lZrM=,tag:1sKC6+EzhO9Fp96V8SjM9g==,type:str] 13 | pgp: [] 14 | unencrypted_suffix: _unencrypted 15 | version: 3.7.2 16 | -------------------------------------------------------------------------------- /config/clusters/utoronto/enc-grafana-token.secret.yaml: -------------------------------------------------------------------------------- 1 | grafana_token: ENC[AES256_GCM,data:QZahZIvf+EKQPolv9RFSEJy+OWqghBM+ejOWAFKdQVjLyklEukuwXJnDDoUWPw==,iv:PU+dsYOO6qEJE6zoCTjkpvY+fR5pQ9MJ1Nnhn318zAc=,tag:ffjtznQJNmDSHURcKwGjow==,type:str] 2 | sops: 3 | kms: [] 4 | gcp_kms: 5 | - resource_id: projects/two-eye-two-see/locations/global/keyRings/sops-keys/cryptoKeys/similar-hubs 6 | created_at: '2023-02-17T04:03:31Z' 7 | enc: CiUA4OM7eLRUO7RuJad23ABqIeYgpsMJtvxdNz3E8T20IV2u8i3qEkgA+0T9hZhp8XKyUPxjUIXkEMhS5dbymfY+7HrCO9qh9HG/F5QIyL/QefFilBENh9liQt3b58DreDJH47C5Qsu5Un+gdt5vN9w= 8 | azure_kv: [] 9 | hc_vault: [] 10 | age: [] 11 | lastmodified: '2023-02-17T04:03:31Z' 12 | mac: ENC[AES256_GCM,data:uIgLocKhcKWS9/jaWXQdJ5yp1PFwf87OnJZBnEQqO6TbBSmjQmo3PizX+My1csRJ6iSACJNq6218/7i689Vxt4YjvQSZ9VNfMl+6pUgwjV+Z+guYdcvFhIYvRvZV1vaSnFD2o8yVgtiRc8+l+HS/0vnXAcbZure2zgzWXALXG74=,iv:g47wnZK5R93XuJW9f7YD9WvvU/m6ICQ6dOvRM+xG6go=,tag:Edh9xXZLyFTyoqhRXyj8iA==,type:str] 13 | pgp: [] 14 | unencrypted_suffix: _unencrypted 15 | version: 3.7.2 16 | -------------------------------------------------------------------------------- /docs/howto/troubleshoot/prometheus.md: -------------------------------------------------------------------------------- 1 | # Troubleshoot prometheus issues 2 | 3 | We use prometheus data exposed via grafana to troubleshoot a lot of other 4 | issues, but sometimes prometheus itself can have issues and not start. 5 | This page documents various issues that might be causing that, and how 6 | to address them. 7 | 8 | ## Running out of disk space 9 | 10 | If there are enough metrics retained for long enough, prometheus will 11 | run out of disk space and not record any more metrics. Increasing the 12 | size of the disk will fix this issue. The default is set in 13 | `helm-charts/support/values.yaml` to `100Gi`, but can be increased 14 | for a specific cluster in its `support.values.yaml` file: 15 | 16 | ```yaml 17 | prometheus: 18 | server: 19 | persistentVolume: 20 | # 100Gi was too little 21 | size: 200Gi 22 | ``` 23 | 24 | Doing a deploy after this should be sufficient, as Kubernetes will 25 | [dynamically resize the volume](https://kubernetes.io/blog/2018/07/12/resizing-persistent-volumes-using-kubernetes/) 26 | -------------------------------------------------------------------------------- /config/clusters/2i2c-jetstream2/enc-grafana-token.secret.yaml: -------------------------------------------------------------------------------- 1 | grafana_token: ENC[AES256_GCM,data:QDK+JeBNMr6pcnpW55IwrVcWo9WcFmj8UjUv7JzYA77F3AY9sJzhzV5ZLp44FA==,iv:sUooRgQjkH9v33x5noaQmMAVyhjs69sB2wO1VH3N3jM=,tag:zZ3c+t4NdGsS9XDIFn2y1A==,type:str] 2 | sops: 3 | kms: [] 4 | gcp_kms: 5 | - resource_id: projects/two-eye-two-see/locations/global/keyRings/sops-keys/cryptoKeys/similar-hubs 6 | created_at: '2025-02-28T15:02:32Z' 7 | enc: CiUA4OM7eEU7o4l3czeOitFW8xhW1HlP2vjZA+Bt5r5IUlrbknPaEkkAWOWv8O5xFAtvA/bMRJft7T8oPU7mkWvf7EOOcvw8m0Q/892PkH79k2ImrNyoFifmXAlo23WJl+KwNb5cd1nxRUryT9qU8OjO 8 | azure_kv: [] 9 | hc_vault: [] 10 | age: [] 11 | lastmodified: '2025-02-28T15:02:33Z' 12 | mac: ENC[AES256_GCM,data:uoqB5UPcBmxS4uuZc1SOLsTLbfKiS1+vmrTnNpZOr0dmbk+2b5OipL3RD/eBX9VlDrqt4KMbyQYpLzxN5CUCfqTJ8hvElxPelcY4Br8ImEJsynpHlvE8lPdniaN3qCyJ+NUwK8R80hgZre3VMmtyjI9zKmGnFEoqCHQw1nzz6Mk=,iv:yXr6FlFojmiiV6UnOEcS2KavyZF3zS6wk7lgdk9/LWs=,tag:C/dNiKzM3YzIiMy+zJZ/cQ==,type:str] 13 | pgp: [] 14 | unencrypted_suffix: _unencrypted 15 | version: 3.8.1 16 | -------------------------------------------------------------------------------- /config/clusters/jupyter-health/enc-grafana-token.secret.yaml: -------------------------------------------------------------------------------- 1 | grafana_token: ENC[AES256_GCM,data:pFUEbEuI9Oos6YtuA/oXDKjP6HklrH8G6C8lLh87DDbjQ8Sz0BD9JotBBKoNzA==,iv:rA2kl2O0lcUDPDUcwxuF1F5nY9lydLl+0K2k3OKYkF8=,tag:FkFR4rGHV7xizsUL969Aug==,type:str] 2 | sops: 3 | kms: [] 4 | gcp_kms: 5 | - resource_id: projects/two-eye-two-see/locations/global/keyRings/sops-keys/cryptoKeys/similar-hubs 6 | created_at: '2024-03-27T03:32:37Z' 7 | enc: CiUA4OM7eMIWtqEIQtysm+s5zxS/nKMoNkjDvRzgvAqs19hSfS03EkkAXoW3JssCZCIo6ovleKWINJnwDXgm/R5uTwhVZqRT0G4cficrTpplNQLvj5Lk7FcWeqqGaXK7pLeYaHeXmPBEDvj4YlRcYFrN 8 | azure_kv: [] 9 | hc_vault: [] 10 | age: [] 11 | lastmodified: '2024-03-27T03:32:37Z' 12 | mac: ENC[AES256_GCM,data:Hx2QfF6std3LBVVV4Bz4vXKFXmW6Pi220z3I4tXPUzuWX0mVyb5AUr8Je2diq+6ds2rWmhKFskL0CLA5/zP9U/9vfpnddkJy5K8krlDn08s6QQ8NN6fzBzaDksghoD7Z3aRW7Hn7GwbgALVpF6j20Ty4ilUPDPjuZXVi8iZDZSQ=,iv:/eMrdS7XKkaAN2OGs2RQn1Y6dIAdXbgTZR9K1BnH/tI=,tag:5JqsQHlzFf1ASNq/M20sjg==,type:str] 13 | pgp: [] 14 | unencrypted_suffix: _unencrypted 15 | version: 3.8.1 16 | -------------------------------------------------------------------------------- /config/clusters/nasa-ghg-hub/enc-grafana-token.secret.yaml: -------------------------------------------------------------------------------- 1 | grafana_token: ENC[AES256_GCM,data:ihqjjOd72G4hmfEFbUvjqyW37toAyED1bAvexOSLi1sx0XoQ8d9nrOW4c6UtVg==,iv:I2NWn3h7ZRcYBpUJ+qlgRLj005Kp3/94YMvrvojhpRk=,tag:Qwk5kApDfracK+j7aWG+jA==,type:str] 2 | sops: 3 | kms: [] 4 | gcp_kms: 5 | - resource_id: projects/two-eye-two-see/locations/global/keyRings/sops-keys/cryptoKeys/similar-hubs 6 | created_at: '2024-02-09T10:34:14Z' 7 | enc: CiUA4OM7eA1BDaIYR2kxnolHFaWLLlf+ZVjdmws2WpD2XdW0WpdxEkkAjTWv+jNxFWkW6Z05+jf+nJY9orGIzSyfX1BkxP/RFWYsar4WEizgP6upIlSVy+4IOtev1mwnyMO9COqTtnh+qSkqFvUJagb4 8 | azure_kv: [] 9 | hc_vault: [] 10 | age: [] 11 | lastmodified: '2024-02-09T10:34:14Z' 12 | mac: ENC[AES256_GCM,data:juFIE8Gf7IemXeQI488EGO1B+1BfWT/xsXS48bv5mpR/IRD1pbEeXdYMUfSac5LVaT7iZL0YzDEFoz756oxpxy04ob09xdtk/YYpdt2e9Gudi/F1skve7iPH12tN5aVaxuwqkRuT/ICcYYB6OKbAgF2wIZpdkqCFD7bDF/ul6KI=,iv:O/2Hz6QuohlVuG+4SbBWOS8WEhZ07Yyqdlscd1WyM8E=,tag:T90pbkmdC7fQbhymrwbklQ==,type:str] 13 | pgp: [] 14 | unencrypted_suffix: _unencrypted 15 | version: 3.7.3 16 | -------------------------------------------------------------------------------- /config/clusters/nmfs-openscapes/enc-grafana-token.secret.yaml: -------------------------------------------------------------------------------- 1 | grafana_token: ENC[AES256_GCM,data:oltr88zTHpqrsAVZbgXMKaCuXlu5WXL3vKqTBvdWnkHPRu19V464JxbIxv1y7Q==,iv:OrV7XtJv9rxSggzdbOkfFGuNAEjzL8DMsm0idjiItIE=,tag:rUfqZ/wjFZXCqyTgm4fT/A==,type:str] 2 | sops: 3 | kms: [] 4 | gcp_kms: 5 | - resource_id: projects/two-eye-two-see/locations/global/keyRings/sops-keys/cryptoKeys/similar-hubs 6 | created_at: '2024-09-09T22:40:15Z' 7 | enc: CiUA4OM7eNkMFbgu/SwLgFDVjyRsMDeExbYpvSPxcSrtqqKLbY+jEkkA5dG1QwO/eaZ+abH604bDUh345L8ylLNA2NYGv91osF+nES1yLOvFRcJnfb4XewcZCqfRM3rqLkL+J/ysFP0kiQbnkCh6LWdx 8 | azure_kv: [] 9 | hc_vault: [] 10 | age: [] 11 | lastmodified: '2024-09-09T22:40:16Z' 12 | mac: ENC[AES256_GCM,data:roFEK54gMLAE6wTvNpVkzKFOcKni3Ve0zvE23KoCeK8/mFDko36FSEYv3dH8Rt00fafz/MB2B+P5VUqslL3ZKlVJVqYeGThXOzHnEx+ncMgkSCI+hYGRM9yg4vEM7QbKQnSTKm2ALuA084R8FOQZ8fzxF4Jqv7WPne4df13PZgc=,iv:JIVOhyk0RHaxFSrEHUTiU1rr98UyDouptuLotTTZNrQ=,tag:pNwdsw6z3ZGrWL9wMalapw==,type:str] 13 | pgp: [] 14 | unencrypted_suffix: _unencrypted 15 | version: 3.9.0 16 | -------------------------------------------------------------------------------- /config/clusters/oceanhackweek/enc-grafana-token.secret.yaml: -------------------------------------------------------------------------------- 1 | grafana_token: ENC[AES256_GCM,data:pqDIbVhBv0gQZgTgZ4UBehRvB5toFI09axJtdyYtIZARbiY978/8/VH4wZKAqg==,iv:NtDm/m3wpRd4swIIrVtia5x6bk0N4SldC9j9CHm8hgo=,tag:pvFqdzw+E+iIFMRFVjfxtQ==,type:str] 2 | sops: 3 | kms: [] 4 | gcp_kms: 5 | - resource_id: projects/two-eye-two-see/locations/global/keyRings/sops-keys/cryptoKeys/similar-hubs 6 | created_at: '2025-09-16T22:52:18Z' 7 | enc: CiUA4OM7eO3htXx0Meuf87eNNranTffd695lEAE4GOguuGmh2KfxEkkAXpa10DQREaErArznCx5onMrYBhqDedb/Vx50KwQkzQTnSUs4S9o/agNtXr5Qi6DKSvFtFSn8TsBR+55VW5b2wPrH3/u5Ekir 8 | azure_kv: [] 9 | hc_vault: [] 10 | age: [] 11 | lastmodified: '2025-09-16T22:52:19Z' 12 | mac: ENC[AES256_GCM,data:g1PLxt64zXKWlFgv5AXoq0iC96R+b5useAmr9hgiG1ayY/uldgCd5+j5RnslnK4VnuYBSa+mfg9s0vfBmRqloXLQSxsYuppSg5OsINmCJbYvph0UjFfUMzoO/KwmedDAnLmQQ6uL5g9X4BUFDorrACnQ/lY95z5LovIZOZ4A8NE=,iv:VYtDaI9l6gT1CdhaeEeu7fDhtEgPBALsZKUrcKzXTP0=,tag:odKNEsOaVohAPw8ZQJDTpQ==,type:str] 13 | pgp: [] 14 | unencrypted_suffix: _unencrypted 15 | version: 3.9.1 16 | -------------------------------------------------------------------------------- /config/clusters/projectpythia/enc-grafana-token.secret.yaml: -------------------------------------------------------------------------------- 1 | grafana_token: ENC[AES256_GCM,data:5vH0WQFA5UPjgNfFfB6dqZSRY98cjzHqoP9uyL7jtfL22zsi1MzFuI98bsUrKA==,iv:jw46EWe1eJmCbafG6mhpGZBymNYfqhmgj1dVB7/1W2U=,tag:233TKdCCpIWtiAPA0tqvew==,type:str] 2 | sops: 3 | kms: [] 4 | gcp_kms: 5 | - resource_id: projects/two-eye-two-see/locations/global/keyRings/sops-keys/cryptoKeys/similar-hubs 6 | created_at: '2024-05-14T14:18:49Z' 7 | enc: CiUA4OM7eBcNpRJBVjUw5D1MR+TcvKDPMZ9iNHxpSYPbHUWA+RwyEkkAWX/fcZnpCQV/m17WPj3tlHF6wMZvn3k+6GAd+9Obe1PhnWYjBcVGhKr3vG5WzxiIInL5e8Hr+8q+PBAodG0lvSCWV3UPyOSM 8 | azure_kv: [] 9 | hc_vault: [] 10 | age: [] 11 | lastmodified: '2024-05-14T14:18:51Z' 12 | mac: ENC[AES256_GCM,data:72R7JjmWRM05JAdZQQBtsFXNdxIA3tI1SWjsrBnEYy+mmrBRLJ0gUAGSLhtn/BdzC5XXxrFo+BSA7u0E4N6OjkswwB4/xnYxpAG+kAItnbCRo6vACcF3QWccv+B3VrLokE3vg6etFxWs8Td0ovgaz5UuJD8z2CeIKzaYaFsc9K0=,iv:RAYHzZxsShEN8V2FMjDqTKp+4/DUuaXt2WWSlQhB204=,tag:Gt/pjjdvVw5dnmuoj3zElg==,type:str] 13 | pgp: [] 14 | unencrypted_suffix: _unencrypted 15 | version: 3.8.1 16 | -------------------------------------------------------------------------------- /terraform/azure/budget-alerts.tf: -------------------------------------------------------------------------------- 1 | # ref: https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/subscription 2 | data "azurerm_subscription" "current" {} 3 | 4 | # ref: https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/consumption_budget_subscription 5 | resource "azurerm_consumption_budget_subscription" "budget" { 6 | count = var.budget_alert_enabled ? 1 : 0 7 | 8 | name = "BudgetSubscription-${var.resourcegroup_name}" 9 | subscription_id = data.azurerm_subscription.current.id 10 | 11 | amount = var.budget_alert_amount 12 | time_grain = "Monthly" 13 | 14 | time_period { 15 | start_date = "2024-07-01T00:00:00Z" 16 | end_date = "2029-07-01T00:00:00Z" 17 | } 18 | 19 | notification { 20 | enabled = true 21 | threshold = 120 22 | operator = "GreaterThanOrEqualTo" 23 | threshold_type = "Forecasted" 24 | 25 | contact_emails = [ 26 | "support+budget-${var.resourcegroup_name}@2i2c.org", 27 | ] 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /config/clusters/catalystproject-latam/enc-grafana-token.secret.yaml: -------------------------------------------------------------------------------- 1 | grafana_token: ENC[AES256_GCM,data:oUTA8DgMo6Xhd+Bh80hIJch5Dfkzd79WGKx829q4S8jyQBTcZwID7wTuMI68oQ==,iv:ppLH+vr7lqmo+nWx3Rf6a6bTd2LbFtRDhZutXgbQnOI=,tag:/Wn8uM+JQPaCoWrj8e/rdA==,type:str] 2 | sops: 3 | kms: [] 4 | gcp_kms: 5 | - resource_id: projects/two-eye-two-see/locations/global/keyRings/sops-keys/cryptoKeys/similar-hubs 6 | created_at: '2023-07-07T09:08:03Z' 7 | enc: CiUA4OM7eNFulYlnO9I5VNFKDfi4ccVRgAmXu4jL0FAgxqUhQV28EkkAyiwFHHTy7Tu2zqR1lfo5dYd4Z72qQlvA/L2jLIQhxOUjEJSMHKGEp7e3d7vT8CuFsaGH+ircv8OV0vWMSvjQQvhCeP1V1iA6 8 | azure_kv: [] 9 | hc_vault: [] 10 | age: [] 11 | lastmodified: '2023-07-07T09:08:03Z' 12 | mac: ENC[AES256_GCM,data:IAgafdIOUlcD+6nW7td0hY89cUfFX1FREYrLaGE/2MeNVATG+lch2YzP4k0dt1Ix6T4BbeHfGveitNKRHhYbUKD4I0uJWOOy16s5tFP0sybQbt811ViiCBRS4J9BmL3d1MBlNuAttzZRr+QDL+oZz2La6+imWCOkR5DH0x58+Hs=,iv:NGoKnQUyO50Ix+9q10sabGuuRvNx1LJbdqF5BjE5PeU=,tag:n0pp4EoKWTX1bdeu15Jvsw==,type:str] 13 | pgp: [] 14 | unencrypted_suffix: _unencrypted 15 | version: 3.7.2 16 | -------------------------------------------------------------------------------- /config/clusters/jupyter-health/cluster.yaml: -------------------------------------------------------------------------------- 1 | name: jupyter-health 2 | provider: aws 3 | provider_url: https://2i2c.awsapps.com/start/#/ 4 | aws: 5 | account: 211125465508 6 | key: enc-deployer-credentials.secret.json 7 | clusterType: eks 8 | clusterName: jupyter-health 9 | region: us-east-2 10 | billing: 11 | paid_by_us: true 12 | support: 13 | helm_chart_values_files: 14 | - support.values.yaml 15 | - enc-support.secret.values.yaml 16 | hubs: 17 | - name: staging 18 | display_name: Jupyter Health (staging) 19 | domain: staging.jupyter-health.2i2c.cloud 20 | helm_chart: basehub 21 | helm_chart_values_files: 22 | - common.values.yaml 23 | - enc-common.secret.values.yaml 24 | - staging.values.yaml 25 | - enc-staging.secret.values.yaml 26 | - name: prod 27 | display_name: Jupyter Health (prod) 28 | domain: jupyter-health.2i2c.cloud 29 | helm_chart: basehub 30 | helm_chart_values_files: 31 | - common.values.yaml 32 | - enc-common.secret.values.yaml 33 | - prod.values.yaml 34 | - enc-prod.secret.values.yaml 35 | -------------------------------------------------------------------------------- /config/clusters/projectpythia-binder/enc-grafana-token.secret.yaml: -------------------------------------------------------------------------------- 1 | grafana_token: ENC[AES256_GCM,data:LF1e5Ua2woMpMsS3nGn+1VR6qguxGUCD03xpo5vRfrbWbReNw3azok4k6B9W5A==,iv:Wv9U8c8reWsPn9QVgOEmAgqKGDNyc7NAwNH02YoqMTs=,tag:/NYwNqYoeQ0Fo/hxUJ4GyA==,type:str] 2 | sops: 3 | kms: [] 4 | gcp_kms: 5 | - resource_id: projects/two-eye-two-see/locations/global/keyRings/sops-keys/cryptoKeys/similar-hubs 6 | created_at: '2025-03-03T17:06:58Z' 7 | enc: CiUA4OM7eCCUPXukVIWBeaIA47izy6yUcTSruEM3iIORjv4yL9+LEkkAWOWv8LuHrlzyvog4KYkb0VKEEpY59Q5NVKTc6ruby31I8EdOZm1o/Jlkra8uUFXsJlj/1GIW1Q/O9XoZGGvYEYRNRppNUD/J 8 | azure_kv: [] 9 | hc_vault: [] 10 | age: [] 11 | lastmodified: '2025-03-03T17:06:58Z' 12 | mac: ENC[AES256_GCM,data:elGEYVwN9w2qDlKuIYrzoY8sBIeGEJkQU3dlPRAGlFSk/vdbx70EzOYpCakYYExGe/Pbb3wgDws1IOMT+ZTfeLvWfbxlQ445NQx9pZGWmtSRlZRg1lWvCALdOxso0sTNvPFoYAQ2u8eV+pZHvZJ/3FgDkvjIHTP7lzM16ppza7g=,iv:tcVGzNbqvjSclYK0Ebb6cnjpN0OYnDEnq6sy0DgjJWQ=,tag:xANYI8kB+ZF8wnyNbc28EA==,type:str] 13 | pgp: [] 14 | unencrypted_suffix: _unencrypted 15 | version: 3.8.1 16 | -------------------------------------------------------------------------------- /terraform/aws/projects/ubc-eoas.tfvars: -------------------------------------------------------------------------------- 1 | region = "ca-central-1" 2 | cluster_name = "ubc-eoas" 3 | cluster_nodes_location = "ca-central-1a" 4 | 5 | disable_cluster_wide_filestore = true 6 | 7 | ebs_volumes = { 8 | "staging" = { 9 | size = 1 10 | type = "gp3" 11 | name_suffix = "staging" 12 | tags = { "2i2c:hub-name" : "staging" } 13 | }, 14 | "prod" = { 15 | size = 128 16 | type = "gp3" 17 | name_suffix = "prod" 18 | tags = { "2i2c:hub-name" : "prod" } 19 | }, 20 | } 21 | enable_nfs_backup = true 22 | 23 | user_buckets = { 24 | "scratch-staging" : { 25 | "delete_after" : 7, 26 | "tags" : { "2i2c:hub-name" : "staging" }, 27 | }, 28 | "scratch" : { 29 | "delete_after" : 7, 30 | "tags" : { "2i2c:hub-name" : "prod" }, 31 | }, 32 | } 33 | 34 | hub_cloud_permissions = { 35 | "staging" : { 36 | bucket_admin_access : ["scratch-staging"], 37 | }, 38 | "prod" : { 39 | bucket_admin_access : ["scratch"], 40 | }, 41 | } 42 | -------------------------------------------------------------------------------- /config/clusters/catalystproject-africa/enc-grafana-token.secret.yaml: -------------------------------------------------------------------------------- 1 | grafana_token: ENC[AES256_GCM,data:g8tOvS8s3v6EcfIORGOQ6CVxDm2gE/KMAJDB5iC0dtvZxYTTzH1EFq6/vwIvxw==,iv:9L0SB84N/K0G8d/s6vGOOMhAQCsLXB2oU4M+xcfEcw4=,tag:TSadskN0moW0Sp2ayr+tAA==,type:str] 2 | sops: 3 | kms: [] 4 | gcp_kms: 5 | - resource_id: projects/two-eye-two-see/locations/global/keyRings/sops-keys/cryptoKeys/similar-hubs 6 | created_at: '2023-07-14T10:40:40Z' 7 | enc: CiUA4OM7eKtJ8kOurSB6tVqB/+2RwC8SxYs/+uJ6mL6Qa0/+HGl7EkgAyiwFHFI5tYorPLEMwvt62I3yrF4XJhVlA0zGuVY7JynKWt98xQlZ6bfn/MkwJBwKGjV6iGJAx7p4IFa9qEfY7ggb9hX/yiM= 8 | azure_kv: [] 9 | hc_vault: [] 10 | age: [] 11 | lastmodified: '2023-07-14T10:40:40Z' 12 | mac: ENC[AES256_GCM,data:8XsbGf9KkiPUiJLpA/q5UQpVj4DleRQjq/AoFMy0OOv0zQuV7w/iEQKT59GajEdw2/wzO3H8NECFOOQLHnwoQVUfWlw+xHNcCfKPJkJvQKOGEsCtnEPMIFxRhT6FoUsdrAz1S6Nxltq291kF/81e/o/IKmqlpcOXtR3hUugzwLc=,iv:775d2luga1LTvLTPTik0ZhzZDLZMS0tFtT70xut99Ws=,tag:JYT245Piq8INhETX8AGSLg==,type:str] 13 | pgp: [] 14 | unencrypted_suffix: _unencrypted 15 | version: 3.7.3 16 | -------------------------------------------------------------------------------- /terraform/gcp/projects/dubois.tfvars: -------------------------------------------------------------------------------- 1 | prefix = "dubois" 2 | project_id = "dubois-436615" 3 | zone = "us-central1-b" 4 | region = "us-central1" 5 | enable_network_policy = true 6 | enable_filestore_backups = false 7 | core_node_machine_type = "n2-highmem-2" 8 | filestores = {} 9 | 10 | # Config required to enable automatic budget alerts to be sent to support@2i2c.org 11 | billing_account_id = "0157F7-E3EA8C-25AC3C" 12 | 13 | k8s_versions = { 14 | min_master_version : "1.32.1-gke.1200003", 15 | core_nodes_version : "1.32.1-gke.1200003", 16 | notebook_nodes_version : "1.32.1-gke.1200003", 17 | } 18 | 19 | notebook_nodes = { 20 | "n2-highmem-4" : { 21 | min : 0, 22 | max : 100, 23 | machine_type : "n2-highmem-4", 24 | }, 25 | "n2-highmem-16" : { 26 | min : 0, 27 | max : 100, 28 | machine_type : "n2-highmem-16", 29 | }, 30 | "n2-highmem-64" : { 31 | min : 0, 32 | max : 100, 33 | machine_type : "n2-highmem-64", 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /config/clusters/disasters/cluster.yaml: -------------------------------------------------------------------------------- 1 | name: disasters 2 | provider: aws 3 | provider_url: https://smce-aws-disasters.signin.aws.amazon.com/console 4 | aws: 5 | account: 515966502221 6 | key: enc-deployer-credentials.secret.json 7 | clusterType: eks 8 | clusterName: disasters 9 | region: us-west-2 10 | billing: 11 | paid_by_us: false 12 | support: 13 | helm_chart_values_files: 14 | - support.values.yaml 15 | - enc-support.secret.values.yaml 16 | hubs: 17 | - name: staging 18 | display_name: Disasters - staging 19 | domain: staging.hub.disasters.2i2c.cloud 20 | helm_chart: basehub 21 | helm_chart_values_files: 22 | - common.values.yaml 23 | - staging.values.yaml 24 | - enc-imagebuilding-common.secret.values.yaml 25 | - enc-staging.secret.values.yaml 26 | - name: prod 27 | display_name: Disasters 28 | domain: hub.disasters.2i2c.cloud 29 | helm_chart: basehub 30 | helm_chart_values_files: 31 | - common.values.yaml 32 | - prod.values.yaml 33 | - enc-imagebuilding-common.secret.values.yaml 34 | - enc-prod.secret.values.yaml 35 | -------------------------------------------------------------------------------- /config/clusters/templates/aws/cluster.yaml: -------------------------------------------------------------------------------- 1 | name: {{ cluster_name }} 2 | provider: aws 3 | provider_url: {{ sign_in_url }} 4 | aws: 5 | account: {{ cluster_account_id }} 6 | key: enc-deployer-credentials.secret.json 7 | clusterType: eks 8 | clusterName: {{ cluster_name }} 9 | region: {{ cluster_region }} 10 | billing: 11 | paid_by_us: {{ paid_by_us }} 12 | support: 13 | helm_chart_values_files: 14 | - support.values.yaml 15 | - enc-support.secret.values.yaml 16 | hubs: [] 17 | # Uncomment the lines below once the support infrastructure was deployed and 18 | # you are ready to add the first cluster 19 | 20 | {% for hub in hubs %} 21 | # - name: {{ hub }} 22 | # # Tip: consider changing this to something more human friendly 23 | # display_name: "{{ cluster_name }} - {{ hub }}" 24 | # domain: {{ hub }}.{{ cluster_name }}.2i2c.cloud 25 | # helm_chart: basehub 26 | # helm_chart_values_files: 27 | # - common.values.yaml 28 | # - {{ hub }}.values.yaml 29 | # - enc-{{ hub }}.secret.values.yaml 30 | {% endfor %} 31 | -------------------------------------------------------------------------------- /config/clusters/catalystproject-africa/kush.values.yaml: -------------------------------------------------------------------------------- 1 | jupyterhub: 2 | ingress: 3 | hosts: [kush.af.catalystproject.2i2c.cloud] 4 | tls: 5 | - hosts: [kush.af.catalystproject.2i2c.cloud] 6 | secretName: https-auto-tls 7 | custom: 8 | homepage: 9 | templateVars: 10 | org: 11 | name: Catalyst Project, Africa - Kush Centre for Genomics & Biomedical Informatics 12 | hub: 13 | config: 14 | JupyterHub: 15 | authenticator_class: github 16 | GitHubOAuthenticator: 17 | oauth_callback_url: https://kush.af.catalystproject.2i2c.cloud/hub/oauth_callback 18 | allowed_organizations: 19 | - CatalystProject-Hubs:kush 20 | Authenticator: 21 | admin_users: 22 | - Fadlelmola 23 | singleuser: 24 | nodeSelector: 25 | 2i2c/hub-name: kush 26 | jupyterhub-home-nfs: 27 | quotaEnforcer: 28 | config: 29 | QuotaManager: 30 | hard_quota: 1 # in GiB 31 | eks: 32 | volumeId: vol-0de5b955b6bd6dfc6 33 | nfs: 34 | pv: 35 | serverIP: 10.100.44.159 36 | -------------------------------------------------------------------------------- /config/clusters/strudel/enc-prod.secret.values.yaml: -------------------------------------------------------------------------------- 1 | jupyterhub: 2 | hub: 3 | config: 4 | DummyAuthenticator: 5 | password: ENC[AES256_GCM,data:b5czbXAdBQ9b6eE=,iv:CTlw85eG+LzeIL+Tb8uUI0Vri/9gpTiIi1sP2lI5KuM=,tag:wJdF9yn2U5d+HxnJ2YyN/A==,type:str] 6 | sops: 7 | kms: [] 8 | gcp_kms: 9 | - resource_id: projects/two-eye-two-see/locations/global/keyRings/sops-keys/cryptoKeys/similar-hubs 10 | created_at: '2025-04-17T09:20:38Z' 11 | enc: CiUA4OM7eFvVRotlLAWUZN2Awwc12QDOlu43E7a+FOjSOTDfqn8hEkkAWOWv8H/f1LvmNB8xHJs9zZfA/mZ+1+p5B3dy1ZjImXbZxNllARIuLA8zYhDR4zwewaRndJZ69ASpomEpyHLt8wx0mIQOU2p+ 12 | azure_kv: [] 13 | hc_vault: [] 14 | age: [] 15 | lastmodified: '2025-04-17T09:20:39Z' 16 | mac: ENC[AES256_GCM,data:8iMAh2edVlS1s++/9yLMk3J70zf92iURzAJ12aqG/8Bwx8M3jq9DesVOyUDOWfAunpqPKmLXU0LRByN/4rWX1LHML9lGQgUoKCXjOp9Paf7W3H1Imvg7a4pQzOolcRPPv2bjQ2liifOdEbKTubqq4vZgUSZ8hJcBMxGwdGNu0Xc=,iv:qE62PaEKhycilxyERcIU/zvWKI/KaKLpzZz28Q6vYKw=,tag:llEXfIDGMseTBzH8JAj7vg==,type:str] 17 | pgp: [] 18 | unencrypted_suffix: _unencrypted 19 | version: 3.9.1 20 | -------------------------------------------------------------------------------- /config/clusters/strudel/enc-staging.secret.values.yaml: -------------------------------------------------------------------------------- 1 | jupyterhub: 2 | hub: 3 | config: 4 | DummyAuthenticator: 5 | password: ENC[AES256_GCM,data:DfRpm6o/YtsNHg==,iv:NXF2DGpL5v3/yRJ9m/5NvsHzliCpAaRLrHIpuOYgRc4=,tag:pjjDTbF89ipv/7yj2t0m0Q==,type:str] 6 | sops: 7 | kms: [] 8 | gcp_kms: 9 | - resource_id: projects/two-eye-two-see/locations/global/keyRings/sops-keys/cryptoKeys/similar-hubs 10 | created_at: '2025-04-17T09:21:51Z' 11 | enc: CiUA4OM7eJohK9+hJFqI4t+aXzh9UaBLHB3huU+JMzjRaPbOB2GhEkkAWOWv8FXGb96CUZGIgavLYhTkH236G4OQI08S+FFwH3NyMGPwoxVCEU5DQ/5A5IzfRyrV0msL5df8TmKRmq9x70td71J24s1D 12 | azure_kv: [] 13 | hc_vault: [] 14 | age: [] 15 | lastmodified: '2025-04-17T09:21:51Z' 16 | mac: ENC[AES256_GCM,data:Ak5oWoNM4NRxmlPOC+IQp98LNF8l0LSv8+mkwwsMTtasvHXpZVLmg6Npvfolzr0VzVN4ZkxdupNcZIPfGGGXx2ymw2fcDSrOqqEQMupZNI6FfgUAQ4vH2Ude51CwVN+EVFlY5NXbRL7iyps5hcLaFQjn0N7g9fOckVXI+4mal2s=,iv:YBHXkfeIx5rPOPycnVYtV0fSX/XIXSE4UvSGHoAc2EM=,tag:HpOb/CLS/1u0Ppri5anN+A==,type:str] 17 | pgp: [] 18 | unencrypted_suffix: _unencrypted 19 | version: 3.9.1 20 | -------------------------------------------------------------------------------- /config/clusters/catalystproject-africa/bon.values.yaml: -------------------------------------------------------------------------------- 1 | jupyterhub: 2 | ingress: 3 | hosts: [bon.af.catalystproject.2i2c.cloud] 4 | tls: 5 | - hosts: [bon.af.catalystproject.2i2c.cloud] 6 | secretName: https-auto-tls 7 | custom: 8 | homepage: 9 | templateVars: 10 | org: 11 | name: Catalyst Project, Africa - Bioinformatics Outreach Nigeria 12 | hub: 13 | config: 14 | JupyterHub: 15 | authenticator_class: github 16 | GitHubOAuthenticator: 17 | oauth_callback_url: https://bon.af.catalystproject.2i2c.cloud/hub/oauth_callback 18 | allowed_organizations: 19 | - CatalystProject-Hubs:bon 20 | Authenticator: 21 | admin_users: 22 | - Seunolufemi123 23 | - Emmanuel19-ada 24 | singleuser: 25 | nodeSelector: 26 | 2i2c/hub-name: bon 27 | jupyterhub-home-nfs: 28 | quotaEnforcer: 29 | config: 30 | QuotaManager: 31 | hard_quota: 1 # in GiB 32 | eks: 33 | volumeId: vol-09dc8201c516e2e70 34 | nfs: 35 | pv: 36 | serverIP: 10.100.135.147 37 | -------------------------------------------------------------------------------- /config/clusters/reflective/enc-workshop.secret.values.yaml: -------------------------------------------------------------------------------- 1 | jupyterhub: 2 | hub: 3 | config: 4 | DummyAuthenticator: 5 | password: ENC[AES256_GCM,data:mI44ouyNut3vGoX2JtqL,iv:ZUKViNjEQFcPPX9tuTyIk6n37V1kwHC36HFWUZwXK2w=,tag:yTKIhoDVN+AOn7dcwkPJEA==,type:str] 6 | sops: 7 | kms: [] 8 | gcp_kms: 9 | - resource_id: projects/two-eye-two-see/locations/global/keyRings/sops-keys/cryptoKeys/similar-hubs 10 | created_at: '2025-04-11T09:58:17Z' 11 | enc: CiUA4OM7eFlVc72nV+TuQ5lymnGxKd59TY5jUXNmbdvNP6F1cP3sEkkAWOWv8N3LmcXJNED84UAFnxpcUKcNe7/39QWFmn/Rn7GrFgzKyMVV/MR6g2jBm2jpCu8lu5tm5sh+TGOdxkUNzOhHnKuAr7C7 12 | azure_kv: [] 13 | hc_vault: [] 14 | age: [] 15 | lastmodified: '2025-04-22T20:19:44Z' 16 | mac: ENC[AES256_GCM,data:t6A11ryZBrQ8u1efqrY+mPhGEJYU9QmmUTId3r5FeZFq5hGKyEwfKRJzN2409rL0dtT/NGfnyz8uZHp7OFd+FDFEvv4T+/DDKia0kKvhNfYil9DMjXf0LCdNQJE2psJZf01Z7kvIgc1WnDg5fVHRtsJmOQB4uuEvjwoWu4AL1+c=,iv:mhMPEmMxMc0c0FVG/0Xxnn7aOy3Q9KdiXtNq5ymVvro=,tag:zbBgPP10osOI1QsAhMVOsQ==,type:str] 17 | pgp: [] 18 | unencrypted_suffix: _unencrypted 19 | version: 3.9.1 20 | -------------------------------------------------------------------------------- /config/clusters/cloudbank/common.values.yaml: -------------------------------------------------------------------------------- 1 | nfs: 2 | enabled: true 3 | shareCreator: 4 | enabled: false 5 | pv: 6 | enabled: true 7 | mountOptions: 8 | - soft 9 | - noatime 10 | # MUST HAVE TRAILING SLASH 11 | jupyterhub: 12 | singleuser: 13 | cpu: 14 | # Each node has about 4 CPUs total, and if we limit users to no more than 15 | # 2, no single user can take down a full node by themselves. We have to 16 | # set the guarantee to *something*, otherwise it is set to be equal 17 | # to the limit! We don't explicitly set a guarantee, because there is 18 | # a guarantee of 0.05 set in basehub/values.yaml 19 | limit: 2 20 | image: 21 | name: us-central1-docker.pkg.dev/cal-icor-hubs/user-images/base-user-image 22 | tag: 79e7ee67211e 23 | nodeSelector: 24 | # Put everything on the most appropriate instance type for these users 25 | node.kubernetes.io/instance-type: n2-highmem-4 26 | jupyterhub-home-nfs: 27 | quotaEnforcer: 28 | config: 29 | QuotaManager: 30 | hard_quota: 5 # in GiB 31 | -------------------------------------------------------------------------------- /docs/howto/features/image.md: -------------------------------------------------------------------------------- 1 | # Enable user image features 2 | 3 | This document points to various other bits of documentation on how 4 | to enable various features that involve modifying the user image. We should 5 | keep the documentation here fairly minimal, as it should all be upstream 6 | wherever possible. 7 | 8 | ## Mount object storage as files with FUSE 9 | 10 | ```{warning} 11 | 12 | Consider [if you actually will benefit from it](https://github.com/yuvipanda/jupyterhub-roothooks/#should-you-do-it) 13 | before you do it 14 | ``` 15 | 16 | [jupyterhub-roothooks](https://github.com/yuvipanda/jupyterhub-roothooks/) 17 | can be used to setup object storage (S3, GCS, etc) as paths on the filesystem 18 | via FUSE. 19 | 20 | This is mounted from inside the user pod, so will use whatever 21 | cloud permissions the user has. So to provide write access or access 22 | to private object storage buckets, we will need to configure 23 | [appropriate cloud permissions]( 24 | howto:features:cloud-access:access-perms). However, for just 25 | public object storage buckets, no extra permissions are needed. -------------------------------------------------------------------------------- /config/clusters/leap/enc-grafana-token.secret.yaml: -------------------------------------------------------------------------------- 1 | grafana_token: ENC[AES256_GCM,data:TdtLCpPMp7DTTSAM8kzztUA3YHMeQnJWi/GgEWjEVmGpQ3gOnC+YwaStRl4YO3Rbw+JZS4R5KZ4sPD5ySV6wH2oR9ofWws6UDgUdKt6WEJHfoMSDQ4tvl01IF9s=,iv:U65xojfHZrRbE7ieWmXE5kmEHbxHJW9sMLsOXisD5Tw=,tag:5kZ85mkKiOnsHqIMKCs1ow==,type:str] 2 | sops: 3 | kms: [] 4 | gcp_kms: 5 | - resource_id: projects/two-eye-two-see/locations/global/keyRings/sops-keys/cryptoKeys/similar-hubs 6 | created_at: '2022-02-24T17:56:52Z' 7 | enc: CiQA4OM7eA1jS3a2zwDnUXuczQfvJW5u9Zp3QHRgCZjXk1ha/P4SSQDm5XgWif8sOYLkjo9k+hTKISv4PddEGATlvRChHeNZREfg2nreeDYujK6tOdiXplp8Yzv+uWxnxxUvlYPbhvReCDgmuEKLGI0= 8 | azure_kv: [] 9 | hc_vault: [] 10 | age: [] 11 | lastmodified: '2022-04-27T03:05:10Z' 12 | mac: ENC[AES256_GCM,data:Ms0CQX6EOxTJ7I9O2kn6V6Ammp4ksO9nb9UOzhkQlWMnCvAGXD2daXMFMZRQrJBveWwInYBcYqQ4sWnjQMg+nsrFtoDStJuqGELjnK0NSYCqYyetltszK+90iXV3+qCUtibW5j9WwiCl0AAHm7r1Sv2dmXC8uyiywTp0PqSd1M4=,iv:DBvhzKR9k8WsNDWVNziI2W/4G6WUdq9KoiPF8xEsAY8=,tag:QAvwc6YP2/Ty0yNwvvlWeQ==,type:str] 13 | pgp: [] 14 | unencrypted_suffix: _unencrypted 15 | version: 3.7.1 16 | -------------------------------------------------------------------------------- /config/clusters/2i2c-uk/cluster.yaml: -------------------------------------------------------------------------------- 1 | name: 2i2c-uk 2 | provider: gcp 3 | provider_url: https://console.cloud.google.com/kubernetes/clusters/details/europe-west2/two-eye-two-see-uk-cluster/nodes?project=two-eye-two-see-uk 4 | gcp: 5 | key: enc-deployer-credentials.secret.json 6 | project: two-eye-two-see-uk 7 | cluster: two-eye-two-see-uk-cluster 8 | zone: europe-west2 9 | billing: 10 | paid_by_us: true 11 | bigquery: 12 | project: two-eye-two-see 13 | dataset: cloud_costs 14 | billing_id: 0157F7-E3EA8C-25AC3C 15 | support: 16 | helm_chart_values_files: 17 | - support.values.yaml 18 | - enc-support.secret.values.yaml 19 | hubs: 20 | - name: staging 21 | display_name: 2i2c-uk Staging 22 | domain: staging.uk.2i2c.cloud 23 | helm_chart: basehub 24 | helm_chart_values_files: 25 | - staging.values.yaml 26 | - enc-staging.secret.values.yaml 27 | - name: lis 28 | display_name: London Interdisciplinary School 29 | domain: ds.lis.2i2c.cloud 30 | helm_chart: basehub 31 | helm_chart_values_files: 32 | - lis.values.yaml 33 | - enc-lis.secret.values.yaml 34 | -------------------------------------------------------------------------------- /config/clusters/2i2c-uk/enc-grafana-token.secret.yaml: -------------------------------------------------------------------------------- 1 | grafana_token: ENC[AES256_GCM,data:XF1r1oEBYsoI03T99WlIhNgTAPNNccsDGJrz1+Rnj+O0EckwvAg4NshBT9ZmwLWC+in+LVbtuv6S04u70QnJAr6fKiAu3txyQtaXff6q8b0JOnAgJnGdBTeENJg=,iv:dxEC7INDDxq5rxx5OZTdsDarZ7sRPi7rSp0jn99zQF8=,tag:PcUgMyEq+eY+N712DG6qQg==,type:str] 2 | sops: 3 | kms: [] 4 | gcp_kms: 5 | - resource_id: projects/two-eye-two-see/locations/global/keyRings/sops-keys/cryptoKeys/similar-hubs 6 | created_at: '2022-09-26T10:38:09Z' 7 | enc: CiQA4OM7eCR3iueV1778GFBq5kvv6CEvIT2bCsPyv9qvk0VnUUESSQDuy/p8VW7Qis9HbDQDw+E5HJgEO7axIi+1EGrorRA0YaDcflSdQkOSxuJe/7WGSe1S/BptKUSC8FLB+8S4cKVGsvAtQ0RenqA= 8 | azure_kv: [] 9 | hc_vault: [] 10 | age: [] 11 | lastmodified: '2022-09-26T10:38:41Z' 12 | mac: ENC[AES256_GCM,data:a5ArT+5azSnVzYEOsK1hE+r4/vOjMvkcrO/V/d40Qv8KQ6qmn2K3KIk0sZW2D/C69VZjXikJbDvXnmKthNBG5GQMm/eEvk1OixWi4PnIv7gpysrIO4eaYX/y/qgf5fvD9e8w8Z6Wte4udfI3F2kGkTJC+7FR2DQseMBb+ifwQvE=,iv:leGwAvQUbxkjX9vFFlLezWe9ug5lz75Dtoo/ohZS6Cg=,tag:zBcpTkcAIZ5aSPmfHvrUkw==,type:str] 13 | pgp: [] 14 | unencrypted_suffix: _unencrypted 15 | version: 3.7.3 16 | -------------------------------------------------------------------------------- /config/clusters/2i2c-aws-us/enc-grafana-token.secret.yaml: -------------------------------------------------------------------------------- 1 | grafana_token: ENC[AES256_GCM,data:t2qk7Ze8CPLm04pnwFDpqhoXv430t1wBH+o4H3KxGLLPZXeeBfMgHNTjOFeX0xABJ8eZw8yRi/TRXHfil9QQ+OKoTIMJ9olTr++YdBEVBRqQijlFJTc5IVRQQXNR9LhG,iv:9vVNYHRyCOexYjx49JMHqxD8RbYSs4OaU2RsDFjW1N4=,tag:Wgnr/0UIGJiCuQPULCfgbA==,type:str] 2 | sops: 3 | kms: [] 4 | gcp_kms: 5 | - resource_id: projects/two-eye-two-see/locations/global/keyRings/sops-keys/cryptoKeys/similar-hubs 6 | created_at: '2022-12-02T17:06:57Z' 7 | enc: CiUA4OM7eE9zAnsvqqZ1DkU29yZuDSdm7AoElAMABbgu9/p8tLGkEkkA+0T9hXy+VFXSo6A4H8d8HFNwQBsm67tqAGBBUQ7SlIoWIz28wMPTIez5sNPBziRv9VrsXuIFJozC+Z2oqwexcy6Wy6663t9I 8 | azure_kv: [] 9 | hc_vault: [] 10 | age: [] 11 | lastmodified: '2022-12-02T17:06:58Z' 12 | mac: ENC[AES256_GCM,data:NHmFKLI8yUkZW+lhh9+rZl0LhTjBFbVgAua1M4E2+5DcDY+tA1tO87T1QcPcX+PPAPIXTO41eofFB01MbfG1FbsXjPYQE3235pmA2WNEIaeY2fTAdKylrUfbiICV/2doex/eXLdQwIrXJeyyrIYXA0Sjj1hDBkuV6DCU8HbKQ+s=,iv:1XrSnJHntEpQ9qx0MbOEfHpzpeFiIIoK0eCsEQCVI40=,tag:4+9qqk4LXBriUpPMSbTlew==,type:str] 13 | pgp: [] 14 | unencrypted_suffix: _unencrypted 15 | version: 3.7.3 16 | -------------------------------------------------------------------------------- /deployer/utils/helm.py: -------------------------------------------------------------------------------- 1 | from subprocess import check_call, check_output 2 | 3 | from .rendering import print_colour 4 | 5 | 6 | def wait_for_deployments_daemonsets(name: str): 7 | """ 8 | Wait for all deployments and daemonsets to be fully rolled out 9 | """ 10 | print_colour( 11 | f"Waiting for all deployments and daemonsets in {name} to be ready", "green" 12 | ) 13 | deployments_and_daemonsets = ( 14 | check_output( 15 | [ 16 | "kubectl", 17 | "get", 18 | f"--namespace={name}", 19 | "--output=name", 20 | "deployments,daemonsets", 21 | ], 22 | ) 23 | .strip() 24 | .split() 25 | ) 26 | 27 | for d in deployments_and_daemonsets: 28 | check_call( 29 | [ 30 | "kubectl", 31 | "rollout", 32 | "status", 33 | f"--namespace={name}", 34 | "--timeout=10m", 35 | "--watch", 36 | d, 37 | ], 38 | ) 39 | -------------------------------------------------------------------------------- /terraform/aws/projects/berkeley-geojupyter.tfvars: -------------------------------------------------------------------------------- 1 | region = "us-west-2" 2 | cluster_name = "berkeley-geojupyter" 3 | cluster_nodes_location = "us-west-2a" 4 | 5 | enable_jupyterhub_cost_monitoring = true 6 | 7 | enable_nfs_backup = true 8 | 9 | filestores = {} 10 | 11 | ebs_volumes = { 12 | "staging" = { 13 | size = 1 # in GB 14 | type = "gp3" 15 | name_suffix = "staging" 16 | tags = { "2i2c:hub-name" : "staging" } 17 | } 18 | "prod" = { 19 | size = 100 # in GB 20 | type = "gp3" 21 | name_suffix = "prod" 22 | tags = { "2i2c:hub-name" : "prod" } 23 | } 24 | } 25 | user_buckets = { 26 | "scratch-staging" : { 27 | "delete_after" : 7, 28 | "tags" : { "2i2c:hub-name" : "staging" }, 29 | }, 30 | "scratch" : { 31 | "delete_after" : 7, 32 | "tags" : { "2i2c:hub-name" : "prod" }, 33 | } 34 | } 35 | 36 | hub_cloud_permissions = { 37 | "staging" : { 38 | bucket_admin_access : ["scratch-staging"], 39 | }, 40 | "prod" : { 41 | bucket_admin_access : ["scratch"], 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /terraform/aws/projects/victor.tfvars: -------------------------------------------------------------------------------- 1 | region = "us-west-2" 2 | cluster_name = "victor" 3 | cluster_nodes_location = "us-west-2a" 4 | 5 | disable_cluster_wide_filestore = true 6 | 7 | default_budget_alert = { 8 | "enabled" = false 9 | } 10 | user_buckets = { 11 | "scratch-staging" : { 12 | "delete_after" : 7, 13 | "tags" : { "2i2c:hub-name" : "staging" } 14 | }, 15 | "scratch" : { 16 | "delete_after" : 7, 17 | "tags" : { "2i2c:hub-name" : "prod" } 18 | }, 19 | } 20 | hub_cloud_permissions = { 21 | "staging" : { 22 | bucket_admin_access : ["scratch-staging"], 23 | }, 24 | "prod" : { 25 | bucket_admin_access : ["scratch"], 26 | }, 27 | } 28 | ebs_volumes = { 29 | "staging" = { 30 | size = 10 # in GB 31 | type = "gp3" 32 | name_suffix = "staging" 33 | tags = { "2i2c:hub-name" : "staging" } 34 | } 35 | "prod" = { 36 | size = 1450 # in GB 37 | type = "gp3" 38 | name_suffix = "prod" 39 | tags = { "2i2c:hub-name" : "prod" } 40 | } 41 | } 42 | 43 | enable_nfs_backup = true 44 | -------------------------------------------------------------------------------- /terraform/azure/secret/enc-pagerduty-service-integration-keys.secret.yaml: -------------------------------------------------------------------------------- 1 | disk_space_service_uri: ENC[AES256_GCM,data:WusTnIvMcE9zaGfF1AD5QbiFwg+/JUti4zYU6SeD8mYRa1ZZVL1qT14GO2YfPs5LYE+9pOZ2zIfoaFJOXmArkDIWtPc3qvdRt8Bm7fOWvqv0,iv:PJQw8CwiAKCy4y+Opy4FeOofpEwc3IvG/XbezSsYLzc=,tag:oJymeH+2EkAAIS2+meSooQ==,type:str] 2 | sops: 3 | kms: [] 4 | gcp_kms: 5 | - resource_id: projects/two-eye-two-see/locations/global/keyRings/sops-keys/cryptoKeys/similar-hubs 6 | created_at: '2024-06-14T12:26:08Z' 7 | enc: CiUA4OM7eGet11mVomgzV59cip2vdaMAp4ixSXaE7ZCPnPFS1J4jEkkAWX/fcVOKu7vC4PheH7d/AkhqJYqvRKBtfhjjWAHsCfLr+3dSy7iY3FesRESw6wRXbhAJ9w9l3XSCDUrQY6sr+368q6zMfWZ6 8 | azure_kv: [] 9 | hc_vault: [] 10 | age: [] 11 | lastmodified: '2024-06-14T12:26:09Z' 12 | mac: ENC[AES256_GCM,data:kTg7+8cedY2mSFkZDkmVLE9ewuR6cCzvEY7v5hy3Aau4L/I/ObTh3RqKsedTdfn7UV07PfJfguevlLCzSr8cxTGPksDo756IW7pHiyK9lzaq2Db24OuWsLT3/rQpi0izmgi+4dkug5LgSJoNHVrXkTLqpaLN1NhHSKgy/LMSwac=,iv:bQmgoYSe+ArbktD5Ju+06RnHR9yijTF9F+7OVZengxE=,tag:MZ+5NJeE8LdGKDEpHNYWTg==,type:str] 13 | pgp: [] 14 | unencrypted_suffix: _unencrypted 15 | version: 3.8.1 16 | -------------------------------------------------------------------------------- /config/clusters/catalystproject-africa/uvri.values.yaml: -------------------------------------------------------------------------------- 1 | jupyterhub: 2 | ingress: 3 | hosts: [uvri.af.catalystproject.2i2c.cloud] 4 | tls: 5 | - hosts: [uvri.af.catalystproject.2i2c.cloud] 6 | secretName: https-auto-tls 7 | custom: 8 | homepage: 9 | templateVars: 10 | org: 11 | name: Catalyst Project, Africa - UVRI 12 | url: https://2i2c.org 13 | logo_url: https://2i2c.org/media/logo.png 14 | hub: 15 | config: 16 | JupyterHub: 17 | authenticator_class: github 18 | GitHubOAuthenticator: 19 | oauth_callback_url: https://uvri.af.catalystproject.2i2c.cloud/hub/oauth_callback 20 | allowed_organizations: 21 | - CatalystProject-Hubs:uvri 22 | Authenticator: 23 | admin_users: 24 | - eddUG 25 | singleuser: 26 | nodeSelector: 27 | 2i2c/hub-name: uvri 28 | jupyterhub-home-nfs: 29 | quotaEnforcer: 30 | config: 31 | QuotaManager: 32 | hard_quota: 1 # in GiB 33 | eks: 34 | volumeId: vol-048173ffd8e87f1d3 35 | nfs: 36 | pv: 37 | serverIP: 10.100.30.88 38 | -------------------------------------------------------------------------------- /.github/workflows/test-docs.yaml: -------------------------------------------------------------------------------- 1 | # This is a GitHub workflow defining a set of jobs with a set of steps. 2 | # ref: https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions 3 | # 4 | name: Test docs 5 | 6 | on: 7 | pull_request: 8 | paths: 9 | - docs/** 10 | - '**/test-docs.yaml' 11 | push: 12 | paths: 13 | - docs/** 14 | - '**/test-docs.yaml' 15 | branches-ignore: 16 | - dependabot/** 17 | - pre-commit-ci-update-config 18 | workflow_dispatch: 19 | 20 | jobs: 21 | test-docs: 22 | runs-on: ubuntu-22.04 23 | steps: 24 | - uses: actions/checkout@v6 25 | with: 26 | fetch-depth: 0 27 | - uses: actions/setup-python@v6 28 | with: 29 | python-version: '3.13' 30 | 31 | - name: Install deps 32 | run: pip install . -r docs/requirements.txt 33 | 34 | # linkcheck is done separately from this in doc-links.yml, scheduled to 35 | # run every day and open/update an issue 36 | - name: make dirhtml 37 | run: | 38 | cd docs 39 | make dirhtml SPHINXOPTS='--color -W --keep-going' 40 | -------------------------------------------------------------------------------- /terraform/aws/projects/jupyter-health.tfvars: -------------------------------------------------------------------------------- 1 | region = "us-east-2" 2 | cluster_name = "jupyter-health" 3 | cluster_nodes_location = "us-east-2a" 4 | 5 | enable_jupyterhub_cost_monitoring = true 6 | disable_cluster_wide_filestore = true 7 | 8 | user_buckets = { 9 | "scratch-staging" : { 10 | "delete_after" : 7, 11 | "tags" : { "2i2c:hub-name" : "staging" }, 12 | }, 13 | "scratch" : { 14 | "delete_after" : 7, 15 | "tags" : { "2i2c:hub-name" : "prod" }, 16 | }, 17 | } 18 | 19 | hub_cloud_permissions = { 20 | "staging" : { 21 | bucket_admin_access : ["scratch-staging"], 22 | }, 23 | "prod" : { 24 | bucket_admin_access : ["scratch"], 25 | }, 26 | } 27 | 28 | enable_nfs_backup = true 29 | 30 | ebs_volumes = { 31 | "staging" = { 32 | size = 10 # in GB 33 | type = "gp3" 34 | name_suffix = "staging" 35 | tags = { "2i2c:hub-name" : "staging" } 36 | } 37 | "prod" = { 38 | size = 100 # in GB 39 | type = "gp3" 40 | name_suffix = "prod" 41 | tags = { "2i2c:hub-name" : "prod" } 42 | } 43 | } -------------------------------------------------------------------------------- /terraform/aws/projects/smithsonian.tfvars: -------------------------------------------------------------------------------- 1 | region = "us-east-2" 2 | cluster_name = "smithsonian" 3 | cluster_nodes_location = "us-east-2b" 4 | 5 | enable_jupyterhub_cost_monitoring = true 6 | disable_cluster_wide_filestore = true 7 | 8 | user_buckets = { 9 | "scratch-staging" : { 10 | "delete_after" : 7, 11 | "tags" : { "2i2c:hub-name" : "staging" }, 12 | }, 13 | "scratch" : { 14 | "delete_after" : 7, 15 | "tags" : { "2i2c:hub-name" : "prod" }, 16 | }, 17 | } 18 | 19 | hub_cloud_permissions = { 20 | "staging" : { 21 | bucket_admin_access : ["scratch-staging"], 22 | }, 23 | "prod" : { 24 | bucket_admin_access : ["scratch"], 25 | }, 26 | } 27 | 28 | enable_nfs_backup = true 29 | 30 | ebs_volumes = { 31 | "staging" = { 32 | size = 10 # in GB 33 | type = "gp3" 34 | name_suffix = "staging" 35 | tags = { "2i2c:hub-name" : "staging" } 36 | } 37 | "prod" = { 38 | size = 100 # in GB 39 | type = "gp3" 40 | name_suffix = "prod" 41 | tags = { "2i2c:hub-name" : "prod" } 42 | } 43 | } 44 | --------------------------------------------------------------------------------