mirror of
https://github.com/danog/code-server.git
synced 2024-11-26 20:34:56 +01:00
ba6b8da76b
* docs(guide): add proxying to Angular app * fixup: formatting * fixup: formatting Co-authored-by: repo-ranger[bot] <39074581+repo-ranger[bot]@users.noreply.github.com>
484 lines
18 KiB
Markdown
484 lines
18 KiB
Markdown
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
|
|
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
|
|
# 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)
|
|
- [TLS 1.3 and Safari](#tls-13-and-safari)
|
|
- [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/<port>` 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)
|
|
- [Proxying to an Angular app](#proxying-to-an-angular-app)
|
|
- [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)
|
|
|
|
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
|
|
|
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 require any additional setup at all.
|
|
|
|
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]@<instance-ip>
|
|
```
|
|
|
|
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/HTTPS 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/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
|
|
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /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/HTTPS 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/HTTPS 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://<your-instance-ip>`.
|
|
|
|
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.
|
|
|
|
### TLS 1.3 and Safari
|
|
|
|
If you will be using Safari and your configuration does not allow anything less
|
|
than TLS 1.3 you will need to add support for TLS 1.2 since Safari does not
|
|
support TLS 1.3 for web sockets at the time of writing. If this is the case you
|
|
should see OSSStatus: 9836 in the browser console.
|
|
|
|
## 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 them 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 `*.<domain>` if your
|
|
domain name registrar supports it, or you can create one for every port you want
|
|
to access (`3000.<domain>`, `8080.<domain>`, etc).
|
|
|
|
You should also set up TLS certificates for these subdomains, either using a
|
|
wildcard certificate for `*.<domain>` or individual certificates for each port.
|
|
|
|
To set your domain, start code-server with the `--proxy-domain` flag:
|
|
|
|
```console
|
|
code-server --proxy-domain <domain>
|
|
```
|
|
|
|
Now you can browse to `<port>.<domain>`. 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/<port>/`.
|
|
|
|
### Stripping `/proxy/<port>` from the request path
|
|
|
|
You may notice that the code-server proxy strips `/proxy/<port>` 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/<port>` 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/<port>` with `create-react-app` (see
|
|
[#2565](https://github.com/coder/code-server/issues/2565) and
|
|
[#2222](https://github.com/coder/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 `<code-server-root>/absproxy/3454` e.g. `http://localhost:8080/absproxy/3454`
|
|
|
|
Read more about `publicPath` in the [Vue.js docs](https://cli.vuejs.org/config/#publicpath)
|
|
|
|
### Proxying to an Angular app
|
|
|
|
In order to use code-server's built-in proxy with Angular, you need to make the following changes in your app:
|
|
|
|
1. use `<base href="./.">` in `src/index.html`
|
|
2. add `--serve-path /absproxy/4200` to `ng serve` in your `package.json`
|
|
|
|
For additional context, see [this GitHub Discussion](https://github.com/coder/code-server/discussions/5439#discussioncomment-3371983).
|
|
|
|
## SSH into code-server on VS Code
|
|
|
|
[![SSH](https://img.shields.io/badge/SSH-363636?style=for-the-badge&logo=GNU+Bash&logoColor=ffffff)](https://ohmyz.sh/) [![Terminal](https://img.shields.io/badge/Terminal-2E2E2E?style=for-the-badge&logo=Windows+Terminal&logoColor=ffffff)](https://img.shields.io/badge/Terminal-2E2E2E?style=for-the-badge&logo=Windows+Terminal&logoColor=ffffff) [![Visual Studio Code](https://img.shields.io/badge/Visual_Studio_Code-007ACC?style=for-the-badge&logo=Visual+Studio+Code&logoColor=ffffff)](vscode:extension/ms-vscode-remote.remote-ssh)
|
|
|
|
Follow these steps where code-server is running:
|
|
|
|
1. Install `openssh-server`, `wget`, and `unzip`.
|
|
|
|
```bash
|
|
# example for Debian and Ubuntu operating systems
|
|
sudo apt update
|
|
sudo apt install wget unzip openssh-server
|
|
```
|
|
|
|
2. Start the SSH server and set the password for your user, if you haven't already. If you use [deploy-code-server](https://github.com/coder/deploy-code-server),
|
|
|
|
```bash
|
|
sudo service ssh start
|
|
sudo passwd {user} # replace user with your code-server user
|
|
```
|
|
|
|
### Option 1: cloudflared tunnel
|
|
|
|
[![Cloudflared](https://img.shields.io/badge/Cloudflared-E4863B?style=for-the-badge&logo=cloudflare&logoColor=ffffff)](https://github.com/cloudflare/cloudflared)
|
|
|
|
1. Install [cloudflared](https://github.com/cloudflare/cloudflared#installing-cloudflared) on your local computer
|
|
2. Then go to `~/.ssh/config` and add the following:
|
|
|
|
```shell
|
|
Host *.trycloudflare.com
|
|
HostName %h
|
|
User root
|
|
Port 22
|
|
ProxyCommand "cloudflared location" access ssh --hostname %h
|
|
```
|
|
|
|
3. Run `cloudflared tunnel --url ssh://localhost:22` on the remote server
|
|
|
|
4. Finally on VS Code or any IDE that supports SSH, run `ssh coder@https://your-link.trycloudflare.com` or `ssh coder@your-link.trycloudflare.com`
|
|
|
|
### Option 2: ngrok tunnel
|
|
|
|
[![Ngrok](https://img.shields.io/badge/Ngrok-1F1E37?style=for-the-badge&logo=ngrok&logoColor=ffffff)](https://ngrok.com/)
|
|
|
|
1. Make a new account for ngrok [here](https://dashboard.ngrok.com/login)
|
|
|
|
2. Now, get the ngrok binary with `wget` and unzip it with `unzip`:
|
|
|
|
```bash
|
|
wget "https://bin.equinox.io/c/4VmDzA7iaHb/ngrok-stable-linux-amd64.zip"
|
|
unzip "ngrok-stable-linux-amd64.zip"
|
|
```
|
|
|
|
5. Then, go to [dashboard.ngrok.com](https://dashboard.ngrok.com) and go to the `Your Authtoken` section.
|
|
6. Copy the Authtoken shown there.
|
|
7. Now, go to the folder where you unzipped ngrok and store the Authtoken from the ngrok Dashboard.
|
|
|
|
```bash
|
|
./ngrok authtoken YOUR_AUTHTOKEN # replace YOUR_AUTHTOKEN with the ngrok authtoken.
|
|
```
|
|
|
|
8. Now, forward port 22, which is the SSH port with this command:
|
|
|
|
```bash
|
|
./ngrok tcp 22
|
|
```
|
|
|
|
Now, you get a screen in the terminal like this:
|
|
|
|
```console
|
|
ngrok by @inconshreveable(Ctrl+C to quit)
|
|
|
|
Session Status online
|
|
Account {Your name} (Plan: Free)
|
|
Version 2.3.40
|
|
Region United States (us)
|
|
Web Interface http://127.0.0.1:4040
|
|
Forwarding tcp://0.tcp.ngrok.io:19028 -> localhost:22
|
|
```
|
|
|
|
In this case, copy the forwarded link `0.tcp.ngrok.io` and remember the port number `19028`. Type this on your local Visual Studio Code:
|
|
|
|
```bash
|
|
ssh user@0.tcp.ngrok.io -p 19028
|
|
```
|
|
|
|
The port redirects you to the default SSH port 22, and you can then successfully connect to code-server by entering the password you set for the user.
|
|
|
|
Note: the port and the url provided by ngrok will change each time you run it so modify as needed.
|