<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<title>Posts</title>
	<subtitle>Systems Engineer | Astral Projection Enthusiast (CLI-variant)</subtitle>
	<link rel="self" type="application/atom+xml" href="https://devedge.github.io/posts/feed.xml"/>
  <link rel="alternate" type="text/html" href="https://devedge.github.io/posts/"/>
  
	<updated>2026-07-04T16:12:39+00:00</updated>
	
	<id>https://devedge.github.io/posts/feed.xml</id>
	<entry xml:lang="en">
		<title>Another year, another blog redesign</title>
		<published>2026-07-04T16:12:39+00:00</published>
		<updated>2026-07-04T16:12:39+00:00</updated>
		<link rel="alternate" type="text/html" href="https://devedge.github.io/posts/another-year-another-blog-redesign/"/>
		<id>https://devedge.github.io/posts/another-year-another-blog-redesign/</id>
    
		<content type="html" xml:base="https://devedge.github.io/posts/another-year-another-blog-redesign/">&lt;p&gt;After a lot of consideration, I&#x27;ve gone ahead and switched out both the backend and the theme of this site yet again. There were a number of ongoing issues, the most notable of which were:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;The monospace font for the &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;probberechts&#x2F;hexo-theme-cactus&quot;&gt;&lt;code&gt;Cactus&lt;&#x2F;code&gt; theme&lt;&#x2F;a&gt; was honestly hard to read. Additionally, the mobile layout had poor padding.&lt;&#x2F;li&gt;
