# 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) - [Cloudflare Rocket Loader](#cloudflare-rocket-loader) - [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) - [Using your own proxy](#using-your-own-proxy) - [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) - [Proxying to an Angular app](#proxying-to-an-angular-app) - [Proxying to a Svelte app](#proxying-to-a-svelte-app) - [Prefixing `/absproxy/` with a path](#prefixing-absproxyport-with-a-path) - [Preflight requests](#preflight-requests) - [Internationalization and customization](#internationalization-and-customization) - [Available keys and placeholders](#available-keys-and-placeholders) - [Legacy flag](#legacy-flag) 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]@ ``` 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: ```shell # 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. 2. 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. 3. 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 ``` 4. 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! 5. 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. 2. 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. 3. Install NGINX: ```bash sudo apt update sudo apt install -y nginx certbot python3-certbot-nginx ``` 4. 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 $http_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! 5. 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://`. 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. ### Cloudflare Rocket Loader If you serve code-server through Cloudflare, disable Rocket Loader for that hostname. Rocket Loader rewrites inline `