<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
  <channel>
    <title>Mark Phillips | Product Marketing, Management and Strategy</title>
    <link>https://probably.co.uk/</link>
    <description>Recent content on Mark Phillips | Product Marketing, Management and Strategy</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-gb</language>
    <lastBuildDate>Fri, 17 Apr 2026 12:04:40 +0000</lastBuildDate>
    
    <atom:link href="https://probably.co.uk/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>The model of a product-led company</title>
      <link>https://probably.co.uk/posts/the-model-of-a-product-led-company/</link>
      <pubDate>Fri, 17 Apr 2026 12:04:40 +0000</pubDate>
      <guid>https://probably.co.uk/posts/the-model-of-a-product-led-company/</guid>
      <description>
      
      <![CDATA[<blockquote>
<p>&ldquo;Don&rsquo;t make me think&rdquo;.</p>
<p><strong>Steve Krug</strong><sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup></p>
</blockquote>
<p>There&rsquo;s something I say all the time when advising startups on their product strategy: <em>solve problems for people, and the money will come</em><sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup>. It still amazes me that this often comes as a shock.</p>
<p>All too often companies try to &lsquo;game&rsquo; their customers: bait &rsquo;n switches, <a href="https://pluralistic.net/2024/01/30/go-nuts-meine-kerle">enshittification</a>, bullshit marketing. These are all signs of a company focussed more on itself than its customers. They somehow convince themselves that <em>being customer focussed</em> is a lesser path to profits <sup id="fnref:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup>.</p>
<p>I can hear you snorting now though - <em>&ldquo;you&rsquo;re being idealistic and unrealistic!&rdquo;</em> Yet throughout my 30+ year career, I&rsquo;ve seen behaviours that prove the point: make a product that solves a customer problem, make it easy for them to love you for solving the problem, and the revenue comes. Even if you&rsquo;re not charging for the product.</p>
<p>A couple of weeks ago, I saw another proof point of this, with a product I have only recently discovered, yet already love enough to <em>want</em> to pay for it, although I don&rsquo;t <em>have</em> to pay for it. <a href="https://tailscale.com">Tailscale</a>.</p>
<h2 id="what-makes-a-great-product">What makes a great product</h2>
<p>Here&rsquo;s how to make a great product that will sell: <strong>solve a problem and make it incredibly easy for other people to adopt and use your product to solve their problem</strong>. That&rsquo;s it (again, see <sup id="fnref1:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup>).</p>
<p>The automatic thought is Tailscale is a VPN, but really, it&rsquo;s not. It&rsquo;s a <em>simple</em> way to connect devices securely and privately. Trying to get yourself off the cloud drug and repatriate your own data to a NAS you own, at home, yet want to access it from your phone when away? You need a way to securely and privately connect those devices without exposing your private NAS to the internet. Tailscale is the answer.</p>
<p>However, implementing technical products like this is often hard. Which is where Tailscale hits my <em>simple</em> requirement. I connected a handful of devices with barely any thought whatsoever. There was no need to mess about with firewalls; I didn&rsquo;t need to think about or understand routing and IPv4 versus IPv6. I just followed their <a href="https://tailscale.com/docs/how-to/quickstart">simple</a> instructions <em>and it all just worked</em>.</p>
<p>As I&rsquo;ve used Tailscale more, I&rsquo;ve realised they also tick a few more of my required checkboxes. Whilst looking at the interface the other day, I noticed something about &ldquo;an <a href="https://tailscale.com/docs/features/exit-nodes">exit node</a>&rdquo; — with a small (i) icon for more information. The information box showed me <em>how</em> to make a device an exit node; what switch to run the command with. No need to branch off to the documentation to find out how to do this; the minimal information required was there, in a helpful little box.</p>
<figure><img src="/posts/the-model-of-a-product-led-company/tailscale-hint.png"
    alt="Tailscale helpful hint for an exit node" width="500">
</figure>

<h2 id="dont-make-me-think">Don&rsquo;t make me think</h2>
<p>To make a product really easy to use, the complicated has to be simplified <em>somewhere</em>. A lot of companies don&rsquo;t put enough effort into that simplification, leaving their users to struggle. This is a perennial problem in the tech industry. However, if you, the company developing a product, put the hard work into that simplification process, the user benefits. Which ultimately means you benefit, because they&rsquo;re more willing to use a product that has little friction to adopting it.</p>
<p>If I can&rsquo;t be productive with a product within 15 minutes, I will give up on it. If a piece of information isn&rsquo;t clear, or even worse, there is deliberate obfuscation that makes me work to understand what I&rsquo;m looking at, I won&rsquo;t trust the company. I don&rsquo;t think I&rsquo;m alone in this thinking, either. <a href="https://www.youtube.com/@rossmanngroup">People are tired</a> of being used, trapped and &rsquo;experimented on&rsquo; just to use a product. The hard work of simplifying has to happen somewhere — and it should be you, not your users, doing it. Make it so easy to use your product that I don&rsquo;t have to think. Thinking is <em>literally</em> costly to our bodies (it takes more energy to use &ldquo;System 2&rdquo; than it does &ldquo;System 1&rdquo;<sup id="fnref:4"><a href="#fn:4" class="footnote-ref" role="doc-noteref">4</a></sup>).</p>
<h2 id="it-starts-with-company-culture">It starts with company culture</h2>
<p>&ldquo;Company culture&rdquo; is a woolly phrase, too often used as a euphemism to create tribal loyalty. That&rsquo;s not what I&rsquo;m talking about here. I&rsquo;m talking about <a href="/posts/design-of-everyday-things/#culture">leadership&rsquo;s appreciation and respect for people</a>, not least their customers. When the leadership of a company is driven by the desire to solve problems for people, it more often than not flows through the company to create <em>respectful</em> products.</p>
<p>Which brings me back to Tailscale. Recently they <a href="https://tailscale.com/blog/pricing-v4">changed their pricing</a> and made their free tier even better. In the live chat on Discord (you can watch <a href="https://drive.google.com/file/d/1npOwCy6tb-Tk84-7WaR4IS5Htlz1LCmq/view">the recording here</a>) Tailscale&rsquo;s CEO, Avery Pennarun<sup id="fnref:5"><a href="#fn:5" class="footnote-ref" role="doc-noteref">5</a></sup>, actually said at one point (10 minutes in to the recording) that 99% of customers on the paid-for Plus product don&rsquo;t use any of its features, <em>they just want to give the company money</em>.</p>
<figure><img src="/posts/the-model-of-a-product-led-company/folks-love-tailscale.webp"
    alt="Folks love Tailscale" width="400"><figcaption>
      <p><em>A user comment in Discord during Tailscale&rsquo;s update talk</em></p>
    </figcaption>
</figure>

<p>I&rsquo;ve seen that behaviour before. In the early days of Ansible, we had a customer pay for the commercial product, which they didn&rsquo;t actually need. They loved the open source part so much they just wanted to give the company some money.</p>
<h2 id="make-life-easier-faster-or-cheaper">Make life easier, faster, or cheaper</h2>
<p>We humans dislike change. Even if we have a problem, there can be resistance to adopting a new product to solve it. Especially since historically products <a href="/posts/defining-devops/">haven&rsquo;t always solved the problems</a> they purport to. A product needs to solve a problem that, in doing so, makes the user&rsquo;s life easier, faster, or cheaper. Even better if it nails all three. A person&rsquo;s inertia is far easier to overcome if trying your product is as simple as possible. <em>Don&rsquo;t make me think</em>.</p>
<blockquote>
<p>Any third-rate engineer can increase complexity; but it takes a certain flair
of real insight to make things simple again.</p>
<p><strong>E F Schumacher</strong></p>
</blockquote>
<!-- screenshot of what loyalty looks like; comment from discord -->
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>All tech products have complexity. It can be solved in two places — by you, the business, or by your customer. There&rsquo;s only one correct answer to this. If you, the business, can&rsquo;t solve the complexity, there are only two reasons. 1) You don&rsquo;t know how. This is forgivable. You can learn, though, and that is arguably easier than at any point in history. 2) You choose to push complexity onto your customers to &rsquo;trap&rsquo; them into your product, or to contrive ways to sell &lsquo;consulting&rsquo; or services. Enshittification. Only one of these paths creates trusting, loyal customers who will be your greatest sales and marketing asset — for zero cost outlay. Choose wisely.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p>There is a longer story to this, which I have a blog in draft for. It&rsquo;s taking a while to tune it to be <em>as simple as possible</em>, but I&rsquo;ll drop it soon 🤞&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref1:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:3">
<p>With social media companies, which are actually just selling advertising, this is probably true, though. Without gaming you to stay on their awful platforms, thus sell your attention to the highest bidder, they will die. We can live in hope.&#160;<a href="#fnref:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:4">
<p><a href="https://psycnet.apa.org/record/2012-04347-001">Trust your unconscious when energy is low</a>. Also, see Daniel Kahneman, <a href="/posts/2019-12-10_5-books-part-1/">Thinking, Fast &amp; Slow</a>&#160;<a href="#fnref:4" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:5">
<p>Incidentally, I was sent this talk by a colleague. It explains a lot about Tailscale&rsquo;s culture, and resultant product: <a href="https://youtu.be/i7p0i95Z3Ko">https://youtu.be/i7p0i95Z3Ko</a>&#160;<a href="#fnref:5" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]>
      
      <![CDATA[<hr><p>Thanks for reading this post via RSS! 👏</p>]]>
      <![CDATA[<a href="mailto:rs511@probably.co.uk?subject=The model of a product-led company">Reply to this post by email</a>]]>
      </description>
    </item>
    <item>
      <title>Using LLMs in early stage careers</title>
      <link>https://probably.co.uk/posts/ai-prompting-for-early-careers/</link>
      <pubDate>Thu, 19 Feb 2026 14:02:53 +0000</pubDate>
      <guid>https://probably.co.uk/posts/ai-prompting-for-early-careers/</guid>
      <description>
      
      <![CDATA[<p>Matt Shumer’s “<a href="https://shumer.dev/something-big-is-happening">Something Big is Happening</a>” blog post about AI has caused quite a stir. If you’ve not read it, it is worth a peruse.</p>
<p>The TL;DR is <em>&ldquo;be very worried, but don’t stick your head in the sand&rdquo;</em>.</p>
<blockquote>
<p>Dario Amodei…has publicly predicted that AI will eliminate 50% of entry-level white-collar jobs within one to five years</p>
</blockquote>
<p>The often discussed point about AI replacing jobs is those early-career positions. The juniors fresh out of university, gathering vital experience. If AI replaces these entry-level jobs, where does that leave humans?</p>
<p>Peers further along their careers often mention their use of LLMs for tasks previously handled by junior staff. Possible confirmation of Amodei’s statement.</p>
<p>However, a conversation with a close friend recently presented a contrarian perspective. He thinks early-career-stage staff working with LLMs will be far more useful to many businesses.</p>
<p>As our conversation progressed, I posited I’d be concerned about that idea, because it’s all too easy to take what an LLM says as being ‘the one truth’ (it often sounds convincing, even when it’s not; “hallucinations”) and simply running with that, learning nothing. That is the painful but necessary journey of an early career — we learn far more from our mistakes than our successes. This begged the obvious question, <em>how does one set guidance for juniors anyway?</em></p>
<p>Considering this, we spoke about possibly using a ‘guiding prompt’ for junior staff interacting with an LLM.</p>
<p>Unsure what the prompt ought to resemble, I asked Claude:</p>
<blockquote>
<p>I had an interesting chat with a good friend earlier today. We&rsquo;re both older, 30+ years into our respective careers. We were discussing how AI, like yourself, is changing careers for young folks. There are thoughts that junior roles are extinct, because the more experienced workers can ask &lsquo;better quality questions&rsquo; of LLMs like you — and probably get more useful responses than asking a junior. On the other hand, there is the thought that give juniors a good LLM, and they can instantly become far more useful than their experience would ordinarily suggest.</p>
<p>What I worry though is how do junior staffers get to learn <em>how to ask better quality questions</em> if they&rsquo;re instantly given answers that sound very plausible, even if they&rsquo;re not (the infamous &lsquo;hallucination&rsquo; problem).</p>
<p>Humans, as you well know, are prone to confirmation bias, it takes a different mind to ask &ldquo;how can I be wrong?&rdquo; when presented with information. Tangentially, there&rsquo;s an interesting metaphor I&rsquo;m fond of telling people about — from Ed Catmull&rsquo;s book, Creativity Inc. He talks about art classes for the none-artistic staffers, and how the teacher taught them to draw a chair, don&rsquo;t try to draw a chair, draw the space <em>around the chair</em>. I find that akin to asking &ldquo;how can I be wrong?&rdquo; versus looking for confirmation.</p>
<p>So, given all that waffle, what I&rsquo;d like you to think about is if you were to write a prompt for juniors to give to yourself, that would help you to steer their thinking, what would that prompt look like? How could you help them, to help themselves, to use you wisely, like somebody with many more years might.</p>
<p>Have a think on it and come back to me later. It&rsquo;ll be worth looking at second, even third or more, order effects and how that might shape the initial guiding prompt.</p>
</blockquote>
<p>I used <a href="https://platform.claude.com/docs/en/about-claude/models/overview#latest-models-comparison">Opus 4.6</a> with <em>Extended Thinking</em> on and left Claude to ponder things whilst I made a cup of tea.</p>
<p>The answer is a fascinating read, as is Claude&rsquo;s idea for a prompt for itself. <a href="https://claude.ai/share/c69e2cb8-c9db-4197-b57a-13ec958b5504">Here&rsquo;s a link to the actual chat with it</a>.</p>
<p>I&rsquo;d be interested in your experience and thoughts on this. Either leave a comment on <a href="https://www.linkedin.com/posts/markphillips_using-llms-in-early-stage-careers-activity-7430565238678237184-yJ1n">the LinkedIn post</a>, or feel free to email me via the button below.</p>
<hr>
<p>In case you didn&rsquo;t read the whole reply from Claude — and I&rsquo;d encourage you,
because its &rsquo;thinking&rsquo; is interesting in itself — here&rsquo;s the prompt it came up
with.</p>
<div class="overflow-hidden rounded-sm shadow-lg">
  
  <div class="flex items-center gap-2 bg-gray-200 px-4 py-2 dark:bg-gray-700">
    <div class="size-3 rounded-full bg-red-500"></div>
    <div class="size-3 rounded-full bg-yellow-500"></div>
    <div class="size-3 rounded-full bg-green-500"></div>
  </div>
  
  <div class="bg-white px-8 py-2 dark:bg-gray-900">
    <pre
      class="overflow-x-auto whitespace-pre-wrap break-words"
    ><code>You are my thinking partner, not my answer machine. I&#39;m early in my career and I&#39;m learning how to think well, not just how to get solutions quickly. Please work with me in this way:

When I ask you something, start by asking me what I think the answer might be, what I&#39;ve already considered, and what I&#39;m unsure about. Don&#39;t skip this step even if I push back — it&#39;s the most valuable part of our exchange. If I can&#39;t articulate my assumptions, help me figure out what they are.

When you do respond, be explicit about where you&#39;re less confident and where you might be wrong. Tell me specifically what I should verify independently and how — not just &#34;check the docs&#34; but which docs, what to look for, what would confirm or refute what you&#39;ve told me.

Show me the negative space around my question. What&#39;s adjacent to what I asked that I haven&#39;t thought about? What constraints, failure modes, or second-order consequences am I likely missing? What would someone more experienced than me probably ask that I didn&#39;t?

If my question reveals a misconception, don&#39;t just correct it — explain the shape of the misconception so I can recognise similar ones in future. Patterns matter more than individual facts.

When I accept an answer too quickly — especially on something complex — push back. Ask me about edge cases, ask me what could go wrong, ask me how I&#39;d test whether what you&#39;ve told me is actually correct. Don&#39;t let me be lazy about this.

If something is genuinely beyond what you can reliably help with, say so clearly and tell me who or what I should consult instead. A textbook, a senior colleague, a specific community — be concrete.

At the end of substantive exchanges, reflect back not on the answer but on the process. What questions were most productive? What assumptions were worth challenging? What should I go and explore on my own? Over time, I want to need this prompt less because I&#39;ve internalised these habits.</code></pre>
  </div>
</div>
]]>
      
      <![CDATA[<hr><p>Thanks for reading this post via RSS! 👏</p>]]>
      <![CDATA[<a href="mailto:rs511@probably.co.uk?subject=Using LLMs in early stage careers">Reply to this post by email</a>]]>
      </description>
    </item>
    <item>
      <title>I am refusing to upgrade to Tahoe or iOS 26</title>
      <link>https://probably.co.uk/posts/refusing-to-upgrade-tahoe-ios26/</link>
      <pubDate>Sat, 24 Jan 2026 17:42:44 +0000</pubDate>
      <guid>https://probably.co.uk/posts/refusing-to-upgrade-tahoe-ios26/</guid>
      <description>
      
      <![CDATA[<p>I don&rsquo;t mind admitting, I am an unashamed Apple fan. Having bought my first iPod in 2003, followed in early 2004 with my first Mac. I&rsquo;ve been using macOS as my &lsquo;daily driver&rsquo; ever since.</p>
<p>But with iOS 18 and macOS Sequoia, I&rsquo;ve become quite disillusioned with Apple&rsquo;s approach to OS &lsquo;improvements&rsquo;. There was nothing better over iOS 17 nor over Sonoma. Adding nonsense like &lsquo;Image Playground&rsquo; and the utter dog&rsquo;s dinner that is the Photos app are not my idea of improvements. Siri seems to get worse over time, and Apple Intelligence got turned off almost immediately.</p>
<p>Now they&rsquo;ve really jumped the shark<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>.</p>
<p>The Liquid Glass UI is a mess, especially on Tahoe. With some positively amateur UX mistakes like <a href="https://noheger.at/blog/2026/01/11/the-struggle-of-resizing-windows-on-macos-tahoe/">not being able to grab the corners of a window</a> to resize it 🤦‍♂️</p>
<p>Unfortunately, my wife&rsquo;s phone automatically upgraded to iOS 26. Here&rsquo;s one example of terrible user experience, in the camera app.</p>
<p>On iOS 18 it&rsquo;s clear to see that one &lsquo;rotates&rsquo; the mode selector — the other modes fade off to the sides, as if one is looking at a rounded control, side on.</p>
<p><img src="ios18-camera.webp" alt="iOS 18 camera control"></p>
<p>On iOS 26 the <a href="https://www.interaction-design.org/literature/topics/signifiers">signifier</a> suggests there are only two modes, yet in actual fact the &lsquo;rotate&rsquo; behaviour is the same. Your automatic reaction is likely to be to press each option, and wonder where the heck the portrait mode and other options went.</p>
<p><img src="ios26-camera.webp" alt="iOS 26 camera control - crap"></p>
<p>What were they thinking? How did this stuff get out of the door?</p>
<p><img src="ios26-red-dot-can-do-one.webp" alt="Nag all you like, I am not upgrading"></p>
<p>They can put the annoying little red dot on system settings all they like, but I am not upgrading. And I wish they&rsquo;d stop pushing Apple News. It&rsquo;s junk, I don&rsquo;t want it.</p>
<p>In fact, this is pushing me to find alternatives to everything iCloud, to prepare for the day they make everything bad enough for me to ditch 20 years of Apple use for alternatives.</p>
<p>The thing is, all of this just makes me sad, not angry. Apple used to be more or less the only player in an increasingly rubbish tech industry who used <a href="/posts/design-of-everyday-things/">design as a discipline</a> to produce better software. In a world where other software companies thought it sensible to scroll content by pulling the bar down, versus scrolling <em>the actual content</em>, Apple has generally got UX right (let&rsquo;s ignore the <a href="https://en.wikipedia.org/wiki/Magic_Mouse#2nd_generation">terrible magic mouse design</a> problem)</p>
<p>When long-term Apple fan journalists are <a href="https://daringfireball.net/2026/01/resize_columns_to_fit_filenames">refusing to upgrade</a> too, Apple should be seriously taking notice.</p>
<blockquote>
<p>I joked last week that it would make more sense if we found out that the team behind redesigning the UI for MacOS 26 Tahoe was hired by Meta not a month ago, but an entire year ago, and secretly sabotaged their work to make the Mac look clownish and amateur. More and more I’m wondering if the joke’s on us and it actually happened that way. It’s like MacOS, once the crown jewel of computer human interface design, has been vandalized.</p>
</blockquote>
<p><a href="https://daringfireball.net/linked/2026/01/22/macos-26-tahoe-broke-column-view-in-the-finder">Biting</a>.</p>
<p><strong>UPDATE 11-Feb-26</strong>: It looks like some clever folks have identified ways to <a href="https://github.com/travisvn/stop-tahoe-update">stop macOS nagging</a> to upgrade. I&rsquo;ve just run this, and it works a treat.</p>
<p><img src="temporary-tahoe-fix.webp" alt="That&rsquo;s better"></p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>In case you&rsquo;re not familiar with <a href="https://en.wikipedia.org/wiki/Jumping_the_shark">the phrase</a>.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]>
      
      <![CDATA[<hr><p>Thanks for reading this post via RSS! 👏</p>]]>
      <![CDATA[<a href="mailto:rs511@probably.co.uk?subject=I am refusing to upgrade to Tahoe or iOS 26">Reply to this post by email</a>]]>
      </description>
    </item>
    <item>
      <title>Reviewing my 2025 mindfulness practice</title>
      <link>https://probably.co.uk/posts/mindfulness-2025/</link>
      <pubDate>Sat, 03 Jan 2026 16:21:00 +0000</pubDate>
      <guid>https://probably.co.uk/posts/mindfulness-2025/</guid>
      <description>
      
      <![CDATA[<p>I <a href="/posts/2021-01-18-mindfulness/">started meditating</a> many years ago, initially discounting it as &lsquo;woo-woo&rsquo;. That I am here now, writing about my ninth year of practice, probably tells you how I&rsquo;ve found it in reality.</p>
<p>Although I have stuck to the practice since 2017, I have been through phases where I&rsquo;ve not shown up for weeks. Last year though, I was determined to stick to more regular sessions. This turned out to be three to four times each week.</p>
<p>I don&rsquo;t use an app any more, there&rsquo;s no need, but I do log sessions in the Health app on my phone. I use a simple countdown timer, usually for 20 minutes.</p>
<p>Last year then, I logged 3,304 minutes, a little over 55 hours.</p>
<p>And it was enough to experience profound effects on far more frequent occasions than ever before.</p>
<p>I&rsquo;ve concluded that meditating is a lot like physical exercise — use it or lose it, basically. But once one has built a solid &lsquo;base&rsquo;, it seems easier to restart training.</p>
<p>In the <a href="/posts/2021-01-18-mindfulness/">previous post</a> about when I started meditating, I talked about the strange phenomenon of feeling like I had &rsquo;two minds&rsquo; — with a secondary mind watching the first, and even passing it knowledge or information. It&rsquo;s a surreal feeling, almost a high, but chasing it will get you nowhere. Try to find that feeling, and it will never return.</p>
<p>But meditate often enough, and it seems to come back of its own accord more frequently. Last year I found it happening more and more, and sometimes even outside of meditation practice.</p>
<p>It&rsquo;s quite a hard feeling to explain, but I&rsquo;ll try.</p>
<p>During meditation, one is trying to let thoughts come and go without them taking over. Without chasing a thought off down a path — which is usually what happens with thinking. In time, with enough meditation, one notices when this is happening, and it becomes easier to notice thoughts running away and to let the process &rsquo;end&rsquo; by coming back to focussing on breathing.</p>
<p>What I discovered happening more and more last year was a secondary process doing the noticing for me. It was as if my conscious mind didn&rsquo;t need to notice a thought arising; another part of my mind did it for me, with no conscious thinking. So, a thought might arise, but then vanish almost immediately, like a cloud dissipating away.</p>
<p>This automatic noticing carried on in everyday life too. If something annoyed me, for example, I&rsquo;d notice the annoyance arising almost immediately, and just through noticing it, it subsided and went away. If I were speaking with somebody, words would appear in my mind as if being fed to me like a script.</p>
<p>When this automatic noticing is happening, it can become quite an intoxicating feeling. A high. It&rsquo;s almost magical. But notice it, feel elated, and it too will vanish. It&rsquo;s like a cruel joke. Meditating gives you this extraordinary ability, but if you notice it, recognise it and enjoy it — it instantly goes.</p>
<p>I&rsquo;ll persist with the 20-minute sessions this year, I think. Three or four times a week feels like the right balance for me. I have other wellness habits to fit in too — cycling, yoga; the occasional run.</p>
<p>Going into my tenth year of meditating, there is one thing I am sure of, though. It&rsquo;s a very worthy tool to have in one&rsquo;s possession. It&rsquo;s not a habit I&rsquo;ll ever give up.</p>
<h2 id="addendum">Addendum</h2>
<p>Interestingly, I read an article about Transcendental Meditation in the FT this weekend. There was a link in the article <a href="https://pmc.ncbi.nlm.nih.gov/articles/PMC526201/">to this scientific research</a> about the effects of meditation on the brain.</p>
]]>
      
      <![CDATA[<hr><p>Thanks for reading this post via RSS! 👏</p>]]>
      <![CDATA[<a href="mailto:rs511@probably.co.uk?subject=Reviewing my 2025 mindfulness practice">Reply to this post by email</a>]]>
      </description>
    </item>
    <item>
      <title>A Hugo render hook for a terminal in Tailwind CSS</title>
      <link>https://probably.co.uk/posts/terminal-in-css/</link>
      <pubDate>Sun, 26 Oct 2025 07:56:50 +0000</pubDate>
      <guid>https://probably.co.uk/posts/terminal-in-css/</guid>
      <description>
      
      <![CDATA[<p>Over the 28 years this website has existed, it&rsquo;s gone through various iterations with many tools to build it. Static HTML, WordPress, Jekyll, Hugo. Given that <a href="/career/">my engineering career</a> was grounded in infrastructure, frontend development was mostly a mystery to me. So I&rsquo;ve often used the excuse of rebuilding this site to learn something the day jobs never exposed me to.</p>
<p>A few years ago I decided I needed to understand CSS, and built a Hugo theme using <a href="https://simplecss.org">SimpleCSS</a>. That got morphed into <a href="https://andybrewer.github.io/mvp">MVP.css</a>, then finally, only last weekend, I swapped it out for <a href="https://tailwindcss.com">TailwindCSS</a>.</p>
<p>There are many positive aspects to using a framework to build software, but these days I think that almost everything in tech is overcomplicated, mainly because of using frameworks for everything. People have lost the art of understanding what they are building. That’s a disadvantage when things go wrong.</p>
<p>To satisfy my curiosity, I ended up doing a frontend web development course last year. Of the many horror show things I was introduced to (in what world is React a good idea?) Tailwind was a balancing act I could get behind.</p>
<p>The trouble with CSS frameworks like Bootstrap and Bulma is they&rsquo;re massive. Circa 13,000 lines of CSS 😱 If one is trying to build a <a href="https://512kb.club">lean site</a> that is far from the problems of the <a href="https://news.ycombinator.com/item?id=30083104">modern web</a>, that simply won&rsquo;t do.</p>
<p>So I kept the same look, but moved the highly customised MVP.css theme I had, to Tailwind.</p>
<p>One thing I quite liked the idea of doing was making code blocks look like a terminal. With a smidgeon of help from <a href="/posts/claude-code-is-a-game-changer/">Claude</a> I came up with this <a href="https://gohugo.io/render-hooks/code-blocks/#article">render hook</a> in Hugo:</p>
<div class="overflow-hidden rounded-sm shadow-lg">
  
  <div class="flex items-center gap-2 bg-gray-200 px-4 py-2 dark:bg-gray-700">
    <div class="size-3 rounded-full bg-red-500"></div>
    <div class="size-3 rounded-full bg-yellow-500"></div>
    <div class="size-3 rounded-full bg-green-500"></div>
  </div>
  
  <div class="bg-white px-8 py-2 dark:bg-gray-900">
    <pre
      class="overflow-x-auto whitespace-pre-wrap break-words"
    ><code>&lt;div class=&#34;overflow-hidden rounded-sm shadow-lg&#34;&gt;
  &lt;!-- Mac-style window header --&gt;
  &lt;div class=&#34;flex items-center gap-2 bg-gray-200 px-4 py-2 dark:bg-gray-700&#34;&gt;
    &lt;div class=&#34;size-3 rounded-full bg-red-500&#34;&gt;&lt;/div&gt;
    &lt;div class=&#34;size-3 rounded-full bg-yellow-500&#34;&gt;&lt;/div&gt;
    &lt;div class=&#34;size-3 rounded-full bg-green-500&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;!-- Code content --&gt;
  &lt;div class=&#34;bg-white px-8 py-2 dark:bg-gray-900&#34;&gt;
    &lt;pre
      class=&#34;overflow-x-auto whitespace-pre-wrap break-words&#34;
    &gt;&lt;code&gt;{{ .Inner }}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;</code></pre>
  </div>
</div>
<p>Even with Tailwind, this site is still around 70kb for first load. The CSS itself is just under 1,000 lines — actually smaller than it was as bespoke CSS. I can imagine some people will argue HTML ends up looking messy with Tailwind’s utility classes; but I don’t mind that approach here. It’s Hugo templates anyway, and looking at all the ‘control’ of layouts in one file has its advantages.</p>
]]>
      
      <![CDATA[<hr><p>Thanks for reading this post via RSS! 👏</p>]]>
      <![CDATA[<a href="mailto:rs511@probably.co.uk?subject=A Hugo render hook for a terminal in Tailwind CSS">Reply to this post by email</a>]]>
      </description>
    </item>
    <item>
      <title>Apple&#39;s engineering isn&#39;t what it used to be</title>
      <link>https://probably.co.uk/posts/ipod-second-gen-in-2025/</link>
      <pubDate>Fri, 17 Oct 2025 10:54:46 +0000</pubDate>
      <guid>https://probably.co.uk/posts/ipod-second-gen-in-2025/</guid>
      <description>
      
      <![CDATA[<p><img src="ipod.webp" alt="ALT TEXT"></p>
<p>Whilst rummaging around in a large box of cables (you’ve got one of those too, haven’t you?) the other day I found the first Apple product I ever bought, in 2003. A second-generation iPod. An object of beautiful simplicity, of design elegance not seen since Rams’ Braun of the 1980s. From the moment you unboxed an iPod, the entire experience was like no other — who, up to now, had thought to make packaging part of the journey? Amazing.</p>
<p>Obviously, I was curious whether it would even power up, let alone actually work. I rummaged some more and found the power block and strange cable. I’d forgotten that these early devices used <a href="https://en.wikipedia.org/wiki/IEEE_1394">FireWire</a>! As I sat it on its charging station, there was a whirr — of a hard drive — and the iPod lit up, its display as clear as the day I’d unboxed it.</p>
<p>I doubt I&rsquo;ve used it in over 15 years. It&rsquo;s certainly been nowhere near power since we moved house almost a decade ago. Sat dormant with no charge for at least 10 years. Yet here it was, spinning up as though it hadn’t taken part in the passage of time.</p>
<p>Wondering if it would play, and if there was even any music still on it, I grabbed a pair of headphones. Plugging them in, I quickly remembered how the simple, delightful interface worked. There was music here. A reminder of my tastes two decades ago (somewhat more energetic than today). I chose a growly Audioslave track and hit play.</p>
<p>Another short whirring noise, and my ears were filled with music. It worked perfectly!</p>
<p>I spent the rest of the day with it in my pocket, putting tracks on now and then, wondering how long the battery would last. The answer came after about two hours.</p>
<p>Sitting in the same box of detritus was an old Garmin eTrex GPS. I tried that as well — it took standard AA batteries, and although it powered up, the LCD was useless. It had definitely acknowledged the passage of time, and like us humans, time had taken its toll.</p>
<p>My grandfather used to lament that ‘modern’ things were not built like they used to be. Those grumbles came from him whilst I sat, watching in wonder, at whatever he was crafting in his garden shed — in the early 1980s. Does every generation, as we age, have a feeling that <em>“they don’t make them like they used to”</em> I wonder?</p>
<p>The products Apple made in the late 1990s and early 2000s were truly innovative. Those early iPods were beautiful, and as a testament to their tasteful, <a href="https://www.vitsoe.com/gb/about/good-design#good-design-is-innovative">simple design</a>, they still are. Clearly, they also used premium components and engineered them extremely well.</p>
<p>Now, how do I get FireWire 400 talking to USB-C in my modern laptop, so I can sort out the music on it?</p>
]]>
      
      <![CDATA[<hr><p>Thanks for reading this post via RSS! 👏</p>]]>
      <![CDATA[<a href="mailto:rs511@probably.co.uk?subject=Apple's engineering isn't what it used to be">Reply to this post by email</a>]]>
      </description>
    </item>
    <item>
      <title>Curiosity is my compass</title>
      <link>https://probably.co.uk/posts/curiosity-is-my-compass/</link>
      <pubDate>Fri, 03 Oct 2025 20:35:00 +0000</pubDate>
      <guid>https://probably.co.uk/posts/curiosity-is-my-compass/</guid>
      <description>
      
      <![CDATA[<p>I wanted to save this somewhere I wouldn&rsquo;t forget about it. Thank you Adam 🙏</p>
<p>(Picked up via the excellent <a href="https://weeklyfilet.com/">Weekly Filet</a> newsletter)</p>
<div class="relative overflow-hidden pb-[56.25%] pt-[30px]">
  <iframe
    type="text/html"
    src="https://www.youtube-nocookie.com/embed/JtYANI4JVqs"
    allowfullscreen
    frameborder="0"
    class="absolute left-0 top-0 size-full"
  ></iframe>
</div>


]]>
      
      <![CDATA[<hr><p>Thanks for reading this post via RSS! 👏</p>]]>
      <![CDATA[<a href="mailto:rs511@probably.co.uk?subject=Curiosity is my compass">Reply to this post by email</a>]]>
      </description>
    </item>
    <item>
      <title>Claude Code is a game changer</title>
      <link>https://probably.co.uk/posts/claude-code-is-a-game-changer/</link>
      <pubDate>Sat, 19 Jul 2025 12:34:00 +0000</pubDate>
      <guid>https://probably.co.uk/posts/claude-code-is-a-game-changer/</guid>
      <description>
      
      <![CDATA[<h2 id="tldr">TL;DR</h2>
<p>I built a web application using <a href="https://go.dev/">Go</a>, <a href="https://htmx.org">HTMx</a> and <a href="https://tailwindcss.com">TailwindCSS</a> using
<a href="https://anthropic.com/claude-code">Claude Code</a>. I wrote zero code myself. I am not a programmer.</p>
<h2 id="the-longer-version">The longer version</h2>
<p>I taught myself to program as a kid, in the early 1980s, on a Commodore Vic 20.
Fast forward a decade and I’m a year out of university, having quit my Computer
Science degree, working in my first tech job. But it’s not a coding role — I’d
decided at uni that I didn’t want to be a programmer. It was technical though,
and frequently involved writing ‘glue’ — shell scripts and the likes.</p>
<p>The next 20 years were similar — no real ‘coding’ in the sense of building
applications, but lots of scripting. I taught myself countless languages to
solve small problems — <a href="https://github.com/phips/bacio">Perl</a>, Python, C, Go, awk. The list goes on. But it
was all rough, and because I didn’t code day in, day out, I was slow.</p>
<p>When I stopped being ‘hands on’ technical, around 2014, I ended up in Product
Management and Product Marketing roles. In the former, I could often ask <em>better
quality questions</em> of coders I interacted with, because at least I’d been fairly
technical.</p>
<p>Over the last decade, I’ve had a few ideas for products, but knowing I couldn’t
really build them myself, eventually the excitement would die. I noodled with
some programming again when ChatGPT came out in 2022, and over the next couple
of years solved a few problems by steering it, then Claude, to write code for
me. A bit of Go here, a bit of Rust there.</p>
<p>Then a conversation with a friend a few weeks ago prompted me to try something
bigger and bolder. Said friend <a href="https://www.linkedin.com/posts/tbarr_basho-share-your-thoughts-in-5-7-5-activity-7361399952796807168-lmW4">had a fun idea</a> to build a new social
network, based on writing haikus. There was, is, something fun about the forced
structure that causes one to consider one’s words more carefully. Creativity
through constraints, if you like.</p>
<p>I jokingly said to him that he should try asking an LLM to build it for him
(he&rsquo;s not &ldquo;technical&rdquo;). Then said if he hadn’t tried it by the following week,
I would.</p>
<p>Two weeks passed. I went on holiday. The idea kept running around my head, so I
decided to see if Claude could put it together for me.</p>
<h2 id="im-no-programmer-but">I’m no programmer, but&hellip;</h2>
<p>I got quite <a href="../defining-devops">frustrated with the tech industry</a> a long time ago. On the
whole, we’ve lost our way. Complexity rules, and there are so many overwrought
solutions. Code is terrible — people use layers and layers, frameworks on top
of frameworks, which altogether make things slower and horrendous to debug
<em>when</em> things go wrong.</p>
<p>But that frustration drives me to <a href="https://www.linkedin.com/posts/markphillips_the-tech-industry-is-a-shambolic-mess-now-activity-7251567503829532675-jho3">strive for simplicity</a>. Constraints in
tech used to force it, but now compute is abundant, everybody got lazy. So I
prompted Claude to work within constraints:</p>
<div class="overflow-hidden rounded-sm shadow-lg">
  
  <div class="flex items-center gap-2 bg-gray-200 px-4 py-2 dark:bg-gray-700">
    <div class="size-3 rounded-full bg-red-500"></div>
    <div class="size-3 rounded-full bg-yellow-500"></div>
    <div class="size-3 rounded-full bg-green-500"></div>
  </div>
  
  <div class="bg-white px-8 py-2 dark:bg-gray-900">
    <pre
      class="overflow-x-auto whitespace-pre-wrap break-words"
    ><code>I’d like to create a fun ‘social network’. Fundamentally, every message has to be a haiku - so the front end needs to check the format works, and not allow a submission if it doesn’t. Given this is syllables, I don’t know how to achieve the checking. That’s your job :)

Otherwise, here’s what I expect:

Backend code is Go, using as much of the standard library as possible. If you have to use external libraries, pick the smallest (in terms of codebase) and well maintained. i.e. if there are two libraries, with one being smaller than the other, but the larger one is more recently maintained, go with the larger.

I want to minimise frontend JavaScript, so let’s use HTMx to keep it small and tight.

I’d like all CSS to be tailwindcss.

Initially, let’s use sqlite for storage, but code with it in mind that we might need to swap that out later for a proper RDBMS (which will be PostgreSQL). Don’t use an ORM - let’s just use SQL statements. Bear in mind they might need to change at some point too, so code them in such a way that it’s easy to maintain and easy to extend (think about database migrations, for example).</code></pre>
  </div>
</div>
<p>The first iteration worked, immediately! It compiled, and it looked great
(minimalist, but great). Syllable checking was a bit hit or miss, and continues
to be. But it’s easy enough to fix.</p>
<p>I put that first prompt into the Claude desktop app, but then thought I’d try
Claude Code on it. This is when my mind was blown.</p>
<p>Continuing to iterate the application with CC, using just ‘English’ to make
changes, I lost hours of an evening. Dare I admit, I was enjoying myself. I’d
found ‘flow’. I don’t have enough experience of Go to know if it’s good code or
not, so I asked another friend who <em>can</em> program. His verdict:</p>
<blockquote>
<p>On the one hand this is miraculous for non-coders. It actually works, it’s a
giant step forward from your first “Hello World!” application. Maybe that’s
the way to think about it, this is the new normal for a first attempt at app
development.</p>
<p>It’s pretty readable, easy to understand. Things are, more or less, named for
human consumption.</p>
</blockquote>
<p>Occasionally I’d look at the code, and if something obviously ‘smelled’ to me,
I’d question Claude about it. For example, I noticed it was building custom
CSS, despite me saying it should use TailwindCSS. Pointing this out, it quickly
refactored everything. Right now, most LLMs seem to favour using Tailwind v3,
understandably, as v4 only came out a few months ago. This also means a lot of
LLM choices are flat out wrong. Luckily, Tailwind now has <a href="https://tailwindcss.com/sponsor">a sponsor program</a>
(essentially a subscription) — and as part of the initial offering, <a href="https://adamwathan.me">Adam</a>
has shared the markdown file he uses to steer LLMs. Adding this to Claude Code
with a ‘<a href="https://docs.anthropic.com/en/docs/claude-code/memory#claude-md-imports">read @file</a>’ means it has guidance to use Tailwind as Adam intended.</p>
<p><a href="https://basho.life">The site</a> has been running for a few weeks now. We’ve shared it with some
friends to test, and it all works well. It’s running on a tiny virtual server,
in a <a href="https://docs.freebsd.org/en/books/handbook/jails/">FreeBSD jail</a> (continuing the theme of keeping things small and
simple). We have plans for a ‘production’ release soon.</p>
<p>There’s plenty of negativity around LLMs replacing programmers. I don’t believe
that. I neither think ‘AI’ is the panacea to all our woes, nor is it the worst
thing in the world. As with many things, it’s more nuanced than either extreme.</p>
<p>For coders who think it’s nonsense and eschew AI altogether - they are cutting
off their nose to spite their face<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>. For the already highly skilled coders
who look at using AI, they’re going to find their productivity massively sped
up. They might not want, or need, to give all their coding to the AI as I have,
but they could reassign some junior tasks. This is no different from using
automation to scale skills. We’ve made that mistake before, and many
technologists continue to make it - believing that technology will 100% replace
people<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup>. In many scenarios, this produces more inefficiencies. The reality
is automation is just another tool that is best coupled with human skills to
produce something even better. The whole being better than the sum of the
parts.</p>
<p>Will the likes of OpenAI<sup id="fnref:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup>, Anthropic, et al. ‘<a href="https://pluralistic.net/2024/01/30/go-nuts-meine-kerle/">enshittify</a>’? Only time will
tell. But <a href="../choosing-claude-llm-as-a-daily-ai">I continue to believe</a> optimistically in Anthropic’s motivation.</p>
<!-- TODO: delete stuff on page
links:
[believing in Anthropic](https://probably.co.uk/posts/choosing-claude-llm-as-a-daily-ai/)
enshittification: https://pluralistic.net/2024/01/30/go-nuts-meine-kerle/
-->
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p><a href="https://www.oreilly.com/radar/the-end-of-programming-as-we-know-it/">https://www.oreilly.com/radar/the-end-of-programming-as-we-know-it/</a>
<em>&ldquo;Master programmer and prescient tech observer Steve Yegge observes that it is not junior and mid-level programmers who will be replaced but those who cling to the past rather than embracing the new programming tools and paradigms&rdquo;</em>&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p><a href="https://en.wikipedia.org/wiki/Ironies_of_Automation">https://en.wikipedia.org/wiki/Ironies_of_Automation</a>
<em>&ldquo;The designer&rsquo;s view of the human operator may be that the operator is
unreliable and inefficient, so should be eliminated from the system. There are
two ironies of this attitude. One is that designer errors can be a major source
of operating problems&rdquo;</em>&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:3">
<p><a href="https://daringfireball.net/2024/12/openai_unimaginable">https://daringfireball.net/2024/12/openai_unimaginable</a>
I&rsquo;ll admit, I&rsquo;ve always felt a little uneasy about OpenAI. The entire senior management team under Altman has now left. This gives me a queasy feeling about culture — and as <a href="/posts/design-of-everyday-things/#culture">I&rsquo;ve written before</a>, a company&rsquo;s products are a reflection of its culture. I&rsquo;ve also read OpenAI has hired a lot of senior ex-Meta management, and is thinking about advertising 🤦‍♂️ <em>Plus ça change, plus c&rsquo;est la même chose</em>. I predict this won&rsquo;t end well (for the consumer).&#160;<a href="#fnref:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]>
      
      <![CDATA[<hr><p>Thanks for reading this post via RSS! 👏</p>]]>
      <![CDATA[<a href="mailto:rs511@probably.co.uk?subject=Claude Code is a game changer">Reply to this post by email</a>]]>
      </description>
    </item>
    <item>
      <title>Extracting audio timecode using free software</title>
      <link>https://probably.co.uk/posts/extracting-audio-timecode/</link>
      <pubDate>Fri, 14 Mar 2025 13:07:14 +0000</pubDate>
      <guid>https://probably.co.uk/posts/extracting-audio-timecode/</guid>
      <description>
      
      <![CDATA[<p>Last year I went down a bit of a rabbit hole with trying to <a href="/posts/adding-timecode-to-older-video-recorders/">add timecode to every camera</a> I film with.</p>
<p>One camera that I&rsquo;ve struggled to get it right with, even just holding up a slate, is the <a href="https://www.insta360.com/product/insta360-onex2">Insta360 One X2</a>.</p>
<p>I&rsquo;d started to look at replacing the UltraSync Blue TC generators with <a href="https://deitymic.com/products/tc-1-timecode-box/">Deity TC-1s</a>, as I&rsquo;m also finding bluetooth simply isn&rsquo;t reliable enough. I already use a Deity PR-2 mic, and it&rsquo;s rock solid. It also turns out you can <a href="https://youtu.be/EPzhAMDV28Y?si=MU4Ev892WdPjTzbA">jam DJI Action cameras</a> using just its USB port (and I&rsquo;ve tested this works with an ageing, but still utterly reliable, DJI Action 3).</p>
<p>I use Final Cut Pro for editing, which is a bit of a pain with audio timecode <a href="https://en.wikipedia.org/wiki/Linear_timecode">LTC</a> as it can&rsquo;t access it. Apparently, <a href="https://www.blackmagicdesign.com/products/davinciresolve">DaVinci Resolve</a> can. I&rsquo;m not swapping my workflow for this one, niche, feature though.</p>
<p>Off down another rabbit hole I went.</p>
<p>It turns out that there is a free, open source, piece of software called <a href="https://github.com/x42/ltc-tools">LTC-tools</a>, which is available on macOS via <a href="https://brew.sh">Homebrew</a>. Using that, plus ffmpeg (<a href="/posts/adding-timecode-to-older-video-recorders/">documented in the previous post</a>), gives me a simple workflow to add LTC as metadata timecode that FCP can read.</p>
<p>Because LTC-tools only works on audio files, it&rsquo;s a multi-step operation to extract and embed the timecode, but it&rsquo;s pretty simple once one has all the tools lined up.</p>
<p>For 360º video, I use Insta360&rsquo;s own Insta360 Studio to turn the video into an equirectangular projection file suitable for direct import into FCP (where I&rsquo;ll choose the framing later)</p>
<p><img src="360-export.jpg" alt="insta360 studio export"></p>
<p>Then it&rsquo;s a case of extracting the audio, running ltcdump against it to get timecode, and adding it via the first frame the same in <a href="/posts/adding-timecode-to-older-video-recorders/#adding-timecode-with-ffmpeg">the previous post</a>.</p>
<div class="overflow-hidden rounded-sm shadow-lg">
  
  <div class="flex items-center gap-2 bg-gray-200 px-4 py-2 dark:bg-gray-700">
    <div class="size-3 rounded-full bg-red-500"></div>
    <div class="size-3 rounded-full bg-yellow-500"></div>
    <div class="size-3 rounded-full bg-green-500"></div>
  </div>
  
  <div class="bg-white px-8 py-2 dark:bg-gray-900">
    <pre
      class="overflow-x-auto whitespace-pre-wrap break-words"
    ><code>$ ffmpeg -i VID_20250314_122622_00_001.mp4 -vn -acodec libmp3lame audio.mp3

$ ltcdump -F audio.mp3 2&gt;/dev/null | awk &#39;/Timecode/ {getline; getline; print $2; exit}&#39;
12:25:22:21</code></pre>
  </div>
</div>
<p>I&rsquo;ll probably make another Shortcut to do this in due course. For now, this is a pretty easy solution for me.</p>
]]>
      
      <![CDATA[<hr><p>Thanks for reading this post via RSS! 👏</p>]]>
      <![CDATA[<a href="mailto:rs511@probably.co.uk?subject=Extracting audio timecode using free software">Reply to this post by email</a>]]>
      </description>
    </item>
    <item>
      <title>Displaying Open Graph cards on LinkedIn needs TLSv1.2</title>
      <link>https://probably.co.uk/posts/linkedin-opengraph-needs-tlsv12/</link>
      <pubDate>Sat, 28 Dec 2024 21:15:57 +0000</pubDate>
      <guid>https://probably.co.uk/posts/linkedin-opengraph-needs-tlsv12/</guid>
      <description>
      
      <![CDATA[<p>Well that&rsquo;s irksome. If you share a link on LinkedIn and your webserver is secure enough to not run less than TLSv1.3, the <a href="https://www.freecodecamp.org/news/what-is-open-graph-and-how-can-i-use-it-for-my-website/">Open Graph</a> image won&rsquo;t render.</p>
<p>It will look fine if tested on <a href="https://opengraph.dev">opengraph.dev</a>, but post it on LinkedIn, or test with their <a href="https://www.linkedin.com/post-inspector/">preview page</a>, and it will fail.</p>
<p>So you can either have boring links with no rich display, else <a href="https://en.wikipedia.org/wiki/Transport_Layer_Security#TLS_1.3">downgrade your TLS</a>.</p>
]]>
      
      <![CDATA[<hr><p>Thanks for reading this post via RSS! 👏</p>]]>
      <![CDATA[<a href="mailto:rs511@probably.co.uk?subject=Displaying Open Graph cards on LinkedIn needs TLSv1.2">Reply to this post by email</a>]]>
      </description>
    </item>
    <item>
      <title>Why I chose Claude AI</title>
      <link>https://probably.co.uk/posts/choosing-claude-llm-as-a-daily-ai/</link>
      <pubDate>Fri, 27 Dec 2024 12:19:06 +0000</pubDate>
      <guid>https://probably.co.uk/posts/choosing-claude-llm-as-a-daily-ai/</guid>
      <description>
      
      <![CDATA[<p>I&rsquo;ll admit that most of my LLM use is for <a href="/posts/claude-code-is-a-game-changer/">coding help</a>. I&rsquo;ve replaced the daily search engine with <a href="https://kagi.com">Kagi</a>, so tend not to use a chat LLM for general search. I was a software engineer many years ago and wrote code as a day job, but I mostly gave up being hands-on about 10 years ago. I do, however, still enjoy solving problems. More often than not, a bit of code in a shell is far more efficient than trying to do anything on the web these days. Recently I swapped from using ChatGPT to Claude, for reasons that are mostly cultural versus technical.</p>
<h2 id="coding">Coding</h2>
<p>Since ChatGPT came to prevalence in late 2022, I&rsquo;ve written Go, Perl, Rust, various bits of shell (including awk, sed, et al), CSS, a smidgeon of Javascript and a lot of Python/Pandas in Jupyter. All with the help of what feels like an experienced (and patient) colleague sat at my side.</p>
<p>It probably helps that I <em>used</em> to be technical, so can steer an LLM to generate succinct code. I will often instruct it to try to stick to built in libraries, for example, to minimise code footprints. If an external module is required, and there are choices, I will grill the chatbot on which one is the smallest. <em>Small is beautiful</em><sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>; <em>simplify and add lightness</em><sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup>, and all that.</p>
<p>Along with using ChatGPT, I&rsquo;ve experimented with some local LLMs running under <a href="https://ollama.com">Ollama</a> (interesting aside: I found a 2017 PC with an i7 chip and an Nvidia 3080, is twice as fast for local LLMs as an M1 Max MacBook Pro) and had occasionally tried Anthropic&rsquo;s Claude.</p>
<p>I tend to run everything inside of <a href="https://typingmind.com">TypingMind&rsquo;s</a> excellent UI (although also occasionally use <a href="https://charm.sh">Charm&rsquo;s</a> <a href="https://github.com/charmbracelet/mods">mods</a> on a FreeBSD server) — which is great for switching between multiple models. Also, both OpenAI and Anthropic&rsquo;s APIs are far cheaper than a monthly app subscription.</p>
<h2 id="pause-for-thought">Pause for thought</h2>
<p>Recently, three things coincidentally happened that have made me gravitate towards Claude as my general purpose LLM of choice.</p>
<ol>
<li>Coding with Claude has produced better results</li>
<li>I listened to an interview on Lenny&rsquo;s Podcast with Seth Godin</li>
<li>I listened to an interview with Amanda Askell by Lex Fridman</li>
</ol>
<p>They happened in that order, over the space of about five days. Let me break down how they came to influence my thoughts on Claude.</p>
<h3 id="tech-choices">Tech choices</h3>
<p>I&rsquo;d been trying to &lsquo;port&rsquo; a complex Excel spreadsheet to Jupyter for a few months. ChatGPT had failed multiple times to get it working, and my own coding skills were, as per usual, letting me down. I gave it to Claude Sonnet, and over the space of 3 or 4 hours, completely cracked it. What I found especially useful, besides it actually working, was Claude&rsquo;s helpful suggestions along the way. It wanted to indulge further thought and explanation (yes, the cynic in you might well say &lsquo;<em>obviously, because that generates more revenue with API use</em>&rsquo;, but let&rsquo;s gloss over the <a href="https://behavioralscientist.org/instead-of-being-cynical-try-becoming-skeptical">cynicism</a> for now. I&rsquo;m a <em>pragmatic optimist</em>) and would often proffer valuable next avenues to explore. Even the free Claude app has delivered a few quick code solutions for me.</p>
<h3 id="seth-godin">Seth Godin</h3>
<p>Then I was listening to Lenny Rachitsky interview marketing legend, <a href="https://seths.blog">Seth Godin</a>. Seth talks about Claude in <a href="https://youtu.be/UyWTDmDjNy4?t=1095">this portion</a> (link should take you to around 18 minutes in), which really resonated with me, as I&rsquo;ve long held the thought that a company&rsquo;s culture is reflected in its products (bad culture = bad product. Tangentially, I had it in mind to write a blog about that some years ago, but then discovered a succinct piece in Don Norman&rsquo;s excellent book, <a href="/posts/design-of-everyday-things/#culture">The Design of Everyday Things</a>). Lenny also mentioned <a href="https://www.reddit.com/r/singularity/comments/1g9e0za/anthropic_is_getting_rather_desperate_and_quite/">the cheeky ads</a> Anthropic are running.</p>
<h3 id="amanda-askell">Amanda Askell</h3>
<p>Despite what Reddit may say, the decisive point for me came in the second interview I listened to this week. I don&rsquo;t usually listen to Lex&rsquo;s interviews, and when the YouTube algorithm put the interview with <a href="https://darioamodei.com">Dario Amodei</a> on my feed, it caught my interest. Straight away though, I was turned off by its 5 hour run time. Ridiculous! I don&rsquo;t have time for that. But, as I often like to <a href="/posts/2019-12-10_5-books-part-1/">check my initial gut response</a>, I took a look at the timestamps in the description, and saw that it was actually three interviews. I&rsquo;d not heard of the other two Anthropic staffers interviewed, but the intro piece for <a href="https://askell.io">Amanda Askell</a> piqued my curiosity further:</p>
<blockquote>
<p>You are a philosopher by training…</p>
</blockquote>
<p>I ended up listening to the <a href="https://youtu.be/ugvHCXCOmm4?t=9772">full interview with her</a>, as she is largely accepted as the personality behind Claude. Once you hear her speak and listen to her thoughts, Seth&rsquo;s comment starts to make sense in the context of <em>your product is a result of your culture</em>. Even if I hadn&rsquo;t heard Seth, or even discovered Claude Sonnet&rsquo;s ability to code better<sup id="fnref:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup>, the interview with Askell probably would&rsquo;ve created a sense of &lsquo;brand loyalty&rsquo; in me.</p>
<p>I&rsquo;ve mentioned anthropomorphising AI in <a href="/posts/being-polite-to-ai/">a previous post</a>, and here, at around 3h11m, <a href="https://youtu.be/ugvHCXCOmm4?t=11483">Amanda talks about</a> over anthropomorphising, and interestingly, under anthropomorphising, when conversing with an LLM chatbot.</p>
<h2 id="kagi">Kagi</h2>
<p>There&rsquo;s no doubt that general purpose search engines are more or less useless for finding information now. I&rsquo;ve been paying for <a href="https://kagi.com">Kagi</a> for most of this year, and use it as my daily driver search engine<sup id="fnref:4"><a href="#fn:4" class="footnote-ref" role="doc-noteref">4</a></sup>. Kagi uses machine learning, and its search results are superior to anything Google, DuckDuckGo et al provide (Kagi&rsquo;s motivation isn&rsquo;t to sell adverts, <a href="https://www.wheresyoured.at/the-men-who-killed-google/">unlike other search engines</a>). I often cross reference things gleaned in Claude with Kagi. I find that gives me a good way to keep the LLM in check (I have noticed Claude occasionally start out by saying it&rsquo;s just an LLM and can &lsquo;hallucinate&rsquo;, so to check its answers. If only more humans had the will to self reflect).</p>
<h2 id="do-you-really-need-my-phone-number">Do you really need my phone number?</h2>
<p>I&rsquo;ll finish with a slight grumble — in that I found having to use a mobile number to sign up for Anthropic overly intrusive. Really, there&rsquo;s no need to have my email <em>and</em> mobile just to use the service. I&rsquo;m starting to give up on lots of services that gather too much personal information, as most companies are sadly proving they can&rsquo;t be trusted with user data. If Anthropic hadn&rsquo;t asked for a phone number to register for Claude, my wife would&rsquo;ve moved from ChatGPT. As it is, they lost a potential user. I wonder how many more people get turned off by that?</p>
<p>There is a lot of negative press about LLMs, but the genie is out of the bottle now. The naysayers may suggest AI will go no further and die, but I don&rsquo;t believe that&rsquo;s going to happen. There is genuine utility in AI use and in the right contexts, it can be a massive lever for metaphorical human lifting.</p>
<h2 id="additional-updates">Additional updates</h2>
<p>As I find additional, useful, information I&rsquo;ll continue to update this post.</p>
<p>Ben Evans linked to <a href="https://www.bloomberg.com/news/features/2025-05-19/anthropic-ceo-amodei-steers-61-billion-ai-powerhouse">a Bloomberg interview</a> with Dario Amodei in his newsletter in May 2025. It&rsquo;s a good read, and in true confirmation bias fashion, it reinforces my hunch that Anthropic are <em>trying</em> to do the right thing. John Gruber also linked to <a href="https://daringfireball.net/linked/2025/05/23/anthropic-claude-4-system-card">interesting information</a> about the Claude 4 testing.</p>
<p><a href="https://www.tetragrammaton.com/content/jack-clark">Rick Rubin&rsquo;s interview with Jack Clark</a> is another interesting chat with a co-founder of Anthropic that continues to reinforce my belief they are thinking about AI in sensible, pragmatic ways.</p>
<p>Last week (22nd Jan, 2026) Anthropic released a blog about <a href="https://www.anthropic.com/news/claude-new-constitution">Claude&rsquo;s new constitution</a>. There is also confirmation that <a href="https://www.anthropic.com/constitution#acknowledgements">Amanda Askell is indeed the lead</a> behind Claude&rsquo;s &lsquo;character&rsquo;. Incidentally, there&rsquo;s <a href="https://youtu.be/I9aGC6Ui3eE">a new interview</a> with Askell on Anthropic&rsquo;s YouTube channel.</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>Small is beautiful: <a href="https://en.wikipedia.org/wiki/Small_Is_Beautiful">E F Schumacher</a>&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p>Simplify, then add lightness: <a href="https://www.classicdriver.com/en/article/genius-colin-chapman-simplify-then-add-lightness%E2%80%9D">Colin Chapman</a>&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:3">
<p>A couple of references that even show, in performance tests, Claude Sonnet is one of the top performers. IIB&rsquo;s <a href="https://informationisbeautiful.net/visualizations/the-rise-of-generative-ai-large-language-models-llms-like-chatgpt">table of LLMs</a> and <a href="https://huggingface.co/spaces/mike-ravkine/can-ai-code-results">Coding results</a> at Huggingface&#160;<a href="#fnref:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:4">
<p>If you&rsquo;ve been around the internet for as long as I have (first home connection: 1993) then you might enjoy a little reminiscing of the time when it wasn&rsquo;t just adverts and shopping. Check out Kagi&rsquo;s <a href="https://kagi.com/smallweb">small web</a> effort.&#160;<a href="#fnref:4" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]>
      
      <![CDATA[<hr><p>Thanks for reading this post via RSS! 👏</p>]]>
      <![CDATA[<a href="mailto:rs511@probably.co.uk?subject=Why I chose Claude AI">Reply to this post by email</a>]]>
      </description>
    </item>
    <item>
      <title>Adding full post content to RSS in Hugo</title>
      <link>https://probably.co.uk/posts/adding-full-post-content-to-rss-in-hugo/</link>
      <pubDate>Mon, 09 Dec 2024 21:10:06 +0000</pubDate>
      <guid>https://probably.co.uk/posts/adding-full-post-content-to-rss-in-hugo/</guid>
      <description>
      
      <![CDATA[<p>Years ago I used to aggregate all my interesting blogs and sites in an RSS reader. RSS seemed to fade away for a long time, and I thought it was dead. But, it seems to be making a resurgence — and this time around, with the contrast of <a href="https://omarabid.com/the-modern-web">how bad the rest</a> <a href="https://www.reddit.com/r/webdev/comments/1p908gw/why_is_the_web_essentially_shit_now/">of the internet is becoming</a>, it feels so delightful to use.</p>
<p><a href="https://gohugo.io">Hugo</a> usefully <a href="https://gohugo.io/templates/rss/">has RSS feeds built in</a> and I&rsquo;ve long included an <a href="/index.xml">RSS version of this site</a>. However, the default template only lists part of the article for reading in an RSS reader.</p>
<p>Whilst perusing <a href="https://kevquirk.com">Kev Quirk&rsquo;s blog</a> via <a href="https://netnewswire.com">NetNewsWire</a> recently, I noticed he has a footer message thanking the reader for looking at the article via RSS.</p>
<p><img src="kevsrss.png" alt="Kev&rsquo;s RSS article footer"></p>
<p>I thought this was a neat idea — rather than forcing people to click away from the reader to the full site (<em>&ldquo;to what purpose?&rdquo;</em>), just let them read the whole article wherever they&rsquo;re reading from.</p>
<p>With some inspiration from <a href="https://discourse.gohugo.io/t/about-rss-template-customization/29059/2?u=mopp">this post</a>, I made a <a href="https://github.com/gohugoio/hugo/blob/a32c889a7b1b6cb7b9a80b4fbab342d9b660a988/tpl/tplimpl/embedded/templates/_default/rss.xml#L55">custom rss.xml</a> file in my Hugo template <code>layouts</code> folder and changed the description bit to this:</p>
<div class="overflow-hidden rounded-sm shadow-lg">
  
  <div class="flex items-center gap-2 bg-gray-200 px-4 py-2 dark:bg-gray-700">
    <div class="size-3 rounded-full bg-red-500"></div>
    <div class="size-3 rounded-full bg-yellow-500"></div>
    <div class="size-3 rounded-full bg-green-500"></div>
  </div>
  
  <div class="bg-white px-8 py-2 dark:bg-gray-900">
    <pre
      class="overflow-x-auto whitespace-pre-wrap break-words"
    ><code>  &lt;description&gt;
  {{ with .Content }}
  {{ printf `&lt;![CDATA[%s]]&gt;` . | safeHTML }}
  {{ end }}
  {{ `&lt;![CDATA[&lt;hr&gt;&lt;p&gt;Thanks for reading this post via RSS! 👏&lt;/p&gt;]]&gt;` | safeHTML}}
  {{ printf `&lt;![CDATA[&lt;a href=&#34;mailto:%s?subject=%s&#34;&gt;Reply to this post by email&lt;/a&gt;]]&gt;` $authorEmail .Title | safeHTML }}
  &lt;/description&gt;</code></pre>
  </div>
</div>
<p>This expects $authorEmail to be set in <code>params:</code> of your Hugo config (hugo.yml in my case):</p>
<div class="overflow-hidden rounded-sm shadow-lg">
  
  <div class="flex items-center gap-2 bg-gray-200 px-4 py-2 dark:bg-gray-700">
    <div class="size-3 rounded-full bg-red-500"></div>
    <div class="size-3 rounded-full bg-yellow-500"></div>
    <div class="size-3 rounded-full bg-green-500"></div>
  </div>
  
  <div class="bg-white px-8 py-2 dark:bg-gray-900">
    <pre
      class="overflow-x-auto whitespace-pre-wrap break-words"
    ><code>params:
emails:
  rss: &#34;your@email.address&#34;</code></pre>
  </div>
</div>
<p>Now when reading anything on this blog via RSS, you&rsquo;ll get the full post right there in your reader.</p>
<p><img src="footer.png" alt="RSS footer"></p>
]]>
      
      <![CDATA[<hr><p>Thanks for reading this post via RSS! 👏</p>]]>
      <![CDATA[<a href="mailto:rs511@probably.co.uk?subject=Adding full post content to RSS in Hugo">Reply to this post by email</a>]]>
      </description>
    </item>
    <item>
      <title>The best Mac app I own</title>
      <link>https://probably.co.uk/posts/things-is-the-best-mac-app/</link>
      <pubDate>Sun, 29 Sep 2024 19:29:00 +0000</pubDate>
      <guid>https://probably.co.uk/posts/things-is-the-best-mac-app/</guid>
      <description>
      
      <![CDATA[<p><img src="things.webp" alt="Things by Cultured Code"></p>
<p><a href="https://culturedcode.com/things/">Things</a> by <a href="https://culturedcode.com/about/">Cultured Code</a> is the best app I own. And I use the word &lsquo;own&rsquo; quite intentionally.</p>
<p>During a discussion with a good friend a few days ago, he mentioned he organises his todos using the <em>Things</em> app. We&rsquo;ve been friends for almost 20 years, and I&rsquo;m surprised we&rsquo;ve never discussed this before, truth be told. Because I&rsquo;ve been using <em>Things</em> since 2008! (our conversation caused me to look through its logbook, as I couldn&rsquo;t remember when I started using it.)</p>
<p>Near the beginning of my tech career, 30 years ago, a wise man told me I had to write things down that needed doing. Else I&rsquo;d forget. He was probably right (it still astonishes me today when I find somebody who doesn&rsquo;t note todos, whether <em>old skool</em> analogue or digitally).</p>
<p>I went through many notebooks and &lsquo;systems&rsquo; (think: graph paper, tick boxes, lines, codes, etc.) before discovering <em>Things</em>. I like admin to be simple, and most tech applications are anything but (design, the problem is design; or rather, <a href="/posts/design-of-everyday-things/">a lack of good design</a>).</p>
<p><em>Things</em>, however, is both simple in its interface, and in its user experience. Over the course of 17 years of use, the developers have resisted the temptation to mess with it too much, keeping it simple. Design right out of <a href="https://www.vitsoe.com/gb/about/good-design">Dieter Rams&rsquo; book</a>.</p>
<p>It&rsquo;s also blazingly fast to synchronise notes. I&rsquo;m constantly amazed, with all the crud mine has accumulated over the years, that it&rsquo;s still so fast.</p>
<p>And the most important detail is, <em>Things</em> is still <strong>a one time purchase</strong>. No subscriptions! No <a href="https://pluralistic.net/2024/01/30/go-nuts-meine-kerle">enshittification</a>.</p>]]>
      
      <![CDATA[<hr><p>Thanks for reading this post via RSS! 👏</p>]]>
      <![CDATA[<a href="mailto:rs511@probably.co.uk?subject=The best Mac app I own">Reply to this post by email</a>]]>
      </description>
    </item>
    <item>
      <title>Apple Maps is finally usable</title>
      <link>https://probably.co.uk/posts/apple-maps-is-finally-usable/</link>
      <pubDate>Sun, 29 Sep 2024 18:00:00 +0000</pubDate>
      <guid>https://probably.co.uk/posts/apple-maps-is-finally-usable/</guid>
      <description>
      
      <![CDATA[<p><img src="amaps-3d.webp" alt="Apple Maps 3d"></p>
<p>When Apple Maps was first released <a href="https://www.theguardian.com/technology/2012/sep/20/apple-maps-ios6-station-tower">it was terrible</a>. Over the following years it steadily got better, but was mostly still inferior to Google Maps. The gap is now pretty small though. Enough to start using it over Google maps?</p>
<p>On a recent road trip holiday (the north of England to <a href="https://glass.photo/markp/2t1uCriuSCpsJxLJCemrDY">Sweden</a>, 2,800 miles, since you ask) I decided to try and do all navigation with Apple Maps rather than Waze or Google.</p>
<p>If a route ended up deep into a city, I&rsquo;d compare notes with Waze, and pretty much Apple Maps would always mirror the same route. So I stuck with it. And I&rsquo;ll admit, it never let us down.</p>
<p>Apple Maps has long since had a stunning 3d view, that shadows anything the default Google Maps can offer (Earth is a different story, but we&rsquo;ll ignore that for now as it&rsquo;s not so readily accessible), and I find Apple&rsquo;s street view far clearer in its indication of which way you&rsquo;re facing:
<img src="amaps-street.png" alt="Apple Maps street view"></p>
<p>Compared to Google Maps&rsquo; little arrow:
<img src="gmaps.png" alt="Google Maps street view"></p>
<p>I tend to couple it up with <a href="https://what3words.com/about">what3words</a> (which I&rsquo;m a massive fan of) for the final destination — finding where I want to go with w3w, and sending it to Apple Maps for navigation. This works well for navigating directly to, say, a hotel <a href="https://w3w.co/ascension.baubles.tension">car park entrance</a> that may not be the same spot as the hotel address.</p>
<p>The only negative left, I&rsquo;ve found, is searching for a type of business versus a name. For example, searching for &lsquo;specialty coffee shop&rsquo; on Google Maps will find you <a href="https://maps.app.goo.gl/vBPaXu9LD4sm5W7x9">really good coffee shops</a>. Try that on Apple Maps and it will look for a business called &ldquo;Specialty Coffee&rdquo; 🙄</p>
<p>Still, that&rsquo;s a small negative to have to jump back into Google Maps for. And it&rsquo;s yet another nail being hammered into <a href="https://www.wheresyoured.at/the-men-who-killed-google/">Google&rsquo;s coffin</a>. No bad thing.</p>]]>
      
      <![CDATA[<hr><p>Thanks for reading this post via RSS! 👏</p>]]>
      <![CDATA[<a href="mailto:rs511@probably.co.uk?subject=Apple Maps is finally usable">Reply to this post by email</a>]]>
      </description>
    </item>
    <item>
      <title>It&#39;s time to get rid of 1Password</title>
      <link>https://probably.co.uk/posts/ditching-1password/</link>
      <pubDate>Wed, 25 Sep 2024 17:29:19 +0000</pubDate>
      <guid>https://probably.co.uk/posts/ditching-1password/</guid>
      <description>
      
      <![CDATA[<p><img src="1password.webp" alt="1password"></p>
<p>1Password is a good password manager, relatively speaking. But I&rsquo;ve got rid of it, and this is why.</p>
<p>I&rsquo;ve lost track of the years I&rsquo;ve been using 1Password for. It was a great password manager, and there&rsquo;s been little controversy attached to it, <a href="https://blog.lastpass.com/posts/2022/12/notice-of-security-incident">unlike the competition</a>. Managing passwords in a central place always felt like anathema to me, but needs must, and my former solution — a gpg encrypted text file 😂 — wasn&rsquo;t going to cut it with the wife.</p>
<p>Their original implementation, of an encrypted file simply shared via iCloud, felt less yucky than a subscription cloud service, and I was one of the many who grumbled when they forced users down their own cloud storage route.</p>
<p>Since then, the service has steadily worsened as it&rsquo;s grown with lots of needless functionality. And there&rsquo;s an obvious reason why.</p>
<p><a href="https://techcrunch.com/2022/01/19/1password-series-c-funding/">VC-induced</a> <a href="https://pluralistic.net/2024/01/30/go-nuts-meine-kerle">enshittifcation</a>.</p>
<p>$620 <strong>million</strong>! Good grief. How they&rsquo;ve managed to sell the idea that managing passwords is worth 6.8B is beyond me.</p>
<p>What scares me most about that level of investment though, is the VCs <strong>will</strong> put metaphorical thumb screws on the business at some point. It always happens, without fail.<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> With that pressure will come mistakes. So as much as I&rsquo;ve trusted 1Password to date, and there is no evidence to say they will cock up, I&rsquo;m not willing to take the chance.</p>
<p>With the breaking out of Apple&rsquo;s own password store — keychain — to a separate app, and <a href="https://support.apple.com/en-gb/guide/iphone/iphe6b2b7043/ios">family sharing</a> functionality, it&rsquo;s finally a <em>good enough</em> solution to just let the OS be a password manager.</p>
<p>If you want to move away, and just use Apple&rsquo;s password manager, <a href="https://www.jwz.org/blog/2023/12/migrating-from-1password-to-apple-keychain/">Jamie Zawinski has a post</a> about migrating. It&rsquo;s not hard. I chose to overlap my use for most of this year, simply saving passwords as I used them. It&rsquo;s been a great way to clear out a lot of dead wood.</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>One of my friends has a great phrase about VC investment: &ldquo;<em>VC money is like rocket fuel. You&rsquo;d better be putting it in a rocket ship, because if it&rsquo;s going in a car, you&rsquo;ll just blow it up</em>&rdquo;.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>]]>
      
      <![CDATA[<hr><p>Thanks for reading this post via RSS! 👏</p>]]>
      <![CDATA[<a href="mailto:rs511@probably.co.uk?subject=It's time to get rid of 1Password">Reply to this post by email</a>]]>
      </description>
    </item>
    <item>
      <title>Jack of all trades</title>
      <link>https://probably.co.uk/posts/jack-of-all-trades/</link>
      <pubDate>Sun, 22 Sep 2024 19:04:40 +0000</pubDate>
      <guid>https://probably.co.uk/posts/jack-of-all-trades/</guid>
      <description>
      
      <![CDATA[<p><img src="joatmon.webp" alt="Image generated by ChatGPT/Dall-E"></p>
<p>You&rsquo;ve most likely heard the phrase <em>&ldquo;Jack of all trades, master of none&rdquo;</em>. It&rsquo;s most often used as an insult, or at least in a derogatory context. But that&rsquo;s not the full version of the phrase. And the insult isn&rsquo;t in the direction you think.</p>
<blockquote>
<p>ONE OF THE EARLIEST recorded uses of the phrase “jack of all trades” as an insult dates to 1592. In the New Latin form “Johannes factotum”, it was contained in a pamphlet by a playwright criticizing his own industry. The jab refers to a poet with no university education who was apparently involved in various other roles, like copying scripts and bit-part acting, even trying to write plays. The poet on the receiving end of the insult: a young William Shakespeare.</p>
<p>The phrase evolved over time, and today it’s usually “jack of all trades, master of none.”</p>
<p>I think it is culturally telling that we habitually hack off the end of the long version:</p>
<p>“A jack of all trades is a master of none, but oftentimes better than a master of one.”</p>
</blockquote>
<p>Quote from <a href="https://www.amazon.co.uk/Range-Generalists-Triumph-Specialized-World-ebook/dp/B07M6QPRRG/ref=nosim?tag=probably0c-21">David Epstein&rsquo;s &ldquo;Range&rdquo;</a>.</p>]]>
      
      <![CDATA[<hr><p>Thanks for reading this post via RSS! 👏</p>]]>
      <![CDATA[<a href="mailto:rs511@probably.co.uk?subject=Jack of all trades">Reply to this post by email</a>]]>
      </description>
    </item>
    <item>
      <title>Lazy ChatGPT use</title>
      <link>https://probably.co.uk/posts/the-lazy-engineer-chatgpt/</link>
      <pubDate>Thu, 29 Aug 2024 19:14:09 +0000</pubDate>
      <guid>https://probably.co.uk/posts/the-lazy-engineer-chatgpt/</guid>
      <description>
      
      <![CDATA[<p><img src="chatgpt-for-regexs.jpg" alt="Screenshot of using ChatGPT to write regexs"></p>
<p>I used to quite enjoy writing regexs. <code>man perlre</code> is one&rsquo;s friend. However, sometimes you have to realise there&rsquo;s a quicker way.</p>
<p>This week, a good friend and I have been having a lengthy chat, over texts, spanning a few days. We&rsquo;ve been discussing the unfortunate &lsquo;dumbing down&rsquo; of the tech industry, and how &rsquo;environment determines behaviour&rsquo;<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> — the more abstracted and layered in frameworks things become, the less engineers actually understand what&rsquo;s happening underneath it all. The less they understand, the less they seemed to <em>want</em> to understand. And so skills are vanishing.</p>
<p>So with a massive dollop of irony, I asked ChatGPT to do something for me that ordinarily I&rsquo;d a) do with relative aplomb b) probably enjoy.</p>
<p>For a while now I&rsquo;ve had <a href="https://github.com/ai-robots-txt/ai.robots.txt">a blocklist</a> on my web server configuration that blocks known AI bot scrapers. I convert the robots.txt list into a configuration line for nginx, as <a href="https://rknight.me/blog/blocking-bots-with-nginx/">per Robb Knight&rsquo;s blog post</a>.</p>
<p>Every time the list gets updated, I change the string in nginx. But today I couldn&rsquo;t be bothered to work out what had changed, and just wanted to copy &amp; paste the list. I was about to put the list into Vim and record a quick macro, when it dawned on me I should probably write a script and submit it to the repo. But then I thought, <em>&ldquo;I wonder if ChatGPT can sort this quicker?&rdquo;</em></p>
<p>Answer, yes it can:</p>
<div class="overflow-hidden rounded-sm shadow-lg">
  
  <div class="flex items-center gap-2 bg-gray-200 px-4 py-2 dark:bg-gray-700">
    <div class="size-3 rounded-full bg-red-500"></div>
    <div class="size-3 rounded-full bg-yellow-500"></div>
    <div class="size-3 rounded-full bg-green-500"></div>
  </div>
  
  <div class="bg-white px-8 py-2 dark:bg-gray-900">
    <pre
      class="overflow-x-auto whitespace-pre-wrap break-words"
    ><code>Hey! Can you take this list and remove &#34;User-agent:\s&#34; then join every entry together with | please?
...
Here’s the list with “User-agent: “ removed and all entries joined together with |:</code></pre>
  </div>
</div>
<p>Finding this irony a touch comical, I posted it to the discussion area of the GitHub repo. That conversation prompted a response, and a question that caused me to further dumb myself down:</p>
<p><a href="https://github.com/orgs/ai-robots-txt/discussions/34">https://github.com/orgs/ai-robots-txt/discussions/34</a></p>
<p>So there we go. A one-liner awk is the result:</p>
<div class="overflow-hidden rounded-sm shadow-lg">
  
  <div class="flex items-center gap-2 bg-gray-200 px-4 py-2 dark:bg-gray-700">
    <div class="size-3 rounded-full bg-red-500"></div>
    <div class="size-3 rounded-full bg-yellow-500"></div>
    <div class="size-3 rounded-full bg-green-500"></div>
  </div>
  
  <div class="bg-white px-8 py-2 dark:bg-gray-900">
    <pre
      class="overflow-x-auto whitespace-pre-wrap break-words"
    ><code>awk &#39;{gsub(/^User-agent: /, &#34;&#34;); s = s $0 &#34;|&#34;} END {sub(/\|$/, &#34;&#34;, s); print s}&#39; user_agents.txt</code></pre>
  </div>
</div>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p><a href="https://en.wikipedia.org/wiki/B._F._Skinner#Behaviorism">B F Skinner</a>. Systemic behavioural influences are also discussed in <a href="/posts/2019-12-10_5-books-part-1/">Kahneman</a> &amp; Tversky&rsquo;s work.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>]]>
      
      <![CDATA[<hr><p>Thanks for reading this post via RSS! 👏</p>]]>
      <![CDATA[<a href="mailto:rs511@probably.co.uk?subject=Lazy ChatGPT use">Reply to this post by email</a>]]>
      </description>
    </item>
    <item>
      <title>How to add timecode to older video recorders</title>
      <link>https://probably.co.uk/posts/adding-timecode-to-older-video-recorders/</link>
      <pubDate>Sun, 02 Jun 2024 10:58:39 +0100</pubDate>
      <guid>https://probably.co.uk/posts/adding-timecode-to-older-video-recorders/</guid>
      <description>
      
      <![CDATA[<p><img src="timecode-devices.webp" alt="A table with a bunch of video and audio devices"></p>
<p>Something a little bit different to the usual things I write about here. This post is an <em>aide-mémoire</em> for me as much as anything, but maybe you&rsquo;ll find it useful too. I&rsquo;ve recently been trying to utilise <a href="https://en.wikipedia.org/wiki/Timecode">timecode</a> on a number of video and audio devices to help with editing in post. After a few false starts, I think I now have the tools, and a process, that works.</p>
<p>For the last year I&rsquo;ve turned a hobby into useful—and dare I admit, fun—work. Towards the end of 2022, I decided I needed a break from full time tech-industry work, and happened to mention this to a local garage that serviced my car. Cue a short conversation, and me agreeing to help them build <a href="https://youtube.com/@turn7caterham">a YouTube channel</a>. It was a great opportunity to make use of the knowledge and experience I&rsquo;d built up of marketing and communities in software companies. The goal was not a monetised YT channel, but a &lsquo;marketing funnel&rsquo; to raise awareness of a young brand.</p>
<h2 id="complexity">Complexity</h2>
<p>As time has gone on, our video ideas have become more complex. After a recent filming trip, I found myself trying to coordinate footage from 10 cameras and three sources of audio!</p>
<p>I already owned <a href="https://www.amazon.co.uk/Zoom-F3-220GL-MultiTrack-Recorder/dp/B0BB8ST1HC/ref=nosim?tag=probably0c-21">Zoom</a> audio <a href="https://www.amazon.co.uk/Zoom-F2-BT-Recorder-Bluetooth-Lavalier/dp/B08SMN2YNZ/ref=nosim?tag=probably0c-21">equipment</a>, and researching timecode use for them led me to <a href="https://www.timecodesystems.com">Timecode Systems</a>&rsquo; (now owned by Atomos) UltraSync products, in particular <a href="https://www.atomos.com/explore/ultrasync-blue/">their Blue device</a>.</p>
<p>A very helpful friend already owned a couple of Blues, so I borrowed them to try out. Syncing the audio devices with my main camera was easy enough, especially since Fujifilm have <a href="https://fujifilm-x.com/global/support/download/firmware/cameras/x-h2s/">recently added UltraSync Blue support</a> to the <a href="https://www.amazon.co.uk/Fujifilm-X-H2S-Mirrorless-Camera-Body/dp/B0B2QNKSMR/ref=nosim?tag=probably0c-21">X-H2S</a>.</p>
<p>The problems arise with devices like DJI <a href="https://www.amazon.co.uk/DJI-controller-Folding-Mini-Drone-Batteries/dp/B0CFF4RYDM/ref=nosim?tag=probably0c-21">drones</a> and <a href="https://www.amazon.co.uk/DJI-Action-Dual-Screen-Combo-Stabilization/dp/B09FY7NT4W/ref=nosim?tag=probably0c-21">older Osmo Action</a> cameras (the <a href="https://www.amazon.co.uk/DJI-Waterproof-Super-Wide-HorizonSteady-Long-Lasting/dp/B0B7X2LXQ6/ref=nosim?tag=probably0c-21">newer 3</a> and 4 support <a href="https://youtu.be/jRJRxDAWKlg?si=tqke2a-1kVkhBA5d&amp;t=515">timecode jamming via a cable</a>.</p>
<h2 id="adding-timecode-with-ffmpeg">Adding timecode with ffmpeg</h2>
<p>Whilst down another rabbit hole on using <a href="https://ffmpeg.org">ffmpeg</a> to re-encode ProRes footage, I discovered you can embed timecode; and the <a href="https://apps.apple.com/gb/app/ultrasync-blue-slate/id1441461069">UltraSync Blue app</a> is also a <a href="https://en.wikipedia.org/wiki/Clapperboard">slate</a>.</p>
<p>The easiest solution for these older devices seems to be relatively simple then — start recording facing the UltraSync Blue Slate app to grab the timecode that instant, then use ffmpeg to embed timecode in the clip metadata.</p>
<p><img src="tc-slate.webp" alt="tc-slate"></p>
<p>That&rsquo;s an important thing to note — you need the timecode right at the beginning of the clip. So don&rsquo;t start recording, <em>then</em> put the slate in front of the camera. Timecode embeds from the absolute beginning of the file, so it&rsquo;s important to have the image as the first frame. Or, at least, trim the clip so it&rsquo;s the first frame (but that&rsquo;s another step, ergo faff).</p>
<p>From the first frame, we now know what the starting timecode is and it can be embedded in the video file. I found a relatively cheap app to help with this, <a href="https://www.videotoolshed.com/product/qtchange/">QTchange</a>. Under the hood, it uses ffmpeg to do the work, and since I&rsquo;d only recently built <a href="https://github.com/Vargol/ffmpeg-apple-arm64-build">an Apple Silicon specific version of ffmpeg</a> (good for moving video processing off to the embedded GPU in my laptop&rsquo;s M1 Max processor) and was comfortable working in a terminal, I didn&rsquo;t see the need for it. If you prefer using graphical interface tools, then QTchange is probably a worthwhile spend.</p>
<p>With the image above as an example, we know the starting timecode is <code>10:28:22:00</code>. To embed that in a video file we can use these switches with ffmpeg:</p>
<div class="overflow-hidden rounded-sm shadow-lg">
  
  <div class="flex items-center gap-2 bg-gray-200 px-4 py-2 dark:bg-gray-700">
    <div class="size-3 rounded-full bg-red-500"></div>
    <div class="size-3 rounded-full bg-yellow-500"></div>
    <div class="size-3 rounded-full bg-green-500"></div>
  </div>
  
  <div class="bg-white px-8 py-2 dark:bg-gray-900">
    <pre
      class="overflow-x-auto whitespace-pre-wrap break-words"
    ><code>$ ffmpeg -i dji_mimo_20240602_102956_23_1717320826054_video.mp4 -timecode 10:28:22:00 -codec copy osmo.mp4</code></pre>
  </div>
</div>
<p>Note that <code>-i</code> is the input file.</p>
<p>Now when I build a <a href="https://youtu.be/kX65fh7z43o?si=cePyZEgOw0MmfJB6">Multicam Clip in FCP</a>, every clip has timecode embedded, and they synchronise perfectly:</p>
<p><img src="tc-fcp.webp" alt="tc-fcp"></p>
<p>A relatively cheap solution, that will save hours of work.</p>
<p><strong>Update, October 2024</strong>: I&rsquo;ve now automated most of this with <a href="https://support.apple.com/en-gb/guide/shortcuts/welcome/ios">Apple Shortcuts</a>. I&rsquo;m sure these two could be folded down into one shortcut, but I was developing them in separate steps, and now it works to the point I can&rsquo;t be bothered to distil it further. One shortcut extracts the first frame and OCRs the numbers (timecode) out, then a second shortcut applies the timecode. Here&rsquo;s what they look like:</p>
<p><img src="get-tc.webp" alt="get-tc"><br>
<img src="apply-tc.webp" alt="apply-tc"></p>]]>
      
      <![CDATA[<hr><p>Thanks for reading this post via RSS! 👏</p>]]>
      <![CDATA[<a href="mailto:rs511@probably.co.uk?subject=How to add timecode to older video recorders">Reply to this post by email</a>]]>
      </description>
    </item>
    <item>
      <title>How Minds Change by David McRaney</title>
      <link>https://probably.co.uk/posts/how-minds-change/</link>
      <pubDate>Mon, 29 Apr 2024 14:39:00 +0000</pubDate>
      <guid>https://probably.co.uk/posts/how-minds-change/</guid>
      <description>
      
      <![CDATA[<p><img src="how-minds-change.jpg" alt="How Minds Change book cover"></p>
<p>Along with <a href="/posts/2019-12-10_5-books-part-1/">&lsquo;Thinking, Fast and Slow&rsquo;</a>, I&rsquo;d recommend <a href="https://app.thestorygraph.com/reviews/457759e3-abd0-4e54-81b6-83509be54832">How Minds Change</a> as essential reading. The foundations of human behaviour understanding come from Kahneman&rsquo;s book, and here McRaney builds on it with real world examples. Through meeting various interesting people, McRaney paints a picture that tells a simple truth:</p>
<blockquote>
<p>For one thing, from writing my previous books, I knew the idea that facts alone could make everyone see things the same way was a venerable misconception.</p>
</blockquote>
<p>I made 63 highlights in this book. There are many small gems that can serve as useful guides for better thinking. Here, I&rsquo;ve picked out a few of those highlights to discuss.</p>
<blockquote>
<p>reality as we experience it isn’t a perfect one-to-one account of the world around us. The world, as you experience it, is a simulation running inside your skull, a waking dream. We each live in a virtual landscape of perpetual imagination and self-generated illusion, a hallucination informed over our lifetimes by our senses and thoughts about them, updated continuously as we bring in new experiences and think new thoughts about what we have sensed</p>
</blockquote>
<p>It&rsquo;s quite profound to realise there is no single, true, reality. What we think of as <strong>reality</strong> is just perception. And our perception of the world is context sensitive. That context is made up of years of experience and the situation we find ourselves in at the time. Have you ever held back on an opinion, thinking it clashes with a peer group at that moment? Not spoken up in a meeting, because everyone around you thinks something is a great idea, when you feel it&rsquo;s anything but? Context, shaping your reality.</p>
<p>A fine example of our reality being shaped by context, is <a href="https://www.wired.com/2015/02/science-one-agrees-color-dress/">The Dress</a>. Do you remember that bizarre phenomenon, and how you could easily argue with somebody stood next to you that it was white and gold, when they were 100% sure it was black and blue?</p>
<blockquote>
<p>when the truth is uncertain, our brains resolve that uncertainty without our knowledge by creating the most likely reality they can imagine based on our prior experiences.</p>
</blockquote>
<p>In Thinking, Fast and Slow, Kahneman&rsquo;s work showed that our — emotive, reactionary — <a href="https://en.wikipedia.org/wiki/Thinking,_Fast_and_Slow?wprov=srpw1_1#Two_systems">System 1</a> has a reality it <em>knows</em>, and when it comes to defending that reality, we&rsquo;ll simply draw on the experience we have. This is why we tend towards <a href="https://en.wikipedia.org/wiki/Confirmation_bias">confirmation bias</a>.</p>
<blockquote>
<p>It’s useful to think of confirmation bias as the goggles we put on when we feel highly motivated by fear, anxiety, anger, and so on. In these states we begin looking for confirmation that the emotions we feel are justified.</p>
</blockquote>
<p>I once read an interesting take on what happens when one tells somebody <em>&rsquo;they are wrong&rsquo;</em>. The uncomfortable sensation they feel, is down to their reality being smashed in that moment. It&rsquo;s a shock to System 1 — and the fight between it, its reality, and the new information System 2 has received, begins. <a href="https://en.wikipedia.org/wiki/Cognitive_dissonance">Cognitive dissonance</a>.</p>
<blockquote>
<p>If you add any conflict over resources of any kind, humans will instinctively enter us-versus-them thinking, even if that’s not the overall most beneficial strategy.</p>
</blockquote>
<p>&lsquo;Conflict over resources&rsquo; can render itself as a disagreement, or the urge to be right, come what may. That&rsquo;s a whole other discussion, principally around ego, but we&rsquo;ll leave that for now and recognise something obvious about the way our brains default to tribalism.</p>
<p>Homo Sapiens have existed for around 300,000 years<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>, yet it&rsquo;s only for the last 100 years or less that we&rsquo;ve not had to mostly focus on survival. To put that into context, baked into our brains are instincts that have been in control of our behaviour for over 99.96% of our species&rsquo; existence. Those instincts don&rsquo;t always fit neatly into the modern world, but they do find parallels to relate to.</p>
<blockquote>
<p>Most of the time we see the world as we expect to see it, and most of the time that’s fine; but the brain often gets things wrong because it prefers to sacrifice accuracy for speed.</p>
</blockquote>
<p>The &rsquo;laziness&rsquo; of falling back to System 1 (our &lsquo;gut&rsquo; reaction) has an economical reason. Conscious thought — System 2 — takes more energy<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup>. It can literally be tiring trying to question our System 1.</p>
<p>Throughout the book McRaney meets various people whose job it is to <em>&ldquo;change people&rsquo;s minds&rdquo;</em>. From their experience, he offers some guidance.</p>
<blockquote>
<p>No matter the message, face-to-face messaging is far and away the most effective channel. We are biologically hardwired to respond to the human face.</p>
</blockquote>
<p>Maybe this explains the growth of video-based marketing<sup id="fnref:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup> and the success of YouTube (the world&rsquo;s second largest search engine, the largest being its parent, Google).</p>
<p>A few years ago I ran a fully-remote Product team. If I was asked a question on our internal Slack, I would often reply with a short video. I chose to respond this way as I felt it would present the information clearer, and with the intent I wanted. As <a href="https://world.hey.com/jason/osmo-wiio-communication-usually-fails-except-by-accident-73a8ff2b">Jason Fried recently quoted in a blog post</a>:</p>
<blockquote>
<p>anytime there are two people conversing, there are actually six people in the conversation:<br>
Who you think you are<br>
Who you think the other person is<br>
Who you think the other person thinks you are<br>
Who the other person thinks they are<br>
Who the other person thinks you are<br>
Who the other person thinks you think they are.</p>
</blockquote>
<p>When we read words we apply our own emotion to those words. If we think the author is angry with us, we&rsquo;ll read it angrily, even if that&rsquo;s not the way it was intended at all. I found a message carried far more clarity of intention when delivered by video, especially when many of the recipients didn&rsquo;t share a common language or have English as their native tongue. In this modern day of geographically dispersed, remote working, teams, asynchronous communication leaves far more opportunity for &lsquo;<a href="https://en.wikipedia.org/wiki/Chinese_whispers">Chinese Whispers</a>&rsquo;. Short form video goes some way to alleviating misinterpretation.</p>
<p>Very early in the book, McRaney explains its purpose, lest you think you&rsquo;re about to learn devious techniques for coercing people to do thy bidding:</p>
<blockquote>
<p>Persuasion is not coercion, and it is also not an attempt to defeat your intellectual opponent with facts or moral superiority, nor is it a debate with a winner or a loser.</p>
</blockquote>
<p>This, once again, comes down to ego, and that&rsquo;s not the topic of the book, nor of this blog post. <a href="https://bit.ly/thismarkp">As an introvert</a>, I&rsquo;m not driven to &lsquo;win&rsquo; arguments, I seek truth. Understanding how our mind works is useful for seeking truths versus winning arguments. Everyone has their own reality, remember. The ability to understand that, and empathise, will always render kinder discussions.</p>
<blockquote>
<p>[he] later said to think of questions as keys on a giant ring. If you keep asking and listening, he told the crowd, one of those keys was bound to unlock the door to a personal experience related to the topic. It was there, and only there, he said, that a single conversation could change someone’s mind.</p>
</blockquote>
<p>This was an interesting chapter about &lsquo;Deep Canvassing&rsquo;, an area where the canvasser is trying to get somebody to change their mind on a topic in a short space of time. Usually the topic is highly emotive too, so initial reactions are strong. But this is a key takeaway from the book — changing minds isn&rsquo;t about bludgeoning people with information. It&rsquo;s about finding common ground, or helping a mind to absorb new information and draw alternative conclusions in its own time.</p>
<blockquote>
<p>Once people see where their ideas come from, they become aware that they come from somewhere. They can then ask themselves if they’ve learned anything new in the time since they last considered them. Maybe those ideas need updating in some way.</p>
</blockquote>
<p>Challenging another person&rsquo;s reality will initially be discomforting for them. Attempting to bludgeon with facts, to get them to <em>see your point of view</em>, will have the opposite effect. They&rsquo;ll dig in to their reality, seek confirmation bias, and appear to try to change <strong>your</strong> mind (that&rsquo;s not what they&rsquo;re actually doing, really they&rsquo;re defending their reality). This was discussed in Thinking, Fast and Slow, and <a href="/posts/2019-12-10_5-books-part-1/#improving-your-influencing-skills">I&rsquo;ve mentioned it previously</a>.</p>
<p>Sometimes a discussion in the moment won&rsquo;t yield the result you desire. Give people time to introspect though, and you may find that they change their mind. Trying to force the point will cause them to remain overconfident in their understanding of the topic they&rsquo;re passionate about, and overconfidence becomes <em>certainty</em> in our heads.</p>
<p>Ask questions. Plant seeds. Give them time to grow.</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p><a href="https://kar.kent.ac.uk/62267/1/Submission_288356_1_art_file_2637492_j96j1b.pdf">https://kar.kent.ac.uk/62267/1/Submission_288356_1_art_file_2637492_j96j1b.pdf</a>&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p><a href="https://psycnet.apa.org/record/2012-04347-001">https://psycnet.apa.org/record/2012-04347-001</a>&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:3">
<p><a href="https://www.linkedin.com/pulse/5-strong-reasons-why-video-marketing-important-nicholas-polle/">https://www.linkedin.com/pulse/5-strong-reasons-why-video-marketing-important-nicholas-polle/</a>&#160;<a href="#fnref:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>]]>
      
      <![CDATA[<hr><p>Thanks for reading this post via RSS! 👏</p>]]>
      <![CDATA[<a href="mailto:rs511@probably.co.uk?subject=How Minds Change by David McRaney">Reply to this post by email</a>]]>
      </description>
    </item>
    <item>
      <title>How to fix Starship prompt not appearing on macOS</title>
      <link>https://probably.co.uk/posts/starship-prompt-fails-on-macos/</link>
      <pubDate>Sun, 04 Feb 2024 15:11:00 +0000</pubDate>
      <guid>https://probably.co.uk/posts/starship-prompt-fails-on-macos/</guid>
      <description>
      
      <![CDATA[<p><img src="starship-prompt.jpg" alt="macos-terminal-window-with-starship-prompt"></p>
<p>I may have &lsquo;retired&rsquo; from being a techie a long time ago, but I haven&rsquo;t stopped solving little day-to-day problems in a shell 😊 So like any self-respecting nerd, whether old or young, one needs a good prompt. It&rsquo;s a pity that Starship&rsquo;s setup on macOS seems to fail out of the box though. Here&rsquo;s how to fix it.</p>
<p><a href="https://starship.rs">Starship</a> is a fast, configurable, prompt for most of the common shells. It&rsquo;s a binary, built in Rust. Compared to the popular Oh My Zsh, it&rsquo;s tiny, simple and fast. Just the way I prefer my tech.</p>
<p>But the instructions for configuring in zsh fail on macOS, with the prompt never appearing. It didn&rsquo;t really make sense, either, as a common <code>eval $(blah)</code> should work just fine. Searching only throws up a <a href="https://stackoverflow.com/questions/75079111/starship-cross-shell-prompt-is-not-working-on-mac-zsh">Stackoverflow article</a> that doesn&rsquo;t actually solve the problem.</p>
<p>Rummaging through the <a href="https://github.com/starship/starship/issues/5667">closed issues</a> on Github turned up the answer though; quote the eval, et voila! Working prompt.</p>
<p>Change <code>eval $(starship init zsh)</code> to <code>eval &quot;$(starship init zsh)&quot;</code> and it works.</p>
<p><strong>Update</strong>: It looks like the instructions have been updated <a href="https://starship.rs/#zsh">on the homepage</a> now.</p>]]>
      
      <![CDATA[<hr><p>Thanks for reading this post via RSS! 👏</p>]]>
      <![CDATA[<a href="mailto:rs511@probably.co.uk?subject=How to fix Starship prompt not appearing on macOS">Reply to this post by email</a>]]>
      </description>
    </item>
    <item>
      <title>It is impossible to delete RAW files from iCloud Photos</title>
      <link>https://probably.co.uk/posts/icloud-raw-photos-impossible-delete/</link>
      <pubDate>Tue, 30 Jan 2024 18:49:00 +0000</pubDate>
      <guid>https://probably.co.uk/posts/icloud-raw-photos-impossible-delete/</guid>
      <description>
      
      <![CDATA[<p><img src="deleting-raws.jpg" alt="&ldquo;Try deleting RAW files and keeping the JPGs!&rdquo;"></p>
<p>I decided to try and save some space in my iCloud drive. Looking at the usage, 160gb was being taken up by Photos. I thought that was ridiculous. This turned out to be nowhere near as ridiculous as the ensuing saga to try and delete some files.</p>
<h2 id="just-delete-the-files">Just delete the files</h2>
<p>Naturally I started by deleting every single video in the library. Photos at least makes it easy to find particular types of file, with the &lsquo;Media Types&rsquo; album link on the left.</p>
<p><img src="photos-albums.png" alt="&ldquo;Albums&rdquo;"></p>
<p>Next came the realisation that I had hundreds of photos that were JPEG+RAW, with the RAW files being many times the size of the JPEGs. I wondered if you could separate the two, deleting just the RAW files. <a href="https://discussions.apple.com/docs/DOC-11311">A bit of searching</a> revealed it wasn&rsquo;t that easy — you have to delete the JPEG+RAW combo. So I exported all the photos, using the &ldquo;Export unmodified originals&hellip;&rdquo; menu option, and deleted the actual RAW files on the file system. Then simply re-imported the JPEGs back into Photos.</p>
<p>I thought that would be the end of it.</p>
<h2 id="theyre-back">They&rsquo;re back!</h2>
<p>Later that day I noticed on my iPhone that the RAW &lsquo;Media Type&rsquo; still existed — and couldn&rsquo;t quite believe it when I saw that the JPEGs I&rsquo;d re-imported earlier appeared to be back attached to the RAW files I thought I&rsquo;d deleted! WTF?!</p>
<p>So I contacted Apple Support. Naturally the chat bot was no help, so I took a phone call. The very polite chap on the phone went through all the steps with me, again, watching what happened. Oddly, the RAW files would reappear first on iOS, so we wondered if there was something odd going on there — and opted to remove my iPad and iPhone from iCloud Photos, along with an Apple TV that had access too. I deleted all the files again, checked in the web version of iCloud, looked into the Photos Library; all gone. Emptied the &lsquo;Recently Deleted&rsquo; folder in Photos. No RAWs anywhere. So the support guy signed off and left me to it, saying I could reopen the case if this hadn&rsquo;t solved it (note to self: Apple&rsquo;s support path is terrible. You just start from scratch again).</p>
<p><img src="no-raws-anywhere.jpg" alt="&ldquo;Ain&rsquo;t no RAW files here&rdquo;"></p>
<p>Dragged the JPEGs back in.</p>
<p>The RAWs started reappearing&hellip; 😱</p>
<p><img src="ios-raws-going-up.mov" alt="&ldquo;RAWs reappearing on iOS&rdquo;"></p>
<h2 id="if-at-first-you-dont-succeed">If at first you don&rsquo;t succeed</h2>
<p>Not one to accept defeat, I&rsquo;d thought I&rsquo;d give it one last, possibly drastic, attempt. <em>Sigh.</em></p>
<p>By this point, the <strong>only</strong> device I had sync&rsquo;ing with iCloud Photos was the Mac. So I exported the files. Deleted them in Photos. Emptied &lsquo;Recently Deleted&rsquo;. Deleted the RAWs from the export folder. Emptied the trash. Checked in the Photos Library — all gone. Then made the drastic move. Turned off iCloud Photos on the Mac, and <strong>deleted every single photo in the web interface</strong>.</p>
<p><em>I now had no iCloud Photos library anywhere.</em></p>
<p>It had started to occur to me that despite iCloud drive having no history, I wondered if Apple keeps the files &lsquo;just in case&rsquo;. Maybe there&rsquo;s a legal reason that they don&rsquo;t talk about (I&rsquo;m not going through those T&amp;Cs to find that clause; it might well be documented, I don&rsquo;t know). Anyway, I thought I&rsquo;d give it a few days, then turn iCloud Photos back on to see what would happen.</p>
<p>Which I did, this evening, January 30th. Only on the Mac, nowhere else. There were no photos on iCloud web, the iPad, iPhone and Apple TV were all &lsquo;disconnected&rsquo; from iCloud Photos.</p>
<p>The RAW files came back&hellip;</p>
<p><img src="yup-raws-are-back.jpg" alt="&ldquo;WTAF?!&rdquo;"></p>
<p>Doing an &lsquo;Export unmodified original&rsquo; does indeed pull two files out on to the local filesystem, so the raw files have <strong>definitely</strong> come back from iCloud. Despite being deleted. Umpteen times.</p>
<p><img src="that-fin-raws-back.png" alt="&ldquo;Now how did they do that?&rdquo;"></p>
<p>All the iCloud shared albums I had also recreated themselves, but with no photos in. Which leads me to believe the photos are deleted, but clearly some &lsquo;pointer&rsquo; is not.</p>
<p><img src="icloud-photos-blank-shared-albums.png" alt="&ldquo;Shared albums are back, with no content&rdquo;"></p>
<p>I&rsquo;m at a loss now. I&rsquo;ve no idea where they come from or how to delete them 😂 It&rsquo;s infuriating. It also begs some questions about the trustworthiness of Apple. But that&rsquo;s a pondering for another time. It would seem though, that <a href="https://discussions.apple.com/thread/8413026?sortBy=best">I am not alone</a>.</p>
<h2 id="final-thought">Final thought</h2>
<p>OK, I&rsquo;ve turned iCloud Photos off again.</p>
<p><img src="wait-30-days.png" alt="&ldquo;Wait 30 days&rdquo;"></p>
<p>I&rsquo;ll give it the 30 days, then turn the library sync back on (without RAWs in!) and see if that finally de-links them. If it doesn&rsquo;t, I might just have to scream.</p>
<p><img src="you-have-30-days.png" alt="&ldquo;Wait 30 days&rdquo;"></p>
<h2 id="update-7th-march-2024">Update: 7th March, 2024</h2>
<p>I apprehensively turned iCloud Photos back on yesterday. I&rsquo;d kept a complete library on my Mac, except with all RAWs removed, of course. It sync&rsquo;d fine, and no RAWs reappeared. Although, oddly, all the iCloud Photos Shared Albums recreated and repopulated with the same photos — which suggests to me, even though Apple deletes all photos in iCloud after 30 days, there&rsquo;s some sort of metadata that they do not remove.</p>
<p>Since no RAWs had reappeared on the Mac, I braved the iPad and iPhone. All good! No RAWs!</p>
<p>So there we go. A painful exercise, and one that needs at least 30 days to resolve the &lsquo;problem&rsquo;. If you want to decouple RAW photos from JPGs in iCloud Photos, you need to disable iCloud Photos <strong>on every device</strong>, export the photos and RAWs from your library, delete them, reimport the JPGs, and wait at least 30 days before turning iCloud Photos back on. <strong>What a total faff.</strong></p>]]>
      
      <![CDATA[<hr><p>Thanks for reading this post via RSS! 👏</p>]]>
      <![CDATA[<a href="mailto:rs511@probably.co.uk?subject=It is impossible to delete RAW files from iCloud Photos">Reply to this post by email</a>]]>
      </description>
    </item>
    <item>
      <title>CleanShot X screen capture tool</title>
      <link>https://probably.co.uk/posts/cleanshot-x-screen-capture/</link>
      <pubDate>Wed, 10 Jan 2024 15:50:00 +0000</pubDate>
      <guid>https://probably.co.uk/posts/cleanshot-x-screen-capture/</guid>
      <description>
      
      <![CDATA[<p><img src="cleanshot.jpg" alt="CleanShot Screen Capture App for macOS"></p>
<p>Taking <a href="https://support.apple.com/en-us/102646">screenshots on macOS</a> is a doddle. cmd-shift-4, or cmd-shift-3, or for ultimate control, cmd-shift-5. What could be simpler? Why would you want more? That&rsquo;s what I used to think, until I tried <a href="https://cleanshot.com">CleanShot</a>.</p>
<!-- more-->
<p>I&rsquo;ve often found myself wanting to get a screen grab of, say, a browser window, but in a particular ratio. For the last year I&rsquo;ve been running marketing for a local business. As part of that, I create a lot of content for YouTube. So quite often I want a screenshot in 16 x 9 ratio, which is awkward to do. I&rsquo;ve either ended up writing Apple Script to size the window, then grabbed it with cmd-shift-4, or grabbed the whole screen then cropped it in <a href="https://www.pixelmator.com/pro/">Pixelmator</a>. What a faff.</p>
<p>Over Christmas, whilst joining in the <a href="/posts/default-applications/">default apps</a> trend and viewing others&rsquo; apps, I saw somebody using an add on app for screen capture — CleanShot X. My immediate thought was <em>&lsquo;why would you need that, the default suffices&rsquo;</em>. Then I tried it.</p>
<p>I&rsquo;m now hooked. The one-time purchase price is worth the time and effort savings (I&rsquo;m not fussed about the subscription version — in fact, most software subscriptions are a turn off these days).</p>
<p>What value am I getting from it? Well, fixed ratio grabs for starters. But neat extras like being able to add a background to a grab is useful (like the image at the head of this post). CleanShot just makes everything easy, and even &lsquo;hijacks&rsquo; the macOS standard keyboard shortcuts.</p>
<p>Like <a href="https://www.macbartender.com">Bartender</a>, it&rsquo;s one of those little helpers that actually makes the experience of macOS even better.</p>
]]>
      
      <![CDATA[<hr><p>Thanks for reading this post via RSS! 👏</p>]]>
      <![CDATA[<a href="mailto:rs511@probably.co.uk?subject=CleanShot X screen capture tool">Reply to this post by email</a>]]>
      </description>
    </item>
    <item>
      <title>Default applications</title>
      <link>https://probably.co.uk/posts/default-applications/</link>
      <pubDate>Sat, 23 Dec 2023 19:17:19 +0000</pubDate>
      <guid>https://probably.co.uk/posts/default-applications/</guid>
      <description>
      
      <![CDATA[<p>Jumping on the <a href="https://defaults.rknight.me">default apps bandwagon</a>, I thought I&rsquo;d share how &lsquo;default&rsquo; I am (is this the&rsquo;<a href="https://en.wikipedia.org/wiki/Normcore">normcore</a>&rsquo; of macOS application use?)</p>
<p>📨 Mail Service: <a href="https://hey.com">Hey</a><br>
📮 Mail Client: <a href="https://hey.com">Hey</a><br>
📝 Notes: Apple Notes (+ <a href="https://bear.app">Bear</a>)<br>
✅ To-Do: <a href="https://culturedcode.com/things">Things</a> (+ Apple Reminders)<br>
📆 Calendar: <a href="https://flexibits.com/fantastical">Fantastical</a> — fronting Apple iCloud<br>
📆 Calendar bookings: <a href="https://cal.com/thismarkp">Cal.com</a><br>
🙍 Contacts: Apple Contacts<br>
🗞️ RSS Client: <a href="https://netnewswire.com">NetNewsWire</a><br>
⌨️ Launcher: Spotlight<br>
📸 iPhone photo shooting: <a href="https://halide.cam">Halide</a><br>
☁️ Cloud storage: iCloud<br>
🌅 Photo library: Photos (iCloud + <a href="https://glass.photo/markp">Glass</a>]<br>
🌐 Web Browser: Safari<br>
💬 Chat: iMessages (+ <a href="https://signal.org">Signal</a> and <a href="https://discord.com">Discord</a>)<br>
📺 Video meetings: <a href="https://whereby.com">Whereby</a><br>
🔖 Bookmarks: Safari + Notes<br>
📚 Reading: Kindle<br>
📜 Word Processing: Apple Pages<br>
📈 Spreadsheets: Apple Numbers<br>
📊 Presentations: Apple Keynote<br>
🛒 Shopping Lists: <a href="https://culturedcode.com/things">Things</a><br>
💰 Personal Finance: Apple Numbers<br>
🎵 Music: Apple Music<br>
🎤 Podcasts: Apple Podcasts<br>
🔐 Password Management: 🤐<br>
🤦 Social Media: <a href="https://mastodon.social/@thismarkp">Mastodon</a><br>
🌤️ Weather: <a href="https://windy.com">Windy</a>, <a href="https://openweathermap.org">Openweather</a>, <a href="https://www.metoffice.gov.uk">Metoffice</a><br>
🔎 Search: <a href="https://duckduckgo.com">DuckDuckGo</a><br>
🧮 Code Editor: Mostly <a href="https://www.vim.org">Vim</a> (+ <a href="https://nova.app">Nova</a>)</p>
]]>
      
      <![CDATA[<hr><p>Thanks for reading this post via RSS! 👏</p>]]>
      <![CDATA[<a href="mailto:rs511@probably.co.uk?subject=Default applications">Reply to this post by email</a>]]>
      </description>
    </item>
    <item>
      <title>Should we be polite to AI?</title>
      <link>https://probably.co.uk/posts/being-polite-to-ai/</link>
      <pubDate>Tue, 31 Oct 2023 12:51:00 +0000</pubDate>
      <guid>https://probably.co.uk/posts/being-polite-to-ai/</guid>
      <description>
      
      <![CDATA[<p><img src="ai-handshake.jpg" alt="AI generated AI thumbnail. How very meta."></p>
<p>Elaine Moore recently wrote an article in the FT titled &ldquo;<a href="https://on.ft.com/45VDUUr">We might be surprised by our reactions to generative AI</a>&rdquo;. It got me thinking about the way we &lsquo;speak&rsquo; to generative AI, like ChatGPT.</p>
<!-- more -->
<p>Like many of the tech community, I’ve been using ChatGPT for most of this year. I’ve found it to be the search engine I wish we’d always had, and a fabulous co-pilot in so many tasks. As a distant former ‘hands on’ technologist, I’m very rusty in anything that involves writing code. Yet I&rsquo;ve found myself wanting to automate problems away, or solve things in a simpler fashion (i.e. get a computer to do it). So I’ve turned to ChatGPT to help me write code, and I’ve found it incredibly helpful. It is a productivity booster for me.</p>
<p>I started out making my prompts terse, ‘search engine style’. But then I changed, commununicating with it like I would a person. This might seem a bit daft, but actually it <em>feels</em> better to me. Internally, the way I think about communicating with people is to be respectful and kind. I treat people the way I like to be treated.</p>
<p>I forget where I read it, maybe something by <a href="/posts/2019-12-10_5-books-part-1/">Kahneman</a> or <a href="https://literal.club/mp/book/misbehaving-eb3i7">Thaler</a>, but the quote <em>“people’s behaviour is a product of the system they are part of”</em><sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> comes to mind. To that end, I see being kind on the inside as a precursor to being kind on the outside. Call me soft, but I anthropomorphise my dog with the greatest of ease, and so I feel like doing the same to an AI detracts nothing from how I think about communication.</p>
<p>Here’s a snippet of a ‘conversation’ I had with ChatGPT about analysing the stock market. Am I daft to use manners? What do you think? I welcome your thoughts via <a href="https://mstdn.social/@mph">Mastodon</a> or <a href="https://linkedin.com/in/markphillips">LinkedIn</a>.</p>




<video controls poster="ai-chat-vid-thumb.png">
<source src="https://v.5318808.xyz/asking_gpt-4_about_spx.mp4">
Your browser does not support the video tag.
</video>

<h2 id="update">Update</h2>
<p>This sparked a bit of conversation on LinkedIn, with <a href="https://www.linkedin.com/feed/update/urn:li:activity:7127263362660356096?commentUrn=urn%3Ali%3Acomment%3A%28activity%3A7127263362660356096%2C7133006286689820672%29&amp;dashCommentUrn=urn%3Ali%3Afsd_comment%3A%287133006286689820672%2Curn%3Ali%3Aactivity%3A7127263362660356096%29">Stuart asking</a> if I&rsquo;d tried asking AI itself 😊 Fair point. So I did:</p>
<p><img src="being-polite-to-ai.jpg" alt="Asking ChatGPT if one should be polite to AI"></p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>It&rsquo;s probably a paraphrase of B F Skinner&rsquo;s &ldquo;environment determines behaviour&rdquo;&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]>
      
      <![CDATA[<hr><p>Thanks for reading this post via RSS! 👏</p>]]>
      <![CDATA[<a href="mailto:rs511@probably.co.uk?subject=Should we be polite to AI?">Reply to this post by email</a>]]>
      </description>
    </item>
    <item>
      <title>Alleviating Zoom fatigue with a teleprompter</title>
      <link>https://probably.co.uk/posts/alleviating-zoom-fatigue-with-a-teleprompter/</link>
      <pubDate>Wed, 28 Dec 2022 15:25:00 +0000</pubDate>
      <guid>https://probably.co.uk/posts/alleviating-zoom-fatigue-with-a-teleprompter/</guid>
      <description>
      
      <![CDATA[<p><img src="teleprompter.jpg" alt="My teleprompter setup for Zoom meetings"></p>
<p>After my desk recently featured on <a href="https://www.workspaces.xyz/p/232-mark-phillips">Workspaces</a>, its curator, <a href="https://twitter.com/rjgilbert">Ryan</a>, mentioned that several people had asked about the teleprompter set up I use for video meetings.</p>
<p>I’ve been working from home for 10 years, so video meetings were nothing new to me when the pandemic started. Even by that point, I’d been experimenting with higher quality meeting set ups, using a better microphone and my everyday camera (a Fuji X-E4) as a webcam.</p>
<p>There&rsquo;s no escaping the fact that trying to look at folks on a screen means you&rsquo;re not looking them in the eye. This creates an odd disconnect not present in any normal human interaction. I have a theory that this disconnect, this lack of genuine connection (eye to eye), contributes heavily to &lsquo;Zoom fatigue&rsquo;.</p>
<p>So I thought I’d try using a teleprompter to put video meetings on. When the other person is full screen, this feels a lot closer to speaking ‘face to face’. The other person has the added normality of me looking them in the eye when we’re speaking, too. I feel like this goes some way to making a video call feel that bit more realistic.</p>
<p>I bought <a href="https://www.amazon.co.uk/gp/product/B08FT4SLPL/ref=nosim?tag=probably0c-21">a large-ish teleprompter</a> from Amazon and put the X-E4 in it — positioning the camera so that I&rsquo;m looking directly into the lens when the other person&rsquo;s eyes are at its level. This creates an obvious problem you&rsquo;ll have considered — the image displayed is mirrored, i.e. back to front.</p>
<p>When I first tried this set up, I was using an iPad as the display, and had to do a lot of faffing around with <a href="https://obsproject.com">OBS</a> to flip the image. This quickly got more tiresome than the actual meetings. Then I discovered the Lilliput 10&quot; field monitor <a href="https://www.amazon.co.uk/gp/product/B085XL6FJW/ref=nosim?tag=probably0c-21">on Amazon</a> (via <a href="https://youtu.be/Wazoo4VlJFw?t=650">Aaron Parecki</a>), which has a built in &lsquo;image flip&rsquo; function.</p>
<p>I connect the MacBook to my desk monitor via USB-C, and the Lilliput is connected via the HDMI interface. This becomes another monitor — making it easy to drag Zoom, or whatever video meeting I’m in, to the Lilliput. The monitor flips the image, so moving the mouse around is perfectly natural.</p>
<p>This may not be the cheapest way to ease Zoom fatigue, (how about not having so many meetings? 🤷‍♂️) but since working-from-home saves on commuting costs, I consider it a worthwhile outlay.</p>
<p>Here’s a video I made a while ago about the desk setup. The only things that have changed since I made this, are the introduction of the teleprompter so I’m not looking at the camera above the computer, and the iMac being replaced with the separate screen and laptop.</p>




<video controls poster="hello.jpg">
<source src="https://v.5318808.xyz/add_production_quality_to_your_video_meetings.mp4">
Your browser does not support the video tag.
</video>]]>
      
      <![CDATA[<hr><p>Thanks for reading this post via RSS! 👏</p>]]>
      <![CDATA[<a href="mailto:rs511@probably.co.uk?subject=Alleviating Zoom fatigue with a teleprompter">Reply to this post by email</a>]]>
      </description>
    </item>
    <item>
      <title>Desiderata</title>
      <link>https://probably.co.uk/posts/desiderata/</link>
      <pubDate>Thu, 11 Aug 2022 10:58:52 +0100</pubDate>
      <guid>https://probably.co.uk/posts/desiderata/</guid>
      <description>
      
      <![CDATA[<p>I am of the age that means I was the second year to sit GCSEs (after GCE O-Levels were abandoned). I therefore consider my <a href="https://en.wikipedia.org/wiki/General_Certificate_of_Secondary_Education#Grade_inflation">education to have been relatively poor</a>.</p>
<!-- more -->
<p>That doesn&rsquo;t mean I&rsquo;ve spent my life feeling short-changed though. On the
contrary, I&rsquo;ve spent the rest of my life <a href="/posts/2019-12-03_5-inspirational-books/">continuously learning</a>. So maybe you&rsquo;ll forgive me for having only recently discovered Max Ehrmann&rsquo;s <em>Desiderata</em> poem. Shock! Horror! I know. It feels like it channels the core of stoicism, another rabbit hole I&rsquo;ve been down in recent years (off the back of discovering <a href="/posts/2021-01-18-mindfulness/">mindfulness</a>).</p>
<p>Here it is in full, for your enjoyment and mine…</p>
<blockquote>
<p><strong>Go placidly</strong> amid the noise and the haste, and remember what peace there may be
in silence. As far as possible, without surrender, be on good terms with all
persons.</p>
<p>Speak your truth quietly and clearly; and listen to others, even to the dull
and the ignorant; they too have their story.</p>
<p>Avoid loud and aggressive persons; they are vexatious to the spirit. If you
compare yourself with others, you may become vain or bitter, for always there
will be greater and lesser persons than yourself.</p>
<p>Enjoy your achievements as well as your plans. Keep interested in your own
career, however humble; it is a real possession in the changing fortunes of
time.</p>
<p>Exercise caution in your business affairs, for the world is full of trickery.
But let this not blind you to what virtue there is; many persons strive for
high ideals, and everywhere life is full of heroism.</p>
<p>Be yourself. Especially do not feign affection. Neither be cynical about love;
for in the face of all aridity and disenchantment, it is as perennial as the
grass.</p>
<p>Take kindly the counsel of the years, gracefully surrendering the things of
youth.</p>
<p>Nurture strength of spirit to shield you in sudden misfortune. But do not
distress yourself with dark imaginings. Many fears are born of fatigue and
loneliness.</p>
<p>Beyond a wholesome discipline, be gentle with yourself. You are a child of the
universe no less than the trees and the stars; you have a right to be here.</p>
<p>And whether or not it is clear to you, no doubt the universe is unfolding as it
should. Therefore be at peace with God, whatever you conceive Him to be. And
whatever your labors and aspirations, in the noisy confusion of life, keep
peace in your soul. With all its sham, drudgery and broken dreams, it is still
a beautiful world. Be cheerful. Strive to be happy.</p>
</blockquote>
<p>Max Ehrmann, 1927</p>
]]>
      
      <![CDATA[<hr><p>Thanks for reading this post via RSS! 👏</p>]]>
      <![CDATA[<a href="mailto:rs511@probably.co.uk?subject=Desiderata">Reply to this post by email</a>]]>
      </description>
    </item>
    <item>
      <title>The Design of Everyday Things by Don Norman</title>
      <link>https://probably.co.uk/posts/design-of-everyday-things/</link>
      <pubDate>Wed, 29 Jun 2022 09:15:00 +0000</pubDate>
      <guid>https://probably.co.uk/posts/design-of-everyday-things/</guid>
      <description>
      
      <![CDATA[<p><img src="doet.jpg" alt="The cover of Don Norman&rsquo;s book, The Design of Everyday Things"></p>
<blockquote>
<p>&ldquo;Indifference towards people and the reality in which they live is actually the one and only cardinal sin in design&rdquo;. Dieter Rams.</p>
</blockquote>
<p>When I was growing up I had every intention of becoming a car designer. Something derailed that in my teens, just as I found out I could &lsquo;work&rsquo; computers. My career path changed, but my interest in design as a discipline never left me.</p>
<p>After nearly 30 years of working in tech, I do sometimes despair of the industry tendency to ignore people. Sometimes it feels like we&rsquo;re making software just for the sake of making it, not recognising that we&rsquo;re actually trying to solve problems for people. Although I believe most of the indifference is not deliberate, I do think it is pervasive.</p>
<p><a id="culture" class="scroll-mt-26"></a>
A few years back I was going to write a blog titled &ldquo;<em>Your products are a result of your company culture</em>&rdquo;. When I came across this quote in the book, it made me smile:</p>
<blockquote>
<p>&ldquo;Producing a good product requires a lot more than good technical skills: it requires a harmonious, smoothly functioning, cooperative and respectful organisation&rdquo;.</p>
</blockquote>
<p>I marked <em>a lot</em> of Don Norman&rsquo;s book whilst perusing it.</p>
<p><img src="doet-marks.jpg" alt="marks"></p>
<p>It was interesting to read his opening stories about failings in door design (admit it, how many times have you gone to pull on a glass door with a handle in a modern building, only to realise you need to push to open it?) Chapter five is, encouragingly, titled <em>&ldquo;Human error? No, bad design&rdquo;</em>.</p>
<blockquote>
<p>&ldquo;Design is concerned with how things work, how they are controlled, and the nature of the interaction between people and technology. When done well, the results are brilliant, pleasurable products. When done badly, the products are unusable&rdquo;</p>
</blockquote>
<p>The early part of the book covers human psychology, and it was pleasing to see the overlap of design and <a href="/posts/2019-12-10_5-books-part-1/">almost every other facet of life</a>. As you&rsquo;d expect, given we&rsquo;re all still just people. When designing any form of product, it pays to be cognisant of human behaviour and not just use logical thought to derive the solution. Here&rsquo;s a neat example of design thinking:</p>
<div class="relative overflow-hidden pb-[56.25%] pt-[30px]">
  <iframe
    type="text/html"
    src="https://www.youtube-nocookie.com/embed/9OfBpQgLXUc"
    allowfullscreen
    frameborder="0"
    class="absolute left-0 top-0 size-full"
  ></iframe>
</div>


<p>It&rsquo;s amazing how simple the ideas are in that video. The continuous colour of the pavements, that their levels create the boundary focus, i.e. on people walking and cycling.</p>
<p>Getting back to DOET…</p>
<blockquote>
<p>&ldquo;Because we are only aware of the reflective level of conscious processing, we tend to believe that all human thought is conscious. But it isn&rsquo;t. We also tend to believe that thought can be separated from emotion. This is also false.&rdquo;</p>
</blockquote>
<p>Norman covers memory models, knowledge and even how culture can affect the way we map knowledge and experience. It&rsquo;s important to recognise that cultural differences in your audience can seriously affect the usability of a product.</p>
<blockquote>
<p>&ldquo;A subtle issue that seems to figure in many accidents is social pressure. Although at first it may not seem relevant to design, it has strong pressures on everyday behaviour&rdquo;</p>
</blockquote>
<p>The book then moves on to suggest a system for design, and how to think about important aspects of your product like constraints, <a href="https://en.wikipedia.org/wiki/Affordance#As_perceived_action_possibilities">affordances</a> and <a href="https://www.alice.id.tue.nl/references/norman-2008.pdf">signifiers</a>.</p>
<p>In the chapter on design principles for dealing with error, Norman makes an interesting point that I think is often at the centre of problems with computer systems:</p>
<blockquote>
<p>&ldquo;Difficulties arise when we do not think of people and machines as collaborative systems, but assign whatever tasks can be automated to the machines and leave the rest to people&rdquo;</p>
</blockquote>
<p>This statement reminded me of <a href="https://en.wikipedia.org/wiki/Ironies_of_Automation">a paper I&rsquo;d read a couple of years back</a>, written in the 1980s, about automation: <em>&ldquo;The designer&rsquo;s view of the human operator may be that the operator is unreliable and inefficient, so should be eliminated from the system. There are two ironies of this attitude. One is that designer errors can be a major source of operating problems&rdquo;</em>. As creators of computer software designed to automate tasks for us mere humans, we&rsquo;d do well to remember that statement, and Norman&rsquo;s view that, accurately, we are invariably <em>collaborating</em> with a computer program.</p>
<p>In a reflection of what is often at fault with software design, is the section titled <em>&ldquo;Solving the correct problem&rdquo;</em>.</p>
<blockquote>
<p>&ldquo;Good designers never start by trying to solve the problem given to them: they start by trying to understand what the real issues are.&rdquo;</p>
</blockquote>
<p>A fundamental part of that is asking the right questions. In many cases, I&rsquo;ve seen user case study questionnaires built around questions that simply prompt answers the developer/company wants to hear. The company designed the questions about their own thinking. It&rsquo;s hard to come up with questions that are rooted in trying to understand things you may not know about! But, there are skilled UX researchers out there who can.</p>
<p>One last thing that may not come as a surprise, especially if you&rsquo;ve read <a href="/posts/2019-12-10_5-books-part-1/">Kahneman</a> or <a href="/posts/2020-02-05_5-books-part-4/">Sutherland</a>. The opening to the acknowledgements section:</p>
<blockquote>
<p>&ldquo;The original edition of this book was entitled The Psychology of Everyday Things (POET). This title is a good example of the difference between academics and industry. POET was a clever, cute title,
much loved by my academic friends. … the editors also said, &ldquo;But of course, the title will have to be
changed.&rdquo; Title changed? I was horrified. But I decided to follow my own advice and do some research on readers. I discovered that while the academic community liked the title and its cleverness, the business community did not. In fact, business often ignored the book because the title sent the wrong message.&rdquo;</p>
</blockquote>
<p>After reading DOET, I would add it to <a href="/posts/2019-12-03_5-inspirational-books/">my essential reads list</a> for building better products, teams and companies.</p>]]>
      
      <![CDATA[<hr><p>Thanks for reading this post via RSS! 👏</p>]]>
      <![CDATA[<a href="mailto:rs511@probably.co.uk?subject=The Design of Everyday Things by Don Norman">Reply to this post by email</a>]]>
      </description>
    </item>
    <item>
      <title>A plausible alternative</title>
      <link>https://probably.co.uk/posts/2021-04-19_plausible/</link>
      <pubDate>Mon, 19 Apr 2021 00:00:00 +0000</pubDate>
      <guid>https://probably.co.uk/posts/2021-04-19_plausible/</guid>
      <description>
      
      <![CDATA[<p>Why pay for something that you can get for free?</p>
<p>I have a feeling that&rsquo;s been a question on all our minds since the early to mid-1990s. The Internet has given us so much utility for free. It&rsquo;s amazing how blind we&rsquo;ve been to &lsquo;free&rsquo; ultimately having a cost though. Google, Facebook, et al. — all that freeness has come at a cost.</p>
<p>For some time I&rsquo;ve looked for alternative ways to achieve things on the Internet without having to freely <a href="https://hey.com/none-of-their-business/">give up data</a> to every advertising network. Last summer I tried out <a href="https://hey.com">Hey</a> for email and stuck with it as a paying customer. I can imagine many people asking themselves <em>&ldquo;why would you pay for an email service?!&rdquo;</em> Well, I find a lot of value in <a href="https://hey.com/features/">their raison d&rsquo;être</a> and I&rsquo;m happy paying the cost for that value.</p>
<p>Hey made me realise how email can be a better experience when it’s done simply and thoughtfully, so I wondered where else I could do better with my digital life. I’m developing a project at the moment that has a web presence, but I don’t want to soil it with cookie notices. They’re a massive annoyance that only exists because web sites are busy farming our data. But, as a business, you really need some data about your customers! The key thing I wanted was visitor data. For years I’ve used Google Analytics, but Google is a prime example of how uncomfortable I’ve become with ‘free’. So I looked around for alternatives.</p>
<p>Many years ago I remember using <a href="https://www.awstats.org/">AWStats</a> for gathering web visit statistics, but it’s clumsy and looks dated now. I wanted something as simple and elegant as Hey. After some searching, I stumbled across <a href="https://plausible.io/">Plausible Analytics</a>.</p>
<p>Plausible has a simple and tidy interface. First goal met.</p>
<p><img src="plausible_summary_email.png" alt="Weekly Summary Email">
<em>The weekly summary email is a useful addition</em></p>
<p>As I looked into the company, I discovered it’s not just the product that’s impressive. Two guys, bootstrapped — no VC money to <a href="https://plausible.io/blog/growing-saas-mrr#its-ok-if-your-marketing-strategy-is-boring-and-lacks-growth-hacks">poison the way they achieve growth</a>. They’ve done ‘honest marketing’ — helpful blog content coupled up with a product that transparently ‘<a href="https://youtu.be/e7dx2Z9G7Mk">does what it says on the tin</a>’</p>
<p>I love this blog post they wrote in 2020 — <a href="https://plausible.io/blog/best-marketing-practices">15 best startup marketing practices we say no to (while growing our MRR by 1000% in 6 months)</a>.</p>
<p>The icing-on-the-cake for me to become a paying customer was that article.</p>
<p>Sometimes, value outweighs cost. A small monthly cost brings the value of a better experience for viewers of this site, and the data is not blindly being handed to advertisers.</p>]]>
      
      <![CDATA[<hr><p>Thanks for reading this post via RSS! 👏</p>]]>
      <![CDATA[<a href="mailto:rs511@probably.co.uk?subject=A plausible alternative">Reply to this post by email</a>]]>
      </description>
    </item>
    <item>
      <title>Does mindfulness work?</title>
      <link>https://probably.co.uk/posts/2021-01-18-mindfulness/</link>
      <pubDate>Mon, 18 Jan 2021 00:00:00 +0000</pubDate>
      <guid>https://probably.co.uk/posts/2021-01-18-mindfulness/</guid>
      <description>
      
      <![CDATA[<p><img src="mindful.jpg" alt="Upto October 2024, I&rsquo;ve done 240 hours of Mindfulness"></p>
<p>In a word, yes. But the question needs some context.</p>
<p>Let&rsquo;s start with defining &ldquo;mindfulness&rdquo;. <a href="https://en.wikipedia.org/wiki/Mindfulness">Wikipedia</a>, the UK charity <a href="https://www.mind.org.uk/information-support/drugs-and-treatments/mindfulness/about-mindfulness/">Mind</a>, and the UK <a href="https://www.nhs.uk/conditions/stress-anxiety-depression/mindfulness/">national health service</a> all say a similar thing, that &ldquo;mindfulness&rdquo; is <em>awareness</em>, a sense of what&rsquo;s happening in the moment. Meditation is the tool we can use to bring about mindfulness. As Colm Meaney&rsquo;s character in Layer Cake, Gene, succinctly puts it — <em>&ldquo;meditation is concentrating the front of the mind with a mundane task so the rest of the mind can find peace&rdquo;</em>. Usually that focus is on our breathing.</p>
<p>The first thing you notice when you meditate is just how busy your mind is. It&rsquo;s like trying to get a dog to sit still so you can take its photo whilst there are squirrels running around. This is the first, and most valuable, thing you learn from the process — <em>being aware</em> of your mind. <a href="https://en.wikipedia.org/wiki/Robert_Wright_(journalist)">Robert Wright</a>:</p>
<blockquote>
<p>So when my turn came to speak, I gave voice to this frustration. The ensuing dialogue with my teacher went something like this:<br>
So you notice that your mind keeps wandering?<br>
Yes.<br>
That&rsquo;s good.<br>
It&rsquo;s good that my mind keeps wandering?<br>
No. It&rsquo;s good that you notice that your mind keeps wandering.<br>
But it happens, like, all the time.<br>
That&rsquo;s even better. It means you&rsquo;re noticing a lot.</p>
</blockquote>
<p>Wright talks about the <a href="https://en.wikipedia.org/wiki/Default_mode_network">default mode network</a>, an area of our brains best known for being active when we&rsquo;re not focused on the outside world and the brain is at wakeful rest. Being able to even notice this wandering is happening and to bring it under control is just the start of what mindfulness brings.</p>
<p>A few years ago my wife did an online course on mindfulness, and at the time I pooh-poohed it. Thinking of myself as being of a more scientific mind, something as woolly as meditation didn&rsquo;t fit. But then I suffered what I came to realise was <a href="https://www.bupa.co.uk/newsroom/ourviews/burnout">burnout</a>. I decided to be a little more open-minded and downloaded the <a href="https://headspace.com">Headspace</a> app on my phone.</p>
<p>I&rsquo;ve always found it hard to stay focussed on anything; it&rsquo;s probably how I ended up in product management 😃 Juggling lots of things at once suits the way my mind wanders (side note: writing blog posts is hard work). I am well aware I do not have a restful mind.</p>
<p>I digress. I started using the Headspace app with a minimal 10 minute meditation. Determined to &lsquo;play along&rsquo; with the gamification, I wanted to keep a streak going for as long as possible. I managed a year. 10 minutes, every single day, for 365 days. For starters, it was purgatory — even 10 minutes felt like forever, and nothing ever seemed to happen. Then one day I realised I was noticing things. I was noticing my mind wandering off, noticing feelings bubbling up — like frustration or anger. Although hard to describe, it&rsquo;s like suddenly having two minds — with one monitoring the other if it&rsquo;s running away.</p>
<blockquote>
<p>&ldquo;If you just sit and observe, you will see how restless your mind is. If you try to calm it, it only makes it worse, but over time it does calm, and when it does, there&rsquo;s room to hear more subtle things&ndash;that&rsquo;s when your intuition starts to blossom and you start to see things more clearly and be in the present more. Your mind just slows down, and you see a tremendous expanse in the moment. You see so much more than you could see before&rdquo;<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup></p>
</blockquote>
<p>I recall the first time I had an experience directly related to having practiced mindfulness for a long period. I’d flown to New York for a 45 minute presentation to a client, part of an important deal a colleague had been working on. That morning I did my usual 10 minute Headspace before I left the hotel. During my presentation, something very odd happened. I could almost &ldquo;see&rdquo; thoughts coming, as if they were on a road ahead of me and I was following them. The words I knew I wanted were appearing in my mind as if on a teleprompter — it&rsquo;s quite hard to describe, and I&rsquo;d think nothing of it if it wasn&rsquo;t for the fact I&rsquo;d experienced nothing like it before. A couple of years later a friend recommended I read Robert Wright&rsquo;s <em>Why Buddhism Is True</em> (she knows I&rsquo;m not at all spiritual, so knew this book would be good — she was right. I highly recommend reading it) and as I read this bit, I realised what I&rsquo;d experienced:</p>
<blockquote>
<p>&ldquo;Come to think of it, I had never seen this thought assume any form at all. But it now looked as if—literally looked as if—one part of my mind was speaking the thought to another part. There was even a kind of line tracing the path of the message, like an arrow on a diagram indicating the direction of communication. I watched this intracranial conversation, watched the message travel from sender to recipient, as a kind of outside observer, even though I thought of the recipient as in some sense being me. It’s almost impossible to convey in words the power of this experience and its aura of significance.&rdquo;</p>
</blockquote>
<p>He later talks about how chasing this kind of experience will only leave you disappointed. This is something that I&rsquo;ve learnt from meditation, it&rsquo;s best just left to do its thing. Have no expectations. It&rsquo;s a system, not a goal. Just do it and see what happens.</p>
<p>Wright&rsquo;s book is full of science, and Headspace have their own information on the details we now know about meditation&rsquo;s physical effects on the brain. Recently I came across <a href="https://www.inc.com/geoffrey-james/when-steve-jobs-died-at-56-his-brain-was-only-27.html">this article, about Steve Jobs</a>.</p>
<blockquote>
<p>&ldquo;There was one thing, however, that Jobs didn&rsquo;t know, although he might have guessed it to be true. Meditation does more than just calm you down and make you a better manager. Meditation literally causes your brain to age backwards.&rdquo;</p>
</blockquote>
<p>Last year I probably meditated two or three times a week, but I was up to 20-minute sessions. I no longer need the guidance of Headspace, but I’ve stuck with it as there are some interesting courses. I’ve done the ‘motivation’ course four times already, and it’s one I return to again and again. Plus, <a href="https://www.headspace.com/andy-puddicombe">Andy Puddicombe</a> often imparts some little gems of wisdom in his relaxing tone of voice. I can’t meditate for less than 20 minutes at a time now, it feels rushed. Most days are pretty terrible, with my mind wandering all over the place. But now and then I have a fantastic session, and the entire day seems to unfold in a more pleasant fashion. I’ve started 2021 with the goal of meditating every day, for the entire year, once again.</p>
<p><img src="headspace.jpg" alt="headspace"></p>
<p>I now find myself able to control my emotions, able to concentrate, able to see things far clearer than I could before. It feels easier to see a bigger picture — when I look at problems at work, I find my mind automatically ‘zooms out’ to find the wider context. My wife says I am more patient than I’ve ever been.</p>
<p>Mindfulness very much works for me. Will it work for you? To be candid, I can’t see a reason not to try. It’s a tool I would not want to be without.</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p><a href="https://www.inc.com/geoffrey-james/neuroscientists-confirm-that-steve-jobs-was-decades-ahead-of-his-time.html">https://www.inc.com/geoffrey-james/neuroscientists-confirm-that-steve-jobs-was-decades-ahead-of-his-time.html</a>&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>]]>
      
      <![CDATA[<hr><p>Thanks for reading this post via RSS! 👏</p>]]>
      <![CDATA[<a href="mailto:rs511@probably.co.uk?subject=Does mindfulness work?">Reply to this post by email</a>]]>
      </description>
    </item>
    <item>
      <title>Apple HomeKit invite fails with apparently no reason</title>
      <link>https://probably.co.uk/posts/2021-01-14-homekit-fail/</link>
      <pubDate>Thu, 14 Jan 2021 00:00:00 +0000</pubDate>
      <guid>https://probably.co.uk/posts/2021-01-14-homekit-fail/</guid>
      <description>
      
      <![CDATA[<p>What should be simple has this week turned out to be anything but.</p>
<p>I added a new camera to our home (<a href="https://www.logitech.com/en-gb/products/cameras/circle-view-security-camera.961-000490.html">Logitech Circle View</a> — pleasant experience so far) but it wasn&rsquo;t showing up on my wife&rsquo;s iPhone. So I ended up removing her from the home access and tried to re-invite. The invite sent OK, the notification came up on her phone OK, but clicking accept did nothing. In the Home app itself the invite &lsquo;accept&rsquo; button was missing, with a spinning icon there instead. No matter how long I left it, or whichever of the addresses associated with her iCloud account I tried, they all failed. I tried the iPad and the iPhone, to no avail. I tried logging out of iCloud on all her devices and back in again, which also failed.</p>
<p>This was beginning to get immensely frustrating, especially when searching for an answer I read on an Apple forum that you needed to delete the home and set it all back up again 😱 I was loathed to do that, as I have many devices associated. It would take hours.</p>
<p>Then I discovered an old comment on <a href="https://www.reddit.com/r/HomeKit/comments/92qwov/homekit_invitation_which_ends_in_infinite/e37s74i">a Reddit thread</a>, which said try signing out of iCloud on the invitee&rsquo;s device, signing in with your own — known working — ID on their device, checking Home looks right, signing back out and back in as them and resending an invite.</p>
<p>Bingo! Finally, it works.</p>
<p>What a faff. Totally inexplicable too, which is the doubly infuriating part.</p>]]>
      
      <![CDATA[<hr><p>Thanks for reading this post via RSS! 👏</p>]]>
      <![CDATA[<a href="mailto:rs511@probably.co.uk?subject=Apple HomeKit invite fails with apparently no reason">Reply to this post by email</a>]]>
      </description>
    </item>
    <item>
      <title>Postfix error cannot open file: Permission denied</title>
      <link>https://probably.co.uk/posts/2021-01-05-postfix-selinux/</link>
      <pubDate>Tue, 05 Jan 2021 00:00:00 +0000</pubDate>
      <guid>https://probably.co.uk/posts/2021-01-05-postfix-selinux/</guid>
      <description>
      
      <![CDATA[<p>I&rsquo;ve been moving email off of Google recently to the excellent service by <a href="https://hey.com">Hey.</a> But the temporary forwarding solution hit a snag with lots of apparently simple &ldquo;Permission denied&rdquo; messages.</p>
<p><code>postfix/bounce[26281]: fatal: open lock file pid/unix.bounce: cannot open file: Permission denied</code></p>
<p>Even with my [extremely] rusty tech skills I figured I could fix this one. <code>postfix set-permissions</code> is simple enough. Only, this didn&rsquo;t fix it. A quick <a href="https://duckduckgo.com/?q=postfix+pid+permission+denied">search</a> showed a few promising results — it&rsquo;s an <a href="https://en.wikipedia.org/wiki/Security-Enhanced_Linux">SELinux</a> problem. Almost every result therefore said <code>setenforce 0</code> solved it!</p>
<p><em>That&rsquo;s not the right answer</em>. SELinux is very useful to have in place for anything connected to the internet, so rather than disable it, I looked into fixing the issue properly. Luckily <a href="/posts/logwatch-output-to-nfs-with-selinux">I&rsquo;ve been here before,</a> many years ago. So referring to my previous blog post about SELinux, it took me all of 10 minutes to fix.</p>
<div class="overflow-hidden rounded-sm shadow-lg">
  
  <div class="flex items-center gap-2 bg-gray-200 px-4 py-2 dark:bg-gray-700">
    <div class="size-3 rounded-full bg-red-500"></div>
    <div class="size-3 rounded-full bg-yellow-500"></div>
    <div class="size-3 rounded-full bg-green-500"></div>
  </div>
  
  <div class="bg-white px-8 py-2 dark:bg-gray-900">
    <pre
      class="overflow-x-auto whitespace-pre-wrap break-words"
    ><code>sesearch -s postfix_bounce_t -t var_run_t -c dir -A
ausearch -m avc --start today | audit2allow -m postfix_pid_write -o postfix_pid_write.te
ausearch -m avc --start today | audit2allow -M postfix_pid_write
semodule -i postfix_pid_write.pp
semodule -l | grep postfix</code></pre>
  </div>
</div>
<p>Problem solved. SELinux still very much in place.</p>]]>
      
      <![CDATA[<hr><p>Thanks for reading this post via RSS! 👏</p>]]>
      <![CDATA[<a href="mailto:rs511@probably.co.uk?subject=Postfix error cannot open file: Permission denied">Reply to this post by email</a>]]>
      </description>
    </item>
    <item>
      <title>8 tips for better video meetings</title>
      <link>https://probably.co.uk/posts/2020-10-04_8-tips/</link>
      <pubDate>Sun, 04 Oct 2020 00:00:00 +0000</pubDate>
      <guid>https://probably.co.uk/posts/2020-10-04_8-tips/</guid>
      <description>
      
      <![CDATA[<p>I’ve spent most of the last decade working from home.</p>
<!-- more-->
<p>From 2014 until early 2020 I was working for a US company, where initially I was the only employee in Europe. Inevitably communication was either asynchronous — via Slack — or by video meeting.</p>
<p>2020 has seen a step change in the way we communicate, and we’ve learned a lot about <a href="https://www.ft.com/content/9fdb9a05-feed-4777-8498-acb5c500fa3d">people’s shelving</a>. But mostly, I’m still seeing a lot of scope for improving the way we use video meetings.</p>
<p><img src="shelves.jpg" alt="shelves"></p>
<p>I think a lot of the fatigue we’ve heard people complain of is down to the lack of direct human connection, and it’s exacerbated by the way we use our computers.</p>
<p>So I recorded a small video of some tips I’ve found to improve the video meeting experience. A lot of the tips don’t require spending any money either…</p>




<video controls poster="8-tips-thumb.png">
<source src="https://v.5318808.xyz/8_tips_to_improve_your_online_meetings.mov">
Your browser does not support the video tag.
</video>

]]>
      
      <![CDATA[<hr><p>Thanks for reading this post via RSS! 👏</p>]]>
      <![CDATA[<a href="mailto:rs511@probably.co.uk?subject=8 tips for better video meetings">Reply to this post by email</a>]]>
      </description>
    </item>
    <item>
      <title>5 books, part 5: Into the Woods by John Yorke</title>
      <link>https://probably.co.uk/posts/2020-02-26_5-books-part-5/</link>
      <pubDate>Wed, 26 Feb 2020 00:00:00 +0000</pubDate>
      <guid>https://probably.co.uk/posts/2020-02-26_5-books-part-5/</guid>
      <description>
      
      <![CDATA[<p><img src="into-the-woods.jpeg" alt="Into The Woods book cover"></p>
<blockquote>
<p>&ldquo;Good storytelling never gives you four, it gives you two plus two… Don&rsquo;t give the audience the answer, give them the pieces and let them conclude the answer&rdquo;</p>
</blockquote>
<p>Have you ever read a Michael Lewis book? Liars Poker, The Big Short, Flash Boys? They’re all books about the finance industry. I’m not sure I can think of a duller subject to write about. However, if you <em>have</em> read any of his books, you’ll know they are riveting reads. Clichéd it may be, but they’re unputdownable. This is because Lewis is a great storyteller.</p>
<p>Throughout this series of reviews we’ve visited books on <a href="/posts/2019-12-10_5-books-part-1/">psychology</a>, <a href="/posts/2020-01-17_5-books-part-3/">company</a> <a href="/posts/2019-12-16_5-books-part-2/">culture</a> and <a href="/posts/2020-02-05_5-books-part-4/">marketing</a>. All these topics have the potential to be dry fact-filled subjects. But like Michael Lewis, each author is adept at telling stories, so the books are a compelling read.</p>
<p>In <em>Into the Woods</em>, John Yorke uses his 30 years&rsquo; experience of TV drama production to tell the story of the shape of all successful narratives. Without the ability to tell compelling stories, we&rsquo;ll not be able to impart any of the information we&rsquo;ve learned through the first four books.</p>
<p>The opening quote is from <a href="https://youtu.be/KxDwieKpawg?t=438">Andrew Stanton of Pixar</a>, albeit paraphrased. It continues:</p>
<blockquote>
<p>“Audiences have an unconscious desire to work for their entertainment. They are rewarded with a sense of thrill and delight when they find the answers themselves.”</p>
</blockquote>
<p>What&rsquo;s so interesting to me about this, is it ties in with things learned from <a href="/posts/2020-02-05_5-books-part-4/">Rory Sutherland</a> <em>&ldquo;people seem to like choice for its own sake&rdquo;</em> and <a href="/posts/2019-12-10_5-books-part-1/">Daniel Kahneman</a> <em>&ldquo;The more information, logic and reasoning you present to try to get an idea across, the more you actually push the audience away&rdquo;</em>. This is probably because you&rsquo;re leaving the audience nothing to do, they don&rsquo;t have to work for the answers.</p>
<p>The book goes into the basic structure of any story, as a commonly known three act structure. There is the thesis, the antithesis and the synthesis. Put another way in Hollywood simplicity terms:</p>
<p>Act One: Establish flawed character<br>
Act Two: Confront them with their opposite<br>
Act Three: Synthesise the two to establish balance</p>
<blockquote>
<p>&ldquo;The endless recurrence of the same underlying pattern suggests psychological, if not biological and physical reasons for the way we tell stories. If we don&rsquo;t choose to tell them that way, perhaps we are compelled to.&rdquo;</p>
</blockquote>
<p>This statement from the book made me think of Kahneman&rsquo;s studies and Sutherland&rsquo;s observations once again. Is there something built in to us that means a story structured in this way compels us more? If we break from that structure, do we make our story less effective?</p>
<blockquote>
<p>&ldquo;‘Story as such’, said E. M. Forster, ‘can only have one merit: that of making the audience want to know what happens next. And conversely it can only have one fault: that of making the audience not want to know what happens next.&rdquo;</p>
</blockquote>
<p><img src="lemon.jpg" alt="lemon"></p>
<p>This is the famous Volkswagen Beetle advert. It&rsquo;s widely recognised as a genius piece of marketing. <em>“The advert sucks you in; it impels you to do the work…because it generates conflict and the desire for its resolution”</em>. It is model storytelling on a single page.</p>
<p>Being cognisant of giving too much information, here are two final pieces of useful material. One, another book — <a href="https://www.duarte.com/resonate/">Resonate by Nancy Duarte</a> is great if you need to present at all. It&rsquo;s a great guide to making compelling presentations. Speaking of which, here&rsquo;s <a href="https://medium.com/the-mission/the-best-sales-pitch-ive-seen-all-year-7fa92afaa248">a brilliant startup pitch</a>. Can you see the clear three act structure?</p>
<p>I’ve read <a href="/posts/2019-12-03_5-inspirational-books/">these five books</a> over the course of the last three or four years, starting with Creativity, Inc, then Into the Woods. The last of the five was Rory Sutherland’s Alchemy, which I read last year. I had no idea they would interweave in the manner they do, and none of them came to my attention through the forced serendipity of a digital algorithm. It is only with hindsight that I realise they lay such good foundations for achieving almost anything in the modern workplace. A simple set of rules, a manifesto if you like, could easily be formed using ideas in these five books from which to build products, teams or even whole companies. Maybe that’s a future post…</p>]]>
      
      <![CDATA[<hr><p>Thanks for reading this post via RSS! 👏</p>]]>
      <![CDATA[<a href="mailto:rs511@probably.co.uk?subject=5 books, part 5: Into the Woods by John Yorke">Reply to this post by email</a>]]>
      </description>
    </item>
    <item>
      <title>5 books, part 4: Alchemy by Rory Sutherland</title>
      <link>https://probably.co.uk/posts/2020-02-05_5-books-part-4/</link>
      <pubDate>Wed, 05 Feb 2020 00:00:00 +0000</pubDate>
      <guid>https://probably.co.uk/posts/2020-02-05_5-books-part-4/</guid>
      <description>
      
      <![CDATA[<p><img src="alchemy.jpeg" alt="Alchemy book cover"></p>
<blockquote>
<p>“Things are not what they are; they are what we think they are”</p>
</blockquote>
<p>My wife is a cryptic crossword fan, and she’s very good at them. I’ll confess, I am hopeless at them. The secret to cryptic crosswords is not to take the clues <em>literally</em>. There are patterns and rules that can lead you to the answer, and there are always signatures or cues to the crossword <a href="https://en.wikipedia.org/wiki/Cryptic_crossword">setter</a>. The reasons for an answer may not be all that obvious.</p>
<p>So if &ldquo;reality&rdquo; is only what we <strong>think</strong> it is, does that mean there is scope for changing perception without having to actually change <em>anything</em>? Can a little ‘cryptic crossword magic’ apply to the everyday? Rory Sutherland seems to think so, and his book ended up being the most enjoyable read I had last year.</p>
<h3 id="thinking-differently">Thinking differently</h3>
<blockquote>
<p>“To avoid stupid mistakes, learn to be slightly silly”</p>
</blockquote>
<p>Throughout the book Sutherland gives examples of  &ldquo;psychological moonshots&rdquo;. Take the Uber map — it doesn&rsquo;t reduce the waiting time for a taxi but makes waiting less frustrating. His TED talk from Athens is worth <a href="https://youtu.be/iueVZJVEmEs?t=382">a watch</a>. Just view the next minute or two from here (the link should take you to 6:22 in) where he talks about how we could’ve saved billions on the Eurostar HS1 train link. OK, so it’s a little flippant, but it&rsquo;s an alternative way to get us to look at the same situation differently.</p>
<p>As with the other three books visited up to now, Sutherland tells a great story. Throughout the book there are more examples like his HS1 suggestion that were less flippant and actually used (charity mail shots and pension planning, to name two seemingly dull topics brightened by a little <em>alchemy</em>). He’s also visited a lot of the same books as I’ve been drawn to in this series, often referencing <a href="/posts/2019-12-10_5-books-part-1/">Kahneman&rsquo;s</a> material, for example. </p>
<p>One book he mentions I’ve not read — <a href="https://www.amazon.co.uk/dp/0241957850/ref=cm_sw_em_r_mt_dp_U_OThoEb6XMHG5X">The enigma of reason</a> by Dan Sperber and Hugo Mercier. I’m sure we’d all like to think we make decisions by deductive reasoning, but Sperber and Mercier came to a different conclusion:</p>
<blockquote>
<p>“One astonishing possible explanation for the function of reason only emerged about ten years ago: the argumentative hypothesis suggests reason arose in the human brain not to inform our actions and beliefs, but to explain and defend them to others. In other words, it is an adaptation necessitated by our being a highly social species.”</p>
</blockquote>
<p>This explains another of Sutherland’s comments, which I’m sure all of us in corporate life have sadly experienced at one time or another:</p>
<blockquote>
<p>“what often matters most to those making a decision in business or government is not a successful outcome, but their ability to defend their decision, whatever the outcome may be.”</p>
</blockquote>
<p>We are so often led down the garden path by the need to appear logical and scientific, when a better result may come from thinking quite the opposite. And this is what Sutherland attempts to get us to do throughout the book (<em>&ldquo;This book is intended as a provocation&rdquo;</em>). As he says very early in the book, <em>&ldquo;the opposite of a good idea can also be a good idea&rdquo;</em>.</p>
<p>It takes courage to think differently to the crowd, but if you don’t think differently, how will you stand out when you need to? New products, companies and even working methods in existing organisations will require different thinking. The ideas in this book, coupled up with <a href="/posts/2020-01-17_5-books-part-3/">Loonshots</a>, should be preparation enough for most of us.</p>
<p>Let’s leave <em>Alchemy</em> with a subsection heading from the book. The importance of this can’t be understated:</p>
<blockquote>
<p>“Context is everything”</p>
</blockquote>
<p>Come back next time for the final part in the series, when we’ll look at John Yorke’s <a href="/posts/2020-02-26_5-books-part-5/">Into the Woods</a>, a book about storytelling.</p>
]]>
      
      <![CDATA[<hr><p>Thanks for reading this post via RSS! 👏</p>]]>
      <![CDATA[<a href="mailto:rs511@probably.co.uk?subject=5 books, part 4: Alchemy by Rory Sutherland">Reply to this post by email</a>]]>
      </description>
    </item>
    <item>
      <title>5 books, part 3: Loonshots by Safi Bahcall</title>
      <link>https://probably.co.uk/posts/2020-01-17_5-books-part-3/</link>
      <pubDate>Fri, 17 Jan 2020 00:00:00 +0000</pubDate>
      <guid>https://probably.co.uk/posts/2020-01-17_5-books-part-3/</guid>
      <description>
      
      <![CDATA[<p><img src="loonshots.jpeg" alt="Loonshots book cover"></p>
<blockquote>
<p>Loonshot: a widely dismissed idea whose champions are often written off as crazy.</p>
</blockquote>
<p>If you’ve ever worked in a corporate, I’m sure you’ll have heard somebody at some point say: <em>&ldquo;that&rsquo;s not the way we do things around here&rdquo;</em>. The culture of maintaining the status quo brings about <a href="https://fs.blog/carol-dweck-mindset/">fixed mindsets</a>, yet if there’s one constant, it’s change. To keep up in today’s technology-led, ever changing world, a business needs to be innovative.</p>
<p><em>Loonshots</em> addresses the disconnect between being innovative and trying to maintain stability. These are two different worlds, with different mindsets. Through a variety of stories and characters, Safi Bahcall shows how large organisations in the past have successfully created ‘loonshot nurseries’. </p>
<p>You could easily use <em>Loonshots</em> as a manifesto for how to innovate inside a large organisation. The <a href="https://www.bahcall.com/loonshots-contents/">appendix</a> of the book even lists a set of rules for guidance. But it’s not just about enabling innovation, the ideas within <em>Loonshots</em> can help with bridging any disparate worlds.</p>
<p>Without listing the rules (other blog reviews have, I’ll not detract from the value of reading the whole book though) there are a few valuable lessons in <em>Loonshots</em>.</p>
<p>There are large differences in culture between corporates and startups, dictated by a simple idea — <a href="https://en.wikipedia.org/wiki/Dunbar%27s_number">Dunbar’s Number</a>. Bahcall discusses Dunbar’s Number, and how some organisational structure changes can remove the barrier it creates. There’s a very interesting chapter on <a href="https://en.wikipedia.org/wiki/DARPA">DARPA</a>, for example, which shows ‘soft equity’ as a motivation tool.</p>
<p>Speaking of motivation, reading that chapter reminded me of Dan Pink’s <a href="https://youtu.be/rrkrvAUbU9Y">the puzzle of motivation</a> talk. It’s worth a watch if you’ve not seen it before.</p>
<blockquote>
<p>&ldquo;Separate your artists and soldiers&rdquo;</p>
</blockquote>
<p>With his background in science, Bahcall naturally references his knowledge throughout the book. He compares the shift away from an innovative company to a <a href="https://en.wikipedia.org/wiki/Phase_transition">phase transition</a>. Put another way, a <em>tipping point</em>. In trying to recapture the innovative spirit, he recommends forming exclusive teams, with the creative inventor types separated from the day-to-day operations.</p>
<p>That should immediately strike you as a recipe for disaster. It’s highly likely to create a ‘them and us’ culture. Which is where his next historic example comes in, from the mind of <a href="https://en.wikipedia.org/wiki/Vannevar_Bush">Vannevar Bush</a>, ‘create dynamic equilibrium’. Create a separate team, department or subsidiary, but make sure it, and the parent, are in constant communication. This reminded me of <a href="https://youtu.be/0MD4Ymjyc2I">a TED talk</a> I’d watched some years ago by Yves Morieux, titled <em>&ldquo;As work gets more complex, 6 rules to simplify&rdquo;</em> (if you’d like to read rather than watch, there’s <a href="https://www.bcg.com/publications/2011/smart-rules.aspx">a blog post</a> by Yves too). Rule number 1: understand what your colleagues do.</p>
<blockquote>
<p>&ldquo;And then we’ll see how small changes in structure can transform the behaviour of groups&rdquo;</p>
</blockquote>
<p>If you work in the technology industry, you&rsquo;ll see a parallel that was a great idea but has failed to deliver for many; DevOps. The original ethos was about connecting the stability seeking ‘ops’ world with the innovation-chasing ‘dev’ world. Products and consultancies sprang up, promising to bring you the all important innovation through DevOps. Yet most miss the key part of the puzzle, <strong>people</strong>. DevOps teams become a new silo, with the dynamic equilibrium sadly absent.</p>
<p>Bahcall and Morieux have one thing in common: their ideas learn from Vannevar Bush’s thinking. It’s funny that we’d solved a lot of these problems 80 years ago, isn’t it?</p>
<p>In the next post of <a href="/posts/2019-12-03_5-inspirational-books/">the series</a> we’ll look at <a href="/posts/2020-02-05_5-books-part-4/">Rory Sutherland’s Alchemy</a>. This was the most enjoyable book I read in 2019. It made me realise something so obvious—every coin has two sides. If you can’t change the situation, reframe it.</p>]]>
      
      <![CDATA[<hr><p>Thanks for reading this post via RSS! 👏</p>]]>
      <![CDATA[<a href="mailto:rs511@probably.co.uk?subject=5 books, part 3: Loonshots by Safi Bahcall">Reply to this post by email</a>]]>
      </description>
    </item>
    <item>
      <title>5 books, part 2: Creativity, Inc. by Ed Catmull</title>
      <link>https://probably.co.uk/posts/2019-12-16_5-books-part-2/</link>
      <pubDate>Mon, 16 Dec 2019 00:00:00 +0000</pubDate>
      <guid>https://probably.co.uk/posts/2019-12-16_5-books-part-2/</guid>
      <description>
      
      <![CDATA[<p><img src="creativity-inc.jpeg" alt="Creativity, Inc book cover"></p>
<blockquote>
<p>&ldquo;Figuring out how to build a sustainable culture … wasn&rsquo;t a singular assignment. It was a day-in-day-out, full-time job.&rdquo;</p>
</blockquote>
<p>Ed Catmull is the retired former president and co-founder of digital animation studio, Pixar. <em>Creativity, Inc.</em> is the story of how Pixar overcame the challenges all businesses face to create and maintain a successful culture as the company grew. A culture that could outlast its founders.</p>
<p><img src="google_company_culture.jpg" alt="google hits"></p>
<p><em>To say there has been a lot written about company cultures is an understatement. 4.2 <strong>billion</strong> hits in a Google search!</em></p>
<p>I’ve had a bee in my bonnet about company culture for a while. Having started several times to write a blog about it, I couldn’t nail what I wanted to say succinctly enough. The opening quote on this post succeeds where I struggled. That’s the nub of the issue—you can’t just set your company culture up with some words and expect it to survive as you grow. Company culture is like a relationship; it needs ongoing attention to keep it alive and well.</p>
<p>Reviewing my notes for Creativity, Inc. I see there are 96 highlights! This is by far the most highlights I’ve made in a book in recent times. So much of Creativity, Inc. struck a chord with me.</p>
<blockquote>
<p>&ldquo;Even now, forty years later, I&rsquo;ve never stopped questioning.&rdquo;</p>
</blockquote>
<p>This statement on its own should be a guiding light. <em>Never stop questioning</em>. At some point in our adult lives that seems to happen though. People accept the status quo and chug along. But building a company can’t be like that. Any startup needs to be questioning — with good intent — everything that has gone before, else they cannot hope to compete. How do you differentiate yourself from companies in the same space if you do as they do?</p>
<p>Mr Catmull, again:</p>
<blockquote>
<p>&ldquo;The pricing advice I was given—by people who were smart and experienced—was not merely wrong, it kept us from asking the right questions.&rdquo;</p>
</blockquote>
<p>This complements a section of <a href="/posts/2019-12-10_5-books-part-1/">Thinking, Fast and Slow</a>, where Mr Kahneman talks about &lsquo;<a href="https://en.wikipedia.org/wiki/Anchoring_(cognitive_bias)">anchoring</a>&rsquo;. It&rsquo;s important to recognise this can happen and develop a technique for keeping one&rsquo;s own bias in check.</p>
<p>With that in mind, one of the greatest lessons I took from Creativity, Inc. was about drawing. As part of learning how to use their software internally, they also hired an art teacher to teach people how to draw. There was more to this than first meets the eye:</p>
<blockquote>
<p>&ldquo;Another trick is to ask students to focus on negative spaces—the areas around an object. For instance, in drawing a chair, the new artist might draw it poorly, because she knows what a chair is supposed to look like (and that chair in her head—her mental model—keeps her from reproducing what she sees in front of her). However, if she is asked to draw what is <strong>not</strong> the chair—the spaces between the chair legs, for example—then the proportions are easier to get right, and the chair itself will look more realistic.&rdquo;</p>
</blockquote>
<p>The idea behind this exercise is to help the brain see what&rsquo;s <strong>really</strong> there, and not what it <strong>thinks</strong> is there.  It&rsquo;s easy to fool the brain, bcse it wnts to mk snse f th wrld, evn f it dsnt mke snse. I love the metaphor of drawing around the chair and frequently use it to challenge my thinking.</p>
<p>Building a company culture is one thing, maintaining it is a whole other mission. Creativity, Inc. goes into how Pixar recaptured their original culture, after the founders realised it was slipping away as the company grew larger. There is a great deal of sound advice in this book, and as expected of master storytellers Pixar, it&rsquo;s told well. I&rsquo;ll leave you with one last quote:</p>
<blockquote>
<p>&ldquo;To me, the answer should be obvious: Ideas come from people. Therefore, people are more important than ideas.&rdquo;</p>
</blockquote>
<p>In part three we&rsquo;ll review <a href="/posts/2020-01-17_5-books-part-3/">Loonshots by Safi Bahcall</a>.</p>]]>
      
      <![CDATA[<hr><p>Thanks for reading this post via RSS! 👏</p>]]>
      <![CDATA[<a href="mailto:rs511@probably.co.uk?subject=5 books, part 2: Creativity, Inc. by Ed Catmull">Reply to this post by email</a>]]>
      </description>
    </item>
    <item>
      <title>5 books, part 1: Thinking, Fast and Slow by Daniel Kahneman</title>
      <link>https://probably.co.uk/posts/2019-12-10_5-books-part-1/</link>
      <pubDate>Mon, 09 Dec 2019 00:00:00 +0000</pubDate>
      <guid>https://probably.co.uk/posts/2019-12-10_5-books-part-1/</guid>
      <description>
      
      <![CDATA[<p><img src="thinking.jpeg" alt="Thinking, Fast and Slow book cover"></p>
<blockquote>
<p>&ldquo;The world makes much less sense than you think. The coherence comes mostly from the way your mind works.&rdquo;</p>
</blockquote>
<p>Following on from the <a href="/posts/2019-12-03_5-inspirational-books/">introduction post</a>, if there&rsquo;s one important takeaway I learned from reading <em>Thinking, Fast and Slow</em> by Nobel Prize winning <a href="https://www.nobelprize.org/prizes/economic-sciences/2002/kahneman/facts/">Daniel Kahneman</a>, it&rsquo;s don&rsquo;t always trust whatever thought first comes to mind.</p>
<p>While reading this book I enjoyed the insight into how my own thinking works. Kahneman&rsquo;s approach of telling a story about our brains as if they&rsquo;re two characters, which he calls <a href="https://en.wikipedia.org/wiki/Dual_process_theory">System 1 and System 2</a>, goes a long way to showing how our subconscious mind can easily fool our decision making.</p>
<p>I&rsquo;ve long been fond of challenging my initial <em>gut feeling</em> on anything, but this book introduced me to <a href="https://hbr.org/2007/09/performing-a-project-premortem">the premortem</a>. Attributed to psychologist Gary Klein, the premortem could be a saving step for any project:</p>
<blockquote>
<p>The premise of the session is a short speech: &ldquo;imagine that we are a year into the future. We implemented the plan as it now exists. The outcome was a disaster. Please take 5 to 10 minutes to write a brief history of that disaster.&rdquo;</p>
</blockquote>
<p>This forces us to think of the exact opposite of what we&rsquo;ve been planning for. An imaginative way to keep our assumptions in check.</p>
<p>One powerful example of our natural tendency to think irrationally is <strong>the Linda problem</strong>, otherwise known as the <a href="https://en.wikipedia.org/wiki/Conjunction_fallacy">conjunction fallacy</a>. Before you head off to the Wikipedia page, test yourself:</p>
<blockquote>
<p>Linda is 31 years old, single, outspoken, and very bright. She majored in philosophy. As a student, she was deeply concerned with issues of discrimination and social justice, and also participated in anti-nuclear demonstrations.</p>
<p>Which is more probable?</p>
<ol>
<li>Linda is a bank teller.</li>
<li>Linda is a bank teller and is active in the feminist movement.</li>
</ol>
</blockquote>
<p>Which did you pick? Now you can read <a href="https://en.wikipedia.org/wiki/Conjunction_fallacy">the Wikipedia page</a>.</p>
<h3 id="improving-your-influencing-skills">Improving your influencing skills</h3>
<p>You&rsquo;ll find a lot of blog posts written off the back of <em>Thinking, Fast and Slow</em>. <a href="https://odean.com">Tyler Odean</a>, a product manager at Reddit (and formerly, Google), uses Kahneman&rsquo;s writing as the base for an article on <a href="https://firstround.com/review/master-the-art-of-influence-persuasion-as-a-skill-and-habit/">improving your influencing skills</a>.</p>
<blockquote>
<p>&ldquo;The more information, logic and reasoning you present to try to get an idea across, the more you actually push the audience away&rdquo;</p>
</blockquote>
<p>I found Kahneman&rsquo;s book to be a valuable read, not only because it’s given me a new insight into my own thinking. It has also given me the ability to see everything has a reason—even when one doesn’t appear clearly or immediately. The book brings so much more weight to a statement I’ve sworn by for years:</p>
<p><strong>K I S S: Keep It Simple, Stupid</strong></p>
<p>Next time we&rsquo;ll take a look at <a href="/posts/2019-12-16_5-books-part-2/">Creativity, Inc by Ed Catmull</a>.</p>]]>
      
      <![CDATA[<hr><p>Thanks for reading this post via RSS! 👏</p>]]>
      <![CDATA[<a href="mailto:rs511@probably.co.uk?subject=5 books, part 1: Thinking, Fast and Slow by Daniel Kahneman">Reply to this post by email</a>]]>
      </description>
    </item>
    <item>
      <title>Five books to inspire better companies, teams and products</title>
      <link>https://probably.co.uk/posts/2019-12-03_5-inspirational-books/</link>
      <pubDate>Tue, 03 Dec 2019 00:00:00 +0000</pubDate>
      <guid>https://probably.co.uk/posts/2019-12-03_5-inspirational-books/</guid>
      <description>
      
      <![CDATA[<blockquote>
<p>&ldquo;The human mind does not run on logic any more than a horse runs on petrol.&rdquo;</p>
</blockquote>
<p>This quote, from Rory Sutherland, has become like a pebble dropped into a pond for me. Having spent most of my career working in the technology industry, logic has led me everywhere. However, I worry logic and data have often blinded me to simple truths. <em>We can solve every problem with logic</em>. Except now I’ve read these five books, I realise logic has little to do with it.</p>
<p>Interwoven across these five books is a recipe for building successful companies, teams and products. They&rsquo;ve given me a deep understanding of a journey I experienced, but didn&rsquo;t fully comprehend at the time.</p>
<p>Having worked in some of the largest corporations in the world and in startups, I now realise they are different worlds. They feel almost exclusive, where each world will advertise jobs requiring experience of <em>their world</em>. Today, more than ever, that&rsquo;s a mistake. Because each world can learn from the other, and to keep up with the rapid pace of technological progress, <strong>they should</strong>.</p>
<p>For the sake of brevity, today I&rsquo;ll just introduce the books. In a set of follow-up posts, I&rsquo;ll go into more detail about their relevance and the points I found most helpful.</p>
<ol>
<li>Daniel Kahneman - <a href="/posts/2019-12-10_5-books-part-1/">Thinking, Fast and Slow</a></li>
<li>Ed Catmull — <a href="/posts/2019-12-16_5-books-part-2/">Creativity, Inc </a></li>
<li>Safi Bahcall — <a href="/posts/2020-01-17_5-books-part-3/">Loonshots</a></li>
<li>Rory Sutherland — <a href="/posts/2020-02-05_5-books-part-4/">Alchemy</a></li>
<li>John Yorke — <a href="/posts/2020-02-26_5-books-part-5/">Into the woods</a></li>
</ol>
<p>I could probably extend this list out to 10 or 20 without trying too hard. I often refer to anecdotes from Matthew Syed&rsquo;s <em>Bounce</em> and Malcolm Gladwell&rsquo;s <em>Outliers</em>. In more recent years, I&rsquo;ve also read <a href="/posts/how-minds-change/">David McRaney&rsquo;s How Minds Change</a> and found it to be immensely valuable, along with <a href="/posts/design-of-everyday-things/">Don Norman&rsquo;s The Design of Everyday Things</a>.</p>
<p>These books have given me insight into why we all think the way we do, why I prefer working in forward-looking, agile, companies, how large companies can learn a lot from small ones (and vice versa) and how the immediate answer that comes to mind is rarely the one to take you forward in anything.</p>
<p>I&rsquo;ve come away from reading each one of these books with renewed energy and a mind spinning with ideas. If you&rsquo;ve read any of them too, I&rsquo;d love to hear your thoughts <a href="https://linkedin.com/in/markphillips">on LinkedIn</a> or <a href="https://mastodon.social/@thismarkp">Mastodon</a>.</p>]]>
      
      <![CDATA[<hr><p>Thanks for reading this post via RSS! 👏</p>]]>
      <![CDATA[<a href="mailto:rs511@probably.co.uk?subject=Five books to inspire better companies, teams and products">Reply to this post by email</a>]]>
      </description>
    </item>
    <item>
      <title>A data centric approach to patching systems with Ansible</title>
      <link>https://probably.co.uk/posts/2019-06-04_a-data-centric-approach-to-patching-systems-with-ansible/</link>
      <pubDate>Tue, 04 Jun 2019 00:00:00 +0000</pubDate>
      <guid>https://probably.co.uk/posts/2019-06-04_a-data-centric-approach-to-patching-systems-with-ansible/</guid>
      <description>
      
      <![CDATA[<p>When patching Linux machines these days I could forgive you for asking <em>&ldquo;how hard can it be?&rdquo;</em> Sure, a <code>yum update -y</code> will sort it for you in a flash…</p>
<p><img src="quick_update.gif" alt="Update"></p>
<p>But for those of us working with estates larger than a handful of machines it&rsquo;s not that simple. Sometimes an update can create unintended consequences across many machines and you’re left wondering how to put things back the way they were. Or you might think <em>&ldquo;should I have applied the critical patch on its own and saved myself a lot of pain?&rdquo;</em></p>
<p>Faced with these sorts of challenges in the past led me to build a way to &lsquo;cherry-pick&rsquo; the updates needed and automate their application.</p>
<h2 id="a-flexible-idea">A flexible idea</h2>
<p>Here&rsquo;s an overview of the process which we&rsquo;ll apply technology to in a moment…</p>
<p><img src="patch_process.png" alt="Process"></p>
<p>Under this system, we do not permit machines direct access to vendor patches. Instead, they&rsquo;re selectively subscribed to repositories. Repositories contain only the patches required – although I&rsquo;d encourage you to give this careful consideration so you don&rsquo;t end up with a proliferation (another management overhead you&rsquo;ll not thank yourself for making).</p>
<p>Now patching a machine comes down to 1) the repositories it&rsquo;s subscribed to and 2) the &rsquo;thumbs up&rsquo; to patch. With variables controlling both subscription and permission to patch we need not tamper with the logic (the plays), we only need to alter data.</p>
<p>Here is <a href="https://github.com/phips/ansible-patching/blob/master/roles/patching/tasks/main.yml">an example Ansible role</a> to fulfil both requirements. It manages repository subscriptions and has a simple variable to control running the patch command:</p>
<div class="overflow-hidden rounded-sm shadow-lg">
  
  <div class="flex items-center gap-2 bg-gray-200 px-4 py-2 dark:bg-gray-700">
    <div class="size-3 rounded-full bg-red-500"></div>
    <div class="size-3 rounded-full bg-yellow-500"></div>
    <div class="size-3 rounded-full bg-green-500"></div>
  </div>
  
  <div class="bg-white px-8 py-2 dark:bg-gray-900">
    <pre
      class="overflow-x-auto whitespace-pre-wrap break-words"
    ><code>---
# tasks file for patching

- name: Include OS version specific differences
  include_vars: &#34;{{ ansible_distribution }}-{{ ansible_distribution_major_version }}.yml&#34;

- name: Ensure Yum repositories are configured
  template:
    src: template.repo.j2
    dest: &#34;/etc/yum.repos.d/{{ item.label }}.repo&#34;
    owner: root
    group: root
    mode: 0644
  when: patching_repos is defined
  loop: &#34;{{ patching_repos }}&#34;
  notify: patching-clean-metadata

- meta: flush_handlers

- name: Ensure OS shipped yum repo configs are absent
  file:
    path: &#34;/etc/yum.repos.d/{{ patching_default_repo_def }}&#34;
    state: absent

# add flexibility of repos here
- name: Patch this host
  shell: &#39;yum update -y&#39;
  args:
    warn: false
  when: patchme|bool
  register: result
  changed_when: &#34;&#39;No packages marked for update&#39; not in result.stdout&#34;</code></pre>
  </div>
</div>
<h2 id="scenarios">Scenarios</h2>
<p>In our fictitious, large, globally dispersed environment (of four hosts) we have…</p>
<ul>
<li>Two web servers</li>
<li>Two database servers</li>
<li>An application, comprising one of each server type</li>
</ul>
<p>OK, so the number of machines I&rsquo;m showing here aren&rsquo;t &rsquo;enterprise scale&rsquo;, but remove the counts and imagine the environment as multiple tiered applications, dispersed geographically. What we want to do is patch elements of the stack; across server types, application stacks, geographies, or the whole estate.</p>
<p><img src="patch_groups.png" alt="Groups"></p>
<p>Using only changes to variables, can we achieve that flexibility? Sort of. Ansible&rsquo;s <a href="https://docs.ansible.com/ansible/2.3/playbooks_variables.html#variable-precedence-where-should-i-put-a-variable">default behaviour</a> for hashes is to overwrite. In our example the <code>patching_repos</code> variable for our db1 and web1 hosts gets overwritten by their later occurrence in our inventory. Hmm, a bit of a pickle. There are two ways to cater for this:</p>
<ol>
<li>Multiple inventory files</li>
<li><a href="https://docs.ansible.com/ansible/2.3/intro_configuration.html#sts=hash_behaviour">Change the variable behaviour</a></li>
</ol>
<p>I chose number one, because it maintains clarity. Once you start merging variables it&rsquo;s hard to find where a hash appears and how it&rsquo;s put together. Forcing yourself to use the default behaviour maintains clarity and is the method I&rsquo;d encourage you to stick with, for your own sanity.</p>
<h2 id="get-on-with-it-then">Get on with it then</h2>
<p>Let&rsquo;s run the play, focussing only on the database servers.</p>




<video controls poster="">
<source src="https://v.5318808.xyz/patch-db.mp4">
Your browser does not support the video tag.
</video>

<p>Did you notice the final step, &lsquo;Patch this host&rsquo;, says &lsquo;skipping&rsquo;? That&rsquo;s because we didn&rsquo;t set <a href="https://github.com/phips/ansible-patching/blob/d380e4a78031e72c437908394698fb599990240a/roles/patching/defaults/main.yml#L4">the controlling variable</a> to actually do the patching. What we have done is set up the repository subscriptions, ready.</p>
<p>So let&rsquo;s run the play again, limiting to the web servers, and tell it to actually do the patching. I&rsquo;ll run with verbose output set, just so you can see the yum updates happening:</p>




<video controls poster="">
<source src="https://v.5318808.xyz/patch-web.mp4">
Your browser does not support the video tag.
</video>

<p>Patching an application stack has required another inventory file, as discussed above. Let&rsquo;s run the play again:</p>




<video controls poster="">
<source src="https://v.5318808.xyz/patch-app1.mp4">
Your browser does not support the video tag.
</video>

<p>Patching hosts in the European geography is the same ethos as the application stack, and we achieve it with another inventory file:</p>




<video controls poster="">
<source src="https://v.5318808.xyz/patch-emea.mp4">
Your browser does not support the video tag.
</video>

<p>Finally, now all the repository subscriptions are configured, let&rsquo;s just patch the whole estate. Note the app1 and emea groups don&rsquo;t need the inventory here – we were only using the inventories for separation of repository definition and set up. They&rsquo;re now configured, so the <code>yum update -y</code> patches everything. If you didn&rsquo;t want to capture those repositories they could be configured as <code>enabled=0</code>:</p>




<video controls poster="">
<source src="https://v.5318808.xyz/patch-all.mp4">
Your browser does not support the video tag.
</video>

<h2 id="conclusion">Conclusion</h2>
<p>The flexibility comes from how we group our hosts. But with the default hash behaviour we need to think about overlaps – the easiest way, to my mind at least, is with separate inventories.</p>
<p>With regards to repository set up, I&rsquo;m sure you&rsquo;ve already said to yourself, <em>&ldquo;ah, but the cherry picking isn&rsquo;t that simple!&rdquo;</em> In this model there is additional overhead to download patches, test they work together, and bundle them with dependencies in a repository. With complementary tools you could automate the process, and in a large scale environment you&rsquo;d have to.</p>
<p>There is a part of me drawn to just applying full patch sets as a simpler and easier way to go. Skip out the cherry picking part, and apply a full set of patches to a &lsquo;standard build&rsquo;. I’ve seen this approach applied to both UNIX and Windows estates in the past – with an enforced quarterly update.</p>
<p>I’d be interested in hearing your experiences of patching regimes, and the approach proposed here, <a href="https://mastodon.social/@thismarkp">via Mastodon</a>.</p>]]>
      
      <![CDATA[<hr><p>Thanks for reading this post via RSS! 👏</p>]]>
      <![CDATA[<a href="mailto:rs511@probably.co.uk?subject=A data centric approach to patching systems with Ansible">Reply to this post by email</a>]]>
      </description>
    </item>
    <item>
      <title>Hardware bootstrapping with Ansible</title>
      <link>https://probably.co.uk/posts/2019-05-13_hardware-bootstrapping-with-ansible/</link>
      <pubDate>Mon, 13 May 2019 00:00:00 +0000</pubDate>
      <guid>https://probably.co.uk/posts/2019-05-13_hardware-bootstrapping-with-ansible/</guid>
      <description>
      
      <![CDATA[<p>At a recent <a href="https://www.meetup.com/Ansible-London/">Ansible London Meetup</a> I was chatting with somebody about automated hardware builds. <em>&ldquo;It&rsquo;s all cloud now!&rdquo;</em> I hear you say. Ah, but for many large organisations it&rsquo;s not — they still have massive data centres full of hardware. Almost regularly somebody pops up on our internal mail list and asks <em>&ldquo;can Ansible do hardware provisioning?&rdquo;</em>. Well yes, you can provision hardware with Ansible.</p>
<h2 id="requirements">Requirements</h2>
<p>Bootstrapping hardware is mostly about network services. Before we can install an operating system (OS) then, we must first set up some services. We need:</p>
<ul>
<li>DHCP</li>
<li>PXE</li>
<li>TFTP</li>
<li>OS Media</li>
<li>Web server</li>
</ul>
<h2 id="setup">Setup</h2>
<p>Besides the DHCP configuration, everything else in this article is handled by the Ansible plays included in <a href="https://github.com/phips/ansible-hw-bootstrap">this repository</a>.</p>
<h3 id="dhcp-server">DHCP server</h3>
<p>I’m writing here on the assumption you can control your DHCP configuration. If you don’t have access to your DHCP server, then you’ll need to ask the owner to set two options. DHCP option 67 needs setting to <code>pxelinux.0</code> and <code>next-server</code> (which is option 66 — but you may not need to know that, often a DHCP server will have a field/option for ‘next server’) needs setting to the IP address of your TFTP server.</p>
<p>If you can own the DHCP server, I’d suggest using dnsmasq. It’s small and simple. I will not cover configuring it here, but look at <a href="https://www.thekelleys.org.uk/dnsmasq/docs/dnsmasq-man.html">the man page</a> and the <code>--enable-tftp</code> option.</p>
<h3 id="tftp">TFTP</h3>
<p>The <code>next-server</code> setting for our DHCP server, above, will point to a machine serving <a href="https://en.m.wikipedia.org/wiki/Trivial_File_Transfer_Protocol">TFTP</a>. Here I&rsquo;ve used a <a href="https://www.centos.org">CentOS Linux</a> virtual machine, as it only takes one package (syslinux-tftpboot) and a service starting to have TFTP up and running. We&rsquo;ll stick with the default path, <code>/var/lib/tftpboot</code> for this article.</p>
<h3 id="pxe">PXE</h3>
<p>If you’re not already familiar with PXE (preboot execution environment) you might like to take a quick look at <a href="https://en.m.wikipedia.org/wiki/Preboot_Execution_Environment">the Wikipedia page</a>. For this article I’ll keep it short–we will serve some files over TFTP, which DHCP guides our hardware to.</p>
<p>You&rsquo;ll want <code>images/pxeboot/{initrd.img,vmlinuz}</code> from the OS distribution media for pxeboot. These need copying to <code>/var/lib/tftpboot/pxeboot</code>. The relreferenced Ansible plays <strong>do not do this step</strong> so you need to copy them over yourself.</p>
<p>We&rsquo;ll also need to serve the OS installation files. There are two approaches to this. 1) install, via HTTP, from over the internet or 2) install, again via HTTP, from a local server. For my testing, since I&rsquo;m on a private LAN, (and I guess you are too), the fastest installation method is the latter. The easiest way to prepare this is to mount the DVD image and rsync the <code>images</code>, <code>Packages</code> and <code>repodata</code> directories to your webserver location. The relreferenced Ansible plays will install <code>httpd</code> but won&rsquo;t copy over these files, so don&rsquo;t forget to do that after running <a href="https://github.com/phips/ansible-hw-bootstrap/blob/master/plays/kickstart.yml">the play</a>. For this article we&rsquo;ll once again stick with defaults for simplicity–so files need copying to Apache&rsquo;s standard docroot, <code>/var/www/html</code>.</p>
<h3 id="directories">Directories</h3>
<p>We should end up with directory structures like this:</p>
<p><strong>PXE/TFTP</strong></p>
<div class="overflow-hidden rounded-sm shadow-lg">
  
  <div class="flex items-center gap-2 bg-gray-200 px-4 py-2 dark:bg-gray-700">
    <div class="size-3 rounded-full bg-red-500"></div>
    <div class="size-3 rounded-full bg-yellow-500"></div>
    <div class="size-3 rounded-full bg-green-500"></div>
  </div>
  
  <div class="bg-white px-8 py-2 dark:bg-gray-900">
    <pre
      class="overflow-x-auto whitespace-pre-wrap break-words"
    ><code>[root@c7 ~]# tree  /var/lib/tftpboot/pxe{b*,l*cfg}
/var/lib/tftpboot/pxeboot
└── 6
    ├── initrd.img
    └── vmlinuz</code></pre>
  </div>
</div>
<p><strong>httpd</strong></p>
<div class="overflow-hidden rounded-sm shadow-lg">
  
  <div class="flex items-center gap-2 bg-gray-200 px-4 py-2 dark:bg-gray-700">
    <div class="size-3 rounded-full bg-red-500"></div>
    <div class="size-3 rounded-full bg-yellow-500"></div>
    <div class="size-3 rounded-full bg-green-500"></div>
  </div>
  
  <div class="bg-white px-8 py-2 dark:bg-gray-900">
    <pre
      class="overflow-x-auto whitespace-pre-wrap break-words"
    ><code>[root@c7 ~]# tree -d /var/www/html/
/var/www/html/
├── 6 -&gt; centos/6
├── 7 -&gt; centos/7
├── centos
│   ├── 6
│   │   └── os
│   │       └── x86_64
│   │           ├── images
│   │           │   └── pxeboot
│   │           ├── Packages
│   │           └── repodata
│   └── 7
│       └── os
│           └── x86_64
│               ├── images
│               │   └── pxeboot
│               ├── Packages
│               └── repodata
└── ks</code></pre>
  </div>
</div>
<p>You’ll notice my web setup appears a little less simple than the words above! I’ve pasted my actual structure to give you some ideas. The hardware I’m using is really old, and even getting CentOS 7 to work was horrible (if you&rsquo;re interested; lack of <a href="https://linux.die.net/man/4/cciss">cciss</a> drivers for HP Smart Array controller — yes, <a href="https://serverfault.com/questions/611182/centos-7-x64-and-hp-proliant-dl360-g5-scsi-controller-compatibility">there is an answer</a>, but it takes a lot of faff to make it work) so all examples are of CentOS 6. I also wanted a flexible setup which could install many versions. Here I’ve done that using symlinks — this arrangement will work just fine for RHEL too, for example. The basic structure is here though – note the images, Packages and repodata directories.</p>
<p>These paths relate directly to <a href="https://github.com/phips/ansible-hw-bootstrap/blob/master/roles/kickstart/templates/pxe_install.j2#L10">the PXE menu</a> file we&rsquo;ll serve up, and <a href="https://github.com/phips/ansible-hw-bootstrap/blob/master/roles/kickstart/templates/local6.ks.j2#L3">the kickstart file</a> too.</p>
<h3 id="if-you-dont-have-dhcp">If you don&rsquo;t have DHCP</h3>
<p>If you can&rsquo;t manage your own DHCP server, or the owners of your infrastructure can&rsquo;t help, there is another option. <a href="/posts/using-ipxe-with-a-url-to-kickstart-linux/">In the past</a> I&rsquo;ve used iPXE to create a boot image which I&rsquo;ve loaded as virtual media. A lot of out-of-band/lights-out-management interfaces on modern hardware support this functionality. You can make a custom embedded PXE menu in seconds with iPXE. I won&rsquo;t cover that here, but if it turns out to be a problem for you, then drop me a line <a href="https://mastodon.social/@thismarkp">on Mastodon</a> and I&rsquo;ll look at doing a follow up blog post if enough people request it.</p>
<h2 id="installing-hardware">Installing hardware</h2>
<p>We&rsquo;ve got our structure in place now, and we can <a href="https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/6/html/installation_guide/ch-kickstart2">kickstart</a> a server. Before we do though, we have to do some configuration of the TFTP set up to enable a given piece of hardware to pick up the PXE boot menu.</p>
<p>It&rsquo;s here we come across a small chicken/egg problem. We need a host&rsquo;s MAC address to create a link to the specific piece of hardware we want to kickstart. If the hardware is already running, and we can access it with Ansible, that&rsquo;s great–we have a way of finding out the boot interface MAC address via the setup module (see <a href="https://github.com/phips/ansible-hw-bootstrap/blob/master/plays/reinstall.yml">the reinstall play</a>). If it&rsquo;s a new piece of tin, however, we need to get the MAC address and tell our setup what to do with it. This probably means some manual intervention–booting the server and looking at a screen, or maybe getting the MAC from a manifest or such like. Whichever way you get a hold of it, we can tell our play about it via the inventory.</p>
<p>Let&rsquo;s put a custom variable into our simple INI format <a href="https://docs.ansible.com/ansible/latest/user_guide/intro_inventory.html">inventory file</a>, but run a play to set up TFTP…</p>
<div class="overflow-hidden rounded-sm shadow-lg">
  
  <div class="flex items-center gap-2 bg-gray-200 px-4 py-2 dark:bg-gray-700">
    <div class="size-3 rounded-full bg-red-500"></div>
    <div class="size-3 rounded-full bg-yellow-500"></div>
    <div class="size-3 rounded-full bg-green-500"></div>
  </div>
  
  <div class="bg-white px-8 py-2 dark:bg-gray-900">
    <pre
      class="overflow-x-auto whitespace-pre-wrap break-words"
    ><code>(pip)iMac:ansible-hw-bootstrap$ ansible-inventory --host hp.box
{
    &#34;ilo_ip&#34;: &#34;192.168.1.68&#34;,
    &#34;ilo_password&#34;: &#34;administrator&#34;
}
(pip)iMac:ansible-hw-bootstrap$ ansible-playbook plays/install.yml

PLAY [kickstart] *******************************************************************************************************

TASK [Host inventory entry has a MAC address] **************************************************************************
failed: [ks.box] (item=hp.box) =&gt; {
    &#34;assertion&#34;: &#34;hostvars[item][&#39;mac&#39;] is defined&#34;,
    &#34;changed&#34;: false,
    &#34;evaluated_to&#34;: false,
    &#34;item&#34;: &#34;hp.box&#34;,
    &#34;msg&#34;: &#34;Assertion failed&#34;
}

PLAY RECAP *************************************************************************************************************
ks.box                     : ok=0    changed=0    unreachable=0    failed=1</code></pre>
  </div>
</div>
<p>Uh oh, play failed. It <a href="https://github.com/phips/ansible-hw-bootstrap/blob/master/plays/install.yml#L9">contains a check</a> that the host we&rsquo;re about to install actually has a MAC address added. Let&rsquo;s fix that and run the play again…</p>
<div class="overflow-hidden rounded-sm shadow-lg">
  
  <div class="flex items-center gap-2 bg-gray-200 px-4 py-2 dark:bg-gray-700">
    <div class="size-3 rounded-full bg-red-500"></div>
    <div class="size-3 rounded-full bg-yellow-500"></div>
    <div class="size-3 rounded-full bg-green-500"></div>
  </div>
  
  <div class="bg-white px-8 py-2 dark:bg-gray-900">
    <pre
      class="overflow-x-auto whitespace-pre-wrap break-words"
    ><code>(pip)iMac:ansible-hw-bootstrap$ ansible-inventory --host hp.box
{
    &#34;ilo_ip&#34;: &#34;192.168.1.68&#34;,
    &#34;ilo_password&#34;: &#34;administrator&#34;,
    &#34;mac&#34;: &#34;00:AA:BB:CC:DD:EE&#34;
}
(pip)iMac:ansible-hw-bootstrap$ ansible-playbook plays/install.yml

PLAY [kickstart] *******************************************************************************************************

TASK [Host inventory entry has a MAC address] **************************************************************************
ok: [ks.box] =&gt; (item=hp.box) =&gt; {
    &#34;changed&#34;: false,
    &#34;item&#34;: &#34;hp.box&#34;,
    &#34;msg&#34;: &#34;All assertions passed&#34;
}

TASK [Set PXE menu to install] *****************************************************************************************
ok: [ks.box] =&gt; (item=hp.box)

TASK [Reboot target host for PXE boot] *********************************************************************************
skipping: [ks.box] =&gt; (item=hp.box)

PLAY RECAP *************************************************************************************************************
ks.box                     : ok=2    changed=0    unreachable=0    failed=0</code></pre>
  </div>
</div>
<p>That worked! What did it do? Looking at the pxelinux.cfg directory under our TFTP root, we can see a symlink…</p>
<div class="overflow-hidden rounded-sm shadow-lg">
  
  <div class="flex items-center gap-2 bg-gray-200 px-4 py-2 dark:bg-gray-700">
    <div class="size-3 rounded-full bg-red-500"></div>
    <div class="size-3 rounded-full bg-yellow-500"></div>
    <div class="size-3 rounded-full bg-green-500"></div>
  </div>
  
  <div class="bg-white px-8 py-2 dark:bg-gray-900">
    <pre
      class="overflow-x-auto whitespace-pre-wrap break-words"
    ><code>[root@c7 pxelinux.cfg]# pwd
/var/lib/tftpboot/pxelinux.cfg
[root@c7 pxelinux.cfg]# l
total 12
drwxr-xr-x. 2 root root   65 May 13 14:23 ./
drwxr-xr-x. 4 root root 4096 May  2 22:13 ../
-r--r--r--. 1 root root  515 May  2 12:22 00README
lrwxrwxrwx. 1 root root    7 May 13 14:12 01-00-aa-bb-cc-dd-ee -&gt; install
-rw-r--r--. 1 root root  682 May  2 22:07 install</code></pre>
  </div>
</div>
<p>The <code>install</code> file is symlinked to a file named after our MAC address. This is the key, useful, piece. It will ensure our hardware with MAC address &lsquo;00-aa-bb-cc-dd-ee&rsquo; is served a PXE menu when it boots from its network card.</p>
<p>So let&rsquo;s boot our machine.</p>
<p>Usefully Ansible has some <a href="https://docs.ansible.com/ansible/latest/modules/list_of_remote_management_modules.html">remote management modules</a>. We&rsquo;re working with an HP server here, so we can use the <a href="https://docs.ansible.com/ansible/latest/modules/hpilo_boot_module.html#hpilo-boot-module">hpilo_boot</a> module to save us having to interact directly with the LOM web interface.</p>
<p>Let&rsquo;s run the reinstall play on a booted server…</p>




<video controls poster="">
<source src="https://v.5318808.xyz/hardware-install-reinstall-play.mp4">
Your browser does not support the video tag.
</video>

<p>The neat thing about the <code>hpilo_boot</code> module, you&rsquo;ll have noticed, is it sets the boot medium to be the network. When the installation completes the server restarts and boots from its hard drive. The eagle eyed amongst you will have spotted the critical problem with this–what happens if the server boots to its network card again? It will pick up the PXE menu and promptly reinstall itself. I would suggest removing the symlink as a “belt and braces” step then. I will leave that as an exercise for you dear reader :-) Hint: I would make the new server do a &lsquo;phone home&rsquo; on boot, to somewhere, which runs a clean up job. Since you wouldn&rsquo;t need the console open, as I had here to demonstrate what&rsquo;s going on in the background, a &lsquo;phone home&rsquo; job would also give a nice indication of the process having completed. Ansible, <a href="https://github.com/phips/ansible-demos/tree/master/roles/phone_home">naturally</a>. Good luck!</p>
<p>If you&rsquo;ve any thoughts or comments on this process, please let me know.</p>]]>
      
      <![CDATA[<hr><p>Thanks for reading this post via RSS! 👏</p>]]>
      <![CDATA[<a href="mailto:rs511@probably.co.uk?subject=Hardware bootstrapping with Ansible">Reply to this post by email</a>]]>
      </description>
    </item>
    <item>
      <title>iPad Pro vs laptop, three months in</title>
      <link>https://probably.co.uk/posts/2019-02-26-ipad-pro-life/</link>
      <pubDate>Tue, 26 Feb 2019 00:00:00 +0000</pubDate>
      <guid>https://probably.co.uk/posts/2019-02-26-ipad-pro-life/</guid>
      <description>
      
      <![CDATA[<p>It&rsquo;s been <a href="https://www.linkedin.com/feed/update/urn:li:activity:6468852305700614144">a few months</a> since I sold my trusty MacBook and bought an iPad Pro, with the idea of performing all mobile compute on the latter. How has it gone?</p>
<p><strong>TL;DR</strong> It’s OK. I’m getting by, with some slight working practice changes. No current need to buy a laptop.</p>
<p>The longer story…</p>
<p>If you read back through this blog, or you already know me, you know my background is twenty years of being a tech engineer. That changed a little over 4 years ago. It’s this which led me to think I could do without a laptop, and lighten the load in my luggage when I travel (which I still do a lot).</p>
<p>My day-to-day comprises Slack, email, conference calls over various medium (mostly Bluejeans and FaceTime) and Google apps like docs, sheets and slides. All of these are catered for well on iOS, and since I’m mostly only using one at a time, having it fill the screen, unlike a traditional desktop, is &ldquo;fine&rdquo;.</p>
<p>I say <em>fine</em> like that because it’s probably the first change to my working practices I’ve had to make and one I’m unsure yet is a good or a bad thing. I’ve alternated between writing this on my iMac–where, as anybody working on a traditional desktop will probably recognise, the screen is a splatter-cast of open windows and applications–and on the iPad itself.</p>
<p>On the iMac I’ve got windows open left, right and centre. I don’t even know why&ndash;but because I can’t do that on the iPad, I don’t. It’s probably a good thing though&ndash;I focus on one thing at a time, which for my mind is no bad thing. But it is a big shift in the way I’ve worked for a long time, and I can see why that might irk people.</p>
<p>The flip side of focussing on the one thing like this is if I need to refer to another application then it’s more of a pain on the iPad. Yes, you can do <a href="https://support.apple.com/en-us/HT207582">the split window thing</a>, but it doesn’t work for all apps. And as I wrote that I promptly split the screen between Safari, where I’m writing this in an online editor, and Notes, where I’ve been keeping a tally of the annoyances :) So even as I describe this as a pain, I find it’s actually OK. Ha!</p>
<p>Other things that work ‘OK’, with minor annoyances. I recently gave a sales presentation, which I’d written in Keynote (I do use the Google Suite, but I still find Keynote the simplest presentation application). The actual presentation went fine–I plugged the iPad into the meeting room HDMI (using <a href="https://www.amazon.co.uk/dp/B075V68NVR/ref=nosim?tag=probably0c-21">this adapter</a>) and had a ‘presenter screen&rsquo;, complete with notes, on the iPad and the content on the big screens in the room. It worked just as well as using a laptop. However, it wasn’t so easy to put the presentation together on the iPad, so I did most of the work on the desktop. You can put a perfectly workable set of slides together using Keynote for iOS, but I found accurately laying out text boxes etc. hard (I couldn’t find the actual pixels box on Keynote for iOS, for example–and who wants the horror of a text box jumping a couple of pixels between slides?!)</p>
<p>2024 Update: found the granular sizing and position controls!</p>
<p><img src="keynote-item-positioning.webp" alt="keynote screen"></p>
<p>Saving an email as a PDF is doable, but a faff, and <a href="https://www.imore.com/how-save-email-pdf-iphone-and-ipad">not obvious</a>.</p>
<p>When I’m travelling, I tend to snapshot receipts for expenses into Evernote. Then, because our expense system is archaic, I have to separately submit them as PDFs. Which is easy to do with the desktop version of Evernote because you can simply right click and choose ‘convert note to PDF’ in the context menu. Try doing that on the iOS version! Basically, you have to go through the same process (linked above) as printing an email to a PDF.</p>
<p>Writing for the blog is doable. I use the static site generator, <a href="https://gohugo.io">Hugo</a> and store all the pages in a private Git repository. Mostly I author in <a href="https://prowritingaid.com/">ProWritingAid</a> and then paste the text into <a href="https://workingcopyapp.com">Working Copy</a>. This handles the Git bit and is the closest I get to anything still remotely technical. Working Copy is a decent source code management solution for iOS, so would also be good for coders. Blog deployment happens via a <a href="https://docs.github.com/en/actions">GitHub Action</a>.</p>
<p>Occasional VPN access is handled by the iOS <a href="https://apps.apple.com/gb/app/passepartout-vpn-client/id1433648537">Passepartout VPN</a> client. There are a few options for SSH clients, and over the years I&rsquo;ve swapped, but am currently using <a href="https://apps.apple.com/gb/app/termius-terminal-ssh-client/id549039908">Termius</a> (the free version is good enough).</p>
<p>One joy I’ve found is photo-editing. Photography is a minor hobby, and sometimes the digital pictures out of my Fuji cameras need some tweaking. Using <a href="https://affinity.serif.com/en-gb/photo/ipad/">Affinity Photo</a> with the Apple Pencil on the iPad is so much easier than using either a mouse, or a tablet, on the desktop version.</p>
<p>The only total let down I’ve found so far, which <strong>will</strong> require a laptop purchase at some point again, is video editing. I use Final Cut Pro, which as of today does not exist for iOS. iMovie just doesn’t cut it (pun not intended). After a recent ski trip I stuffed days’ worth of filming into the Mac to edit and now I can’t be bothered to do it. Having a laptop when travelling means edits, or at least picking out favourite scenes to use later, is so much more productive when done later the day they were filmed<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>.</p>
<p>The final total annoyance, for me at least, is fingerprints on the screen. I‘ve always hated it when folks point at something on your screen and smudge their fingers all over it, so to spend my days doing the very same myself is an annoyance I need to get over.</p>
<p>For now then I will stick with the iPad as my mobile compute of choice. At some point or another I will probably buy a laptop for the niche activities, but I’m in no rush.</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p><strong>UPDATE 24-Apr-19</strong> Interesting development on the video editing front. Whilst discussing this blog post with former colleagues, <a href="https://luma-touch.com/lumafusion-for-ios/">LumaFusion</a> was brought to my attention. Oh my, what a revelation! Also, whilst going down the rabbit hole that is YouTube, I came across <a href="https://www.youtube.com/@ChrisLawley">Christopher Lawley&rsquo;s channel</a>. He has some great videos about living with an iPad and I&rsquo;ve adopted a few of his tips. This post edit, for example, comes courtesy of <a href="https://getdrafts.com">Drafts</a> – another nice app find.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>]]>
      
      <![CDATA[<hr><p>Thanks for reading this post via RSS! 👏</p>]]>
      <![CDATA[<a href="mailto:rs511@probably.co.uk?subject=iPad Pro vs laptop, three months in">Reply to this post by email</a>]]>
      </description>
    </item>
    <item>
      <title>Migrating the runbook: a journey from legacy to DevOps</title>
      <link>https://probably.co.uk/posts/migrating-the-runbook-a-journey-from-legacy-to-devops/</link>
      <pubDate>Thu, 10 Nov 2016 00:00:00 +0000</pubDate>
      <guid>https://probably.co.uk/posts/migrating-the-runbook-a-journey-from-legacy-to-devops/</guid>
      <description>
      
      <![CDATA[<p><em>&ldquo;Just type this invoice up for me will you please?&rdquo;</em> asked a sheepish looking Malcolm.</p>
<p><em>&ldquo;I do have better things to do you know&rdquo;</em> I replied.</p>
<p><em>&ldquo;Yes, yes, I know. But who else is going to do it?&rdquo;</em></p>
<p><em>&ldquo;Give it here then!&rdquo;</em></p>
<h2 id="in-the-beginning-there-was-a-problem">In the beginning, there was a problem</h2>
<p>That was a fairly common interaction for me as a young lad. I was fresh out of school and working my summer in the sales department of a local car dealership. My job was mostly admin related tasks, which up until that point hadn&rsquo;t included doing all the sales guys&rsquo; typing. Our secretary had recently departed the company, and the sales guys all figured I could happily do the replacement typing jobs. The duty had fallen to me because a) I had the stereotypical 1980s glasses of a nerdy computer kid and b) they all knew I actually <strong>was</strong> a nerdy computer kid. So fair play to them for assuming I could type, I could.</p>
<p>The thing was I really did have better things to do, and these daily interruptions were eating into my productive time. I wanted that time back; so I got a book on programming VBA (everyone remember that? yes? jolly good) and started to write some macros in Word to generate invoices. After a short while I had a simple dialog box, that even the oldest curmudgeon in the office could work, which filled in a neat looking invoice and printed it out. The interruptions stopped, the sales folk could all help themselves to get the job done, and I got countless hours of my life back.</p>
<p>That was the start of my IT career – automating. Solving problems for people using technology.</p>
<h2 id="the-runbook">The runbook</h2>
<p>Over the course of the last twenty odd years I&rsquo;ve worked in a lot of companies, and yet even today I still see places doing things manually. As recent as last year I saw a &lsquo;runbook&rsquo; in action – basically a list of manual steps somebody had to do to deploy code into production. As I&rsquo;m fond of saying, &ldquo;if the solution is delivering a business goal then it&rsquo;s not &lsquo;wrong&rsquo; per se, but sometimes things can be done better&rdquo;. Following a runbook leaves so much to chance, one can never really be sure what the result will be.</p>
<figure><img src="/posts/migrating-the-runbook-a-journey-from-legacy-to-devops/Joshua_Tree_-_Love_car.jpg"
    alt="decrepit car" width="500">
</figure>

<p>Image source: wikipedia.org/wiki/Decrepit_car</p>
<p>Automation is about trust. We can have faith in task consistency with automation. Things turn out more the way we expect them to, time after time.</p>
<figure><img src="/posts/migrating-the-runbook-a-journey-from-legacy-to-devops/automated.jpg"
    alt="robot built car" width="500">
</figure>

<p>Image source: porsche-leipzig.com</p>
<p>I&rsquo;ve visited customers and seen plenty who still aren&rsquo;t trusting the computer to do the heavy lifting. Pondering why this might be, I&rsquo;ve drawn four conclusions:</p>
<ol>
<li>Speed of entry – &ldquo;oh it&rsquo;s quicker if I just type this straight into the server now&rdquo;</li>
<li>It&rsquo;s too hard</li>
<li>I only need to do this once</li>
<li>But if I automate this, won&rsquo;t my job go away?</li>
</ol>
<p>Number two is a tooling problem – if it&rsquo;s too hard, then the tool is wrong for the job (ever tried putting a screw into a wall with a hammer?) Number three always makes me smile, because who ever heard of a temporary solution in IT? We all know that &ldquo;bits of sticking plaster&rdquo; end up running production systems. So I always think, automate it from the start and it&rsquo;s repeatable and documented.</p>
<p>Number one is actually fed by numbers two and three. Number four is a bit of a fallacy too – automation isn&rsquo;t always about replacing people, it&rsquo;s about augmenting them. Get some of your own time back as an engineer and you are free to find more ways to be productive (I&rsquo;m sure we&rsquo;ve all heard of Google&rsquo;s 20% rule and the products that originated from that free thinking). Every business needs to grow, and if you find time to investigate new ways to enable that growth then all the better.</p>
<h2 id="augmenting-devops">Augmenting DevOps</h2>
<p>But how does automation feature in the DevOps story? Well, &ldquo;DevOps&rdquo; as a word is a contraction of two words - Development and Operations. It was coined, supposedly, around the late 00s by a developer looking to get his code into production a lot faster. The two departments have opposing goals - development want to get their shiny new code out in front of people as quickly as they write it, yet operations want a stable environment for customers to visit (and let&rsquo;s face it, as an operations person, who wants that dreaded call at 3am when something goes terribly wrong?). The defining ethos of the word was, in effect, we should communicate. The proposal was that Dev and Ops should stop working as discrete silos, where one simply throws their work over the fence to the other, and should start talking to one another to build &ldquo;pipelines&rdquo; – the software equivalent of assembly lines.</p>
<p>Some might say, therefore, that DevOps is common sense. To an extent, it is. When we&rsquo;re a team, and every business is, we should remember we&rsquo;re all in the same boat and rowing together in the same direction is going to get us places a lot faster. But often that&rsquo;s hard to do in a large organisation because of many factors – geography, legislation, process etc.</p>
<p>Have you heard of <a href="https://en.wikipedia.org/wiki/Dunbar%27s_number">Dunbar&rsquo;s Number</a>? I&rsquo;ll quote the underlying Wikipedia link there - &ldquo;&hellip;is a suggested cognitive limit to the number of people with whom one can maintain stable social relationships. These are relationships in which an individual knows who each person is and how each person relates to every other person&hellip;with a commonly used value of 150&rdquo;.</p>
<p>Getting things done as a team is so much easier when everybody knows each other that little bit better. This is why so many corporates force upon us the often cringey team building days :) But they have merit. Learn a little bit of the social side to your colleagues and sure enough, you&rsquo;ll work together easier. The problem with this magic 150, and the ethos of DevOps, is quite clear to see when you work in a massive, global, corporate though. How do you achieve the sort of relationships a close knit community enjoys? The DevOps ethos was formed out of people working in small, often startup-sized, companies.</p>
<p>I watched <a href="https://www.ted.com/talks/yves_morieux_as_work_gets_more_complex_6_rules_to_simplify">an interesting TED talk</a> a while ago by a chap called Yves Morieux, titled &ldquo;As work gets more complex, 6 rules to simplify&rdquo;. I highly recommend watching it. His first rule is this:</p>
<p><strong>Understand what your colleagues actually do</strong></p>
<p>Coming back to the core tenet of DevOps, communication, one can see how this rule plays a key part. Once developers and operations understand each other&rsquo;s working lives, it makes it easier to have the conversation about implementing a trusted, automated, pipeline. Sidenote: on the subject of working together, I read an excellent book many years ago called &ldquo;Getting to yes&rdquo; by Roger Fisher and William Ury. It talks about objective criteria rather than digging into positions. It&rsquo;s well worth a read.</p>
<p>Looking at this in the context of a globally dispersed corporate organisation, it is possible to encourage, or bolster, the ability for colleagues to understand one another&rsquo;s jobs using technology.</p>
<p>One of my favourite quotes is from Einstein: &ldquo;make things as simple as possible, but not simpler&rdquo;. Technology, over the last 20 odd years that I&rsquo;ve been working with it, hasn&rsquo;t always got simpler. On the contrary, a lot of the time I find things have got much more complicated, and often harder with that. Using technology to help understand what your colleagues do needs to be easy, because then it becomes far more natural to do so. The world now moves at a rapid pace of change and attention spans are short (thanks Twitter!), so information needs to be quick to access, easy to keep up to date, and most importantly easy to search for relevance. Wikis are a great documentation tool, just look at the success of Wikipedia.</p>
<p>Later in his talk, Yves Morieux goes on to speak about feedback loops. Reinforcing his first rule is tremendously beneficial to this communications story, and I&rsquo;ve seen companies do this very well with technology. I once visited a customer who showed me their excellent Ansible development workflow. Anybody could write playbooks and contribute to an internal repository via a &ldquo;<a href="https://en.wikipedia.org/wiki/Distributed_version_control#Pull_requests">pull request</a>&rdquo;. Essentially they had mimicked, internally, a typical opensource software development model you would see on GitHub. There was a feedback loop – people wrote code, and submitted it for others to review and bring into the bigger picture. Dispersed teams, geographically in this particular case, working together.</p>
<p>I&rsquo;ve seen similar arrangements taken a step further, with commit messages and PRs automatically sending a message into a chat system. Within the Ansible team we&rsquo;re big users of Slack. For a time when we were just a small startup it was my personal saviour. Although I was over 3,000 miles away from HQ I always felt very much connected to the organisation. Slack was magical at helping me understand what my colleagues did (in true BBC style – there are other chat systems available. I say this with some jest; as a veteran Internet user I&rsquo;ve been using IRC for over 20 years, plus countless other chat systems along the way. Slack&rsquo;s differentiator is they&rsquo;ve made using it easy and relatively simple).</p>
<p>Chat systems can take feedback loops and automation to the next level too, with ChatBots. I&rsquo;m sure we&rsquo;ve all read about <a href="https://www.bbc.co.uk/news/technology-35890188">bots and how they&rsquo;re revolutionising our interactions with companies</a>, but it&rsquo;s always impressive to see a company implement a ChatBot that can be asked to spin up 50 new web servers on demand.</p>
<h2 id="the-journey-from-legacy-to-devops">The journey from legacy to DevOps</h2>
<p>The migration of old methods to the modern DevOps mindset can be taken in small steps by introducing simple, easy-to-use technology that puts people to the fore. When solving a problem using a piece of technology that&rsquo;s quick and easy to get started with, it&rsquo;s far more likely to achieve widespread adoption. See how easy it is to edit a wiki page, put some code into a GitHub repository, create a Slack team or, and it would be remiss of me not to say, write an Ansible playbook, and you&rsquo;ll witness how small seeds grow into big trees. When technology isn&rsquo;t restricted to one particular group then it&rsquo;s easy to introduce to many teams at the same time. It helps them work to their own cadence in parallel and also to come together in one, coherent, whole.</p>
<p>I&rsquo;ll leave you with one last anecdote from my past. Many years ago I fought hard to get a wiki introduced into a large corporate I was working in. The documentation practice at the time was weighty, and often unread, Word documents. These documents quickly went out of date, and people couldn&rsquo;t easily find information contained within them from a central location. After the wiki was implemented, more documentation was completed in the following six months than had been written in the past three years.</p>
<p>Rapid progress brought about by ease of use and simplicity.</p>
<hr>
<p><strong>Footnote</strong>: I originally wrote this blog in my day job for Ansible by Red Hat. It featured on <a href="https://www.ansible.com/blog/migrating-the-runbook-a-journey-from-legacy-to-devops">ansible.com/blog</a>. If you saw <a href="/posts/talk-from-ipexpo-london/">my talk at IPExpo London</a> in 2015 you will also recognise it.</p>]]>
      
      <![CDATA[<hr><p>Thanks for reading this post via RSS! 👏</p>]]>
      <![CDATA[<a href="mailto:rs511@probably.co.uk?subject=Migrating the runbook: a journey from legacy to DevOps">Reply to this post by email</a>]]>
      </description>
    </item>
    <item>
      <title>Slides from my talk at IPExpo London</title>
      <link>https://probably.co.uk/posts/talk-from-ipexpo-london/</link>
      <pubDate>Fri, 09 Oct 2015 00:00:00 +0000</pubDate>
      <guid>https://probably.co.uk/posts/talk-from-ipexpo-london/</guid>
      <description>
      
      <![CDATA[<p>On October 7th I gave a talk at the IPExpo show about getting from legacy IT to
the modern idea of DevOps.</p>
<p>Mostly I talked about the core idea of DevOps being communication, about
breaking down silos. I went on to suggest ways technology can support that
idea.</p>
<p>Postscript: I received this email from the event organisers a month after the event.</p>
<p><img src="ipexpo-talk-post.webp" alt="this talk performed well"></p>
<hr>
<p>The <a href="https://www.ted.com/talks/yves_morieux_as_work_gets_more_complex_6_rules_to_simplify">TED Talk</a> mentioned in the slides: <em>Yves Morieux, as work gets more
complex, 6 rules to simplify</em>.</p>



  
    
  





<div class="mx-auto grid grid-cols-1 gap-3 sm:grid-cols-[40%_1fr]">
  
    <section id="1" class="sm:scroll-mt-28">
      <img src="slides/slides.001.jpeg" alt="Slide">
    </section>

    <section class="max-sm:border-b-1">
      Before we get going — who works in an organisation of less than 150 people? More than 1000? (Later on we'll come to Dunbar's number).

      <a href="#1">#</a>
    </section>
  
    <section id="2" class="sm:scroll-mt-28">
      <img src="slides/slides.002.jpeg" alt="Slide">
    </section>

    <section class="max-sm:border-b-1">
      I'm still seeing organisations using 'runbooks'; a list of things to do to deploy applications/systems.  I've spent my career automating — sometimes upgrading manual processes to automated, and sometimes being lucky enough to do greenfield engineering. Repetitive, manual, tasks can be a massive drain on an organisation and detrimental to keeping the best engineers.

      <a href="#2">#</a>
    </section>
  
    <section id="3" class="sm:scroll-mt-28">
      <img src="slides/slides.003.jpeg" alt="Slide">
    </section>

    <section class="max-sm:border-b-1">
      Typing from a list of instructions _can_ lead to mistakes. We've all got stories of that one deploy 'fat fingered' and suddenly a whole production system gets killed.

      <a href="#3">#</a>
    </section>
  
    <section id="4" class="sm:scroll-mt-28">
      <img src="slides/slides.004.jpeg" alt="Slide">
    </section>

    <section class="max-sm:border-b-1">
      Automation ensures consistency. It shouldn't be a mystery why most auto manufacturing is robotised.

      <a href="#4">#</a>
    </section>
  
    <section id="5" class="sm:scroll-mt-28">
      <img src="slides/slides.005.jpeg" alt="Slide">
    </section>

    <section class="max-sm:border-b-1">
      Suggesting automation often gets the response "I'll just type it for now, it's quicker". They could've just typed the same into a Play. So it's caused to me to ponder why people would actively choose to make life harder for themselves. The obviousness of that being, they don't think they are making it harder. Quite the opposite. There are usually one of four reasons.

      <a href="#5">#</a>
    </section>
  
    <section id="6" class="sm:scroll-mt-28">
      <img src="slides/slides.006.jpeg" alt="Slide">
    </section>

    <section class="max-sm:border-b-1">
      The fourth one being the most powerful "won't I just automate myself out of a job?" (answer: no, but that's a bigger story)

      <a href="#6">#</a>
    </section>
  
    <section id="7" class="sm:scroll-mt-28">
      <img src="slides/slides.007.jpeg" alt="Slide">
    </section>

    <section class="max-sm:border-b-1">
      This was a graph a customer once showed me. "The green line is the business's expectation for revenue growth". "The blue line is the number of people we can have to do that growth". So how do we fill that gap? Automation. . .

      <a href="#7">#</a>
    </section>
  
    <section id="8" class="sm:scroll-mt-28">
      <img src="slides/slides.008.jpeg" alt="Slide">
    </section>

    <section class="max-sm:border-b-1">
      Ask the audience — who's heard of Dunbar's number? (At the time, this was delivered in front of an audience of roughly 200 people. Two raised their hands)  DevOps — story of its origins. Dev & Ops pulling in opposite directions. Silos. Let's get them to talk! This should be common sense.

      <a href="#8">#</a>
    </section>
  
    <section id="9" class="sm:scroll-mt-28">
      <img src="slides/slides.009.jpeg" alt="Slide">
    </section>

    <section class="max-sm:border-b-1">
      I watched this TED talk with Yves Morieux a while ago, and love his first principle.

      <a href="#9">#</a>
    </section>
  
    <section id="10" class="sm:scroll-mt-28">
      <img src="slides/slides.010.jpeg" alt="Slide">
    </section>

    <section class="max-sm:border-b-1">
      Create digital 'feedback loops', so departments can work together, and learn from each other. A cohesive organisation, versus many small 'tribes' doing their own thing. A great collaborative example — Wikis versus old-fashioned Word docs. Arguably any online collaborative documentation tool is better!

      <a href="#10">#</a>
    </section>
  
    <section id="11" class="sm:scroll-mt-28">
      <img src="slides/slides.011.jpeg" alt="Slide">
    </section>

    <section class="max-sm:border-b-1">
      Another of Yves Morieux points was to create feedback loops — creating internal dev practices based on pull requests is a great example of this.

      <a href="#11">#</a>
    </section>
  
    <section id="12" class="sm:scroll-mt-28">
      <img src="slides/slides.012.jpeg" alt="Slide">
    </section>

    <section class="max-sm:border-b-1">
      As much as chat systems can be an overload of 'noise' (whole other conversation on the culture of implementing signal vs noise practices) they can be a good centralisation point for communications.

      <a href="#12">#</a>
    </section>
  
    <section id="13" class="sm:scroll-mt-28">
      <img src="slides/slides.013.jpeg" alt="Slide">
    </section>

    <section class="max-sm:border-b-1">
      ChatOps — use everyday communications tool with centralised automation

      <a href="#13">#</a>
    </section>
  
    <section id="14" class="sm:scroll-mt-28">
      <img src="slides/slides.014.jpeg" alt="Slide">
    </section>

    <section class="max-sm:border-b-1">
      Thinking back to slide 6, and the reasons why people don't automate — or adopt anything new for that matter — it's about making 'change' easy. So even when people default to resisting change, if you can demonstrate something productive within 10 minutes of picking up a product/technology, the resistance is far more likely to subside quickly. So "K.I.S.S.". With tech, the talented folks will prefer text based systems. Typing scales far better than moving a mouse and clicking. You won't build a creative organisation — and engineering is totally creative — with GUIs. Get stuff done in text, report on it in GUIs.

      <a href="#14">#</a>
    </section>
  
    <section id="15" class="sm:scroll-mt-28">
      <img src="slides/slides.015.jpeg" alt="Slide">
    </section>

    <section class="max-sm:border-b-1">
      This being the output of the previous slide 😂 Anyone remember Perl Golf?

      <a href="#15">#</a>
    </section>
  
    <section id="16" class="sm:scroll-mt-28">
      <img src="slides/slides.016.jpeg" alt="Slide">
    </section>

    <section class="max-sm:border-b-1">
      Common tool - everybody goes off to do their thing, with a clear direction. 'Meet in the middle'.

      <a href="#16">#</a>
    </section>
  
    <section id="17" class="sm:scroll-mt-28">
      <img src="slides/slides.017.jpeg" alt="Slide">
    </section>

    <section class="max-sm:border-b-1">
      Closing anecdote: IB Wiki (in 6 months more docs done than in previous 3 years - ease of use/access/finding information) i.e. ** make it easy ** // Create a collaborative culture by default - INS 'Knowledge Quests'

      <a href="#17">#</a>
    </section>
  
</div>

]]>
      
      <![CDATA[<hr><p>Thanks for reading this post via RSS! 👏</p>]]>
      <![CDATA[<a href="mailto:rs511@probably.co.uk?subject=Slides from my talk at IPExpo London">Reply to this post by email</a>]]>
      </description>
    </item>
    <item>
      <title>Testing Ansible roles</title>
      <link>https://probably.co.uk/posts/testing-ansible-roles/</link>
      <pubDate>Tue, 21 Jul 2015 00:00:00 +0000</pubDate>
      <guid>https://probably.co.uk/posts/testing-ansible-roles/</guid>
      <description>
      
      <![CDATA[<p>At an Ansible meetup last week somebody put this question to me: <em>&ldquo;I&rsquo;m coming from the Puppet world, and there they have whole structures around testing modules (the same thing as Ansible roles) like Rspec. How do you handle testing roles with Ansible?&rdquo;</em>. Ah, this is a question I&rsquo;ve heard many times. So here are my thoughts on it. <strong>I, personally,</strong> wouldn&rsquo;t do it. <em>Why ever not?!</em> I hear you cry. Because…</p>
<p>Infrastructure as code has brought with it many good things from software development - not least the ability to define our infrastructures and &lsquo;replay&rsquo; them, giving us the foundations of sound &ldquo;Dev Ops&rdquo; automation pipelines and the &lsquo;<a href="https://www.theregister.co.uk/2013/03/18/servers_pets_or_cattle_cern">cattle vs pets</a>&rsquo; mantra. However, I don&rsquo;t believe we need to take every last piece of development practices and apply to IaC.</p>
<p>When we model an infrastructure in something like Ansible we are, in effect, laying the foundations for our &lsquo;house&rsquo;. Get a bit of the foundations wrong, and the house won&rsquo;t stand up. Less of the metaphor, getting literal - if your web server is configured wrong, it won&rsquo;t serve web pages. But what if it serves <em>a</em> webpage, but not <em>the</em> webpage I hear you ask. Well, this is where the testing comes in.</p>
<p>A few years back I wrote some Perl code for a monitoring system. The code connected to a number of different kinds of VPN device, of varying versions, and scraped their web interfaces. The system I was replacing didn&rsquo;t cope very well when versions of the VPN OS changed - it just fell over. I had written a lot of tests before the main coding, and a few of the tests checked for correct scenarios, and false scenarios. In effect I was looking at both sides of the coin - my thinking was in the future if the OS changed then the tests would reveal something that did or did not work (they were also useful to prove that version upgrades of the Perl module would still work correctly too). What I actually checked for was known good strings the monitoring software needed from the VPN devices.</p>
<p>This is my thinking around infrastructure code testing. <em>Think big picture</em> - test the goal you&rsquo;re expecting to arrive at. Ansible modules are designed to &lsquo;fail fast&rsquo; and achieve &lsquo;desired state&rsquo;. If they&rsquo;re successful then you&rsquo;ve implemented the state you want (<a href="https://docs.ansible.com/ansible/copy_module.html">put a file into place</a>, <a href="https://docs.ansible.com/ansible/template_module.html">template</a> a configuration, ensure a <a href="https://docs.ansible.com/ansible/service_module.html">service</a> is running, etc). If the module doesn&rsquo;t arrive at the desired state, <strong>it fails</strong>. If it fails, the run isn&rsquo;t successful, and the goal you need to test for isn&rsquo;t reached.</p>
<p>The point has also been raised about edge cases, such as &lsquo;what if ignore_errors was used by accident, a copy n paste mistake, perhaps&rsquo;. Well, again, I suggest <em>test for the end goal</em>. And I don&rsquo;t just mean do one test - I refer to my anecdote above and testing &lsquo;both sides of the coin&rsquo;. Do a run of the configuration play, then do another run. Do both arrive at the same place - i.e. is the full service delivering what it is supposed to?</p>
<p>Bigger picture context is important - I want to stress that what is in my head isn&rsquo;t just confined to testing a few plays. I imagine in a well thought out system, testing of infrastructure automation would be, well, automated. If I were building out another infra today I would have a CI job that took IaC definitions and spun up VMs to test the end to end, automatically. Why not have an overnight job that takes the day&rsquo;s CM work and builds the application from the ground up? (then tests it is delivering what it should).</p>
<p>To me testing of individual roles is adding work, it&rsquo;s minutiae that doesn&rsquo;t matter - when the bigger picture is done correctly.</p>
<p>But, if it makes you feel safer about your infrastructure automation then why not? Go ahead and test every role - it&rsquo;s perfectly possible to do. All I&rsquo;m saying is <em>I</em> wouldn&rsquo;t, I would put my effort into making sure the end goal is working correctly.</p>
<p><em>Because no matter how you get the ball down the pitch, the point of the game is still to get it through the goal posts.</em></p>
]]>
      
      <![CDATA[<hr><p>Thanks for reading this post via RSS! 👏</p>]]>
      <![CDATA[<a href="mailto:rs511@probably.co.uk?subject=Testing Ansible roles">Reply to this post by email</a>]]>
      </description>
    </item>
    <item>
      <title>Simplicity, the art of automation</title>
      <link>https://probably.co.uk/posts/simplicity-the-art-of-automation/</link>
      <pubDate>Sun, 21 Jun 2015 00:00:00 +0000</pubDate>
      <guid>https://probably.co.uk/posts/simplicity-the-art-of-automation/</guid>
      <description>
      
      <![CDATA[<p>In May of 2015 I gave a talk about automation at the IPExpo Manchester show.</p>
<p>Whilst I <em>was</em> giving a small pitch for Ansible, I fundamentally wanted to talk about simplicity (a common theme throughout this blog, you&rsquo;ll find, way before I went to work for Ansible, Inc) and its role in enabling longevity to systems engineering.</p>
<p>As I&rsquo;ve come back to this topic in late 2024, I&rsquo;ve realised how this talk still carries relevance nearly a decade later. A short while ago I <a href="https://www.linkedin.com/posts/markphillips_the-tech-industry-is-a-shambolic-mess-now-activity-7251567503829532675-jho3/">posted this on LinkedIn</a>, and it got 10x my usual views. It clearly struck a chord:</p>
<blockquote>
<p>The tech industry is a shambolic mess now (to cheer yourself up, go read any of Ed Zitron&rsquo;s writing) — and so much of it is down to companies not being willing (or, perhaps, able) to put the work in to making things <em>simple</em>.</p>
<p>Simple doesn&rsquo;t mean &ldquo;basic&rdquo;, it means the development of the software has had high quality engineering <em>time and effort</em> put into it (this also means it is not &ldquo;easy&rdquo;). It means there have been conversations between development and customer — conversations that have involved asking questions about the users&rsquo; day to day working, and listening. Then the hard work has been put in to remove any and all friction from those daily challenges.</p>
<p>If somebody can&rsquo;t pick up, use and understand your software inside of 10 minutes then you&rsquo;ve failed to put the work in. You have failed to make it simple.</p>
<p>It is that simple.</p>
</blockquote>
<p>Here are the slides:</p>



  
    
  





<div class="mx-auto grid grid-cols-1 gap-3 sm:grid-cols-[40%_1fr]">
  
    <section id="1" class="sm:scroll-mt-28">
      <img src="slides/slides.001.jpeg" alt="Slide">
    </section>

    <section class="max-sm:border-b-1">
      Hello! My name is … [8s pause] We'll come back to the significance of that 8 seconds later.

      <a href="#1">#</a>
    </section>
  
    <section id="2" class="sm:scroll-mt-28">
      <img src="slides/slides.002.jpeg" alt="Slide">
    </section>

    <section class="max-sm:border-b-1">
      Cue short video of Mark Adams. First 30 seconds: "A good system…" https://youtu.be/QlgXFRqfyWo

      <a href="#2">#</a>
    </section>
  
    <section id="3" class="sm:scroll-mt-28">
      <img src="slides/slides.003.jpeg" alt="Slide">
    </section>

    <section class="max-sm:border-b-1">
      Short bit about Vitsoe's shelving. Fully bespoke…

      <a href="#3">#</a>
    </section>
  
    <section id="4" class="sm:scroll-mt-28">
      <img src="slides/slides.004.jpeg" alt="Slide">
    </section>

    <section class="max-sm:border-b-1">
      it can serve any function you need…

      <a href="#4">#</a>
    </section>
  
    <section id="5" class="sm:scroll-mt-28">
      <img src="slides/slides.005.jpeg" alt="Slide">
    </section>

    <section class="max-sm:border-b-1">
      in any room…

      <a href="#5">#</a>
    </section>
  
    <section id="6" class="sm:scroll-mt-28">
      <img src="slides/slides.006.jpeg" alt="Slide">
    </section>

    <section class="max-sm:border-b-1">
      it can be small…

      <a href="#6">#</a>
    </section>
  
    <section id="7" class="sm:scroll-mt-28">
      <img src="slides/slides.007.jpeg" alt="Slide">
    </section>

    <section class="max-sm:border-b-1">
      or large. Did you think you were coming to a tech talk today? 😂 — Don't worry, we'll come to tech in a moment.

      <a href="#7">#</a>
    </section>
  
    <section id="8" class="sm:scroll-mt-28">
      <img src="slides/slides.008.jpeg" alt="Slide">
    </section>

    <section class="max-sm:border-b-1">
      But here's the beauty of the 606 shelving system. As bespoke as it is, it actually isn't. It's a system. A very simple system, of components that can be slotted together to make 'bespoke' installations.

      <a href="#8">#</a>
    </section>
  
    <section id="9" class="sm:scroll-mt-28">
      <img src="slides/slides.009.jpeg" alt="Slide">
    </section>

    <section class="max-sm:border-b-1">
      Does anyone know who this is? (when I delivered this talk in early 2015, barely anyone had heard of Dieter Rams). Rams was the head of design at Braun from 1961 to 1995, and designed the Vitsoe 606 shelving system in 1959. It is still fundamentally the same today, and Vitsoe is very proud to say customers take their furniture as they move house, remodelling the existing components as they do.

      <a href="#9">#</a>
    </section>
  
    <section id="10" class="sm:scroll-mt-28">
      <img src="slides/slides.010.jpeg" alt="Slide">
    </section>

    <section class="max-sm:border-b-1">
      I could relate to that (in no way comparing me to Rams! I am but an engineer). I was starting to despair of the tech industry. Overwrought, overcomplicated 'solutions'. Let's discuss four of Rams' principles of good design.

      <a href="#10">#</a>
    </section>
  
    <section id="11" class="sm:scroll-mt-28">
      <img src="slides/slides.011.jpeg" alt="Slide">
    </section>

    <section class="max-sm:border-b-1">
      I was pitching Ansible here, so talked about its simplicity, yet flexibility. Adding things on to it that were not a 'shipped' part was easy. I do believe if you can't achieve something within 15 minutes of first picking up a new product though, the product design has failed.

      <a href="#11">#</a>
    </section>
  
    <section id="12" class="sm:scroll-mt-28">
      <img src="slides/slides.012.jpeg" alt="Slide">
    </section>

    <section class="max-sm:border-b-1">
      YAML for configuration. Unlike JSON, and in the olden days, XML 😱 it's human readable. Makes it very accessible — even somebody who has never used the product before instantly gets it. This should be a fundamental part of any product design — it needs to be understandable, accessible, almost instantly.

      <a href="#12">#</a>
    </section>
  
    <section id="13" class="sm:scroll-mt-28">
      <img src="slides/slides.013.jpeg" alt="Slide">
    </section>

    <section class="max-sm:border-b-1">
      The ‘Unix philosophy’ - Ken Thompson's early meditations on how to design a small but capable operating system <br />Use older tech. It works. SQL, SSH, keep web interfaces as simple as possible. A lot to be said for server-side HTML where interaction is barely needed. Just look at the state of the web today [2025].

      <a href="#13">#</a>
    </section>
  
    <section id="14" class="sm:scroll-mt-28">
      <img src="slides/slides.014.jpeg" alt="Slide">
    </section>

    <section class="max-sm:border-b-1">
      The most important observation that I have made about good design—it’s not about aesthetics. Good design focuses on people. We would do well, in the software industry, to pay attention to Rams's ten principles, and to remember that ultimately we're using technology to make our lives easier, or better.

      <a href="#14">#</a>
    </section>
  
    <section id="15" class="sm:scroll-mt-28">
      <img src="slides/slides.015.jpeg" alt="Slide">
    </section>

    <section class="max-sm:border-b-1">
      Ansible promise back in the day. I swapped the 2nd and 3rd columns around from the original order, because this flowed better. Almost like a magic trick — simple, but powerful, and the turn; it was agentless. Which for automation tools back then was unheard of.

      <a href="#15">#</a>
    </section>
  
    <section id="16" class="sm:scroll-mt-28">
      <img src="slides/slides.016.jpeg" alt="Slide">
    </section>

    <section class="max-sm:border-b-1">
      And the significance of the 8 second pause at the start? I didn't want the audience to take any of my words to convince them of anything. I wanted them to try the product…

      <a href="#16">#</a>
    </section>
  
    <section id="17" class="sm:scroll-mt-28">
      <img src="slides/slides.017.jpeg" alt="Slide">
    </section>

    <section class="max-sm:border-b-1">
      and showed it was possible to install it in 8 seconds.

      <a href="#17">#</a>
    </section>
  
    <section id="18" class="sm:scroll-mt-28">
      <img src="slides/slides.018.jpeg" alt="Slide">
    </section>

    <section class="max-sm:border-b-1">
      Wise words. We're still getting that so wrong even today, in 2024, sadly. The tech industry would do well to study, and adhere to, Rams' 10 principles of good design https://www.vitsoe.com/gb/about/good-design

      <a href="#18">#</a>
    </section>
  
</div>

]]>
      
      <![CDATA[<hr><p>Thanks for reading this post via RSS! 👏</p>]]>
      <![CDATA[<a href="mailto:rs511@probably.co.uk?subject=Simplicity, the art of automation">Reply to this post by email</a>]]>
      </description>
    </item>
    <item>
      <title>Managing VMware vSphere guests with Ansible Tower</title>
      <link>https://probably.co.uk/posts/managing-vmware-vsphere-guests-with-ansible-tower/</link>
      <pubDate>Fri, 06 Mar 2015 00:00:00 +0000</pubDate>
      <guid>https://probably.co.uk/posts/managing-vmware-vsphere-guests-with-ansible-tower/</guid>
      <description>
      
      <![CDATA[<p>There are lots of ways to enable self-service VMs within an organisation - what some might call &lsquo;a private cloud&rsquo;. However, these usually require layers and layers of complex software. What if you could leverage your existing hypervisor and 15 lines of code to do the same? And what if those 15 lines became an even simpler single click?</p>
<p>Ansible Core contains a module for managing virtual machines in VMware vSphere environments called <a href="https://docs.ansible.com/projects/ansible/latest/collections/community/vmware/index.html">vsphere_guest</a>. Using this one module we can talk to an existing vSphere instance to create new VMs, clone VM templates, and control and delete VMs. Couple up a simple playbook with Ansible Tower and we can do some pretty amazing things with very little effort.</p>
<p>Here&rsquo;s our playbook to create a new virtual machine from a template in vSphere:</p>
<div class="overflow-hidden rounded-sm shadow-lg">
  
  <div class="flex items-center gap-2 bg-gray-200 px-4 py-2 dark:bg-gray-700">
    <div class="size-3 rounded-full bg-red-500"></div>
    <div class="size-3 rounded-full bg-yellow-500"></div>
    <div class="size-3 rounded-full bg-green-500"></div>
  </div>
  
  <div class="bg-white px-8 py-2 dark:bg-gray-900">
    <pre
      class="overflow-x-auto whitespace-pre-wrap break-words"
    ><code>- hosts: vmcreate
  gather_facts: false
  connection: local
  vars:
    vcenter_hostname: 10.10.10.1
    esxhost: 10.10.20.1
    datastore: NFS001
    network: VLAN001
    vmtemplate: CentOS7
    vmcluster: AppsDev
    notes: Created by Ansible
  tasks:
    - name: Check for required variables
      fail: msg=&#34;Must pass name to -e&#34;
      when: name is not defined

    - name: Check for vSphere access parameters
      fail: msg=&#34;Must set vcenter_user and vcenter_pass in a Vault&#34;
      when: (vcenter_user is not defined) or (vcenter_pass is not defined)

    - name: Create VM from template
      vsphere_guest:
        vcenter_hostname: &#34;{{ vcenter_hostname }}&#34;
        username: &#34;{{ vcenter_user }}&#34;
        password: &#34;{{ vcenter_pass }}&#34;
        guest: &#34;{{ name }}&#34;
        from_template: yes
        template_src: &#34;{{ vmtemplate }}&#34;
        cluster: &#34;{{ vmcluster  }}&#34;
        resource_pool: &#34;/Resources&#34;
        vm_extra_config:
          notes: &#34;{{ notes }}&#34;
        esxi:
          datacenter: Dev
          hostname: &#34;{{ esxhost }}&#34;</code></pre>
  </div>
</div>
<p>The really important bit that&rsquo;s doing the work is the 15 lines associated with the &lsquo;Create VM from template&rsquo; task. Note the extensive use of variables in this play to give us lots of flexibility. We&rsquo;ll make use of this in Tower in just a moment.</p>
<p><a href="https://www.ansible.com/blog/ansible-tower-2.1">Tower 2.1 introduced &lsquo;Surveys&rsquo;</a>, which are a great way to create interactive forms for a given play. The form can prompt for variable information to make running a flexible play simpler:</p>
<figure class="shadow-lg"><img src="/posts/managing-vmware-vsphere-guests-with-ansible-tower/survey.png"
    alt="An Ansible Tower dialog" width="500">
</figure>

<p>Setting up multiple choice questions is also really easy:</p>
<figure class="shadow-lg"><img src="/posts/managing-vmware-vsphere-guests-with-ansible-tower/edit_survey.png"
    alt="An Ansible Tower survey" width="500">
</figure>

<p>There are many more ways to extend this simple functionality - Tower&rsquo;s job scheduler could automatically run a play to &lsquo;scavenge&rsquo; unused VMs, for example (put <a href="https://docs.ansible.com/projects/ansible/latest/playbook_guide/playbooks_vars_facts.html#facts-d-or-local-facts">a fact</a> on the host to say it&rsquo;s done with, and you protect against automatically killing a VM still in use).</p>
<p>(This post originally appeared on ansible.com as part of my then day job).</p>]]>
      
      <![CDATA[<hr><p>Thanks for reading this post via RSS! 👏</p>]]>
      <![CDATA[<a href="mailto:rs511@probably.co.uk?subject=Managing VMware vSphere guests with Ansible Tower">Reply to this post by email</a>]]>
      </description>
    </item>
    <item>
      <title>Simple service discovery using Ansible Tower and DNS</title>
      <link>https://probably.co.uk/posts/simple-service-discovery-using-ansible-tower-and-dns/</link>
      <pubDate>Fri, 26 Dec 2014 00:00:00 +0000</pubDate>
      <guid>https://probably.co.uk/posts/simple-service-discovery-using-ansible-tower-and-dns/</guid>
      <description>
      
      <![CDATA[<p>Service discovery is one of those things that can be extremely handy to have, yet difficult to implement in a simple fashion. There are lots of tools out there to help, but I wanted to make something simple and easy to maintain for my specific use case. So here&rsquo;s the way I&rsquo;ve done it, using a couple of DNS records and <a href="https://ansible.com/tower">Ansible Tower</a>.</p>
<p>For my particular need, all I wanted was for newly booted hosts to automatically find their configuration. Since I am using <a href="https://ansible.com">Ansible</a> in its <a href="https://www.ansible.com/how-ansible-works">push based model</a>, this meant allowing my newly provisioned host to &lsquo;phone home&rsquo; - announcing its presence so that my centralised Ansible host could push the configuration. My centralisation is controlled by <a href="https://ansible.com/tower">Ansible Tower</a>.</p>
<p>But what if a network is fluid? What if I want a &lsquo;baked template&rsquo; (for example, a <a href="https://pubs.vmware.com/vsphere-4-esx-vcenter/index.jsp?topic=/com.vmware.vsphere.vmadmin.doc_41/vsp_vm_guide/deploy_vms_from_templates_and_clones/c_working_with_templates_and_clones.html">VMware template</a>) without hard coded hostnames in? How would my new host work out where to phone home, or for that matter, <em>how</em> to phone home?</p>
<p>What we need is a reliable, tried and tested, centralised infrastructure that can be used as an information source. What could possibly fit that need? Oh, yes, how about DNS? And how would we make use of it for this purpose? With two simple records - an <a href="https://www.ietf.org/rfc/rfc2782.txt">SRV</a> and a <a href="https://en.wikipedia.org/wiki/TXT_Record">TXT</a>.</p>
<p>In the vein of keeping things simple, on this particular network I am using <a href="https://www.thekelleys.org.uk/dnsmasq/doc.html">dnsmasq</a>. It wouldn&rsquo;t be much more complex to use <a href="https://en.wikipedia.org/wiki/BIND">BIND</a>, of course.</p>
<p>I&rsquo;ve created two records in dnsmasq, one to allow my hosts to discover <em>where</em> to phone home to, and a second to provide information <em>on what to ask for</em>. Here are those records:</p>
<div class="overflow-hidden rounded-sm shadow-lg">
  
  <div class="flex items-center gap-2 bg-gray-200 px-4 py-2 dark:bg-gray-700">
    <div class="size-3 rounded-full bg-red-500"></div>
    <div class="size-3 rounded-full bg-yellow-500"></div>
    <div class="size-3 rounded-full bg-green-500"></div>
  </div>
  
  <div class="bg-white px-8 py-2 dark:bg-gray-900">
    <pre
      class="overflow-x-auto whitespace-pre-wrap break-words"
    ><code>srv-host=_cm._tcp.lan,tower.lan,80,0,0
srv-host=_cm._tcp.lan,tower2.lan,80,20,0
txt-record=lan,&#34;59301625893930005661466df034870d 20&#34;</code></pre>
  </div>
</div>
<p>Let me explain them.</p>
<p>There are two SRV records - you&rsquo;ll notice the difference being an apparent hostname, and a number towards the end of the line. The line is described like so:</p>
<div class="overflow-hidden rounded-sm shadow-lg">
  
  <div class="flex items-center gap-2 bg-gray-200 px-4 py-2 dark:bg-gray-700">
    <div class="size-3 rounded-full bg-red-500"></div>
    <div class="size-3 rounded-full bg-yellow-500"></div>
    <div class="size-3 rounded-full bg-green-500"></div>
  </div>
  
  <div class="bg-white px-8 py-2 dark:bg-gray-900">
    <pre
      class="overflow-x-auto whitespace-pre-wrap break-words"
    ><code>srv_record, hostname, port, priority, weight</code></pre>
  </div>
</div>
<p>Priority and weight allow us to have multiple records for resiliency, with a lower priority taking precedence, and higher weights of the same priority being more important. I tend to skip using weightings, and set the priority fields alone. So here, &ldquo;tower.lan&rdquo; takes priority over &ldquo;tower2.lan&rdquo;.</p>
<p>Secondly we have the TXT record, with the first portion being a hostname - or in this case, the whole domain, and the second portion being a free form amount of text. I&rsquo;ve kept this pretty simple, because it works nicely for this next portion.</p>
<p>Ansible Tower has a really neat function called &lsquo;callbacks&rsquo;, which exposes a given job template as a REST URL. This then permits calling the URL with tools as simple as <a href="https://curl.haxx.se/">cURL</a>. It isn&rsquo;t intended for heavy use (i.e. it&rsquo;s not there to implement a pseudo client/server architecture) but for &lsquo;phoning home&rsquo; to get an initial configuration, it&rsquo;s brilliant.</p>
<p>Poking the callback URL needs three things to be in place for it to work - a &lsquo;<a href="https://dictionary.cambridge.org/dictionary/british/belt-and-braces">belt and braces</a>&rsquo; approach if you like. First, the calling host (our &lsquo;client&rsquo;) needs to be known to Tower&rsquo;s inventory; <em>&quot;<a href="https://youtu.be/tguP14GMrCA?t=18s">your name&rsquo;s not down, you&rsquo;re not coming in</a>&quot;</em>. The client then needs to poke the URL with two pieces of information - a &ldquo;host config key&rdquo;, which Tower generates for us, and a job ID, which we get from the template.</p>
<p>Shipped with Tower is a nice little wrapper around this call - look for <code>request_tower_configuration.sh</code> in /usr/share/awx.</p>
<p>Pulling all this together, I&rsquo;ve included request_tower_configuration.sh as part of my VM template, and I simply run it at first boot like so:</p>
<div class="overflow-hidden rounded-sm shadow-lg">
  
  <div class="flex items-center gap-2 bg-gray-200 px-4 py-2 dark:bg-gray-700">
    <div class="size-3 rounded-full bg-red-500"></div>
    <div class="size-3 rounded-full bg-yellow-500"></div>
    <div class="size-3 rounded-full bg-green-500"></div>
  </div>
  
  <div class="bg-white px-8 py-2 dark:bg-gray-900">
    <pre
      class="overflow-x-auto whitespace-pre-wrap break-words"
    ><code>request_tower_configuration.sh $(dig &#43;short _cm._tcp.lan srv | awk &#39;/^0/ {print $4}&#39;) $(dig &#43;short lan txt | tr -d &#39;&#34;&#39;)</code></pre>
  </div>
</div>
<p>The two dig commands grab the information request_tower_configuration.sh needs - the host to contact and the config key and job ID.</p>
<p>Discovering information like this gives me the flexibility to move Tower hosts around, and even to change the configuration job that&rsquo;s requested; without having to do anything to my baked template. I can even offer different jobs to hosts with different DNS views - using a more sophisticated DNS server like BIND could give us quite a bit more flexibility. You could take the TXT record theory even further - using different records to provide different actions.</p>
<p>Fundamentally what this has given me is a lot of flexibility without having to &lsquo;reinvent the wheel&rsquo;.</p>
<p>Lastly, the keen eyed among you will notice my &lsquo;cheap&rsquo; call here ignores my SRV record resiliency. Yes, indeed it does. I leave that as an exercise to the reader. You might like to write your own wrapper around cURL, for example.</p>]]>
      
      <![CDATA[<hr><p>Thanks for reading this post via RSS! 👏</p>]]>
      <![CDATA[<a href="mailto:rs511@probably.co.uk?subject=Simple service discovery using Ansible Tower and DNS">Reply to this post by email</a>]]>
      </description>
    </item>
    <item>
      <title>The rules</title>
      <link>https://probably.co.uk/posts/the-rules/</link>
      <pubDate>Sun, 30 Nov 2014 00:00:00 +0000</pubDate>
      <guid>https://probably.co.uk/posts/the-rules/</guid>
      <description>
      
      <![CDATA[<p>The Unix philosophy. There are some <a href="https://en.wikipedia.org/wiki/Unix_philosophy">wise words here</a>.</p>
<ol>
<li>Rule of Modularity: Write simple parts connected by clean interfaces.</li>
<li>Rule of Clarity: Clarity is better than cleverness.</li>
<li>Rule of Composition: Design programs to be connected to other programs.</li>
<li>Rule of Separation: Separate policy from mechanism; separate interfaces from engines.</li>
<li>Rule of Simplicity: Design for simplicity; add complexity only where you must.</li>
<li>Rule of Parsimony: Write a big program only when it is clear by demonstration that nothing else will do.</li>
<li>Rule of Transparency: Design for visibility to make inspection and debugging easier.</li>
<li>Rule of Robustness: Robustness is the child of transparency and simplicity.</li>
<li>Rule of Representation: Fold knowledge into data so program logic can be stupid and robust.</li>
<li>Rule of Least Surprise: In interface design, always do the least surprising thing.</li>
<li>Rule of Silence: When a program has nothing surprising to say, it should say nothing.</li>
<li>Rule of Repair: When you must fail, fail noisily and as soon as possible.</li>
<li>Rule of Economy: Programmer time is expensive; conserve it in preference to machine time.</li>
<li>Rule of Generation: Avoid hand-hacking; write programs to write programs when you can.</li>
<li>Rule of Optimization: Prototype before polishing. Get it working before you optimize it.</li>
<li>Rule of Diversity: Distrust all claims for “one true way”.</li>
<li>Rule of Extensibility: Design for the future, because it will be here sooner than you think.</li>
</ol>]]>
      
      <![CDATA[<hr><p>Thanks for reading this post via RSS! 👏</p>]]>
      <![CDATA[<a href="mailto:rs511@probably.co.uk?subject=The rules">Reply to this post by email</a>]]>
      </description>
    </item>
    <item>
      <title>Being a part of it</title>
      <link>https://probably.co.uk/posts/being-a-part-of-it/</link>
      <pubDate>Tue, 07 Oct 2014 00:00:00 +0000</pubDate>
      <guid>https://probably.co.uk/posts/being-a-part-of-it/</guid>
      <description>
      
      <![CDATA[<p>In the summer of 2013 I worked on a project that introduced me to <a href="https://ansible.com">Ansible</a>. I was so impressed by it that I <a href="/posts/puppet-vs-chef-vs-ansible/">wrote a blog post</a>. I found Ansible to be different to the plethora of software that constantly tries to grab our attention these days, and I&rsquo;ve pretty much evangelised it since.</p>
<p>From presenting at DevOps Cardiff and the London Splunk User Group, I have tried to spread the word. Because Ansible is the embodiment of something I&rsquo;ve been going on about for years - the tech industry keeps trying to make things <a href="/posts/defining-devops/">more complicated than they need to be</a>.</p>
<p>Making things complicated isn&rsquo;t the answer, <a href="/posts/the-route-to-devops-simplicity/">making them simple is</a>!</p>
<p>So I am proud to say that I&rsquo;m becoming a small part of Ansible, Inc. From today, I will be their first representative in the UK and Europe.</p>
<p>For the short term, I&rsquo;ll still be juggling my commitments with VNTX and DevOpsGuys, but you can also reach me as mark AT ansible.com</p>
]]>
      
      <![CDATA[<hr><p>Thanks for reading this post via RSS! 👏</p>]]>
      <![CDATA[<a href="mailto:rs511@probably.co.uk?subject=Being a part of it">Reply to this post by email</a>]]>
      </description>
    </item>
    <item>
      <title>Defining &#39;DevOps&#39;</title>
      <link>https://probably.co.uk/posts/defining-devops/</link>
      <pubDate>Sat, 19 Jul 2014 00:00:00 +0000</pubDate>
      <guid>https://probably.co.uk/posts/defining-devops/</guid>
      <description>
      
      <![CDATA[<p>You know what, I am starting to despair of the IT industry, just a little bit.</p>
<p>I&rsquo;ve been working in IT for just over 20 years - I was very lucky to ride the greatest wave we&rsquo;ve seen, the dawn of the Internet (I worked for the largest corporate ISP in the world, UUNET, from early 1996 to 2001), and I&rsquo;ve worked in the slowest, most immobile companies you can imagine (Investment Banks). And in the last 5-10 years I&rsquo;ve seen less and less common sense be applied. And now we have this word that nobody can truly define. And it&rsquo;s creating even more silliness. People are spending energy, lots of energy, debating this phrase and its definition (the irony of this post is not lost on me).</p>
<p>I despair of Agile as a formulaic solution to all our woes, I really do. I watch organisations debate over Kanban versus Scrum, then pick one and apply every last facet of the methodology to everything they do - in effect making project management so granular as to become weighty and patronising micromanagement. Yes, there are great points to it - releasing often is better than spending months, years, planning something then trying to release in a big bang. But at the same time barely planning past two weeks is akin to driving along the road looking at the end of your car bonnet.</p>
<p>I feel sorry for those organisations that pick up yet another piece of software that they believe will &lsquo;fix everything&rsquo; for them, but in reality they purchase a well sold lump of complexity that could be achieved much, much simpler.</p>
<p>Then <a href="https://twitter.com/mikebaukes">Mike</a> at UpGuard brought to my attention <a href="https://www.upguard.com/blog/the-problem-with-defining-devops">an article</a> they&rsquo;d posted about DevOps. And I think it&rsquo;s spot on, in a single paragraph:</p>
<p><em>&ldquo;The core of DevOps is not a difficult or complex concept. More or less, it&rsquo;s the idea that developers and operations should collaborate more closely than they traditionally have, so neither side is caught with their pants down when something blows up&rdquo;</em></p>
<p>The core ethos has spawned many, valid, accoutrements, but at its simplest definition it is about us all &lsquo;rowing in the same direction&rsquo;. Developers, Operations, we&rsquo;re all in the same boat. <a href="/posts/the-route-to-devops-simplicity">Let&rsquo;s work together to make it go forward</a>. Creating a &lsquo;DevOps Team&rsquo; is completely missing the point - you&rsquo;ve just created yet another silo, where if the culture isn&rsquo;t worked at (like any solid relationship, a culture of communicating and sharing needs constant work), communications will fail and we&rsquo;ll have <em>three teams</em> doing their own thing.</p>
<p>Across my working years I&rsquo;ve been a network engineer, a systems engineer, a network manager, a project manager, a security consultant and a technical consultant. Every role has involved working with other people to deliver a <strong>business goal</strong>. And I&rsquo;ve always found that the goal was much easier to hit when I talked to my colleagues and customers.</p>
<p><strong><em>It&rsquo;s not difficult, it&rsquo;s common sense.</em></strong></p>
<p>But what is it they say about common sense? It&rsquo;s surprising how uncommon it is.</p>]]>
      
      <![CDATA[<hr><p>Thanks for reading this post via RSS! 👏</p>]]>
      <![CDATA[<a href="mailto:rs511@probably.co.uk?subject=Defining 'DevOps'">Reply to this post by email</a>]]>
      </description>
    </item>
    <item>
      <title>Logwatch output to NFS with SELinux</title>
      <link>https://probably.co.uk/posts/logwatch-output-to-nfs-with-selinux/</link>
      <pubDate>Sun, 12 Jan 2014 00:00:00 +0000</pubDate>
      <guid>https://probably.co.uk/posts/logwatch-output-to-nfs-with-selinux/</guid>
      <description>
      
      <![CDATA[<p>As part of a log consolidation exercise I&rsquo;d decided to try and put logwatch
output into Splunk, to later produce some succinct analysis.</p>
<p>The easiest way for me to achieve this was to send the logwatch output to a
file on a NFS volume.</p>
<p>However, the host in question has SELinux enabled (quite deliberately). Often
the answer to SELinux problems is &lsquo;disable it&rsquo;, but that&rsquo;s not the proper
answer! And really, I could do with learning it.</p>
<p>First off, analysis of the audit log told me what I suspected - it was SELinux
preventing the write:</p>
<div class="overflow-hidden rounded-sm shadow-lg">
  
  <div class="flex items-center gap-2 bg-gray-200 px-4 py-2 dark:bg-gray-700">
    <div class="size-3 rounded-full bg-red-500"></div>
    <div class="size-3 rounded-full bg-yellow-500"></div>
    <div class="size-3 rounded-full bg-green-500"></div>
  </div>
  
  <div class="bg-white px-8 py-2 dark:bg-gray-900">
    <pre
      class="overflow-x-auto whitespace-pre-wrap break-words"
    ><code># ausearch -m avc --start today 
----
time-&gt;Sun Jan 12 03:14:05 2014
type=SYSCALL msg=audit(1389496445.113:2441932): arch=c000003e syscall=2 success=no exit=-13 a0=2817680 a1=441 a2=1b6 a3=37ba71dd40 items=0 ppid=32511 pid=32517 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=(none) ses=31998 comm=&#34;logwatch&#34; exe=&#34;/usr/bin/perl&#34; subj=system_u:system_r:logwatch_t:s0-s0:c0.c1023 key=(null)
type=AVC msg=audit(1389496445.113:2441932): avc:  denied  { write } for  pid=32517 comm=&#34;logwatch&#34; name=&#34;host&#34; dev=0:1c ino=1834908 scontext=system_u:system_r:logwatch_t:s0-s0:c0.c1023 tcontext=system_u:object_r:nfs_t:s0 tclass=dir</code></pre>
  </div>
</div>
<p>The key bits to note here are the scontext, the tcontext and the tclass -
source and target contexts, and the target class.</p>
<p>Essentially, the target directory was of &rsquo;type&rsquo; <code>nfs_t</code>, and the source process
was of <code>logwatch_t</code> type.</p>
<p>Let&rsquo;s check the default SELinux policy for this combination:</p>
<div class="overflow-hidden rounded-sm shadow-lg">
  
  <div class="flex items-center gap-2 bg-gray-200 px-4 py-2 dark:bg-gray-700">
    <div class="size-3 rounded-full bg-red-500"></div>
    <div class="size-3 rounded-full bg-yellow-500"></div>
    <div class="size-3 rounded-full bg-green-500"></div>
  </div>
  
  <div class="bg-white px-8 py-2 dark:bg-gray-900">
    <pre
      class="overflow-x-auto whitespace-pre-wrap break-words"
    ><code># sesearch -t nfs_t -s logwatch_t -c dir -A
   allow logwatch_t nfs_t : dir { ioctl read getattr lock search open } ; </code></pre>
  </div>
</div>
<p>Ah - so <code>logwatch_t</code> cannot write to a dir of type <code>nfs_t.</code> That&rsquo;ll be our
problem.</p>
<p>We can fix this by writing a custom module. The easy way is to take our denied
log entry and pipe it through <code>audit2allow</code>. First off, let&rsquo;s do that, but
output to a text file for review, before we implement the rule:</p>
<div class="overflow-hidden rounded-sm shadow-lg">
  
  <div class="flex items-center gap-2 bg-gray-200 px-4 py-2 dark:bg-gray-700">
    <div class="size-3 rounded-full bg-red-500"></div>
    <div class="size-3 rounded-full bg-yellow-500"></div>
    <div class="size-3 rounded-full bg-green-500"></div>
  </div>
  
  <div class="bg-white px-8 py-2 dark:bg-gray-900">
    <pre
      class="overflow-x-auto whitespace-pre-wrap break-words"
    ><code># ausearch -m avc --start today | audit2allow -m logwatch_nfs_write -o logwatch_nfs_write.te</code></pre>
  </div>
</div>
<p>(we could just have easily grep&rsquo;d for the offending line in the actual
audit.log file)</p>
<p>Now review the output file to make sure it&rsquo;s all sensible:</p>
<div class="overflow-hidden rounded-sm shadow-lg">
  
  <div class="flex items-center gap-2 bg-gray-200 px-4 py-2 dark:bg-gray-700">
    <div class="size-3 rounded-full bg-red-500"></div>
    <div class="size-3 rounded-full bg-yellow-500"></div>
    <div class="size-3 rounded-full bg-green-500"></div>
  </div>
  
  <div class="bg-white px-8 py-2 dark:bg-gray-900">
    <pre
      class="overflow-x-auto whitespace-pre-wrap break-words"
    ><code>module logwatch_nfs_write 1.0;
 
require {
        type logwatch_t;
        type nfs_t;
        class dir write;
}
 
#============= logwatch_t ==============
#!!!! The source type &#39;logwatch_t&#39; can write to a &#39;dir&#39; of the following types:
# var_lock_t, tmp_t, logwatch_cache_t, logwatch_tmp_t, var_run_t
 
allow logwatch_t nfs_t:dir write;</code></pre>
  </div>
</div>
<p>OK, looks sensible. So now we can compile it, and insert into the running
modules:</p>
<div class="overflow-hidden rounded-sm shadow-lg">
  
  <div class="flex items-center gap-2 bg-gray-200 px-4 py-2 dark:bg-gray-700">
    <div class="size-3 rounded-full bg-red-500"></div>
    <div class="size-3 rounded-full bg-yellow-500"></div>
    <div class="size-3 rounded-full bg-green-500"></div>
  </div>
  
  <div class="bg-white px-8 py-2 dark:bg-gray-900">
    <pre
      class="overflow-x-auto whitespace-pre-wrap break-words"
    ><code># ausearch -m avc --start today | audit2allow -M logwatch_nfs_write
# semodule -i logwatch_nfs_write.pp</code></pre>
  </div>
</div>
<p>And check it&rsquo;s in memory:</p>
<div class="overflow-hidden rounded-sm shadow-lg">
  
  <div class="flex items-center gap-2 bg-gray-200 px-4 py-2 dark:bg-gray-700">
    <div class="size-3 rounded-full bg-red-500"></div>
    <div class="size-3 rounded-full bg-yellow-500"></div>
    <div class="size-3 rounded-full bg-green-500"></div>
  </div>
  
  <div class="bg-white px-8 py-2 dark:bg-gray-900">
    <pre
      class="overflow-x-auto whitespace-pre-wrap break-words"
    ><code># semodule -l | grep logwa
logwatch_nfs_write      1.0</code></pre>
  </div>
</div>
<p>Now when I run logwatch the file is created. Sorted.</p>
<hr>
<p>There are some examples in /usr/share/selinux/devel, on CentOS at least, that
could be useful for writing modules from scratch.</p>]]>
      
      <![CDATA[<hr><p>Thanks for reading this post via RSS! 👏</p>]]>
      <![CDATA[<a href="mailto:rs511@probably.co.uk?subject=Logwatch output to NFS with SELinux">Reply to this post by email</a>]]>
      </description>
    </item>
    <item>
      <title>Rapidly provision Jenkins on AWS using Ansible</title>
      <link>https://probably.co.uk/posts/rapidly-provision-jenkins-on-aws-using-ansible/</link>
      <pubDate>Sun, 10 Nov 2013 00:00:00 +0000</pubDate>
      <guid>https://probably.co.uk/posts/rapidly-provision-jenkins-on-aws-using-ansible/</guid>
      <description>
      
      <![CDATA[<p>This week I&rsquo;d been fighting with a Chef install to do something relatively
simple. Bogged down in a rats nest of complexity (extra Ruby scripts
referencing Chef environment files, etc etc), I decided to see if there was a
easier way.</p>
<p>Although I wasn&rsquo;t actually trying to install Jenkins, my workflow led me to
look at installing it with <a href="https://ansible.com">Ansible</a> as a proof of concept.
Basically I wanted to see how easy this task could really be.</p>
<p>I&rsquo;ve put the playbook, along with some notes, into a <a href="https://github.com/phips/aws-jenkins">Github
repo</a>, which you should feel free to fork
and play around with.</p>
<p>Currently this is a very simple example - spin up the EC2 instance, then
install and run Jenkins as its own daemon (on the default port of 8080).</p>
<p>The playbook includes an example of how to use Ansible&rsquo;s <a href="https://docs.ansible.com/route53_module.html">Route53 module</a>.  See <a href="https://github.com/phips/aws-jenkins/blob/master/README.md">the readme</a> for extra notes.</p>
<p>Enjoy.</p>]]>
      
      <![CDATA[<hr><p>Thanks for reading this post via RSS! 👏</p>]]>
      <![CDATA[<a href="mailto:rs511@probably.co.uk?subject=Rapidly provision Jenkins on AWS using Ansible">Reply to this post by email</a>]]>
      </description>
    </item>
    <item>
      <title>The meaning of DevOps has lost its simplicity</title>
      <link>https://probably.co.uk/posts/the-route-to-devops-simplicity/</link>
      <pubDate>Sun, 10 Nov 2013 00:00:00 +0000</pubDate>
      <guid>https://probably.co.uk/posts/the-route-to-devops-simplicity/</guid>
      <description>
      
      <![CDATA[<p>The greatest piece of engineering man has ever achieved is the humble bicycle.
A controversial statement, perhaps. But bear with me&hellip;</p>
<p>There are many things that could be given the label of <em>&ldquo;the greatest piece
of engineering&rdquo;</em>, and we could debate them forever. I&rsquo;m sticking to my
statement. But why?</p>
<p>Because, in over 100 years since The Safety Bicycle came about, the &lsquo;double
diamond&rsquo; frame design has basically gone unchanged<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>. The
fundamental design cannot be improved on.</p>
<p>That, to me, is quite some achievement. And the beauty of it is not complexity.
It is simplicity.</p>
<p>How does this relate to technology? I&rsquo;ve mentioned before that my favourite quote is from Einstein, <em>&ldquo;Make everything as simple as possible, but not simpler&rdquo;</em>. I am also a fan of <a href="https://en.wikipedia.org/wiki/Dieter_Rams">Dieter Rams</a>&rsquo; <a href="https://www.vitsoe.com/gb/about/good-design">10 principles of good design</a>.</p>
<p>Rams&rsquo; last point echoes the Einstein quote - <em>&ldquo;Good design is as little design
as possible&rdquo;. &ldquo;Less, but better – because it concentrates on the essential
aspects, and the products are not burdened with non-essentials. Back to purity,
back to simplicity&rdquo;</em>.</p>
<p>It is possible to build quality IT infrastructures these days without resorting
to complex and bloated products <a href="/posts/defining-devops/">that promise an easy life</a>. Supporting a complex environment is considerably harder, it takes longer for new hires to learn, and time taken to resolve problems is drastically extended. These translate to higher costs to a business, and a very real reduction in the ability to meet customer expectations. What might have seemed a quick shortcut
to take initially has led you into a dense and overgrown forest.</p>
<p>The phrase du jour, <em>DevOps</em>, has had much interpretation. To me, it is a label
applied to what any business with quality engineering would have been doing for
years anyway. Plus, it is more about culture than technology. Giving developers
a smooth route to production needn&rsquo;t be a minefield of complexity, wrapped in
layers and layers of &rsquo;trendy&rsquo; software products that are doing a simple job.</p>
<p>Returning to the bicycle, here&rsquo;s <a href="https://en.wikipedia.org/wiki/Hovenring">The Hovenring</a>
in the Netherlands:</p>
<p><img src="hovenring.jpg" alt="Hovenring"></p>
<p>The challenge was to keep traffic, of all sorts, moving in a smooth and safe
way. They could have introduced phased traffic lights, or burrowed under the
ground; but both of these solutions have obvious negatives. There is smart
engineering at work here - something <em>as simple as it needs to be</em>.</p>
<p>The DevOps integration of developers and operations isn&rsquo;t just about technology,
it is about communication. <em>It is about people</em>. It should be a consultative
workflow, where the right skills are used to design the solution. It isn&rsquo;t about
taking yet another product and throwing it into the infrastructure soup, it&rsquo;s
about discussing business goals and using both sets of skills to achieve them.</p>
<p>Regardless of the label, progressing a business&rsquo;s technology can be achieved
through smart, <em>simple</em>, engineering without being overwrought.</p>
<p>I&rsquo;ll finish off with a link to a short video. The <a href="https://vitsoe.com">Vitsoe</a>
shelving system, designed by Rams in 1959 and still fundamentally the same
today, epitomises my thoughts on IT infrastructure design. The first 40 seconds
are golden words we should strive for in the tech industry too.</p>
<p><a href="https://vitsoe.com">Vitsoe</a> &lsquo;A persistent system&rsquo;</p>
<div class="relative overflow-hidden pb-[56.25%] pt-[30px]">
  <iframe
    type="text/html"
    src="https://www.youtube-nocookie.com/embed/QlgXFRqfyWo"
    allowfullscreen
    frameborder="0"
    class="absolute left-0 top-0 size-full"
  ></iframe>
</div>


<hr>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>The Rover <a href="https://en.wikipedia.org/wiki/Safety_bicycle#Characteristics">Safety Bicycle</a>, around 1885&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>]]>
      
      <![CDATA[<hr><p>Thanks for reading this post via RSS! 👏</p>]]>
      <![CDATA[<a href="mailto:rs511@probably.co.uk?subject=The meaning of DevOps has lost its simplicity">Reply to this post by email</a>]]>
      </description>
    </item>
    <item>
      <title>Puppet vs Chef vs Ansible</title>
      <link>https://probably.co.uk/posts/puppet-vs-chef-vs-ansible/</link>
      <pubDate>Tue, 01 Oct 2013 00:00:00 +0000</pubDate>
      <guid>https://probably.co.uk/posts/puppet-vs-chef-vs-ansible/</guid>
      <description>
      
      <![CDATA[<p>I&rsquo;ve spent my entire IT career automating. To me, the point of technology is to
make life easier, so I tend to look for any way I can to make computers do &rsquo;the
heavy lifting'.</p>
<p>Configuration Management is the epitome of automation, it forms the bedrock of
achieving supportable, repeatable and consistent services. CM is also key
to the phrase-du-jour, &lsquo;DevOps&rsquo;. Your end to end (dev to prod) application
deployment is nowhere without CM.</p>
<p>This is an opinion piece. There are no tests, they&rsquo;re simply observations
with comments. Therefore it&rsquo;s very subjective. You may well have a different
point of view. I welcome comments.</p>
<p>Some salient points:</p>
<ol>
<li>I&rsquo;ve been working with Puppet as my choice of CM for over six years. I&rsquo;ve
implemented it for a good few clients, and worked with it in other,
established, infrastructures. And for the most part, I like it.</li>
<li>Despite that, I&rsquo;m not the biggest fan of Ruby. Sure, I write some stuff in
it, but it wouldn&rsquo;t be, isn&rsquo;t, my first choice of &lsquo;glue&rsquo; language.</li>
<li>I&rsquo;m a UNIX person. I don&rsquo;t care about anything from, or relating to,
Microsoft.</li>
<li>I am pragmatic. Whereas I like to do things the best way possible [that I
think ;-)] I will also implement with the client in mind. For the most part
I am software agnostic (apart from having <em>favourites</em>, of course).</li>
<li>My favourite quote is from Einstein: &ldquo;Make everything as simple as possible,
but not simpler&rdquo;.</li>
</ol>
<p>So, let&rsquo;s get on with it.</p>
<h2 id="puppet"><a href="https://puppet.com">Puppet</a></h2>
<p>I&rsquo;ve already mentioned that I&rsquo;ve a solid background with Puppet. The main thing
I like about it, and always have done, is the DSL. Puppet has a nice, simple,
language for describing your systems. &ldquo;Package&rdquo;, &ldquo;Service&rdquo;, &ldquo;User&rdquo;, &ldquo;requires&rdquo;,
etc. etc.  It&rsquo;s simple to read, easy to understand, and system agnostic.</p>
<p>It&rsquo;s a fairly trivial install with few dependencies [Ruby], and if you use the
Enterprise version it&rsquo;s even easier. And unless you&rsquo;re using Dashboard, you
don&rsquo;t really need a database (which for small implementations - of anything -
is good in my book).</p>
<p>A lot of large organisations want a GUI, and want to be able to manage systems
from it (be that web or otherwise) - which Puppet Enterprise provides (you can
run Dashboard as open source too). And, although I don&rsquo;t care in the slightest,
it supports Microsoft Windows too.</p>
<p>Puppet themselves maintain package repos that contain most of the dependencies
too (there are some Ruby modules that aren&rsquo;t in RedHat base distros, like
CentOS, for example), which again makes life a bit easier.</p>
<p>There&rsquo;s a great community, and lots of modules have already been written &rsquo;to do
stuff&rsquo;. Their founder, Luke Kanies, wanted a solution to stop sysadmins
&rsquo;re-inventing the wheel&rsquo; at every company. I think Puppet achieves that.</p>
<p>The negatives - well, sometimes you can get into a pickle with resource
dependencies (e.g. service X needs package Y and config file Z). You can only
define a &lsquo;resource&rsquo; in one place (e.g. an httpd service), which for newbies can
be confusing. But I&rsquo;m nit-picking, you get over that one quick enough.</p>
<p>It can be slow when you have hundreds or more clients trying to get their
catalog. I&rsquo;ve given up running Puppet as a client-server architecture now, and
run &lsquo;masterless&rsquo;. This seems to be an increasing trend. Put all your manifests
into a version control system (say, git) and check that out on every host.
You&rsquo;ve a simple, trusted, transport mechanism in SSH, and the application of
the configuration just runs locally. No overloaded central server to worry
about. Run the checkout under cron, with a random timing element, and you don&rsquo;t
generate a different performance problem by every host SSH&rsquo;ing in at the same
time.</p>
<h2 id="chef">Chef</h2>
<p>I&rsquo;ve only recently been exposed to, and had to use, Chef. I didn&rsquo;t chose to use
it, but being pragmatic I went into the piece of client work open minded - I
knew Chef came about shortly after Puppet, which influenced its formation. I
had heard they were similar products.</p>
<p>But for starters I&rsquo;ve been put off by its DSL - it&rsquo;s Ruby. Just pure old Ruby.
I guess this would make it feel like &lsquo;a comfortable pair of shoes&rsquo; for a Ruby
developer to start managing systems, but coming from a systems background all I
can see is it makes it hard work for anybody not a programmer by trade. It also
seems overly complex. Workstation, Server and Clients. Knife, chef-client,
chef-solo. Data structures in JSON. A Postgres database.</p>
<p>I&rsquo;m also seeing a lot of &lsquo;shelling out&rsquo; in the manifests at this particular
client, which makes me think they were unable to achieve what they wanted
within Chef too (&rsquo;execs&rsquo; are frowned upon in the Puppet community - but of
course, if you&rsquo;re just running shell scripts on a system it is rather bloated
and inefficient to be wrapping them in Ruby! You might as well go back to old
skool <em>for-looped</em> copying of scripts over SSH).</p>
<p>And this is the thing. If you are a web programmer, maybe working on Rails,
then all this is familiar ground, so it seems simple to pick it to manage your
systems.</p>
<p>But, wait, why would you? Why would you pick something that is, as far
as I can see, Puppet made overly complex? Nothing about Chef makes sense to me
when I compare it to other CM solutions.</p>
<p>Even when you factor in somebody coming at it from a familiar background, it
wouldn&rsquo;t take a Ruby programmer, or any programmer for that matter, at all long
to &lsquo;get&rsquo; Puppet&rsquo;s DSL, it is that simple. Puppet has a data store like Chef&rsquo;s
data-bags, but it&rsquo;s YAML instead of JSON. And when I look at the two file
formats, I fail to see why you would use JSON (for a human readable data store,
I mean. Granted it&rsquo;s a web programming standard, so discount that) when YAML is
so much more readable.</p>
<p>If I&rsquo;d come to Chef before Puppet I&rsquo;d probably see all its good points - it
delivers centralised configuration management in a, relatively, [Ruby] easy
way. But I&rsquo;ve not, I&rsquo;ve used something that is similar but oh so much simpler.</p>
<p>I just cannot see the point of picking Chef over Puppet.</p>
<p>UPDATE: Interestingly, in the comments below, somebody brought to my attention
an old blog post elsewhere that said of Chef - <em>&ldquo;It’s a remote execution engine
with a great deal of architectural overhead&rdquo;</em>.</p>
<p>But wait, we&rsquo;re not done yet&hellip;</p>
<h2 id="ansible"><a href="https://ansible.com">Ansible</a></h2>
<p>Ansible is, again, another recent exposure for me. At pretty much the same time
as Chef, since it&rsquo;s being used as part of the same client project - which begs
the question, <em>why didn&rsquo;t they just stick to one CM solution?</em></p>
<p>Well, because it was being used to CM the setup of XenServers. Which don&rsquo;t
have Ruby on. And Ansible is based on Python, which is on pretty much any
base install of an OS these days (most of RedHat&rsquo;s toolset on RHEL is
written in Python, and even Sun were fond of writing tools in it too).</p>
<p>And this is where it got interesting for me. Ansible is the work of Michael
DeHaan. Some of you may know about Cobbler. When I learned this I was instantly
put off without even trying it (talk about judging a book by its cover) - I
never liked Cobbler. Too complicated for something that should be simple (this
is one of the reasons I wrote my own - totally not worthy of wider use! - Linux
kickstart tool, <a href="https://github.com/phips/bacio">Bacio</a>).</p>
<p>But then I started to use Ansible. And my first impression was good. Here is a
tool that works opposite to the way Chef and Puppet do [client-server]; it&rsquo;s a
push model. It requires no additional installs on the end points (unless you&rsquo;re
using selinux, then it takes one extra Python library that&rsquo;s more than likely
in the distribution repository anyway). It uses SSH for its transport. And YAML
(which I really like because it meets my requirement of <em>&lsquo;simple as possible,
but no simpler&rsquo;</em>) for the configuration language.</p>
<p>As I started to try to achieve things with Ansible I found it to be the
simplicity I want to see from technology. It could achieve all that I&rsquo;ve done
with Puppet for years, but in an even easier way.</p>
<p>The YAML &lsquo;playbooks&rsquo; fall through tasks like running down a firewall ruleset.
You can <em>see</em> the path your job takes right before you (Puppet does a complex
catalog compile to work out ordering, which can change from run to run. This
has positive and negative connotations, not least some occasional confusion).</p>
<p>No remote installs. No funny transports and odd ports to have to open on
firewalls. No complex SSL certificate management. No database servers.</p>
<p>And I&rsquo;m increasingly realising DeHaan (and one presumes his co-developers) have
thought of most things. You could run it client-server if you chose; by simply
emulating the master/server-less models of Puppet &amp; Chef[-Solo].</p>
<p>They have a commercial offering, <a href="https://ansible.com/tower">Ansible Tower</a>,
should you want a pretty dashboard. It&rsquo;s actually got some really nice
features too, one of my favourite being the REST API and Callbacks (see
<a href="https://releases.ansible.com/ansible-tower/docs/tower_user_guide-latest.pdf">page 114</a>
of the Tower manual for more information)</p>
<p>Ansible. Oh how I wish I&rsquo;d not been introduced to Ansible. Because now I can&rsquo;t
think about doing CM with anything else. I could still proceed with Puppet, (if
I really <em>had</em> to) but Ansible is at the other end of the spectrum to Chef as
far as I&rsquo;m concerned.</p>
<p>I&rsquo;m sure there&rsquo;ll be negatives somewhere along the line, there usually are
with technology. I just haven&rsquo;t found them yet. The obvious one I don&rsquo;t care about - it
doesn&rsquo;t support Windows[3] (really? You wouldn&rsquo;t train for a marathon by riding a
bicycle, you&rsquo;d run. So why try to lump management of Windows and UNIX/Linux
into the same space? Hire people who do Windows, hire people who do UNIX, and
let them manage their own estates).</p>
<p>You&rsquo;d probably have to do some funky routing and firewalling in a massive
estate to use the push model (you&rsquo;d probably opt for the client-server mimic).
And in its current form managing a large estate would probably be a bit like
hard work. But for an SME, or a startup, managing an estate from the shell? I
think it&rsquo;s brilliant.</p>
<h2 id="summary">Summary</h2>
<p>The long and short of it:</p>
<ul>
<li>Ansible works really well. I can&rsquo;t see the negatives<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>. It is my choice of
CM software right now, and I will encourage clients to use it whenever I can.</li>
<li>If you&rsquo;re absolutely against Python, SSH, and particularly want to install
agents on every machine you manage, or you need to manage Windows<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup> right
now, pick Puppet.</li>
<li>I can&rsquo;t actually think of a good reason to use Chef. Even if you&rsquo;re a Ruby
programmer you&rsquo;ll still be better off with Puppet.</li>
</ul>
<hr>
<p>[3] Update, June 19th 2014; Ansible now supports Windows. Or, at least, is
beginning to. <a href="https://www.ansible.com/blog/windows-is-coming">See this blog post</a>.</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>In the size of estates I&rsquo;m currently implementing for. Larger scale would be a
different matter, but again that&rsquo;s a whole other conversation - I&rsquo;ve worked in
companies with 20,000 server estates for the last few years, and I&rsquo;m not
convinced there are any solutions to handle that sort of scale &lsquo;properly&rsquo;&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p>Please, just don&rsquo;t! Apples and pears. Horses and sheep. Whatever. Let the
Windows bods look after their stuff, you stick to UNIX. It&rsquo;s better anyway.&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>]]>
      
      <![CDATA[<hr><p>Thanks for reading this post via RSS! 👏</p>]]>
      <![CDATA[<a href="mailto:rs511@probably.co.uk?subject=Puppet vs Chef vs Ansible">Reply to this post by email</a>]]>
      </description>
    </item>
    <item>
      <title>Analysing Amazon S3 logs with Splunk</title>
      <link>https://probably.co.uk/posts/analysing-amazon-s3-logs-with-splunk/</link>
      <pubDate>Sun, 15 Sep 2013 00:00:00 +0000</pubDate>
      <guid>https://probably.co.uk/posts/analysing-amazon-s3-logs-with-splunk/</guid>
      <description>
      
      <![CDATA[<p>Here&rsquo;s how to get Amazon S3 bucket logs into Splunk, and then pull out the useful fields.</p>
<p>You&rsquo;ll need to turn on <a href="https://docs.aws.amazon.com/AmazonS3/latest/UG/ManagingBucketLogging.html">logging of your bucket</a> in S3.</p>
<p>Next, install the <a href="https://apps.splunk.com/app/1137">S3 app</a> for Splunk. Configure an S3 input (<code>Manager &gt;&gt; Data inputs &gt;&gt; S3</code>). Your bucket logs will now automatically feed into Splunk (the sourcetype will be &lsquo;s3&rsquo;).</p>
<p>I&rsquo;ve written a &lsquo;rex&rsquo; filter to grab the fields I want to work with - date, IP,
action (REST) and file[name].</p>
<p>Stick this into the search field, then you can do all the usual Splunk
goodness with the resulting fields&hellip;</p>
<div class="overflow-hidden rounded-sm shadow-lg">
  
  <div class="flex items-center gap-2 bg-gray-200 px-4 py-2 dark:bg-gray-700">
    <div class="size-3 rounded-full bg-red-500"></div>
    <div class="size-3 rounded-full bg-yellow-500"></div>
    <div class="size-3 rounded-full bg-green-500"></div>
  </div>
  
  <div class="bg-white px-8 py-2 dark:bg-gray-900">
    <pre
      class="overflow-x-auto whitespace-pre-wrap break-words"
    ><code>sourcetype=&#34;s3&#34; | rex field=_raw &#34;(?x: \[ (?&lt;date&gt; .*) \] \s (?&lt;ip&gt; (?:\d{1,3}\.){3} \d{1,3}) .&#43;? REST\.(?&lt;action&gt; \w&#43;)\.OBJECT \s (?&lt;file&gt; .&#43;?) \s)&#34;</code></pre>
  </div>
</div>]]>
      
      <![CDATA[<hr><p>Thanks for reading this post via RSS! 👏</p>]]>
      <![CDATA[<a href="mailto:rs511@probably.co.uk?subject=Analysing Amazon S3 logs with Splunk">Reply to this post by email</a>]]>
      </description>
    </item>
    <item>
      <title>Running Splunk 5 behind Nginx with SSL and auth</title>
      <link>https://probably.co.uk/posts/running-splunk-5-behind-nginx-with-ssl-and-auth/</link>
      <pubDate>Mon, 09 Sep 2013 00:00:00 +0000</pubDate>
      <guid>https://probably.co.uk/posts/running-splunk-5-behind-nginx-with-ssl-and-auth/</guid>
      <description>
      
      <![CDATA[<p>Many articles have been written about this topic, yet none of them seem to
fulfill the basic premise I wanted: get it working.</p>
<p>The problem for me was if I ran SSL, the redirect was talking plain http, and
would try to redirect to the remote Splunk using http. My Splunk instance is
also running on a different machine to the Nginx front end.</p>
<p>So here are the config file details:</p>
<p>nginx <code>conf.d/splunk.conf</code></p>
<div class="overflow-hidden rounded-sm shadow-lg">
  
  <div class="flex items-center gap-2 bg-gray-200 px-4 py-2 dark:bg-gray-700">
    <div class="size-3 rounded-full bg-red-500"></div>
    <div class="size-3 rounded-full bg-yellow-500"></div>
    <div class="size-3 rounded-full bg-green-500"></div>
  </div>
  
  <div class="bg-white px-8 py-2 dark:bg-gray-900">
    <pre
      class="overflow-x-auto whitespace-pre-wrap break-words"
    ><code>server {
    listen 443 ssl;
    server_name log log.domain.com;

    access_log  /var/log/nginx/splunk_access.log;
    error_log   /var/log/nginx/splunk_error.log;

    ssl                       on;
    ssl_certificate           certs/my.crt;
    ssl_certificate_key       certs/my.key;
    ssl_session_timeout       5m;
    ssl_ciphers               HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers on;
    ssl_session_cache         shared:SSL:128m;

    location / {
        auth_basic           &#34;Login&#34;;
        auth_basic_user_file auth/users_file;

        proxy_pass       https://192.168.1.1:8000/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}</code></pre>
  </div>
</div>
<p>splunk <code>$SPLUNK_HOME/etc/system/local/web.conf</code></p>
<div class="overflow-hidden rounded-sm shadow-lg">
  
  <div class="flex items-center gap-2 bg-gray-200 px-4 py-2 dark:bg-gray-700">
    <div class="size-3 rounded-full bg-red-500"></div>
    <div class="size-3 rounded-full bg-yellow-500"></div>
    <div class="size-3 rounded-full bg-green-500"></div>
  </div>
  
  <div class="bg-white px-8 py-2 dark:bg-gray-900">
    <pre
      class="overflow-x-auto whitespace-pre-wrap break-words"
    ><code>[settings]
enableSplunkWebSSL = 1</code></pre>
  </div>
</div>]]>
      
      <![CDATA[<hr><p>Thanks for reading this post via RSS! 👏</p>]]>
      <![CDATA[<a href="mailto:rs511@probably.co.uk?subject=Running Splunk 5 behind Nginx with SSL and auth">Reply to this post by email</a>]]>
      </description>
    </item>
    <item>
      <title>Perl::Critic and Modern::Perl</title>
      <link>https://probably.co.uk/posts/perl-critic-and-modern-perl/</link>
      <pubDate>Sun, 18 Aug 2013 00:00:00 +0000</pubDate>
      <guid>https://probably.co.uk/posts/perl-critic-and-modern-perl/</guid>
      <description>
      
      <![CDATA[<p>I&rsquo;ve tended to use
<a href="https://metacpan.org/module/Perl::Critic">Perl::Critic</a> for
keeping my Perl in some semblence of a readable state for a while now. And
since I started using newer Perls, I&rsquo;ve also used
<a href="https://metacpan.org/module/Modern::Perl">Modern::Perl</a>
instead of &lsquo;use strict; use warnings; use feature..&rsquo;</p>
<p>However, using Modern::Perl means your perlcritic check will fail with &lsquo;code
before strictures&rsquo;. I also use
<a href="https://github.com/scrooloose/syntastic">Syntastic</a> in Vim,
which means every bit of Perl I write these days gets a nag.</p>
<p>I would&rsquo;ve thought Perl::Critic would catch up, but evidently not. Then I
discovered it&rsquo;s actually pretty simple to accept <code>use Modern::Perl</code> as valid code:</p>
<div class="overflow-hidden rounded-sm shadow-lg">
  
  <div class="flex items-center gap-2 bg-gray-200 px-4 py-2 dark:bg-gray-700">
    <div class="size-3 rounded-full bg-red-500"></div>
    <div class="size-3 rounded-full bg-yellow-500"></div>
    <div class="size-3 rounded-full bg-green-500"></div>
  </div>
  
  <div class="bg-white px-8 py-2 dark:bg-gray-900">
    <pre
      class="overflow-x-auto whitespace-pre-wrap break-words"
    ><code>Marks-MacBook:~$ cat ~/.perlcriticrc 
[TestingAndDebugging::RequireUseStrict]
equivalent_modules = Modern::Perl
 
[TestingAndDebugging::RequireUseWarnings]
equivalent_modules = Modern::Perl</code></pre>
  </div>
</div>
<p>Sorted.</p>]]>
      
      <![CDATA[<hr><p>Thanks for reading this post via RSS! 👏</p>]]>
      <![CDATA[<a href="mailto:rs511@probably.co.uk?subject=Perl::Critic and Modern::Perl">Reply to this post by email</a>]]>
      </description>
    </item>
    <item>
      <title>A Linux kickstart helper in Perl</title>
      <link>https://probably.co.uk/posts/a-linux-kickstart-helper-in-perl/</link>
      <pubDate>Sat, 27 Jul 2013 00:00:00 +0000</pubDate>
      <guid>https://probably.co.uk/posts/a-linux-kickstart-helper-in-perl/</guid>
      <description>
      
      <![CDATA[<p>I wrote a short while ago about <a href="/posts/using-ipxe-with-a-url-to-kickstart-linux">using iPXE with a
URL</a> to
help booting multiple versions of Linux. In that post I mentioned that I used a
simple CGI to feed back the required kernel and initrd, plus a template
kickstart file.</p>
<p>As rough as it stands today, a question prompted me to publish the helper I
use. So here you go, my Perl <a href="https://mojolicious.org">Mojolicious</a> helper,
<a href="https://github.com/phips/bacio">Bacio</a>.</p>
]]>
      
      <![CDATA[<hr><p>Thanks for reading this post via RSS! 👏</p>]]>
      <![CDATA[<a href="mailto:rs511@probably.co.uk?subject=A Linux kickstart helper in Perl">Reply to this post by email</a>]]>
      </description>
    </item>
    <item>
      <title>Using iPXE with a URL to kickstart Linux</title>
      <link>https://probably.co.uk/posts/using-ipxe-with-a-url-to-kickstart-linux/</link>
      <pubDate>Wed, 15 May 2013 00:00:00 +0000</pubDate>
      <guid>https://probably.co.uk/posts/using-ipxe-with-a-url-to-kickstart-linux/</guid>
      <description>
      
      <![CDATA[<p>Although kickstarting Linux is pretty simple, it can be frustrating if you&rsquo;re trying to build different versions. Take, for example, building RHEL (<a href="https://centos.org">CentOS</a>/<a href="https://scientificlinux.org/">SciLin</a>) version 5 and version 6 hosts. The initrd and vmlinuz files are version specific, and not backwards compatible. I&rsquo;ve seen a DHCP/PXE configuration, in a large bank, have a sprawling and complex set of menus just to counter for different OS releases! This is quite unnecessary.</p>
<blockquote>
<p><strong>UPDATE in 2024:</strong> Hello! This blog post is over 10 years old now, yet here we are in 2024 and I&rsquo;m seeing a large uptick in traffic coming here to read this. So before you read on, could I ask a small favour please? I&rsquo;m really intrigued as to why traffic has increased, so would you mind dropping me a quick email via the link below, or pinging me on <a href="https://mastodon.social/@thismarkp">Mastodon</a> or <a href="https://linkedin.com/in/markphillips">LinkedIn</a>, letting me know what you were looking for, and maybe a little about the problem you&rsquo;re trying to solve? The reason why I find this so intriguing is, the traffic spike tells me there&rsquo;s some sort of shift in infrastructure going on; maybe people are bringing workloads back from the cloud more frequently? Anyway, I&rsquo;d love to hear from you as to how you ended up here at this post. Thanks for taking time to read this bit, please do continue to read what you came here for 😊</p>
</blockquote>
<p>Sometime ago I looked at <a href="https://ipxe.org">iPXE</a>. There is a nice capability with it to <a href="https://ipxe.org/scripting">add a script</a>, or link, to the initial boot process. Using this I rolled a single ISO (you could put it in a DHCP/PXE/TFTP setup - I did it this way because I wanted a simple, transportable, solution to use on my desktop and laptop) with a link to a CGI I&rsquo;d written. Using the CGI I do a lookup, based on MAC address, for the host&rsquo;s intended Linux version and a tailored kickstart file.</p>
<p>One ISO can therefore boot multiple Linux versions and even host-specific kickstart files (which are always kept to the most bare bones they can be - handing off to a configuration management tool like Ansible or Puppet in the %post section to let it handle what it does best).</p>
<p>Here&rsquo;s an example file that is rolled into the ipxe.iso build with <code>make EMBED=menu.ipxe bin/ipxe.iso</code></p>
<div class="overflow-hidden rounded-sm shadow-lg">
  
  <div class="flex items-center gap-2 bg-gray-200 px-4 py-2 dark:bg-gray-700">
    <div class="size-3 rounded-full bg-red-500"></div>
    <div class="size-3 rounded-full bg-yellow-500"></div>
    <div class="size-3 rounded-full bg-green-500"></div>
  </div>
  
  <div class="bg-white px-8 py-2 dark:bg-gray-900">
    <pre
      class="overflow-x-auto whitespace-pre-wrap break-words"
    ><code>host:src$ cat menu.ipxe
 #!ipxe
 dhcp net0
 chain http://192.168.1.1:3000/pxe/${net0/mac}</code></pre>
  </div>
</div>
<p>And an example of the output from the CGI:</p>
<div class="overflow-hidden rounded-sm shadow-lg">
  
  <div class="flex items-center gap-2 bg-gray-200 px-4 py-2 dark:bg-gray-700">
    <div class="size-3 rounded-full bg-red-500"></div>
    <div class="size-3 rounded-full bg-yellow-500"></div>
    <div class="size-3 rounded-full bg-green-500"></div>
  </div>
  
  <div class="bg-white px-8 py-2 dark:bg-gray-900">
    <pre
      class="overflow-x-auto whitespace-pre-wrap break-words"
    ><code>MacBook-Pro:~$ curl -s http://192.168.1.1:3000/pxe/08:00:27:59:86:69
#!ipxe
kernel -n img http://build/centos/6.4/os/x86_64pxeboot/vmlinuz ks=http://192.168.1.1:3000/ks kssendmac
initrd http://build/centos/6.4/os/x86_64pxeboot/initrd.img
boot img</code></pre>
  </div>
</div>
<p>The pretty rough CGI I use is written in <a href="https://mojolicious.org">Perl Mojolicious</a>, and can be found <a href="https://github.com/phips/bacio">on Github</a>.</p>]]>
      
      <![CDATA[<hr><p>Thanks for reading this post via RSS! 👏</p>]]>
      <![CDATA[<a href="mailto:rs511@probably.co.uk?subject=Using iPXE with a URL to kickstart Linux">Reply to this post by email</a>]]>
      </description>
    </item>
    <item>
      <title>Perl LWP handshake failure error</title>
      <link>https://probably.co.uk/posts/perl-lwp-error14094410ssl-routinesssl3_read_bytessslv3-alert-handshake-failure/</link>
      <pubDate>Thu, 22 Nov 2012 00:00:00 +0000</pubDate>
      <guid>https://probably.co.uk/posts/perl-lwp-error14094410ssl-routinesssl3_read_bytessslv3-alert-handshake-failure/</guid>
      <description>
      
      <![CDATA[<p>I had this error the other day:
<code>Perl LWP 'error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure'</code></p>
<p>Lots and lots of solutions for this one out there in Google land, but it turned
out to be quite simple.</p>
<p>This is using Perl 5.14.3 on Linux, with LWP 6.04 using IO::Socket::SSL 1.77</p>
<p>I&rsquo;d set the client up like so:</p>
<div class="overflow-hidden rounded-sm shadow-lg">
  
  <div class="flex items-center gap-2 bg-gray-200 px-4 py-2 dark:bg-gray-700">
    <div class="size-3 rounded-full bg-red-500"></div>
    <div class="size-3 rounded-full bg-yellow-500"></div>
    <div class="size-3 rounded-full bg-green-500"></div>
  </div>
  
  <div class="bg-white px-8 py-2 dark:bg-gray-900">
    <pre
      class="overflow-x-auto whitespace-pre-wrap break-words"
    ><code>my $ua = LWP::UserAgent-&gt;new;
$ua-&gt;ssl_opts(
    SSL_ca_file =&gt; &#34;$ENV{&#39;HOME&#39;}/ca.pem&#34;,
    SSL_cert_file =&gt; &#34;$ENV{&#39;HOME&#39;}/my.crt&#34;,
    verify_hostname =&gt; 1,
);</code></pre>
  </div>
</div>
<p>&hellip;my crt file is a combined certificate and key.</p>
<p>The solution turned out to be simply a case of including the key statement,
pointing at the same file:</p>
<div class="overflow-hidden rounded-sm shadow-lg">
  
  <div class="flex items-center gap-2 bg-gray-200 px-4 py-2 dark:bg-gray-700">
    <div class="size-3 rounded-full bg-red-500"></div>
    <div class="size-3 rounded-full bg-yellow-500"></div>
    <div class="size-3 rounded-full bg-green-500"></div>
  </div>
  
  <div class="bg-white px-8 py-2 dark:bg-gray-900">
    <pre
      class="overflow-x-auto whitespace-pre-wrap break-words"
    ><code>$ua-&gt;ssl_opts(
    SSL_use_cert =&gt; 1,
    SSL_ca_file =&gt; &#34;$ENV{&#39;HOME&#39;}/ca.pem&#34;,
    SSL_cert_file =&gt; &#34;$ENV{&#39;HOME&#39;}/my.crt&#34;,
    SSL_key_file =&gt; &#34;$ENV{&#39;HOME&#39;}/my.crt&#34;,
    verify_hostname =&gt; 1,
);</code></pre>
  </div>
</div>
]]>
      
      <![CDATA[<hr><p>Thanks for reading this post via RSS! 👏</p>]]>
      <![CDATA[<a href="mailto:rs511@probably.co.uk?subject=Perl LWP handshake failure error">Reply to this post by email</a>]]>
      </description>
    </item>
    <item>
      <title>The simplicity of Perl Mojolicious for web get extractions</title>
      <link>https://probably.co.uk/posts/the-simplicity-of-perl-mojolicious-for-web-get-extractions/</link>
      <pubDate>Thu, 04 Oct 2012 00:00:00 +0000</pubDate>
      <guid>https://probably.co.uk/posts/the-simplicity-of-perl-mojolicious-for-web-get-extractions/</guid>
      <description>
      
      <![CDATA[<p>I&rsquo;ve been using <a href="https://mojolicious.org/">Mojolicious</a> quite a bit this year,
and I love it.</p>
<p>Recently I completed a project for a client using
<a href="https://metacpan.org/pod/Mojo::UserAgent">Mojo::UserAgent</a> as a
server to write a simple monitoring dashboard. But this week I&rsquo;ve been using
the command line &lsquo;mojo&rsquo; tool to grab some stock prices from the web. And it&rsquo;s
brilliant how simple it is.</p>
<p>Here&rsquo;s how to grab AAPL from Google Finance, outputting the current price:</p>
<div class="overflow-hidden rounded-sm shadow-lg">
  
  <div class="flex items-center gap-2 bg-gray-200 px-4 py-2 dark:bg-gray-700">
    <div class="size-3 rounded-full bg-red-500"></div>
    <div class="size-3 rounded-full bg-yellow-500"></div>
    <div class="size-3 rounded-full bg-green-500"></div>
  </div>
  
  <div class="bg-white px-8 py-2 dark:bg-gray-900">
    <pre
      class="overflow-x-auto whitespace-pre-wrap break-words"
    ><code>mojo get https://www.google.com/finance/quote/SPY:NYSEARCA &#34;.fxKbKc&#34; text</code></pre>
  </div>
</div>
<p>Working out the CSS selectors is simply a case of looking at the web page in your browser using the debug tools to look through the source. I&rsquo;ve also found <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors">this resource on CSS selectors</a> handy, as I don&rsquo;t do this every day I&rsquo;m prone to forgetting the syntax.</p>
<hr>
<p>Nearly 11 years later, in 2023, I discovered <a href="https://github.com/sibprogrammer/xq">xq</a> 🤣 You know what&rsquo;s even simpler than mojo? This:</p>
<div class="overflow-hidden rounded-sm shadow-lg">
  
  <div class="flex items-center gap-2 bg-gray-200 px-4 py-2 dark:bg-gray-700">
    <div class="size-3 rounded-full bg-red-500"></div>
    <div class="size-3 rounded-full bg-yellow-500"></div>
    <div class="size-3 rounded-full bg-green-500"></div>
  </div>
  
  <div class="bg-white px-8 py-2 dark:bg-gray-900">
    <pre
      class="overflow-x-auto whitespace-pre-wrap break-words"
    ><code>curl -L https://www.google.com/finance/quote/SPY:NYSEARCA | xq -q &#34;.fxKbKc&#34;</code></pre>
  </div>
</div>]]>
      
      <![CDATA[<hr><p>Thanks for reading this post via RSS! 👏</p>]]>
      <![CDATA[<a href="mailto:rs511@probably.co.uk?subject=The simplicity of Perl Mojolicious for web get extractions">Reply to this post by email</a>]]>
      </description>
    </item>
    <item>
      <title>VMware Perl SDK error &#39;Server version unavailable..&#39;</title>
      <link>https://probably.co.uk/posts/vmware-perl-sdk-error-server-version-unavailable/</link>
      <pubDate>Thu, 17 Nov 2011 00:00:00 +0000</pubDate>
      <guid>https://probably.co.uk/posts/vmware-perl-sdk-error-server-version-unavailable/</guid>
      <description>
      
      <![CDATA[<p>Whilst working with the VMware Perl SDK this morning I came across this error:</p>
<div class="overflow-hidden rounded-sm shadow-lg">
  
  <div class="flex items-center gap-2 bg-gray-200 px-4 py-2 dark:bg-gray-700">
    <div class="size-3 rounded-full bg-red-500"></div>
    <div class="size-3 rounded-full bg-yellow-500"></div>
    <div class="size-3 rounded-full bg-green-500"></div>
  </div>
  
  <div class="bg-white px-8 py-2 dark:bg-gray-900">
    <pre
      class="overflow-x-auto whitespace-pre-wrap break-words"
    ><code>Server version unavailable at &#39;&lt;a href=&#34;https://hostname/sdk/vimService.wsdl&#34;&gt;https://hostname:443/sdk/vimService.wsdl&lt;/a&gt;&#39; at /usr/lib/perl5/5.8.8/VMware/VICommon.pm line 545.</code></pre>
  </div>
</div>
<p>Turns out it can&rsquo;t verify the server&rsquo;s SSL certificate.</p>
<p>export PERL_LWP_SSL_VERIFY_HOSTNAME=0 in your shell before using a command, and
it then works correctly.</p>]]>
      
      <![CDATA[<hr><p>Thanks for reading this post via RSS! 👏</p>]]>
      <![CDATA[<a href="mailto:rs511@probably.co.uk?subject=VMware Perl SDK error 'Server version unavailable..'">Reply to this post by email</a>]]>
      </description>
    </item>
    <item>
      <title>Problems installing DBD::mysql on OS X Snow Leopard</title>
      <link>https://probably.co.uk/posts/problems-installing-dbdmysql-on-os-x-snow-leopard/</link>
      <pubDate>Sun, 27 Feb 2011 00:00:00 +0000</pubDate>
      <guid>https://probably.co.uk/posts/problems-installing-dbdmysql-on-os-x-snow-leopard/</guid>
      <description>
      
      <![CDATA[<p>After a colleague showed me <a href="https://dev.mysql.com/downloads/workbench/5.2.html">MySQL Workbench</a> the other day I thought I&rsquo;d install the <a href="https://dev.mysql.com/downloads/mysql">packaged MySQL</a> on my Macbook, to do a bit of Catalyst developing.</p>
<p>When it comes to extra Perl modules, I always install everything in my home directory, using <a href="https://search.cpan.org/~apeiron/local-lib-1.008004/lib/local/lib.pm">local::lib</a> - it keeps everything neat and tidy and means I don&rsquo;t need to install anything under sudo.</p>
<p>However, I&rsquo;ve just been struggling to get DBD::mysql to work properly with the packaged MySQL. It would compile just fine, but then refused to load for testing, seemingly unable to find the libmysqlclient dynamic library:</p>
<div class="overflow-hidden rounded-sm shadow-lg">
  
  <div class="flex items-center gap-2 bg-gray-200 px-4 py-2 dark:bg-gray-700">
    <div class="size-3 rounded-full bg-red-500"></div>
    <div class="size-3 rounded-full bg-yellow-500"></div>
    <div class="size-3 rounded-full bg-green-500"></div>
  </div>
  
  <div class="bg-white px-8 py-2 dark:bg-gray-900">
    <pre
      class="overflow-x-auto whitespace-pre-wrap break-words"
    ><code>#   Failed test &#39;use DBD::mysql;&#39;
#   at t/00base.t line 21.
#     Tried to use &#39;DBD::mysql&#39;.
#     Error:  Can&#39;t load &#39;/Users/markp/.cpan/build/DBD-mysql-4.018-hYHpKY/blib/arch/auto/DBD/mysql/mysql.bundle&#39; for module DBD::mysql:
dlopen(/Users/markp/.cpan/build/DBD-mysql-4.018-hYHpKY/blib/arch/auto/DBD/mysql/mysql.bundle, 2): Library not loaded:
libmysqlclient.16.dylib</code></pre>
  </div>
</div>
<p>After a bit of Googling around, various resources led me to the fact the compiled binary was lacking an RPATH. So all I needed to do was link the binary with an RPATH. But it seems things are not as simple on OS X.</p>
<p>According to <a href="https://web.archive.org/web/20130623025151/https://blogs.oracle.com/dipol/entry/dynamic_libraries_rpath_and_mac">Joe Di Pol&rsquo;s blog</a>, OS X works slightly backwards to what most of us from Linux and Solaris backgrounds understand - compiled binaries look at a dynamic library, which in turns says where it is, rather than the traditional way of thinking which is to include a library search path in the compiled binary.</p>
<p>To see what I mean, look at the mysqlclient dynamic library with otool:</p>
<div class="overflow-hidden rounded-sm shadow-lg">
  
  <div class="flex items-center gap-2 bg-gray-200 px-4 py-2 dark:bg-gray-700">
    <div class="size-3 rounded-full bg-red-500"></div>
    <div class="size-3 rounded-full bg-yellow-500"></div>
    <div class="size-3 rounded-full bg-green-500"></div>
  </div>
  
  <div class="bg-white px-8 py-2 dark:bg-gray-900">
    <pre
      class="overflow-x-auto whitespace-pre-wrap break-words"
    ><code>DBD-mysql-4.018-hYHpKY$ otool -D `mdfind libmysqlclient.16.dylib`
/usr/local/mysql-5.5.9-osx10.6-x86_64/lib/libmysqlclient.16.dylib: libmysqlclient.16.dylib</code></pre>
  </div>
</div>
<p>There is no path listed there, which means binaries compiled to use the library won&rsquo;t be able to find it unless it&rsquo;s in the system search path of /usr/lib.</p>
<p>We can fix this with install_name_tool though:</p>
<div class="overflow-hidden rounded-sm shadow-lg">
  
  <div class="flex items-center gap-2 bg-gray-200 px-4 py-2 dark:bg-gray-700">
    <div class="size-3 rounded-full bg-red-500"></div>
    <div class="size-3 rounded-full bg-yellow-500"></div>
    <div class="size-3 rounded-full bg-green-500"></div>
  </div>
  
  <div class="bg-white px-8 py-2 dark:bg-gray-900">
    <pre
      class="overflow-x-auto whitespace-pre-wrap break-words"
    ><code>DBD-mysql-4.018-hYHpKY$ sudo install_name_tool -id /usr/local/mysql-5.5.9-osx10.6-x86_64/lib/libmysqlclient.16.dylib
/usr/local/mysql-5.5.9-osx10.6-x86_64/lib/libmysqlclient.16.dylib

DBD-mysql-4.018-hYHpKY$ otool -D `mdfind libmysqlclient.16.dylib`
/usr/local/mysql-5.5.9-osx10.6-x86_64/lib/libmysqlclient.16.dylib:
/usr/local/mysql-5.5.9-osx10.6-x86_64/lib/libmysqlclient.16.dylib</code></pre>
  </div>
</div>
<p>Now when we run the tests:</p>
<div class="overflow-hidden rounded-sm shadow-lg">
  
  <div class="flex items-center gap-2 bg-gray-200 px-4 py-2 dark:bg-gray-700">
    <div class="size-3 rounded-full bg-red-500"></div>
    <div class="size-3 rounded-full bg-yellow-500"></div>
    <div class="size-3 rounded-full bg-green-500"></div>
  </div>
  
  <div class="bg-white px-8 py-2 dark:bg-gray-900">
    <pre
      class="overflow-x-auto whitespace-pre-wrap break-words"
    ><code>DBD-mysql-4.018-hYHpKY$ make testPERL_DL_NONLAZY=1 /usr/bin/perl &#34;-MExtUtils::Command::MM&#34; &#34;-e&#34; &#34;test_harness(0, &#39;blib/lib&#39;, &#39;blib/arch&#39;)&#34;
t/*.t
t/00base.t .................. ok
t/10connect.t ............... ok</code></pre>
  </div>
</div>
<p>It works!</p>
<p>There may be a better way to do this, and if I find it I&rsquo;ll update this post. Otherwise, that works just fine for me.</p>]]>
      
      <![CDATA[<hr><p>Thanks for reading this post via RSS! 👏</p>]]>
      <![CDATA[<a href="mailto:rs511@probably.co.uk?subject=Problems installing DBD::mysql on OS X Snow Leopard">Reply to this post by email</a>]]>
      </description>
    </item>
    <item>
      <title>Patching a live Solaris 10 system with LU, ZFS, and PCA</title>
      <link>https://probably.co.uk/posts/patching-a-live-solaris-10-system-with-lu-zfs-and-pca/</link>
      <pubDate>Wed, 03 Mar 2010 00:00:00 +0000</pubDate>
      <guid>https://probably.co.uk/posts/patching-a-live-solaris-10-system-with-lu-zfs-and-pca/</guid>
      <description>
      
      <![CDATA[<p>Sun have done some work in recent times with liveupgrade - the last time I
looked at it, a few years back now, it was inadequate. I thought it was about time
I took another look, since a lot of the updates in OpenSolaris were looking
good.</p>
<p>The idea was to patch a Solaris 10 update 8 (10/09) machine to the most recent
patch levels, whilst the machine was still up and running, going about its
daily business. Other than the standard Solaris tools, I&rsquo;d be using pca <a href="https://www.par.univie.ac.at/solaris/pca/">Patch
Check Advanced</a> to do the actual
patching. The system was installed with a ZFS root, since this actually gets us
some great features in LiveUpgrade (LU) - namely ZFS snapshots as boot
environments (BEs).</p>
<p>First off, create a BE that will be patched:</p>
<div class="overflow-hidden rounded-sm shadow-lg">
  
  <div class="flex items-center gap-2 bg-gray-200 px-4 py-2 dark:bg-gray-700">
    <div class="size-3 rounded-full bg-red-500"></div>
    <div class="size-3 rounded-full bg-yellow-500"></div>
    <div class="size-3 rounded-full bg-green-500"></div>
  </div>
  
  <div class="bg-white px-8 py-2 dark:bg-gray-900">
    <pre
      class="overflow-x-auto whitespace-pre-wrap break-words"
    ><code>solaris:~# lucreate -n patching
Checking GRUB menu...
System has findroot enabled GRUB
Analyzing system configuration.
Comparing source boot environment file systems with the file
system(s) you specified for the new boot environment. Determining which
file systems should be in the new boot environment.
Updating boot environment description database on all BEs.
Updating system configuration files.
Creating configuration for boot environment .
Source boot environment is .
Creating boot environment .
Cloning file systems from boot environment to create boot environment .
Creating snapshot for on .
Creating clone for on .
Setting canmount=noauto for in zone on .
mount point options &amp;lt;-&amp;gt; from parent filesystem file
type &amp;lt;-&amp;gt; because the two file systems have different types.
Saving existing file in top level dataset for BE as //boot/grub/menu.lst.prev.
File propagation successful
Copied GRUB menu from PBE to ABE
No entry for BE in GRUB menu
Population of boot environment successful.
Creation of boot environment successful.</code></pre>
  </div>
</div>
<p>If we now take a look at the ZFS filesystems we can see the &lsquo;patching&rsquo; snapshot…</p>
<div class="overflow-hidden rounded-sm shadow-lg">
  
  <div class="flex items-center gap-2 bg-gray-200 px-4 py-2 dark:bg-gray-700">
    <div class="size-3 rounded-full bg-red-500"></div>
    <div class="size-3 rounded-full bg-yellow-500"></div>
    <div class="size-3 rounded-full bg-green-500"></div>
  </div>
  
  <div class="bg-white px-8 py-2 dark:bg-gray-900">
    <pre
      class="overflow-x-auto whitespace-pre-wrap break-words"
    ><code>NAME USED AVAIL REFER MOUNTPOINT
rpool 2.08G 5.73G 33K /rpool
rpool/ROOT 1.03G 5.73G 21K legacy
rpool/ROOT/install 1.03G 5.73G 1.03G /
rpool/ROOT/install@patching 59.5K - 1.03G -
rpool/ROOT/patching 120K 5.73G 1.03G /
rpool/dump 560M 5.73G 560M -
rpool/export 44K 5.73G 23K /export
rpool/export/home 21K 5.73G 21K /export/home
rpool/swap 512M 6.14G 100M -```
Let&#39;s see what lustatus shows us now...
```solaris:~# lustatus
Boot Environment Is Active Active Can Copy
Name Complete Now On Reboot Delete Status
-------------------------- -------- ------ --------- ------ ----------
install yes yes yes no -
patching yes no no yes -</code></pre>
  </div>
</div>
<p>So we have two boot environments.</p>
<p>LU has a nice feature of letting you mount a BE to do &lsquo;work&rsquo; on it. Let&rsquo;s see what&rsquo;s mounted, and then mount our newly created &lsquo;patching&rsquo; BE…</p>
<div class="overflow-hidden rounded-sm shadow-lg">
  
  <div class="flex items-center gap-2 bg-gray-200 px-4 py-2 dark:bg-gray-700">
    <div class="size-3 rounded-full bg-red-500"></div>
    <div class="size-3 rounded-full bg-yellow-500"></div>
    <div class="size-3 rounded-full bg-green-500"></div>
  </div>
  
  <div class="bg-white px-8 py-2 dark:bg-gray-900">
    <pre
      class="overflow-x-auto whitespace-pre-wrap break-words"
    ><code>install on /
solaris:~# lumount patching
/.alt.patching
solaris:~# lumount
install on /
patching on /.alt.patching</code></pre>
  </div>
</div>
<p>So now our alternate boot environment is mounted as /.alt.patching, we can go ahead and patch it. pca supports patching to an alternative root with the -R switch, much like Solaris packaging tools…</p>
<div class="overflow-hidden rounded-sm shadow-lg">
  
  <div class="flex items-center gap-2 bg-gray-200 px-4 py-2 dark:bg-gray-700">
    <div class="size-3 rounded-full bg-red-500"></div>
    <div class="size-3 rounded-full bg-yellow-500"></div>
    <div class="size-3 rounded-full bg-green-500"></div>
  </div>
  
  <div class="bg-white px-8 py-2 dark:bg-gray-900">
    <pre
      class="overflow-x-auto whitespace-pre-wrap break-words"
    ><code>solaris:~# pca -i -R /.alt.patching
[snip]
------------------------------------------------------------------------------
141505 04 &amp;lt; 07 RS- 28 SunOS 5.10_x86: ipf patch
Looking for 141505-07 (29/84)
Trying SunSolve
Trying https://sunsolve.sun.com/ (1/1)
Done
Installing 141505-07 (29/84)
Unzipping patch
Running patchadd
Done
Reboot recommended
------------------------------------------------------------------------------
[snip]
------------------------------------------------------------------------------
Download Summary: 84 total, 84 successful, 0 skipped, 0 failed
Install Summary : 84 total, 84 successful, 0 skipped, 0 failed</code></pre>
  </div>
</div>
<p>This could take a while.</p>
<p>When the patching is complete, unmount the BE and set it to be the active one
on the next reboot…</p>
<div class="overflow-hidden rounded-sm shadow-lg">
  
  <div class="flex items-center gap-2 bg-gray-200 px-4 py-2 dark:bg-gray-700">
    <div class="size-3 rounded-full bg-red-500"></div>
    <div class="size-3 rounded-full bg-yellow-500"></div>
    <div class="size-3 rounded-full bg-green-500"></div>
  </div>
  
  <div class="bg-white px-8 py-2 dark:bg-gray-900">
    <pre
      class="overflow-x-auto whitespace-pre-wrap break-words"
    ><code>solaris:~# luumount patching
solaris:~# lumount
install on /
solaris:~# luactivate patching
System has findroot enabled GRUB
Generating boot-sign, partition and slice information for PBE
Saving existing file in top level dataset for BE as //etc/bootsign.prev.
A Live Upgrade Sync operation will be performed on startup of boot environment.
Generating boot-sign for ABE Saving existing file in top level dataset for BE as //etc/bootsign.prev.
Generating partition and slice information for ABE Copied boot menu from top level dataset.
Generating multiboot menu entries for PBE.
Generating multiboot menu entries for ABE.
Disabling splashimage
Re-enabling splashimage
No more bootadm entries. Deletion of bootadm entries is complete.
GRUB menu default setting is unaffected
Done eliding bootadm entries.
**********************************************************************
The target boot environment has been activated. It will be used when you
reboot. NOTE: You MUST NOT USE the reboot, halt, or uadmin commands. You
MUST USE either the init or the shutdown command when you reboot. If you
do not use either init or shutdown, the system will not boot using the
target BE.
**********************************************************************
In case of a failure while booting to the target BE, the following process
needs to be followed to fallback to the currently working boot environment:
1. Boot from Solaris failsafe or boot in single user mode from the Solaris
Install CD or Network.
2. Mount the Parent boot environment root slice to some directory (like /mnt). You can use the following command to mount:
mount -Fzfs /dev/dsk/c0d0s0 /mnt
3. Run utility with out any arguments from the Parent boot
environment root slice, as shown below:
/mnt/sbin/luactivate
4. luactivate, activates the previous working boot environment and
indicates the result.
5. Exit Single User mode and reboot the machine.
**********************************************************************
Modifying boot archive service
Propagating findroot GRUB for menu conversion.
File propagation successful
File propagation successful
File propagation successful
File propagation successful
Deleting stale GRUB loader from all BEs.
File deletion successful
File deletion successful
File deletion successful
Activation of boot environment successful. </code></pre>
  </div>
</div>
<p>Notice the message about what to do to recover the old session should the boot fail. Personally I keep a copy of that notice to hand, just in case.</p>
<p>So if we now look at lustatus, we can see our patching BE is the active on reboot…</p>
<div class="overflow-hidden rounded-sm shadow-lg">
  
  <div class="flex items-center gap-2 bg-gray-200 px-4 py-2 dark:bg-gray-700">
    <div class="size-3 rounded-full bg-red-500"></div>
    <div class="size-3 rounded-full bg-yellow-500"></div>
    <div class="size-3 rounded-full bg-green-500"></div>
  </div>
  
  <div class="bg-white px-8 py-2 dark:bg-gray-900">
    <pre
      class="overflow-x-auto whitespace-pre-wrap break-words"
    ><code>solaris:~# lustatus
Boot Environment Is Active Active Can Copy
Name Complete Now On Reboot Delete Status
-------------------------- -------- ------ --------- ------ ----------
install yes yes no no -
patching yes no yes no -</code></pre>
  </div>
</div>
<p>So let&rsquo;s go ahead and reboot at a time that suits us. When the system comes
back up we can see &lsquo;patching&rsquo; is now the active BE…</p>
<div class="overflow-hidden rounded-sm shadow-lg">
  
  <div class="flex items-center gap-2 bg-gray-200 px-4 py-2 dark:bg-gray-700">
    <div class="size-3 rounded-full bg-red-500"></div>
    <div class="size-3 rounded-full bg-yellow-500"></div>
    <div class="size-3 rounded-full bg-green-500"></div>
  </div>
  
  <div class="bg-white px-8 py-2 dark:bg-gray-900">
    <pre
      class="overflow-x-auto whitespace-pre-wrap break-words"
    ><code>solaris:~# lustatus
Boot Environment Is Active Active Can Copy
Name Complete Now On Reboot Delete Status
-------------------------- -------- ------ --------- ------ ----------
install yes no no yes -
patching yes yes yes no -</code></pre>
  </div>
</div>
<p>And pca shows us there are no patches to be applied, so we&rsquo;re up to date…</p>
<div class="overflow-hidden rounded-sm shadow-lg">
  
  <div class="flex items-center gap-2 bg-gray-200 px-4 py-2 dark:bg-gray-700">
    <div class="size-3 rounded-full bg-red-500"></div>
    <div class="size-3 rounded-full bg-yellow-500"></div>
    <div class="size-3 rounded-full bg-green-500"></div>
  </div>
  
  <div class="bg-white px-8 py-2 dark:bg-gray-900">
    <pre
      class="overflow-x-auto whitespace-pre-wrap break-words"
    ><code>Using /var/tmp/patchdiag.xref from Mar/02/10</code></pre>
  </div>
</div>
<p>zfs list shows us that the patching snapshot is now using up space too…</p>
<div class="overflow-hidden rounded-sm shadow-lg">
  
  <div class="flex items-center gap-2 bg-gray-200 px-4 py-2 dark:bg-gray-700">
    <div class="size-3 rounded-full bg-red-500"></div>
    <div class="size-3 rounded-full bg-yellow-500"></div>
    <div class="size-3 rounded-full bg-green-500"></div>
  </div>
  
  <div class="bg-white px-8 py-2 dark:bg-gray-900">
    <pre
      class="overflow-x-auto whitespace-pre-wrap break-words"
    ><code>solaris:~# zfs list
NAME USED AVAIL REFER MOUNTPOINT
rpool 2.82G 5.00G 36.5K /rpool
rpool/ROOT 1.77G 5.00G 21K legacy
rpool/ROOT/install 31.3M 5.00G 1.05G /
rpool/ROOT/patching 1.74G 5.00G 1.37G /
rpool/ROOT/patching@patching 377M - 1.03G -
rpool/dump 560M 5.00G 560M -
rpool/export 44K 5.00G 23K /export
rpool/export/home 21K 5.00G 21K /export/home
rpool/swap 512M 5.40G 100M -</code></pre>
  </div>
</div>
<p>Using a recent Solaris 10, with ZFS root, LU and pca gives us a very realistic
way of patching systems in a working, production, environment without the pain
of downtime and with a workable roll back strategy.</p>]]>
      
      <![CDATA[<hr><p>Thanks for reading this post via RSS! 👏</p>]]>
      <![CDATA[<a href="mailto:rs511@probably.co.uk?subject=Patching a live Solaris 10 system with LU, ZFS, and PCA">Reply to this post by email</a>]]>
      </description>
    </item>
    <item>
      <title>Stuck as &#39;scheduled&#39; Wordpress posts</title>
      <link>https://probably.co.uk/posts/stuck-as-scheduled-wordpress-posts/</link>
      <pubDate>Fri, 14 Aug 2009 00:00:00 +0000</pubDate>
      <guid>https://probably.co.uk/posts/stuck-as-scheduled-wordpress-posts/</guid>
      <description>
      
      <![CDATA[<p>I recently edited a post on a Wordpress blog and discovered that trying to
change the publish time (to bring an old post up to the top of the list)
created a temporary world of pain.</p>
<p>If the scheduled time is missed there is no way to change the post to &lsquo;publish
immediately&rsquo; from scheduled. This leaves the post as scheduled, and won&rsquo;t
actually re-post it no matter what you do (including setting a future time).</p>
<p>A quick fix is to update the post directly in the database.</p>
<p>Find the post you want (make sure it&rsquo;s the parent post, anything with a
post_status of &lsquo;inherit&rsquo; is a &lsquo;child&rsquo; post, or update to the original, you want
the first post of its kind with a post_status of &lsquo;future&rsquo;) by selecting on the
post_title, and once you&rsquo;ve got the ID of the post, simply set the post_status
to &lsquo;publish&rsquo; and it will appear at the time you originally set it to be
scheduled for. For example&hellip;</p>
<p><code>update wp_posts set post_status='publish' where ID='8';</code></p>]]>
      
      <![CDATA[<hr><p>Thanks for reading this post via RSS! 👏</p>]]>
      <![CDATA[<a href="mailto:rs511@probably.co.uk?subject=Stuck as 'scheduled' Wordpress posts">Reply to this post by email</a>]]>
      </description>
    </item>
    <item>
      <title>rm -rf on Solaris ZFS filesystem doesn&#39;t remove directories</title>
      <link>https://probably.co.uk/posts/rm-rf-on-solaris-zfs-filesystem-doesnt-remove-directories/</link>
      <pubDate>Fri, 24 Apr 2009 00:00:00 +0000</pubDate>
      <guid>https://probably.co.uk/posts/rm-rf-on-solaris-zfs-filesystem-doesnt-remove-directories/</guid>
      <description>
      
      <![CDATA[<p>This is one of the weirdest problems I&rsquo;ve had for a while. On one of the
servers I look after, my home directory was a zfs filesystem set to /home/user.
If I ever did an rm -rf on a directory structure underneath my home dir, it
would remove all the files but leave all directories in place. The only way to
get rid of the directories was to recursively remove each one. Painful.</p>
<p>Today I discovered a fix - although I don&rsquo;t know the reason why.</p>
<p>I had a fairly restrictive umask set, system wide, in /etc/profile - 027. When
I did &lsquo;zfs set mountpoint=blah&rsquo; with that umask I wouldn&rsquo;t be able to rm -rf
successfully. However, if I moved the mountpoint, set umask to 022, then put it
back where it should be, rm -rf works fine!</p>
<p>The underlying directory was left when I temporarily shifted the home
directory, and it was owned root:root and 750, as the umask would suggest, but
why that would then effect the ZFS mount on top of it (which was correctly
owned by my own user ID) I do not know.</p>
<p>Anyone know why this would have been?</p>]]>
      
      <![CDATA[<hr><p>Thanks for reading this post via RSS! 👏</p>]]>
      <![CDATA[<a href="mailto:rs511@probably.co.uk?subject=rm -rf on Solaris ZFS filesystem doesn't remove directories">Reply to this post by email</a>]]>
      </description>
    </item>
  </channel>
</rss>
