VSCode server on Azure Ubuntu VM. A step by step guide
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?
- 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 youre 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.
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
echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p
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 passwd [your username]
sh -c "$(wget -O- [https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh](https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh))" git clone https://github.com/zsh-users/zsh-autosuggestions $ZSH_CUSTOM:-~/.oh-my-zsh/custom>/plugins/zsh-autosuggestions
plugins=(git zsh-autosuggestions)
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
systemctl --user start code-server systemctl --user enable code-server
Note; these commands are not run as sudo I’ve noticed that my code-server was not started at boot, because it’s tied to my user-account. To allow starting at boot, use the following command;
sudo loginctl enable-linger
- 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
certbot certonly --standalone --agree-tos -m -d set up>
cd /etc/nginx/sites-available/ sudo vim code-server
server < listen 80; server_name ; # enforce https return 301 https://$server_name:443$request_uri; > server < listen 443 ssl http2; server_name ; ssl_certificate /etc/letsencrypt/live//fullchain.pem; ssl_certificate_key /etc/letsencrypt/live//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; >>
sudo ln -s /etc/nginx/sites-available/code-server /etc/nginx/sites-enabled/
sudo systemctl restart nginx sudo systemctl enable nginx
- 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
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"
- Install the global packages you might want to use
- Install the VSCode Remote Development extension pack
- Open VSCode and click «Open Remote window» at the most bottom left corner
- Select Open SSH Configuration File
- 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]
- 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.
bash -c "$(wget -q -O - [https://linux.kite.com/dls/linux/current](https://linux.kite.com/dls/linux/current))" systemctl --user start kite-autostart
systemctl --user restart code-server
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 http://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
- 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