Ivo Toby
Syntactic Sugar

Syntactic Sugar

VSCode server on Azure Ubuntu VM.

VSCode server on Azure Ubuntu VM.

A step by step guide

Ivo Toby's photo
Ivo Toby
·May 8, 2021·

11 min read

Subscribe to my newsletter and never miss my upcoming articles

In this article I'll explain step-by-step on how to create your own VSCode server running on a VM in Microsoft Azure. You do not need Azure, you can also use this guide on a VM on a home-server, any other cloud provider or a VM provided by your employer.

What to expect from this guide?

After following these steps, you'll end up with a development server which you can use to work on Node.js frontend and backend projects. You could probably use it for other stacks. From my experience working with this setup is almost the same as running VSCode on your own machine, except it's not on your local machine.

You can connect your local VSCode editor with the VSCode server using SSH. Code completion, 'go to definition', debugging, running your code, even the terminal, it's all the same. If you ever worked from VSCode on Windows with locally running containers or WSL ; it's exactly the same.

Your development server will connect to your Global Area Network using ZeroTier. This makes it easy to connect without the need to change local configuration each time you start the server and it gets a new IP-address. Your development machine will be available from a local network. Nice bonus; you can completely fence the VM behind a firewall and still have SMB access.

Why would you want to run VSCode from a server?

Couple of reasons

  • Resources; a fairly complex webapp can contain a lot of files and do a lot of resource hungry stuff. My main development machine is a Macbook Pro 13'' from 2019. It has an Intel Core i7 and 16 GB of RAM. Should be enough, right? While working, most of you have other stuff running; Slack or other chat apps, an email client, your browser (most webdevs have several running at once), a music player. My Macbook does throttle a lot and gets pretty hot when working on a fairly large codebase in TypeScript. Using a dedicated VM will result in faster transpiling, faster response when testing your app, faster code completion and overall a more productive IDE/text editor.
  • Security; having the code I write for my employer sitting on a system from my employer is safe. If you're freelancing you can even use this as a USP; "everything I code for you is on systems you own".
  • Flexibility; you can work from whatever machine you have within reach, as long as it is connected and has VSCode. Let me correct that; as long as it has a decent browser. You can use a normal local VSCode instance to connect to your VSCode server, I'd recommend this as daily driver. However; since VSCode is a webapp you can also use your browser to connect to your VSCode server. You can use a Chromebook, or even an iPad with a keyboard. You have the full functionality you'd have when you use the VSCode application. And since your code is not actually on the machine you're using it does not really matter if it's a company laptop or personal laptop.

Costs

Free Microsoft credits aside, this VM will probably set you back around $25,- per month. You can shutdown the vm when you are not working, but you will need some grunt to comfortably run VSCode server. I use the Standard B2ms (2 vcpus, 8 GB memory) VM-size which costs $70,- per month. That's steep, and you might get the same results use the B2s instance, which has 2 cores, 4GB of RAM and 16GB SSD and will set you back roughly $15,- per month. If you'd left it running a full month you'd be paying $35,- per month. I'll be testing the B2S instance upcoming week and will report back on my findings.

Update : after one morning working on the B2s instance I ran into memory issues. I had 3 projects open, 2 of them running (a serverless backend and a isomorphic frontend), I noticed the editor getting sluggish and top revealed there was no RAM left. Since by default the Azure Linux VM's have no swap enabled the VM was slowly crashing. So I created a swap-file using the procedure described at the end of this article and I'm currently working with 4GB RAM and 5GB of swap.

Prerequisites

I assume you have all of the next items in place, or know a decent amount about;

  • An Azure account, either with credits or a valid creditcard and reasonable understanding of what Azure is, how to use it and the way the webapp works.
  • Comfortable with Linux terminal, you know how to create a SSH-key, install packages
  • You already have a ZeroTier account and the ZeroTier client installed on your own machine. There are a lot resources explaining setting up ZeroTier, so use the-Google for that (or read this)
  • If you want to secure the webinterface with an SSL certificate; a (sub)domain of which you can update the DNS records(recommended!)

