loading...
Cover image for How to run VS Code on the server!

How to run VS Code on the server!

babak profile image Babak ・5 min read

VS Code is my favorite editor for web development. The integrated terminal, the great plugin ecosystem, debugger, and excellent TypeScript support make it just perfect. Its one reason I keep coming back to developing locally. Because while I could run vim on the terminal and work remotely, I'm just not as productive in vim.

Of course there are other options. Cloud development is pretty great. Working on a project entirely remote on a browser is liberating. My project is always ready to be worked on, untethered from my machine. But cloud editors each have their own drawbacks. Ultimately, I want to drop into the terminal, start and stop services, and do all that I am able to do from my local machine. If only there was a way to run VS Code directly on a remote server, it would be the best of both worlds.

Well, now there is! Thanks to code-server by coder.com

GitHub logo cdr / code-server

VS Code in the browser

code-server

Run VS Code on any machine anywhere and access it in the browser.

Screenshot

Highlights

  • Code everywhere
    • Code on your Chromebook, tablet, and laptop with a consistent development environment.
    • Develop on a Linux machine and pick up from any device with a web browser.
  • Server-powered
    • Take advantage of large cloud servers to speed up tests, compilations, downloads, and more.
    • Preserve battery life when you're on the go as all intensive tasks runs on your server.
    • Make use of a spare computer you have lying around and turn it into a full development environment.

Getting Started

For a full setup and walkthrough, please see ./doc/guide.md.

Quick Install

We have a script to install code-server for Linux, macOS and FreeBSD.

It tries to use the system package manager if possible.

First run to print out the install process:

curl -fsSL https://code-server.dev/install.sh | sh -s -- --dry-run

Now to actually install:

curl

Getting started

To get started, you'll need to log into your remote development server. This can be something like a Droplet from Digital Ocean, an AWS Lightsail instance, or any other cloud or internet connected server one would want to use. ssh access is needed.

One could then log into the remote server and either run code-server in docker or just use one of their binary releases. I used the the binary distribution for my purposes

https://github.com/codercom/code-server/releases

Here is an example of how that might go

mkdir ~/code-server
wget -qO- LINK_TO_DESIRED_BINARY \
  | tar xvz --strip-components=1 -C ~/code-server

The code-server binary comes with a few options. At the time of this writing, it seems that the application had some trouble when given a relative paths on my system. So I wrote a super simple wrapper around it in bash, decided to call it code and place that in ~/bin which is my PATH variable.

vim ~/bin/code

#!/usr/bin/env bash
abs=$(realpath .)
req=$1
if [[ ! $1 =~ ^\/ ]];
then
  req="$abs/$1"
fi;

if [[ ! -d $req ]];
then
  echo "ERROR: path does not exist"
  echo "$req"
  exit;
fi;

~/code-server/code-server $req --no-auth

chmod +x ~/bin/code

This script starts code-server with the no-auth option. The no-auth option disables the built-in encryption functionality and the password authentication page. I do this because I would rather encrypt the traffic through a proxy server or through a SSH tunnel. I can also password protect the page using the web server that proxies connections.

Now to start the server, I simply open a project similar to how I would with VS Code directly.

code /path/to/project

This will start serving VS Code over port 8443. There are two ways to connect to it; either through an SSH tunnel or by using a web server reverse proxy.

SSH Tunneling / Port Forwarding

You can forward a remote port from the server to your local client by using SSH. Here is how it would look to format port 8443 from the server to your local machine.

ssh -N -L 0.0.0.0:8443:localhost:8443 login@your-server \
  2> /dev/null

This command won't give you the remote shell, it will just do the port forwarding. Now you can open your browser and visit http://localhost:8443. Behold! You are now using VS Code, running on your server, from your browser!

What is pretty incredible is that you have access to the terminal as well! This is very powerful stuff--so beware!

One final piece is to proxy any other running services on unprivileged ports, like port 3000 or 8080. One way to do this is by opening another terminal and making another connection.

ssh -N -L0.0.0.0:3000:localhost:3000 login@your-server \
  2> /dev/null

Or proxy both ports at once

ssh -N \
  -L 0.0.0.0:8443:localhost:8443 \
  -L 0.0.0.0:3000:localhost:3000 \
  login@your-server \
  2> /dev/null

Web Server Reverse Proxy

Note: this option is for if you want to handle encryption and password protection yourself.


BE SURE TO ENCRYPT AND PASSWORD PROTECT PUBLIC URLS.

