Customizing Microsoft Dev Boxes with code

Configuration as code is coming to Microsoft’s Azure-hosted workstations, allowing us to use WinGet, YAML files, and PowerShell DSC to deliver ready-to-run toolchains to developers.

man holding code sign programmer developer devops data scientist tech roles hitesh choudhary via un
Hitesh Choudhary (CC0)

Microsoft Dev Box, Microsoft’s cloud-hosted developer environments, recently entered general availability, ready to run with a mix of Windows images and a range of VMs with different capabilities. Fully customizable and centrally manageable, Dev Boxes allow you to tune your development environment for the work your team is doing. As tools like the new Dev Drive and Dev Home roll out across Windows, you will be in a position to quickly stand up new isolated developer systems that use resilient virtual drives and that link directly into Git-based workflows.

Tools like Dev Box make perfect sense for organizations that need to quickly on-board new developers, or that work with contractors and other contingent staff and need to control their environments. The same approach works well with remote staff, where assigning them Dev Boxes ensures that your code and their personal projects don’t mix and that they can use their own hardware without handing over full control. All they need is a machine that can run a remote desktop session.

At Build 2023 in May, Microsoft noted that nearly 10,000 of its own engineers were already using Dev Boxes as part of their toolchain, speeding up on-boarding for new projects. The company uses a mix of self-service and pre-configured images, with project-specific and role-specific instances as well as Azure-based virtual networks for securely connecting engineers to the resources they need. Getting started with a pre-configured Dev Box means engineers can be productive more quickly, even while they add their own favorite settings and add-ons to the provided virtual environments.

But there is still work to be done, if we’re to automate the provisioning of developer environments. What’s needed is more than Office and Visual Studio. We need a way to provision all of the elements that make up a toolchain, from editors and design tools to platforms and testing frameworks, along with the libraries and SDKs needed to build code.

Customizing Dev Boxes with code

Microsoft is rolling out a new set of “config as code” tools, currently in private preview, to ease the customization of Dev Boxes. The new tools use YAML to define Dev Box images and run setup tasks, which install the tools you need via familiar package managers like Chocolatey and Winget. These tasks can also work with the Visual Studio installer to add extensions. You can also enable Windows features like Windows Subsystem for Linux and Windows Subsystem for Android, extending your toolchain beyond Windows.

One useful new feature for configuring a Dev Box comes from the Windows Package Manager, WinGet, with its new configuration tooling. This allows you to define the state of your software install using a YAML configuration file and PowerShell’s Desired State Configuration (DSC) tooling. This approach allows WinGet configurations to be declarative, describing the end state of an installation process, not the steps needed to get there.

To use WinGet configuration files, you will need to enable WinGet’s experimental features, as this feature is currently in preview. The first step is to download and install the current WinGet preview (the necessary MSI installer is linked from this Microsoft Learn page). You should also get familiar with the WinGet configuration schema, currently in version 0.2.

Once ready to use, WinGet will first check for a valid configuration file, before using PowerShell DSC to manage the installation process. Installs can happen in any order, and even in parallel. The only sequencing comes where there are defined dependencies. For example, if an assertion on an application version fails, then the resulting steps won’t run. However, that won’t stop the rest of a configuration from completing, so you will need to test an install before deploying it to your Dev Box fleet. Any errors will be displayed on your console or written to log files.

There’s a certain logic to running configurations non-sequentially. For one thing it allows you to group elements the way you want in order to make the YAML more readable. For example, you could have a section for SDKs, another for developer tools and languages, and another for required services and applications. Then updates could be quickly added in the right place, helping you keep track of changes and letting you quickly compare different versions of your configurations—as well as making it possible to customize installs for different roles in a team.

Authoring WinGet configuration files

So how do you create a WinGet configuration file? Much of this is based on PowerShell’s DSC management model, so there’s a definite link between how DSC works and the structure of a WinGet configuration. There are two parts to a configuration file. The first details assertions, which are the base state necessary for a set of software installs to complete. The second describes resources, the software to be installed and any configuration settings.

Assertions use DSC modules to work with the underlying OS, and you can specify specific versions, or minimum or even maximum versions. You should start by using these to ensure that your Dev Boxes have the right base configuration before installing additional features and applications. Similarly, your YAML will define the necessary resources, which can include ensuring that certain OS mode switches are enabled, as well as adding workloads to installed applications, which might entail loading additional configuration files for tooling like Visual Studio. Again, you’re using the configuration file to automate DSC modules, with the WinGet module handling installs and applications’ own modules managing configurations.

Think of a WinGet configuration as a list of resource nodes. These are the main YAML elements in each section of the file, containing the instructions needed to either install or configure a part of your toolchain. Each resource contains a directive, in the shape of a DSC module, and the necessary settings as key/value pairs. Each resource can require another to be completed before it runs (ensuring that Visual Studio has been installed before you configure it, for example).

DSC modules are easy to find, either in Microsoft’s own repository of supported modules or in the community PowerShell Gallery. You can even author your own, for installing in-house tools or relatively rare applications.

Testing WinGet configurations

If you’re going to automate installs using WinGet configuration files, then it’s important to ensure that the modules you’re using are trustworthy and your YAML works as expected. While you can use a sacrificial Dev Box environment for final tests, initial tests are best run using your own Windows virtual machines or even Windows’ built-in Sandbox, which throws away its contents on every reboot. Once tested you can include the WinGet configuration file in your Dev Box setup YAML.

Using code to configure our Dev Boxes is an important step forward, as it allows us not only to speed up configurations, but also store the code we use for building development environments in the same repositories as the code we’re building. It’s easy to imagine an extension for the new Dev Hub application that connects to GitHub, downloads a setup file, and automates both setup and configuration, allowing us to build a development environment at a click of a button, ready to start coding.

Copyright © 2023 IDG Communications, Inc.

How to choose a low-code development platform