Let's get started!

  • Create a Virtual Machine in Azure in the region close to where you are, select whatever type you want and what your credit card allows. I will be setting up a B2s instance, with 2 Cores and 4GB or RAM.
  • Select Ubuntu Server 21.04 - Gen1 as image.
  • Use SSH public key authentication and use the key Azure creates or use a key you already have in place. Please note; you can not use ed25519 keys for now. Don't forget to enter a username to login.
  • Network; for now allow SSH (22) and port 80 (service: http).
  • Disks; depending on your needs you can add extra data disks. For my situation the standard amount of 32 GB is enough.
  • Management; Enable auto shutdown and set a time that's convenient for you, I use 9 pm, the likelihood of me still working at 9 pm is very slim.
  • When the VM is up and running, connect to it with SSH. You can use the IP found at "Overview" in the Azure portal. If the SSH key you used is not the default key you can use the -i argument to switch sshkeys like so:
    ssh -i ~/.ssh/id_rsa user@address
    
  • First thing I usually do is add my ed25519 key to ~/.ssh/authorized_keys (optional).
  • Second thing; update the system;
    sudo apt-get update && sudo apt-get upgrade
    
  • Configure max_user_watches. If you keep this at it's default value you might get errors like this Error: ENOSPC: System limit for number of file watchers reached when you use node_modules like nodemon or other file watchers in larger codebases. You can increase the value for max_user_watches:
    echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p
    
  • Now install ZeroTier:
    curl -s https://install.zerotier.com | sudo bash
    
  • Authorize the client at the ZeroTier website and give it a static IP (by adding an address to the machine by hand on the website instead of letting the site decide).
  • Disable the ubuntu firewall:

    sudo ufw disable
    

    Now try to connect to the VM with SSH on its ZeroTier address be fore proceding. It could take a while before the virtual network is up & running, also after rebooting!

  • Set a password for your user, you will need it to install packages from VSCode terminal; sudo passwd [your username]

  • Download VSCode server from https://github.com/cdr/code-server/releases and install it:

    wget -q https://github.com/cdr/code-server/releases/download/v3.9.3/code-server_3.9.3_amd64.deb
    sudo dpkg -i code-server_3.9.3_amd64.deb
    
  • Setup systemctl:

    systemctl --user start code-server
    systemctl --user enable code-server
    
  • Configure authentication by editing ~/.config/code-server/config.yaml. Set up a strong password, you won't need to change the IP-binding since we'll be setting up a reverse proxy.

If you don't want to use the web interface and will only use SSH from another VSCode app you're basically ready, skip next steps to finish up.

If you do like to use VSCode from a browser, move on to install NGINX and optionally Let's Encrypt.

You need to set up a (sub)domain with an A record that points to the IP address assigned to the VM. For this tutorial I set up vscode.syntacticsugar.nl with a TTL of 60 seconds to ensure it's available quickly. You can change the IP to the IP you've assigned from ZeroTier in a later stage.

Install Let's Encrypt

sudo apt install certbot -y

Request a certificate

certbot certonly --standalone --agree-tos -m <enter your email> -d <the domain you set up>

This could fail the first few times as DNS updates tend to be slower whenever you need them to be fast.

When the certificate has been successfully created, change the DNS to the IP address you assigned in ZeroTier.

NGINX reverse (SSL) proxy

  • Install NGINX
    sudo apt install nginx -y
    
  • Create a config
    cd /etc/nginx/sites-available/
    sudo vim code-server
    
  • If you have setup SSL, paste this config (and change ) :
server {
 listen 80;
 server_name <YOUR DOMAIN>;
 return 301 https://$server_name:443$request_uri;
}

server {
 listen 443 ssl http2;
 server_name <YOUR DOMAIN>;

 ssl_certificate /etc/letsencrypt/live/<YOUR DOMAIN>/fullchain.pem;
 ssl_certificate_key /etc/letsencrypt/live/<YOUR DOMAIN>/privkey.pem;

 location / {
 proxy_pass http://127.0.0.1:8080/;
 proxy_set_header Host $host;
 proxy_set_header Upgrade $http_upgrade;
 proxy_set_header Connection upgrade;
 proxy_set_header Accept-Encoding gzip;
 }
}
  • Activate the vhost
    sudo ln -s /etc/nginx/sites-available/code-server /etc/nginx/sites-enabled/
    
  • Check the config
    sudo nginx -t
    
  • If all's fine, restart the services;
    sudo systemctl restart nginx
    sudo systemctl enable nginx
    

