diff --git a/ci/helm-chart/README.md b/ci/helm-chart/README.md deleted file mode 100644 index 2e576c3ec..000000000 --- a/ci/helm-chart/README.md +++ /dev/null @@ -1,162 +0,0 @@ -# code-server - -![Version: 1.0.0](https://img.shields.io/badge/Version-1.0.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 3.11.1](https://img.shields.io/badge/AppVersion-3.11.1-informational?style=flat-square) - -[code-server](https://github.com/cdr/code-server) code-server is VS Code running -on a remote server, accessible through the browser. - -This chart is community maintained by [@Matthew-Beckett](https://github.com/Matthew-Beckett) and [@alexgorbatchev](https://github.com/alexgorbatchev) - -## TL;DR; - -```console -$ git clone https://github.com/cdr/code-server -$ cd code-server -$ helm upgrade --install code-server ci/helm-chart -``` - -## Introduction - -This chart bootstraps a code-server deployment on a -[Kubernetes](http://kubernetes.io) cluster using the [Helm](https://helm.sh) -package manager. - -## Prerequisites - - - Kubernetes 1.6+ - -## Installing the Chart - -To install the chart with the release name `code-server`: - -```console -$ git clone https://github.com/cdr/code-server -$ cd code-server -$ helm upgrade --install code-server ci/helm-chart -``` - -The command deploys code-server on the Kubernetes cluster in the default -configuration. The [configuration](#configuration) section lists the parameters -that can be configured during installation. - -> **Tip**: List all releases using `helm list` - -## Uninstalling the Chart - -To uninstall/delete the `code-server` deployment: - -```console -$ helm delete code-server -``` - -The command removes all the Kubernetes components associated with the chart and -deletes the release. - -## Configuration - -The following table lists the configurable parameters of the code-server chart -and their default values. - -## Values - -| Key | Type | Default | Description | -|-----|------|---------|-------------| -| affinity | object | `{}` | | -| extraArgs | list | `[]` | | -| extraConfigmapMounts | list | `[]` | | -| extraContainers | string | `""` | | -| extraInitContainers | string | `""` | | -| extraSecretMounts | list | `[]` | | -| extraVars | list | `[]` | | -| extraVolumeMounts | list | `[]` | | -| fullnameOverride | string | `""` | | -| hostnameOverride | string | `""` | | -| image.pullPolicy | string | `"Always"` | | -| image.repository | string | `"codercom/code-server"` | | -| image.tag | string | `"3.11.1"` | | -| imagePullSecrets | list | `[]` | | -| ingress.enabled | bool | `false` | | -| nameOverride | string | `""` | | -| nodeSelector | object | `{}` | | -| persistence.accessMode | string | `"ReadWriteOnce"` | | -| persistence.annotations | object | `{}` | | -| persistence.enabled | bool | `true` | | -| persistence.size | string | `"1Gi"` | | -| podAnnotations | object | `{}` | | -| podSecurityContext | object | `{}` | | -| replicaCount | int | `1` | | -| resources | object | `{}` | | -| securityContext.enabled | bool | `true` | | -| securityContext.fsGroup | int | `1000` | | -| securityContext.runAsUser | int | `1000` | | -| service.port | int | `8443` | | -| service.type | string | `"ClusterIP"` | | -| serviceAccount.create | bool | `true` | | -| serviceAccount.name | string | `nil` | | -| tolerations | list | `[]` | | -| volumePermissions.enabled | bool | `true` | | -| volumePermissions.securityContext.runAsUser | int | `0` | | - -Specify each parameter using the `--set key=value[,key=value]` argument to `helm -install`. For example, - -```console -$ helm upgrade --install code-server \ - ci/helm-chart \ - --set persistence.enabled=false -``` - -The above command sets the the persistence storage to false. - -Alternatively, a YAML file that specifies the values for the above parameters -can be provided while installing the chart. For example, - -```console -$ helm upgrade --install code-server ci/helm-chart -f values.yaml -``` - -> **Tip**: You can use the default [values.yaml](values.yaml) - -# Extra Containers - -There are two parameters which allow to add more containers to pod. -Use `extraContainers` to add regular containers -and `extraInitContainers` to add init containers. You can read more -about init containers in [k8s documentation](https://kubernetes.io/docs/concepts/workloads/pods/init-containers/). - -Both parameters accept strings and use them as a templates - -Example of using `extraInitContainers`: - -``` yaml -extraInitContainers: | - - name: customization - image: {{ .Values.image.repository }}:{{ .Values.image.tag }} - imagePullPolicy: IfNotPresent - env: - - name: SERVICE_URL - value: https://open-vsx.org/vscode/gallery - - name: ITEM_URL - value: https://open-vsx.org/vscode/item - command: - - sh - - -c - - | - code-server --install-extension ms-python.python - code-server --install-extension golang.Go - volumeMounts: - - name: data - mountPath: /home/coder - -``` - -With this yaml in file `init.yaml`, you can execute - -```console -$ helm upgrade --install code-server \ - ci/helm-chart \ - --values init.yaml -``` - -to deploy code-server with python and golang extensions preinstalled -before main container have started. \ No newline at end of file diff --git a/docs/guide.md b/docs/guide.md index c60d985a2..80d01ddca 100644 --- a/docs/guide.md +++ b/docs/guide.md @@ -1,5 +1,396 @@ +# Setup Guide + + - [Expose code-server](#expose-code-server) + - [Port forwarding via SSH](#port-forwarding-via-ssh) + - [Using Let's Encrypt with Caddy](#using-lets-encrypt-with-caddy) + - [Using Let's Encrypt with NGINX](#using-lets-encrypt-with-nginx) + - [Using a self-signed certificate](#using-a-self-signed-certificate) + - [External authentication](#external-authentication) + - [HTTPS and self-signed certificates](#https-and-self-signed-certificates) + - [Accessing web services](#accessing-web-services) + - [Using a subdomain](#using-a-subdomain) + - [Using a subpath](#using-a-subpath) + - [Stripping `/proxy/` from the request path](#stripping-proxyport-from-the-request-path) + - [Proxying to create a React app](#proxying-to-create-a-react-app) + - [Proxying to a Vue app](#proxying-to-a-vue-app) +- [Setup Guide](#setup-guide) + - [Expose code-server](#expose-code-server-1) + - [Port forwarding via SSH](#port-forwarding-via-ssh-1) + - [Using Let's Encrypt with Caddy](#using-lets-encrypt-with-caddy-1) + - [Using Let's Encrypt with NGINX](#using-lets-encrypt-with-nginx-1) + - [Using a self-signed certificate](#using-a-self-signed-certificate-1) + - [External authentication](#external-authentication-1) + - [HTTPS and self-signed certificates](#https-and-self-signed-certificates-1) + - [Accessing web services](#accessing-web-services-1) + - [Using a subdomain](#using-a-subdomain-1) + - [Using a subpath](#using-a-subpath-1) + - [Stripping `/proxy/` from the request path](#stripping-proxyport-from-the-request-path-1) + - [Proxying to create a React app](#proxying-to-create-a-react-app-1) + - [Proxying to a Vue app](#proxying-to-a-vue-app-1) + - [SSH into code-server on VS Code](#ssh-into-code-server-on-vs-code) + - [Option 1: cloudflared tunnel](#option-1-cloudflared-tunnel) + - [Option 2: ngrok tunnel](#option-2-ngrok-tunnel) + + + +This article will walk you through exposing code-server securely once you've +completed the [installation process](install.md). + +## Expose code-server + +**Never** expose code-server directly to the internet without some form of +authentication and encryption, otherwise someone can take over your machine via +the terminal. + +By default, code-server uses password authentication. As such, you must copy the +password from code-server's config file to log in. To avoid exposing itself +unnecessarily, code-server listens on `localhost`; this practice is fine for +testing, but it doesn't work if you want to access code-server from a different +machine. + +> **Rate limits:** code-server rate limits password authentication attempts to +> two per minute plus an additional twelve per hour. + +There are several approaches to operating and exposing code-server securely: + +- Port forwarding via SSH +- Using Let's Encrypt with Caddy +- Using Let's Encrypt with NGINX +- Using a self-signed certificate + +### Port forwarding via SSH + +We highly recommend using [port forwarding via +SSH](https://help.ubuntu.com/community/SSH/OpenSSH/PortForwarding) to access +code-server. If you have an SSH server on your remote machine, this approach +doesn't required additional setup. + +The downside to SSH forwarding, however, is that you can't access code-server +when using machines without SSH clients (such as iPads). If this applies to you, +we recommend using another method, such as [Let's Encrypt](#let-encrypt) instead. + +> To work properly, your environment should have WebSockets enabled, which +> code-server uses to communicate between the browser and server. + +1. SSH into your instance and edit the code-server config file to disable + password authentication: + + ```console + # Replaces "auth: password" with "auth: none" in the code-server config. + sed -i.bak 's/auth: password/auth: none/' ~/.config/code-server/config.yaml + ``` + +2. Restart code-server: + + ```console + sudo systemctl restart code-server@$USER + ``` + +3. Forward local port `8080` to `127.0.0.1:8080` on the remote instance by running the following command on your local machine: + + ```console + # -N disables executing a remote shell + ssh -N -L 8080:127.0.0.1:8080 [user]@ + ``` + +4. At this point, you can access code-server by pointing your web browser to `http://127.0.0.1:8080`. + +5. If you'd like to make the port forwarding via SSH persistent, we recommend + using [mutagen](https://mutagen.io/documentation/introduction/installation) + to do so. Once you've installed mutagen, you can port forward as follows: + + ```console + # This is the same as the above SSH command, but it runs in the background + # continuously. Be sure to add `mutagen daemon start` to your ~/.bashrc to + # start the mutagen daemon when you open a shell. + + mutagen forward create --name=code-server tcp:127.0.0.1:8080 < instance-ip > :tcp:127.0.0.1:8080 + ``` + +6. Optional, but highly recommended: add the following to `~/.ssh/config` so + that you can detect bricked SSH connections: + + ```bash + Host * + ServerAliveInterval 5 + ExitOnForwardFailure yes + ``` + +> You can [forward your +> SSH](https://developer.github.com/v3/guides/using-ssh-agent-forwarding/) and +> [GPG agent](https://wiki.gnupg.org/AgentForwarding) to the instance to +> securely access GitHub and sign commits without having to copy your keys. + +### Using Let's Encrypt with Caddy + +Using [Let's Encrypt](https://letsencrypt.org) is an option if you want to +access code-server on an iPad or do not want to use SSH port forwarding. + +1. This option requires that the remote machine be exposed to the internet. Make sure that your instance allows HTTP/HTTP traffic. + +1. You'll need a domain name (if you don't have one, you can purchase one from + [Google Domains](https://domains.google.com) or the domain service of your + choice)). Once you have a domain name, add an A record to your domain that contains your + instance's IP address. + +1. Install [Caddy](https://caddyserver.com/docs/download#debian-ubuntu-raspbian): + +```console +sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https +curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/cfg/gpg/gpg.155B6D79CA56EA34.key' | sudo apt-key add - +curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/cfg/setup/config.deb.txt?distro=debian&version=any-version' | sudo tee -a /etc/apt/sources.list.d/caddy-stable.list +sudo apt update +sudo apt install caddy +``` + +1. Replace `/etc/caddy/Caddyfile` using `sudo` so that the file looks like this: + + ```text + mydomain.com + + reverse_proxy 127.0.0.1:8080 + ``` + + If you want to serve code-server from a sub-path, you can do so as follows: + + ```text + mydomain.com/code/* { + uri strip_prefix /code + reverse_proxy 127.0.0.1:8080 + } + ``` + + Remember to replace `mydomain.com` with your domain name! + +1. Reload Caddy: + + ```console + sudo systemctl reload caddy + ``` + +At this point, you should be able to access code-server via +`https://mydomain.com`. + +### Using Let's Encrypt with NGINX + +1. This option requires that the remote machine be exposed to the internet. Make sure that your instance allows HTTP/HTTP traffic. + +1. You'll need a domain name (if you don't have one, you can purchase one from + [Google Domains](https://domains.google.com) or the domain service of your + choice)). Once you have a domain name, add an A record to your domain that contains your + instance's IP address. + +1. Install NGINX: + + ```bash + sudo apt update + sudo apt install -y nginx certbot python3-certbot-nginx + ``` + +1. Update `/etc/nginx/sites-available/code-server` using sudo with the following + configuration: + + ```text + server { + listen 80; + listen [::]:80; + server_name mydomain.com; + + location / { + proxy_pass http://localhost:8080/; + proxy_set_header Host $host; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection upgrade; + proxy_set_header Accept-Encoding gzip; + } + } + ``` + + Be sure to replace `mydomain.com` with your domain name! + +1. Enable the config: + + ```console + sudo ln -s ../sites-available/code-server /etc/nginx/sites-enabled/code-server + sudo certbot --non-interactive --redirect --agree-tos --nginx -d mydomain.com -m me@example.com + ``` + + Be sure to replace `me@example.com` with your actual email. + +At this point, you should be able to access code-server via +`https://mydomain.com`. + +### Using a self-signed certificate + +> Self signed certificates do not work with iPad; see [./ipad.md](./ipad.md) for +> more information. + +Before proceeding, we recommend familiarizing yourself with the [risks of +self-signing a certificate for +SSL](https://security.stackexchange.com/questions/8110). + +We recommend self-signed certificates as a last resort, since self-signed +certificates do not work with iPads and may cause unexpected issues with +code-server. You should only proceed with this option if: + +- You do not want to buy a domain or you cannot expose the remote machine to + the internet +- You do not want to use port forwarding via SSH + +To use a self-signed certificate: + +1. This option requires that the remote machine be exposed to the internet. Make + sure that your instance allows HTTP/HTTP traffic. + +1. SSH into your instance and edit your code-server config file to use a + randomly generated self-signed certificate: + + ```console + # Replaces "cert: false" with "cert: true" in the code-server config. + sed -i.bak 's/cert: false/cert: true/' ~/.config/code-server/config.yaml + # Replaces "bind-addr: 127.0.0.1:8080" with "bind-addr: 0.0.0.0:443" in the code-server config. + sed -i.bak 's/bind-addr: 127.0.0.1:8080/bind-addr: 0.0.0.0:443/' ~/.config/code-server/config.yaml + # Allows code-server to listen on port 443. + sudo setcap cap_net_bind_service=+ep /usr/lib/code-server/lib/node + ``` + +1. Restart code-server: + + ```console + sudo systemctl restart code-server@$USER + ``` + +At this point, you should be able to access code-server via +`https://`. + +If you'd like to avoid the warnings displayed by code-server when using a +self-signed certificate, you can use [mkcert](https://mkcert.dev) to create a +self-signed certificate that's trusted by your operating system, then pass the +certificate to code-server via the `cert` and `cert-key` config fields. + +## External authentication + +If you want to use external authentication mechanism (e.g., Sign in with +Google), you can do this with a reverse proxy such as: + +- [Pomerium](https://www.pomerium.io/guides/code-server.html) +- [oauth2_proxy](https://github.com/pusher/oauth2_proxy) +- [Cloudflare Access](https://teams.cloudflare.com/access) + +## HTTPS and self-signed certificates + +For HTTPS, you can use a self-signed certificate by: + +- Passing in `--cert` +- Passing in an existing certificate by providing the path to `--cert` and the + path to the key with `--cert-key` + +The self signed certificate will be generated to +`~/.local/share/code-server/self-signed.crt`. + +If you pass a certificate to code-server, it will respond to HTTPS requests and +redirect all HTTP requests to HTTPS. + +> You can use [Let's Encrypt](https://letsencrypt.org/) to get a TLS certificate +> for free. + +Note: if you set `proxy_set_header Host $host;` in your reverse proxy config, it will change the address displayed in the green section of code-server in the bottom left to show the correct address. + +## Accessing web services + +If you're working on web services and want to access it locally, code-server +can proxy to any port using either a subdomain or a subpath, allowing you to +securely access these services using code-server's built-in authentication. + +### Using a subdomain + +You will need a DNS entry that points to your server for each port you want to +access. You can either set up a wildcard DNS entry for `*.` if your +domain name registrar supports it, or you can create one for every port you want +to access (`3000.`, `8080.`, etc). + +You should also set up TLS certificates for these subdomains, either using a +wildcard certificate for `*.` or individual certificates for each port. + +To set your domain, start code-server with the `--proxy-domain` flag: + +```console +code-server --proxy-domain +``` + +Now you can browse to `.`. Note that this uses the host header, so +ensure your reverse proxy (if you're using one) forwards that information. + +### Using a subpath + +Simply browse to `/proxy//`. + +### Stripping `/proxy/` from the request path + +You may notice that the code-server proxy strips `/proxy/` from the +request path. + +HTTP servers should use relative URLs to avoid the need to be coupled to the +absolute path at which they are served. This means you must [use trailing +slashes on all paths with +subpaths](https://blog.cdivilly.com/2019/02/28/uri-trailing-slashes). + +This reasoning is why the default behavior is to strip `/proxy/` from the +base path. If your application uses relative URLs and does not assume the +absolute path at which it is being served, it will just work no matter what port +you decide to serve it off or if you put it in behind code-server or any other +proxy. + +However, some prefer the cleaner aesthetic of no trailing slashes. Omitting the +trailing slashes couples you to the base path, since you cannot use relative +redirects correctly anymore. If you're okay with this tradeoff, use `/absproxy` +instead and the path will be passed as is (e.g., `/absproxy/3000/my-app-path`). + +### Proxying to create a React app + +You must use `/absproxy/` with `create-react-app` (see +[#2565](https://github.com/cdr/code-server/issues/2565) and +[#2222](https://github.com/cdr/code-server/issues/2222) for more information). +You will need to inform `create-react-app` of the path at which you are serving +via `$PUBLIC_URL` and webpack via `$WDS_SOCKET_PATH`: + +```sh +PUBLIC_URL=/absproxy/3000 \ + WDS_SOCKET_PATH=$PUBLIC_URL/sockjs-node \ + BROWSER=none yarn start +``` + +You should then be able to visit `https://my-code-server-address.io/absproxy/3000` to see your app exposed through +code-server! + +> We highly recommend using the subdomain approach instead to avoid this class of issue. + +### Proxying to a Vue app + +Similar to the situation with React apps, you have to make a few modifications to proxy a Vue app. + +1. add `vue.config.js` +2. update the values to match this (you can use any free port): + +```js +module.exports = { + devServer: { + port: 3454, + sockPath: "sockjs-node", + }, + publicPath: "/absproxy/3454", +} +``` + +3. access app at `/absproxy/3454` e.g. `http://localhost:8080/absproxy/3454` + +Read more about `publicPath` in the [Vue.js docs](https://cli.vuejs.org/config/#publicpath) + + + + # Setup Guide - [Expose code-server](#expose-code-server) diff --git a/docs/helm.md b/docs/helm.md new file mode 100644 index 000000000..a9045eb14 --- /dev/null +++ b/docs/helm.md @@ -0,0 +1,160 @@ +# code-server Helm Chart + +[![Version: 1.0.0](https://img.shields.io/badge/Version-1.0.0-informational?style=flat-square)](https://img.shields.io/badge/Version-1.0.0-informational?style=flat-square) [![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square)](https://img.shields.io/badge/Type-application-informational?style=flat-square) [![AppVersion: 3.11.1](https://img.shields.io/badge/AppVersion-3.11.1-informational?style=flat-square)](https://img.shields.io/badge/AppVersion-3.11.1-informational?style=flat-square) + +[code-server](https://github.com/cdr/code-server) code-server is VS Code running +on a remote server, accessible through the browser. + +This chart is community maintained by [@Matthew-Beckett](https://github.com/Matthew-Beckett) and [@alexgorbatchev](https://github.com/alexgorbatchev) + +## Quickstart + +```console +$ git clone https://github.com/cdr/code-server +$ cd code-server +$ helm upgrade --install code-server ci/helm-chart +``` + +## Introduction + +This chart bootstraps a code-server deployment on a +[Kubernetes](http://kubernetes.io) cluster using the [Helm](https://helm.sh) +package manager. + +## Prerequisites + +- Kubernetes 1.6+ + +## Installing the Chart + +To install the chart with the release name `code-server`: + +```console +$ git clone https://github.com/cdr/code-server +$ cd code-server +$ helm upgrade --install code-server ci/helm-chart +``` + +The command deploys code-server on the Kubernetes cluster in the default +configuration. The [configuration](#configuration) section lists the parameters +that can be configured during installation. + +> **Tip**: List all releases using `helm list` + +## Uninstalling the Chart + +To uninstall/delete the `code-server` deployment: + +```console +$ helm delete code-server +``` + +The command removes all the Kubernetes components associated with the chart and +deletes the release. + +## Configuration + +The following table lists the configurable parameters of the code-server chart +and their default values. + +## Values + +| Key | Type | Default | +| ------------------------------------------- | ------ | ------------------------ | +| affinity | object | `{}` | +| extraArgs | list | `[]` | +| extraConfigmapMounts | list | `[]` | +| extraContainers | string | `""` | +| extraInitContainers | string | `""` | +| extraSecretMounts | list | `[]` | +| extraVars | list | `[]` | +| extraVolumeMounts | list | `[]` | +| fullnameOverride | string | `""` | +| hostnameOverride | string | `""` | +| image.pullPolicy | string | `"Always"` | +| image.repository | string | `"codercom/code-server"` | +| image.tag | string | `"3.11.1"` | +| imagePullSecrets | list | `[]` | +| ingress.enabled | bool | `false` | +| nameOverride | string | `""` | +| nodeSelector | object | `{}` | +| persistence.accessMode | string | `"ReadWriteOnce"` | +| persistence.annotations | object | `{}` | +| persistence.enabled | bool | `true` | +| persistence.size | string | `"1Gi"` | +| podAnnotations | object | `{}` | +| podSecurityContext | object | `{}` | +| replicaCount | int | `1` | +| resources | object | `{}` | +| securityContext.enabled | bool | `true` | +| securityContext.fsGroup | int | `1000` | +| securityContext.runAsUser | int | `1000` | +| service.port | int | `8443` | +| service.type | string | `"ClusterIP"` | +| serviceAccount.create | bool | `true` | +| serviceAccount.name | string | `nil` | +| tolerations | list | `[]` | +| volumePermissions.enabled | bool | `true` | +| volumePermissions.securityContext.runAsUser | int | `0` | + +Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. For example, + +```console +$ helm upgrade --install code-server \ + ci/helm-chart \ + --set persistence.enabled=false +``` + +The above command sets the the persistence storage to false. + +Alternatively, a YAML file that specifies the values for the above parameters +can be provided while installing the chart. For example, + +```console +$ helm upgrade --install code-server ci/helm-chart -f values.yaml +``` + +> **Tip**: You can use the default [values.yaml](values.yaml) + +# Extra Containers + +There are two parameters which allow to add more containers to pod. +Use `extraContainers` to add regular containers +and `extraInitContainers` to add init containers. You can read more +about init containers in [k8s documentation](https://kubernetes.io/docs/concepts/workloads/pods/init-containers/). + +Both parameters accept strings and use them as a templates + +Example of using `extraInitContainers`: + +```yaml +extraInitContainers: | + - name: customization + image: {{ .Values.image.repository }}:{{ .Values.image.tag }} + imagePullPolicy: IfNotPresent + env: + - name: SERVICE_URL + value: https://open-vsx.org/vscode/gallery + - name: ITEM_URL + value: https://open-vsx.org/vscode/item + command: + - sh + - -c + - | + code-server --install-extension ms-python.python + code-server --install-extension golang.Go + volumeMounts: + - name: data + mountPath: /home/coder +``` + +With this yaml in file `init.yaml`, you can execute + +```console +$ helm upgrade --install code-server \ + ci/helm-chart \ + --values init.yaml +``` + +to deploy code-server with python and golang extensions preinstalled +before main container have started. diff --git a/docs/install.md b/docs/install.md index 29725227a..e325fd6c4 100644 --- a/docs/install.md +++ b/docs/install.md @@ -224,7 +224,7 @@ alternative](https://hub.docker.com/r/linuxserver/code-server). ## Helm -You can install code-server via [Helm](https://github.com/cdr/code-server/blob/main/ci/helm-chart/README.md). +You can install code-server using the [Helm package manager](https://coder.com/docs/code-server/latest/helm). ## Windows diff --git a/docs/manifest.json b/docs/manifest.json index 065bc7d37..f1cf8dbd4 100644 --- a/docs/manifest.json +++ b/docs/manifest.json @@ -23,6 +23,11 @@ "title": "npm", "description": "How to install code-server using npm or yarn", "path": "./npm.md" + }, + { + "title": "Helm", + "description": "How to install code-server using the Helm package manager", + "path": "./helm.md" } ] },