Make flags additive and clean up docs

This means that you have to turn on features now instead of disabling
them like auth and https.

In addition:
- Allow multiple options for auth (only password for now).
- Combine the install docs since they had many commonalities and
- generally simplified them (hopefully not too much).
- Move all example configs into docs/examples.
This commit is contained in:
Asher 2019-07-23 15:38:00 -05:00
parent 7b7f5b542e
commit fd55139c82
No known key found for this signature in database
GPG Key ID: D63C1EF81242354A
24 changed files with 329 additions and 571 deletions

View File

@ -1,15 +1,11 @@
# code-server # code-server [!["Latest Release"](https://img.shields.io/github/release/cdr/code-server.svg)](https://github.com/cdr/code-server/releases/latest) [![MIT license](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/cdr/code-server/blob/master/LICENSE) [![Discord](https://img.shields.io/discord/463752820026376202.svg?label=&logo=discord&logoColor=ffffff&color=7389D8&labelColor=6A7EC2)](https://discord.gg/zxSwN8Z)
[!["Open Issues"](https://img.shields.io/github/issues-raw/cdr/code-server.svg)](https://github.com/cdr/code-server/issues)
[!["Latest Release"](https://img.shields.io/github/release/cdr/code-server.svg)](https://github.com/cdr/code-server/releases/latest)
[![MIT license](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/cdr/code-server/blob/master/LICENSE)
[![Discord](https://img.shields.io/discord/463752820026376202.svg?label=&logo=discord&logoColor=ffffff&color=7389D8&labelColor=6A7EC2)](https://discord.gg/zxSwN8Z)
`code-server` is [VS Code](https://github.com/Microsoft/vscode) running on a `code-server` is [VS Code](https://github.com/Microsoft/vscode) running on a
remote server, accessible through the browser. remote server, accessible through the browser.
Try it out: Try it out:
```bash ```bash
docker run -it -p 127.0.0.1:8443:8443 -p 127.0.0.1:8444:8444 -v "$PWD:/home/coder/project" codercom/code-server --allow-http --no-auth docker run -it -p 127.0.0.1:8443:8443 -p 127.0.0.1:8444:8444 -v "$PWD:/home/coder/project" codercom/code-server
``` ```
- Code on your Chromebook, tablet, and laptop with a consistent dev environment. - Code on your Chromebook, tablet, and laptop with a consistent dev environment.
@ -29,29 +25,20 @@ Use [sshcode](https://github.com/codercom/sshcode) for a simple setup.
See docker oneliner mentioned above. Dockerfile is at See docker oneliner mentioned above. Dockerfile is at
[/Dockerfile](/Dockerfile). [/Dockerfile](/Dockerfile).
To debug Golang using the
[ms-vscode-go extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode.Go),
you need to add `--security-opt seccomp=unconfined` to your `docker run`
arguments when launching code-server with Docker. See
[#725](https://github.com/cdr/code-server/issues/725) for details.
### Binaries ### Binaries
1. [Download a binary](https://github.com/cdr/code-server/releases) (Linux and 1. [Download a binary](https://github.com/cdr/code-server/releases) (Linux and
OS X supported. Windows coming soon) OS X supported. Windows coming soon).
2. Start the binary with the project directory as the first argument 2. Unpack the downloaded file then run the binary.
3. In your browser navigate to `localhost:8443`.
``` - For self-hosting and other information see [doc/quickstart.md](doc/quickstart.md).
code-server <initial directory to open> - For hosting on cloud platforms see [doc/deploy.md](doc/deploy.md).
```
You will be prompted to enter the password shown in the CLI. `code-server`
should now be running at https://localhost:8443.
`code-server` uses a self-signed SSL certificate that may prompt your
browser to ask you some additional questions before you proceed. Please
[read here](doc/self-hosted/index.md) for more information.
For detailed instructions and troubleshooting, see the
[self-hosted quick start guide](doc/self-hosted/index.md).
Quickstart guides for [Google Cloud](doc/admin/install/google_cloud.md),
[AWS](doc/admin/install/aws.md), and
[DigitalOcean](doc/admin/install/digitalocean.md).
How to [secure your setup](/doc/security/ssl.md).
### Build ### Build
- If you also plan on developing, set the `OUT` environment variable: - If you also plan on developing, set the `OUT` environment variable:
@ -69,12 +56,9 @@ How to [secure your setup](/doc/security/ssl.md).
code into a single binary. code into a single binary.
## Known Issues ## Known Issues
- Uploading .vsix files doesn't work.
- Creating custom VS Code extensions and debugging them doesn't work. - Creating custom VS Code extensions and debugging them doesn't work.
- To debug Golang using - Extension profiling and tips are currently disabled.
[ms-vscode-go extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode.Go),
you need to add `--security-opt seccomp=unconfined` to your `docker run`
arguments when launching code-server with Docker. See
[#725](https://github.com/cdr/code-server/issues/725) for details.
## Future ## Future
- **Stay up to date!** Get notified about new releases of code-server. - **Stay up to date!** Get notified about new releases of code-server.
@ -86,17 +70,17 @@ How to [secure your setup](/doc/security/ssl.md).
## Extensions ## Extensions
At the moment we can't use the official VSCode Marketplace. We've created a At the moment we can't use the official VSCode Marketplace. We've created a
custom extension marketplace focused around open-sourced extensions. However, custom extension marketplace focused around open-sourced extensions. However,
if you have access to the `.vsix` file, you can manually install the extension. you can manually download the extension to your extensions directory. It's also
possible to host your own marketplace by setting the `SERVICE_URL` and
`ITEM_URL` environment variables.
## Telemetry ## Telemetry
Use the `--disable-telemetry` flag to completely disable telemetry. Use the `--disable-telemetry` flag to completely disable telemetry. We use the
data collected to improve code-server.
We use the data collected to improve code-server.
## Contributing ## Contributing
### Development ### Development
```fish ```shell
git clone https://github.com/microsoft/vscode git clone https://github.com/microsoft/vscode
cd vscode cd vscode
git checkout 1.36.1 git checkout 1.36.1
@ -107,7 +91,7 @@ yarn
yarn watch yarn watch
# Wait for the initial compilation to complete (it will say "Finished compilation"). # Wait for the initial compilation to complete (it will say "Finished compilation").
# Run the next command in another shell. # Run the next command in another shell.
yarn start --allow-http --no-auth yarn start
# Visit http://localhost:8443 # Visit http://localhost:8443
``` ```
@ -130,7 +114,7 @@ Our changes include:
- Rewrite assets used in the CSS (like icons) or as images to use the base URL. - Rewrite assets used in the CSS (like icons) or as images to use the base URL.
- Change the loader to use the base URL. - Change the loader to use the base URL.
- Change the web socket to use the base URL. - Change the web socket to use the base URL.
- Set the favicon (using a relative path). - Set the favicon using a relative path.
- Modify the file service to support writing from an asynchronous stream (for - Modify the file service to support writing from an asynchronous stream (for
uploading files). uploading files).
- Add a file prefix to ignore for temporary files created during upload. - Add a file prefix to ignore for temporary files created during upload.

View File

@ -1,66 +0,0 @@
# Deploy on AWS
This tutorial shows you how to deploy `code-server` on an EC2 AWS instance.
If you're just starting out, we recommend [installing code-server locally](../../self-hosted/index.md). It takes only a few minutes and lets you try out all of the features.
---
## Deploy to EC2
### Use the AWS wizard
- Click **Launch Instance** from your [EC2 dashboard](https://console.aws.amazon.com/ec2/v2/home).
- Select the Ubuntu Server 18.04 LTS (HVM), SSD Volume Type
- Select an appropriate instance size (we recommend t2.medium/large, depending on team size and number of repositories/languages enabled), then **Next: Configure Instance Details**
- Select **Next: ...** until you get to the **Configure Security Group** page, then add a **Custom TCP Rule** rule with port range set to `8443` and source set to "Anywhere"
> Rules with source of 0.0.0.0/0 allow all IP addresses to access your instance. We recommend setting [security group rules](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-network-security.html?icmpid=docs_ec2_console) to allow access from known IP addresses only.
- Click **Launch**
- You will be prompted to create a key pair
> A key pair consists of a public key that AWS stores, and a private key file that you store. Together, they allow you to connect to your instance securely. For Windows AMIs, the private key file is required to obtain the password used to log into your instance. For Linux AMIs, the private key file allows you to securely SSH into your instance.
- From the dropdown choose "create a new pair", give the key pair a name
- Click **Download Key Pair**
> This is necessary before you proceed. A `.pem` file will be downloaded. make sure you store is in a safe location because it can't be retrieved once we move on.
- Finally, click **Launch Instances**
---
### SSH Into EC2 Instance
- First head to your [EC2 dashboard](https://console.aws.amazon.com/ec2/v2/home) and choose instances from the left panel
- In the description of your EC2 instance copy the public DNS (iPv4) address using the copy to clipboard button
- Open a terminal on your computer and use the following command to SSH into your EC2 instance
```
ssh -i "path/to/your/keypair.pem" ubuntu@(paste the public DNS here)
```
>example: `ssh -i "/Users/John/Downloads/TestInstance.pem" ubuntu@ec2-3-45-678-910.compute-1.amazonaws.co`
- You should see a prompt for your EC2 instance like so<img src="../../assets/aws_ubuntu.png">
- At this point it is time to download the `code-server` binary. We will of course want the linux version.
- Find the latest Linux release from this URL:
```
https://github.com/cdr/code-server/releases/latest
```
- Replace {version} in the following command with the version found on the releases page and run it (or just copy the download URL from the releases page):
```
wget https://github.com/cdr/code-server/releases/download/{version}/code-server{version}-linux-x64.tar.gz
```
- Extract the downloaded tar.gz file with this command, for example:
```
tar -xvzf code-server{version}-linux-x64.tar.gz
```
- Navigate to extracted directory with this command:
```
cd code-server{version}-linux-x64
```
- If you run into any permission errors, make the binary executable by running:
```
chmod +x code-server
```
> To ensure the connection between you and your server is encrypted view our guide on [securing your setup](../../security/ssl.md)
- Finally, run
```
./code-server
```
- Open your browser and visit `https://$public_ip:8443/` (where `$public_ip` is your AWS instance's public IP address). You will be greeted with a page similar to the following screenshot. Code-server is using a self-signed SSL certificate for easy setup. In Chrome/Chromium, click **"Advanced"** then click **"proceed anyway"**. In Firefox, click **Advanced**, then **Add Exception**, then finally **Confirm Security Exception**.<img src ="../../assets/chrome_warning.png">
> For instructions on how to keep the server running after you end your SSH session please checkout [how to use systemd](https://www.linode.com/docs/quick-answers/linux/start-service-at-boot/) to start linux based services if they are killed
---
> NOTE: If you get stuck or need help, [file an issue](https://github.com/cdr/code-server/issues/new?&title=Improve+self-hosted+quickstart+guide), [tweet (@coderhq)](https://twitter.com/coderhq) or [email](mailto:support@coder.com?subject=Self-hosted%20quickstart%20guide).

View File

@ -1,48 +0,0 @@
# Deploy on DigitalOcean
This tutorial shows you how to deploy `code-server` to a single node running on DigitalOcean.
If you're just starting out, we recommend [installing code-server locally](../../self-hosted/index.md). It takes only a few minutes and lets you try out all of the features.
---
## Use the "Create Droplets" wizard
[Open your DigitalOcean dashboard](https://cloud.digitalocean.com/droplets/new) to create a new droplet
- **Choose an image -** Select the **Distributions** tab and then choose Ubuntu
- **Choose a size -** We recommend at least 4GB RAM and 2 CPU, more depending on team size and number of repositories/languages enabled.
- Launch your instance
- Open a terminal on your computer and SSH into your instance
> example: ssh root@203.0.113.0
- Once in the SSH session, visit code-server [releases page](https://github.com/cdr/code-server/releases/) and copy the link to the download for the latest linux release
- Find the latest Linux release from this URL:
```
https://github.com/cdr/code-server/releases/latest
```
- Replace {version} in the following command with the version found on the releases page and run it (or just copy the download URL from the releases page):
```
wget https://github.com/cdr/code-server/releases/download/{version}/code-server{version}-linux-x64.tar.gz
```
- Extract the downloaded tar.gz file with this command, for example:
```
tar -xvzf code-server{version}-linux-x64.tar.gz
```
- Navigate to extracted directory with this command:
```
cd code-server{version}-linux-x64
```
- If you run into any permission errors when attempting to run the binary:
```
chmod +x code-server
```
> To ensure the connection between you and your server is encrypted view our guide on [securing your setup](../../security/ssl.md)
- Finally start the code-server
```
./code-server
```
> For instructions on how to keep the server running after you end your SSH session please checkout [how to use systemd](https://www.linode.com/docs/quick-answers/linux/start-service-at-boot/) to start linux based services if they are killed
- Open your browser and visit `https://$public_ip:8443/` (where `$public_ip` is your Digital Ocean instance's public IP address). You will be greeted with a page similar to the following screenshot. Code-server is using a self-signed SSL certificate for easy setup. In Chrome/Chromium, click **"Advanced"** then click **"proceed anyway"**. In Firefox, click **Advanced**, then **Add Exception**, then finally **Confirm Security Exception**.<img src ="../../assets/chrome_warning.png">
---
> NOTE: If you get stuck or need help, [file an issue](https://github.com/cdr/code-server/issues/new?&title=Improve+self-hosted+quickstart+guide), [tweet (@coderhq)](https://twitter.com/coderhq) or [email](mailto:support@coder.com?subject=Self-hosted%20quickstart%20guide).

View File

@ -1,66 +0,0 @@
# Deploy on Google Cloud
This tutorial shows you how to deploy `code-server` to a single node running on Google Cloud.
If you're just starting out, we recommend [installing code-server locally](../../self-hosted/index.md). It takes only a few minutes and lets you try out all of the features.
---
## Deploy to Google Cloud VM
> Pre-requisite: Please [set up Google Cloud SDK](https://cloud.google.com/sdk/docs/) on your local machine
- [Open your Google Cloud console](https://console.cloud.google.com/compute/instances) to create a new VM instance and click **Create Instance**
- Choose an appropriate machine type (we recommend 2 vCPU and 7.5 GB RAM, more depending on team size and number of repositories/languages enabled)
- Choose Ubuntu 16.04 LTS as your boot disk
- Expand the "Management, security, disks, networking, sole tenancy" section, go to the "Networking" tab, then under network tags add "code-server"
- Create your VM, and **take note** of its public IP address.
- Visit "VPC network" in the console and go to "Firewall rules". Create a new firewall rule called "http-8443". Under "Target tags" add "code-server", and under "Protocols and ports" tick "Specified protocols and ports" and "tcp". Beside "tcp", add "8443", then create the rule.
- Copy the link to download the latest Linux binary from our [releases page](https://github.com/cdr/code-server/releases)
---
## Final Steps
- SSH into your Google Cloud VM
```
gcloud compute ssh --zone [region] [instance name]
```
- Find the latest Linux release from this URL:
```
https://github.com/cdr/code-server/releases/latest
```
- Replace {version} in the following command with the version found on the releases page and run it (or just copy the download URL from the releases page):
```
wget https://github.com/cdr/code-server/releases/download/{version}/code-server{version}-linux-x64.tar.gz
```
- Extract the downloaded tar.gz file with this command, for example:
```
tar -xvzf code-server{version}-linux-x64.tar.gz
```
- Navigate to extracted directory with this command:
```
cd code-server{version}-linux-x64
```
- Make the binary executable if you run into any errors regarding permission:
```
chmod +x code-server
```
> To ensure the connection between you and your server is encrypted view our guide on [securing your setup](../../security/ssl.md)
- Start the code-server
```
./code-server
```
- Open your browser and visit `https://$public_ip:8443/` (where `$public_ip` is your Compute Engine instance's public IP address). You will be greeted with a page similar to the following screenshot. Code-server is using a self-signed SSL certificate for easy setup. In Chrome/Chromium, click **"Advanced"** then click **"proceed anyway"**. In Firefox, click **Advanced**, then **Add Exception**, then finally **Confirm Security Exception**.<img src ="../../assets/chrome_warning.png">
> For instructions on how to keep the server running after you end your SSH session please checkout [how to use systemd](https://www.linode.com/docs/quick-answers/linux/start-service-at-boot/) to start linux based services if they are killed
---
> NOTE: If you get stuck or need help, [file an issue](https://github.com/cdr/code-server/issues/new?&title=Improve+self-hosted+quickstart+guide), [tweet (@coderhq)](https://twitter.com/coderhq) or [email](mailto:support@coder.com?subject=Self-hosted%20quickstart%20guide).

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 137 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

75
doc/cros-install.md Normal file
View File

@ -0,0 +1,75 @@
# Installing code-server in your ChromiumOS/ChromeOS/CloudReady machine
This guide will show you how to install code-server into your CrOS machine.
## Using Crostini
One of the easier ways to run code-server is via
[Crostini](https://www.aboutchromebooks.com/tag/project-crostini/), the Linux
apps support feature in CrOS. Make sure you have enough RAM, HDD space and your
CPU has VT-x/ AMD-V support. If your chromebook has this, then you are
qualified to use Crostini.
If you are running R69, you might want to enable this on
[Chrome Flags](chrome://flags/#enable-experimental-crostini-ui).
If you run R72, however, this is already enabled for you.
After checking your prerequisites, follow the steps in [the self-host install guide](index.md)
on installing code-server. Once done, make sure code-server works by running
it. After running it, simply go to `penguin.linux.test:8443` to access
code-server. Now you should be greeted with this screen. If you did,
congratulations, you have installed code-server in your Chromebook!
![code-server on Chromebook](assets/cros.png)
Alternatively, if you ran code-server in another container and you need the IP
for that specific container, simply go to Termina's shell via `crosh` and type
`vsh termina`.
```bash
Loading extra module: /usr/share/crosh/dev.d/50-crosh.sh
Welcome to crosh, the Chrome OS developer shell.
If you got here by mistake, don't panic! Just close this tab and carry on.
Type 'help' for a list of commands.
If you want to customize the look/behavior, you can use the options page.
Load it by using the Ctrl+Shift+P keyboard shortcut.
crosh> vsh termina
(termina) chronos@localhost ~ $
```
While in termina, run `lxc list`. It should output the list of running containers.
```bash
(termina) chronos@localhost ~ $ lxc list
+---------|---------|-----------------------|------|------------|-----------+
| NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS |
+---------|---------|-----------------------|------|------------|-----------+
| penguin | RUNNING | 100.115.92.199 (eth0) | | PERSISTENT | 0 |
+---------|---------|-----------------------|------|------------|-----------+
(termina) chronos@localhost ~ $
```
For this example, we show the default `penguin` container, which is exposed on
`eth0` at 100.115.92.199. Simply enter the IP of the container where the
code-server runs to Chrome.
## Using Crouton
[Crouton](https://github.com/dnschneid/crouton) is one of the old ways to get a
running full Linux via `chroot` on a Chromebook. To use crouton, enable
developer mode and go to `crosh`. This time, run `shell`, which should drop you
to `bash`.
Make sure you downloaded `crouton`, if so, go ahead and run it under
`~/Downloads`. After installing your chroot container via crouton, go ahead and
enter `enter-chroot` to enter your container.
Follow the instructions set in [the self-host install guide](index.md) to
install code-server. After that is done, run `code-server` and verify it works
by going to `localhost:8443`.
> At this point in writing, `localhost` seems to work in this method. However,
> the author is not sure if it applies still to newer Chromebooks.

73
doc/deploy.md Normal file
View File

@ -0,0 +1,73 @@
# Set up instance
## EC2 on AWS
- Click **Launch Instance** from your [EC2 dashboard](https://console.aws.amazon.com/ec2/v2/home).
- Select the Ubuntu Server 18.04 LTS (HVM), SSD Volume Type
- Select an appropriate instance size (we recommend t2.medium/large, depending
on team size and number of repositories/languages enabled), then
**Next: Configure Instance Details**.
- Select **Next: ...** until you get to the **Configure Security Group** page,
then add a **Custom TCP Rule** rule with port range set to `8443` and source
set to "Anywhere".
> Rules with source of 0.0.0.0/0 allow all IP addresses to access your
> instance. We recommend setting [security group rules](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-network-security.html?icmpid=docs_ec2_console)
> to allow access from known IP addresses only.
- Click **Launch**.
- You will be prompted to create a key pair.
- From the dropdown choose "create a new pair", give the key pair a name.
- Click **Download Key Pair** and store the file in a safe place.
- Click **Launch Instances**.
- Head to your [EC2 dashboard](https://console.aws.amazon.com/ec2/v2/home)
and choose instances from the left panel.
- In the description of your EC2 instance copy the public DNS (iPv4) address
using the copy to clipboard button.
- Open a terminal on your computer and SSH into your instance:
```
ssh -i ${path to key pair} ubuntu@${public address}
```
## DigitalOcean
[Open your DigitalOcean dashboard](https://cloud.digitalocean.com/droplets/new)
to create a new droplet
- **Choose an image -** Select the **Distributions** tab and then choose Ubuntu.
- **Choose a size -** We recommend at least 4GB RAM and 2 CPU, more depending
on team size and number of repositories/languages enabled.
- Launch your instance.
- Open a terminal on your computer and SSH into your instance:
```
ssh root@${instance ip}
```
## Google Cloud
> Pre-requisite: Set up the [Google Cloud SDK](https://cloud.google.com/sdk/docs/)
> on your local machine
- [Open your Google Cloud console](https://console.cloud.google.com/compute/instances)
to create a new VM instance and click **Create Instance**.
- Choose an appropriate machine type (we recommend 2 vCPU and 7.5 GB RAM, more
depending on team size and number of repositories/languages enabled).
- Choose Ubuntu 16.04 LTS as your boot disk.
- Expand the "Management, security, disks, networking, sole tenancy" section,
go to the "Networking" tab, then under network tags add "code-server".
- Create your VM, and **take note** of its public IP address.
- Visit "VPC network" in the console and go to "Firewall rules". Create a new
firewall rule called "http-8443". Under "Target tags" add "code-server", and
under "Protocols and ports" tick "Specified protocols and ports" and "tcp".
Beside "tcp", add "8443", then create the rule.
- Open a terminal on your computer and SSH into your Google Cloud VM:
```
gcloud compute ssh --zone ${region} ${instance name}
```
# Run code-server
- Download the latest code-server release from the
[releases page](https://github.com/cdr/code-server/releases/latest)
to the instance, extract the file, then run the code-server binary:
```
wget https://github.com/cdr/code-server/releases/download/{version}/code-server{version}-linux-x64.tar.gz
tar -xvzf code-server{version}-linux-x64.tar.gz
cd code-server{version}-linux-x64
./code-server
```
- Open your browser and visit http://$public_ip:8443/ where `$public_ip` is
your instance's public IP address.
- For long-term use, set up a systemd service to run code-server.

View File

@ -0,0 +1,15 @@
# Fail2Ban filter for code-server
[Definition]
failregex = ^INFO\s+Failed login attempt\s+{\"password\":\"(\\.|[^"])*\",\"remoteAddress\":\"<HOST>\"
# Use this instead for proxies (ensure the proxy is configured to send the
# X-Forwarded-For header).
# failregex = ^INFO\s+Failed login attempt\s+{\"password\":\"(\\.|[^"])*\",\"xForwardedFor\":\"<HOST>\"
ignoreregex =
datepattern = "timestamp":{EPOCH}}$
# Author: Dean Sheather

35
doc/fail2ban.md Normal file
View File

@ -0,0 +1,35 @@
# Protecting code-server from bruteforce attempts
code-server outputs all failed login attempts, along with the IP address,
provided password, user agent and timestamp by default.
When using a reverse proxy such as Nginx or Apache, the remote address may
appear to be `127.0.0.1` or a similar address so `X-Forwarded-For` should be
used instead. Ensure that you are setting this value in your reverse proxy:
Nginx:
```
location / {
...
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
...
}
```
Apache:
```
<VirtualEnv>
...
SetEnvIf X-Forwarded-For "^.*\..*\..*\..*" forwarded
...
</VirtualEnv>
```
It is extremely important that you ensure that your code-server instance is not
accessible from the internet (use localhost or block it in your firewall).
## Fail2Ban
Fail2Ban allows for automatically banning and logging repeated failed
authentication attempts for many applications through regex filters. A working
filter for code-server can be found in `./code-server.fail2ban.conf`. Once this
is installed and configured correctly, repeated failed login attempts should
automatically be banned from connecting to your server.

57
doc/quickstart.md Normal file
View File

@ -0,0 +1,57 @@
# Quickstart Guide
1. Visit the [releases page](https://github.com/cdr/code-server/releases) and
download the latest binary for your operating system.
2. Unpack the downloaded file then run the binary.
3. In your browser navigate to `localhost:8443`.
## Usage
Run `code-server --help` to view available options.
### Encrypting traffic with HTTPS
To encrypt the traffic between the browser and server use `code-server --cert`
followed by the path to your certificate. Additionally, you can use certificate
keys with `--cert-key` followed by the path to your key. If you pass `--cert`
without any path code-server will generate a self-signed certificate.
You can use [Let's Encrypt](https://letsencrypt.org/) to get an SSL certificate
for free.
### Nginx Reverse Proxy
The trailing slashes are important.
```
server {
listen 80;
listen [::]:80;
server_name code.example.com code.example.org;
location /some/path/ { # Or / if hosting at the root.
proxy_pass http://localhost:8443/;
proxy_set_header Host $host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection upgrade;
proxy_set_header Accept-Encoding gzip;
}
}
```
### Apache Reverse Proxy
```
<VirtualHost *:80>
ServerName code.example.com
RewriteEngine On
RewriteCond %{HTTP:Upgrade} =websocket [NC]
RewriteRule /(.*) ws://localhost:8443/$1 [P,L]
RewriteCond %{HTTP:Upgrade} !=websocket [NC]
RewriteRule /(.*) http://localhost:8443/$1 [P,L]
ProxyRequests off
RequestHeader set X-Forwarded-Proto https
RequestHeader set X-Forwarded-Port 443
ProxyPass / http://localhost:8443/ nocanon
ProxyPassReverse / http://localhost:8443/
</VirtualHost>
```

View File

@ -1,15 +0,0 @@
# Fail2Ban filter for code-server
#
#
[Definition]
failregex = ^INFO\s+Failed login attempt\s+{\"password\":\"(\\.|[^"])*\",\"remote_address\":\"<HOST>\"
ignoreregex =
datepattern = "timestamp":{EPOCH}}$
# Author: Dean Sheather

View File

@ -1,42 +0,0 @@
# Protecting code-server from bruteforce attempts
code-server outputs all failed login attempts, along with the IP address,
provided password, user agent and timestamp by default. When using a reverse
proxy such as Nginx or Apache, the remote address may appear to be `127.0.0.1`
or a similar address unless the `--trust-proxy` argument is provided to
code-server.
When used with the `--trust-proxy` argument, code-server will use the last IP in
`X-Forwarded-For` (if provided) instead of the remote socket address. Ensure
that you are setting this value in your reverse proxy:
Nginx:
```
location / {
...
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
...
}
```
Apache:
```
<VirtualEnv>
...
SetEnvIf X-Forwarded-For "^.*\..*\..*\..*" forwarded
...
</VirtualEnv>
```
It is extremely important that if you enable `--trust-proxy` you ensure your
code-server instance is not accessible from the internet (block it in your
firewall).
## Fail2Ban
Fail2Ban allows for automatically banning and logging repeated failed
authentication attempts for many applications through regex filters. A working
filter for code-server can be found in `./code-server.fail2ban.conf`. Once this
is installed and configured correctly, repeated failed login attempts should
automatically be banned from connecting to your server.

View File

@ -1,53 +0,0 @@
# Generate a self-signed certificate 🔒
code-server has the ability to secure your connection between client and server using SSL/TSL certificates. By default, the server will start with an unencrypted connection. We recommend Self-signed TLS/SSL certificates for personal use of code-server or within an organization.
This guide will show you how to create a self-signed certificate and start code-server using your certificate/key.
## TLS / HTTPS
You can specify any location that you want to save the certificate and key. In this example, we will navigate to the root directory, create a folder called `certs` and cd into it.
```shell
mkdir ~/certs && cd ~/certs
```
If you don't already have a TLS certificate and key, you can generate them with the command below. They will be placed in `~/certs`
```shell
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout ~/certs/MyKey.key -out ~/certs/MyCertificate.crt
```
You will be prompted to add some identifying information about your organization
```shell
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:US
State or Province Name (full name) [Some-State]:TX
Locality Name (eg, city) []:Austin
Organization Name (eg, company) [Coder Technologies]:Coder
Organizational Unit Name (eg, section) []:Docs
Common Name (e.g. server FQDN or YOUR name) []:hostname.example.com
Email Address []:admin@example.com
```
>If you already have a TLS certificate and key, you can simply reference them in the `--cert` and `--cert-key` flags when launching code-server
## Starting code-server with certificate and key
1. At the end of the path to your binary, add the following flags followed by the path to your certificate and key like so. Then press enter to run code-server.
```shell
./code-server --cert=~/certs/MyCertificate.crt --cert-key=~/certs/MyKey.key
```
2. After that you will be running a secure code-server.
> You will know your connection is secure if the lines `WARN No certificate specified. This could be insecure. WARN Documentation on securing your setup: https://coder.com/docs` no longer appear.
## Other options
For larger organizations you may wish to rely on a Certificate Authority as opposed to a self-signed certificate. For more information on generating free and open certificates for your site, please check out EFF's [certbot](https://certbot.eff.org/). Certbot is a cli to generate certificates using [LetsEncrypt](https://letsencrypt.org/).

View File

@ -1,53 +0,0 @@
# Installng code-server in your ChromiumOS/ChromeOS/CloudReady machine
This guide will show you how to install code-server into your CrOS machine.
## Using Crostini
One of the easier ways to run code-server is via [Crostini](https://www.aboutchromebooks.com/tag/project-crostini/), the Linux apps support feature in CrOS. Make sure you have enough RAM, HDD space and your CPU has VT-x/ AMD-V support. If your chromebook has this, then you are qualified to use Crostini.
If you are running R69, you might want to enable this on [Chrome Flags](chrome://flags/#enable-experimental-crostini-ui). If you run R72, however, this is already enabled for you.
After checking your prerequisites, follow the steps in [the self-host install guide](index.md) on installing code-server. Once done, make sure code-server works by running it. After running it, simply go to `penguin.linux.test:8443` to access code-server. Now you should be greeted with this screen. If you did, congratulations, you have installed code-server in your Chromebook!
![code-server on Chromebook](../assets/cros.png)
Alternatively, if you ran code-server in another container and you need the IP for that specific container, simply go to Termina's shell via `crosh` and type `vsh termina`.
```bash
Loading extra module: /usr/share/crosh/dev.d/50-crosh.sh
Welcome to crosh, the Chrome OS developer shell.
If you got here by mistake, don't panic! Just close this tab and carry on.
Type 'help' for a list of commands.
If you want to customize the look/behavior, you can use the options page.
Load it by using the Ctrl+Shift+P keyboard shortcut.
crosh> vsh termina
(termina) chronos@localhost ~ $
```
While in termina, run `lxc list`. It should output the list of running containers.
```bash
(termina) chronos@localhost ~ $ lxc list
+---------+---------+-----------------------+------+------------+-----------+
| NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS |
+---------+---------+-----------------------+------+------------+-----------+
| penguin | RUNNING | 100.115.92.199 (eth0) | | PERSISTENT | 0 |
+---------+---------+-----------------------+------+------------+-----------+
(termina) chronos@localhost ~ $
```
For this example, we show the default `penguin` container, which is exposed on `eth0` at 100.115.92.199. Simply enter the IP of the container where the code-server runs to Chrome.
## Using Crouton
[Crouton](https://github.com/dnschneid/crouton) is one of the old ways to get a running full Linux via `chroot` on a Chromebook. To use crouton, enable developer mode and go to `crosh`. This time, run `shell`, which should drop you to `bash`.
Make sure you downloaded `crouton`, if so, go ahead and run it under `~/Downloads`. After installing your chroot container via crouton, go ahead and enter `enter-chroot` to enter your container.
Follow the instructions set in [the self-host install guide](index.md) to install code-server. After that is done, run `code-server` and verify it works by going to `localhost:8443`.
> At this point in writing, `localhost` seems to work in this method. However, the author is not sure if it applies still to newer Chromebooks.

View File

@ -1,144 +0,0 @@
# Getting Started
[code-server](https://coder.com) is used by developers at Azure, Google,
Reddit, and more to give them access to VS Code in the browser.
## Quickstart Guide
> NOTE: If you get stuck or need help, [file an issue](https://github.com/cdr/code-server/issues/new?&title=Improve+self-hosted+quickstart+guide),
> [tweet (@coderhq)](https://twitter.com/coderhq) or
> [email](mailto:support@coder.com?subject=Self-hosted%20quickstart%20guide).
This document pertains to Coder-specific implementations of VS Code. For
documentation on how to use VS Code itself, please refer to the official
[documentation for VS Code](https://code.visualstudio.com/docs)
It takes just a few minutes to get your own self-hosted server running. If
you've got a machine running macOS, Windows, or Linux, you're ready to start
the binary which listens on ports `8443` and `8444` by default.
<!--
DO NOT CHANGE THIS TO A CODEBLOCK.
We want line breaks for readability, but backslashes to escape them do not work cross-platform.
This uses line breaks that are rendered but not copy-pasted to the clipboard.
-->
1. Visit [the releases](https://github.com/cdr/code-server/releases) page and
download the latest cli for your operating system.
2. Double click the executable to run in the current directory.
3. Copy the password that appears in the CLI. <img src="../assets/cli.png">
4. In your browser navigate to `localhost:8443`.
5. Paste the password from the cli into the login window. <img src="../assets/server-password-modal.png">
> NOTE: Be careful with your password as sharing it will grant those users
> access to your server's file system
### Things To Know
- When you visit the IP for your code-server instance, you will be greeted with
a page similar to the following screenshot. Code-server is using a
self-signed SSL certificate for easy setup. In Chrome/Chromium, click
**"Advanced"** then click **"proceed anyway"**. In Firefox, click
**Advanced**, then **Add Exception**, then finally **Confirm Security
Exception**. <img src ="../assets/chrome_warning.png">
## Usage
```
code-server --help
```
code-server can be ran with a number of arguments to customize your working
directory, host, port, and SSL certificate.
### Data Directory
Use `code-server --user-data-dir path/to/directory` to specify the root folder
that VS Code will start in.
### Host
By default, code-server will use `127.0.0.1` for insecure connections and
`0.0.0.0` for secure connections. This can be changed by using
`code-server --host `.
> Example: `code-server --host 127.0.0.1`
### Open
You can have the server automatically open the VS Code in your browser on
startup by using the `code-server -o` or `code-server --open` flags
### Port
By default, code-server will use `8443` as its port. This can be changed by
using `code-server -p` or `code-server --port=` followed by the port you want
to use.
> Example: `code-server -p 9000`
### Cert and Cert Key
To encrypt the traffic between the browser and server use `code-server --cert`
followed by the path to your `.cer` file. Additionally, you can use certificate
keys with `code-server --cert-key` followed by the path to your `.key` file.
Example:
```
code-server --cert /path/to/certificate/fullchain.cer --cert-key /path/to/certificate/fullchain.key
```
Example for Let's Encrypt:
```
code-server --cert /etc/letsencrypt/live/example.com/fullchain.pem --cert-key /etc/letsencrypt/live/example.com/privkey.key
```
To ensure the connection between you and your server is encrypted view our
guide on [securing your setup](../security/ssl.md).
### Nginx Reverse Proxy
Below is a virtual host example that works with code-server. Please also pass
`--allow-http` and `--trust-proxy` to code-server to allow the proxy to
connect. You can also use Let's Encrypt to get a SSL certificates for free.
```
server {
listen 80;
listen [::]:80;
server_name code.example.com code.example.org;
location / {
proxy_pass http://localhost:8443/;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection upgrade;
proxy_set_header Accept-Encoding gzip;
}
}
```
### Apache Reverse Proxy
Example of an HTTPS virtualhost configuration for Apache as a reverse proxy.
Please also pass `--allow-http` and `--trust-proxy` to code-server to allow the
proxy to connect. You can also use Let's Encrypt to get a SSL certificates for
free.
```
<VirtualHost *:80>
ServerName code.example.com
RewriteEngine On
RewriteCond %{HTTP:Upgrade} =websocket [NC]
RewriteRule /(.*) ws://localhost:8443/$1 [P,L]
RewriteCond %{HTTP:Upgrade} !=websocket [NC]
RewriteRule /(.*) http://localhost:8443/$1 [P,L]
ProxyRequests off
RequestHeader set X-Forwarded-Proto https
RequestHeader set X-Forwarded-Port 443
ProxyPass / http://localhost:8443/ nocanon
ProxyPassReverse / http://localhost:8443/
</VirtualHost>
```
*Important:* For more details about Apache reverse proxy configuration checkout
the [documentation](https://httpd.apache.org/docs/current/mod/mod_proxy.html) -
especially the [Securing your Server](https://httpd.apache.org/docs/current/mod/mod_proxy.html#access)
section.
### Help
Use `code-server --help` to view the usage for the CLI.

View File

@ -1,5 +1,4 @@
import * as os from "os"; import * as os from "os";
import * as path from "path";
import { validatePaths } from "vs/code/node/paths"; import { validatePaths } from "vs/code/node/paths";
import { parseMainProcessArgv } from "vs/platform/environment/node/argvHelper"; import { parseMainProcessArgv } from "vs/platform/environment/node/argvHelper";
@ -8,13 +7,12 @@ import { buildHelpMessage, buildVersionMessage, options } from "vs/platform/envi
import pkg from "vs/platform/product/node/package"; import pkg from "vs/platform/product/node/package";
import product from "vs/platform/product/node/product"; import product from "vs/platform/product/node/product";
import { MainServer, WebviewServer } from "vs/server/src/server"; import { AuthType, MainServer, WebviewServer } from "vs/server/src/server";
import "vs/server/src/tar"; import "vs/server/src/tar";
import { generateCertificate, generatePassword, open, unpackExecutables } from "vs/server/src/util"; import { buildAllowedMessage, generateCertificate, generatePassword, open, unpackExecutables } from "vs/server/src/util";
interface Args extends ParsedArgs { interface Args extends ParsedArgs {
"allow-http"?: boolean; auth?: AuthType;
auth?: boolean;
"base-path"?: string; "base-path"?: string;
cert?: string; cert?: string;
"cert-key"?: string; "cert-key"?: string;
@ -54,14 +52,13 @@ while (i--) {
} }
} }
options.push({ id: "allow-http", type: "boolean", cat: "o", description: "Allow http connections." });
options.push({ id: "base-path", type: "string", cat: "o", description: "Base path of the URL at which code-server is hosted (used for login redirects)." }); options.push({ id: "base-path", type: "string", cat: "o", description: "Base path of the URL at which code-server is hosted (used for login redirects)." });
options.push({ id: "cert", type: "string", cat: "o", description: "Path to certificate." }); options.push({ id: "cert", type: "string", cat: "o", description: "Path to certificate. If the path is omitted, both this and --cert-key will be generated." });
options.push({ id: "cert-key", type: "string", cat: "o", description: "Path to certificate key." }); options.push({ id: "cert-key", type: "string", cat: "o", description: "Path to the certificate's key if one was provided." });
options.push({ id: "extra-builtin-extensions-dir", type: "string", cat: "o", description: "Path to extra builtin extension directory." }); options.push({ id: "extra-builtin-extensions-dir", type: "string", cat: "o", description: "Path to an extra builtin extension directory." });
options.push({ id: "extra-extensions-dir", type: "string", cat: "o", description: "Path to extra user extension directory." }); options.push({ id: "extra-extensions-dir", type: "string", cat: "o", description: "Path to an extra user extension directory." });
options.push({ id: "host", type: "string", cat: "o", description: "Host for the main and webview servers." }); options.push({ id: "host", type: "string", cat: "o", description: "Host for the main and webview servers." });
options.push({ id: "no-auth", type: "boolean", cat: "o", description: "Disable password authentication." }); options.push({ id: "auth", type: "string", cat: "o", description: `The type of authentication to use. ${buildAllowedMessage(AuthType)}.` });
options.push({ id: "open", type: "boolean", cat: "o", description: "Open in the browser on startup." }); options.push({ id: "open", type: "boolean", cat: "o", description: "Open in the browser on startup." });
options.push({ id: "port", type: "string", cat: "o", description: "Port for the main server." }); options.push({ id: "port", type: "string", cat: "o", description: "Port for the main server." });
options.push({ id: "socket", type: "string", cat: "o", description: "Listen on a socket instead of host:port." }); options.push({ id: "socket", type: "string", cat: "o", description: "Listen on a socket instead of host:port." });
@ -118,8 +115,7 @@ const main = async (): Promise<void> => {
const extra = args["_"] || []; const extra = args["_"] || [];
const options = { const options = {
allowHttp: args["allow-http"], auth: args.auth,
auth: typeof args.auth !== "undefined" ? args.auth : true,
basePath: args["base-path"], basePath: args["base-path"],
cert: args.cert, cert: args.cert,
certKey: args["cert-key"], certKey: args["cert-key"],
@ -128,22 +124,20 @@ const main = async (): Promise<void> => {
password: process.env.PASSWORD, password: process.env.PASSWORD,
}; };
if (!options.host) { if (options.auth && Object.keys(AuthType).filter((k) => AuthType[k] === options.auth).length === 0) {
options.host = !options.auth || options.allowHttp ? "localhost" : "0.0.0.0"; throw new Error(`'${options.auth}' is not a valid authentication type.`);
} else if (options.auth && !options.password) {
options.password = await generatePassword();
} }
let usingGeneratedCert = false; if (!options.certKey && typeof options.certKey !== "undefined") {
if (!options.allowHttp && (!options.cert || !options.certKey)) { throw new Error(`--cert-key cannot be blank`);
} else if (options.certKey && !options.cert) {
throw new Error(`--cert-key was provided but --cert was not`);
} if (!options.cert && typeof options.cert !== "undefined") {
const { cert, certKey } = await generateCertificate(); const { cert, certKey } = await generateCertificate();
options.cert = cert; options.cert = cert;
options.certKey = certKey; options.certKey = certKey;
usingGeneratedCert = true;
}
let usingGeneratedPassword = false;
if (options.auth && !options.password) {
options.password = await generatePassword();
usingGeneratedPassword = true;
} }
const webviewPort = args["webview-port"]; const webviewPort = args["webview-port"];
@ -167,7 +161,7 @@ const main = async (): Promise<void> => {
console.log(`Main server listening on ${serverAddress}`); console.log(`Main server listening on ${serverAddress}`);
console.log(`Webview server listening on ${webviewAddress}`); console.log(`Webview server listening on ${webviewAddress}`);
if (usingGeneratedPassword) { if (options.auth && !process.env.PASSWORD) {
console.log(" - Password is", options.password); console.log(" - Password is", options.password);
console.log(" - To use your own password, set the PASSWORD environment variable"); console.log(" - To use your own password, set the PASSWORD environment variable");
} else if (options.auth) { } else if (options.auth) {
@ -176,17 +170,17 @@ const main = async (): Promise<void> => {
console.log(" - No authentication"); console.log(" - No authentication");
} }
if (!options.allowHttp && options.cert && options.certKey) { if (server.protocol === "https") {
console.log( console.log(
usingGeneratedCert args.cert
? ` - Using generated certificate and key in ${path.dirname(options.cert)} for HTTPS` ? ` - Using provided certificate${args["cert-key"] ? " and key" : ""} for HTTPS`
: " - Using provided certificate and key for HTTPS", : ` - Using generated certificate and key for HTTPS`,
); );
} else { } else {
console.log(" - Not serving HTTPS"); console.log(" - Not serving HTTPS");
} }
if (!args.socket && args.open) { if (!server.options.socket && args.open) {
// The web socket doesn't seem to work if using 0.0.0.0. // The web socket doesn't seem to work if using 0.0.0.0.
const openAddress = `http://localhost:${server.options.port}`; const openAddress = `http://localhost:${server.options.port}`;
await open(openAddress).catch(console.error); await open(openAddress).catch(console.error);

View File

@ -95,9 +95,12 @@ export class HttpError extends Error {
} }
} }
export enum AuthType {
Password = "password",
}
export interface ServerOptions { export interface ServerOptions {
readonly allowHttp?: boolean; readonly auth?: AuthType;
readonly auth?: boolean;
readonly basePath?: string; readonly basePath?: string;
readonly cert?: string; readonly cert?: string;
readonly certKey?: string; readonly certKey?: string;
@ -112,19 +115,21 @@ export abstract class Server {
protected readonly server: http.Server | https.Server; protected readonly server: http.Server | https.Server;
protected rootPath = path.resolve(__dirname, "../../../.."); protected rootPath = path.resolve(__dirname, "../../../..");
private listenPromise: Promise<string> | undefined; private listenPromise: Promise<string> | undefined;
private readonly protocol: string; public readonly protocol: string;
private readonly basePath: string = ""; public readonly options: ServerOptions;
public constructor(public readonly options: ServerOptions) { public constructor(options: ServerOptions) {
this.protocol = this.options.allowHttp ? "http" : "https"; this.options = {
if (this.options.basePath) { host: options.auth && options.cert ? "0.0.0.0" : "localhost",
this.basePath = this.options.basePath.replace(/\/+$/, ""); basePath: options.basePath ? options.basePath.replace(/\/+$/, "") : "",
} ...options,
if (this.options.cert && this.options.certKey) { };
this.protocol = this.options.cert ? "https" : "http";
if (this.protocol === "https") {
const httpolyglot = require.__$__nodeRequire(path.resolve(__dirname, "../node_modules/httpolyglot/lib/index")) as typeof import("httpolyglot"); const httpolyglot = require.__$__nodeRequire(path.resolve(__dirname, "../node_modules/httpolyglot/lib/index")) as typeof import("httpolyglot");
this.server = httpolyglot.createServer({ this.server = httpolyglot.createServer({
cert: fs.readFileSync(this.options.cert), cert: this.options.cert && fs.readFileSync(this.options.cert),
key: fs.readFileSync(this.options.certKey), key: this.options.certKey && fs.readFileSync(this.options.certKey),
}, this.onRequest); }, this.onRequest);
} else { } else {
this.server = http.createServer(this.onRequest); this.server = http.createServer(this.onRequest);
@ -180,7 +185,7 @@ export abstract class Server {
"Cache-Control": "max-age=86400", // TODO: ETag? "Cache-Control": "max-age=86400", // TODO: ETag?
"Content-Type": getMediaMime(payload.filePath), "Content-Type": getMediaMime(payload.filePath),
...(payload.redirect ? { ...(payload.redirect ? {
Location: `${this.protocol}://${request.headers.host}${this.basePath}${payload.redirect}`, Location: `${this.protocol}://${request.headers.host}${this.options.basePath}${payload.redirect}`,
} : {}), } : {}),
...payload.headers, ...payload.headers,
}); });
@ -196,7 +201,7 @@ export abstract class Server {
private async preHandleRequest(request: http.IncomingMessage): Promise<Response> { private async preHandleRequest(request: http.IncomingMessage): Promise<Response> {
const secure = (request.connection as tls.TLSSocket).encrypted; const secure = (request.connection as tls.TLSSocket).encrypted;
if (!this.options.allowHttp && !secure) { if (this.options.cert && !secure) {
return { redirect: request.url }; return { redirect: request.url };
} }

View File

@ -12,6 +12,8 @@ import { extname } from "vs/base/common/path";
import { URITransformer, IRawURITransformer } from "vs/base/common/uriIpc"; import { URITransformer, IRawURITransformer } from "vs/base/common/uriIpc";
import { mkdirp } from "vs/base/node/pfs"; import { mkdirp } from "vs/base/node/pfs";
import { AuthType } from "vs/server/src/server";
export const tmpdir = path.join(os.tmpdir(), "code-server"); export const tmpdir = path.join(os.tmpdir(), "code-server");
export const generateCertificate = async (): Promise<{ cert: string, certKey: string }> => { export const generateCertificate = async (): Promise<{ cert: string, certKey: string }> => {
@ -108,3 +110,8 @@ export const unpackExecutables = async (): Promise<void> => {
await util.promisify(fs.chmod)(destination, "755"); await util.promisify(fs.chmod)(destination, "755");
} }
}; };
export const buildAllowedMessage = (t: typeof AuthType): string => {
const values = <string[]>Object.keys(t).map((k) => t[k]);
return `Allowed value${values.length === 1 ? " is" : "s are"} ${values.map((t) => `'${t}'`).join(",")}`;
};