Check if you can reach code-server from your browser by going to yourdomain

Harden the firewall of your VM in the Azure Portal in the Networking Section. If you dare to rely on your ZeroTier connection you can disable SSH completely. If you're not the daring type consider only allowing connections to SSH from your own company or home IP. Also remove the rule for port 80. If you are planning to use VSCode from a browser outside ZeroTier you can leave port 80 and add an allow rule for port 443. This is NOT recommended from a security point of view.

Optional steps

So basically you have a VSCode server running! Hurray! Next would be installing the toolset you need for the language your're working with. I'm sticking with NodeJS, so the following steps only apply if you want to work with Node.

Install NVM (node version manager, check https://github.com/nvm-sh/nvm for the latest version)

curl -o- [https://raw.githubusercontent.com/nvm-sh/nvm/v0.38.0/install.sh](https://raw.githubusercontent.com/nvm-sh/nvm/v0.38.0/install.sh) | bash

Setup paths

nano ~/.zshrc

Paste the following config at the end of the file:

export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"  # This loads nvm
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"

Reload your environment:

source ~/.zshrc

install the Node.js version you want to use (to list al available versions, use nvm ls-remote):

nvm install v16.4.2

Connecting VSCode from your local machine with VSCode server

Install the VSCode Remote Development extension pack. Open VSCode and click "Open Remote window" at the most bottom left corner

n4c2hd9k220if6mmlc1p.png

Select Open SSH Configuration File and select the config file in your home-directory/.ssh

Add the following configuration (and modify it to reflect your environment):

Host [the hostname you used to create ssl or the Zerotier IP address ]
HostName [the ZeroTier Ip address]
User [your username]
IdentityFile ~/.ssh/id25519 [or the SSH private key file you use to connect]

Now click the same button Open Remote window , select Connect to host and select the host you just added.

If all is fine you should get an empty VSCode window, the button has changed and shows SSH: [hostname].

Congrats; you are now working on your VSCode server!

Plugins

Open the plugins tab and scroll through the windows with locally installed plugins. Click Install in SSH: [hostname] to install them on your VSCode server. You probably need to close VSCode and reconnect.

Tips and tricks and daily usage

Getting started in the morning

I have not found an easy way to autostart my VM every morning. To be honest; I don't think I need that either. I have days with back to back meetings and I don't want the VM burning to my Azure credits without me using it. So I login to the Azure portal and start it manually every time I need it. When it's up and running I connect my local VSCode app and hack away. Update: I stumbled upon the Azure App for iOS, this app makes it very easy to start your development VM.

Portmapping

If you run a project using node you'd normally fire up a browser and navigate to localhost:port . Using VSCode server is exactly the same! VSCode will create SSH tunnels for you so you can connect to localhost:portnumber. So you won't run into CORS issues or other strange behaviour.

Opening a VSCode window from the VSCode terminal

Imagine; you are working on a frontend from on your VSCode server from a local VSCode instance using SSH. You realize you need to check some stuff in another project, which has been cloned into another folder on your VSCode server. You can cd to that project using the terminal within VSCode and fire up a new editor by simply typing code .

Finishing up for the day

You had a productive day writing elegant code and finishing several tickets. You're ready for a quiet evening doing other stuff. Before closing the lid of your laptop be sure to save ALL files in VSCode and commit & push your work. Your VM will shut down later tonight which could lead to data loss. I have not run into this, but better safe than sorry right?

Known Issues

  • It could take a while for ZeroTier to connect after booting the server. If you have issues ZeroTier not connecting at all try to login using SSH with the dynamic IP assigned by Azure and run ZeroTier join command; sudo zerotier-cli join <your network-id from ZeroTier>
  • The VSCode webinterface might work better if you use Chrome.
  • Not enough memory? Enable swap on your Azure VM; edit /etc/waagent.conf. add or uncomment these lines (set SwapSizeMB to match the amount of RAM your VM or more) :
    ResourceDisk.Format=y
    ResourceDisk.Filesystem=ext4
    ResourceDisk.MountPoint=/mnt/resource 
    ResourceDisk.EnableSwap=y
    ResourceDisk.SwapSizeMB=4096
    
    reboot your VM and you should see swap memory in top

Questions? Praise? Complaints?

Email: Twitter: https://twitter.com/buttonfreak

 
Share this