├── CODE_OF_CONDUCT.md
├── LICENSE.txt
├── README.md
├── assets
└── animation.gif
└── values.yaml
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | In the interest of fostering an open and welcoming environment, we as
6 | contributors and maintainers pledge to making participation in our project and
7 | our community a harassment-free experience for everyone, regardless of age, body
8 | size, disability, ethnicity, sex characteristics, gender identity and expression,
9 | level of experience, education, socio-economic status, nationality, personal
10 | appearance, race, religion, or sexual identity and orientation.
11 |
12 | ## Our Standards
13 |
14 | Examples of behavior that contributes to creating a positive environment
15 | include:
16 |
17 | * Using welcoming and inclusive language
18 | * Being respectful of differing viewpoints and experiences
19 | * Gracefully accepting constructive criticism
20 | * Focusing on what is best for the community
21 | * Showing empathy towards other community members
22 |
23 | Examples of unacceptable behavior by participants include:
24 |
25 | * The use of sexualized language or imagery and unwelcome sexual attention or
26 | advances
27 | * Trolling, insulting/derogatory comments, and personal or political attacks
28 | * Public or private harassment
29 | * Publishing others' private information, such as a physical or electronic
30 | address, without explicit permission
31 | * Other conduct which could reasonably be considered inappropriate in a
32 | professional setting
33 |
34 | ## Our Responsibilities
35 |
36 | Project maintainers are responsible for clarifying the standards of acceptable
37 | behavior and are expected to take appropriate and fair corrective action in
38 | response to any instances of unacceptable behavior.
39 |
40 | Project maintainers have the right and responsibility to remove, edit, or
41 | reject comments, commits, code, wiki edits, issues, and other contributions
42 | that are not aligned to this Code of Conduct, or to ban temporarily or
43 | permanently any contributor for other behaviors that they deem inappropriate,
44 | threatening, offensive, or harmful.
45 |
46 | ## Scope
47 |
48 | This Code of Conduct applies both within project spaces and in public spaces
49 | when an individual is representing the project or its community. Examples of
50 | representing a project or community include using an official project e-mail
51 | address, posting via an official social media account, or acting as an appointed
52 | representative at an online or offline event. Representation of a project may be
53 | further defined and clarified by project maintainers.
54 |
55 | ## Enforcement
56 |
57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
58 | reported by contacting the project team at nilslennartbraun@gmail.com. All
59 | complaints will be reviewed and investigated and will result in a response that
60 | is deemed necessary and appropriate to the circumstances. The project team is
61 | obligated to maintain confidentiality with regard to the reporter of an incident.
62 | Further details of specific enforcement policies may be posted separately.
63 |
64 | Project maintainers who do not follow or enforce the Code of Conduct in good
65 | faith may face temporary or permanent repercussions as determined by other
66 | members of the project's leadership.
67 |
68 | ## Attribution
69 |
70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
72 |
73 | [homepage]: https://www.contributor-covenant.org
74 |
75 | For answers to common questions about this code of conduct, see
76 | https://www.contributor-covenant.org/faq
77 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | MIT LICENCE
2 |
3 | Copyright (c) 2020 Nils Braun
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
6 | documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
7 | rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
8 | persons to whom the Software is furnished to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
11 | Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
14 | WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
15 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
16 | OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
17 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Zero-to-Codehub
2 |
3 |
4 |
5 |
6 |
7 | This repository contains a guide on how to deploy a multi-user full-blown IDE (Visual Studio Code) installation
8 | on your k8s cluster (e.g. in the public cloud) by glueing together two very nice projects:
9 |
10 | * [Zero to Jupyterhub](https://zero-to-jupyterhub.readthedocs.io/en/latest/index.html): a guide (and helm charts) for deploying jupyterhub to k8s. Jupyterhub is a multi-tenancy installation for managing [jupyter notebooks](https://jupyter.org/).
11 | * [code-server](https://github.com/cdr/code-server), an open-source ready-to-use VS Code installation (and docker image).
12 |
13 | ## Features
14 |
15 | The Codehub brings you multiple nice features:
16 | * Give developers the chance to start working on a project without any overhead or installation: a browser and credentials is all they need
17 | * Scalable, low-maintenance, multi-user installation of an IDE: every logged-in user gets its own running VS Code accessible via the browser.
18 | Optionally, you can add persistent storage, extensions, personalization, different project spaces...
19 | * Use the huge ecosystem around jupyterhub for easily integrating and configuring authentication (LDAP, OAuth, active directory, simple, ...), HTTPS, resource management and storage, user customization and so much more
20 |
21 | ## Get started
22 |
23 | If you have k8s, helm and a persistent storage provider not already set up, follow one of these [guides](https://zero-to-jupyterhub.readthedocs.io/en/latest/kubernetes/index.html) from the Zero to Jupyterhub documentation, to create a k8s cluster on GCP, AWS, Azure or other cloud provider.
24 | Also make sure, to have [helm](https://helm.sh/) installed.
25 |
26 | In principle, we just follow the remaining installation [guide](https://zero-to-jupyterhub.readthedocs.io/en/latest/jupyterhub/installation.html) to also install jupyterhub on k8s, but we use the supplied custom values file to choose the VS Code image.
27 |
28 | Add the jupyterhub helm chart:
29 |
30 | helm repo add jupyterhub https://jupyterhub.github.io/helm-chart/
31 | helm repo update
32 |
33 | Now clone or download the [values.yaml](./values.yaml) file and replace the `proxy.secretToken` by the output of `openssl rand -hex 32`.
34 |
35 | After that, install the jupyterhub/codehub helm chart:
36 |
37 | helm upgrade --cleanup-on-fail --install codehub jupyterhub/jupyterhub --values values.yaml
38 |
39 | Wait for all pods to be running
40 |
41 | kubectl get pod
42 |
43 | You can now visit your codehub on the external address of the `proxy-public` service
44 |
45 | kubectl get service
46 |
47 | or by using a port forwarding
48 |
49 | kubectl port-forward svc/proxy-public 8000:80
50 |
51 | and then visiting http://localhost:8000.
52 |
53 | The default authenticator is a dummy authenticator which accepts any username or password combination.
54 |
55 | **Attention**: this repository is for educative purposes only. It was not tested for security thoroughly. Giving users a full IDE with root access can be a severe security problem - even when "only" running in containers.
56 |
57 | ### Stopping your server
58 |
59 | So far, there is no button to stop your server from within VS Code.
60 | However, you can visit `/hub/home` and press "Stop My Server".
61 |
62 | ## Possible customizations
63 |
64 | Behind the scenes, it is still a "normal" jupyterhub installation deployed via the battle-tested jupyterhub helm chart.
65 | Therefore, every customization und extension already implemented in jupyterhub can probably used without any changes.
66 |
67 | Examples are:
68 | * Let users choose between different "profiles" (e.g. resources, predefined images), see [here](https://zero-to-jupyterhub.readthedocs.io/en/latest/jupyterhub/customizing/user-environment.html#using-multiple-profiles-to-let-users-select-their-environment)
69 | * Customize user [resources](https://zero-to-jupyterhub.readthedocs.io/en/latest/jupyterhub/customizing/user-resources.html) and [persistent storage](https://zero-to-jupyterhub.readthedocs.io/en/latest/jupyterhub/customizing/user-storage.html)
70 | * Using a different authenticator, e.g. OAuth2 (e.g. via github), LDAP, Active Directory. See [here](https://zero-to-jupyterhub.readthedocs.io/en/latest/administrator/authentication.html) for more information.
71 | * Use HTTPS for encrypting the communication with the hub. See [here](https://zero-to-jupyterhub.readthedocs.io/en/latest/administrator/security.html#https) for more information.
72 | * Automatically remove idle servers, see [here](https://zero-to-jupyterhub.readthedocs.io/en/latest/jupyterhub/customizing/user-management.html#culling-user-pods).
73 |
74 | All the mentioned configurations can be controlled via the `values.yaml` file specified on helm chart installation.
75 | When customizing, make sure to not overwrite the already present
76 | settings needed for the VS code image.
77 |
78 | The very good [documentation](https://zero-to-jupyterhub.readthedocs.io/en/latest/index.html) on the jupyterhub k8s installation also contains valuable information on monitoring and operating.
79 |
80 | ## How does it work
81 |
82 | All components are already there - codehub just glues them together with very little glue-settings.
83 | The basis is a normal jupyterhub installation.
84 | Jupyterhub consists roughly of two components: the webfrontend (that your users will interact with) and a (reverse) proxy.
85 | Whenever users log in via the webfrontend, jupyterhub spawns a new pod which normally contains the jupyter notebook server.
86 | This is where codehub steps in: instead, a VS code instance is spawned.
87 | The address of the running VS code instance is registered with the
88 | proxy so that subsequent calls to the hub by this user will be redirected to the running VS Code directly.
89 | That's it! The changes to jupyterhub are really small - because both jupyterhub and VS Code are already very nice projects!
90 |
91 |
92 |
93 |
94 |
95 |
--------------------------------------------------------------------------------
/assets/animation.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nils-braun/codehub/baaf77d133d97a9bb34954fdb9619a3f71eeb0af/assets/animation.gif
--------------------------------------------------------------------------------
/values.yaml:
--------------------------------------------------------------------------------
1 | # Configuration file for the vscode-jupyterhub helm installation
2 | # See the README.md for information on how to apply it
3 |
4 | singleuser:
5 | # Use the code-server image
6 | image:
7 | name: "codercom/code-server"
8 | tag: "3.6.2"
9 |
10 | # Mount the persistant volume claim
11 | # directly inside the home folder of
12 | # the coder user
13 | storage:
14 | homeMountPath: "/home/coder"
15 |
16 | proxy:
17 | chp:
18 | # Make sure the code server does never get to know about
19 | # the user-specific prefixes and thinks "it runs by itself"
20 | extraCommandLineFlags:
21 | - "--no-include-prefix"
22 | # secret token
23 | secretToken: # TODO: Fill with the result of `openssl rand -hex 32`
24 |
25 | hub:
26 | # The code-server needs different arguments
27 | # than the jupyter notebook image
28 | extraConfig:
29 | code_spawner.py: |
30 | from kubespawner.spawner import KubeSpawner
31 | from jupyterhub.spawner import _quote_safe
32 |
33 | class VSCodeKubeSpawner(KubeSpawner):
34 | def get_args(self):
35 | """Custom args function for the coder"""
36 |
37 | # Turn off authentication (happens via jupyterhub)
38 | args = ["--auth", "none"]
39 | # Turn off telemetry
40 | args += ["--disable-telemetry"]
41 |
42 | # set port and ip if given
43 | ip = "0.0.0.0"
44 | if self.ip:
45 | ip = _quote_safe(self.ip)
46 |
47 | port = 8888
48 | if self.port:
49 | port = self.port
50 | elif self.server and self.server.port:
51 | self.log.warning(
52 | "Setting port from user.server is deprecated as of JupyterHub 0.7."
53 | )
54 | port = self.server.port
55 |
56 | args += ["--bind-addr", f"{ip}:{port}"]
57 |
58 | # set startup folder
59 | if self.notebook_dir:
60 | notebook_dir = self.format_string(self.notebook_dir)
61 | args += ["--user-data-dir", _quote_safe(notebook_dir)]
62 |
63 | if self.debug:
64 | args += ["-vvv"]
65 |
66 | args.extend(self.args)
67 | return args
68 |
69 | # Use the configured spawner
70 | c.JupyterHub.spawner_class = VSCodeKubeSpawner
71 |
72 | code_settings.py: |
73 | # The working dir is by default set to
74 | # /home/coder in the VSCode image
75 | c.VSCodeKubeSpawner.working_dir = "/home/coder"
76 |
77 | # By default, the cmd includes the call to "jupyterhub-singleserver"
78 | # However, the docker image already comes with the correct
79 | # VSCode command to call, so we just set it to an empty string here
80 | c.VSCodeKubeSpawner.cmd = ""
--------------------------------------------------------------------------------