Overview 
 I have been building secure, reliable, and resilient Internet-facing services on
both the Linux and Windows platforms since the late 90s, and the consulted for
years on Continuous Integration and automated deployment practices. 
 I've been responsible for PCI and SOC2 compliance programs for at least a decade,
adding ISO 27001 more recently. I believe in…
Over the last two years I've recovered the capacity in my personal life to think about my dependency
on the big tech companies and to start exploring and migrating to alternatives. 
 Part of my motivations are to be voting with my wallet against enshittification, partly in response to increasing
geopolitical uncertainty, and partly to be an example that it's possible to…
I replaced Windows 11 on all my home and work machines with Linux about 6 months
ago and I am not going back. 
 I had been a Windows user at home and work for at least 30 years, starting with
Windows 3.1, and being an early adopter of NT 4.0 Workstation, XP 64-bit, and
all the way through to Windows 11, occasionally running the Betas and Release
Candidates. Windows is a kind of…
1Password has an excellent solution for managing SSH keys securely using their
 1Password SSH Agent .
However I interact with a few devices that either require keyboard-interactive
multi-factor authentication (MFA) or force the use of a password instead of
accepting keys or certificates. 
 Thankfully, through the use of the
 1Password CLI ,
the SSH_ASKPASS…
Update 2026-08-05: Added DNS-PERSIST-01 challenge option. 
 In April 2025, CA/B Forum ballot SC-081v3 
was passed 
to reduce the maximum certificate validity to 47 days by the 15th of March 2029.
The first step will be to reduce the maximum validity period to 200 days by the 15th of March 2026. 
 There has been a great deal of debate on whether this will be useful or, in some…
Update: minikube 0.29.0 has been released and includes my merged PR so you can enable embedded certificates with minikube config set embed-certs true once and then just symlink your .kube/config file from your WSL home directory to the same file in your Windows home directory. 
 
 I recently blogged about how I work with minikube from the Windows Subsystem for Linux (WSL) , describing some…
Update: I've been using the Sennheiser Presence for several hours every weekday for a year now and I'm still very happy with it and recommend it to others. I work from home near full-time, and the rest of my team works remotely too, so I spend a decent amount of time on VoIP calls for scheduled meetings, paired debugging sessions, and general chit-chat. For at least the last four years…
I develop services that run on Kubernetes. During development minikube provides an convenient way to run a local Kubernetes "cluster" regardless of whether you use Windows, OS X, or a Linux distribution as your host OS. Day-to-day I use minikube on Windows 10 and I prefer to use the Windows Subsystem for Linux (WSL) bash shell to have a scripting environment consistent with my colleagues, some of…
The Windows Subsystem for Linux (aka WSL or Bash on Ubuntu on Windows) provides a fantastic reproduction of a local Linux environment without needing a virtual machine. Even better than a virtual machine, WSL includes a lot of conveniences for interoperating with the host Windows file system and processes. That is, I can access my C: drive via /mnt/c/ and I can pop calc via calc.exe . Naturally,…
While I favour a containerize-all-the-things approach to new projects I still need to maintain systems that were designed several years ago around a combination of containers and host-based applications working together. In these situations it is common enough to execute ps or iotop on the host and see all the host and container processes together with no obvious indication of which processes…
Update: On 2017-DEC-13, DigitalOcean announced that private networking will be isolated to each account beginning February 2018. 
 
 If you've come from running virtual machines on AWS, Azure, or Google Cloud, you will be familiar with the idea that the VMs can have a public Internet-facing IP address and a private IP address, or some combination or multiple of the two options.…
Recently, Matt Hilton blogged about Source Control Antipatterns which included the practice of commenting code instead of deleting the code. As wholeheartedly as I agree with deleting code, I know that a popular objection is that deleted code is harder to find. While it might be harder than your favourite editor's Find In Files feature, it is important to know how to use the tools central to…
On Google Compute Engine (GCE) the latest VM boot images (at the time of writing) for Ubuntu 14.04 and 16.04 (eg ubuntu-1604-xenial-v20170811 ) ship with a file at /etc/sysctl.d/99-gce.conf which contains: 
 net.ipv4.ip_forward = 0
 
 This kernel parameter determines whether packets can be forwarded between network interfaces . On its own, the presence of this line isn't a big…
In recent weeks we started receiving alerts whenever a new AWS EC2 Instance running Ubuntu 14.04 LTS was launched for a specific Auto Scaling Group. On average, one new instance would be provisioned per day but the fault would only occur for about one or two of the new instances per week. The alert was an indicator that the new instance was unable to communicate with the message broker located on…
I recently had a frustrating experience with network connectivity for a set of AWS EC2 Instances running Ubuntu Trusty 14.04. Three instances, running Graphite and Carbon Cache 0.9.15 would intermittently become unreachable on the network for seconds or minutes at a time and several times a day. There was no obvious pattern to when these events would occur and when they did there was no…
I have previously blogged about queuing a new Team Build at the successful completion of another Team Build for Team Foundation Server 2010. Since then I've had a few people ask how to queue a new Team Build and pass information into the new Team Build via the build process parameters. Recently I've needed to implement this exact behaviour for a client, and with TFS 2013 which has quite…
In PowerShell, one of the most common examples you will see for parsing an XML file into a variable uses the Get-Content cmdlet and the cast operator , like this: 
 $Document = [xml](Get-Content -Path myfile.xml)
 
 The resulting type of the $Document variable is an instance of System.Xml.XmlDocument . However, there is another approach to get the same, or better, result using the…