Correctly setting up a reverse proxy through a web server is a more involved process. I will provide only an overview of what you need to make this work.

  • Make sure you have an SSL certificate. You can get one using certbot by Let's Encrypt.
  • Configure a web server to create reverse proxy between port 8443 and your desired URL. Be sure to proxy websocket traffic as well.
  • Password protect access to the URL

In my case, I also want to proxy services running for development purposes, like port 3000 or 8080.

APACHE

You'll need to ensure that the proper modules are loaded

sudo a2enmod rewrite

Then a configuration might be something that starts like this

<VirtualHost ip_address:443>
  # Enable Modules
  RewriteEngine On
  SSLEngine On

  # Configure basics
  ServerName your.address
  ServerAdmin whoever@your.address


  # Proxy Traffic
  RewriteCond %{HTTP:Upgrade} =websocket
  RewriteRule /(.*)           ws://localhost:8443/$1 [P,L]
  RewriteCond %{HTTP:Upgrade} !=websocket
  RewriteRule /(.*)           http://localhost:8443/$1 [P,L]

  # Require Password
  AuthUserFile /path/to/.htpasswd
  AuthGroupFile /dev/null
  AuthName "Title"
  AuthType Basic
  require valid-user

  # Use SSL
  Include /etc/letsencrypt/options-ssl-apache.conf
  SSLCertificateFile /etc/letsencrypt/live/yourwebsite.com/fullchain.pem
  SSLCertificateKeyFile /etc/letsencrypt/live/yourwebsite.com/privkey.pem

  SSLProtocol all
  SSLCipherSuite HIGH:MEDIUM
  # And so on...

NGINX

I've not tried doing this for code-server with NGINX yet. NGINX is particularly apt for this. Here are some references on where I would start:

Encrypt traffic and reverse proxy w/ websockets
https://gist.github.com/steve-ng/ed6de1fa702ef70bd6ce

Password protect
https://www.digitalocean.com/community/tutorials/how-to-set-up-password-authentication-with-nginx-on-ubuntu-14-04

Other options

Let code-server handle its own encryption

Another option is to not include the --no-auth option and let code-server do its thing. Here is a resource for more information on this would work on Digital Ocean

https://github.com/codercom/code-server/blob/master/doc/admin/install/digitalocean.md

Use coder.com

I should also mention that coder.com has a cloud service for this.

https://www.coder.com

Overview

Running VS Code on the cloud untethers the developer from their workstation. One could install their plugins, configure the editor to their liking, and work directly from the could. The environment is always there, ready to go.

Discussion

pic
Editor guide
Collapse
ronjonarod profile image
Alex Rodriguez

So for the SSH Tunneling/ Port Forwarding section is there a reason why you did the 0.0.0.0? Because if you use that instead of just leaving that off (i.e.

ssh -N -L 3000:localhost:3000 login@your-server \
  2> /dev/null

(or doing localhost) then that means, if you don't have a firewall on your machine that is actively blocking port 3000, anyone will be access that port that is one the same network as you. Since you are just referencing accessing localhost in the article I think it would make more since to just drop the 0.0.0.0 so you don't expose unnecessary ports from your machine (or in this case from the remote machine).

really cool post though, thank you 😁

Collapse
joeschr profile image
JoeSchr

have you tried running other docker container in parallel? I tried doing that a few weeks ago but on coder.com but support told me they are not there yet...

for my use case to make sense developing remotely I would really need to be able to run other docker containere

Collapse
picocreator profile image
Eugene Cheah

This is exactly what I wanted for a long time - been trying to hack some HTML5 screen sharing tools to achieve the same objective.

Naturally this would be 1000x better.

winning

Collapse
darkain profile image
Vincent Milum Jr

I contribute to about 20 different repositories. Curious, how would this setup handle that? Would I need a new instance of this per repository, or could vscode access multiple machines like it can locally? Also, is this limited to docker/Linux? I run windows and FreeBSD in my environment, curious to know how this would Translate, too.

Collapse
ronjonarod profile image
Alex Rodriguez

in theory you should be able to access different repo's, but you should also be able to use something like this plugin: marketplace.visualstudio.com/items... to aid in repo switching if needed.

also, it looks like they package all the dependencies in a docker container so if you wanted to run it somewhere else, you would have to make sure all the deps are installed on the target machine. aside from that you should be able to run it in a vm (or vagrant box) with relative ease on windows/freebsd. looks like freebsd is trying to get it working: wiki.freebsd.org/Docker , and for windows you should be able to use docker desktop.

Collapse
daviddesmet profile image
David De Smet

Really interesting concept.
I want to try it out but sadly, I'm not receiving the verification code by SMS :(