<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>lost in the bewilderness</title><link>https://bewilderness.blog/</link><description>Modern life is eating its own children. Attend, consume and conform.</description><language>en-gb</language><generator>Hugo</generator><lastBuildDate>Sat, 25 Apr 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://bewilderness.blog/index.xml" rel="self" type="application/rss+xml"/><item><title>blog mechanics</title><link>https://bewilderness.blog/posts/blog-mechanics/</link><pubDate>Sat, 25 Apr 2026 00:00:00 +0000</pubDate><guid isPermaLink="true">https://bewilderness.blog/posts/blog-mechanics/</guid><description>This site is written using a simple offline stack: Hugo as a static site generator and Ansible as a deployment mechanism taking care of syncing things to my VPS.
I used Claude to carry out some of the initial scaffolding and busywork to get things up and running quickly, with a clear brief on what I wanted the workflow to look like.
the basic workflow For writing articles, I exclusively use Neovim running with my personal combination of plugins and scripts. It&amp;rsquo;s my day-to-day editor for most things because of its extensibility and speed. All articles are written in Markdown as you might expect these days.</description><content:encoded><![CDATA[<p>This site is written using a simple offline stack: <a href="https://gohugo.io/" target="_blank" rel="noopener noreferrer">Hugo</a> as a static site
generator and <a href="https://www.ansible.com/" target="_blank" rel="noopener noreferrer">Ansible</a> as a deployment mechanism taking care of syncing
things to my VPS.</p>
<p>I used <a href="https://claude.ai/" target="_blank" rel="noopener noreferrer">Claude</a> to carry out some of the initial scaffolding and busywork to get
things up and running quickly, with a clear brief on what I wanted the workflow to look like.</p>
<h2 id="the-basic-workflow">the basic workflow</h2>
<p>For writing articles, I exclusively use <a href="https://neovim.io" target="_blank" rel="noopener noreferrer">Neovim</a> running with my personal
combination of plugins and scripts. It&rsquo;s my day-to-day editor for most things because of its
extensibility and speed. All articles are written in Markdown as you might expect these days.</p>
<p>To preview and refine articles locally prior to publishing, I use a
<a href="https://docs.docker.com/compose" target="_blank" rel="noopener noreferrer">Docker Compose</a> setup which allows me to run a Hugo
instance, mounted on my local copy of the blog repository root.</p>
<p>The <code>docker-compose.yml</code> looks like this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#f92672">services</span>:
</span></span><span style="display:flex;"><span>  <span style="color:#75715e"># Dev: hugo&#39;s built-in server with hot reload. Edit content/, layouts/, static/ —</span>
</span></span><span style="display:flex;"><span>  <span style="color:#75715e"># the browser refreshes automatically. No Caddy involved in dev.</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">blog</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">image</span>: <span style="color:#ae81ff">hugomods/hugo:latest</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">container_name</span>: <span style="color:#ae81ff">blog-hugo-dev</span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># Run as the host user/group so any cache or generated-resource files</span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># Hugo writes to the bind-mounted repo are owned by the host user, not</span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># root. Without this, prod deploy fails when Hugo&#39;s --cleanDestinationDir</span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># can&#39;t remove root-owned leftovers in public/.</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">user</span>: <span style="color:#e6db74">&#34;${UID:-1000}:${GID:-1000}&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">working_dir</span>: <span style="color:#ae81ff">/src</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">command</span>:
</span></span><span style="display:flex;"><span>      <span style="color:#ae81ff">hugo server --bind 0.0.0.0 --port 80 --baseURL http://localhost:18080/ --appendPort=false</span>
</span></span><span style="display:flex;"><span>      --<span style="color:#ae81ff">disableFastRender</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">ports</span>:
</span></span><span style="display:flex;"><span>      - <span style="color:#e6db74">&#34;18080:80&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">volumes</span>:
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">.:/src</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">restart</span>: <span style="color:#ae81ff">unless-stopped</span>
</span></span></code></pre></div><p>Running the blog locally is just this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>docker compose up
</span></span></code></pre></div><p>Once I&rsquo;m happy with a new post — or a tweak to the site structure — I publish by running an Ansible
playbook that builds the site locally and rsyncs the result to my VPS.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>ansible-playbook deploy.yml
</span></span></code></pre></div><p>The <code>deploy.yml</code> used for publication looks like this:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span>- <span style="color:#f92672">name</span>: <span style="color:#ae81ff">Deploy blog</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">hosts</span>: <span style="color:#ae81ff">blog</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">gather_facts</span>: <span style="color:#66d9ef">false</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">collections</span>:
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">ansible.posix</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">vars</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">repo_root</span>: <span style="color:#e6db74">&#34;{{ playbook_dir | dirname }}&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">tasks</span>:
</span></span><span style="display:flex;"><span>    - <span style="color:#f92672">name</span>: <span style="color:#ae81ff">Build Hugo site locally (Docker one-shot)</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">ansible.builtin.command</span>:
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">cmd</span>: &gt;-<span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">          docker run --rm -v {{ repo_root }}:/src -w /src --user {{ lookup(&#39;pipe&#39;, &#39;id -u&#39;) }}:{{
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">          lookup(&#39;pipe&#39;, &#39;id -g&#39;) }} hugomods/hugo:latest hugo --minify --cleanDestinationDir</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">delegate_to</span>: <span style="color:#ae81ff">localhost</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">run_once</span>: <span style="color:#66d9ef">true</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">changed_when</span>: <span style="color:#66d9ef">true</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">tags</span>: [<span style="color:#ae81ff">build]</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    - <span style="color:#f92672">name</span>: <span style="color:#ae81ff">Sync rendered site to host</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">ansible.posix.synchronize</span>:
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">src</span>: <span style="color:#e6db74">&#34;{{ repo_root }}/public/&#34;</span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">dest</span>: <span style="color:#e6db74">&#34;{{ web_root }}/&#34;</span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">delete</span>: <span style="color:#66d9ef">true</span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">recursive</span>: <span style="color:#66d9ef">true</span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">rsync_opts</span>:
</span></span><span style="display:flex;"><span>          - <span style="color:#e6db74">&#34;--omit-dir-times&#34;</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">become</span>: <span style="color:#66d9ef">true</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">tags</span>: [<span style="color:#ae81ff">sync]</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    - <span style="color:#f92672">name</span>: <span style="color:#ae81ff">Re-apply SELinux file contexts on web root</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">ansible.builtin.command</span>:
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">cmd</span>: <span style="color:#e6db74">&#34;restorecon -R {{ web_root }}&#34;</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">become</span>: <span style="color:#66d9ef">true</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">register</span>: <span style="color:#ae81ff">restorecon_result</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">changed_when</span>: <span style="color:#ae81ff">restorecon_result.stdout | length &gt; 0</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">tags</span>: [<span style="color:#ae81ff">sync]</span>
</span></span></code></pre></div><p>In addition to the <code>deploy.yml</code> playbook, I also have a playbook for <em>provisioning</em> all the
pre-requisites on a given VPS, with the assumption that the VPS is running a Fedora/DNF based
distribution.</p>
<p>This means moving between VPS providers is trivial - stand up a fresh host, point Ansible at it,
done.</p>
<p>All authentication is carried out via SSH where the keys live on one of my personal
<a href="https://www.yubico.com" target="_blank" rel="noopener noreferrer">Yubikeys</a>.</p>
]]></content:encoded><category>technical</category><category>nerd juice</category></item></channel></rss>