I've blogged twice before about the OutDir MSBuild property set by Team Build and I've recently discovered that with the default build process templates included with Team Foundation Server 2013, the passing of the OutDir can be disabled via a simple Team Build process parameter. The parameter I am referring to is the "Output location" : This parameter's default value,…
This year I have been working with a code base that exhibits Visual Studio projects with three characteristics:
1. The project references a NuGet package.
2. The project is included in more than one Visual Studio solution.
3. The solution files are located in different folders.
I'm not sure how common this scenario is. A few different threads on the NuGet CodePlex site…
PowerShell v3 doesn't ship with help in the box anymore. You may love this or you may hate it. Regardless of your stance, if your environment is behind an authenticating web proxy, it is not obvious how to make it work. The general guidance is to use Save-Help from another computer but this doesn't help when every computer is behind the proxy and sneakernet is prohibited. This was my…
A common problem when managing deployments of applications, manual or automated, is where to securely store the passwords for service accounts used by Windows Services, IIS Application Pools, and Scheduled Tasks in each of the environments the applications are deployed to. With Windows Server 2008 R2, the first step to simplifying this problem was introduced in the form of Managed Service Accounts…
In my last post I described the problem of trying to change the Process Template of an existing Team Project in Team Foundation Server and the open-source project I built to solve it, WitMorph . In this post I want to demonstrate a simple walkthrough of the currently even simpler GUI. I have a Team Project, imaginatively named "Agile-6.1", and it was originally created with the "MSF for Agile…
Background 
 Historically Team Foundation Server process templates have not had a good upgrade story. When you create a new Team Project you are required to select the process template (typically CMMI, Agile, or recently Scrum) and that is the process template used by your project for the rest of its life. From the first TFS version, customizing the project has always been possible - adding…
I've been working with a PowerShell script to automatically deploy an application to an environment. The script is initiated on one machine and uses PowerShell Remoting to perform the install on one or more target machines. On the target machines the install process needs the username and password of the service account that the application will be configured to run as. I despise handling…
Update: with Team Build 2013 it is easier still . I've blogged before about the challenge of overriding the OutDir MSBuild property set by Team Build but this hassle is gone in version 4.5 of the .NET Framework. I stumbled upon a change to the core Microsoft.Common.targets file while trying to understand some build issues with a work project and discovered new logic to modify the OutDir…
Update: with .NET 4.5 there is an easier way . A very common complaint from users of Team Foundation Server's build system is that it changes the folder structure of the project outputs. By default Visual Studio puts all the files in each project's respective /bin/ or /bin/<configuration>/ folder but Team Build just uses a flat folder structure putting all the files in the drop folder…
Note: This process is based on PowerShell v3 CTP 2 and is subject change. When you open PowerShell v3's ISE (Integrated Scripting Environment) you should see a new Commands pane that wasn't present in version 2. This is a built-in example of an ISE Add-on Tool but you can also create your own quite easily. At its simplest an ISE Add-on Tool is a WPF Control that implements the…
Update: with Team Build 2013 you can even pass parameters to queued builds . I have seen several Team Foundation Server environments where multiple build definitions exist in a single project and need to executed in a particular order. Two common techniques to achieve this are: 
 
 Queue all the builds immediately and rely upon using a single build agent to serialize the builds. This…
One of the many great things about PowerShell is that it can utilise the .NET framework directly and third party .NET libraries whenever PowerShell doesn't offer a native solution. However, the PowerShell console, the Integrated Scripting Environment (ISE) and PS-Remoting in PowerShell 2.0 are all built for use with .NET 2.0 through to .NET 3.5. With the release of version 4 of the .NET…
Today I was working on introducing Continuous Integration to a legacy code base and was discovering the hard way that the solution of about 20 projects had many conflicting references to external assemblies. Some assemblies were different versions, others the same version but in different paths, and others completely missing altogether. Needless to say this wasn't going to build cleanly on a…
Now that I get to work with a TFS 2010 Lab Management environment most days, I find myself building various virtual machines to replicate the production environments of our clients for testing. With many different clients and projects, the range of virtual machine operating systems expands exponentially as matrix of core OS version, processor architecture, service pack, IE version, and other minor…
I have pieced together a simple PowerShell script to recursively locate all duplicate files (by content, not name) below a chosen directory. It is not the most elegant code but for my purposes it works and hopefully you will be able to tweak it to suit your needs. Firstly, it filters out any zero-length files. Zero-length files are naturally duplicates of each other and can be found quite…
I recently encountered a server where SQL Server had somehow been installed to the admin user's mapped U: drive instead of drive C:. As a result all SQL file paths in the registry referred to "U:\Program Files\Microsoft SQL Server\…" but for most users (including the SQL service account) the U: drive did not map to C:. This prevented Management Studio from working and probably many…