&lt;li&gt;Configuration of the theme involved managing 2 different config files, which quickly became convoluted.&lt;&#x2F;li&gt;
&lt;li&gt;There was no auto-dark mode for &lt;code&gt;Cactus&lt;&#x2F;code&gt;, and I was not particularly interested in trying to design and configure one.&lt;&#x2F;li&gt;
&lt;li&gt;The theme was not self-contained, and was loading 5 different minified JS scripts through Cloudflare.&lt;&#x2F;li&gt;
&lt;li&gt;The &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;hexo.io&#x2F;&quot;&gt;&lt;code&gt;hexo&lt;&#x2F;code&gt; backend&lt;&#x2F;a&gt; was excessive for what was essentially a collection of static webpages. It required 10 NPM packages, installing nearly 60Mb of dependencies (the theme was another 12Mb).&lt;&#x2F;li&gt;
&lt;li&gt;To run &lt;code&gt;hexo&lt;&#x2F;code&gt;, I had to install a NodeJS runtime and a specific version of NPM, which I was doing with NVM (&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;nvm-sh&#x2F;nvm&quot;&gt;Node Version Manager&lt;&#x2F;a&gt;). Sourcing this in my &lt;code&gt;zshrc&lt;&#x2F;code&gt; was so bloated it was taking seconds to load my shell, which is a &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;superuser.com&#x2F;a&#x2F;1611283&quot;&gt;known problem&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Ultimately, my requirements are very basic: convert Markdown files into HTML &amp;amp; attach minimal CSS styling (and maybe some very minimal JS for page interactions). I could have put in a lot of time trying to address these items with the existing framework, but my skills in the graphic design department, especially webdev, is currently not my strongest suit. I knew I had gone too far when I started to learn Figma...&lt;&#x2F;p&gt;
&lt;p&gt;Luckily, there was an existing project made specifically for this use case!: &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;www.getzola.org&#x2F;&quot;&gt;Zola&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;This project hits all the points in my wishlist:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;A single, simple, small binary&lt;&#x2F;li&gt;
&lt;li&gt;Built-in, easy to use templating engine that can transpile Markdown into HTML&lt;&#x2F;li&gt;
&lt;li&gt;Can compile Sass into CSS&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;I also found a theme that looks much better on both mobile and on desktop: &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;isunjn&#x2F;serene&quot;&gt;Serene&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;It has an auto-dark mode theme that looks nice&lt;&#x2F;li&gt;
&lt;li&gt;Padding is significantly better&lt;&#x2F;li&gt;
&lt;li&gt;The font choice is much more readable&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;All in all, this framework and theme is much easier to configure, so I may actually tweak it further (unlike with the previous theme). The only negative impact of this change is that the URL slugs have changed, which will break previous links:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;date baked-in (&lt;code&gt;&#x2F;2026&#x2F;03&#x2F;14&#x2F;replacin...&lt;&#x2F;code&gt;) --&amp;gt; directly under &lt;code&gt;&#x2F;posts&#x2F;&lt;&#x2F;code&gt; (&lt;code&gt;&#x2F;posts&#x2F;replacin...&lt;&#x2F;code&gt;)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Given how minimal (and external dependency-free) this new theme is, I can also revisit hosting a copy of it on a Hidden site through Tor (or even I2P) which, although a fun project, was also annoyingly slow with the heavier framework &amp;amp; additional JS dependencies.&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Deleting Sequoia-PGP certificates</title>
		<published>2026-05-21T00:51:02+00:00</published>
		<updated>2026-05-21T00:51:02+00:00</updated>
		<link rel="alternate" type="text/html" href="https://devedge.github.io/posts/deleting-sequoia-pgp-certificates/"/>
		<id>https://devedge.github.io/posts/deleting-sequoia-pgp-certificates/</id>
    
		<content type="html" xml:base="https://devedge.github.io/posts/deleting-sequoia-pgp-certificates/">&lt;p&gt;If you have been messing around with the potential GPG replacement command-line tool &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;sequoia-pgp.org&#x2F;&quot;&gt;Sequoia-PGP&lt;&#x2F;a&gt;, you may have noticed that there doesn&#x27;t appear to be a way to delete &#x27;certs&#x27; from the certificate store.&lt;&#x2F;p&gt;
&lt;p&gt;After spending some time digging in the manpages and documentation with no clarification, it appears that this isn&#x27;t a mistake but a matter of opinion. The developers treat the certificate store as a completely intentional append-only list, and an issue created about this was &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;sequoia-pgp&#x2F;pgp-cert-d&#x2F;-&#x2F;work_items&#x2F;33&quot;&gt;closed as &quot;won&#x27;t complete&quot; 3 years ago&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;This means that if you were experimenting with creating&#x2F;deleting keys and certs or importing external certs, your certificate store will become littered with unused or broken certs with no possibility to clean it up (this could even be considered a privacy risk, since the default stance is to automatically &quot;hide&quot; them from users).&lt;&#x2F;p&gt;
&lt;p&gt;Unfortunately, if you are at this point, the only solution is nuclear - wipe the entire certstore and start over. Before moving forwards however, be sure to back up your certs &amp;amp; keys.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;backing-up-keys-certs&quot;&gt;Backing up keys &amp;amp; certs&lt;a class=&quot;zola-anchor&quot; href=&quot;#backing-up-keys-certs&quot; aria-label=&quot;Anchor link for: backing-up-keys-certs&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;First, export your full keys, as they are also listed in the cert output. List them with:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;sq&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; key&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; list&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;and then export them with:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;sq&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; key&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; export&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-cert&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; KEYFINGERPRINT&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-output&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; examplename.key.asc&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Next, export any certs that you want to keep and re-import. List them with:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;sq&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; cert&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; list&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;and export with&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;sq&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; cert&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; export&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-cert&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; KEYFINGERPRINT&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-output&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; examplename.cert.asc&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The original documentation for these steps can be found here:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;book.sequoia-pgp.org&#x2F;key_export_import.html#export-a-key&quot;&gt;Exporting Keys&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;book.sequoia-pgp.org&#x2F;cert_import_export.html&quot;&gt;Exporting Certs&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;wiping-everything&quot;&gt;Wiping everything&lt;a class=&quot;zola-anchor&quot; href=&quot;#wiping-everything&quot; aria-label=&quot;Anchor link for: wiping-everything&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;To find where Sequoia-PGP is storing its configurations, run:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;sq&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; config&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; inspect&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; paths&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;On macOS, these will be in an entirely different location than indicated &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;book.sequoia-pgp.org&#x2F;files.html&quot;&gt;in the documentation&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Certificate Store:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&#x2F;Users&#x2F;YOURUSERNAME&#x2F;Library&#x2F;Application Support&#x2F;pgp.cert.d&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Keystore:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&#x2F;Users&#x2F;YOURUSERNAME&#x2F;Library&#x2F;Application Support&#x2F;org.Sequoia-PGP.sequoia&#x2F;keystore&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Navigate to these directories and delete everything. You can confirm that this worked by running &lt;code&gt;sq cert list&lt;&#x2F;code&gt; and &lt;code&gt;sq key list&lt;&#x2F;code&gt; - no keys or certificates should show up.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Note: if you have GNUPG set up, Sequoia-PGP will automatically pick up keys in the &lt;code&gt;~&#x2F;.gnupd&#x2F;&lt;&#x2F;code&gt; directory&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;re-import-keys-certs&quot;&gt;Re-import keys &amp;amp; certs&lt;a class=&quot;zola-anchor&quot; href=&quot;#re-import-keys-certs&quot; aria-label=&quot;Anchor link for: re-import-keys-certs&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Importing is straightforwards:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;sq&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; key&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; import&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; examplename.key.asc&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;sq&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; cert&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; import&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; examplename.cert.asc&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;workaround&quot;&gt;Workaround&lt;a class=&quot;zola-anchor&quot; href=&quot;#workaround&quot; aria-label=&quot;Anchor link for: workaround&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;A clunky workaround that was proposed in the above GitLab issue was creating a temporary configuration directory. By setting the &lt;code&gt;SEQUOIA_HOME&lt;&#x2F;code&gt; variable to this temporary directory (eg., with &lt;code&gt;export SEQUOIA_HOME=$HOME&#x2F;.tmp-sequoia-data&lt;&#x2F;code&gt;), you can delete the directory later.&lt;&#x2F;p&gt;
&lt;p&gt;Ultimately however, this isn&#x27;t a real solution to proper certificate management, so GnuPG will remain my default choice for now.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Replacing macOS BSD utils with GNU coreutils</title>
		<published>2026-03-14T17:35:40+00:00</published>
		<updated>2026-03-14T17:35:40+00:00</updated>
		<link rel="alternate" type="text/html" href="https://devedge.github.io/posts/replacing-macos-bsd-utils-with-gnu-coreutils/"/>
		<id>https://devedge.github.io/posts/replacing-macos-bsd-utils-with-gnu-coreutils/</id>
    
		<content type="html" xml:base="https://devedge.github.io/posts/replacing-macos-bsd-utils-with-gnu-coreutils/">&lt;p&gt;By default, macOS is packaged with the BSD versions of many common CLI utilities such as &lt;code&gt;grep&lt;&#x2F;code&gt;, &lt;code&gt;sed&lt;&#x2F;code&gt;, &lt;code&gt;awk&lt;&#x2F;code&gt;, and more. These are not the same ones that can be found on most Linux distributions, and the slight differences between them can be confusing when working with both systems at the same time.&lt;&#x2F;p&gt;
&lt;p&gt;Thankfully, most of these can be installed through Homebrew. There are some caveats, but for the most part, they can be treated as a one-to-one replacement. The &lt;code&gt;coreutils&lt;&#x2F;code&gt; package is commonly cited, but over time, I have compiled a larger list of other non-GNU utilities that can be replaced.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;installation&quot;&gt;Installation&lt;a class=&quot;zola-anchor&quot; href=&quot;#installation&quot; aria-label=&quot;Anchor link for: installation&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;The full list of default mac packages that I&#x27;ve replaced are:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;brew&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; install&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;    coreutils&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;    diffutils&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;    findutils&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;    man-db&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;    gawk&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;    gnu-sed&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;    watch&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;    grep&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;    gzip&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;    less&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;    curl&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;    wget&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;    rsync&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;    git&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;    vim&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;configuration&quot;&gt;Configuration&lt;a class=&quot;zola-anchor&quot; href=&quot;#configuration&quot; aria-label=&quot;Anchor link for: configuration&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Since the BSD and GNU utils have the same names, these new utils are usually installed with a &lt;code&gt;g&lt;&#x2F;code&gt; prefix. Additionally, their &lt;code&gt;manpages&lt;&#x2F;code&gt; may not be properly pointed to the installed application either. As a result, you&#x27;ll have to redefine the &lt;code&gt;PATH&lt;&#x2F;code&gt; and &lt;code&gt;MANPATH&lt;&#x2F;code&gt; shell variables for a number of these tools.&lt;&#x2F;p&gt;
&lt;p&gt;However, it may not be clear which ones are necessary to set. I will provide a full list of these paths below, but this is the strategy I followed to build it.&lt;&#x2F;p&gt;
&lt;p&gt;First, I made sure there were no &lt;code&gt;PATH&lt;&#x2F;code&gt; or &lt;code&gt;MANPATH&lt;&#x2F;code&gt; variables set in my &lt;code&gt;~&#x2F;.zshrc&lt;&#x2F;code&gt; or remaining ZSH environment. Then, I closed out all ZSH sessions that might exist in the user environment, including &lt;code&gt;tmux&lt;&#x2F;code&gt; sessions and the terminal. Then, I reopened my terminal and &lt;code&gt;echo&lt;&#x2F;code&gt;&#x27;d the path variables to get a clear list of the default paths that macOS uses:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; echo&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; $&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;PATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; tr&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;&#x2F;opt&#x2F;homebrew&#x2F;bin&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;&#x2F;opt&#x2F;homebrew&#x2F;sbin&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;&#x2F;usr&#x2F;local&#x2F;bin&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;&#x2F;System&#x2F;Cryptexes&#x2F;App&#x2F;usr&#x2F;bin&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;&#x2F;usr&#x2F;bin&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;&#x2F;bin&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;&#x2F;usr&#x2F;sbin&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;&#x2F;sbin&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;&#x2F;var&#x2F;run&#x2F;com.apple.security.cryptexd&#x2F;codex.system&#x2F;bootstrap&#x2F;usr&#x2F;local&#x2F;bin&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;&#x2F;var&#x2F;run&#x2F;com.apple.security.cryptexd&#x2F;codex.system&#x2F;bootstrap&#x2F;usr&#x2F;bin&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;&#x2F;var&#x2F;run&#x2F;com.apple.security.cryptexd&#x2F;codex.system&#x2F;bootstrap&#x2F;usr&#x2F;appleinternal&#x2F;bin&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;&#x2F;Applications&#x2F;Ghostty.app&#x2F;Contents&#x2F;MacOS&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; echo&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; $&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;MANPATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; tr&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;&#x2F;usr&#x2F;share&#x2F;man&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;&#x2F;usr&#x2F;local&#x2F;share&#x2F;man&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;&#x2F;Applications&#x2F;Ghostty.app&#x2F;Contents&#x2F;Resources&#x2F;ghostty&#x2F;..&#x2F;man&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Next, I added the &lt;code&gt;PATH&lt;&#x2F;code&gt; for &lt;code&gt;coreutils&lt;&#x2F;code&gt; that was recommended during installation. (You can also re-print the message by running &lt;code&gt;brew info coreutils&lt;&#x2F;code&gt;):&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;export&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; PATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;opt&#x2F;homebrew&#x2F;opt&#x2F;coreutils&#x2F;libexec&#x2F;gnubin:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;PATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;code&gt;MANPATH&lt;&#x2F;code&gt; location usually follows 2 directory conventions. They are located under either:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;&#x2F;opt&#x2F;homebrew&#x2F;opt&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;APPLICATION&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; NAM&lt;&#x2F;span&gt;&lt;span&gt;E&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;libexec&#x2F;gnuman&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; or&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;&#x2F;opt&#x2F;homebrew&#x2F;opt&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;APPLICATION&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; NAM&lt;&#x2F;span&gt;&lt;span&gt;E&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;share&#x2F;man&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;For &lt;code&gt;coreutils&lt;&#x2F;code&gt;, &lt;code&gt;diffutils&lt;&#x2F;code&gt; and &lt;code&gt;findutils&lt;&#x2F;code&gt;, the &lt;code&gt;PATH&lt;&#x2F;code&gt; and &lt;code&gt;MANPATH&lt;&#x2F;code&gt; values were fairly straightforward:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; coreutils&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;export&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; PATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;opt&#x2F;homebrew&#x2F;opt&#x2F;coreutils&#x2F;libexec&#x2F;gnubin:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;PATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;export&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; MANPATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;opt&#x2F;homebrew&#x2F;opt&#x2F;coreutils&#x2F;libexec&#x2F;gnuman:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;MANPATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; diffutils&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;export&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; PATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;opt&#x2F;homebrew&#x2F;opt&#x2F;diffutils&#x2F;bin:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;PATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;export&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; MANPATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;opt&#x2F;homebrew&#x2F;opt&#x2F;diffutils&#x2F;share&#x2F;man:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;MANPATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; findutils&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;export&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; PATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;opt&#x2F;homebrew&#x2F;opt&#x2F;findutils&#x2F;libexec&#x2F;gnubin:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;PATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;export&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; MANPATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;opt&#x2F;homebrew&#x2F;opt&#x2F;findutils&#x2F;libexec&#x2F;gnuman:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;MANPATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The other applications are not as clear. I first added &lt;code&gt;man&lt;&#x2F;code&gt;, following the &lt;a href=&quot;https:&#x2F;&#x2F;devedge.github.io&#x2F;posts&#x2F;man-man&#x2F;#manpages-on-macos&quot;&gt;guide here&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; man&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;export&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; PATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;opt&#x2F;homebrew&#x2F;opt&#x2F;man-db&#x2F;libexec&#x2F;bin:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;PATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;export&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; MANPATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;opt&#x2F;homebrew&#x2F;opt&#x2F;man-db&#x2F;libexec&#x2F;man:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;MANPATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This makes the next step simpler, which is to identify the default binary and manpath location. By running &lt;code&gt;which &amp;lt;APPLICATION NAME&amp;gt;&lt;&#x2F;code&gt; and &lt;code&gt;man --path &amp;lt;APPLICATION NAME&amp;gt;&lt;&#x2F;code&gt;, I can identify where they are located. Homebrew installs everything underneath &lt;code&gt;&#x2F;opt&#x2F;homebrew&#x2F;&lt;&#x2F;code&gt;, so if the path doesn&#x27;t start there, then I know it needs to be reconfigured.&lt;&#x2F;p&gt;
&lt;p&gt;In these three examples, &lt;code&gt;awk&lt;&#x2F;code&gt; is not configured automatically at all, &lt;code&gt;gzip&lt;&#x2F;code&gt; only has its binary in &lt;code&gt;PATH&lt;&#x2F;code&gt;, and &lt;code&gt;git&lt;&#x2F;code&gt; is automatically configured correctly for both its &lt;code&gt;PATH&lt;&#x2F;code&gt; and &lt;code&gt;MANPATH&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; which&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; awk&lt;&#x2F;span&gt;&lt;span&gt; &amp;amp;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; man&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-path&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; awk&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;&#x2F;usr&#x2F;bin&#x2F;awk&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;&#x2F;usr&#x2F;share&#x2F;man&#x2F;man1&#x2F;awk.1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; which&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; gzip&lt;&#x2F;span&gt;&lt;span&gt; &amp;amp;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; man&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-path&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; gzip&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;&#x2F;opt&#x2F;homebrew&#x2F;bin&#x2F;gzip&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;&#x2F;usr&#x2F;share&#x2F;man&#x2F;man1&#x2F;gunzip.1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; which&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; git&lt;&#x2F;span&gt;&lt;span&gt; &amp;amp;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; man&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-path&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; git&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;&#x2F;opt&#x2F;homebrew&#x2F;bin&#x2F;git&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;&#x2F;opt&#x2F;homebrew&#x2F;Cellar&#x2F;git&#x2F;2.53.0&#x2F;share&#x2F;man&#x2F;man1&#x2F;git.1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The remaining list of values that need to be configured after &lt;code&gt;man&lt;&#x2F;code&gt; are:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; awk&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;export&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; PATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;opt&#x2F;homebrew&#x2F;opt&#x2F;gawk&#x2F;libexec&#x2F;gnubin:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;PATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;export&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; MANPATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;opt&#x2F;homebrew&#x2F;opt&#x2F;gawk&#x2F;libexec&#x2F;gnuman:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;MANPATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; sed&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;export&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; PATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;opt&#x2F;homebrew&#x2F;opt&#x2F;gnu-sed&#x2F;libexec&#x2F;gnubin:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;PATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;export&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; MANPATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;opt&#x2F;homebrew&#x2F;opt&#x2F;gnu-sed&#x2F;libexec&#x2F;gnuman:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;MANPATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; grep&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;export&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; PATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;opt&#x2F;homebrew&#x2F;opt&#x2F;grep&#x2F;libexec&#x2F;gnubin:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;PATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;export&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; MANPATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;opt&#x2F;homebrew&#x2F;opt&#x2F;grep&#x2F;libexec&#x2F;gnuman:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;MANPATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; curl&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;export&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; PATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;opt&#x2F;homebrew&#x2F;opt&#x2F;curl&#x2F;bin:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;PATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;export&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; MANPATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;opt&#x2F;homebrew&#x2F;opt&#x2F;curl&#x2F;share&#x2F;man:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;MANPATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; gzip&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;export&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; MANPATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;opt&#x2F;homebrew&#x2F;opt&#x2F;gzip&#x2F;share&#x2F;man:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;MANPATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; less&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;export&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; MANPATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;opt&#x2F;homebrew&#x2F;opt&#x2F;less&#x2F;share&#x2F;man:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;MANPATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; rsync&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;export&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; MANPATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;opt&#x2F;homebrew&#x2F;opt&#x2F;rsync&#x2F;share&#x2F;man:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;MANPATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; vim&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;export&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; MANPATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;opt&#x2F;homebrew&#x2F;opt&#x2F;vim&#x2F;share&#x2F;man:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;MANPATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;For logical separation, I place all of these configurations in a file called &lt;code&gt;gnu-coreutils.sh&lt;&#x2F;code&gt;, and source it in &lt;code&gt;~&#x2F;.zshrc&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; GNU coreutils, diffutils and findutils&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; coreutils&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;export&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; PATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;opt&#x2F;homebrew&#x2F;opt&#x2F;coreutils&#x2F;libexec&#x2F;gnubin:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;PATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;export&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; MANPATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;opt&#x2F;homebrew&#x2F;opt&#x2F;coreutils&#x2F;libexec&#x2F;gnuman:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;MANPATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; diffutils&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;export&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; PATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;opt&#x2F;homebrew&#x2F;opt&#x2F;diffutils&#x2F;bin:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;PATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;export&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; MANPATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;opt&#x2F;homebrew&#x2F;opt&#x2F;diffutils&#x2F;share&#x2F;man:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;MANPATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; findutils&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;export&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; PATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;opt&#x2F;homebrew&#x2F;opt&#x2F;findutils&#x2F;libexec&#x2F;gnubin:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;PATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;export&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; MANPATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;opt&#x2F;homebrew&#x2F;opt&#x2F;findutils&#x2F;libexec&#x2F;gnuman:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;MANPATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Other CLI tools either installed with `g` prefix, or not under &#x2F;opt&#x2F;homebrew&#x2F;bin&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; man&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;export&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; PATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;opt&#x2F;homebrew&#x2F;opt&#x2F;man-db&#x2F;libexec&#x2F;bin:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;PATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;export&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; MANPATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;opt&#x2F;homebrew&#x2F;opt&#x2F;man-db&#x2F;libexec&#x2F;man:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;MANPATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; awk&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;export&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; PATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;opt&#x2F;homebrew&#x2F;opt&#x2F;gawk&#x2F;libexec&#x2F;gnubin:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;PATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;export&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; MANPATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;opt&#x2F;homebrew&#x2F;opt&#x2F;gawk&#x2F;libexec&#x2F;gnuman:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;MANPATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; sed&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;export&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; PATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;opt&#x2F;homebrew&#x2F;opt&#x2F;gnu-sed&#x2F;libexec&#x2F;gnubin:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;PATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;export&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; MANPATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;opt&#x2F;homebrew&#x2F;opt&#x2F;gnu-sed&#x2F;libexec&#x2F;gnuman:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;MANPATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; grep&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;export&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; PATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;opt&#x2F;homebrew&#x2F;opt&#x2F;grep&#x2F;libexec&#x2F;gnubin:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;PATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;export&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; MANPATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;opt&#x2F;homebrew&#x2F;opt&#x2F;grep&#x2F;libexec&#x2F;gnuman:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;MANPATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; curl&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;export&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; PATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;opt&#x2F;homebrew&#x2F;opt&#x2F;curl&#x2F;bin:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;PATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;export&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; MANPATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;opt&#x2F;homebrew&#x2F;opt&#x2F;curl&#x2F;share&#x2F;man:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;MANPATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; CLI tools that already exist under &#x2F;opt&#x2F;homebrew&#x2F;bin but don&amp;#39;t&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; have their manpath correctly updated&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; gzip&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;export&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; MANPATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;opt&#x2F;homebrew&#x2F;opt&#x2F;gzip&#x2F;share&#x2F;man:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;MANPATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; less&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;export&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; MANPATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;opt&#x2F;homebrew&#x2F;opt&#x2F;less&#x2F;share&#x2F;man:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;MANPATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; rsync&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;export&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; MANPATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;opt&#x2F;homebrew&#x2F;opt&#x2F;rsync&#x2F;share&#x2F;man:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;MANPATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; vim&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;export&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; MANPATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;opt&#x2F;homebrew&#x2F;opt&#x2F;vim&#x2F;share&#x2F;man:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;MANPATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;exclusions&quot;&gt;Exclusions&lt;a class=&quot;zola-anchor&quot; href=&quot;#exclusions&quot; aria-label=&quot;Anchor link for: exclusions&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;There are some notable exclusions from this list of programs. Specifically, &lt;code&gt;openssh&lt;&#x2F;code&gt;, &lt;code&gt;unzip&lt;&#x2F;code&gt; and &lt;code&gt;tar&lt;&#x2F;code&gt;. The reason for this is that the default versions bundled with macOS have been modified to recognize macOS-specific extended attributes&#x2F;additional functionality, which the GNU versions do not recognize.&lt;&#x2F;p&gt;
&lt;p&gt;For example, the &lt;code&gt;coreutils&lt;&#x2F;code&gt; tools &lt;code&gt;mv&lt;&#x2F;code&gt; and &lt;code&gt;cp&lt;&#x2F;code&gt; tools &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;brettterpstra.com&#x2F;2014&#x2F;07&#x2F;03&#x2F;mavericks-tags-and-coreutils-a-warning&#x2F;&quot;&gt;do not preserve tags&lt;&#x2F;a&gt;. &lt;code&gt;unzip&lt;&#x2F;code&gt; and &lt;code&gt;tar&lt;&#x2F;code&gt; also reportedly &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;apple.stackexchange.com&#x2F;a&#x2F;71120&quot;&gt;do not recognize macOS metadata&lt;&#x2F;a&gt;. I&#x27;ve found that the bundled OpenSSH has a configuration option &lt;code&gt;UseKeychain&lt;&#x2F;code&gt; that can cache your SSH key in macOS&#x27;s Keychain.&lt;&#x2F;p&gt;
&lt;p&gt;There may be many more examples, but these are the only ones I am aware of. I have re-aliased &lt;code&gt;mv&lt;&#x2F;code&gt; &amp;amp; &lt;code&gt;cp&lt;&#x2F;code&gt;, and haven&#x27;t updated the &lt;code&gt;PATH&lt;&#x2F;code&gt;&#x2F;&lt;code&gt;MANPATH&lt;&#x2F;code&gt; for &lt;code&gt;unzip&lt;&#x2F;code&gt; and &lt;code&gt;gnu-tar&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;alias&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; mv&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;bin&#x2F;mv&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;alias&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; cp&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;bin&#x2F;cp&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I also haven&#x27;t found a reason to replace the bundled &lt;code&gt;zsh&lt;&#x2F;code&gt; as of yet.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;resources&quot;&gt;Resources&lt;a class=&quot;zola-anchor&quot; href=&quot;#resources&quot; aria-label=&quot;Anchor link for: resources&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;www.topbug.net&#x2F;blog&#x2F;2013&#x2F;04&#x2F;14&#x2F;install-and-use-gnu-command-line-tools-in-mac-os-x&#x2F;&quot;&gt;Older guide for installing &lt;code&gt;coreutils&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;apple.stackexchange.com&#x2F;a&#x2F;69332&quot;&gt;Stackexchange guide for installing &lt;code&gt;coreutils&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;brettterpstra.com&#x2F;2014&#x2F;07&#x2F;03&#x2F;mavericks-tags-and-coreutils-a-warning&#x2F;&quot;&gt;Warning regarding tag preservation failure&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;scriptingosx.com&#x2F;2019&#x2F;06&#x2F;moving-to-zsh-part-2-configuration-files&#x2F;&quot;&gt;Good guide on ZSH configuration for macOS&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Minimally functional ZSH config for servers</title>
		<published>2026-02-28T22:27:37+00:00</published>
		<updated>2026-02-28T22:27:37+00:00</updated>
		<link rel="alternate" type="text/html" href="https://devedge.github.io/posts/minimally-functional-zsh-config-for-servers/"/>
		<id>https://devedge.github.io/posts/minimally-functional-zsh-config-for-servers/</id>
    
		<content type="html" xml:base="https://devedge.github.io/posts/minimally-functional-zsh-config-for-servers/">&lt;p&gt;As I set up servers, I have a fairly minimal ZSH configuration I like to deploy to keep consistent behavior across all systems. A number of these tweaks make the shell much more usable and modify inconvenient defaults.&lt;&#x2F;p&gt;
&lt;p&gt;ZSH has a massive list of options that can be modified, so for logical clarity, I will be grouping my configs below based on the &lt;code&gt;manpages&lt;&#x2F;code&gt; where you can find them. This will make it easier to reference them and find related commands if needed. (If you need a quick refresher on using &lt;code&gt;manpages&lt;&#x2F;code&gt;, I have written up &lt;a href=&quot;https:&#x2F;&#x2F;devedge.github.io&#x2F;posts&#x2F;man-man&#x2F;&quot;&gt;a guide right here&lt;&#x2F;a&gt;)&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;&lt;a href=&quot;https:&#x2F;&#x2F;devedge.github.io&#x2F;posts&#x2F;minimally-functional-zsh-config-for-servers&#x2F;#full-zsh-config&quot;&gt;Jump to the complete &lt;code&gt;~&#x2F;.zshrc&lt;&#x2F;code&gt; config here&lt;&#x2F;a&gt;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;zshparam&quot;&gt;&lt;code&gt;zshparam&lt;&#x2F;code&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#zshparam&quot; aria-label=&quot;Anchor link for: zshparam&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;ZSH parameters (&lt;code&gt;man zshparam&lt;&#x2F;code&gt;) are the variables that can be set to configure ZSH defaults. I set a default &lt;code&gt;HISTFILE&lt;&#x2F;code&gt; filename of &lt;code&gt;~&#x2F;.zsh_history&lt;&#x2F;code&gt; that follows the same convention as Bash&#x27;s &lt;code&gt;~&#x2F;.bash_history&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;I also set a generous &lt;code&gt;HISTSIZE&lt;&#x2F;code&gt; of 10 million lines to save in memory, and set &lt;code&gt;SAVEHIST&lt;&#x2F;code&gt; to the same value for the number of lines in the history file:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;HISTFILE&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;~&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;z&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;s&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;h&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;_&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;h&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;i&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;s&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;t&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;o&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;r&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;y&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;HISTSIZE&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;SAVEHIST&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;HISTSIZE&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;code&gt;KEYTIMEOUT&lt;&#x2F;code&gt; is set to 1 (10ms) to minimize the &lt;code&gt;ESC&lt;&#x2F;code&gt; delay in the shell. I have another post &lt;a href=&quot;https:&#x2F;&#x2F;devedge.github.io&#x2F;posts&#x2F;eliminating-esc-delays-in-tmux-vim-and-zsh&#x2F;&quot;&gt;that elaborates on this issue&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;KEYTIMEOUT&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;zshoptions&quot;&gt;&lt;code&gt;zshoptions&lt;&#x2F;code&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#zshoptions&quot; aria-label=&quot;Anchor link for: zshoptions&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;ZSH options (&lt;code&gt;man zshoptions&lt;&#x2F;code&gt;) are toggles that can be flipped to modify default ZSH behavior. I adjust these to provide a better shell history experience.&lt;&#x2F;p&gt;
&lt;p&gt;The first option ensures that every single shell instance immediately writes to &lt;code&gt;~&#x2F;.zsh_history&lt;&#x2F;code&gt; as commands are typed. This ensures that I never lose a command, or that they get written in blocks as the shell exits as opposed to chronological order.&lt;&#x2F;p&gt;
&lt;p&gt;An important point to note is that this doesn&#x27;t update the in-memory history of each shell session. Thus, scrolling through the history with either the arrow keys or &lt;code&gt;CTRL+r&lt;&#x2F;code&gt; means that the history still looks contiguous per-shell. New shell sessions will have the entire history loaded in chronological order, as they were typed:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;setopt&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; INC_APPEND_HISTORY_TIME&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This next option ensures the history also captures the instant timestamp (format: &lt;code&gt;:start:elapsed;command&lt;&#x2F;code&gt;) of when a command was run, and for how long:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;setopt&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; EXTENDED_HISTORY&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;These next two options are for search convenience. The first doesn&#x27;t display duplicate lines while searching (with the up arrow or &lt;code&gt;CTRL+r&lt;&#x2F;code&gt;), and the second option strips out unecessary spaces between commands (eg,. if you accidentally double-tapped the spacebar):&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;setopt&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; HIST_FIND_NO_DUPS&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;setopt&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; HIST_REDUCE_BLANKS&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This next option allows you to deliberately exclude a specific command from being written to ZSH history by typing a space first. This is especially useful when specifying passwords or secret keys in environment variables before a command, so that it doesn&#x27;t get recorded in shell history. Note that it is temporarily saved in-memory until the next command is entered, so that you can use the up arrow to edit the command &amp;amp; re-run it:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;setopt&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; HIST_IGNORE_SPACE&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is a simple command that automatically expands &lt;code&gt;!!&lt;&#x2F;code&gt; into the previous command after you type a space. The advantage is better visibility into exactly what command you are re-running, which is a nice safeguard especially when typing &lt;code&gt;sudo !!&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;setopt&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; BANG_HIST&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This last option disables a particularly annoying behavior: when using unquoted URLs in the shell (such as with &lt;code&gt;curl&lt;&#x2F;code&gt; or &lt;code&gt;wget&lt;&#x2F;code&gt;), certain common characters in the URL are the same ones that the shell uses for glob matching, such as &lt;code&gt;?&lt;&#x2F;code&gt;. While Bash silently ignores it, ZSH fails the command with an error; unsetting the option causes ZSH to behave like Bash:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;unsetopt&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; NOMATCH&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;zshcompsys-zshcontrib-zshbuiltins&quot;&gt;&lt;code&gt;zshcompsys&lt;&#x2F;code&gt;, &lt;code&gt;zshcontrib&lt;&#x2F;code&gt;, &lt;code&gt;zshbuiltins&lt;&#x2F;code&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#zshcompsys-zshcontrib-zshbuiltins&quot; aria-label=&quot;Anchor link for: zshcompsys-zshcontrib-zshbuiltins&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;These are a collection of smaller functions that allow for advanced functionality in ZSH.&lt;&#x2F;p&gt;
&lt;p&gt;ZSH has a completion system (&lt;code&gt;man zshcompsys&lt;&#x2F;code&gt;) that allows for autocompletion of many command-line flags, options, and more. ZSH creates a dumped (cached) configuration file under &lt;code&gt;~&#x2F;.zcompdump&lt;&#x2F;code&gt; that gets intelligently updated as CLI programs are upgraded:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;autoload&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;U&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; compinit&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; compinit&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;To navigate quickly over CLI options, I frequently use &lt;code&gt;Control&#x2F;Alt&lt;&#x2F;code&gt; to jump between words quickly instead of scrolling character-by-character. Bash only considers alphanumeric sequences of characters as words, so to mimic this in ZSH, set the word-style as Bash (&lt;code&gt;man zshcontrib&lt;&#x2F;code&gt;, &lt;code&gt;ZLE FUNCTIONS&lt;&#x2F;code&gt; section) with:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;autoload&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;U&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; select-word-style&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span&gt; select-word-style bash&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;ZSH builtins (&lt;code&gt;man zshbuiltins&lt;&#x2F;code&gt;) are additional commands, bundled with ZSH, that expand on the functionality of the shell. One of these functions is the command &lt;code&gt;fc&lt;&#x2F;code&gt;, which controls various aspects of the shell history.&lt;&#x2F;p&gt;
&lt;p&gt;I can never remember this command name, so I alias 2 of the most useful functions to more memorable commands.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;zread&lt;&#x2F;code&gt; will instantly update the current shell&#x27;s in-memory history with the &lt;code&gt;~&#x2F;.zsh_history&lt;&#x2F;code&gt; file (which is being written to in realtime). I use this when I want to update command history from another open shell session into the current one (a common occurrence when I have multiple shells open in &lt;code&gt;tmux&lt;&#x2F;code&gt;).&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;zhist&lt;&#x2F;code&gt; is a quick way to preview the last few commands (globally, from &lt;code&gt;~&#x2F;.zsh_history&lt;&#x2F;code&gt;) with the exact date-timestamps they were executed. By default, it only lists the last 10 commands. If a negative number is specified afterwards (eg., &lt;code&gt;zhist -32&lt;&#x2F;code&gt;), it displays the last X number of lines.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;alias&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; zread&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;fc -R&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;alias&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; zhist&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;fc -lni&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;systemd-bonus&quot;&gt;&lt;code&gt;systemd&lt;&#x2F;code&gt; bonus&lt;a class=&quot;zola-anchor&quot; href=&quot;#systemd-bonus&quot; aria-label=&quot;Anchor link for: systemd-bonus&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;code&gt;systemd&lt;&#x2F;code&gt; sets some frustrating options when the &lt;code&gt;less&lt;&#x2F;code&gt; pager is called (by default, the full list of options passed to &lt;code&gt;less&lt;&#x2F;code&gt; are: &lt;code&gt;FRSXMK&lt;&#x2F;code&gt; (found in &lt;code&gt;man systemctl&lt;&#x2F;code&gt;)).&lt;&#x2F;p&gt;
&lt;p&gt;These two options are:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;S&lt;&#x2F;code&gt; This automatically chops lines that are wider than the terminal width instead of wrapping them. As a result, you have to start scrolling first right and then left to trigger the &lt;code&gt;less&lt;&#x2F;code&gt; pager and read the entire line.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;X&lt;&#x2F;code&gt;: This prevents the terminal from restoring its previous view after you&#x27;ve exited the pager. This means that output from commands such as &lt;code&gt;journalctl&lt;&#x2F;code&gt; completely fill up the terminal with lingering output.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;By removing both of these options, you can have a more friendly default:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;export&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; SYSTEMD_LESS&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;FRMK&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;fedora-double-bonus&quot;&gt;Fedora double bonus&lt;a class=&quot;zola-anchor&quot; href=&quot;#fedora-double-bonus&quot; aria-label=&quot;Anchor link for: fedora-double-bonus&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;When I exited an &lt;code&gt;ssh&lt;&#x2F;code&gt; session from my Fedora servers, it would clear the entire terminal pane. I didn&#x27;t like this, since sometimes I was just jumping in to check a quick config option and this would reset my viewport.&lt;&#x2F;p&gt;
&lt;p&gt;After some digging, I found that Fedora sets a default &lt;code&gt;zlogout&lt;&#x2F;code&gt; in &lt;code&gt;&#x2F;etc&#x2F;zlogout&lt;&#x2F;code&gt; that gets called every time I exit an &lt;code&gt;ssh&lt;&#x2F;code&gt; session. I simply commented out the following line to disable the behavior:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;command -v clear &amp;amp;&amp;gt; &#x2F;dev&#x2F;null &amp;amp;&amp;amp; clear&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Alternatively, if you only want to disable this behavior for a single user, you can add the following to the local user&#x27;s &lt;code&gt;~&#x2F;.zlogout&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;setop&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; norcs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;full-zsh-config&quot;&gt;Full ZSH config&lt;a class=&quot;zola-anchor&quot; href=&quot;#full-zsh-config&quot; aria-label=&quot;Anchor link for: full-zsh-config&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Here is the full &lt;code&gt;~&#x2F;.zshrc&lt;&#x2F;code&gt; config file, annotated with short comments:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; zsh configuration&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; man zshparam&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;HISTFILE&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;~&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;z&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;s&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;h&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;_&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;h&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;i&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;s&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;t&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;o&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;r&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;y&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;         #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; history file&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;HISTSIZE&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;               #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; in-memory history&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;SAVEHIST&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;HISTSIZE&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;              #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; history file size&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;KEYTIMEOUT&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;                    #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; 10ms delay for key sequences&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; man zshoptions&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;setopt&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; INC_APPEND_HISTORY_TIME&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;  #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; write history immediately, not when shell exits&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;setopt&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; EXTENDED_HISTORY&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;         #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; history format: &amp;quot;:start:elapsed;command&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;setopt&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; HIST_FIND_NO_DUPS&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;        #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; don&amp;#39;t display duplicate lines when searching&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;setopt&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; HIST_REDUCE_BLANKS&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;       #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; remove superfluous blanks&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;setopt&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; HIST_IGNORE_SPACE&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;        #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; don&amp;#39;t save lines that start with a space&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;setopt&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; BANG_HIST&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;                #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; automatically expand !! after typing a space&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;unsetopt&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; NOMATCH&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;                #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; allow typing URLs without quoting them&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; man zshcompsys, zshcontrib, zshbuiltins&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;autoload&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;U&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; compinit&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; compinit&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;  #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; initialize zsh completion&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;autoload&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;U&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; select-word-style&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span&gt; select-word-style bash&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;   #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; bash-style word jumping&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;alias&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; zread&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;fc -R&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;             #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; read latest shell history from file into memory&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;alias&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; zhist&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;fc -lni&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;           #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; list last 10 historical commands (zhist -&amp;lt;number&amp;gt; for more)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; remove &amp;#39;X&amp;#39; and &amp;#39;S&amp;#39; options&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;export&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; SYSTEMD_LESS&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;FRMK&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;resources&quot;&gt;Resources&lt;a class=&quot;zola-anchor&quot; href=&quot;#resources&quot; aria-label=&quot;Anchor link for: resources&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;unix.stackexchange.com&#x2F;a&#x2F;273863&quot;&gt;Good StackExchange reference for many of these options&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;devedge.github.io&#x2F;posts&#x2F;man-man&#x2F;&quot;&gt;Manpage guide&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;devedge.github.io&#x2F;posts&#x2F;eliminating-esc-delays-in-tmux-vim-and-zsh&#x2F;&quot;&gt;Escape Delay post&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;unix.stackexchange.com&#x2F;a&#x2F;162897&quot;&gt;StackExchange post to disable &lt;code&gt;zlogout&lt;&#x2F;code&gt; behavior&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Switching Fedora bootloader to systemd-boot</title>
		<published>2026-02-22T12:30:03+00:00</published>
		<updated>2026-02-22T12:30:03+00:00</updated>
		<link rel="alternate" type="text/html" href="https://devedge.github.io/posts/switching-fedora-bootloader-to-systemd-boot/"/>
		<id>https://devedge.github.io/posts/switching-fedora-bootloader-to-systemd-boot/</id>
    
		<content type="html" xml:base="https://devedge.github.io/posts/switching-fedora-bootloader-to-systemd-boot/">&lt;p&gt;The current default bootloader for Fedora 43 is still &lt;code&gt;GRUB&lt;&#x2F;code&gt;, and I wanted to switch over to the native systemd bootloader &lt;code&gt;systemd-boot&lt;&#x2F;code&gt;. However, it was somewhat of a challenge to find clear instructions for this process, so I&#x27;ll step through them here.&lt;&#x2F;p&gt;
&lt;p&gt;This guide only shows how to set up &lt;code&gt;systemd-boot&lt;&#x2F;code&gt; on a fresh Fedora 43 install, since I had challenges trying to switch from &lt;code&gt;GRUB&lt;&#x2F;code&gt; post-installation.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Note&lt;&#x2F;em&gt;: Ironically, this method is &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;bugzilla.redhat.com&#x2F;show_bug.cgi?id=2402975&quot;&gt;broken specifically for Fedora 43&lt;&#x2F;a&gt;. A fix &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;bodhi.fedoraproject.org&#x2F;updates&#x2F;FEDORA-2025-3190649b5c&quot;&gt;has been merged&lt;&#x2F;a&gt; into the upcoming Fedora 44 release.&lt;&#x2F;p&gt;
&lt;p&gt;Before you even boot into the Fedora ISO of your choosing, the &lt;code&gt;GRUB&lt;&#x2F;code&gt; bootloader will flash:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;assets&#x2F;switching-fedora-bootloader-to-systemd-boot&#x2F;bootloader-picker.png&quot; alt=&quot;bootloader-picker&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Before the 60s timer runs out, use the arrow keys to select the installation and press &lt;code&gt;e&lt;&#x2F;code&gt; to enter an Emacs-like editor:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;assets&#x2F;switching-fedora-bootloader-to-systemd-boot&#x2F;bootloader-editor.png&quot; alt=&quot;bootloader-editor&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The editor will show the current boot parameters that are being used to boot into the specified ISO.&lt;&#x2F;p&gt;
&lt;p&gt;Now, enter the text &lt;code&gt;inst.sdboot&lt;&#x2F;code&gt; after the second line, &lt;code&gt;linuxefi &#x2F;images&#x2F;pxeboot&#x2F;vmlinuz &lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;assets&#x2F;switching-fedora-bootloader-to-systemd-boot&#x2F;bootloader-sdboot.png&quot; alt=&quot;bootloader-sdboot&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Type &lt;code&gt;Ctrl+x&lt;&#x2F;code&gt; to save &amp;amp; boot with the modified boot parameters, and you&#x27;ll be good to start your OS installation!&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;assets&#x2F;switching-fedora-bootloader-to-systemd-boot&#x2F;fedora43-installation.png&quot; alt=&quot;fedora43-installation&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;resources&quot;&gt;Resources&lt;a class=&quot;zola-anchor&quot; href=&quot;#resources&quot; aria-label=&quot;Anchor link for: resources&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;fedoraproject.org&#x2F;wiki&#x2F;Changes&#x2F;cleanup_systemd_install&quot;&gt;Fedora instructions for testing &lt;code&gt;systemd-boot&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;wiki.archlinux.org&#x2F;title&#x2F;Systemd-boot&quot;&gt;Arch Wiki entry for further information on &lt;code&gt;systemd-boot&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Quick aside on AI usage</title>
		<published>2026-02-17T18:23:47+00:00</published>
		<updated>2026-02-17T18:23:47+00:00</updated>
		<link rel="alternate" type="text/html" href="https://devedge.github.io/posts/quick-aside-on-ai-usage/"/>
		<id>https://devedge.github.io/posts/quick-aside-on-ai-usage/</id>
    
		<content type="html" xml:base="https://devedge.github.io/posts/quick-aside-on-ai-usage/">&lt;p&gt;It seems that with the ubiquity of AI and its potential to disrupt so many fields, just about every blog has a take on its future. However, this is not what this post will be about.&lt;&#x2F;p&gt;
&lt;p&gt;Rather, I&#x27;d like this to be more of a general disclaimer that, to date, in any of the work I do in the public&#x2F;open source domain, I don&#x27;t use AI to:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Write any blog posts&lt;&#x2F;li&gt;
&lt;li&gt;Generate or create any code&lt;&#x2F;li&gt;
&lt;li&gt;Research any topics (including search engine summaries)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This isn&#x27;t for ideological issues, but moreso that I genuinely enjoy the essence of the work I do. Using AI to replace myself in the loop feels like using an exoskeleton to lift weights, or an e-bike to cycle. I have also felt the frustration of becoming deeply engrossed in some technical article, only to eventually realize it isn&#x27;t saying anything meaningful and was AI-generated (or heavily assisted).&lt;&#x2F;p&gt;
&lt;p&gt;If at any point I change this approach, I&#x27;ll be sure to clearly annotate it, either in my posts or in my code.&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>man man</title>
		<published>2026-02-16T20:09:59+00:00</published>
		<updated>2026-02-16T20:09:59+00:00</updated>
		<link rel="alternate" type="text/html" href="https://devedge.github.io/posts/man-man/"/>
		<id>https://devedge.github.io/posts/man-man/</id>
    
		<content type="html" xml:base="https://devedge.github.io/posts/man-man/">&lt;p&gt;Manpages are something I&#x27;ve often underutilized, despite how useful they are. After spending some time researching them further, here are some takeaways and modifications that significantly improve my usage.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;using-the-pager&quot;&gt;Using the pager&lt;a class=&quot;zola-anchor&quot; href=&quot;#using-the-pager&quot; aria-label=&quot;Anchor link for: using-the-pager&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;By default, &lt;code&gt;man&lt;&#x2F;code&gt; uses the &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;www.greenwoodsoftware.com&#x2F;less&#x2F;faq.html&quot;&gt;&lt;code&gt;less&lt;&#x2F;code&gt; pager&lt;&#x2F;a&gt; to display documentation as pages in your terminal. As a result, it uses a lot of Vi-style keyboard commands that allow you to move around while rarely shifting your hands from the &lt;code&gt;f&lt;&#x2F;code&gt; and &lt;code&gt;j&lt;&#x2F;code&gt; keys.&lt;&#x2F;p&gt;
&lt;p&gt;A few of the most useful ones are:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;j&lt;&#x2F;code&gt; - scroll down a line&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;k&lt;&#x2F;code&gt; - scroll up a line&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;d&lt;&#x2F;code&gt; - scroll &lt;code&gt;d&lt;&#x2F;code&gt;own half a page. Useful for keeping visual context while scrolling quicker.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;u&lt;&#x2F;code&gt; - scroll &lt;code&gt;u&lt;&#x2F;code&gt;p half a page&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;PageUp&#x2F;PageDown&lt;&#x2F;code&gt;, &lt;code&gt;b&#x2F;&amp;lt;SPACE&amp;gt;&lt;&#x2F;code&gt; keys - scrolls up&#x2F;down an entire &#x27;page&#x27; of content. While fast, I find it harder to visually track content.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The most common searches can be done with:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&#x2F;&lt;&#x2F;code&gt; - search downwards in the manpage: &lt;code&gt;&#x2F;searchpattern&amp;lt;ENTER&amp;gt;&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;?&lt;&#x2F;code&gt; - search upwards in the manpage: &lt;code&gt;?searchpattern&amp;lt;ENTER&amp;gt;&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;n&lt;&#x2F;code&gt; - jump to the &lt;code&gt;n&lt;&#x2F;code&gt;ext search result&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;N&lt;&#x2F;code&gt; - jump to the previous search result. &lt;code&gt;SHIFT+n&lt;&#x2F;code&gt;, the reverse action of &lt;code&gt;n&lt;&#x2F;code&gt;, is a common pattern in Vi commands.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;g&lt;&#x2F;code&gt; - &lt;code&gt;g&lt;&#x2F;code&gt;o to the bottom of the manpage&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;G&lt;&#x2F;code&gt; - &lt;code&gt;G&lt;&#x2F;code&gt;o to the top of the manpage. This used to be the way I restarted a new search from the top.*&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;*this is technically an anti-pattern that I picked up. Typing a &lt;code&gt;&#x2F;&lt;&#x2F;code&gt; followed by &lt;code&gt;&amp;lt;CTRL&amp;gt;f&lt;&#x2F;code&gt; automatically jumps to the top of the page to restart the search while transforming your prompt to look like this:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;First-file &#x2F;searchpattern&amp;lt;ENTER&amp;gt;&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;assets&#x2F;man-man&#x2F;man-search-top.png&quot; alt=&quot;man-search-top&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Continuing in the vein of more advanced search tricks, a few more are:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&#x2F;&amp;lt;CTRL&amp;gt;k&lt;&#x2F;code&gt; - show search results in the currently displayed screen area without moving&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;&#x2F;&amp;lt;CTRL&amp;gt;w&lt;&#x2F;code&gt; - wrap your search around to restart at the opposite end of the page&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;&#x2F;&amp;lt;CTRL&amp;gt;r&lt;&#x2F;code&gt; - disable the automatic regex when searching (searching in reverse would be &lt;code&gt;?&amp;lt;CTRL&amp;gt;r&lt;&#x2F;code&gt;)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The search line automatically uses regex, so special charaters such as &lt;code&gt;^&lt;&#x2F;code&gt; (start of line) will need to be escaped with a &lt;code&gt;\&lt;&#x2F;code&gt; to be read literally; eg., &lt;code&gt;&#x2F;\^F&amp;lt;ENTER&amp;gt;&lt;&#x2F;code&gt; to search for the literal characters &#x27;^F&#x27;.&lt;&#x2F;p&gt;
&lt;p&gt;To escape out of any of these prompts, use backspace to reset the search line (instead of frantically hitting &lt;code&gt;q&lt;&#x2F;code&gt; and &lt;code&gt;Escape&lt;&#x2F;code&gt; like I often do ;) )&lt;&#x2F;p&gt;
&lt;h2 id=&quot;customizing-the-pager&quot;&gt;Customizing the pager&lt;a class=&quot;zola-anchor&quot; href=&quot;#customizing-the-pager&quot; aria-label=&quot;Anchor link for: customizing-the-pager&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;As nice as the above commands are, there are a few command line flags you can pass to &lt;code&gt;less&lt;&#x2F;code&gt; to make it play better and avoid using so many of them:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;--ignore-case&lt;&#x2F;code&gt; - by default, &lt;code&gt;less&lt;&#x2F;code&gt; is case-sensitive. This ignores case, &lt;em&gt;unless&lt;&#x2F;em&gt; you begin typing uppercase letters.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;--use-color&lt;&#x2F;code&gt; - colorizes various elements, including the status bar and search results&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;--wordwrap&lt;&#x2F;code&gt; - wraps words as they reach the right side of the terminal instead of hyphenating them. This avoid words being split with a hypen (&lt;code&gt;-&lt;&#x2F;code&gt;)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;--status-line&lt;&#x2F;code&gt; - highlights the entire line that has a &lt;code&gt;mark&lt;&#x2F;code&gt;. Marks are covered below.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The full list of flags to &lt;code&gt;export&lt;&#x2F;code&gt; for the &lt;code&gt;MANPAGER&lt;&#x2F;code&gt; variable is:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;export&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; MANPAGER&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;less --ignore-case --use-color --wordwrap --status-line --lesskey-src=&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;HOME&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;.manpage-lesskey&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The last two flags are covered in the next two sections respectively:&lt;&#x2F;p&gt;
&lt;h2 id=&quot;advanced-usage-with-marks&quot;&gt;Advanced usage with marks&lt;a class=&quot;zola-anchor&quot; href=&quot;#advanced-usage-with-marks&quot; aria-label=&quot;Anchor link for: advanced-usage-with-marks&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;A common problem I had when using very large manpages for tools like &lt;code&gt;tmux&lt;&#x2F;code&gt; was that I was constantly re-searching flags or keywords to check multiple sections (sometimes even opening up 2 &lt;code&gt;tmux&lt;&#x2F;code&gt; manpages).&lt;&#x2F;p&gt;
&lt;p&gt;However it turns out that you can &#x27;book&lt;code&gt;mark&lt;&#x2F;code&gt;&#x27; sections of the manpage and jump between them! The process to do this is a little convoluted, but I&#x27;ve found it useful once I committed it to memory.&lt;&#x2F;p&gt;
&lt;p&gt;Assuming you have already found a position you would like to (book)&lt;code&gt;mark&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;First, type &lt;code&gt;m&lt;&#x2F;code&gt; followed by an upper- or lower-case letter: &lt;code&gt;ma&lt;&#x2F;code&gt;. If you enabled the &lt;code&gt;--status-line&lt;&#x2F;code&gt; flag above, the top line in your pager will be highlighted.&lt;&#x2F;li&gt;
&lt;li&gt;Now, continue to another section of the manpage however you&#x27;d like (scrolling or through search)&lt;&#x2F;li&gt;
&lt;li&gt;Then, &lt;code&gt;mark&lt;&#x2F;code&gt; this new section with a different letter: &lt;code&gt;mb&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Continue however many times as needed...&lt;&#x2F;li&gt;
&lt;li&gt;To jump to a &lt;code&gt;mark&lt;&#x2F;code&gt;, type a single apostrophe &lt;code&gt;&#x27;&lt;&#x2F;code&gt; (right of &lt;code&gt;;&lt;&#x2F;code&gt; on keyboard) and the letter you used: &lt;code&gt;&#x27;a&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;While I initially tried to use letters that made sense for the current section, I found that it was too much mental overhead. Instead, I pick the next sequential letter in the alphabet.&lt;&#x2F;p&gt;
&lt;p&gt;There is more you can do with marks, but I haven&#x27;t found them particularly helpful:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&#x27;&#x27;&lt;&#x2F;code&gt; - jump to last position (often the top of the page). This doesn&#x27;t seem to jump between marks though, which is unfortunate.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;M&lt;&#x2F;code&gt; - add a mark to the bottom of the page instead&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;ESC&amp;gt;ma&lt;&#x2F;code&gt; - clears the mark &lt;code&gt;a&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;--save‐marks&lt;&#x2F;code&gt; - when specified in the &lt;code&gt;less&lt;&#x2F;code&gt; options, this saves the marks even when you close the file&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;searching-cli-flags&quot;&gt;Searching CLI flags&lt;a class=&quot;zola-anchor&quot; href=&quot;#searching-cli-flags&quot; aria-label=&quot;Anchor link for: searching-cli-flags&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;This following configuration has become invaluable for me on a daily basis. I find myself constantly searching for CLI flags (eg., &lt;code&gt;-f&lt;&#x2F;code&gt;) and getting results somewhere in the middle of an explanation section instead of the actual flag. A user on StackOverflow provided an &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;superuser.com&#x2F;a&#x2F;1731762&quot;&gt;excellent solution&lt;&#x2F;a&gt; to this problem.&lt;&#x2F;p&gt;
&lt;p&gt;The magic is a &lt;code&gt;lesskey&lt;&#x2F;code&gt; configuration that jumps to the top of the file and auto-inserts a regex string:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;command&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;\eF&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; forw-search&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;\^&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;\\&lt;&#x2F;span&gt;&lt;span&gt;s&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;\+&lt;&#x2F;span&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;|&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; -&lt;&#x2F;span&gt;&lt;span&gt;)-&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;?&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;\ef&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; noaction&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; g&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;\e&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;F&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;By adding this to the file &lt;code&gt;~&#x2F;.manpage-lesskey&lt;&#x2F;code&gt; and using the flag &lt;code&gt;--lesskey-src=$HOME&#x2F;.manpage-lesskey&lt;&#x2F;code&gt; as above, you can enable this feature only on manpages and not anytime you open &lt;code&gt;less&lt;&#x2F;code&gt;. (&lt;code&gt;$HOME&lt;&#x2F;code&gt; is required because &lt;code&gt;man&lt;&#x2F;code&gt; cannot interpret &lt;code&gt;~&lt;&#x2F;code&gt;)&lt;&#x2F;p&gt;
&lt;p&gt;To use this, type &lt;code&gt;⌥f&lt;&#x2F;code&gt; (Option+f) or &lt;code&gt;&amp;lt;ALT&amp;gt;f&lt;&#x2F;code&gt;. You&#x27;ll immediately jump to the top of the manpage and the following prompt will appear in your search bar:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;&#x2F;(^\s+-|, -)-?&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Type the flag letter or the name of the full flag, eg., &lt;code&gt;s&lt;&#x2F;code&gt; or &lt;code&gt;case&lt;&#x2F;code&gt; - there&#x27;s no need to prepend the dash &lt;code&gt;-&lt;&#x2F;code&gt; - and hit &lt;code&gt;&amp;lt;ENTER&amp;gt;&lt;&#x2F;code&gt; to jump to the definition.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;searching-everything-man&quot;&gt;Searching everything &lt;code&gt;man&lt;&#x2F;code&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#searching-everything-man&quot; aria-label=&quot;Anchor link for: searching-everything-man&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;To do a full text search of all manpages, use the &lt;code&gt;-K&lt;&#x2F;code&gt;&#x2F;&lt;code&gt;--global-apropos&lt;&#x2F;code&gt; flag:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;man -K searchpattern&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;p&gt;However, this immediately opens up the manpage of the first search result, and when you exit with &lt;code&gt;q&lt;&#x2F;code&gt;, it prompts you to:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;[ view (return) | skip (Ctrl-D) | quit (Ctrl-C) ]&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;p&gt;for every single entry, one at a time, looking like this:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;assets&#x2F;man-man&#x2F;man-search.png&quot; alt=&quot;man-search&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;A bit inconvenient, so I may find a workaround eventually.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;tldr&quot;&gt;&lt;code&gt;tldr&lt;&#x2F;code&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#tldr&quot; aria-label=&quot;Anchor link for: tldr&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Despite all the above, sometimes you don&#x27;t want to trawl through a manpage for minutes to piece together a comprehensive command, flag-by-flag. In that case, the &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;tldr.sh&#x2F;&quot;&gt;&lt;code&gt;tldr&lt;&#x2F;code&gt; project&lt;&#x2F;a&gt; gives you a short synopsis and a list of example commands instead.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;assets&#x2F;man-man&#x2F;man-tldr.png&quot; alt=&quot;man-tldr&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;While the front page instructions recommend installing it through &lt;code&gt;npm&lt;&#x2F;code&gt;, thankfully there&#x27;s a &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;tldr-pages&#x2F;tlrc&quot;&gt;client written in Rust called &lt;code&gt;tlrc&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;. It&#x27;s available through Homebrew with &lt;code&gt;brew install tlrc&lt;&#x2F;code&gt; (be sure to update the &lt;code&gt;tldr&lt;&#x2F;code&gt; database with a &lt;code&gt;tldr -u&lt;&#x2F;code&gt; before using).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;manpages-on-macos&quot;&gt;&lt;code&gt;manpages&lt;&#x2F;code&gt; on macOS&lt;a class=&quot;zola-anchor&quot; href=&quot;#manpages-on-macos&quot; aria-label=&quot;Anchor link for: manpages-on-macos&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;If you&#x27;ve noticed that your &lt;code&gt;man&lt;&#x2F;code&gt; does not have a status prompt at the bottom of your terminal, it&#x27;s likely that you&#x27;re using the bundled version of &lt;code&gt;man&lt;&#x2F;code&gt; on macOS.&lt;&#x2F;p&gt;
&lt;p&gt;Bundled:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;assets&#x2F;man-man&#x2F;man-macos-bsd.png&quot; alt=&quot;man-macos-bsd&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Modern:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;assets&#x2F;man-man&#x2F;man-macos-gnu.png&quot; alt=&quot;man-macos-gnu&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The default version of &lt;code&gt;man&lt;&#x2F;code&gt; installed on macOS is frequently out of date and based on BSD. The more modern implementation that is normally seen on Linux machines is not &lt;code&gt;man&lt;&#x2F;code&gt;, but &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;man-db.gitlab.io&#x2F;man-db&#x2F;&quot;&gt;another implementation called &lt;code&gt;man-db&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Installation can be done through &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;brew.sh&quot;&gt;Homebrew&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;brew&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; install&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; man-db&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;However, this will be installed as &lt;code&gt;gman&lt;&#x2F;code&gt; to avoid breaking compatibilty with your default installation of  &lt;code&gt;man&lt;&#x2F;code&gt;. To make it your default, export the path &amp;amp; its manpath in your shell configuration file, eg., &lt;code&gt;~&#x2F;.zshrc&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;export&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; PATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;opt&#x2F;homebrew&#x2F;opt&#x2F;man-db&#x2F;libexec&#x2F;bin:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;PATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;export&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; MANPATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;opt&#x2F;homebrew&#x2F;opt&#x2F;man-db&#x2F;libexec&#x2F;man:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;MANPATH&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;strange-bugs-with-hyphens&quot;&gt;Strange bugs with hyphens&lt;a class=&quot;zola-anchor&quot; href=&quot;#strange-bugs-with-hyphens&quot; aria-label=&quot;Anchor link for: strange-bugs-with-hyphens&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;While trying to search flags with hyphens, I was confused why &lt;code&gt;less&lt;&#x2F;code&gt; refused to match them especially if they were between letters. After some digging around, &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;unix.stackexchange.com&#x2F;a&#x2F;136142&quot;&gt;this StackOverflow post&lt;&#x2F;a&gt; revealed the issue: the manpages on my mac are being rendered with non-ASCII characters.&lt;&#x2F;p&gt;
&lt;p&gt;I could validate this by running the following command:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;LC_COLLATE&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;C&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; LESS&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;+&#x2F;[^ -~]&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; man&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; rsync&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;assets&#x2F;man-man&#x2F;man-non-ascii.png&quot; alt=&quot;man-non-ascii&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Every single highlight is a non-ASCII character.&lt;&#x2F;p&gt;
&lt;p&gt;While a bit inelegant, I re-aliased &lt;code&gt;man&lt;&#x2F;code&gt; such that it forces it to use an ASCII character set, as specified in the post:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;alias&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; man&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;LC_CTYPE=C man&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;resources&quot;&gt;Resources&lt;a class=&quot;zola-anchor&quot; href=&quot;#resources&quot; aria-label=&quot;Anchor link for: resources&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;www.mankier.com&#x2F;&quot;&gt;ManKier: Search manpages translated to HTML5&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;man-db.gitlab.io&#x2F;man-db&#x2F;&quot;&gt;&lt;code&gt;man-db&lt;&#x2F;code&gt; homepage&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;unix.stackexchange.com&#x2F;questions&#x2F;762442&#x2F;whats-the-difference-between-ubuntus-man-and-macoss-man&quot;&gt;BSD &lt;code&gt;man&lt;&#x2F;code&gt; vs. &lt;code&gt;man-db&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;medium.com&#x2F;better-programming&#x2F;man-pages-the-complete-guide-800ad93425fe&quot;&gt;Excellent deep-dive into manpages&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Vim encoding&#x2F;decoding base64 in Kubernetes secrets</title>
		<published>2025-08-09T21:54:21+00:00</published>
		<updated>2025-08-09T21:54:21+00:00</updated>
		<link rel="alternate" type="text/html" href="https://devedge.github.io/posts/vim-encoding-decoding-base64-in-kubernetes-secrets/"/>
		<id>https://devedge.github.io/posts/vim-encoding-decoding-base64-in-kubernetes-secrets/</id>
    
		<content type="html" xml:base="https://devedge.github.io/posts/vim-encoding-decoding-base64-in-kubernetes-secrets/">&lt;p&gt;Kubernetes provides the ability to edit secrets from the command line, but there&#x27;s a catch: they&#x27;re encoded with base64 and &lt;code&gt;kubectl&lt;&#x2F;code&gt; provides no way to encode&#x2F;decode it.&lt;&#x2F;p&gt;
&lt;p&gt;There are several solutions online to this problem, often involving installing another tool. However, vim can do this with the help of the &lt;code&gt;base64&lt;&#x2F;code&gt; binary commonly found on Linux systems.&lt;&#x2F;p&gt;
&lt;p&gt;The following solution is based on &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;stackoverflow.com&#x2F;a&#x2F;7846569&quot;&gt;this StackOverflow post&lt;&#x2F;a&gt;, but with a critical modification to fix unintended behavior.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;echo-decode-in-command-mode&quot;&gt;&lt;code&gt;echo&lt;&#x2F;code&gt; decode in Command Mode&lt;a class=&quot;zola-anchor&quot; href=&quot;#echo-decode-in-command-mode&quot; aria-label=&quot;Anchor link for: echo-decode-in-command-mode&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;These commands rely on using Visual selection mode to select a block of text that should be encoded or decoded.&lt;&#x2F;p&gt;
&lt;p&gt;This first configuration entry, which can be added in &lt;code&gt;~&#x2F;.vimrc&lt;&#x2F;code&gt;, only decodes the selected text in Visual mode and prints it into the Command Mode line at the bottom of the vim editor:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;viml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;vnoremap&lt;&#x2F;span&gt;&lt;span&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;leader&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;64&lt;&#x2F;span&gt;&lt;span&gt; y:&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;echo&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; system&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;base64 --wrap=0 --decode&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; @&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;)&amp;lt;cr&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;After making a visual selection, type &lt;code&gt;\&lt;&#x2F;code&gt; quickly followed by &lt;code&gt;64&lt;&#x2F;code&gt; to print the base64 decoded line. The &#x27;quickly&#x27; is because &lt;code&gt;\&lt;&#x2F;code&gt;, known as the &#x27;leader&#x27;, is a special character used to prefix these kinds of custom mappings and has a timeout of 1 second.&lt;&#x2F;p&gt;
&lt;p&gt;This can be extended by setting the &lt;code&gt;timeoutlen&lt;&#x2F;code&gt; variable in vim, but be sure to utilize the &lt;code&gt;ttimeoutlen&lt;&#x2F;code&gt; variable so pressing ESC does not also use the same delay. &lt;a href=&quot;https:&#x2F;&#x2F;devedge.github.io&#x2F;posts&#x2F;eliminating-esc-delays-in-tmux-vim-and-zsh&#x2F;&quot;&gt;This post&lt;&#x2F;a&gt; dives into this further.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;code&gt;--wrap=0&lt;&#x2F;code&gt; is very important because by default, &lt;code&gt;base64&lt;&#x2F;code&gt; wraps to 76 characters - that flag will disable this behavior.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;decode-inline&quot;&gt;Decode inline&lt;a class=&quot;zola-anchor&quot; href=&quot;#decode-inline&quot; aria-label=&quot;Anchor link for: decode-inline&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;This configuration line does the same as above, but actually modifies the text inline in the vim editor:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;viml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;vnoremap&lt;&#x2F;span&gt;&lt;span&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;leader&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;d64 c&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;c-r&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;system&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;base64 --wrap=0 --decode&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; @&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;)&amp;lt;cr&amp;gt;&amp;lt;esc&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Use this by typing &lt;code&gt;\&lt;&#x2F;code&gt; followed by &lt;code&gt;d64&lt;&#x2F;code&gt; (decode 64).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;encode-inline&quot;&gt;Encode inline&lt;a class=&quot;zola-anchor&quot; href=&quot;#encode-inline&quot; aria-label=&quot;Anchor link for: encode-inline&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;After making modifications to a secret, it should be re-encoded. This following configuration entry allows for re-encoding a block of visually selected text inline in the vim editor:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;viml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;vnoremap&lt;&#x2F;span&gt;&lt;span&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;leader&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;e64 c&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;c-r&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;system&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;base64 --wrap=0&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; @&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;)&amp;lt;cr&amp;gt;&amp;lt;esc&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Use this by typing &lt;code&gt;\&lt;&#x2F;code&gt; followed by &lt;code&gt;e64&lt;&#x2F;code&gt; (encode 64)&lt;&#x2F;p&gt;
&lt;h2 id=&quot;correctly-selecting-text-in-visual-mode&quot;&gt;Correctly selecting text in Visual Mode&lt;a class=&quot;zola-anchor&quot; href=&quot;#correctly-selecting-text-in-visual-mode&quot; aria-label=&quot;Anchor link for: correctly-selecting-text-in-visual-mode&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;It might make sense to start Visual selection mode and select an entire line of text to the end with &lt;code&gt;v$&lt;&#x2F;code&gt;. However, this would be a mistake since it &lt;em&gt;also&lt;&#x2F;em&gt; selects the newline character &lt;code&gt;\n&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Instead, to select to the end without the newline, type: &lt;code&gt;vg_&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Alternatively if the cursor is already at the end of the line, the reverse selection up to (but not including) the first space character can be done with v + SHIFT t + SPACE (&lt;code&gt;vT &lt;&#x2F;code&gt;).&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;resources&quot;&gt;Resources&lt;a class=&quot;zola-anchor&quot; href=&quot;#resources&quot; aria-label=&quot;Anchor link for: resources&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;stackoverflow.com&#x2F;a&#x2F;7846569&quot;&gt;Reference StackOverflow post&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;alldrops.info&#x2F;posts&#x2F;vim-drops&#x2F;2018-05-15_understand-vim-mappings-and-create-your-own-shortcuts&#x2F;&quot;&gt;Excellent resource for creating vim mappings&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>ZFS local replication with systemd units + timers</title>
		<published>2025-07-09T19:39:21+00:00</published>
		<updated>2025-07-09T19:39:21+00:00</updated>
		<link rel="alternate" type="text/html" href="https://devedge.github.io/posts/zfs-local-replication-with-systemd-units-timers/"/>
		<id>https://devedge.github.io/posts/zfs-local-replication-with-systemd-units-timers/</id>
    
		<content type="html" xml:base="https://devedge.github.io/posts/zfs-local-replication-with-systemd-units-timers/">&lt;p&gt;Following up the previous post on &lt;a href=&quot;https:&#x2F;&#x2F;devedge.github.io&#x2F;posts&#x2F;zfs-rolling-snapshots-with-systemd-units-timers&#x2F;&quot;&gt;creating rolling ZFS snapshots with systemd units &amp;amp; timers&lt;&#x2F;a&gt;, this entry will cover continuous replication of these snapshots to another pool on the same host, using the same strategy.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;unit-file&quot;&gt;Unit file&lt;a class=&quot;zola-anchor&quot; href=&quot;#unit-file&quot; aria-label=&quot;Anchor link for: unit-file&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;The unit file relies on snapshots having a consistent naming scheme. The names here are the ones defined in the the previous post:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;autosnapshot-7-days-ago&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;autosnapshot-6-days-ago&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;autosnapshot-1-day-ago&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Unlike the autosnapshot unit file however, this is not initialized with the pool name as an instance variable. This is because there are 2 variables: the source pool and the target pool, which would necessitate some implicit functionality - they are both defined as environment variables in the unit file instead:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;ini&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Service&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;Environment&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;REPLICATION_SOURCE=pool-1&#x2F;dataset2&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;Environment&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;REPLICATION_TARGET=pool-2&#x2F;backups&#x2F;pool-1&#x2F;dataset2&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This unit file handles rotating the snapshots on the replication target. This could be adjusted to save a different number of snapshots, but for consistency, it will match the strategy used in the autosnapshot unit file.&lt;&#x2F;p&gt;
&lt;p&gt;Lastly, the replication command needs to be wrapped in a &lt;code&gt;&#x2F;usr&#x2F;bin&#x2F;sh -c &quot;...&quot;&lt;&#x2F;code&gt; statement since the ZFS CLI requires a unix pipe to send&#x2F;receive and has no alternative. The systemd Exec* directives do not support pipes, so running it in a subshell is hacky but officially recommended (&lt;code&gt;COMMAND LINES&lt;&#x2F;code&gt; section in the &lt;code&gt;systemd.service(5)&lt;&#x2F;code&gt; manpage).&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;ini&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Service&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;ExecStart&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;usr&#x2F;bin&#x2F;sh -c &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;zfs send --raw --props -i @autosnapshot-2-days-ago ${REPLICATION_SOURCE}@autosnapshot-1-day-ago | zfs receive -Fv ${REPLICATION_TARGET}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The filename format of the unit file is:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;zfs-autoreplication-&amp;lt;dataset name&amp;gt;-&amp;lt;number of retained snapshots&amp;gt;-&amp;lt;frequency&amp;gt;.service&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;zfs-autoreplication-dataset2-7-daily-service&quot;&gt;&lt;code&gt;zfs-autoreplication-dataset2-7-daily.service&lt;&#x2F;code&gt;:&lt;a class=&quot;zola-anchor&quot; href=&quot;#zfs-autoreplication-dataset2-7-daily-service&quot; aria-label=&quot;Anchor link for: zfs-autoreplication-dataset2-7-daily-service&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;ini&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Unit&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;Description&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span&gt;Keep 7 rotating daily snapshots of pool-1&#x2F;dataset2 replicated to pool-2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;Requires&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span&gt;zfs.target&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;After&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span&gt;zfs.target&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;ConditionACPower&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span&gt;true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;ConditionPathIsDirectory&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;sys&#x2F;module&#x2F;zfs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;ConditionPathExists&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span&gt;!&#x2F;home&#x2F;gadget&#x2F;pause-replications&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Service&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;EnvironmentFile&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span&gt;-&#x2F;etc&#x2F;sysconfig&#x2F;zfs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;Type&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span&gt;exec&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;Environment&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;REPLICATION_SOURCE=pool-1&#x2F;dataset2&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;Environment&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;REPLICATION_TARGET=pool-2&#x2F;backups&#x2F;pool-1&#x2F;dataset2&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;ExecStartPre&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span&gt;-&#x2F;sbin&#x2F;zfs destroy ${REPLICATION_TARGET}@autosnapshot-7-days-ago&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;ExecStartPre&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span&gt;-&#x2F;sbin&#x2F;zfs rename ${REPLICATION_TARGET}@autosnapshot-6-days-ago ${REPLICATION_TARGET}@autosnapshot-7-days-ago&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;ExecStartPre&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span&gt;-&#x2F;sbin&#x2F;zfs rename ${REPLICATION_TARGET}@autosnapshot-5-days-ago ${REPLICATION_TARGET}@autosnapshot-6-days-ago&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;ExecStartPre&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span&gt;-&#x2F;sbin&#x2F;zfs rename ${REPLICATION_TARGET}@autosnapshot-4-days-ago ${REPLICATION_TARGET}@autosnapshot-5-days-ago&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;ExecStartPre&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span&gt;-&#x2F;sbin&#x2F;zfs rename ${REPLICATION_TARGET}@autosnapshot-3-days-ago ${REPLICATION_TARGET}@autosnapshot-4-days-ago&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;ExecStartPre&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span&gt;-&#x2F;sbin&#x2F;zfs rename ${REPLICATION_TARGET}@autosnapshot-2-days-ago ${REPLICATION_TARGET}@autosnapshot-3-days-ago&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;ExecStartPre&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span&gt;-&#x2F;sbin&#x2F;zfs rename ${REPLICATION_TARGET}@autosnapshot-1-day-ago ${REPLICATION_TARGET}@autosnapshot-2-days-ago&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;ExecStart&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;usr&#x2F;bin&#x2F;sh -c &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;zfs send --raw --props -i @autosnapshot-2-days-ago ${REPLICATION_SOURCE}@autosnapshot-1-day-ago | zfs receive -Fv ${REPLICATION_TARGET}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;timer-file&quot;&gt;Timer file&lt;a class=&quot;zola-anchor&quot; href=&quot;#timer-file&quot; aria-label=&quot;Anchor link for: timer-file&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;The timer is very simple. The &lt;code&gt;OnCalendar&lt;&#x2F;code&gt; directive is set to 5 minutes after midnight, allowing the autosnapshot service plenty of time to complete first.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;zfs-autoreplication-dataset2-7-daily-timer&quot;&gt;&lt;code&gt;zfs-autoreplication-dataset2-7-daily.timer&lt;&#x2F;code&gt;:&lt;a class=&quot;zola-anchor&quot; href=&quot;#zfs-autoreplication-dataset2-7-daily-timer&quot; aria-label=&quot;Anchor link for: zfs-autoreplication-dataset2-7-daily-timer&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;ini&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Unit&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;Description&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span&gt;Keep 7 rotating daily snapshots of pool-1&#x2F;dataset2 replicated to pool-2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Timer&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;OnCalendar&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span&gt;*-*-* 00:05:00&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;Unit&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span&gt;zfs-autoreplication-dataset2-7-daily.service&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Install&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;WantedBy&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span&gt;timers.target&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;enabling-the-service&quot;&gt;Enabling the service&lt;a class=&quot;zola-anchor&quot; href=&quot;#enabling-the-service&quot; aria-label=&quot;Anchor link for: enabling-the-service&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Unlike the autosnapshot service, the autoreplication service requires some manual preliminary setup.&lt;&#x2F;p&gt;
&lt;p&gt;First, the entire ZFS pool+dataset hierarchy needs to be created beforehand, &lt;em&gt;except&lt;&#x2F;em&gt; for the actual dataset to be replicated. In this example, &lt;code&gt;pool-1&#x2F;dataset2&lt;&#x2F;code&gt; is being replicated to &lt;code&gt;pool-2&#x2F;backups&#x2F;pool-1&#x2F;dataset2&lt;&#x2F;code&gt;, so the path to create is &lt;code&gt;pool-2&#x2F;backups&#x2F;pool-1&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; zfs&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; create&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;p&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; pool-2&#x2F;backups&#x2F;pool-1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Next, send over the very first snapshot. In this case the dataset is encrypted, so the &lt;code&gt;--raw&lt;&#x2F;code&gt; and &lt;code&gt;--props&lt;&#x2F;code&gt; flags are used to send over the dataset exactly as it exists on disk with all of its custom properties:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; zfs&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; send&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-raw&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-props&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; pool-1&#x2F;dataset2@autosnapshot-1-day-ago&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; zfs&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; receive&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;Fv&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; pool-2&#x2F;backups&#x2F;pool-1&#x2F;dataset2@autosnapshot-1-day-ago&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The reason for manually running this command is because it does not include the previous snapshot as an option (&lt;code&gt;-i&lt;&#x2F;code&gt;) - something the unit file relies on.&lt;&#x2F;p&gt;
&lt;p&gt;Finally, the autoreplication service + timer can be started:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; systemctl&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; enable&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-now&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; zfs-autoreplication-dataset2-7-daily.timer&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;hr &#x2F;&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>ZFS rolling snapshots with systemd units + timers</title>
		<published>2025-07-06T19:49:33+00:00</published>
		<updated>2025-07-06T19:49:33+00:00</updated>
		<link rel="alternate" type="text/html" href="https://devedge.github.io/posts/zfs-rolling-snapshots-with-systemd-units-timers/"/>
		<id>https://devedge.github.io/posts/zfs-rolling-snapshots-with-systemd-units-timers/</id>
    
		<content type="html" xml:base="https://devedge.github.io/posts/zfs-rolling-snapshots-with-systemd-units-timers/">&lt;p&gt;As a copy-on-write filesystem, ZFS provides the capability to take snapshots. However, taking and managing them is completely manual, so maintaining a rolling list of snapshots requires either custom bash scripts + cron, installing external tools such as sanoid, or using an entire OS in the case of TrueNAS.&lt;&#x2F;p&gt;
&lt;p&gt;However, this functionality can be easily achieved by utilizing systemd units and timers.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;unit-file&quot;&gt;Unit file&lt;a class=&quot;zola-anchor&quot; href=&quot;#unit-file&quot; aria-label=&quot;Anchor link for: unit-file&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;The goal of this unit file is to keep a week&#x27;s worth of daily snapshots. Each snapshot is named in a way that is easily referenced:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;autosnapshot-7-days-ago&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;autosnapshot-6-days-ago&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;autosnapshot-5-days-ago&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;autosnapshot-4-days-ago&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;autosnapshot-3-days-ago&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;autosnapshot-2-days-ago&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;autosnapshot-1-day-ago&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Since ZFS snapshots can be renamed, the strategy for rolling them is to delete the oldest one, rename all the subsequent ones, and take a new one.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;zfs&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; destroy&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; %I@autosnapshot-7-days-ago&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;zfs&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; rename&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; %I@autosnapshot-6-days-ago&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; %I@autosnapshot-7-days-ago&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;zfs&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; snapshot&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; %I@autosnapshot-1-day-ago&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Conveniently, systemd units have the &lt;code&gt;ExecStartPre&lt;&#x2F;code&gt; directive in the &lt;code&gt;[Service]&lt;&#x2F;code&gt; section, allowing for commands to be run before the actual target command., eg., the latest snapshot.&lt;&#x2F;p&gt;
&lt;p&gt;Additionally, it is possible to prepend the entire command with a &lt;code&gt;-&lt;&#x2F;code&gt;, which prevents the unit from failing if the command fails. This is great for a first-time run where none of the previous snapshots exist, causing the ZFS commands to fail.&lt;&#x2F;p&gt;
&lt;p&gt;Finally, this unit file has the ability to pause snapshots instantly. This is done by requiring a specific path &lt;em&gt;not&lt;&#x2F;em&gt; exist with a negated &lt;code&gt;ConditionPathExists&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;ConditionPathExists=!&#x2F;home&#x2F;gadget&#x2F;pause-snapshots&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Pausing is as simple as a &lt;code&gt;touch ~&#x2F;pause-snapshots&lt;&#x2F;code&gt;, and once the file is deleted, snapshots resume whenever the timer triggers the unit file again. This could even be used to pause multiple (or all) autosnapshots on a system if they are all pointed to the same file.&lt;&#x2F;p&gt;
&lt;p&gt;The filename format of the unit file is:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;zfs-autosnapshot-&amp;lt;number of retained snapshots&amp;gt;-&amp;lt;frequency&amp;gt;@.service&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;zfs-autosnapshot-7-daily-service&quot;&gt;&lt;code&gt;zfs-autosnapshot-7-daily@.service&lt;&#x2F;code&gt;:&lt;a class=&quot;zola-anchor&quot; href=&quot;#zfs-autosnapshot-7-daily-service&quot; aria-label=&quot;Anchor link for: zfs-autosnapshot-7-daily-service&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;ini&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Unit&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;Description&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span&gt;Keep 7 rotating snapshots of %I daily&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;Requires&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span&gt;zfs.target&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;After&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span&gt;zfs.target&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;ConditionACPower&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span&gt;true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;ConditionPathIsDirectory&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;sys&#x2F;module&#x2F;zfs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;ConditionPathExists&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span&gt;!&#x2F;home&#x2F;gadget&#x2F;pause-snapshots&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Service&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;EnvironmentFile&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span&gt;-&#x2F;etc&#x2F;sysconfig&#x2F;zfs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;Type&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span&gt;exec&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;Restart&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span&gt;no&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;ExecStartPre&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span&gt;-&#x2F;sbin&#x2F;zfs destroy %I@autosnapshot-7-days-ago&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;ExecStartPre&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span&gt;-&#x2F;sbin&#x2F;zfs rename %I@autosnapshot-6-days-ago %I@autosnapshot-7-days-ago&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;ExecStartPre&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span&gt;-&#x2F;sbin&#x2F;zfs rename %I@autosnapshot-5-days-ago %I@autosnapshot-6-days-ago&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;ExecStartPre&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span&gt;-&#x2F;sbin&#x2F;zfs rename %I@autosnapshot-4-days-ago %I@autosnapshot-5-days-ago&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;ExecStartPre&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span&gt;-&#x2F;sbin&#x2F;zfs rename %I@autosnapshot-3-days-ago %I@autosnapshot-4-days-ago&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;ExecStartPre&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span&gt;-&#x2F;sbin&#x2F;zfs rename %I@autosnapshot-2-days-ago %I@autosnapshot-3-days-ago&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;ExecStartPre&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span&gt;-&#x2F;sbin&#x2F;zfs rename %I@autosnapshot-1-day-ago %I@autosnapshot-2-days-ago&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;ExecStart&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;sbin&#x2F;zfs snapshot %I@autosnapshot-1-day-ago&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The remainder of the directives were taken from the &lt;code&gt;zfs-scrub@.service&lt;&#x2F;code&gt; bundled along with the ZFS installation on Fedora 41. No &lt;code&gt;[Install]&lt;&#x2F;code&gt; section is required since this unit file will be triggered by a timer.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;timer-file&quot;&gt;Timer file&lt;a class=&quot;zola-anchor&quot; href=&quot;#timer-file&quot; aria-label=&quot;Anchor link for: timer-file&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;The timer is even simpler, with the only customization being the &lt;code&gt;OnCalendar&lt;&#x2F;code&gt; directive set to &lt;code&gt;daily&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;h3 id=&quot;zfs-autosnapshot-7-daily-timer&quot;&gt;&lt;code&gt;zfs-autosnapshot-7-daily@.timer&lt;&#x2F;code&gt;:&lt;a class=&quot;zola-anchor&quot; href=&quot;#zfs-autosnapshot-7-daily-timer&quot; aria-label=&quot;Anchor link for: zfs-autosnapshot-7-daily-timer&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;ini&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Unit&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;Description&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span&gt;Keep 7 rotating snapshots of %I daily&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Timer&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;OnCalendar&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span&gt;daily&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;Unit&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span&gt;zfs-autosnapshot-7-daily@%i.service&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Install&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;WantedBy&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span&gt;timers.target&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;enabling-the-service&quot;&gt;Enabling the service&lt;a class=&quot;zola-anchor&quot; href=&quot;#enabling-the-service&quot; aria-label=&quot;Anchor link for: enabling-the-service&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;There&#x27;s a gotcha when trying to pass the full ZFS pool+dataset(s) path to the timer as an instance variable: a ZFS path contains invalid characters that can&#x27;t be passed on the command line - namely, forward slashes and dashes (&lt;code&gt;&#x2F;&lt;&#x2F;code&gt;, &lt;code&gt;-&lt;&#x2F;code&gt;).&lt;&#x2F;p&gt;
&lt;p&gt;Luckily, systemd has a way to handle this: &lt;code&gt;systemd-escape&lt;&#x2F;code&gt;, and the variables &lt;code&gt;%i&lt;&#x2F;code&gt; and &lt;code&gt;%I&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;First, pass the full ZFS path to &lt;code&gt;systemd-escape&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; systemd-escape&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;pool-1&#x2F;dataset2&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;pool\x2d1-dataset2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is the safely escaped ZFS path, and the timer can be enabled by using it:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; systemctl&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; enable&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-now&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;zfs-autosnapshot-7-daily@pool\x2d1-dataset2.timer&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Or in one command:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; systemctl&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; enable&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-now&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;zfs-autosnapshot-7-daily@&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;systemd-escape&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;pool-1&#x2F;dataset2&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;.timer&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The timer unit file will use &lt;code&gt;%i&lt;&#x2F;code&gt; to enable the respective unit service file with the escaped string. However, the service will use the unescaped string with &lt;code&gt;%I&lt;&#x2F;code&gt; to run the ZFS snapshot commands.&lt;&#x2F;p&gt;
&lt;p&gt;The systemd timers can be listed with:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;systemctl&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; list-timers&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And the snapshots, their creation dates, and the amount of space they use can be listed with:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; zfs&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; list&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;t&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; snapshot&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;o&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; name,creation,used&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;NAME&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;                                                        CREATION&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;                USED&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;pool-1&#x2F;dataset2@autosnapshot-7-days-ago&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;                     Sun&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Aug&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;  3&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;  0:00&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 2025&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;     0B&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;pool-1&#x2F;dataset2@autosnapshot-6-days-ago&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;                     Mon&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Aug&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;  4&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;  0:00&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 2025&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;     0B&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;pool-1&#x2F;dataset2@autosnapshot-5-days-ago&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;                     Tue&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Aug&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;  5&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;  0:00&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 2025&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;     0B&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;pool-1&#x2F;dataset2@autosnapshot-4-days-ago&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;                     Wed&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Aug&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;  6&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;  0:00&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 2025&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;   432K&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;pool-1&#x2F;dataset2@autosnapshot-3-days-ago&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;                     Thu&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Aug&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;  7&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;  0:00&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 2025&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;     0B&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;pool-1&#x2F;dataset2@autosnapshot-2-days-ago&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;                     Fri&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Aug&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;  8&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;  0:00&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 2025&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;     0B&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;pool-1&#x2F;dataset2@autosnapshot-1-day-ago&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;                      Sat&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Aug&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;  9&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;  0:00&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 2025&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;     0B&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;</content>
	</entry>
	<entry xml:lang="en">
		<title>Prometheus node_exporter on Fedora</title>
		<published>2025-05-12T23:08:58+00:00</published>
		<updated>2025-05-12T23:08:58+00:00</updated>
		<link rel="alternate" type="text/html" href="https://devedge.github.io/posts/prometheus-node-exporter-on-fedora/"/>
		<id>https://devedge.github.io/posts/prometheus-node-exporter-on-fedora/</id>
    
		<content type="html" xml:base="https://devedge.github.io/posts/prometheus-node-exporter-on-fedora/">&lt;p&gt;Prometheus provides a server-level metrics exporter &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;prometheus.io&#x2F;docs&#x2F;guides&#x2F;node-exporter&#x2F;&quot;&gt;called &lt;code&gt;node_exporter&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; that reports hardware &amp;amp; kernel-level metrics. However, I found the container deployment method in Docker to be too extreme, and there was no clear documentation for setting it up manually or any officially supported package on Fedora.&lt;&#x2F;p&gt;
&lt;p&gt;Other unofficial online resources didn&#x27;t mention working with SELinux or firewalld, so this guide outlines how to set up a basic &lt;code&gt;node_exporter&lt;&#x2F;code&gt; daemon on a Fedora 41 server.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;download-and-extraction&quot;&gt;Download and extraction&lt;a class=&quot;zola-anchor&quot; href=&quot;#download-and-extraction&quot; aria-label=&quot;Anchor link for: download-and-extraction&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Fairly straightforward, find your appropriate version &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;prometheus.io&#x2F;download&#x2F;#node_exporter&quot;&gt;on the downloads page&lt;&#x2F;a&gt; and download it:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;curl&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;JLO&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; https:&#x2F;&#x2F;github.com&#x2F;prometheus&#x2F;node_exporter&#x2F;releases&#x2F;...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;and extract it:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;tar&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;xvf&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; node_exporter-1.9.1.linux-amd64.tar.gz&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;user-creation-and-manual-installation&quot;&gt;User creation and manual installation&lt;a class=&quot;zola-anchor&quot; href=&quot;#user-creation-and-manual-installation&quot; aria-label=&quot;Anchor link for: user-creation-and-manual-installation&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Manual installation involves moving the executable to the &lt;code&gt;&#x2F;usr&#x2F;local&#x2F;bin&#x2F;&lt;&#x2F;code&gt; directory, which &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Unix_filesystem#Conventional_directory_layout&quot;&gt;is specifically for programs&lt;&#x2F;a&gt; that normal users can run.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; mv&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; node_exporter-1.9.1.linux-amd64&#x2F;node_exporter&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &#x2F;usr&#x2F;local&#x2F;bin&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Create the &lt;code&gt;node_exporter&lt;&#x2F;code&gt; user &amp;amp; group for the service account that runs the binary, and apply them to the binary. It does not need to run with any special privileges to gather metrics, and the login shell is disabled for security:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; useradd&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;rs&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &#x2F;sbin&#x2F;nologin&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; node_exporter&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; chown&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; node_exporter:node_exporter&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &#x2F;usr&#x2F;local&#x2F;bin&#x2F;node_exporter&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;systemd-unit-file&quot;&gt;Systemd unit file&lt;a class=&quot;zola-anchor&quot; href=&quot;#systemd-unit-file&quot; aria-label=&quot;Anchor link for: systemd-unit-file&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Create the systemd unit file at &lt;code&gt;&#x2F;etc&#x2F;systemd&#x2F;system&#x2F;node_exporter.service&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;ini&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Unit&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;Description&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span&gt;Node Exporter&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;After&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span&gt;network.target&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Service&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;User&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span&gt;node_exporter&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;Group&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span&gt;node_exporter&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;Type&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span&gt;exec&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;Restart&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span&gt;always&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;ExecStart&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;usr&#x2F;local&#x2F;bin&#x2F;node_exporter --&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;web.listen-address&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;0.0.0.0:9100&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Install&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;WantedBy&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span&gt;multi-user.target&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is a very simple configuration that gets &lt;code&gt;node_exporter&lt;&#x2F;code&gt; listening on all interfaces on the default port &lt;code&gt;9100&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;selinux-relabelling&quot;&gt;SELinux relabelling&lt;a class=&quot;zola-anchor&quot; href=&quot;#selinux-relabelling&quot; aria-label=&quot;Anchor link for: selinux-relabelling&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Depending on where&#x2F;how you downloaded it, the binary will likely have an incorrect SELinux label:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[gadget@trinity ~]# ls -Z &#x2F;usr&#x2F;local&#x2F;bin&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;unconfined_u:object_r:user_home_t:s0 node_exporter&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This means that attempting to start it will fail. This is the &lt;code&gt;journalctl&lt;&#x2F;code&gt; log, and you can see SELinux kicking in with the &lt;code&gt;AVC&lt;&#x2F;code&gt; line:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;May 12 17:11:45 trinity audit[569311]: AVC avc:  denied  { execute } for  pid=569311 comm=&amp;quot;(exporter)&amp;quot; name=&amp;quot;node_exporter&amp;quot; dev=&amp;quot;dm-0&amp;quot; ino=180936 scontext=system_u:system_r:init_t:s0 tcontext=unconfined_u:object_r:user_home_t:s0 tclass=file permissive=0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;May 12 17:11:45 trinity (exporter)[569311]: node_exporter.service: Unable to locate executable &amp;#39;&#x2F;usr&#x2F;local&#x2F;bin&#x2F;node_exporter&amp;#39;: Permission denied&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;May 12 17:11:45 trinity (exporter)[569311]: node_exporter.service: Failed at step EXEC spawning &#x2F;usr&#x2F;local&#x2F;bin&#x2F;node_exporter: Permission denied&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;May 12 17:11:45 trinity systemd[1]: node_exporter.service: Main process exited, code=exited, status=203&#x2F;EXEC&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;May 12 17:11:45 trinity systemd[1]: node_exporter.service: Failed with result &amp;#39;exit-code&amp;#39;.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Fixing this is easy since the binary is located in the correct directory. The &lt;code&gt;restorecon&lt;&#x2F;code&gt; command with the recursive flag (&lt;code&gt;-R&lt;&#x2F;code&gt;) will apply the parent folder&#x27;s label to its children, and &lt;code&gt;&#x2F;usr&#x2F;local&#x2F;bin&lt;&#x2F;code&gt; is already defined with a specific label:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; restorecon&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;R&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;v&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &#x2F;usr&#x2F;local&#x2F;bin&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In this case, SELinux is in &lt;code&gt;targeted&lt;&#x2F;code&gt; mode rather than &lt;code&gt;MLS&lt;&#x2F;code&gt; mode, so &lt;code&gt;unconfined_u&lt;&#x2F;code&gt; is still allowed to run:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[gadget@trinity ~]# ls -Z &#x2F;usr&#x2F;local&#x2F;bin&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;unconfined_u:object_r:bin_t:s0 node_exporter&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;open-firewall-port&quot;&gt;Open firewall port&lt;a class=&quot;zola-anchor&quot; href=&quot;#open-firewall-port&quot; aria-label=&quot;Anchor link for: open-firewall-port&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;If &lt;code&gt;firewalld&lt;&#x2F;code&gt; is enabled and running (the default), you will need to open its port to query the metrics from another host.&lt;&#x2F;p&gt;
&lt;p&gt;You can check the active &lt;code&gt;firewalld&lt;&#x2F;code&gt; zone with:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[gadget@trinity ~]$ firewall-cmd --get-active-zones&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;public (default)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then, add the port as an exception to the zone:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; firewall-cmd&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-zone=public&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-add-port=9100&#x2F;tcp&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-permanent&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; firewall-cmd&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-reload&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;start-node-exporter-and-test&quot;&gt;Start &lt;code&gt;node_exporter&lt;&#x2F;code&gt; and test&lt;a class=&quot;zola-anchor&quot; href=&quot;#start-node-exporter-and-test&quot; aria-label=&quot;Anchor link for: start-node-exporter-and-test&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Enable and start &lt;code&gt;node_exporter&lt;&#x2F;code&gt; in one line:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; systemctl&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; enable&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-now&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; node_exporter&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;and from another host, query the endpoint:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;curl&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; trinity.local:9100&#x2F;metrics&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You will be greeted by a wall of metrics:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# HELP go_gc_duration_seconds A summary of the wall-time pause (stop-the-world) duration in garbage collection cycles.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# TYPE go_gc_duration_seconds summary&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;go_gc_duration_seconds{quantile=&amp;quot;0&amp;quot;} 3.7163e-05&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;go_gc_duration_seconds{quantile=&amp;quot;0.25&amp;quot;} 8.5233e-05&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;go_gc_duration_seconds{quantile=&amp;quot;0.5&amp;quot;} 9.2137e-05&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;go_gc_duration_seconds{quantile=&amp;quot;0.75&amp;quot;} 0.000103134&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;go_gc_duration_seconds{quantile=&amp;quot;1&amp;quot;} 0.000114001&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;go_gc_duration_seconds_sum 0.001062938&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;go_gc_duration_seconds_count 12&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# HELP go_gc_gogc_percent Heap size target percentage configured by the user, otherwise 100. This value is set by the GOGC environment variable, and the runtime&#x2F;debug.SetGCPercent function. Sourced from &#x2F;gc&#x2F;gogc:percent&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# TYPE go_gc_gogc_percent gauge&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;go_gc_gogc_percent 100&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# HELP go_gc_gomemlimit_bytes Go runtime memory limit configured by the user, otherwise math.MaxInt64. This value is set by the GOMEMLIMIT environment variable, and the runtime&#x2F;debug.SetMemoryLimit function. Sourced from &#x2F;gc&#x2F;gomemlimit:bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# TYPE go_gc_gomemlimit_bytes gauge&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;go_gc_gomemlimit_bytes 9.223372036854776e+18&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# HELP go_goroutines Number of goroutines that currently exist.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# TYPE go_goroutines gauge&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;go_goroutines 7&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;resources&quot;&gt;Resources&lt;a class=&quot;zola-anchor&quot; href=&quot;#resources&quot; aria-label=&quot;Anchor link for: resources&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;prometheus.io&#x2F;docs&#x2F;guides&#x2F;node-exporter&#x2F;&quot;&gt;Prometheus Node Exporter home page&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Eliminating ESC delays in tmux, Vim and ZSH</title>
		<published>2025-05-09T17:36:40+00:00</published>
		<updated>2025-05-09T17:36:40+00:00</updated>
		<link rel="alternate" type="text/html" href="https://devedge.github.io/posts/eliminating-esc-delays-in-tmux-vim-and-zsh/"/>
		<id>https://devedge.github.io/posts/eliminating-esc-delays-in-tmux-vim-and-zsh/</id>
    
		<content type="html" xml:base="https://devedge.github.io/posts/eliminating-esc-delays-in-tmux-vim-and-zsh/">&lt;p&gt;For a while, I had vaguely noticed an odd delay whenever I pressed &lt;code&gt;ESC&lt;&#x2F;code&gt; in vim. It was not until I started using vim inside tmux that the delay became very obvious. After some quick research, it turned out this was an intentional feature of both programs (and certainly many more).&lt;&#x2F;p&gt;
&lt;p&gt;To cut a long story short, a number of key sequences that your keyboard transmits are actually a combination of &lt;code&gt;ESC&lt;&#x2F;code&gt; and a letter on your keyboard for historical reasons (known as an &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;ANSI_escape_code&quot;&gt;&lt;code&gt;escape squence&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;). As a result, older computers could have trouble telling the difference between them and a really fast typist. Programs such as tmux and vim get around this by adding an artifical delay any time the &lt;code&gt;ESC&lt;&#x2F;code&gt; key is pressed, so it remains slower then when it is used as an escape sequence.&lt;&#x2F;p&gt;
&lt;p&gt;Of course, these limitations rarely apply to modern computers anymore. Unless you&#x27;re on a network connection with crazy latency, this is not an issue. The following are the settings to adjust in tmux, vim, and zsh to reduce this delay:&lt;&#x2F;p&gt;
&lt;h2 id=&quot;tmux-escape-time&quot;&gt;tmux &lt;code&gt;escape-time&lt;&#x2F;code&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#tmux-escape-time&quot; aria-label=&quot;Anchor link for: tmux-escape-time&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Despite a lot of common advice, you should avoid setting the delay time to zero. Even though internet latency in general has never been shorter, the delay between characters is still not zero and can &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;superuser.com&#x2F;a&#x2F;1809494&quot;&gt;lead to strange problems&lt;&#x2F;a&gt; if you set it that low.&lt;&#x2F;p&gt;
&lt;p&gt;I generally keep all of the combined delays to a value that is barely noticeable, often not perceptible at all. Anything above 100ms is annoying for me, and I currently keep the combined delay values across all 3 tools to 25ms.&lt;&#x2F;p&gt;
&lt;p&gt;For tmux, this means setting the delay to 5ms in &lt;code&gt;~&#x2F;.tmux.conf&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;set -g escape-time 5&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;vim-timeoutlen-ttimeoutlen&quot;&gt;Vim &lt;code&gt;timeoutlen&lt;&#x2F;code&gt;, &lt;code&gt;ttimeoutlen&lt;&#x2F;code&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#vim-timeoutlen-ttimeoutlen&quot; aria-label=&quot;Anchor link for: vim-timeoutlen-ttimeoutlen&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;vim has two settings for controlling delays. However by default, only one, &lt;code&gt;timeoutlen&lt;&#x2F;code&gt;, is used to set a delay of 1000ms (1 second) for both mappings and for the delays between escape sequences. Since mappings are deliberate sequences of characters that you (usually) can&#x27;t start typing in less than 10ms, it makes sense to keep that one at 1000ms (or longer if needed). This leaves us with the second option &lt;code&gt;ttimeoutlen&lt;&#x2F;code&gt;, which we can set to a much lower value in &lt;code&gt;~&#x2F;.vimrc&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;set timeoutlen=1000 ttimeoutlen=10&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;zsh-keytimeout&quot;&gt;ZSH &lt;code&gt;KEYTIMEOUT&lt;&#x2F;code&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#zsh-keytimeout&quot; aria-label=&quot;Anchor link for: zsh-keytimeout&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Your shell will also have a delay for escape sequences. Since I use zsh, I set this in my &lt;code&gt;~&#x2F;.zshrc&lt;&#x2F;code&gt; file:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;KEYTIMEOUT&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This value is in &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;zsh.sourceforge.io&#x2F;Doc&#x2F;Release&#x2F;Parameters.html#Parameters-Used-By-The-Shell-1&quot;&gt;hundredths of a second&lt;&#x2F;a&gt;, so a value of 1 will result in a 10ms delay.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;resources&quot;&gt;Resources&lt;a class=&quot;zola-anchor&quot; href=&quot;#resources&quot; aria-label=&quot;Anchor link for: resources&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;unix.stackexchange.com&#x2F;a&#x2F;608179&quot;&gt;An excellent historical breakdown on the origin of escape sequences&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;superuser.com&#x2F;a&#x2F;1809494&quot;&gt;Cautionary warning against setting escape delay times to zero&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Writing tmux scrollback to file</title>
		<published>2025-05-03T22:55:37+00:00</published>
		<updated>2025-05-03T22:55:37+00:00</updated>
		<link rel="alternate" type="text/html" href="https://devedge.github.io/posts/writing-tmux-scrollback-to-file/"/>
		<id>https://devedge.github.io/posts/writing-tmux-scrollback-to-file/</id>
    
		<content type="html" xml:base="https://devedge.github.io/posts/writing-tmux-scrollback-to-file/">&lt;p&gt;Occasionally, I&#x27;ll be running a command in tmux that prints a lot of output - then realize midway that I&#x27;d like to save it for further inspection (eg., bootloader recompilation errors on system upgrade).&lt;&#x2F;p&gt;
&lt;p&gt;After digging around for a while, I found an excellent starting point &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;unix.stackexchange.com&#x2F;a&#x2F;26568&quot;&gt;on StackOverflow&lt;&#x2F;a&gt; and modified it:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;bind-key&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;T&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; copy-mode-vi&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; S&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; command-prompt&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt;    -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;p&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Save scrollback (start at cursor):&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt;    -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;I&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;.&#x2F;tmuxscrollback-history-#{t|f|%%Y%%m%%d%%H%%M%%S:client_activity}.txt&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt;    -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;F&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;capture-pane -S #{e|*:-1,#{e|-:#{scroll_position},#{copy_cursor_y}}} ; save-buffer %1 ; delete-buffer&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;To use this:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;jump into copy mode (Vi) with &lt;code&gt;&amp;lt;TMUX PREFIX&amp;gt; [&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;scroll up however far as needed&lt;&#x2F;li&gt;
&lt;li&gt;leave the cursor at the line where the scrollback should start&lt;&#x2F;li&gt;
&lt;li&gt;type &lt;code&gt;SHIFT s&lt;&#x2F;code&gt;, and either use the default timestamped filename or overwrite it with a custom one&lt;&#x2F;li&gt;
&lt;li&gt;hit &lt;code&gt;&amp;lt;ENTER&amp;gt;&lt;&#x2F;code&gt; to save to the file&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The command automatically calculates the scrollback position and the cursor offset to pick the starting line, and writes everything from that point on downwards to the target file.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;command-breakdown&quot;&gt;Command breakdown&lt;a class=&quot;zola-anchor&quot; href=&quot;#command-breakdown&quot; aria-label=&quot;Anchor link for: command-breakdown&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Bind &lt;code&gt;S&lt;&#x2F;code&gt; (capital s) in Vi copy mode &amp;amp; prompt for a filename:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;bind-key -T copy-mode-vi S command-prompt -p &amp;#39;Save scrollback (start at cursor):&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Autogenerate a default filename with an instant timestamp. The &lt;code&gt;client_activity&lt;&#x2F;code&gt; event was picked because it continues to update as the user interacts with tmux, rather than something like &lt;code&gt;buffer_created&lt;&#x2F;code&gt; which would not update when taking multiple scrollback saves. Use tmux string formatting (can be found under &lt;code&gt;FORMATS&lt;&#x2F;code&gt; section in the manpage, or on &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;tmux&#x2F;tmux&#x2F;wiki&#x2F;Formats&quot;&gt;the official Wiki&lt;&#x2F;a&gt;) to generate a &lt;code&gt;YearMonthDayHourMinuteSecond&lt;&#x2F;code&gt; timestamp.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-I &amp;#39;.&#x2F;tmuxscrollback-history-#{t|f|%%Y%%m%%d%%H%%M%%S:client_activity}.txt&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The command that the &lt;code&gt;command-prompt&lt;&#x2F;code&gt; directive will execute. The &lt;code&gt;-F&lt;&#x2F;code&gt; flag is required for the calculation of the scrollback offset defined in the next section, and the &lt;code&gt;-S&lt;&#x2F;code&gt; flag sets the starting line number.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-F &amp;#39;capture-pane -S&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Calculate the offset. First, the entire calculation is multplied by &lt;code&gt;-1&lt;&#x2F;code&gt; to provide a negative offset into the scroll buffer. &lt;code&gt;#{e&lt;&#x2F;code&gt; marks this as an execution block, and the &lt;code&gt;*&lt;&#x2F;code&gt; (after the &lt;code&gt;|&lt;&#x2F;code&gt; delineator) marks the mathematical operation that will happen between the next 2 values, which are specified after the &lt;code&gt;:&lt;&#x2F;code&gt; (&lt;code&gt;-1&lt;&#x2F;code&gt; and the offset).&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#{e|*:-1, ... }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The offset is calculated by subtracting the scrollback position into the pane history from the cursor offset in the currently visible pane. These two variables are defined as:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;#{scroll_position}&lt;&#x2F;code&gt; the scrollback position during copy mode. This is anchored against the top of the tmux pane, and is zero-indexed when copy mode is initialized at the very bottom of the scrollback history.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;#{copy_cursor_y}&lt;&#x2F;code&gt; the cursor offset, which is zero-indexed against the top of the currently visible tmux pane.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The &lt;code&gt;scroll_position&lt;&#x2F;code&gt; is the larger value unless the user does not scroll up. This makes the multiplication by &lt;code&gt;-1&lt;&#x2F;code&gt; a much better choice than prepending the equation with a minus sign: the cursor offset &lt;code&gt;copy_cursor_y&lt;&#x2F;code&gt; reduces the starting line position &lt;em&gt;except&lt;&#x2F;em&gt; when the pane has not been scrolled up, which instead results in a positive value.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;... #{e|-:#{scroll_position},#{copy_cursor_y}} ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Save the buffer that was just calculated into the filename, using the variable &lt;code&gt;%1&lt;&#x2F;code&gt;. Then, clear it so it doesn&#x27;t linger in the user&#x27;s copy buffer.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; ; save-buffer %1 ; delete-buffer&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;resources&quot;&gt;Resources&lt;a class=&quot;zola-anchor&quot; href=&quot;#resources&quot; aria-label=&quot;Anchor link for: resources&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;tmux&#x2F;tmux&#x2F;wiki&quot;&gt;tmux official Wiki&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;tmux&#x2F;tmux&#x2F;wiki&#x2F;Formats&quot;&gt;tmux Wiki FORMATS&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>Creating ED25519 GPG keys to sign Git commits</title>
		<published>2024-12-27T16:14:30+00:00</published>
		<updated>2024-12-27T16:14:30+00:00</updated>
		<link rel="alternate" type="text/html" href="https://devedge.github.io/posts/creating-ed25519-gpg-keys-to-sign-git-commits/"/>
		<id>https://devedge.github.io/posts/creating-ed25519-gpg-keys-to-sign-git-commits/</id>
    
		<content type="html" xml:base="https://devedge.github.io/posts/creating-ed25519-gpg-keys-to-sign-git-commits/">&lt;p&gt;Git provides the ability to sign your commits with a GPG key. I felt this could be a fun thing to start doing, and since I&#x27;ve had trouble finding simple guides for doing this specifically with ed25519 keys, I&#x27;m writing my own.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;&lt;em&gt;If you&#x27;re just looking for a quick summary of the commands, here they are:&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;export&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; KEYUID&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Firstname Lastname (username) &amp;lt;firstname.lastname@email.com&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;gpg&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-quick-generate-key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;KEYUID&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; ed25519&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; cert&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; never&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;gpg&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-quick-add-key&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; KEYFINGERPRINTFROMABOVE&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; ed25519&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; sign&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; 5y&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;git&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; config&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-local&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; user.signingkey&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; username&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;git&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; config&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-local&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; commit.gpgsign&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;installation-prerequisites&quot;&gt;Installation prerequisites&lt;a class=&quot;zola-anchor&quot; href=&quot;#installation-prerequisites&quot; aria-label=&quot;Anchor link for: installation-prerequisites&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;My development environment is a Macbook Pro, so your milage may vary depending on the system you&#x27;re using. You&#x27;ll need to install 2 items, &lt;code&gt;gnupg&lt;&#x2F;code&gt; and &lt;code&gt;pinentry&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;brew&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; install&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; gnupg&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; pinentry-mac&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;While the first is self-evident, &lt;code&gt;pinentry&lt;&#x2F;code&gt; is not - and unfortunately, if it is not installed, the errors you might run into are incomprehensible:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;error: gpg failed to sign the data:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[GNUPG:] KEY_CONSIDERED 55BE5089F634003042AE70985E88702C976C97B1 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[GNUPG:] BEGIN_SIGNING H10&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[GNUPG:] PINENTRY_LAUNCHED 60797 curses 1.3.1 - alacritty - - 501&#x2F;20 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;gpg: signing failed: Inappropriate ioctl for device&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[GNUPG:] FAILURE sign 83918950&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;gpg: signing failed: Inappropriate ioctl for device&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;fatal: failed to write commit object&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;From what I have found, the regular TTY is insecure for entering passwords, so GnuPG has developed their own alternative (GnuPG architecture diagram &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;www.gnupg.org&#x2F;documentation&#x2F;manuals&#x2F;gnupg&#x2F;Component-interaction.html#Component-interaction&quot;&gt;found here&lt;&#x2F;a&gt;). However, I&#x27;ve found a lot of users reporting usability problems with this tool, especially over SSH, so I&#x27;ll include a section on bypassing it altogether.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;configuring-gnupg-to-use-pinentry&quot;&gt;Configuring &lt;code&gt;gnupg&lt;&#x2F;code&gt; to use &lt;code&gt;pinentry&lt;&#x2F;code&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#configuring-gnupg-to-use-pinentry&quot; aria-label=&quot;Anchor link for: configuring-gnupg-to-use-pinentry&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;In &lt;code&gt;~&#x2F;.gnupg&#x2F;gpg.conf&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;use-agent&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;and in &lt;code&gt;~&#x2F;.gnupg&#x2F;gpg-agent.conf&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;pinentry-program &#x2F;opt&#x2F;homebrew&#x2F;bin&#x2F;pinentry-mac&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You can choose to cache it in macOS&#x27; Keychain so it does not need to be entered repeatedly.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;bypassing-pinentry-entirely&quot;&gt;Bypassing &lt;code&gt;pinentry&lt;&#x2F;code&gt; entirely&lt;a class=&quot;zola-anchor&quot; href=&quot;#bypassing-pinentry-entirely&quot; aria-label=&quot;Anchor link for: bypassing-pinentry-entirely&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;In &lt;code&gt;~&#x2F;.gnupg&#x2F;gpg.conf&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;use-agent&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;pinentry-mode loopback&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;and in &lt;code&gt;~&#x2F;.gnupg&#x2F;gpg-agent.conf&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;allow-loopback-pinentry&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;These instructions were found online here: &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;d.sb&#x2F;2016&#x2F;11&#x2F;gpg-inappropriate-ioctl-for-device-errors&quot;&gt;https:&#x2F;&#x2F;d.sb&#x2F;2016&#x2F;11&#x2F;gpg-inappropriate-ioctl-for-device-errors&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;And then run the following to let &lt;code&gt;gpg-agent&lt;&#x2F;code&gt; pick up the configurations:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;echo&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; RELOADAGENT&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; gpg-connect-agent&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;generating-the-gpg-keys&quot;&gt;Generating the GPG keys&lt;a class=&quot;zola-anchor&quot; href=&quot;#generating-the-gpg-keys&quot; aria-label=&quot;Anchor link for: generating-the-gpg-keys&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Many guides still show how to generate RSA keys. However, the modern alternative for a while has been ED25519. To use it, run:&lt;&#x2F;p&gt;
&lt;h3 id=&quot;master-key&quot;&gt;Master key&lt;a class=&quot;zola-anchor&quot; href=&quot;#master-key&quot; aria-label=&quot;Anchor link for: master-key&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;gpg&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-quick-generate-key&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;lt;User ID&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; ed25519&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; cert&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; never&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This generates a Certify-only (&lt;code&gt;cert&lt;&#x2F;code&gt;) &lt;code&gt;ed25519&lt;&#x2F;code&gt; key that &lt;code&gt;never&lt;&#x2F;code&gt; expires.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;code&gt;&amp;lt;User ID&amp;gt;&lt;&#x2F;code&gt; can generally be anything. The standard format follows the convention of:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;Your Name (comment) &amp;lt;your.email@address.com&amp;gt;&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;p&gt;However, keep in mind that for commits to appear as valid on websites such as Github, you need to include an email that matches one of your verified Github emails. The angle brackets surrounding the email (&lt;code&gt;&amp;lt; &amp;gt;&lt;&#x2F;code&gt;) are required.&lt;&#x2F;p&gt;
&lt;p&gt;Once you hit Enter, it&#x27;ll ask you to provide a password. If you followed the configuration steps in the first section, it&#x27;ll only ask for it once, so be sure to type&#x2F;paste it correctly.&lt;&#x2F;p&gt;
&lt;p&gt;GPG will then print the new key:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;pub   ed25519 2024-12-20 [C]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      55BE5089F634003042AE70985E88702C976C97B1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;uid           [ultimate] Firstname Lastname (username) &amp;lt;firstname.lastname@email.com&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;code&gt;[C]&lt;&#x2F;code&gt; stands for Certify. Generally, since GPG relies on a &#x27;web of trust&#x27; where people hold onto your key for a long time, you want your root level key to rarely expire. It will also have no abilities, existing solely to sign subkeys that you actually use for day-to-day work.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;signing-key&quot;&gt;Signing key&lt;a class=&quot;zola-anchor&quot; href=&quot;#signing-key&quot; aria-label=&quot;Anchor link for: signing-key&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h3&gt;
&lt;p&gt;The signing key is a subkey of the master key, and they are both logically considered part of the same GPG key.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;gpg&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-quick-add-key&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; 55BE5089F634003042AE70985E88702C976C97B1&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; ed25519&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; sign&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; 5y&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This generates a Sign-only (&lt;code&gt;sign&lt;&#x2F;code&gt;) &lt;code&gt;ed25519&lt;&#x2F;code&gt; key that expires in 5 years (&lt;code&gt;5y&lt;&#x2F;code&gt;). The &lt;code&gt;55BE5...&lt;&#x2F;code&gt; string is the master key&#x27;s full fingerprint, which was printed above.&lt;&#x2F;p&gt;
&lt;p&gt;To continue signing after this time has passed, you&#x27;ll need to generate a new subkey again with the master key. The idea behind this is that if you&#x27;ve had your key copied&#x2F;stolen somehow, it can&#x27;t be used forever.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;note-on-ed25519-encryption&quot;&gt;&lt;em&gt;Note on ed25519 encryption&lt;&#x2F;em&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#note-on-ed25519-encryption&quot; aria-label=&quot;Anchor link for: note-on-ed25519-encryption&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h4&gt;
&lt;p&gt;Adding an encryption key involves a very small change: instead of &lt;code&gt;ed25519&lt;&#x2F;code&gt;, you&#x27;ll need to specify &lt;code&gt;cv25519&lt;&#x2F;code&gt; for the encryption algorithm:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;gpg&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-quick-add-key&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; 55BE5089F634003042AE70985E88702C976C97B1&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; cv25519&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; encr&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; 5y&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;listing-keys&quot;&gt;Listing keys&lt;a class=&quot;zola-anchor&quot; href=&quot;#listing-keys&quot; aria-label=&quot;Anchor link for: listing-keys&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;While there&#x27;s numerous ways to list your keys, I&#x27;ve found that you generally don&#x27;t need to worry about most of them. Regardless of how many subkeys your GPG key has, referencing either the master key&#x27;s ID or any part of your UID will allow GPG to pick the appropriate subkey. If you have multiple subkeys with the same function, GPG picks the most recently created one.&lt;&#x2F;p&gt;
&lt;p&gt;However, here&#x27;s a few I&#x27;ve found useful:&lt;&#x2F;p&gt;
&lt;p&gt;The default:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ gpg --list-keys username&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[keyboxd]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;---------&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;pub   ed25519 2024-12-20 [C]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      55BE5089F634003042AE70985E88702C976C97B1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;uid           [ultimate] Firstname Lastname (username) &amp;lt;firstname.lastname@email.com&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;sub   ed25519 2024-12-20 [S] [expires: 2029-12-19]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;sub   cv25519 2024-12-29 [E] [expires: 2029-12-28]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Same as above, but with the master key ID split into 4-character chunks:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ gpg --fingerprint username&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;pub   ed25519 2024-12-20 [C]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      55BE 5089 F634 0030 42AE  7098 5E88 702C 976C 97B1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;uid           [ultimate] Firstname Lastname (username) &amp;lt;firstname.lastname@email.com&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;sub   ed25519 2024-12-20 [S] [expires: 2029-12-19]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;sub   cv25519 2024-12-29 [E] [expires: 2029-12-28]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You can also go all-out and list each of the subkey fingerprints:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ gpg --list-keys --with-subkey-fingerprints --keyid-format=LONG username&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;pub   ed25519&#x2F;5E88702C976C97B1 2024-12-20 [C]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      55BE5089F634003042AE70985E88702C976C97B1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;uid                 [ultimate] Firstname Lastname (username) &amp;lt;firstname.lastname@email.com&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;sub   ed25519&#x2F;882630A8E2F9526B 2024-12-20 [S] [expires: 2029-12-19]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      AE9E8E56437D11587FAFE840882630A8E2F9526B&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;sub   cv25519&#x2F;258ADE692963C5B3 2024-12-29 [E] [expires: 2029-12-28]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      1C3C6C37E6E0248E5B54C0E8258ADE692963C5B3&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Finally, to export your public key in ASCII plaintext to share, run:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ gpg --armor --export username&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-----BEGIN PGP PUBLIC KEY BLOCK-----&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;mDMEZ2TErhYJKwYBBAHaRw8BAQdAzgjB3r552mWBwNhcdGZ+2G48SnhSoTWr5CzK&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;QfXxHre0O1JpY2hhcmQgSC4gUGFqZXJza2kgSUkgKGRldmVkZ2UpIDxyaWNoYXJk&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;LnBqc2tpMkBwcm90b24ubWU+iJMEExYKADsWIQRVvlCJ9jQAMEKucJheiHAsl2yX&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;sQUCZ2TIwwIbAQULCQgHAgIiAgYVCgkICwIEFgIDAQIeBwIXgAAKCRBeiHAsl2yX&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;sTMKAQCcrv1D1M8pWFnpTA+SSCZxK1RVk9x&#x2F;CUit2Hv+1oPPbQEAnIgqoryLxrkh&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;wtt+OifSZzzhdN7qvcmJQbvkoq2MRwq4MwRnZMgtFgkrBgEEAdpHDwEBB0BA8iAQ&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;7zCdTB5&#x2F;7HFzWXbbCUndzykTezhkpksoqtTH9Yj1BBgWCgAmFiEEVb5QifY0ADBC&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;rnCYXohwLJdsl7EFAmdkyC0CGwIFCQlmAYAAgQkQXohwLJdsl7F2IAQZFgoAHRYh&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;BK6ejlZDfRFYf6&#x2F;oQIgmMKji+VJrBQJnZMgtAAoJEIgmMKji+VJrb+UA&#x2F;iIF0zAc&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;LFKQbhzP6lY8GHfKd5mWKk2pjqG3E8HAErPlAP9MxH+qIF3FlpQB95Kog&#x2F;oUh3EI&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;hX9M+helqM8mMhGBBv9dAQCl2jqJrrJY9py53LejlLZ0pzTwDQA7FdzoHWz&#x2F;UJF7&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;+QEAosZC3I3kQD&#x2F;pmIzupZbwROyDjYp4utqlPOS3uCC4PQi4OARncU&#x2F;0EgorBgEE&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;AZdVAQUBAQdA3Bs&#x2F;kDcYB3WVD+V2uk7L5w0968NSvgjmpPgMrv1ScBkDAQgHiH4E&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;GBYKACYWIQRVvlCJ9jQAMEKucJheiHAsl2yXsQUCZ3FP9AIbDAUJCWYBgAAKCRBe&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;iHAsl2yXsU12AP46i6XmHRcWJY6vMI36F0LLXfe&#x2F;IyaFNFI28vA4iQeV&#x2F;AEAvqAi&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;5&#x2F;yO7vn&#x2F;NItgMIfqC84ZeDirypv7f3y3LQq3xwU=&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;=ubLP&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-----END PGP PUBLIC KEY BLOCK-----&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Or directly exported to a file:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;gpg&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-armor&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-export&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-output&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; username.asc&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; username&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;signing-commits-with-them&quot;&gt;Signing commits with them&lt;a class=&quot;zola-anchor&quot; href=&quot;#signing-commits-with-them&quot; aria-label=&quot;Anchor link for: signing-commits-with-them&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;A good idea to ensure you never forget to sign commits is to run the command:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;git&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; config&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-local&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; commit.gpgsign&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;in the root directory of your git repository. This will add a configuration entry in &lt;code&gt;.git&#x2F;config&lt;&#x2F;code&gt; for that repo, automatically requiring a signature for every commit. This is more convenient than having to manually type the &lt;code&gt;-S&lt;&#x2F;code&gt; flag to sign every &lt;code&gt;git commit&lt;&#x2F;code&gt; as a one-off.&lt;&#x2F;p&gt;
&lt;p&gt;To specify your new key for that repository, run one of the following:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; some part of the UID&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;git&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; config&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-local&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; user.signingkey&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; username&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; a different example using the email instead&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;git&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; config&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-local&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; user.signingkey&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; firstname.lastname@email.com&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You could also (confusingly) specify the key fingerprint or full key ID of either the master key or the signing key:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; master key fingerprint (last 16 characters of full key ID)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;git&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; config&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-local&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; user.signingkey&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; 5E88702C976C97B1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; full master key ID&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;git&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; config&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-local&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; user.signingkey&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; 55BE5089F634003042AE70985E88702C976C97B1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; or likewise for the signing key:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;git&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; config&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-local&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; user.signingkey&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; 882630A8E2F9526B&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;git&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; config&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-local&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; user.signingkey&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; AE9E8E56437D11587FAFE840882630A8E2F9526B&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;GPG will automatically pick the signing key you created. If you have multiple, it appears to use the most recently created one.&lt;&#x2F;p&gt;
&lt;p&gt;If you want to use this key globally for every repository on your machine, replace the &lt;code&gt;--local&lt;&#x2F;code&gt; flag with &lt;code&gt;--global&lt;&#x2F;code&gt;. This will place the configuration options in your home directory instead, inside &lt;code&gt;~&#x2F;.gitconfig&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;resources&quot;&gt;Resources&lt;a class=&quot;zola-anchor&quot; href=&quot;#resources&quot; aria-label=&quot;Anchor link for: resources&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;git-scm.com&#x2F;book&#x2F;en&#x2F;v2&#x2F;Git-Tools-Signing-Your-Work&quot;&gt;Git guide to signing your work&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;docs.github.com&#x2F;en&#x2F;authentication&#x2F;managing-commit-signature-verification&#x2F;generating-a-new-gpg-key&quot;&gt;Github guide to using your GPG key with Github&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;d.sb&#x2F;2016&#x2F;11&#x2F;gpg-inappropriate-ioctl-for-device-errors&quot;&gt;Fixing GPG &quot;Inappropriate ioctl for device&quot; errors&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;velvetcache.org&#x2F;2023&#x2F;03&#x2F;26&#x2F;a-peek-inside-pinentry&#x2F;&quot;&gt;Guide for &lt;code&gt;pinentry-mac&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;ertt.ca&#x2F;blog&#x2F;2022&#x2F;01-10-git-gpg-ssh&#x2F;&quot;&gt;Another article covering a slightly different solution to signing commits over ssh&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
	</entry>
	<entry xml:lang="en">
		<title>New site, new beginnings</title>
		<published>2024-12-22T17:47:23+00:00</published>
		<updated>2024-12-22T17:47:23+00:00</updated>
		<link rel="alternate" type="text/html" href="https://devedge.github.io/posts/new-site-new-beginnings/"/>
		<id>https://devedge.github.io/posts/new-site-new-beginnings/</id>
    
		<content type="html" xml:base="https://devedge.github.io/posts/new-site-new-beginnings/">&lt;p&gt;As you may have noticed, this site has a very different look.&lt;&#x2F;p&gt;
&lt;p&gt;This has been a long time coming, as I had many problems with the previous Jekyll framework that this blog was built on. This often held me back from detailing the in-depth work I&#x27;ve always been doing, and as we move into the new year, I look forward to utilizing this new site much more.&lt;&#x2F;p&gt;
&lt;p&gt;As for the previous posts: I will eventually bring them back, in one form or another. Looking back on them, there&#x27;s a lot to be improved - some will stay as-is as a reminder of where I&#x27;ve come, but others will be completely reworked.&lt;&#x2F;p&gt;
&lt;p&gt;The reason is that this site&#x27;s purpose has always been threefold:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;A personal technical reference guide, accessible from anywhere&lt;&#x2F;li&gt;
&lt;li&gt;Detailed guides on specific tools or processes that I can link to people during discussions, which is much easier than working off of (an often spotty) recollection&lt;&#x2F;li&gt;
&lt;li&gt;An archive of the breadth and depth of my technical expertise that I can look back on as a reference, better than any resume&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;As a result, they will be molded to better fit these goals.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-is-this-running-on&quot;&gt;What is this running on?&lt;a class=&quot;zola-anchor&quot; href=&quot;#what-is-this-running-on&quot; aria-label=&quot;Anchor link for: what-is-this-running-on&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;This blog is built using a NodeJS framework called &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;hexo.io&#x2F;&quot;&gt;hexo&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Specifically, I&#x27;m running a modified version of the &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;probberechts.github.io&#x2F;hexo-theme-cactus&#x2F;&quot;&gt;Cactus theme&lt;&#x2F;a&gt; (&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;probberechts&#x2F;hexo-theme-cactus&quot;&gt;github&lt;&#x2F;a&gt;), with a number of personal changes.&lt;&#x2F;p&gt;
&lt;p&gt;These are:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Removed all tracking &amp;amp; analytics from the codebase (Google&#x2F;Baidu&#x2F;Cloudflare&#x2F;Umami Analytics)&lt;&#x2F;li&gt;
&lt;li&gt;Removed the commenting frameworks (Disqus&#x2F;Utterances)&lt;&#x2F;li&gt;
&lt;li&gt;Used &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;www.nordtheme.com&#x2F;&quot;&gt;Nord Theme&lt;&#x2F;a&gt; as a color reference to create a new color style&lt;&#x2F;li&gt;
&lt;li&gt;Designed a new icon&#x2F;favicon, fitting with a more polar&#x2F;edge-like theme&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;the-future&quot;&gt;The future&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-future&quot; aria-label=&quot;Anchor link for: the-future&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;There&#x27;s a lot in store for the future. For starters:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Setup and integration of the Hexo search extension to make finding content much easier&lt;&#x2F;li&gt;
&lt;li&gt;Dedicated styling to mark specific sections of posts as &#x27;out-of-date&#x27;, or &#x27;updated&#x27;&lt;&#x2F;li&gt;
&lt;li&gt;The introduction of a new special category, &#x27;living posts&#x27; of sorts, where certain items will always be considered in flux (think configurations or running services)&lt;&#x2F;li&gt;
&lt;li&gt;Auto dark mode&#x2F;light mode switching based on time of day&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This is in addition to an ever-growing backlog of (at least) a couple dozen individual topics that have been patiently waiting in my Notes and Reminders to be brought to life.&lt;&#x2F;p&gt;
&lt;p&gt;Happy new year!&lt;&#x2F;p&gt;
</content>
	</entry>
</feed>
