diff --git a/.github/ISSUE_TEMPLATE/release-checklist.md b/.github/ISSUE_TEMPLATE/release-checklist.md
index 72d2c369cc..b892879152 100644
--- a/.github/ISSUE_TEMPLATE/release-checklist.md
+++ b/.github/ISSUE_TEMPLATE/release-checklist.md
@@ -58,6 +58,7 @@ Release captain responsible - <@gh_username>
## Cut the official release
_If there were changes to the following packages, handle their releases before cutting a new release for Nebari_
+
- [ ] [Cut PyPI release for `nebari-workflow-controller`](https://github.com/nebari-dev/nebari-workflow-controller)
- [ ] [Cut PyPI release for `argo-jupyter-scheduler`](https://github.com/nebari-dev/argo-jupyter-scheduler)
diff --git a/.github/actions/init-local/action.yml b/.github/actions/init-local/action.yml
index 306876973a..d1b5af5e6c 100644
--- a/.github/actions/init-local/action.yml
+++ b/.github/actions/init-local/action.yml
@@ -5,7 +5,7 @@ inputs:
directory:
description: "Path to directory to initialize in"
required: false
- default: './local-deployment'
+ default: "./local-deployment"
outputs:
directory:
diff --git a/.github/actions/publish-from-template/action.yml b/.github/actions/publish-from-template/action.yml
index 8c45e37271..8891a32a56 100644
--- a/.github/actions/publish-from-template/action.yml
+++ b/.github/actions/publish-from-template/action.yml
@@ -15,8 +15,7 @@ runs:
if: github.event_name != 'schedule'
shell: bash
env: ${{ env }}
- run:
- python ${{ github.action_path }}/render_template.py ${{inputs.filename }}
+ run: python ${{ github.action_path }}/render_template.py ${{inputs.filename }}
- uses: JasonEtco/create-an-issue@v2
# Only render template and create an issue in case the workflow is a scheduled one
diff --git a/.github/workflows/build_push_docker.yaml b/.github/workflows/build_push_docker.yaml
new file mode 100644
index 0000000000..4219295763
--- /dev/null
+++ b/.github/workflows/build_push_docker.yaml
@@ -0,0 +1,123 @@
+# Build and push images to:
+# GitHub Container Registry (ghcr.io)
+# Red Hat Container Registry (quay.io)
+name: "Build Docker Images"
+
+on:
+ workflow_dispatch: null
+ push:
+ branches:
+ - "*"
+ paths:
+ - "./docker/Dockerfile"
+ - "./docker/dask-worker/*"
+ - "./docker/jupyterhub/*"
+ - "./docker/jupyterlab/*"
+ - "./docker/nebari-workflow-controller/*"
+
+ - "./docker/scripts/*"
+
+ - ".github/workflows/build-push-docker.yaml"
+ tags:
+ - "*"
+
+env:
+ DOCKER_ORG: nebari
+ GPU_BASE_IMAGE: nvidia/cuda:12.8.1-base-ubuntu24.04
+ GPU_IMAGE_SUFFIX: gpu
+ BASE_IMAGE: ubuntu:24.04
+
+permissions:
+ contents: read
+ packages: write
+ id-token: write
+ security-events: write
+
+# https://docs.github.com/en/actions/using-jobs/using-concurrency
+concurrency:
+ # only cancel in-progress jobs or runs for the current workflow - matches against branch & tags
+ group: ${{ github.workflow }}-${{ github.ref }}
+ cancel-in-progress: true
+
+jobs:
+ build-images:
+ name: "Build Docker Images"
+ runs-on: ubuntu-latest
+ strategy:
+ matrix:
+ dockerfile:
+ - jupyterlab
+ - jupyterhub
+ - dask-worker
+ - workflow-controller
+ platform:
+ - gpu
+ - cpu
+ exclude:
+ # excludes JupyterHub/GPU, Workflow Controller/GPU
+ - dockerfile: jupyterhub
+ platform: gpu
+ - dockerfile: workflow-controller
+ platform: gpu
+
+ steps:
+ - name: "Checkout Repository 🛎️"
+ uses: actions/checkout@v3
+
+ - name: "Set up Docker Buildx 🛠️"
+ uses: docker/setup-buildx-action@v2
+
+ - name: "Login to GitHub Container Registry 🔐"
+ uses: docker/login-action@v2
+ with:
+ registry: ghcr.io
+ username: ${{ github.repository_owner }}
+ password: ${{ secrets.BOT_GHCR_TOKEN }}
+
+ - name: "Login to Quay Container Registry 🔐"
+ uses: docker/login-action@v2
+ with:
+ registry: quay.io
+ username: ${{ secrets.QUAY_USERNAME }}
+ password: ${{ secrets.QUAY_TOKEN }}
+
+ - name: "Set BASE_IMAGE and Image Suffix 📷"
+ if: ${{ matrix.platform == 'gpu' }}
+ run: |
+ echo "GPU Platform Matrix"
+ echo "BASE_IMAGE=$GPU_BASE_IMAGE" >> $GITHUB_ENV
+ echo "IMAGE_SUFFIX=-$GPU_IMAGE_SUFFIX" >> $GITHUB_ENV
+
+ - name: "Generate Docker images tags 🏷️"
+ id: meta
+ uses: docker/metadata-action@v4
+ with:
+ images: |
+ "quay.io/${{ env.DOCKER_ORG }}/nebari-${{ matrix.dockerfile }}${{ env.IMAGE_SUFFIX }}"
+ "ghcr.io/${{ github.repository_owner }}/nebari-${{ matrix.dockerfile }}${{ env.IMAGE_SUFFIX }}"
+ tags: |
+ # branch event -> e.g. `main-f0f6994-20221001`
+ type=ref, event=branch, suffix=-{{sha}}-{{date 'YYYYMMDD'}}
+ # needed for integration tests
+ type=ref, event=branch
+ # on tag push -> e.g. `2022.10.1`
+ type=ref, event=tag
+
+ - name: "Inspect image dir tree 🔍"
+ run: |
+ sudo apt-get install tree
+ tree .
+
+ - name: "Build docker images 🐳"
+ uses: docker/build-push-action@v3
+ with:
+ context: ./docker/
+ file: "Dockerfile"
+ target: ${{ matrix.dockerfile }}
+ tags: ${{ steps.meta.outputs.tags }}
+ push: ${{ github.event_name != 'pull_request' }}
+ labels: ${{ steps.meta.outputs.labels }}
+ cache-from: type=gha
+ cache-to: type=gha,mode=max
+ build-args: BASE_IMAGE=${{ env.BASE_IMAGE }}
+ platforms: linux/amd64,linux/arm64
diff --git a/.github/workflows/docker_trivy.yaml b/.github/workflows/docker_trivy.yaml
new file mode 100644
index 0000000000..27d44dc482
--- /dev/null
+++ b/.github/workflows/docker_trivy.yaml
@@ -0,0 +1,40 @@
+name: Code Scanning
+
+on:
+ push:
+ branches: ["main"]
+ pull_request:
+ # The branches below must be a subset of the branches above
+ branches: ["main"]
+
+permissions:
+ contents: read
+
+jobs:
+ SAST:
+ permissions:
+ contents: read # for actions/checkout to fetch code
+ security-events: write # for github/codeql-action/upload-sarif to upload SARIF results
+ actions: read # only required for a private repository by github/codeql-action/upload-sarif to get the Action run status
+ name: Trivy config Scan
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v4
+
+ - name: Run Trivy vulnerability scanner in config mode
+ uses: aquasecurity/trivy-action@master
+ with:
+ scan-type: "config"
+ hide-progress: true
+ format: "sarif"
+ output: "trivy-results.sarif"
+ ignore-unfixed: true
+ severity: "CRITICAL,HIGH"
+ limit-severities-for-sarif: true
+
+ - name: Upload Trivy scan results to GitHub Security tab
+ uses: github/codeql-action/upload-sarif@v3
+ if: always()
+ with:
+ sarif_file: "trivy-results.sarif"
diff --git a/.github/workflows/generate_cli_doc.yml b/.github/workflows/generate_cli_doc.yml
index 0e50b7057f..1fff4892ef 100644
--- a/.github/workflows/generate_cli_doc.yml
+++ b/.github/workflows/generate_cli_doc.yml
@@ -3,14 +3,14 @@ name: Update API docs
on:
pull_request:
paths:
- - "src/_nebari/subcommands/**"
- - "src/_nebari/cli.py"
+ - "src/_nebari/subcommands/**"
+ - "src/_nebari/cli.py"
push:
branches:
- main
paths:
- - "src/_nebari/subcommands/**"
- - "src/_nebari/cli.py"
+ - "src/_nebari/subcommands/**"
+ - "src/_nebari/cli.py"
workflow_dispatch:
jobs:
@@ -64,7 +64,7 @@ jobs:
signoff: false
branch: auto_cli_doc_update
delete-branch: true
- title: '[AUTO] Update CLI doc'
+ title: "[AUTO] Update CLI doc"
body: |
Update CLI doc
- Auto-generated by [create-pull-request][1]
diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml
index 771999f51d..7b1edac45c 100644
--- a/.github/workflows/release.yaml
+++ b/.github/workflows/release.yaml
@@ -9,7 +9,7 @@ jobs:
name: Test PyPi release
runs-on: ubuntu-latest
permissions:
- id-token: write # IMPORTANT: this permission is mandatory for trusted publishing
+ id-token: write # IMPORTANT: this permission is mandatory for trusted publishing
steps:
- name: Set up python
uses: actions/setup-python@v5
diff --git a/.github/workflows/run-precommit.yaml b/.github/workflows/run-precommit.yaml
index 6a79e0da1a..0181427040 100644
--- a/.github/workflows/run-precommit.yaml
+++ b/.github/workflows/run-precommit.yaml
@@ -21,14 +21,13 @@ jobs:
- name: Setup python
uses: actions/setup-python@v5
with:
- python-version: '3.x'
+ python-version: "3.x"
- name: Setup terraform
uses: hashicorp/setup-terraform@v3
with:
terraform_version: "1.5.7"
-
- name: Run terraform pre-commit ⚡️
uses: pre-commit/action@v3.0.1
with:
diff --git a/.github/workflows/test-provider.yaml b/.github/workflows/test-provider.yaml
index 48eb68d553..6f9f3b5dcc 100644
--- a/.github/workflows/test-provider.yaml
+++ b/.github/workflows/test-provider.yaml
@@ -78,12 +78,12 @@ jobs:
with:
python-version: "3.11"
- - name: 'Authenticate to GCP'
+ - name: "Authenticate to GCP"
if: ${{ matrix.provider == 'gcp' }}
- uses: 'google-github-actions/auth@v1'
+ uses: "google-github-actions/auth@v1"
with:
token_format: access_token
- create_credentials_file: 'true'
+ create_credentials_file: "true"
workload_identity_provider: ${{ secrets.GCP_WORKFLOW_PROVIDER }}
service_account: ${{ secrets.GCP_SERVICE_ACCOUNT }}
@@ -92,7 +92,7 @@ jobs:
run: |
echo "GOOGLE_CREDENTIALS=${{ env.GOOGLE_APPLICATION_CREDENTIALS }}" >> $GITHUB_ENV
- - name: 'Authenticate to AWS'
+ - name: "Authenticate to AWS"
if: ${{ matrix.provider == 'aws' }}
uses: aws-actions/configure-aws-credentials@v1
with:
@@ -100,7 +100,7 @@ jobs:
role-session-name: github-action
aws-region: us-east-1
- - name: 'Azure login'
+ - name: "Azure login"
if: ${{ matrix.provider == 'azure' }}
uses: azure/login@v2
with:
diff --git a/.github/workflows/test_aws_integration.yaml b/.github/workflows/test_aws_integration.yaml
index 59075ea7de..abe85bbb08 100644
--- a/.github/workflows/test_aws_integration.yaml
+++ b/.github/workflows/test_aws_integration.yaml
@@ -6,22 +6,21 @@ on:
workflow_dispatch:
inputs:
image-tag:
- description: 'Nebari image tag created by the nebari-docker-images repo'
+ description: "Nebari image tag created by the nebari-docker-images repo"
required: true
default: main
type: string
tf-log-level:
- description: 'Change Terraform log levels'
+ description: "Change Terraform log levels"
required: false
default: info
type: choice
options:
- - info
- - warn
- - debug
- - trace
- - error
-
+ - info
+ - warn
+ - debug
+ - trace
+ - error
env:
AWS_DEFAULT_REGION: "us-west-2"
diff --git a/.github/workflows/test_azure_integration.yaml b/.github/workflows/test_azure_integration.yaml
index 269461f320..b1076bfe56 100644
--- a/.github/workflows/test_azure_integration.yaml
+++ b/.github/workflows/test_azure_integration.yaml
@@ -6,21 +6,21 @@ on:
workflow_dispatch:
inputs:
image-tag:
- description: 'Nebari image tag created by the nebari-docker-images repo'
+ description: "Nebari image tag created by the nebari-docker-images repo"
required: true
default: main
type: string
tf-log-level:
- description: 'Change Terraform log levels'
+ description: "Change Terraform log levels"
required: false
default: info
type: choice
options:
- - info
- - warn
- - debug
- - trace
- - error
+ - info
+ - warn
+ - debug
+ - trace
+ - error
env:
NEBARI_IMAGE_TAG: ${{ github.event.inputs.image-tag || 'main' }}
@@ -50,7 +50,7 @@ jobs:
conda install --quiet --yes conda-build
playwright install
- - name: 'Azure login'
+ - name: "Azure login"
uses: azure/login@v2
with:
client-id: ${{ secrets.ARM_CLIENT_ID }}
diff --git a/.github/workflows/test_conda_build.yaml b/.github/workflows/test_conda_build.yaml
index 74584ee620..0291969736 100644
--- a/.github/workflows/test_conda_build.yaml
+++ b/.github/workflows/test_conda_build.yaml
@@ -17,11 +17,11 @@ jobs:
test-conda-build:
runs-on: ubuntu-latest
defaults:
- run:
- shell: bash -el {0}
+ run:
+ shell: bash -el {0}
concurrency:
- group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
- cancel-in-progress: true
+ group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
+ cancel-in-progress: true
steps:
- name: "Checkout Infrastructure"
uses: actions/checkout@v4
diff --git a/.github/workflows/test_gcp_integration.yaml b/.github/workflows/test_gcp_integration.yaml
index 0d6c06b0c0..86fd3a1f5d 100644
--- a/.github/workflows/test_gcp_integration.yaml
+++ b/.github/workflows/test_gcp_integration.yaml
@@ -6,21 +6,21 @@ on:
workflow_dispatch:
inputs:
image-tag:
- description: 'Nebari image tag created by the nebari-docker-images repo'
+ description: "Nebari image tag created by the nebari-docker-images repo"
required: true
default: main
type: string
tf-log-level:
- description: 'Change Terraform log levels'
+ description: "Change Terraform log levels"
required: false
default: info
type: choice
options:
- - info
- - warn
- - debug
- - trace
- - error
+ - info
+ - warn
+ - debug
+ - trace
+ - error
env:
NEBARI_IMAGE_TAG: ${{ github.event.inputs.image-tag || 'main' }}
@@ -50,11 +50,11 @@ jobs:
pip install .[dev]
playwright install
- - name: 'Authenticate to GCP'
- uses: 'google-github-actions/auth@v1'
+ - name: "Authenticate to GCP"
+ uses: "google-github-actions/auth@v1"
with:
- workload_identity_provider: ${{ secrets.GCP_WORKFLOW_PROVIDER }}
- service_account: ${{ secrets.GCP_SERVICE_ACCOUNT }}
+ workload_identity_provider: ${{ secrets.GCP_WORKFLOW_PROVIDER }}
+ service_account: ${{ secrets.GCP_SERVICE_ACCOUNT }}
- name: Set required environment variables
run: |
diff --git a/.github/workflows/test_images.yaml b/.github/workflows/test_images.yaml
new file mode 100644
index 0000000000..262ec01170
--- /dev/null
+++ b/.github/workflows/test_images.yaml
@@ -0,0 +1,78 @@
+name: Test Docker images
+
+on:
+ pull_request:
+ paths:
+ - "./docker/Dockerfile"
+
+ - "./docker/dask-worker/*"
+ - "./docker/jupyterhub/*"
+ - "./docker/jupyterlab/*"
+
+ - "./docker/scripts/*"
+
+ - ".github/workflows/build-push-docker.yaml"
+ - ".github/workflows/test-images.yaml"
+
+env:
+ DOCKER_ORG: nebari
+ GITHUB_SHA: ${{ github.sha }}
+ GPU_BASE_IMAGE: nvidia/cuda:12.8.1-base-ubuntu24.04
+ GPU_IMAGE_SUFFIX: gpu
+ BASE_IMAGE: ubuntu:24.04
+
+# https://docs.github.com/en/actions/using-jobs/using-concurrency
+concurrency:
+ # only cancel in-progress jobs or runs for the current workflow - matches against branch & tags
+ group: ${{ github.workflow }}-${{ github.ref }}
+ cancel-in-progress: true
+
+jobs:
+ build-test-images:
+ runs-on: ubuntu-latest
+ strategy:
+ matrix:
+ dockerfile:
+ - jupyterlab
+ - jupyterhub
+ - dask-worker
+ - nebari-workflow-controller
+ platform:
+ - gpu
+ - cpu
+ exclude:
+ # excludes JupyterHub/GPU
+ - dockerfile: jupyterhub
+ platform: gpu
+ steps:
+ - name: Checkout Repository 🛎
+ uses: actions/checkout@v3
+
+ - name: Lint Dockerfiles 🔍
+ uses: jbergstroem/hadolint-gh-action@v1
+ with:
+ dockerfile: Dockerfile
+ output_format: tty
+ error_level: 0
+
+ - name: "Set BASE_IMAGE and Image Suffix 📷"
+ if: ${{ matrix.platform == 'gpu' }}
+ run: |
+ echo "GPU Platform Matrix"
+ echo "BASE_IMAGE=$GPU_BASE_IMAGE" >> $GITHUB_ENV
+ echo "IMAGE_SUFFIX=-$GPU_IMAGE_SUFFIX" >> $GITHUB_ENV
+
+ - name: "Set up Docker Buildx 🛠️"
+ uses: docker/setup-buildx-action@v2
+
+ - name: Build Image 🛠
+ uses: docker/build-push-action@v3
+ with:
+ context: ./docker/
+ file: "Dockerfile"
+ target: ${{ matrix.dockerfile }}
+ push: false
+ cache-from: type=gha
+ cache-to: type=gha,mode=max
+ build-args: BASE_IMAGE=${{ env.BASE_IMAGE }}
+ platforms: linux/amd64,linux/arm64
diff --git a/.github/workflows/test_local_integration.yaml b/.github/workflows/test_local_integration.yaml
index 3078c6252b..262ae86bd7 100644
--- a/.github/workflows/test_local_integration.yaml
+++ b/.github/workflows/test_local_integration.yaml
@@ -52,7 +52,7 @@ jobs:
shell: bash -l {0}
steps:
- name: "Checkout Infrastructure"
- # Pin checkout version due to issue with node24 support on self-hosted runners
+ # Pin checkout version due to issue with node24 support on self-hosted runners
uses: actions/checkout@v4
with:
fetch-depth: 0
@@ -171,12 +171,12 @@ jobs:
env:
CONDA: /home/runnerx/miniconda3
with:
- environment-file: conda-store/conda-store-server/environment-dev.yaml
- miniforge-version: latest
- auto-activate-base: false
- activate-environment: conda-store-server-dev
- python-version: ${{ env.PYTHON_VERSION }}
- conda-remove-defaults: "true"
+ environment-file: conda-store/conda-store-server/environment-dev.yaml
+ miniforge-version: latest
+ auto-activate-base: false
+ activate-environment: conda-store-server-dev
+ python-version: ${{ env.PYTHON_VERSION }}
+ conda-remove-defaults: "true"
- name: Install conda-store dependencies
run: |
diff --git a/.github/workflows/test_local_upgrade.yaml b/.github/workflows/test_local_upgrade.yaml
index 06be364ebf..fc1acaf770 100644
--- a/.github/workflows/test_local_upgrade.yaml
+++ b/.github/workflows/test_local_upgrade.yaml
@@ -10,7 +10,6 @@ on:
- prereleased
workflow_dispatch:
-
concurrency:
group: ${{ github.ref_name }}
cancel-in-progress: true
diff --git a/.github/workflows/trivy.yml b/.github/workflows/trivy.yml
index 5185daf46e..212a836d25 100644
--- a/.github/workflows/trivy.yml
+++ b/.github/workflows/trivy.yml
@@ -7,12 +7,12 @@ name: Code Scanning
on:
push:
- branches: [ "main" ]
+ branches: ["main"]
pull_request:
# The branches below must be a subset of the branches above
- branches: [ "main" ]
+ branches: ["main"]
schedule:
- - cron: '19 23 * * 6'
+ - cron: "19 23 * * 6"
permissions:
contents: read
@@ -27,7 +27,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
- scan-type: ['config', 'fs']
+ scan-type: ["config", "fs"]
steps:
- name: Checkout code
uses: actions/checkout@v4
@@ -47,14 +47,14 @@ jobs:
with:
scan-type: ${{ matrix.scan-type }}
hide-progress: true
- format: 'sarif'
- output: 'trivy-${{ matrix.scan-type }}.sarif'
+ format: "sarif"
+ output: "trivy-${{ matrix.scan-type }}.sarif"
ignore-unfixed: true
- severity: 'CRITICAL,HIGH'
+ severity: "CRITICAL,HIGH"
limit-severities-for-sarif: true
- name: Upload Trivy results to GitHub Security tab
uses: github/codeql-action/upload-sarif@v3
if: always()
with:
- sarif_file: 'trivy-${{ matrix.scan-type }}.sarif'
+ sarif_file: "trivy-${{ matrix.scan-type }}.sarif"
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 3fd8676936..fd8a505bd5 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -45,13 +45,10 @@ repos:
rev: v2.4.1
hooks:
- id: codespell
- args:
- [
- "--write",
- ]
+ args: ["--write"]
language: python
additional_dependencies:
- - tomli
+ - tomli
# python
- repo: https://github.com/psf/black
@@ -82,3 +79,28 @@ repos:
- id: terraform_fmt
args:
- --args=-write=true
+
+ # Autoformat: markdown, yaml to ensure that it doesn't need to be updated in other repos
+ - repo: https://github.com/pre-commit/mirrors-prettier
+ rev: v2.6.1
+ hooks:
+ - id: prettier
+
+ # Misc...
+ - repo: https://github.com/pre-commit/pre-commit-hooks
+ rev: v4.0.1
+ # ref: https://github.com/pre-commit/pre-commit-hooks#hooks-available
+ hooks:
+ # Autoformat: Makes sure files end in a newline and only a newline.
+ - id: end-of-file-fixer
+
+ # Trims trailing whitespace.
+ - id: trailing-whitespace
+ args: [--markdown-linebreak-ext=md]
+
+ # Lint: Check for files with names that would conflict on a
+ # case-insensitive filesystem like MacOS HFS+ or Windows FAT.
+ - id: check-case-conflict
+
+ # Lint: Checks that non-binary executables have a proper shebang.
+ - id: check-executables-have-shebangs
diff --git a/README.md b/README.md
index cad68137de..d2471ba94b 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,12 @@
+> [!IMPORTANT] > **Nebari Deployment Issues**
+>
+> The current stable releases on PyPI and conda-forge suffer from issues related to [Bitnami image deprecation](https://github.com/bitnami/charts/issues/35164) that prevent successful deployments.
+> These issues have been resolved on the `main` branch and will be included in the upcoming `2025.10.1` release.
+>
+> If trying to deploy nebari in the meantime, please install directly from the `main` branch e.g. `pip install git+https://github.com/nebari-dev/nebari.git@main`.
+
+---
+
@@ -10,12 +19,18 @@
---
-| Information | Links |
-| :---------- | :-----|
-| Project | [](https://opensource.org/licenses/BSD-3-Clause) [](https://www.nebari.dev/docs/welcome) [](https://badge.fury.io/py/nebari) []((https://anaconda.org/conda-forge/nebari)) |
-| Community | [](https://github.com/nebari-dev/nebari/discussions) [](https://github.com/nebari-dev/nebari/issues/new/choose) [](https://www.nebari.dev/docs/community/) |
-| CI | [](https://github.com/nebari-dev/nebari/actions/workflows/test_local_integration.yaml) [](https://github.com/nebari-dev/nebari/actions/workflows/test.yaml) [](https://github.com/nebari-dev/nebari/actions/workflows/test-provider.yaml)|
-| Cloud Providers | [](https://github.com/nebari-dev/nebari/actions/workflows/test_aws_integration.yaml) [](https://github.com/nebari-dev/nebari/actions/workflows/test_azure_integration.yaml) [](https://github.com/nebari-dev/nebari/actions/workflows/test_gcp_integration.yaml)|
+| Information | Links |
+| :-------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| Project | [](https://opensource.org/licenses/BSD-3-Clause) [](https://www.nebari.dev/docs/welcome) [](https://badge.fury.io/py/nebari) [](<(https://anaconda.org/conda-forge/nebari)>) |
+| Community | [](https://github.com/nebari-dev/nebari/discussions) [](https://github.com/nebari-dev/nebari/issues/new/choose) [](https://www.nebari.dev/docs/community/) |
+| CI | [](https://github.com/nebari-dev/nebari/actions/workflows/kubernetes_test.yaml) [](https://github.com/nebari-dev/nebari/actions/workflows/test.yaml) [](https://github.com/nebari-dev/nebari/actions/workflows/test-provider.yaml) |
+| Cloud Providers | [](https://github.com/nebari-dev/nebari/actions/workflows/test_aws_integration.yaml) [](https://github.com/nebari-dev/nebari/actions/workflows/test_azure_integration.yaml) [](https://github.com/nebari-dev/nebari/actions/workflows/test_gcp_integration.yaml) |
+| Information | Links |
+| :---------- | :----- |
+| Project | [](https://opensource.org/licenses/BSD-3-Clause) [](https://www.nebari.dev/docs/welcome) [](https://badge.fury.io/py/nebari) [](<(https://anaconda.org/conda-forge/nebari)>) |
+| Community | [](https://github.com/nebari-dev/nebari/discussions) [](https://github.com/nebari-dev/nebari/issues/new/choose) [](https://www.nebari.dev/docs/community/) |
+| CI | [](https://github.com/nebari-dev/nebari/actions/workflows/test_local_integration.yaml) [](https://github.com/nebari-dev/nebari/actions/workflows/test.yaml) [](https://github.com/nebari-dev/nebari/actions/workflows/test-provider.yaml) |
+| Cloud Providers | [](https://github.com/nebari-dev/nebari/actions/workflows/test_aws_integration.yaml) [](https://github.com/nebari-dev/nebari/actions/workflows/test_azure_integration.yaml) [](https://github.com/nebari-dev/nebari/actions/workflows/test_gcp_integration.yaml) |
## Table of contents
@@ -151,7 +166,7 @@ Have a look at our [Frequently Asked Questions (FAQ)][nebari-faqs] to see if you
Getting help:
- [GitHub Discussions][gh-discussions] is our user forum. It can be used to raise discussions about a subject,
- such as: "What is the recommended way to do _X_ with Nebari?"
+ such as: "What is the recommended way to do _X_ with Nebari?"
- [Issues][nebari-issues] for queries, bug reporting, feature requests, documentation, etc.
> We work around the clock to make Nebari better, but sometimes your query might take a while to get a reply. We
@@ -170,6 +185,7 @@ If you're using Nebari and would like professional support, please get in touch
[Nebari is BSD3 licensed](LICENSE).
+
[nebari-issues]: https://github.com/nebari-dev/nebari/issues
[nebari-faqs]: https://www.nebari.dev/docs/faq
[gh-discussions]: https://github.com/nebari-dev/nebari/discussions
diff --git a/RELEASE.md b/RELEASE.md
index f86129d771..536a0f8175 100644
--- a/RELEASE.md
+++ b/RELEASE.md
@@ -12,6 +12,7 @@ This file is copied to nebari-dev/nebari-docs using a GitHub Action. -->
## Release 2025.6.1 - June 06, 2025
### What's Changed
+
- Enable resource monitoring for cirun runners by @aktech in https://github.com/nebari-dev/nebari/pull/3047
- Add filesystem scan in Trivy GHA workflow to scan Python dependencies by @marcelovilla in https://github.com/nebari-dev/nebari/pull/3045
- Pin click to avoid incompatibility issues with Typer by @marcelovilla in https://github.com/nebari-dev/nebari/pull/3051
@@ -26,6 +27,7 @@ This file is copied to nebari-dev/nebari-docs using a GitHub Action. -->
> NOTE: You may notice messages like groups: cannot find name for group ID when using the terminal. These warnings are harmless and do not affect system functionality or permissions. We're aware of the issue and it will be resolved in the next version.
### What's Changed
+
- Upgrade verify-changed-files action by @marcelovilla in https://github.com/nebari-dev/nebari/pull/3037
- Monkeypatch version validator to avoid failing tests by @marcelovilla in https://github.com/nebari-dev/nebari/pull/3039
- Upgrade azure-identity by @marcelovilla in https://github.com/nebari-dev/nebari/pull/3038
@@ -35,6 +37,7 @@ This file is copied to nebari-dev/nebari-docs using a GitHub Action. -->
## Release 2025.4.1 - April 11, 2025
### What's Changed
+
- [pre-commit.ci] pre-commit autoupdate by @pre-commit-ci in https://github.com/nebari-dev/nebari/pull/2969
- Add extra services checks to kuberhealthy by @viniciusdc in https://github.com/nebari-dev/nebari/pull/2978
- Add workflow to run conda-store user journey tests by @soapy1 in https://github.com/nebari-dev/nebari/pull/2895
@@ -58,6 +61,7 @@ This file is copied to nebari-dev/nebari-docs using a GitHub Action. -->
## Release 2025.3.1 - March 14, 2025
### What's Changed
+
- fix buffer full deadlock by @Adam-D-Lewis in https://github.com/nebari-dev/nebari/pull/2929
- support KubeSpawner profile_options by @Adam-D-Lewis in https://github.com/nebari-dev/nebari/pull/2937
- fix ansi color reset bug by @Adam-D-Lewis in https://github.com/nebari-dev/nebari/pull/2970
@@ -79,6 +83,7 @@ This file is copied to nebari-dev/nebari-docs using a GitHub Action. -->
> 1.31).
### What's Changed
+
- fix bug to allow --import-plugin to work by @Adam-D-Lewis in https://github.com/nebari-dev/nebari/pull/2864
- Add azure kubernetes policy add-on by @viniciusdc in https://github.com/nebari-dev-nebari/pull/2888
- Yaml config sets by @Adam-D-Lewis in https://github.com/nebari-dev/nebari/pull/287-
@@ -102,7 +107,7 @@ This file is copied to nebari-dev/nebari-docs using a GitHub Action. -->
- @soapy1 made their first contribution in https://github.com/nebari-dev/nebari/pull2891
- @smokestacklightnin made their first contribution in https://github.com/nebari-dev
-/nebari/pull/2839
+ /nebari/pull/2839
- @kernel-loophole made their first contribution in https://github.com/nebari-dev/nebari/pull/2916
**Full Changelog**: https://github.com/nebari-dev/nebari/compare/2024.12.1...2025.2.1
@@ -112,6 +117,7 @@ This file is copied to nebari-dev/nebari-docs using a GitHub Action. -->
> NOTE: Support for DigitalOcean has been removed in this release. If you plan to deploy Nebari on DigitalOcean, you first need to independently create a Kubernetes cluster and then use the `existing` deployment option.
### What's Changed
+
- Precommit typos by @blakerosenthal in https://github.com/nebari-dev/nebari/pull/2731
- fix typo in KubernetesCredentials by @blakerosenthal in https://github.com/nebari-dev/nebari/pull/2729
- handle branch rename from develop to main in github actions by @Adam-D-Lewis in https://github.com/nebari-dev/nebari/pull/2748
@@ -152,6 +158,7 @@ This file is copied to nebari-dev/nebari-docs using a GitHub Action. -->
- update gcp instance validation by @dcmcand in https://github.com/nebari-dev/nebari/pull/2875
### New Contributors
+
- @jcbolling made their first contribution in https://github.com/nebari-dev/nebari/pull/2850
**Full Changelog**: https://github.com/nebari-dev/nebari/compare/2024.11.1...2024.12.1
diff --git a/docker/Dockerfile b/docker/Dockerfile
new file mode 100644
index 0000000000..a12d460814
--- /dev/null
+++ b/docker/Dockerfile
@@ -0,0 +1,158 @@
+FROM ubuntu:24.04 AS builder
+LABEL MAINTAINER="Nebari development team"
+
+RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
+ --mount=type=cache,target=/var/lib/apt,sharing=locked \
+ apt-get update && apt-get install -y --no-install-recommends \
+ wget \
+ bzip2 \
+ ca-certificates \
+ curl \
+ git
+
+COPY scripts /opt/scripts
+
+ENV MAMBAFORGE_VERSION=4.13.0-1 \
+ MAMBAFORGE_AARCH64_SHA256=69e3c90092f61916da7add745474e15317ed0dc6d48bfe4e4c90f359ba141d23 \
+ MAMBAFORGE_X86_64_SHA256=412b79330e90e49cf7e39a7b6f4752970fcdb8eb54b1a45cc91afe6777e8518c \
+ PATH=/opt/conda/bin:${PATH}:/opt/scripts
+
+
+RUN /opt/scripts/install-conda.sh
+
+
+
+# ========== dask-worker install ===========
+FROM builder AS dask-worker
+COPY dask-worker/environment.yaml /opt/dask-worker/environment.yaml
+RUN --mount=type=cache,target=/opt/conda/pkgs,sharing=locked \
+ --mount=type=cache,target=/root/.cache/pip,sharing=locked \
+ /opt/scripts/install-conda-environment.sh /opt/dask-worker/environment.yaml 'false'
+
+ENV LD_LIBRARY_PATH=/usr/local/nvidia/lib64
+ENV NVIDIA_PATH=/usr/local/nvidia/bin
+ENV PATH="$NVIDIA_PATH:$PATH"
+
+COPY dask-worker /opt/dask-worker
+RUN /opt/dask-worker/postBuild
+
+
+
+
+
+# ========== jupyterhub install ===========
+FROM builder AS jupyterhub
+COPY jupyterhub/environment.yaml /opt/jupyterhub/environment.yaml
+RUN --mount=type=cache,target=/opt/conda/pkgs,sharing=locked \
+ --mount=type=cache,target=/root/.cache/pip,sharing=locked \
+ /opt/scripts/install-conda-environment.sh /opt/jupyterhub/environment.yaml 'false'
+
+COPY jupyterhub /opt/jupyterhub
+RUN /opt/jupyterhub/postBuild
+
+WORKDIR /srv/jupyterhub
+
+# So we can actually write a db file here
+RUN fix-permissions /srv/jupyterhub
+
+CMD ["jupyterhub", "--config", "/usr/local/etc/jupyterhub/jupyterhub_config.py"]
+
+
+
+
+# ========== jupyterlab base ===========
+FROM builder AS intermediate
+ENV LANG=C.UTF-8 LC_ALL=C.UTF-8 \
+ CONDA_DIR=/opt/conda \
+ DEFAULT_ENV=default
+RUN chmod -R a-w ~
+ENV TZ=UTC \
+ PATH=/opt/conda/envs/${DEFAULT_ENV}/bin:/opt/conda/bin:${PATH}:/opt/scripts
+# Set timezone
+RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
+
+RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
+ --mount=type=cache,target=/var/lib/apt,sharing=locked \
+ apt-get update && apt-get install -y --no-install-recommends \
+ locales \
+ libnss-wrapper \
+ htop \
+ tree \
+ zip \
+ unzip \
+ openssh-client \
+ tmux \
+ xvfb \
+ nano \
+ vim \
+ emacs
+
+
+# ========== jupyterlab install ===========
+FROM intermediate AS jupyterlab
+ENV CONDA_DIR=/opt/conda \
+ DEFAULT_ENV=default \
+ LD_LIBRARY_PATH=/usr/local/nvidia/lib64 \
+ NVIDIA_PATH=/usr/local/nvidia/bin
+
+ENV PATH="$NVIDIA_PATH:$PATH"
+
+RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
+ --mount=type=cache,target=/var/lib/apt,sharing=locked \
+ apt-get update && apt-get install -y --no-install-recommends \
+ zsh \
+ neovim \
+ libgl1 \
+ libglx-mesa0 \
+ libxrandr2 \
+ libxss1 \
+ libxcursor1 \
+ libxcomposite1 \
+ libasound2t64 \
+ libxi6 \
+ libxtst6 \
+ libfontconfig1 \
+ libxrender1 \
+ libosmesa6 \
+ gnupg \
+ pinentry-curses \
+ git-lfs
+
+ARG SKIP_CONDA_SOLVE=no
+COPY jupyterlab/environment.yaml /opt/jupyterlab/environment.yaml
+RUN --mount=type=cache,target=/opt/conda/pkgs,sharing=locked \
+ --mount=type=cache,target=/root/.cache/pip,sharing=locked \
+ if [ "${SKIP_CONDA_SOLVE}" != "no" ];then \
+ ENV_FILE=/opt/jupyterlab/conda-linux-64.lock ; \
+ else \
+ ENV_FILE=/opt/jupyterlab/environment.yaml ; \
+ fi ; \
+ /opt/scripts/install-conda-environment.sh "${ENV_FILE}" 'true'
+
+# ========== code-server install ============
+ENV PATH=/opt/conda/envs/${DEFAULT_ENV}/share/code-server/bin:${PATH}
+
+COPY jupyterlab /opt/jupyterlab
+RUN /opt/jupyterlab/postBuild
+
+
+
+
+
+# ========== nebari-workflow-controller install ============
+FROM intermediate AS workflow-controller
+
+ARG SKIP_CONDA_SOLVE=no
+COPY nebari-workflow-controller/environment.yaml /opt/nebari-workflow-controller/environment.yaml
+RUN --mount=type=cache,target=/opt/conda/pkgs,sharing=locked \
+ --mount=type=cache,target=/root/.cache/pip,sharing=locked \
+ if [ "${SKIP_CONDA_SOLVE}" != "no" ];then \
+ ENV_FILE=/opt/nebari-workflow-controller/conda-linux-64.lock ; \
+ else \
+ ENV_FILE=/opt/nebari-workflow-controller/environment.yaml ; \
+ fi ; \
+ /opt/scripts/install-conda-environment.sh "${ENV_FILE}" 'true'
+
+COPY nebari-workflow-controller /opt/nebari-workflow-controller
+
+CMD ["python", "-m", "nebari_workflow_controller"]
diff --git a/docker/README.md b/docker/README.md
new file mode 100644
index 0000000000..d943cd37fb
--- /dev/null
+++ b/docker/README.md
@@ -0,0 +1,136 @@
+
+
+
+
+
+
+
+
+---
+
+# Nebari base Docker images
+
+| Information | Links |
+| :---------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| Project | [](https://opensource.org/licenses/BSD-3-Clause) [][nebari-docs] |
+| Community | [][nebari-discussions] [][nebari-docker-issues] |
+| CI |  |
+
+- [Nebari base Docker images](#nebari-base-docker-images)
+ - [Getting started ⚡️](#getting-started-️)
+ - [Prerequisites 💻](#prerequisites-)
+ - [Building the Docker images 🛠](#building-the-docker-images-)
+ - [Pre-commit hooks 🧹](#pre-commit-hooks-)
+ - [Reporting an issue 📝](#reporting-an-issue-)
+ - [Contributions 🤝](#contributions-)
+ - [License 📄](#license-)
+
+This repository contains the source code for Docker (container) images used by the [Nebari platform][nebari-docs]. It also contains an automated means of building and pushing these images to public container registries through [GitHub actions][nebari-docker-actions]. Currently, these images are built and pushed to the following registries:
+
+**GitHub Container Registry (ghcr.io)**
+
+- [`nebari-jupyterlab`](https://github.com/orgs/nebari-dev/packages/container/package/nebari-jupyterlab)
+- [`nebari-jupyterlab-gpu`](https://github.com/orgs/nebari-dev/packages/container/package/nebari-jupyterlab-gpu)
+- [`nebari-jupyterhub`](https://github.com/orgs/nebari-dev/packages/container/package/nebari-jupyterhub)
+- [`nebari-dask-worker`](https://github.com/orgs/nebari-dev/packages/container/package/nebari-dask-worker)
+- [`nebari-dask-worker-gpu`](https://github.com/orgs/nebari-dev/packages/container/package/nebari-dask-worker-gpu)
+
+**Quay Container Registry (quay.io)**
+
+- [`nebari-jupyterlab`](https://quay.io/repository/nebari/nebari-jupyterlab)
+- [`nebari-jupyterlab-gpu`](https://quay.io/repository/nebari/nebari-jupyterlab-gpu)
+- [`nebari-jupyterhub`](https://quay.io/repository/nebari/nebari-jupyterhub)
+- [`nebari-dask-worker`](https://quay.io/repository/nebari/nebari-dask-worker)
+- [`nebari-dask-worker-gpu`](https://quay.io/repository/nebari/nebari-dask-worker-gpu)
+
+## Getting started ⚡️
+
+Whether you want to contribute to this project or whether you wish use these images, to get started, fork this repo and then clone the forked repo onto your local machine.
+
+### Prerequisites 💻
+
+- [`docker`](https://docs.docker.com/get-docker/), make sure to read the [Docker official documentation on how to install Docker on your machine](https://docs.docker.com/get-docker/).
+- [pre-commit](https://pre-commit.com/), which can be installed with:
+
+ ```bash
+ pip install pre-commit
+ # or using conda
+ conda install -c conda-forge pre-commit
+ ```
+
+### Building the Docker images 🛠
+
+From the repository's root folder, you can build these images locally by running the listed commands on your terminal.
+
+- To build nebari-jupyterlab
+
+ ```shell
+ make jupyterlab
+ ```
+
+- To build nebari-jupyterhub
+
+ ```shell
+ make jupyterhub
+ ```
+
+- To build nebari-dask-worker
+
+ ```shell
+ make dask-worker
+ ```
+
+- To build nebari-workflow-controller
+
+ ```shell
+ make workflow-controller
+ ```
+
+- To build all of the images
+
+ ```shell
+ make all
+ ```
+
+- To delete built images
+
+ ```shell
+ make clean
+ ```
+
+> **NOTE**
+> It is extremely important to pin specific packages `dask-gateway` and `distributed` as they need to run the same version for the `dask-workers` to work as expected.
+
+### Pre-commit hooks 🧹
+
+This repository uses the `prettier` pre-commit hook to standardize our YAML and markdown structure.
+To install and run it, use these commands from the repository root:
+
+```bash
+# install the pre-commit hooks
+pre-commit install
+
+# run the pre-commit hooks
+pre-commit run --all-files
+```
+
+## Reporting an issue 📝
+
+If you encounter an issue or want to make suggestions on how we can make this project better, feel free to [open an issue on this repository's issue tracker](https://github.com/nebari-dev/nebari-docker-images/issues/new/choose).
+
+## Contributions 🤝
+
+Thinking about contributing to this repository or any other in the Nebari org? Check out our
+[Contribution Guidelines](https://nebari.dev/community).
+
+## License 📄
+
+[Nebari is BSD3 licensed](LICENSE).
+
+
+
+[nebari-docker-repo]: https://github.com/nebari-dev/nebari-docker-images
+[nebari-docker-issues]: https://github.com/nebari-dev/nebari-docker-images/issues/new/choose
+[nebari-docker-actions]: https://github.com/nebari-dev/nebari-docker-images/actions
+[nebari-discussions]: https://github.com/orgs/nebari-dev/discussions
+[nebari-docs]: https://nebari.dev
diff --git a/docker/dask-worker/environment.yaml b/docker/dask-worker/environment.yaml
new file mode 100644
index 0000000000..16f4acb89f
--- /dev/null
+++ b/docker/dask-worker/environment.yaml
@@ -0,0 +1,9 @@
+# Copyright (c) Nebari Development Team.
+# Distributed under the terms of the Modified BSD License.
+
+name: base
+channels:
+ - conda-forge
+dependencies:
+ # dask
+ - nebari-dask
diff --git a/docker/dask-worker/postBuild b/docker/dask-worker/postBuild
new file mode 100644
index 0000000000..72cee969b8
--- /dev/null
+++ b/docker/dask-worker/postBuild
@@ -0,0 +1,26 @@
+#!/usr/bin/env bash
+# Copyright (c) Nebari Development Team.
+# Distributed under the terms of the Modified BSD License.
+
+set -euo pipefail
+
+# A workaround that allows a command to run in a
+# specific conda environment
+cat </opt/conda-run-worker
+#!/bin/bash
+set -xe
+
+source activate \$CONDA_ENVIRONMENT
+dask-worker "\$@"
+EOF
+
+cat </opt/conda-run-scheduler
+#!/bin/bash
+set -xe
+
+source activate \$CONDA_ENVIRONMENT
+dask-scheduler "\$@"
+EOF
+
+chmod 755 /opt/conda-run-worker
+chmod 755 /opt/conda-run-scheduler
diff --git a/docker/jupyterhub/environment.yaml b/docker/jupyterhub/environment.yaml
new file mode 100644
index 0000000000..dc4739995c
--- /dev/null
+++ b/docker/jupyterhub/environment.yaml
@@ -0,0 +1,17 @@
+name: base
+channels:
+ - conda-forge
+dependencies:
+ - pip==21.1.2
+ - jupyterhub==5.3.0
+ - jupyterhub-kubespawner==6.2.0
+ - oauthenticator==16.3.0
+ - escapism==1.0.1
+ - python-kubernetes
+ - kubernetes_asyncio==29.0.0
+ - jupyterhub-idle-culler==1.2.1
+ - sqlalchemy==1.4.46
+ - pip:
+ - nebari-jupyterhub-theme==2024.7.1
+ - python-keycloak==0.26.1
+ - jhub-apps==2025.2.1
diff --git a/docker/jupyterhub/postBuild b/docker/jupyterhub/postBuild
new file mode 100644
index 0000000000..6b7e4da137
--- /dev/null
+++ b/docker/jupyterhub/postBuild
@@ -0,0 +1,5 @@
+#!/usr/bin/env bash
+# Copyright (c) Nebari Development Team.
+# Distributed under the terms of the Modified BSD License.
+
+set -euo pipefail
diff --git a/docker/jupyterlab/environment.yaml b/docker/jupyterlab/environment.yaml
new file mode 100644
index 0000000000..2c22a36e2c
--- /dev/null
+++ b/docker/jupyterlab/environment.yaml
@@ -0,0 +1,69 @@
+# Copyright (c) Nebari Development Team.
+# Distributed under the terms of the Modified BSD License.
+
+name: default
+channels:
+ - conda-forge
+dependencies:
+ # general
+ - pip
+
+ # jupyterhub/jupyterlab
+ - nb_conda_kernels
+ - ipython > 7
+ - jupyter-server-proxy >=4.4.0
+ - "jupyter_server>=2.13.0"
+ - jupyterlab==4.4.2
+ - jupyter_client
+ - jupyter_console
+ - jupyterhub==5.3.0
+ - nbconvert
+ - nbval
+
+ # jupyterhub extension
+
+ # jupyterlab extensions
+ - dask_labextension >= 5.3.0
+ - jupyterlab-git >=0.30.0
+ - sidecar >=0.5.0
+ - ipywidgets >= 8.0.0
+ - ipyleaflet >=0.13.5
+ - pyviz_comms >=3.0.3
+ - jupyter-resource-usage >=0.6.0
+ - nbgitpuller
+ - jupyterlab_code_formatter
+ - jupyterlab-spellchecker >= 0.7.3
+ - jupyterlab-pioneer
+ - jupyter-ai
+ - jupyterlab-favorites >=3.2.1
+ - jupyter-scheduler >=2.8.0,<3.0.0 # >=2.8 due to https://github.com/conda-forge/jupyter_scheduler-feedstock/issues/46
+
+ # viz tools
+ - param
+ - python-graphviz
+ - plotly >=5.0
+ - ipympl >=0.9.6
+ - bokeh >=3.5.2
+
+ # testing, docs, linting
+ - pytest
+ - hypothesis
+ - flake8
+ - sphinx
+ - pytest-cov
+ - black
+ - isort
+ - importnb
+ - git-lfs
+
+ - pip:
+ # vscode jupyterlab launcher
+ - git+https://github.com/betatim/vscode-binder
+ - jupyterlab_nvdashboard==0.12.0
+ - argo-jupyter-scheduler==2024.6.1
+ - jhub-apps==2025.2.1
+ - jupyterlab-nebari-mode==0.3.0
+ - jupyterlab-conda-store==2024.11.1
+ - jupyterlab-launchpad==1.0.3
+ - jupyterlab-gallery==0.6.3
+ - jupyterlab-jhub-apps==0.3.1
diff --git a/docker/jupyterlab/postBuild b/docker/jupyterlab/postBuild
new file mode 100644
index 0000000000..67fb479153
--- /dev/null
+++ b/docker/jupyterlab/postBuild
@@ -0,0 +1,15 @@
+#!/usr/bin/env bash
+set -euo pipefail
+set -x
+
+# install code-server extension
+sh /opt/scripts/install-code-server.sh "/opt/conda/envs/${DEFAULT_ENV}/share"
+
+# if DEFAULT_ENV is unset ${DEFAULT_ENV+x} expands to nothing otherwise
+# it substitutes the string x. This allows us to check if the variable
+# is set without triggering an unbound variable error
+if [[ -z "${DEFAULT_ENV+x}" ]]; then
+ fix-permissions /opt/conda/bin
+else
+ fix-permissions "/opt/conda/envs/${DEFAULT_ENV}"
+fi
diff --git a/docker/makefile b/docker/makefile
new file mode 100644
index 0000000000..0075e45cb1
--- /dev/null
+++ b/docker/makefile
@@ -0,0 +1,27 @@
+IMAGES := jupyterhub jupyterlab dask-worker workflow-controller
+DOCKERFILE := Dockerfile
+CONTEXT := .
+
+.PHONY: all $(IMAGES) clean
+
+# Build all images
+all: $(IMAGES)
+
+# Build individual images
+jupyterhub:
+ docker build -t nebari-dev/nebari-docker-images:nebari-jupyterhub -f $(DOCKERFILE) $(CONTEXT) --target jupyterhub
+
+jupyterlab:
+ docker build -t nebari-dev/nebari-docker-images:nebari-jupyterlab -f $(DOCKERFILE) $(CONTEXT) --target jupyterlab
+
+dask-worker:
+ docker build -t nebari-dev/nebari-docker-images:nebari-dask-worker -f $(DOCKERFILE) $(CONTEXT) --target dask-worker
+
+workflow-controller:
+ docker build -t nebari-dev/nebari-docker-images:nebari-workflow-controller -f $(DOCKERFILE) $(CONTEXT) --target workflow-controller
+
+# Clean up images
+clean:
+ @for image in $(IMAGES); do \
+ docker rmi nebari-dev/nebari-docker-images:nebari-$$image; \
+ done
diff --git a/docker/nebari-workflow-controller/environment.yaml b/docker/nebari-workflow-controller/environment.yaml
new file mode 100644
index 0000000000..55e6859ad7
--- /dev/null
+++ b/docker/nebari-workflow-controller/environment.yaml
@@ -0,0 +1,8 @@
+name: default
+channels:
+ - conda-forge
+dependencies:
+ - python=3.10
+ - pip
+ - pip:
+ - nebari-workflow-controller==2023.7.1
diff --git a/docker/scripts/fix-permissions b/docker/scripts/fix-permissions
new file mode 100644
index 0000000000..8e9926c02c
--- /dev/null
+++ b/docker/scripts/fix-permissions
@@ -0,0 +1,15 @@
+#!/bin/bash
+# Copyright (c) Nebari Development Team.
+# Distributed under the terms of the Modified BSD License.
+
+# uses find to avoid touching files that already have the right permissions
+# right permissions are:
+# world rX, we have no guarantees of uids or gids upon
+# deployment so we want files accessible to all.
+
+set -e
+for d in "$@"; do
+ find "$d" \
+ ! -perm -o+rX \
+ -exec chmod o+rX {} \;
+done
diff --git a/docker/scripts/install-code-server.sh b/docker/scripts/install-code-server.sh
new file mode 100644
index 0000000000..9c5700c65e
--- /dev/null
+++ b/docker/scripts/install-code-server.sh
@@ -0,0 +1,26 @@
+#!/usr/bin/env bash
+# Copyright (c) Nebari Development Team.
+# Distributed under the terms of the Modified BSD License.
+
+set -xe
+DEFAULT_PREFIX="${1}"
+shift # path to environment yaml or lock file
+CODE_SERVER_VERSION=4.23.1
+
+mkdir -p ${DEFAULT_PREFIX}/code-server
+cd ${DEFAULT_PREFIX}/code-server
+
+# Fetch the snapshot of https://code-server.dev/install.sh as of the time of writing
+wget --quiet https://raw.githubusercontent.com/coder/code-server/v4.23.1/install.sh
+expected_sum=ef0324043bc7493989764315e22bbc85c38c4e895549538b7e701948b64495e6
+
+if [[ ! $(sha256sum install.sh) == "${expected_sum} install.sh" ]]; then
+ echo Unexpected hash from code-server install script
+ exit 1
+fi
+
+mkdir /opt/tmpdir
+sh ./install.sh --method standalone --prefix /opt/tmpdir --version ${CODE_SERVER_VERSION}
+
+mv /opt/tmpdir/lib/code-server-${CODE_SERVER_VERSION}/* ${DEFAULT_PREFIX}/code-server
+rm -rf /opt/tmpdir
diff --git a/docker/scripts/install-conda-environment.sh b/docker/scripts/install-conda-environment.sh
new file mode 100644
index 0000000000..92b7a8fde9
--- /dev/null
+++ b/docker/scripts/install-conda-environment.sh
@@ -0,0 +1,61 @@
+#!/usr/bin/env bash
+# Copyright (c) Nebari Development Team.
+# Distributed under the terms of the Modified BSD License.
+
+set -xe
+ENV_FILE="${1}"
+shift # path to environment yaml or lock file
+NEW_ENV="${1}"
+shift # true or false indicating whether env update should occur
+
+# Capture last optional arg or set a ENV_NAME. This can be changed but be
+# careful... setting the path for both the dockerfile and runtime container
+# can be tricky
+if [[ -z "${1+x}" ]] || [[ "${1}" == "" ]]; then
+ ENV_NAME=default
+else
+ ENV_NAME="${1}"
+ shift
+fi
+
+# Set a default value for skipping the conda solve (using a lock file).
+: ${SKIP_CONDA_SOLVE:=no}
+
+# ==== install conda dependencies ====
+
+if ! ${NEW_ENV}; then
+ if [[ $(basename "${ENV_FILE}") =~ "*lock*" ]]; then
+ echo "${ENV_FILE} should not be a lock file as this is not supported when \
+ only updating the conda environment. Consider setting NEW_ENV to yes."
+ exit 1
+ fi
+ echo Installing into current conda environment
+ mamba env update -f "${ENV_FILE}"
+
+# Env not being updated... create one now:
+elif [[ "${SKIP_CONDA_SOLVE}" == "no" ]]; then
+ mamba env create --prefix=/opt/conda/envs/${ENV_NAME} -f "${ENV_FILE}"
+elif [[ "${SKIP_CONDA_SOLVE}" == "yes" ]]; then
+ mamba create --prefix=/opt/conda/envs/${ENV_NAME} --file "${ENV_FILE}"
+
+ # This needs to be set using the ENV directive in the docker file
+ PATH="/opt/conda/envs/${ENV_NAME}/bin:${PATH}"
+ # For now install pip section manually. We could consider using pip-tools...
+ # See https://github.com/conda-incubator/conda-lock/issues/4
+ pip install https://github.com/dirkcgrunwald/jupyter_codeserver_proxy-/archive/5596bc9c2fbd566180545fa242c659663755a427.tar.gz
+else
+ echo "SKIP_CONDA_SOLVE should be yes or no instead got: '${SKIP_CONDA_SOLVE}'"
+ exit 1
+fi
+
+# ========= list dependencies ========
+/opt/conda/bin/conda list
+
+# ========== cleanup conda ===========
+/opt/conda/bin/mamba clean -afy
+# remove unnecessary files (status, js.maps)
+find /opt/conda/ -follow -type f -name '*.a' -delete
+find /opt/conda/ -follow -type f -name '*.js.map' -delete
+
+# Fix permissions
+fix-permissions "/opt/conda/envs/${ENV_NAME}" || fix-permissions /opt/conda/bin
diff --git a/docker/scripts/install-conda.sh b/docker/scripts/install-conda.sh
new file mode 100644
index 0000000000..feda68b221
--- /dev/null
+++ b/docker/scripts/install-conda.sh
@@ -0,0 +1,53 @@
+#!/usr/bin/env bash
+# Copyright (c) Nebari Development Team.
+# Distributed under the terms of the Modified BSD License.
+
+set -xe
+
+# Requires environment MAMBAFORGE_SHA256, MINIFORGE_VERSION, and DEFAULT_ENV
+arch=$(uname -i)
+wget --quiet -O mambaforge.sh https://github.com/conda-forge/miniforge/releases/download/$MAMBAFORGE_VERSION/Mambaforge-Linux-$arch.sh
+
+if [[ $arch == "aarch64" ]]; then
+ echo "${MAMBAFORGE_AARCH64_SHA256} mambaforge.sh" >mambaforge.checksum
+elif [[ $arch == "x86_64" ]]; then
+ echo "${MAMBAFORGE_X86_64_SHA256} mambaforge.sh" >mambaforge.checksum
+else
+ echo "Unsupported architecture: $arch"
+ exit 1
+fi
+
+echo $(sha256sum -c mambaforge.checksum)
+
+if [ $(sha256sum -c mambaforge.checksum | awk '{print $2}') != "OK" ]; then
+ echo Error when testing checksum
+ exit 1
+fi
+
+# Install Mamba and clean-up
+if [ -d "/opt/conda" ]; then
+ sh ./mambaforge.sh -b -u -p /opt/conda
+else
+ sh ./mambaforge.sh -b -p /opt/conda
+fi
+
+rm mambaforge.sh mambaforge.checksum
+
+mamba --version
+mamba clean -afy
+
+ln -s /opt/conda/etc/profile.d/conda.sh /etc/profile.d/conda.sh
+
+mkdir -p /etc/conda
+cat </etc/conda/condarc
+always_yes: true
+changeps1: false
+auto_update_conda: false
+aggressive_update_packages: []
+envs_dirs:
+ - /home/conda/environments
+EOF
+
+# Fix permissions in accordance with jupyter stack permissions
+# model
+fix-permissions /opt/conda /etc/conda /etc/profile.d
diff --git a/docker/scripts/install-gitlfs.sh b/docker/scripts/install-gitlfs.sh
new file mode 100644
index 0000000000..47dc9177f0
--- /dev/null
+++ b/docker/scripts/install-gitlfs.sh
@@ -0,0 +1,20 @@
+#!/usr/bin/env bash
+# Copyright (c) Nebari Development Team.
+# Distributed under the terms of the Modified BSD License.
+
+set -xe
+
+# Adding the packagecloud repository for git-lfs installation
+wget --quiet -O script.deb.sh https://packagecloud.io/install/repositories/github/git-lfs/script.deb.sh
+expected_sum=8c4d07257b8fb6d612b6085f68ad33c34567b00d0e4b29ed784b2a85380f727b
+
+if [[ ! $(sha256sum script.deb.sh) == "${expected_sum} script.deb.sh" ]]; then
+ echo Unexpected hash from git-lfs install script
+ exit 1
+fi
+
+# Install packagecloud's repository signing key and add repository to apt
+bash ./script.deb.sh
+
+# Install git-lfs
+apt-get install -y --no-install-recommends git-lfs
diff --git a/docs-sphinx/cli.html b/docs-sphinx/cli.html
index 6cb22bdbd4..621a973ae1 100644
--- a/docs-sphinx/cli.html
+++ b/docs-sphinx/cli.html
@@ -3,757 +3,2351 @@
-
-
- Nebari CLI — Nebari CLI documentation documentation
-
-
-
+
+
+
+ Nebari CLI — Nebari CLI documentation documentation
+
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
Create and initialize your [purple]nebari-config.yaml[/purple] file.
-
This command will create and initialize your [purple]nebari-config.yaml[/purple] :sparkles:
-
This file contains all your Nebari cluster configuration details and,
-is used as input to later commands such as [green]nebari render[/green], [green]nebari deploy[/green], etc.
-
If you’re new to Nebari, we recommend you use the Guided Init wizard.
-To get started simply run:
[bold green]START HERE[/bold green] - this will guide you step-by-step to generate your [purple]nebari-config.yaml[/purple]. It is an [i]alternative[/i] to passing the options listed below.
Support tool to write all Kubernetes logs locally and compress them into a zip file.
-
The Nebari team recommends k9s to manage and inspect the state of the cluster.
-However, this command occasionally helpful for debugging purposes should the logs need to be shared.
Upgrade your [purple]nebari-config.yaml[/purple] after an nebari upgrade. If necessary, prompts users to perform manual upgrade steps required for the deploy process.
-
See the project [green]RELEASE.md[/green] for details.
+ Create and initialize your
+ [purple]nebari-config.yaml[/purple] file.
+
+
+ This command will create and initialize your
+ [purple]nebari-config.yaml[/purple] :sparkles:
+
+
+ This file contains all your Nebari cluster configuration
+ details and, is used as input to later commands such as
+ [green]nebari render[/green], [green]nebari deploy[/green],
+ etc.
+
+
+ If you’re new to Nebari, we recommend you use the Guided
+ Init wizard. To get started simply run:
+
+ [bold green]START HERE[/bold green] - this will guide
+ you step-by-step to generate your
+ [purple]nebari-config.yaml[/purple]. It is an
+ [i]alternative[/i] to passing the options listed below.
+
+ Support tool to write all Kubernetes logs locally and
+ compress them into a zip file.
+
+
+ The Nebari team recommends k9s to manage and inspect the
+ state of the cluster. However, this command occasionally
+ helpful for debugging purposes should the logs need to be
+ shared.
+
+ Upgrade your [purple]nebari-config.yaml[/purple] after an
+ nebari upgrade. If necessary, prompts users to perform
+ manual upgrade steps required for the deploy process.
+
+
See the project [green]RELEASE.md[/green] for details.