Sandboxed Development Environments
As supply chain attacks and typosquatting are becoming more prevalent, it is important to sandbox your development environment to minimize the risks. The technology has finally progressed to the point that remote development tools let us create sandboxed environments. This contains the access a malicious programs have if such packages get installed.
In this article, I describe a simple way to create a containerized development environment with Vagrant.
Vagrant
Vagrant manages the virtual machines for you, it has good support for VirtualBox machines. Vagrant should work in all platforms, but I find it easiest in Linux.
To get started, start the installation process:
- Enable virtualization technology in BIOS. It should be under the CPU settings, the names varies e.g.
AMD-V
, orVT-x
- Install VirtualBox
- Install Vagrant
Vagrantfile
Each project you have needs Vagrantfile
which defines the environment your program runs.
The default one can be generated using command vagrant init
.
The basic configuration will look like this
Vagrant.configure("2") do |config|
config.vm.box = "ubuntu/jammy64"
config.ssh.port = 2222
config.vm.network "forwarded_port", guest: 3000, host: 3000
config.vm.synced_folder ".", "/home/vagrant/app"
config.vm.provider "virtualbox" do |vb|
vb.memory = 8192
vb.cpus = 1
end
config.vm.provision "shell", path: "Vagrant.provision.sh"
It is important that you allocate enough memory as the remote IDE will run inside the container. The CPU count does not matter but it should not exceed the number of cores you have in the host.
Provisioning
Then you'll have another file named Vagrant.provision.sh
which contains the commands you need when the machine is
created the first time. An example to install a Node.js would look like this
#!/usr/bin/env bash
echo "Installing Node.js version 16..."
curl -fsSL https://deb.nodesource.com/setup_16.x | sudo -E bash -
apt install nodejs -y
The script is a normal bash
script, to make the script idempotent you may want to check if the command exists
if ! [ -x "$(`command -v node`)"]; then
curl -fsSL https://deb.nodesource.com/setup_16.x | sudo -E bash -
apt install nodejs -y
fi
Docker
The Docker containers can be run inside the virtual machine:
config.vm.network "forwarded_port", guest: 5432, host: 5432
config.vm.provision "docker" do |d|
d.run "postgres:14",
args: "-e POSTGRES_USER=postgres -e POSTGRES_PASSWORD=postgres -p 5432:5432"
end
Alternatively, you can install Docker Compose in the provisioning script and run that. Running the docker containers directly is simpler if there aren't many of them.
JetBrains Gateway
After starting the virtual machine using vagrant up
, you can use JetBrains Gateway to install the remote IDE using SSH.
Notice that all plugins need to be installed after the remote IDE is installed.
The following connection credentials are to be used:
Configuration | Value |
---|---|
Username | vagrant |
Host | 127.0.0.1 |
Port | 2222 |
Private key | /home/YOUR_USERNAME/.vagrant.d/insecure_private_key |
There are some environments where Remote IDEs are redundant as the IDE interpreters can use the same modules as the virtual machine. In those cases, you can use the IDE natively but run the program itself in virtual machine.
Visual Studio Code Remote SSH
Install the Remote Development extension and connect to the machine using the same configurations described above.
Provisioning Scripts for Common Environments
Node.js
Do not install from Snap, those packages do not work well with postinstall scripts. Instead, install them from NodeSource or use Node Version Manager.
#!/usr/bin/env bash
if ! [ -x "$(`command -v node`)"]; then
echo "Installing Node.js version 16..."
curl -fsSL https://deb.nodesource.com/setup_16.x | sudo -E bash -
apt install nodejs -y
npm install -g pnpm
fi
cd app
pnpm install