Hugo ReevesStudent software developer.
Software Engineering '24 @ University of Canterbury.
[NixOS](https://nixos.org/) user and Package Maintainer.
Currently building an open-source finance tool called [EARL](./projects/earl/devlog-01/).
Content licensed under [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/).
Zola2021-02-05T11:45:00+12:00https://hugoreeves.com/atom.xmlNotes on Martin Fowler's: The Many Meanings of Event-Driven Architecture2021-02-05T11:45:00+12:002021-02-05T11:45:00+12:00https://hugoreeves.com/notes/2021/the-many-meanings-of-event-driven-architecture/<h1 id="overview">Overview</h1>
<p><strong>Notes Taken: 2021-01-28</strong></p>
<p><a rel="noopener" target="_blank" href="https://www.youtube.com/watch?v=STKCRSUsyP0">GOTO 2017 • The Many Meanings of Event-Driven Architecture • Martin Fowler</a></p>
<p>Martin explains there are several different understandings of what Event-Driven Architecture is. All of these are valid but are distinct in their actual form. Martin delves into four of these.</p>
<p>At a high level, there is a difference between events and commands.
Events explain, 'something <strong>has</strong> happened', the receiver is free to ignore the event or do something in response to the event occurring.
Commands explain, 'something <strong>should</strong> happen', the producer of the command has to know what command to issue.
Events and commands are both valid, the disadvantage of commands is that the producer has to know which system wants to react to a command, and the producer must issue the appropriate command - arguably this creates more coupling.</p>
<p>The four patterns of Event-Driven Architecture:</p>
<ol>
<li>Event Notification</li>
<li>Event Carried State Transfer</li>
<li>Event Sourcing</li>
<li>CQRS (Command Query Responsibility Segregation)</li>
</ol>
<h1 id="patterns">Patterns</h1>
<h2 id="pattern-1-event-notification">Pattern 1: Event Notification</h2>
<p><a rel="noopener" target="_blank" href="https://www.youtube.com/watch?v=STKCRSUsyP0&t=200s">Timecode - 3:20</a></p>
<p>Martin pictures a system where a user changes their address in the <strong>Customer Management System</strong>, this should cause the <strong>Insurance Quoting System</strong> to calculate a new quote for the customer. In a classic model, the customer management system must call out to the Insurance Quoting System to order a requote. This creates a strong coupling, in particular the Customer Management System is dependent on the Insurance Quoting System. This is likely suboptimal as the Insurance Quoting System is a more specialised and less general system than the Customer Management System; Martin argues dependencies should usually be drawn from specialised systems to more general systems. Instead of calling from the Customer Management System to the Insurance Quoting System, the Customer Management System could publish an event 'CustomerAddressChange' to a queue, and the Insurance Quoting System could listen for these events and requote the customer when it receives the event. This effectively alters a coupling of '<em>Customer Management System -> Insurance Quoting System</em>' into <em>Customer Management System -> Event Queue <- Insurance Quoting System</em>.
This is the most basic of event architectures, it simply alters the way dependencies can be drawn.</p>
<h2 id="pattern-2-event-carried-state-transfer">Pattern 2: Event Carried State Transfer</h2>
<p><a rel="noopener" target="_blank" href="https://www.youtube.com/watch?v=STKCRSUsyP0&t=893s">Timecode - 14:53</a></p>
<p>A less common pattern. Built atop Event Notification, when we receive an event, we pull the data from the Customer Management System and store the relevant parts in our own database. This means the Insurance Quoting System can stay available, even when the Customer Management System goes down. The problem is we now have to copies of data so we lose consistency.</p>
<h2 id="pattern-3-event-sourcing">Pattern 3: Event Sourcing</h2>
<p><a rel="noopener" target="_blank" href="https://www.youtube.com/watch?v=STKCRSUsyP0&t=1251s">Timecode - 20:51</a></p>
<p>The previous two patterns are largely still CRUD, when we make a change, we save it to a database, <strong>overwriting</strong> the previous value and maybe publishing an event.
Event Sourcing changes this, we both overwrite the current state but we also log an event to an event log.
We now have a system with two forms of state, the <strong>application state</strong> and the <strong>event log</strong>.
The application state is the point in time state, which can be recovered from the <strong>event log</strong>.
The standard for an event sourcing system, is that at any point in time the application state can be destroyed and we can <strong>reliably recover</strong> from the <strong>event log</strong>.
In Event Sourcing, we move from being oriented around application state, with events as an optional extra, to being oriented around a log of all events, with application state derived from that log.</p>
<p>Developers are constantly using an example of an event sourcing program, almost all vcs systems such as git are event sourced.
The current commit/working state is the application state, and branches, commits, etc are all just events in the event log.
For business people, an accounting system makes for a good analogy to an event sourced system.
The current balance of accounts is the application state, but the series of entries in the ledger is the set of events that are used to construct that state.</p>
<p>One great benefit of Event Sourcing is that we can change the models of application state at any time, and fully reconstruct from our event log. Instead of writing database migrations when data models change, like we do in the SQL world, we just change how state is derived from events. We can even test systems in a read only mode against production, by reading the event log to construct a new application state. One key advantage Martin mentions is that Event Sourcing enables a 'Memory Image'. This essentially means that our application state can be completely ephemeral, and in memory; you don't need a database for application state, you only need to read from the event log and construct the application state in memory. This can be very fast and performant. The other benefit of this is that memory is super fast, and you can essentially avoid database calls, whilst having persistence. Martin mentions, think about the opportunities opening up here as we begin to see more and more systems with high amounts of RAM or super fast non-volatile RAM.</p>
<p>There are added complexities. Consider how you can order events reliably. Consider how you ensure transactional guarantees, if you write to the event log, you must also update the application state at the same time. You can't update application state before writing to the event log because then you have a working state that is ahead of the event log state, and remember, the event log state is the source of truth. Event Sourcing systems generally bring asynchrony with them, and this can add quite a bit of complexity. You must also consider consistency, what does it mean to write to the event log, if other systems are going to react to those events, they will not be consistent at the point of time you write to the event log. This is a trade off with all event driven architectures however.</p>
<p>Martin mentions in passing that he is very surprised by how uncommon Event Sourcing is in practice.</p>
<p>Martin brings forward a final and very important consideration when Event Sourcing. We must carefully consider which events are worth storing, and which are not. Suppose there is a service that receives an order to 'buy 15 widgets', the service then creates a transaction that is stored in the application state, this transaction contains additional info like the tax applied and any discounts applied. The service could persist an event with the business logic derived details, such as tax and discounts, or an event that most closely mirrors the input request. The advantage of the former is that the event log contains a more precise record of what was computed at the time the request was received, the advantage with the latter is that it contains only the bare minimum required to recompute the application state, and nothing more. In practice, many systems persist both types of events. Greg Young says that there should be no business logic between your events and your application state.</p>
<h2 id="pattern-4-command-query-responsibility-segregation">Pattern 4: Command Query Responsibility Segregation</h2>
<p><a rel="noopener" target="_blank" href="https://www.youtube.com/watch?v=STKCRSUsyP0&t=2611s">Timecode - 43:31</a></p>
<p>Martin warns outright, this is a complex pattern that is more often than not implemented incorrectly, and can cause troubles if so. The idea here is to separate out the write (command) path from the read (query) path of your system. This is particularly useful when you have an application that is read from much more frequently than it is read from, especially if the reads are of a form derived from the write form.</p>
Monthlog 13: November 20202021-01-30T00:00:00+13:002021-01-30T00:00:00+13:00https://hugoreeves.com/posts/monthlog/13/<p>This is the <strong>13</strong> installment in my <strong>'Monthlog'</strong> - a public list of articles, papers, books, discussions, videos, podcasts and software that catch my attention each month.
I hope that regular readers will skim through the listings and find one, or multiple, things that pique their interest.</p>
<p><strong>Note:</strong> Posts are not ordered in any particular way.
If you find an article you think I might like, send it to me via one of the channels on my <a href="/">homepage</a>.</p>
<h1 id="articles">Articles</h1>
<ul>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://www.masterhowtolearn.com/2020-10-31-why-i-no-longer-tell-my-friends-about-anki-supermemo/">Master How To Learn: Why I No Longer Tell My Friends about Anki/SuperMemo</a></strong> - In a month where I've spent hours inside Anki, adding hundreds of cards and completing thousands of reviews, this was well timed to show up in my Hacker News feed.
I've recommended Anki to quite a few people over the years, none them seem to have picked it up, and I think this article kind of explains why.
You really need a strong desire to want a better study solution, and to stumble across a tool like Anki on your own for it to really hold your attention long enough for you to get hooked.
I'm currently drafting a blog post about my exam study technique, with a lot of details about how I leverage Anki.
<a rel="noopener" target="_blank" href="https://news.ycombinator.com/item?id=24957617">Discussion on HN</a></p>
</li>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://www.lesswrong.com/posts/6NvbSwuSAooQxxf7f/beware-of-other-optimizing">Eliezer Yudkowsky: Beware of Other Optimizing</a></strong> - Linked in the above post as a key inspiration.
Lengthy discussion below the article itself.</p>
</li>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://lexi-lambda.github.io/blog/2019/11/05/parse-don-t-validate/">Parse, Don't Validate</a></strong> - A blog post from 2019 that provides some really valuable context and understanding for the next article.</p>
</li>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://lexi-lambda.github.io/blog/2020/11/01/names-are-not-type-safety/">Names are not type safety</a></strong> - Thoughts on data modelling, with a functional perspective that applies well to languages like Haskell and Rust.
The rough argument here is that type aliases <code>type Email = String</code> often don't offer the benefits we hope they do.
<a rel="noopener" target="_blank" href="https://news.ycombinator.com/item?id=24963821">Discussion on HN</a></p>
</li>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://vlfig.me/posts/microservices">Vasco Figueira: Microservices — architecture nihilism in minimalism's clothes</a></strong> - Great article, long form and very in-depth.
Doesn't just criticise Microservices, but explains the common problems people run into, why they might arise and provides multiple ways to think about microservices that might be less error prone.
Highly recommended.
<a rel="noopener" target="_blank" href="https://news.ycombinator.com/item?id=24963742">Discussion on HN</a></p>
</li>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://amontalenti.com/2019/11/04/work-is-a-queue-of-queues">Andrew Montalenti: Work is a Queue of Queues</a></strong> - A good look at how work and task management methods can modelled through CS data structures.
Quite enjoyed this article, it's a bit longer than some of the others but probably worth your time if you're into things like GTD or Agile/Scrum.</p>
</li>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://www.lukethorburn.com/anki/">Using Anki for Math</a></strong> - I've used Anki for a number of years but have often struggled to find a suitable way to learn math theorems and proofs through Anki.
This article offers some insights into building cards for math study.</p>
</li>
</ul>
<h1 id="software">Software</h1>
<ul>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://github.com/curlpipe/ox">Ox</a></strong> - '<em>An independent Rust text editor that runs in your terminal!</em>'
Worth keeping an eye on but I'll be using <a rel="noopener" target="_blank" href="https://neovim.io/">NeoVim</a> for now.</p>
</li>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://github.com/ogham/dog">Dog</a></strong> - '<em>Command-line DNS client</em>', a replacement for Dig written in Rust.
Been using this for a bit now and really enjoying it.
Just a few quality of life improvements over standard <code>dig</code>.</p>
</li>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://github.com/dandavison/delta">Delta</a></strong> - '<em>A fancy git diff viewer.</em>', written in Rust.
I've set this up in my <a rel="noopener" target="_blank" href="https://github.com/hugoreeves/elemental">Dotfile setup</a> and quite like the slightly more readable diff view it offers over the standard <code>diff</code> tool.
Definitely worth a look if, like me, you use the Git CLI over a Git GUI.</p>
</li>
</ul>
<h1 id="recommended-sources-to-follow">Recommended Sources to Follow</h1>
<p>Below are a few media sources and voices I follow.</p>
<h2 id="blogs">Blogs</h2>
<ul>
<li><strong><a rel="noopener" target="_blank" href="http://paulgraham.com/">Paul Graham</a></strong>: Member of YC, offers insightful well-written posts about business and software.</li>
<li><strong><a rel="noopener" target="_blank" href="https://endler.dev/">Matthias Endler</a></strong>: Rust developer and host of 'Hello, Rust!'</li>
<li><strong><a rel="noopener" target="_blank" href="https://victorzhou.com/">Victor Zhou</a></strong>: Recent Princeton CS Graduate publishing informative guides with some focus on Machine Learning.</li>
<li><strong><a rel="noopener" target="_blank" href="https://campoy.cat/">Francesc Campoy</a></strong>: Gopher and JustForFunc host.</li>
<li><strong><a rel="noopener" target="_blank" href="https://deterministic.space/">Deterministic.Space - Pascal Hertleif's blog (g/KillerCup)</a></strong>: Mostly Rust stuff.</li>
</ul>
<h2 id="newsletters">Newsletters</h2>
<ul>
<li><strong><a rel="noopener" target="_blank" href="https://jamesclear.com/">James Clear's Newsletter</a></strong> - Twice a week James sends out his 3-2-1 Newsletter, 3 ideas from James, 2 quotes from others and 1 question for the reader. </li>
<li><strong><a rel="noopener" target="_blank" href="https://this-week-in-rust.org/">This Week In Rust</a></strong> - Rust news every week.</li>
<li><strong><a rel="noopener" target="_blank" href="https://ethhub.substack.com/">EthHub Weekly</a></strong> - Weekly Ethereum updates, a quick paragraph summarising each headline.</li>
</ul>
<h2 id="podcasts">Podcasts</h2>
<ul>
<li><strong><a rel="noopener" target="_blank" href="https://changelog.com/podcast">The Changelog</a></strong>: 'Conversations with the hackers, leaders, and innovators of software development.'</li>
<li><strong><a rel="noopener" target="_blank" href="https://softwareengineeringdaily.com/category/all-episodes/exclusive-content/Podcast">Software Engineering Daily</a></strong>: Daily conversations covering anything Software Development related.</li>
<li><strong><a rel="noopener" target="_blank" href="https://linuxunplugged.com/">Linux Unplugged</a></strong>: A Jupiter Broadcasting show. Relaxed, focused on Linux but touches on all things Unix and Open Source.</li>
<li><strong><a rel="noopener" target="_blank" href="http://investorfieldguide.com/podcast/">Invest Like the Best</a></strong>: Finance and investing podcast often featuring Crypto.</li>
<li><strong><a rel="noopener" target="_blank" href="https://pca.st/3Gld">Y Combinator</a></strong>: Conversations with Y Combinator founders.</li>
<li><strong><a rel="noopener" target="_blank" href="https://pca.st/1uHy">Into the Ether</a></strong>: 'Focusing on all things Ethereum, the leading blockchain for decentralized applications.'</li>
</ul>
Monthlog 12: October 20202021-01-29T00:00:00+00:002021-01-29T00:00:00+00:00https://hugoreeves.com/posts/monthlog/12/<p>This is the <strong>12</strong> installment in my <strong>'Monthlog'</strong> - a public list of articles, discussions, books, software, videos, and podcasts that catch my attention each month.
I hope that regular readers will skim through the listings and find one, or multiple, things that pique their interest.</p>
<p><strong>Note:</strong> Posts are not ordered in any particular way.
If you find an article you think I might like, send it to me via one of the channels on my <a href="/">homepage</a>.</p>
<h1 id="articles">Articles</h1>
<ul>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://kevinmahoney.co.uk/articles/applying-misu/">Kevin Mahoney: Applying “Make Invalid States Unrepresentable”</a></strong> - People often talk about 'Parse don't validate' and similar principles around structuring data in a way that makes it hard to make mistakes.
Making invalid states unrepresentable means designing data structures and database schemas that won't allow for invalid data to be written to the database.
Data structures could be wrong in what they tell you, but the idea is that you will never end up with data that is logically invalid.
This articles explains how to actually apply the principle of making invalid states unrepresentable.
<a rel="noopener" target="_blank" href="https://news.ycombinator.com/item?id=24685772">Discussion on HN</a></p>
</li>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://vasilishynkarenka.com/learning/">Vasili Shynkarenka: How to remember what you learn</a></strong> - If you spend time reading and watching lectures/talks to try and learn new things, it's worth trying to optimize how you actually memorise what you learn.
This article offers a great practical system to help you remember content.
I've presonally adopted part of the system and am using it while taking notes on books.
<a rel="noopener" target="_blank" href="https://news.ycombinator.com/item?id=24700647">Discussion on HN</a></p>
</li>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://blog.maximeheckel.com/posts/seo-mistakes-i-have-made-and-how-i-fixed-them">Maxime Heckel: SEO Mistakes I Have Made and How I Fixed Them</a></strong> - I'm trying to work a little bit on SEO, next year I have hopes of publishing more on this site and hopefully getting more traction.
This article contains some very specific things to be aware of when optimizing a static site blog for SEO.
<a rel="noopener" target="_blank" href="https://news.ycombinator.com/item?id=24766682">Discussion on HN</a></p>
</li>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://bloggingfordevs.com">Blogging For Devs</a></strong> - A 7 day email course for developers looking to improve their blog.
Linked in the previous article.</p>
</li>
</ul>
<h1 id="watch">Watch</h1>
<ul>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://www.youtube.com/watch?v=t7iVCIYQbgk">Monzo: Modern Banking with 1500 Microservices</a></strong> - There are a lot of critics of the current "everything is it's own microservice" mentality.
Monzo has over 1600 microservices, and the speakers here explicitly mention that many of them include less than 1000 lines of business logic.
Over the next ten years, we'll see whether Monzo and other startups of the 2010's benefit or suffer from an obsession around microservices. The speakers here do raise some great points about developer agility and the tools they have created as a platform team to help developers deploy code quickly and with confidence.</p>
</li>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://www.youtube.com/watch?v=QyJZzq0v7Z4">Richard Feldman: Why Isn't Functional Programming the Norm?</a></strong> - Watched this multiple times before.
I believe the crux of why FP isn't more popular is that many FP languages are perceived as academic or niche.
Many devs who haven't spent a lot of time writing functional code often feel slow and mentally burdend when forced into the hard constraints of FP.
I'm enjoying Rust at the moment particularly due to it's functional take on iterators and other parts of the language.</p>
</li>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://www.youtube.com/watch?v=0if71HOyVjY">Russ Olsen @ GOTO 2018: Functional Programming in 40 Minutes</a></strong> - If FP interests you, you may also like this video.</p>
</li>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://www.youtube.com/watch?v=3Fx5Q8xGU8k">Peter Thiel: Competition is for Losers</a></strong> - Whatever you think of Thiel, I think he's probably got some great advice for entrepreneurs.
This talk is particularly great in that it outlines how you might look to create a business that exists in a 'Blue Ocean' or a new market that is not attractive to competition.</p>
</li>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://www.youtube.com/watch?v=AjoxkxM_I5g">Ali Abdaal: How I Remember Everything I Read</a></strong> - Continuing to get more into memory optimization and actually absorbing information.</p>
</li>
</ul>
<h1 id="software">Software</h1>
<ul>
<li><strong><a rel="noopener" target="_blank" href="https://github.com/chriswalz/bit">Bit</a></strong> - '<em>Bit is a modern Git CLI</em>', written in Go.
I don't actually use this but some may find it a useful, more intuitive Git CLI.
Personally, I avoid Git GUIs and alternative CLIs as I think the Git CLI is good to use to actually understand how Git works.
The CLI can be quite verbose and unintuitive, but at least I know exactly what I'm doing to my Git repo.</li>
</ul>
<h1 id="recommended-sources-to-follow">Recommended Sources to Follow</h1>
<p>Below are a few media sources and voices I follow.</p>
<h2 id="blogs">Blogs</h2>
<ul>
<li><strong><a rel="noopener" target="_blank" href="http://paulgraham.com/">Paul Graham</a></strong>: Member of YC, offers insightful well-written posts about business and software.</li>
<li><strong><a rel="noopener" target="_blank" href="https://endler.dev/">Matthias Endler</a></strong>: Rust developer and host of 'Hello, Rust!'</li>
<li><strong><a rel="noopener" target="_blank" href="https://victorzhou.com/">Victor Zhou</a></strong>: Recent Princeton CS Graduate publishing informative guides with some focus on Machine Learning.</li>
<li><strong><a rel="noopener" target="_blank" href="https://campoy.cat/">Francesc Campoy</a></strong>: Gopher and JustForFunc host.</li>
<li><strong><a rel="noopener" target="_blank" href="https://deterministic.space/">Deterministic.Space - Pascal Hertleif's blog (g/KillerCup)</a></strong>: Mostly Rust stuff.</li>
</ul>
<h2 id="newsletters">Newsletters</h2>
<ul>
<li><strong><a rel="noopener" target="_blank" href="https://jamesclear.com/">James Clear's Newsletter</a></strong> - Twice a week James sends out his 3-2-1 Newsletter, 3 ideas from James, 2 quotes from others and 1 question for the reader. </li>
<li><strong><a rel="noopener" target="_blank" href="https://this-week-in-rust.org/">This Week In Rust</a></strong> - Rust news every week.</li>
<li><strong><a rel="noopener" target="_blank" href="https://ethhub.substack.com/">EthHub Weekly</a></strong> - Weekly Ethereum updates, a quick paragraph summarising each headline.</li>
</ul>
<h2 id="podcasts">Podcasts</h2>
<ul>
<li><strong><a rel="noopener" target="_blank" href="https://changelog.com/podcast">The Changelog</a></strong>: 'Conversations with the hackers, leaders, and innovators of software development.'</li>
<li><strong><a rel="noopener" target="_blank" href="https://softwareengineeringdaily.com/category/all-episodes/exclusive-content/Podcast">Software Engineering Daily</a></strong>: Daily conversations covering anything Software Development related.</li>
<li><strong><a rel="noopener" target="_blank" href="https://linuxunplugged.com/">Linux Unplugged</a></strong>: A Jupiter Broadcasting show. Relaxed, focused on Linux but touches on all things Unix and Open Source.</li>
<li><strong><a rel="noopener" target="_blank" href="http://investorfieldguide.com/podcast/">Invest Like the Best</a></strong>: Finance and investing podcast often featuring Crypto.</li>
<li><strong><a rel="noopener" target="_blank" href="https://pca.st/3Gld">Y Combinator</a></strong>: Conversations with Y Combinator founders.</li>
<li><strong><a rel="noopener" target="_blank" href="https://pca.st/1uHy">Into the Ether</a></strong>: 'Focusing on all things Ethereum, the leading blockchain for decentralized applications.'</li>
</ul>
Monthlog 11: September 20202020-10-14T00:00:00+00:002020-10-14T00:00:00+00:00https://hugoreeves.com/posts/monthlog/11/<p>This is the <strong>11</strong> installment in my <strong>'Monthlog'</strong> - a public list of blog posts, announcements, videos, podcasts, software, and libraries that catch my attention each month.
I hope that regular readers will skim through the listings and find one, or multiple, things that pique their interest.</p>
<p><strong>Note:</strong> Posts are not ordered in any particular way.
If you find an article you think I might like, send it to me via one of the channels on my <a href="/">homepage</a>.</p>
<h1 id="read">Read</h1>
<ul>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://blog.datawrapper.de/beautifulcolors/">How to pick more beautiful colors for your data visualizations</a></strong> - I've been doing a bit of UI design this month, and looking into color theory as a part of this.
If you're into data visualization this will definitely appeal.
<a rel="noopener" target="_blank" href="https://news.ycombinator.com/item?id=24391049">Discussion on HN</a></p>
</li>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://raphlinus.github.io/gpu/2020/09/05/stack-monoid.html">Raph Levins: The stack monoid</a></strong> - This article covers how a fundamentally sequential and non-parallel algorithm can be broken down into a monoid function that can be run in parallel.
<a rel="noopener" target="_blank" href="https://news.ycombinator.com/item?id=24385095">Discussion on HN</a></p>
</li>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://www.tweag.io/blog/2020-05-25-flakes/">Nixos Flakes Series</a></strong> - As a Nix user, the development of Flakes is an exciting change coming on the horizon.
This series is a good first introduction to the concept of Flakes and how to use them.</p>
</li>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://www.mindtheproduct.com/the-hidden-costs-of-constantly-shipping-new-things/">The Hidden Cost of Constantly Shipping New Things</a></strong> - This article outlines some of the pitfalls of trying to deliver too much without taking a high-level view of what you're building and how existing parts of your product may be improved.
Two of the main difficulties outlined, 'No Decision Paper Trail' and 'Insufficient Iteration', seem particularly relevant to projects I've worked on in the past.
<a rel="noopener" target="_blank" href="https://news.ycombinator.com/item?id=24390362">Discussion on HN</a></p>
</li>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://a16z.com/2020/09/07/on-productivity-scheduling-reading-habits-marc-andreessen/">Marc Andreessen On Productivity, Scheduling, Reading Habits, Work, and More</a></strong> - Knowing how some of the world's most successful individuals achieve productivity can be very enlightening.
I took a lot away from this interview-style article, in particular, I think the emphasis on protecting 'open time' is well-founded.
<a rel="noopener" target="_blank" href="https://news.ycombinator.com/item?id=24534674">Discussion on HN</a></p>
</li>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://eriktorenberg.substack.com/p/build-personal-moats">Erik Torenberg: Build Personal Moats</a></strong> - Building a 'personal moat' is a new concept to me, but it seems like a valid idea.
Somewhat tangentially I really enjoyed being introduced to the Japanese concept of <strong>Ikigai</strong>: the intersection of what you love, what you’re good at, and what the world needs.</p>
</li>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://danielmiessler.com/blog/no-moving-your-ssh-port-isnt-security-by-obscurity/">Daniel Miessler: No, Moving Your SSH Port Isn’t Security by Obscurity</a></strong> - People often claim that moving the SSH port of a server is '<em>security by obscurity</em>'.
This article does a great job of explaining why that's not the truth and explaining what 'security by obscurity' actually is.
<a rel="noopener" target="_blank" href="https://news.ycombinator.com/item?id=24542104">Discussion on HN</a></p>
</li>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://barehands.substack.com/p/how-to-take-meeting-notes">How To Take Meeting Notes</a></strong> - Trying to improve the quality and quantity of information I can remember following a conversation with someone has been a goal of mine for a while.
This article provides a few systems that can be used to improve the way in which you take notes and ultimately remember a meeting.</p>
</li>
</ul>
<h1 id="discuss">Discuss</h1>
<ul>
<li><strong><a rel="noopener" target="_blank" href="https://news.ycombinator.com/item?id=24398077">Ask HN: What did you do to improve your company?</a></strong> - I found it oddly surprising that the number one comment here is, '<em>leaving</em>', as in, leaving the company.</li>
</ul>
<h1 id="recommended-sources-to-follow">Recommended Sources to Follow</h1>
<p>Below are a few media sources and voices I follow.</p>
<h2 id="blogs">Blogs</h2>
<ul>
<li><strong><a rel="noopener" target="_blank" href="https://endler.dev/">Matthias Endler</a></strong>: Rust developer and host of 'Hello, Rust!'</li>
<li><strong><a rel="noopener" target="_blank" href="http://paulgraham.com/">Paul Graham</a></strong>: Member of YC, offers insightful well-written posts about business and software.</li>
<li><strong><a rel="noopener" target="_blank" href="https://victorzhou.com/">Victor Zhou</a></strong>: Recent Princeton CS Graduate publishing informative guides with some focus on Machine Learning.</li>
<li><strong><a rel="noopener" target="_blank" href="https://campoy.cat/">Francesc Campoy</a></strong>: Gopher and JustForFunc host.</li>
<li><strong><a rel="noopener" target="_blank" href="https://deterministic.space/">Deterministic.Space - Pascal Hertleif's blog (g/KillerCup)</a></strong>: Mostly Rust stuff.</li>
</ul>
<h2 id="newsletters">Newsletters</h2>
<ul>
<li><strong><a rel="noopener" target="_blank" href="https://this-week-in-rust.org/">This Week In Rust</a></strong> - Rust news every week.</li>
<li><strong><a rel="noopener" target="_blank" href="https://ethhub.substack.com/">EthHub Weekly</a></strong> - Weekly Ethereum updates, a quick paragraph summarising each headline.</li>
</ul>
<h2 id="podcasts">Podcasts</h2>
<ul>
<li><strong><a rel="noopener" target="_blank" href="https://changelog.com/podcast">The Changelog</a></strong>: 'Conversations with the hackers, leaders, and innovators of software development.'</li>
<li><strong><a rel="noopener" target="_blank" href="https://softwareengineeringdaily.com/category/all-episodes/exclusive-content/Podcast">Software Engineering Daily</a></strong>: Daily conversations covering anything Software Development related.</li>
<li><strong><a rel="noopener" target="_blank" href="https://linuxunplugged.com/">Linux Unplugged</a></strong>: A Jupiter Broadcasting show. Relaxed, focused on Linux but touches on all things Unix and Open Source.</li>
<li><strong><a rel="noopener" target="_blank" href="http://investorfieldguide.com/podcast/">Invest Like the Best</a></strong>: Finance and investing podcast often featuring Crypto.</li>
<li><strong><a rel="noopener" target="_blank" href="https://pca.st/3Gld">Y Combinator</a></strong>: Conversations with Y Combinator founders.</li>
<li><strong><a rel="noopener" target="_blank" href="https://pca.st/1uHy">Into the Ether</a></strong>: 'Focusing on all things Ethereum, the leading blockchain for decentralized applications.'</li>
</ul>
Monthlog 10: August 20202020-09-01T00:01:00+00:002020-09-01T00:01:00+00:00https://hugoreeves.com/posts/monthlog/10/<p>This is the <strong>10</strong> installment in my <strong>'Monthlog'</strong> - a public list of blog posts, announcements, videos, podcasts, software, and libraries that catch my attention each month.
I hope that regular readers will skim through the listings and find one, or multiple, things that pique their interest.</p>
<p><strong>Note:</strong> Posts are not ordered in any particular way.
If you find an article you think I might like, send it to me via one of the channels on my <a href="/">homepage</a>.</p>
<h1 id="read">Read</h1>
<ul>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://nullprogram.com/blog/2020/08/01/">Null Program: Conventions for Command Line Options</a></strong> - If you're building a CLI this is a great read; explaining the conventions of CLI arguments and where they originated from.
<a rel="noopener" target="_blank" href="https://news.ycombinator.com/item?id=24020952">Discussion on HN</a></p>
</li>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://users.ece.utexas.edu/%7Eadnan/pike.html">Rob Pike's 5 Rules of Programming</a></strong> - Just five short bullet points detailing Rob Pike's 5 Rules of Programming.
<a rel="noopener" target="_blank" href="https://news.ycombinator.com/item?id=24135189">Discussion on HN</a></p>
</li>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://www.aaronkharris.com/raise-less-money">Aaron Harris: Raise Less Money</a></strong> - Short thoughts on why founders try to raise too much money and end up becoming overly diluted.
<a rel="noopener" target="_blank" href="https://news.ycombinator.com/item?id=24133146">Discussion on HN</a></p>
</li>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://jesseduffield.com/beginners-guide-to-abstraction/">Jesse Duffield: Beginners Guide to Abstraction</a></strong> - A look at how to properly abstract as a software developer.
Jesse is the developer of some popular open-source command-line utilities such as <a rel="noopener" target="_blank" href="https://github.com/jesseduffield/lazygit">Lazy Git</a>.</p>
</li>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://blog.nindalf.com/posts/factorio-and-software-engineering/">Factorio and Software Engineering</a></strong> - This article manages to relate concepts from a factory building video game to software development.
<a rel="noopener" target="_blank" href="https://news.ycombinator.com/item?id=24181783">Discussion on r/rust</a></p>
</li>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://meiert.com/en/blog/minimal-web-development/">Minimal Web Development</a></strong> - I'm very much a fan of minimal websites and blogs, so this article caught my attention.
One of my goals when designing this latest iteration of my blog was to remove the need for almost all Javascript, trying to align myself with principles of minimal web development.</p>
</li>
</ul>
<h1 id="software">Software</h1>
<ul>
<li><strong><a rel="noopener" target="_blank" href="https://github.com/RustScan/RustScan">RustScan</a></strong> - '<em>The Modern Day Port Scanner.</em>'
A faster port scanner utilizing <a rel="noopener" target="_blank" href="https://nmap.org/">nmap</a>, written in Rust.</li>
</ul>
<h1 id="recommended-sources-to-follow">Recommended Sources to Follow</h1>
<p>Below are a few media sources and voices I follow.</p>
<h2 id="blogs">Blogs</h2>
<ul>
<li><strong><a rel="noopener" target="_blank" href="https://endler.dev/">Matthias Endler</a></strong>: Rust developer and host of 'Hello, Rust!'</li>
<li><strong><a rel="noopener" target="_blank" href="http://paulgraham.com/">Paul Graham</a></strong>: Member of YC, offers insightful well-written posts about business and software.</li>
<li><strong><a rel="noopener" target="_blank" href="https://victorzhou.com/">Victor Zhou</a></strong>: Recent Princeton CS Graduate publishing informative guides with some focus on Machine Learning.</li>
<li><strong><a rel="noopener" target="_blank" href="https://campoy.cat/">Francesc Campoy</a></strong>: Gopher and JustForFunc host.</li>
<li><strong><a rel="noopener" target="_blank" href="https://deterministic.space/">Deterministic.Space - Pascal Hertleif's blog (g/KillerCup)</a></strong>: Mostly Rust stuff.</li>
</ul>
<h2 id="newsletters">Newsletters</h2>
<ul>
<li><strong><a rel="noopener" target="_blank" href="https://this-week-in-rust.org/">This Week In Rust</a></strong> - Rust news every week.</li>
<li><strong><a rel="noopener" target="_blank" href="https://ethhub.substack.com/">EthHub Weekly</a></strong> - Weekly Ethereum updates, a quick paragraph summarising each headline.</li>
</ul>
<h2 id="podcasts">Podcasts</h2>
<ul>
<li><strong><a rel="noopener" target="_blank" href="https://changelog.com/podcast">The Changelog</a></strong>: 'Conversations with the hackers, leaders, and innovators of software development.'</li>
<li><strong><a rel="noopener" target="_blank" href="https://softwareengineeringdaily.com/category/all-episodes/exclusive-content/Podcast">Software Engineering Daily</a></strong>: Daily conversations covering anything Software Development related.</li>
<li><strong><a rel="noopener" target="_blank" href="https://linuxunplugged.com/">Linux Unplugged</a></strong>: A Jupiter Broadcasting show. Relaxed, focused on Linux but touches on all things Unix and Open Source.</li>
<li><strong><a rel="noopener" target="_blank" href="http://investorfieldguide.com/podcast/">Invest Like the Best</a></strong>: Finance and investing podcast often featuring Crypto.</li>
<li><strong><a rel="noopener" target="_blank" href="https://pca.st/3Gld">Y Combinator</a></strong>: Conversations with Y Combinator founders.</li>
<li><strong><a rel="noopener" target="_blank" href="https://pca.st/1uHy">Into the Ether</a></strong>: 'Focusing on all things Ethereum, the leading blockchain for decentralized applications.'</li>
</ul>
Monthlog 09: July 20202020-08-02T00:01:00+00:002020-08-02T00:01:00+00:00https://hugoreeves.com/posts/monthlog/09/<p>This is the <strong>09</strong> installment in my <strong>'Monthlog'</strong> - a public list of blog posts, announcements, videos, podcasts, software, and libraries that catch my attention each month.
I hope that regular readers will skim through the listings and find one, or multiple, things that pique their interest.</p>
<p><strong>Note:</strong> Posts are not ordered in any particular way.
If you find an article you think I might like, send it to me via one of the channels on my <a href="/">homepage</a>.</p>
<h1 id="read">Read</h1>
<ul>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://without.boats/blog/ringbahn-ii/">Ringbahn II: the central state machine</a></strong> - Ringbahn is 'a safe API for using io-uring from Rust'.
This is a great article documenting how Ringbahn's lowest level type, the 'Ring', is implemented.
A great read about interactions between low-level Rust and the Linux Kernel.</p>
</li>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://slack.engineering/a-terrible-horrible-no-good-very-bad-day-at-slack/">A Terrible, Horrible, No-Good, Very Bad Day at Slack</a></strong> - Slack's post-mortem following a service outage on May 12, 2020.
Gives a great behind the scenes look at how Slack is engineered on the server-side and how engineers went about diagnosing and resolving an issue in production.
<a rel="noopener" target="_blank" href="https://news.ycombinator.com/item?id=23755843">Discussion on HN</a></p>
</li>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://memo.barrucadu.co.uk/2018-budget.html">I Need A Budget</a></strong> - This article is probably only relevant to a very niche audience.
It covers implementing a budgeting system in the plain text accounting tool, Ledger.
If you're generally interested in personal finance or budgeting, you might also find this article relevant.</p>
</li>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://jesseduffield.com/beginners-guide-to-abstraction/">Jesse Duffield: Beginners Guide to Abstraction</a></strong> - A look at how to properly abstract as a software developer.
Jesse is the developer of some popular open-source command-line utilities such as <a rel="noopener" target="_blank" href="https://github.com/jesseduffield/lazygit">Lazy Git</a>.</p>
</li>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://www.lpalmieri.com/posts/2020-07-04-choosing-a-rust-web-framework-2020-edition/">Choosing a Rust web framework, 2020 edition</a></strong> - Rust web frameworks are developing very quickly, and there's been a lot of change over the past year.
This article does a great job summarising the differences between the popular frameworks, assessing design decisions, community adoption, and documentation.
<a rel="noopener" target="_blank" href="https://www.reddit.com/r/rust/comments/hlpsw5/choosing_a_rust_web_framework_2020_edition/">Discussion on r/rust</a></p>
</li>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://codingcoffee.dev/blog/wireguard_on_kubernetes_with_adblocking/">Ameya Shenoy: Wireguard on Kubernetes with Ad Blocking</a></strong> - Setting up a VPN using Wireguard and ad-blocking on top of Kubernetes.
This is a good introduction to both Wireguard and the current state of Kubernetes.
<a rel="noopener" target="_blank" href="https://news.ycombinator.com/item?id=23812063">Discussion on HN</a></p>
</li>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://healeycodes.com/creating-randomness/">Andrew Healey: Creating Randomness Without Math.random</a></strong> - I'm not familiar with random number generation but enjoyed this post as it introduced me to a new concept and Computer Science area.</p>
</li>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://blog.carlosgaldino.com/writing-a-file-system-from-scratch-in-rust.html">Carlos Galdino: Writing a File System from scratch in Rust</a></strong> - I'm continuing to look at file systems, and learning Rust.
This article looks at both.
<a rel="noopener" target="_blank" href="https://news.ycombinator.com/item?id=23967016">Discussion on HN</a>.
<a rel="noopener" target="_blank" href="https://www.reddit.com/r/rust/comments/hyw8oh/writing_a_file_system_from_scratch_in_rust/">Discussion on r/rust</a></p>
</li>
</ul>
<h1 id="discuss">Discuss</h1>
<ul>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://news.ycombinator.com/item?id=23947818">Ask HN: What are some good resources to learn business administration/finance?</a></strong> - I'm always interested to learn more about business and finance.
There are some great recommendations here that mesh the worlds of software, startups, and business administration.</p>
</li>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://www.reddit.com/r/btrfs/comments/hyra46/benchmark_of_btrfs_decompression/">r/btrfs: Benchmark of BTRFS decompression</a></strong> - More file system stuff.
Interestingly, these benchmarks show a sweet spot for read speeds at certain compression ratios.
At some ratios, in this case <code>zstd:11</code>, reads are faster than at higher and lower ratios.
This is due to the balance between read speed off of disks and the speed at which the data can be decompressed.</p>
</li>
</ul>
<h1 id="recommended-sources-to-follow">Recommended Sources to Follow</h1>
<p>Below are a few media sources and voices I follow.</p>
<h2 id="blogs">Blogs</h2>
<ul>
<li><strong><a rel="noopener" target="_blank" href="https://endler.dev/">Matthias Endler</a></strong>: Rust developer and host of 'Hello, Rust!'</li>
<li><strong><a rel="noopener" target="_blank" href="http://paulgraham.com/">Paul Graham</a></strong>: Member of YC, offers insightful well-written posts about business and software.</li>
<li><strong><a rel="noopener" target="_blank" href="https://victorzhou.com/">Victor Zhou</a></strong>: Recent Princeton CS Graduate publishing informative guides with some focus on Machine Learning.</li>
<li><strong><a rel="noopener" target="_blank" href="https://campoy.cat/">Francesc Campoy</a></strong>: Gopher and JustForFunc host.</li>
<li><strong><a rel="noopener" target="_blank" href="https://deterministic.space/">Deterministic.Space - Pascal Hertleif's blog (g/KillerCup)</a></strong>: Mostly Rust stuff.</li>
</ul>
<h2 id="newsletters">Newsletters</h2>
<ul>
<li><strong><a rel="noopener" target="_blank" href="https://this-week-in-rust.org/">This Week In Rust</a></strong> - Rust news every week.</li>
<li><strong><a rel="noopener" target="_blank" href="https://ethhub.substack.com/">EthHub Weekly</a></strong> - Weekly Ethereum updates, a quick paragraph summarising each headline.</li>
</ul>
<h2 id="podcasts">Podcasts</h2>
<ul>
<li><strong><a rel="noopener" target="_blank" href="https://changelog.com/podcast">The Changelog</a></strong>: 'Conversations with the hackers, leaders, and innovators of software development.'</li>
<li><strong><a rel="noopener" target="_blank" href="https://softwareengineeringdaily.com/category/all-episodes/exclusive-content/Podcast">Software Engineering Daily</a></strong>: Daily conversations covering anything Software Development related.</li>
<li><strong><a rel="noopener" target="_blank" href="https://linuxunplugged.com/">Linux Unplugged</a></strong>: A Jupiter Broadcasting show. Relaxed, focused on Linux but touches on all things Unix and Open Source.</li>
<li><strong><a rel="noopener" target="_blank" href="http://investorfieldguide.com/podcast/">Invest Like the Best</a></strong>: Finance and investing podcast often featuring Crypto.</li>
<li><strong><a rel="noopener" target="_blank" href="https://pca.st/3Gld">Y Combinator</a></strong>: Conversations with Y Combinator founders.</li>
<li><strong><a rel="noopener" target="_blank" href="https://pca.st/1uHy">Into the Ether</a></strong>: 'Focusing on all things Ethereum, the leading blockchain for decentralized applications.'</li>
</ul>
Monthlog 08: June 20202020-07-02T00:01:00+00:002020-07-02T00:01:00+00:00https://hugoreeves.com/posts/monthlog/08/<p>This is the <strong>08</strong> installment in my <strong>'Monthlog'</strong> - a public list of blog posts, announcements, videos, podcasts, software, and libraries that catch my attention each month.
I hope that regular readers will skim through the listings and find one, or multiple, things that pique their interest.</p>
<p><strong>Note:</strong> Posts are not ordered in any particular way.
If you find an article you think I might like, send it to me via one of the channels on my <a href="/">homepage</a>.</p>
<h1 id="read">Read</h1>
<ul>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://tonsky.me/blog/monitors/">Time to upgrade your monitor</a></strong> - A font designer's commentary on what monitor you should buy and why.
In a very succinct manner, this article taught me a lot about font rendering and why some displays look better than others.</p>
</li>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://teachyourselfcs.com">Teach Yourself CS</a></strong> - At a high level this website provides both a book and a video course to cover each domain of Computer Science.
A great resource for people who can code but want to become Computer Scientists.
<a rel="noopener" target="_blank" href="https://news.ycombinator.com/item?id=23588896">Discussion on HN</a></p>
</li>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://jepsen.io/analyses/redis-raft-1b3fbf6">Jepsen: Redis Raft Analysis</a></strong> - I'd never looked at Jepsen testing but found this document an interesting read.
It essentially covers the failure/inconsistency modes of the Redis raft implementation.
<a rel="noopener" target="_blank" href="https://news.ycombinator.com/item?id=23615790">Discussion on HN</a></p>
</li>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://raphlinus.github.io/xi/2020/06/27/xi-retrospective.html">Raph Levien: Xi-Editor Retrospective</a></strong> - I watched the development of Xi periodically over the past few years.
It's sad to see that the project didn't work out, or at least, didn't quite reach the full vision it had intended to achieve.
Post mortems are always a good read as you can see the decisions that lead to a product's failure.
<a rel="noopener" target="_blank" href="https://news.ycombinator.com/item?id=23663878">Discussion on HN</a></p>
</li>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://dave.cheney.net/high-performance-json.html">Dave Cheney: Building a high-performance JSON parser</a></strong> - JSON decoding is a relatively expensive and slow process in most languages; this post goes into great detail outlining how a faster JSON parser in Go was implemented.
<a rel="noopener" target="_blank" href="https://news.ycombinator.com/item?id=23666498">Linked in the previous Hacker News discussion</a></p>
</li>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://arstechnica.com/information-technology/2020/05/zfs-101-understanding-zfs-storage-and-performance/3/">Ars Technica: ZFS 101—Understanding ZFS storage and performance</a></strong> - I've been doing some more reading on filesystems and in particular, the design differences between Zfs and Btrfs - two Copy-on-Write filesystems.
This article is a precise explanation of how some of Zfs is architected at a high level.</p>
</li>
</ul>
<h1 id="discuss">Discuss</h1>
<ul>
<li><strong><a rel="noopener" target="_blank" href="https://news.ycombinator.com/item?id=23089999">Ask HN: What do you self-host?</a></strong> - I self host a few things, including a Bitwarden_rs instance.
It's always interesting to see what others self-host, and also the incredible range of open-source software that exists for different niches.</li>
</ul>
<h1 id="software-and-libraries">Software and Libraries</h1>
<ul>
<li><strong><a rel="noopener" target="_blank" href="https://www.zettlr.com">Zettlr</a></strong> - Last month I mentioned <a rel="noopener" target="_blank" href="https://obsidian.md/">Obsidian</a>, an alternative to Roam Research.
Zettlr follows in the same vein and is an open-source markdown editor and knowledge base.
I'm interested to see how this develops.</li>
</ul>
<h1 id="recommended-sources-to-follow">Recommended Sources to Follow</h1>
<p>Below are a few media sources and voices I follow.</p>
<h2 id="blogs">Blogs</h2>
<ul>
<li><strong><a rel="noopener" target="_blank" href="https://endler.dev/">Matthias Endler</a></strong>: Rust developer and host of 'Hello, Rust!'</li>
<li><strong><a rel="noopener" target="_blank" href="http://paulgraham.com/">Paul Graham</a></strong>: Member of YC, offers insightful well-written posts about business and software.</li>
<li><strong><a rel="noopener" target="_blank" href="https://victorzhou.com/">Victor Zhou</a></strong>: Recent Princeton CS Graduate publishing informative guides with some focus on Machine Learning.</li>
<li><strong><a rel="noopener" target="_blank" href="https://campoy.cat/">Francesc Campoy</a></strong>: Gopher and JustForFunc host.</li>
<li><strong><a rel="noopener" target="_blank" href="https://deterministic.space/">Deterministic.Space - Pascal Hertleif's blog (g/KillerCup)</a></strong>: Mostly Rust stuff.</li>
</ul>
<h2 id="newsletters">Newsletters</h2>
<ul>
<li><strong><a rel="noopener" target="_blank" href="https://this-week-in-rust.org/">This Week In Rust</a></strong> - Rust news every week.</li>
<li><strong><a rel="noopener" target="_blank" href="https://ethhub.substack.com/">EthHub Weekly</a></strong> - Weekly Ethereum updates, a quick paragraph summarising each headline.</li>
</ul>
<h2 id="podcasts">Podcasts</h2>
<ul>
<li><strong><a rel="noopener" target="_blank" href="https://changelog.com/podcast">The Changelog</a></strong>: 'Conversations with the hackers, leaders, and innovators of software development.'</li>
<li><strong><a rel="noopener" target="_blank" href="https://softwareengineeringdaily.com/category/all-episodes/exclusive-content/Podcast">Software Engineering Daily</a></strong>: Daily conversations covering anything Software Development related.</li>
<li><strong><a rel="noopener" target="_blank" href="https://linuxunplugged.com/">Linux Unplugged</a></strong>: A Jupiter Broadcasting show. Relaxed, focused on Linux but touches on all things Unix and Open Source.</li>
<li><strong><a rel="noopener" target="_blank" href="http://investorfieldguide.com/podcast/">Invest Like the Best</a></strong>: Finance and investing podcast often featuring Crypto.</li>
<li><strong><a rel="noopener" target="_blank" href="https://pca.st/3Gld">Y Combinator</a></strong>: Conversations with Y Combinator founders.</li>
<li><strong><a rel="noopener" target="_blank" href="https://pca.st/1uHy">Into the Ether</a></strong>: 'Focusing on all things Ethereum, the leading blockchain for decentralized applications.'</li>
</ul>
Monthlog 07: May 20202020-06-21T00:01:00+00:002020-06-21T00:01:00+00:00https://hugoreeves.com/posts/monthlog/07/<p>This is the <strong>07</strong> installment in my <strong>'Monthlog'</strong> - a public list of blog posts, announcements, videos, podcasts, software and libraries that catch my attention each month.
I hope that regular readers will skim through the listings and find one, or multiple, things that pique their interest.</p>
<p><strong>Note:</strong> Posts are not ordered in any particular way.
If you find an article you think I might like, send it to me via one of the channels on my <a href="/">homepage</a>.</p>
<h1 id="read">Read</h1>
<ul>
<li>
<p><strong><a rel="noopener" target="_blank" href="http://fabiensanglard.net/floating_point_visually_explained/index.html">Floating Point Visually Explained</a></strong> - Having not yet finished a CS degree, I have never really delved deep into how floating-point numbers work.
I know that they're not precise but I found this visual representation very helpful to understand what the two components of the floating-point mean.
<a rel="noopener" target="_blank" href="https://news.ycombinator.com/item?id=23081924">Discussion on HN</a></p>
</li>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://www.theregister.co.uk/2003/09/11/bill_joys_greatest_gift/">Bill Joy's greatest gift to man – the vi editor</a></strong> - An interview from 2003 discussing the Vi editor with Bill Joy.
Interesting that modem speed was a tight constraint when building Vi.
<a rel="noopener" target="_blank" href="https://www.reddit.com/r/vim/comments/geli14/bill_joys_greatest_gift_to_man_the_vi_editor/">Discussion on r/vim</a></p>
</li>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://github.com/santhoshtr/wikipedia-ipfs">Wikipedia IPFS</a></strong> - There's been work on this for a couple of years but it looks like someone from Wikipedia finally made a solution as a passion project.
<a rel="noopener" target="_blank" href="https://news.ycombinator.com/item?id=23127829">Discussion on HN</a></p>
</li>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://christine.website/blog/how-i-start-nix-2020-03-08">Christine Dodrill: How I Start Nix</a></strong> - A detailed and relatively newcomer-friendly introduction to setting up various parts of a Nix development system.</p>
</li>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://nikic.github.io/2020/05/10/Make-LLVM-fast-again.html">Make LLVM Fast Again</a></strong> - There was a bit of discussion in Rust circles this month surrounding a performance regression in LLVM that relates specifically to Rust code.
<a rel="noopener" target="_blank" href="https://news.ycombinator.com/item?id=23137345">Discussion on HN</a></p>
</li>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://lists.llvm.org/pipermail/llvm-dev/2020-May/141482.html">[llvm-dev] 7-8% compile time slowdowns in LLVM 10</a></strong> - A closely related mailing list extract.
<a rel="noopener" target="_blank" href="https://www.reddit.com/r/rust/comments/gh3thc/llvm_10_has_performance_regressions_with_rust/">Discussion on r/rust</a></p>
</li>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://blog.technodrone.cloud/2019/02/goodbye-docker-and-thanks-for-all-fish.html">Goodbye Docker and Thanks for all the Fish</a></strong> - I don't quite agree with most of what the author is trying to say in this article, however, it's a good primer on some of Docker's history and the forces that are now working against its success as a business.
<a rel="noopener" target="_blank" href="https://news.ycombinator.com/item?id=19351236">Discussion on HN</a></p>
</li>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://www.mcls.io/blog/encouraging-a-culture-of-written-communication">Encouraging a Culture of Written Communication</a></strong> - With more work moving online-only, I found this article to be a useful guide to the benefits of good written communication.
<a rel="noopener" target="_blank" href="https://news.ycombinator.com/item?id=23155647">Discussion on HN</a></p>
</li>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://engineering.shopify.com/blogs/engineering/what-is-nix">Shopify: What is Nix?</a></strong> - <a rel="noopener" target="_blank" href="https://news.ycombinator.com/item?id=23251754">Discussion on HN</a></p>
</li>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://www.lennyrachitsky.com/p/how-the-biggest-consumer-apps-got">How the biggest consumer apps got their first 1k users</a></strong> - Self-explanatory.
If you're interested in the tech startup world you'll probably like this article.
<a rel="noopener" target="_blank" href="https://news.ycombinator.com/item?id=23290154">Discussion on HN</a></p>
</li>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://blog.samaltman.com/idea-generation">Sam Altman: Idea Generation</a></strong> - <a rel="noopener" target="_blank" href="https://news.ycombinator.com/item?id=23341179">Discussion on HN</a></p>
</li>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://www.mscs.dal.ca/%7Eselinger/accounting/tutorial.html">Tutorial on Multiple Currency Accounting</a></strong> - I've been using this document to guide the accounting implementation for EARL.</p>
</li>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://www.stephendiehl.com/posts/marketing.html">Stephen Diehl: On Marketing Haskell</a></strong> - A great, thorough, article on some takeaway lessons from Haskell's 'marketing'.
Discusses how a language communicates it's value proposition to developers and decision-makers.
A quote I enjoyed: "managing a software project isn’t about correctness or engineering anymore: it’s about running a risk portfolio of distressed assets"</p>
</li>
</ul>
<h1 id="discuss">Discuss</h1>
<p>New section!
I've decided to start linking the odd discussion on sites like Reddit and HN that I find interesting and that you might too.</p>
<ul>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://news.ycombinator.com/item?id=23089999">Ask HN: Is your company sticking to on-premise servers? Why?</a></strong></p>
</li>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://news.ycombinator.com/item?id=23363595">Ask HN: Best books under 200 pages for developers?</a></strong></p>
</li>
</ul>
<h1 id="watch">Watch</h1>
<ul>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://www.youtube.com/watch?v=2wZ1pCpJUIM&t">Bryan Cantrill @ Scale By The Bay: Rust and Other Interesting Things</a></strong> - It Begins.</p>
</li>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://www.youtube.com/watch?v=LjFM8vw3pbU&t=1527s">Bryan Cantrill: The Summer of Rust</a></strong> - I watched a bunch of Bryan's talks this month.
His first-hand experience and involvement in the development of modern computing makes him an amazing speaker to learn from.</p>
</li>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://www.youtube.com/watch?v=fE2KDzZaxvE">Bryan Cantril @ Uptime 2017: Zebras All The Way Down</a></strong> - Brain uses the medical idiom - <em>idiom?</em> - of Zebras vs Horses to explain the types of bugs in the datapath of computer software.
The key takeaway here is that a Zebra is a rare bug, but in our tried and tested systems, the only bugs we have are Zebras.
We get to squash Zebras each time they appear but as Computer Scientists and Engineers we are now only faced by Zebras and they extend all the way down the datapath.</p>
</li>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://www.youtube.com/watch?v=vvZA9n3e5pc">Bryan Cantrill: Stanford Seminar - The Soul of a New Machine: Rethinking the Computer</a></strong> - Delivered March 2020.
If you watched the previous video in which Bryan talks about the troubles of navigating firmware bugs and failure modes, Bryan's interest in creating a new computer company likely seems justified.
Bryan's starting a new server company, keep an eye out for the <a rel="noopener" target="_blank" href="https://oxide.computer/">Oxide Computer Company</a>.</p>
</li>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://www.youtube.com/watch?v=30jNsCVLpAE&t=329s">Bryan Cantrill: GOTO 2017 - Debugging Under Fire</a></strong> - Great.
What more can I say?
If you made it to this entry in the videos from Bryan series you'll probably watch this one regardless of how I justify its relevance.</p>
</li>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://www.youtube.com/watch?v=NP189MPfR7Q">Daniel Bryant: GOTO 2017 - The Seven (More) Deadly Sins of Microservices</a></strong></p>
</li>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://www.youtube.com/watch?v=n9VKAKwBj_0">Laura Frank: KubeCon Europe 2018 - Understanding Distributed Consensus in etcd and Kubernetes</a></strong></p>
</li>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://www.youtube.com/watch?v=4XpnKHJAok8&t=1029s">Linus Torvalds: Tech Talk @ Google - Git</a></strong> - Linus is definitely outspoken and rarely holds back.
I liked this somewhat older talk of his as you can get a feel for the struggles of version control before Git.</p>
</li>
</ul>
<h1 id="listen">Listen</h1>
<ul>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://pca.st/4hr2j6jx">On the Metal: Jonathan Blow</a></strong> - The Oxide Computer Company's podcast, Bryan Cantril leads the discussion in these.</p>
</li>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://pca.st/mjzjelog">On the Metal: Jeff Rothschild</a></strong></p>
</li>
</ul>
<h1 id="software-and-libraries">Software and Libraries</h1>
<ul>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://github.com/excalidraw/excalidraw">Excalidraw</a></strong> - Appeared in my GitHub Explore and seems like a useful quick sketching tool that's also open source.</p>
</li>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://obsidian.md/">Obsidian</a></strong> - Obsidian looks like a good open source alternative to Roam Research.
Like Roam, Obsidian offers a 'Knowledge Graph' to connect notes together.
Some questions were raised in the following HN thread about the License but hopefully, the license will be revised soon.
<a rel="noopener" target="_blank" href="https://news.ycombinator.com/item?id=23324598">Discussion on HN</a></p>
</li>
</ul>
<h1 id="recommended-sources-to-follow">Recommended Sources to Follow</h1>
<p>Below are a few media sources and voices I follow.</p>
<h2 id="blogs">Blogs</h2>
<ul>
<li><strong><a rel="noopener" target="_blank" href="https://endler.dev/">Matthias Endler</a></strong>: Rust developer and host of 'Hello, Rust!'</li>
<li><strong><a rel="noopener" target="_blank" href="http://paulgraham.com/">Paul Graham</a></strong>: Member of YC, offers insightful well-written posts about business and software.</li>
<li><strong><a rel="noopener" target="_blank" href="https://victorzhou.com/">Victor Zhou</a></strong>: Recent Princeton CS Graduate publishing informative guides with some focus on Machine Learning.</li>
<li><strong><a rel="noopener" target="_blank" href="https://campoy.cat/">Francesc Campoy</a></strong>: Gopher and JustForFunc host.</li>
<li><strong><a rel="noopener" target="_blank" href="https://deterministic.space/">Deterministic.Space - Pascal Hertleif's blog (g/KillerCup)</a></strong>: Mostly Rust stuff.</li>
</ul>
<h2 id="newsletters">Newsletters</h2>
<ul>
<li><strong><a rel="noopener" target="_blank" href="https://this-week-in-rust.org/">This Week In Rust</a></strong> - Rust news every week.</li>
<li><strong><a rel="noopener" target="_blank" href="https://ethhub.substack.com/">EthHub Weekly</a></strong> - Weekly Ethereum updates, a quick paragraph summarising each headline.</li>
</ul>
<h2 id="podcasts">Podcasts</h2>
<ul>
<li><strong><a rel="noopener" target="_blank" href="https://changelog.com/podcast">The Changelog</a></strong>: 'Conversations with the hackers, leaders, and innovators of software development.'</li>
<li><strong><a rel="noopener" target="_blank" href="https://softwareengineeringdaily.com/category/all-episodes/exclusive-content/Podcast">Software Engineering Daily</a></strong>: Daily conversations covering anything Software Development related.</li>
<li><strong><a rel="noopener" target="_blank" href="https://linuxunplugged.com/">Linux Unplugged</a></strong>: A Jupiter Broadcasting show. Relaxed, focused on Linux but touches on all things Unix and Open Source.</li>
<li><strong><a rel="noopener" target="_blank" href="http://investorfieldguide.com/podcast/">Invest Like the Best</a></strong>: Finance and investing podcast often featuring Crypto.</li>
<li><strong><a rel="noopener" target="_blank" href="https://pca.st/3Gld">Y Combinator</a></strong>: Conversations with Y Combinator founders.</li>
<li><strong><a rel="noopener" target="_blank" href="https://pca.st/1uHy">Into the Ether</a></strong>: 'Focusing on all things Ethereum, the leading blockchain for decentralized applications.'</li>
</ul>
Monthlog 06: April 20202020-05-10T00:01:00+13:002020-05-10T00:01:00+13:00https://hugoreeves.com/posts/monthlog/06/<p>This is the <strong>06</strong> installment in my <strong>'Monthlog'</strong> - a public list of blog posts, announcements, videos, podcasts, software and libraries that catch my attention each month.
I hope that regular readers will skim through the listings and find one, or multiple, things that pique their interest.</p>
<p>I didn't do a good job with the monthlog this time. Expect a more thorough monthlog in future.</p>
<p><strong>Note:</strong> Posts are not ordered in any particular way.
If you find an article you think I might like, send it to me via one of the messaging channels on my homepage.</p>
<h1 id="read">Read</h1>
<ul>
<li><strong><a rel="noopener" target="_blank" href="https://blog.ipfs.io/2020-04-28-go-ipfs-0-5-0/">IPFS 0.5 Announcement</a></strong> - I've been following IPFS for a few years with great interest.
It's amazing to see the project develop and performance improve.
<a rel="noopener" target="_blank" href="https://news.ycombinator.com/item?id=23010245">Discussion on HN</a></li>
</ul>
<h1 id="watch">Watch</h1>
<p>NA</p>
<h1 id="listen">Listen</h1>
<ul>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://pca.st/cpudjmbg">The Changelog: Securing the Web with Let's Encrypt</a></strong> - Let's Encrypt has had a massive impact on the security of the web, making it easy for anyone to obtain an SSL certificate for their website.</p>
</li>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://pca.st/j2d38lob">SE Daily: Ceph Storage System w/ Sage Weil</a></strong> - Ceph is a great story of open source success against established enterprise firms.
The algorithms and mechanics behind Ceph are quite elegant and worth looking at if you're at all interested in distributed systems.</p>
</li>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://pca.st/lu4yentz">Go Time: The Monolith vs Microservices Debate</a></strong> - A nice summary of monoliths vs microservices and what we've learned through the journey from monolith to microservice.</p>
</li>
</ul>
<h1 id="software-and-libraries">Software and Libraries</h1>
<ul>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://github.com/orf/dirscan">Dirscan</a></strong> - '<em>A high performance tool for summarizing large directories or drives.</em>'
Scan large, possibly networked, directories.
Can report the largest files, smallest files, or some other kind of query.
Written in Rust.</p>
</li>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://github.com/ajeetdsouza/zoxide">Zoxide</a></strong> - '<em>A faster way to navigate your filesystem.</em>'
Like other fast navigation systems including <a rel="noopener" target="_blank" href="https://github.com/rupa/z">z</a>, Zoxide allows for quick navigation of frequently visited directories.
Written in Rust so it's significantly faster than many of the existing shell script only solutions.</p>
</li>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://github.com/nmattia/niv">Niv</a></strong> - '<em>Easy dependency management for Nix projects.</em>'
I've started using Niv alongside Lorri for my local Nix development.
Niv's most basic feature is simplifying the Nix pinning mechanism and making it easier to roll forward to a new nixpkgs-unstable and rollback if there is an issue.
Expect a blog post soon.</p>
</li>
</ul>
<h1 id="recommended-sources-to-follow">Recommended Sources to Follow</h1>
<p>Below are a few media sources and voices I follow.</p>
<h2 id="blogs">Blogs</h2>
<ul>
<li><strong><a rel="noopener" target="_blank" href="https://endler.dev/">Matthias Endler</a></strong>: Rust developer and host of 'Hello, Rust!'</li>
<li><strong><a rel="noopener" target="_blank" href="http://paulgraham.com/">Paul Graham</a></strong>: Member of YC, offers insightful well-written posts about business and software.</li>
<li><strong><a rel="noopener" target="_blank" href="https://victorzhou.com/">Victor Zhou</a></strong>: Recent Princeton CS Graduate publishing informative guides with some focus on Machine Learning.</li>
<li><strong><a rel="noopener" target="_blank" href="https://campoy.cat/">Francesc Campoy</a></strong>: Gopher and JustForFunc host.</li>
<li><strong><a rel="noopener" target="_blank" href="https://deterministic.space/">Deterministic.Space - Pascal Hertleif's blog (g/KillerCup)</a></strong>: Mostly Rust stuff.</li>
</ul>
<h2 id="newsletters">Newsletters</h2>
<ul>
<li><strong><a rel="noopener" target="_blank" href="https://this-week-in-rust.org/">This Week In Rust</a></strong> - Rust news every week.</li>
<li><strong><a rel="noopener" target="_blank" href="https://ethhub.substack.com/">EthHub Weekly</a></strong> - Weekly Ethereum updates, a quick paragraph summarising each headline.</li>
</ul>
<h2 id="podcasts">Podcasts</h2>
<ul>
<li><strong><a rel="noopener" target="_blank" href="https://changelog.com/podcast">The Changelog</a></strong>: 'Conversations with the hackers, leaders, and innovators of software development.'</li>
<li><strong><a rel="noopener" target="_blank" href="https://softwareengineeringdaily.com/category/all-episodes/exclusive-content/Podcast">Software Engineering Daily</a></strong>: Daily conversations covering anything Software Development related.</li>
<li><strong><a rel="noopener" target="_blank" href="https://linuxunplugged.com/">Linux Unplugged</a></strong>: A Jupiter Broadcasting show. Relaxed, focused on Linux but touches on all things Unix and Open Source.</li>
<li><strong><a rel="noopener" target="_blank" href="http://investorfieldguide.com/podcast/">Invest Like the Best</a></strong>: Finance and investing podcast often featuring Crypto.</li>
<li><strong><a rel="noopener" target="_blank" href="https://pca.st/3Gld">Y Combinator</a></strong>: Conversations with Y Combinator founders.</li>
<li><strong><a rel="noopener" target="_blank" href="https://pca.st/1uHy">Into the Ether</a></strong>: 'Focusing on all things Ethereum, the leading blockchain for decentralized applications.'</li>
</ul>
Monthlog 05: March 20202020-05-10T00:00:00+13:002020-05-10T00:00:00+13:00https://hugoreeves.com/posts/monthlog/05/<p>This is the <strong>05</strong> installment in my <strong>'Monthlog'</strong> - a public list of blog posts, announcements, videos, podcasts, software and libraries that catch my attention each month.
I hope that regular readers will skim through the listings and find one, or multiple, things that pique their interest.</p>
<p>I didn't do a good job with the monthlog this time. Expect a more thorough monthlog in future.</p>
<p><strong>Note:</strong> Posts are not ordered in any particular way.
If you find an article you think I might like, send it to me via one of the messaging channels on my homepage.</p>
<h1 id="read">Read</h1>
<ul>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://tailscale.com/blog/how-tailscale-works/">How Tailscale Works</a></strong> - There are new few new entrants to the private VPN space popping up.
The good thing is many of them are fully or partially open source.
If you're interested in this kind of thing, take a look at <a rel="noopener" target="_blank" href="https://github.com/slackhq/nebula">Nebula</a>.
<a rel="noopener" target="_blank" href="https://news.ycombinator.com/item?id=22644357">Discussion on HN</a></p>
</li>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://devblogs.microsoft.com/oldnewthing/20200317-00/?p=103566">We called it RAID because it kills bugs dead</a></strong> - A look back at Microsoft bug tracking and some lessons learned.
<a rel="noopener" target="_blank" href="https://news.ycombinator.com/item?id=22612281">Discussion on HN</a></p>
</li>
<li>
<p><strong><a rel="noopener" target="_blank" href="http://blog.ifost.org.au/2020/03/how-i-teach-classes-remotely.html">How I teach classes remotely</a></strong> - Unfortunately online teaching is now a big thing.
I'm not a teacher but it's interesting to see what teachers consider when teaching online.
<a rel="noopener" target="_blank" href="https://news.ycombinator.com/item?id=22612343">Discussion on HN</a></p>
</li>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://dave.cheney.net/2020/02/23/the-zen-of-go">Dave Cheney: The Zen of Go</a></strong> - Every programming language has its own set of idioms, culture, and values.
I think that understanding the programming beliefs of language authors helps me gain a broader picture of how to code and systems can and should be architected.</p>
</li>
</ul>
<h1 id="watch">Watch</h1>
<ul>
<li><strong><a rel="noopener" target="_blank" href="https://youtu.be/tyuDitqoZbM">Lifetimes - Rust</a></strong> - I'm still trying to fully wrap my head around actually using lifetimes in Rust.
Even if you don't write Rust, you may find this video interesting as the lifetime mechanism is quite novel and often helps people reason about non-Rust code.
<a rel="noopener" target="_blank" href="https://reddit.com/r/rust/comments/fqeq2v/a_video_to_help_you_climb_one_of_rusts_highest/">Discussion on r/rust</a></li>
</ul>
<h1 id="listen">Listen</h1>
<ul>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://pca.st/2a49jx4b">Go Time: The Zen of Go w/ Dave Cheney</a></strong> - To accompany the blog post linked previously, Dave Cheney discusses the Zen of Go.</p>
</li>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://pca.st/cwna2mgu">SE Daily: Alpaca Stock Trading API w/ Yoshi Yokokawa</a></strong> - Finance and tech mix in interesting ways.
Alpaca brings an API to stockbrokers.</p>
</li>
</ul>
<h1 id="software-and-libraries">Software and Libraries</h1>
<p>N/A</p>
<h1 id="recommended-sources-to-follow">Recommended Sources to Follow</h1>
<p>Below are a few media sources and voices I follow.</p>
<h2 id="blogs">Blogs</h2>
<ul>
<li><strong><a rel="noopener" target="_blank" href="https://endler.dev/">Matthias Endler</a></strong>: Rust developer and host of 'Hello, Rust!'</li>
<li><strong><a rel="noopener" target="_blank" href="http://paulgraham.com/">Paul Graham</a></strong>: Member of YC, offers insightful well-written posts about business and software.</li>
<li><strong><a rel="noopener" target="_blank" href="https://victorzhou.com/">Victor Zhou</a></strong>: Recent Princeton CS Graduate publishing informative guides with some focus on Machine Learning.</li>
<li><strong><a rel="noopener" target="_blank" href="https://campoy.cat/">Francesc Campoy</a></strong>: Gopher and JustForFunc host.</li>
<li><strong><a rel="noopener" target="_blank" href="https://deterministic.space/">Deterministic.Space - Pascal Hertleif's blog (g/KillerCup)</a></strong>: Mostly Rust stuff.</li>
</ul>
<h2 id="newsletters">Newsletters</h2>
<ul>
<li><strong><a rel="noopener" target="_blank" href="https://this-week-in-rust.org/">This Week In Rust</a></strong> - Rust news every week.</li>
<li><strong><a rel="noopener" target="_blank" href="https://ethhub.substack.com/">EthHub Weekly</a></strong> - Weekly Ethereum updates, a quick paragraph summarising each headline.</li>
</ul>
<h2 id="podcasts">Podcasts</h2>
<ul>
<li><strong><a rel="noopener" target="_blank" href="https://changelog.com/podcast">The Changelog</a></strong>: 'Conversations with the hackers, leaders, and innovators of software development.'</li>
<li><strong><a rel="noopener" target="_blank" href="https://softwareengineeringdaily.com/category/all-episodes/exclusive-content/Podcast">Software Engineering Daily</a></strong>: Daily conversations covering anything Software Development related.</li>
<li><strong><a rel="noopener" target="_blank" href="https://linuxunplugged.com/">Linux Unplugged</a></strong>: A Jupiter Broadcasting show. Relaxed, focused on Linux but touches on all things Unix and Open Source.</li>
<li><strong><a rel="noopener" target="_blank" href="http://investorfieldguide.com/podcast/">Invest Like the Best</a></strong>: Finance and investing podcast often featuring Crypto.</li>
<li><strong><a rel="noopener" target="_blank" href="https://pca.st/3Gld">Y Combinator</a></strong>: Conversations with Y Combinator founders.</li>
<li><strong><a rel="noopener" target="_blank" href="https://pca.st/1uHy">Into the Ether</a></strong>: 'Focusing on all things Ethereum, the leading blockchain for decentralized applications.'</li>
</ul>
Monthlog 04: February 20202020-03-01T00:00:00+13:002020-03-01T00:00:00+13:00https://hugoreeves.com/posts/monthlog/04/<p>This is the <strong>04</strong> installment in my <strong>'Monthlog'</strong> - a public list of blog posts, announcements, videos, podcasts, software and libraries that catch my attention each month.
I hope that regular readers will skim through the listings and find one, or multiple, things that pique their interest.</p>
<p><strong>Note:</strong> Posts are not ordered in any particular way.
If you find an article you think I might like, send it to me via one of the messaging channels on my homepage.</p>
<h1 id="read">Read</h1>
<ul>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://blog.cloudflare.com/technical-details-of-why-cloudflare-chose-amd-epyc-for-gen-x-servers/">Cloudflare: Technical Details of Why Cloudflare Chose AMD EPYC for Gen X Servers</a></strong> - AMD Epyc is starting to really improve AMD's server positioning.
The author identifies improved cache locality, due to a larger L3 cache, providing performance benefits over Intel CPU's with the same number of cores.
<a rel="noopener" target="_blank" href="https://news.ycombinator.com/item?id=22456702">Discussion on HN</a></p>
</li>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://fasterthanli.me/blog/2020/i-want-off-mr-golangs-wild-ride/">I want off Mr. Golang's Wild Ride</a></strong> - A Rust user outlines - in "rant" form - many of the issues they have bumped into when writing Go code over '<em>thousands of hours</em>'.
<a rel="noopener" target="_blank" href="https://old.reddit.com/r/rust/comments/fax7lj/i_want_off_mr_golangs_wild_ride/">Discussion on r/rust</a></p>
</li>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://matklad.github.io/2020/02/14/why-rust-is-loved.html">Why is Rust the Most Loved Programming Language?</a></strong> - A Rust user outlines a few language features that might explain Rust's position as the most loved language in the StackOverflow survey.
<a rel="noopener" target="_blank" href="https://old.reddit.com/r/rust/comments/f41ynd/blog_post_why_is_rust_the_most_loved_programming/">Discussion on r/rust</a></p>
</li>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://blog.antoyo.xyz/vim-tips">Antoyo's Vim Tips</a></strong> - A Vim users personal database of Vim tips.
<a rel="noopener" target="_blank" href="https://old.reddit.com/r/vim/comments/f0iwrk/my_personal_list_of_vim_tips/">Discussion on r/vim</a></p>
</li>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://fuchsia.googlesource.com/fuchsia/+/refs/heads/master/docs/project/policy/programming_languages.md">Fuschia Programming Language Policy</a></strong> - Document from the Google Fuschia (A new operating system) source repository outlines the language guidelines for Fuschia.
The big surprises here seem to be a complete rejection of Golang, even though Google is a big Go supporter, and the decision not to use Rust in the Kernel.</p>
</li>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://understandlegacycode.com/blog/avoid-rewriting-a-legacy-system-from-scratch-by-strangling-it/">Avoid rewriting a legacy system from scratch, by strangling it</a></strong> - It's quite a common sentiment that full project rewrites almost always end badly.
This article explains the challenges faced when rewriting projects and a method to make full rewrites more achievable.</p>
</li>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://utcc.utoronto.ca/%7Ecks/space/blog/sysadmin/RunningServersNotTrivial">Running servers (and services) well is not trivial</a></strong> - A response to the notion that 'self-hosting isn't that hard'.</p>
</li>
</ul>
<h1 id="watch">Watch</h1>
<ul>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://www.youtube.com/watch?v=a6Q8Na575qc&list=PLyzOVJj3bHQuloKGG59rS43e29ro7I57J">MIT, Lecture 3: Editors (vim) (2020)</a></strong> - MIT 'The Missing Semester' introduction to Vim.
If you've used Vim for a while, listen to this in the background and you might learn a thing or two.
Even if you don't plan to use Vim, the analysis of Vim's modal editing might be of interest.</p>
</li>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://fosdem.org/2020/schedule/event/rust_cargo_deny/">FOSDEM: Cargo Deny</a></strong> - 'A talk about cargo-deny, why we created it, and how it helps us manage our dependencies in the long term.'</p>
</li>
</ul>
<h1 id="listen">Listen</h1>
<ul>
<li><strong><a rel="noopener" target="_blank" href="https://pca.st/v1yyoy4c">Rustacean Station: What's New in Rust 1.41</a></strong> - A 45 Minute outline of the new features and changes in Rust version 1.41.</li>
</ul>
<h1 id="software-and-libraries">Software and Libraries</h1>
<ul>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://github.com/Nukesor/pueue">Pueue</a></strong> - '<em>A daemon for managing long-running shell commands.</em>'
Written in Rust, could be really useful for long-running tasks that must run sequentially, like Machine Learning workloads.</p>
</li>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://github.com/target/lorri">Lorri</a></strong> - '<em>Your project's nix-env.</em>'
Finally started using this.
Written in Rust, Lorri provides a Daemon to build nix-shell environments in the background.
If you use nix, you'll know the pain of long shell builds.
Lorri builds things in the background so your nix-env loads more quickly and reloads transparently whenever you change your shell definition.
Expect to see a post on how I use lorri day to day soon.</p>
</li>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://github.com/cjbassi/ytop">ytop</a></strong> - '<em>A TUI system monitor written in Rust</em>.'
Yet another rewrite by <a rel="noopener" target="_blank" href="https://github.com/cjbassi/">CJbassi</a> of his 'top' program.
This time it's written in Rust, currently approaching feature parity with the old <a rel="noopener" target="_blank" href="https://github.com/cjbassi/gotop">gotop</a>.</p>
</li>
<li>
<p><strong><a rel="noopener" target="_blank" href="https://github.com/MaterializeInc/materialize">Materialize</a></strong> - A newly announced company offering a tool to use SQL queries on live, streaming data.
Cool to see Rust being used here, in a very latency-sensitive environment with high data throughput.
A year ago I would imagine Go would be used for this kind of task but I think people are slowly coming around to Rust being used in this kind of situation.</p>
</li>
</ul>
<h1 id="recommended-sources-to-follow">Recommended Sources to Follow</h1>
<p>Below are a few media sources and voices I follow.</p>
<h2 id="blogs">Blogs</h2>
<ul>
<li><strong><a rel="noopener" target="_blank" href="https://endler.dev/">Matthias Endler</a></strong>: Rust developer and host of 'Hello, Rust!'</li>
<li><strong><a rel="noopener" target="_blank" href="http://paulgraham.com/">Paul Graham</a></strong>: Member of YC, offers insightful well-written posts about business and software.</li>
<li><strong><a rel="noopener" target="_blank" href="https://victorzhou.com/">Victor Zhou</a></strong>: Recent Princeton CS Graduate publishing informative guides with some focus on Machine Learning.</li>
<li><strong><a rel="noopener" target="_blank" href="https://campoy.cat/">Francesc Campoy</a></strong>: Gopher and JustForFunc host.</li>
<li><strong><a rel="noopener" target="_blank" href="https://deterministic.space/">Deterministic.Space - Pascal Hertleif's blog (g/KillerCup)</a></strong>: Mostly Rust stuff.</li>
</ul>
<h2 id="newsletters">Newsletters</h2>
<ul>
<li><strong><a rel="noopener" target="_blank" href="https://this-week-in-rust.org/">This Week In Rust</a></strong> - Rust news every week.</li>
<li><strong><a rel="noopener" target="_blank" href="https://ethhub.substack.com/">EthHub Weekly</a></strong> - Weekly Ethereum updates, a quick paragraph summarising each headline.</li>
</ul>
<h2 id="podcasts">Podcasts</h2>
<ul>
<li><strong><a rel="noopener" target="_blank" href="https://changelog.com/podcast">The Changelog</a></strong>: 'Conversations with the hackers, leaders, and innovators of software development.'</li>
<li><strong><a rel="noopener" target="_blank" href="https://softwareengineeringdaily.com/category/all-episodes/exclusive-content/Podcast">Software Engineering Daily</a></strong>: Daily conversations covering anything Software Development related.</li>
<li><strong><a rel="noopener" target="_blank" href="https://linuxunplugged.com/">Linux Unplugged</a></strong>: A Jupiter Broadcasting show. Relaxed, focused on Linux but touches on all things Unix and Open Source.</li>
<li><strong><a rel="noopener" target="_blank" href="http://investorfieldguide.com/podcast/">Invest Like the Best</a></strong>: Finance and investing podcast often featuring Crypto.</li>
<li><strong><a rel="noopener" target="_blank" href="https://pca.st/3Gld">Y Combinator</a></strong>: Conversations with Y Combinator founders.</li>
<li><strong><a rel="noopener" target="_blank" href="https://pca.st/1uHy">Into the Ether</a></strong>: 'Focusing on all things Ethereum, the leading blockchain for decentralized applications.'</li>
</ul>
Monthlog 03: January 20202020-01-29T00:11:00+13:002020-01-29T00:11:00+13:00https://hugoreeves.com/posts/monthlog/03/<p>Happy New Year!</p>
<p>This is the <strong>03</strong> installment in my <strong>'Monthlog'</strong> - a public list of blog posts, announcements, software, libraries, videos and podcasts that catch my attention each month.
I hope that regular readers will skim through the listings and find one, or multiple, things that pique their interest.</p>
<p><strong>Note:</strong> Posts are not ordered in any particular way.
If you find an article you think I might like, send it to me via one of the messaging channels on my homepage.</p>
<h1 id="read">Read</h1>
<p><strong><a rel="noopener" target="_blank" href="https://www.calhoun.io/why-cant-we-settle-on-a-single-application-structure-in-go/">John Calhoun: Why Can't we Settle on a Single Application Structure In Go</a></strong> - If you are new to go, within your first 50 to 200 hours, this blog post will help you understand some basics of Go project structuring.
The first in a series that covers various common Go repository structures.</p>
<p><strong><a rel="noopener" target="_blank" href="https://medium.com/@alexkaskasoli/pull-based-cd-pipelines-for-security-4e044b403f56">Pull Based CD Pipelines for Security</a></strong> - Kubernetes focused but general to most CICD processes.
Encourages replacing automated CD deployments reliant on a push to Docker, K8s, etc. with a GitOps based pull.
<a rel="noopener" target="_blank" href="https://reddit.com/r/kubernetes/comments/eku68p/security_advantages_of_pullbased_cd_pipelines/">Discussion on r/kubernetes</a></p>
<p><strong><a rel="noopener" target="_blank" href="https://www.nushell.sh/blog/2019/12/31/happy-nu-year-2020.html">Happy Nu Year: Nushell's Year in Review</a></strong> - An overview of where Nushell started and where it's heading.</p>
<p><strong><a rel="noopener" target="_blank" href="https://www.nushell.sh/blog/2020/01/07/nushell-0_8_0.html">Nushell v0.8</a></strong> - Various improvements, notably all calls of <code>.unwrap()</code> have been removed which should make Nushell less prone to panics and more graceful in error handling.
<a rel="noopener" target="_blank" href="https://www.reddit.com/r/rust/comments/elfv0p/nushell_080/">Discussion or r/rust</a></p>
<p><strong><a rel="noopener" target="_blank" href="https://kevinlynagh.com/financial-plan/">Financial Plan</a></strong> - Spotted in HN new.
A short post with some interesting details on retirement planning and income maximization as a Software Engineer.</p>
<p><strong><a rel="noopener" target="_blank" href="https://multithreaded.stitchfix.com/blog/2019/12/19/good-marketing-decisions/">Want to make good business decisions? Learn causality</a></strong> - Understand causality and what it means for making informed decisions.
<a rel="noopener" target="_blank" href="https://news.ycombinator.com/item?id=21991268">Discussion on HN</a></p>
<p><strong><a rel="noopener" target="_blank" href="https://grafana.com/blog/2020/01/09/introducing-tanka-our-way-of-deploying-to-kubernetes/">Grafana: Introducing Tanka</a></strong> - Grafana announces a new Kubernetes configuration definition tool, an alternative to Helm.
There's so much going on with Kubernetes.
I used Kubernetes, Istio, and Helm back in 2018 and the beginning of 2019, but have since dropped the cluster as I moved to serverless.
It feels like so much is changing, things are getting simpler, and Kubernetes itself is stabilizing, but the best practices for things like configuration definitions are still evolving.
<a rel="noopener" target="_blank" href="https://news.ycombinator.com/item?id=22011251">Discussion on HN</a></p>
<p><strong><a rel="noopener" target="_blank" href="https://markmcb.com/2020/01/07/five-years-of-btrfs/">Five Years of Btrfs</a></strong> - Always interested to see updates on the CoW (Copy on Write) Cold War between ZFS, Btrfs and to a lesser extent, XFS.
I've been running Btrfs on a single Nvme drive in an Intel NUC for about 7 months now without issue, I have really enjoyed the process and the subvolume features are quite useful.
I'd recommend checking out Btrfs for any new desktop or server Linux installs.
<a rel="noopener" target="_blank" href="https://news.ycombinator.com/item?id=22159204">Discussion on HN</a></p>
<p><strong><a rel="noopener" target="_blank" href="https://www.atlassian.com/git/tutorials/comparing-workflows/gitflow-workflow">Atlassian: Git Flow Workflow</a></strong> - The Git Flow workflow.
I've used this heavily before for many of my personal projects, decided recently to brush up on the workflow.
I personally enjoy the develop vs master separation and I think it makes a lot of sense in terms of minimizing merge conflicts and allowing earlier merges into the cutting edge tree.</p>
<p><strong><a rel="noopener" target="_blank" href="https://www.monterail.com/blog/famous-companies-using-elixir">Six Famous Companies Using Elixir</a></strong> - I gave Elixir a go in late 2018 and found it to be quite an interesting and easy to use language.
Seeing how some top companies, including Pinterest, use Elixir in production lends credibility to the production readiness of the language.
<a rel="noopener" target="_blank" href="https://reddit.com/r/elixir/comments/esantm/six_famous_companies_using_elixirand_why_they/">Discussion on r/elixir</a></p>
<h3 id="the-actix-web-drama">The Actix Web drama</h3>
<p>Those of you familiar with Rust or following the <a rel="noopener" target="_blank" href="https://reddit.com/r/rust">r/rust</a> subreddit will have noticed the apparent drama surrounding Actix Web.
Through the second half of January a chain of blog posts, Github issues, and Reddit discussions stirred up a heated discussion surrounding the use of Rust's <code>unsafe</code> mechanism within the Actix project.
In particular, people in the Rust community were disappointed by the author's decision to close pull requests that aimed to make Actix safer by avoiding undefined behavior (UB).
The issue eventually came to a resolution, but I think it's a great case study to remember and a lesson for everyone involved in consuming or maintaining open source projects.</p>
<p><em>The following blog posts are in chronological order.</em></p>
<p><strong><a rel="noopener" target="_blank" href="https://medium.com/@shnatsel/smoke-testing-rust-http-clients-b8f2ee5db4e6">Smoke-testing Rust HTTP Clients</a></strong> - It begins.
By this point in time, there had been a few minor controversies surrounding Actix Web.
This post highlighted the issues of insecurity and, mostly unintentionally, kicked off the most recent round of Actix Web drama.
<a rel="noopener" target="_blank" href="https://reddit.com/r/rust/comments/epoloy/ive_smoketested_rust_http_clients_heres_what_i/">Discussion on r/rust</a></p>
<p><strong><a rel="noopener" target="_blank" href="https://reddit.com/r/rust/comments/epzukc/actix_web_repository_cleared_by_author_who_says/">The Actix Web Repository is Cleared</a></strong> - The Actix Web author, after enduring a few unnecessary and entirely unhelpful personal attacks, decided to delete the Actix repos.</p>
<p><strong><a rel="noopener" target="_blank" href="https://words.steveklabnik.com/a-sad-day-for-rust">A sad day for Rust</a></strong> - This post from Steve Klabnik does a brilliant job of highlighting the general struggles of open source, through the lens of the unfolding Actix Web situation.
<a rel="noopener" target="_blank" href="https://reddit.com/r/rust/comments/eq11t3/a_sad_day_for_rust/">Discussion on r/rust</a></p>
<p><strong><a rel="noopener" target="_blank" href="https://github.com/actix/actix-web/issues/1289">The Future of Actix Web</a></strong> - The Actix Web author decides to forge a path forward for the project.
A new maintainer is announced.
<a rel="noopener" target="_blank" href="https://reddit.com/r/rust/comments/erdklb/actixweb_is_back_in_the_main_repo_with_a_note/">Discussion on r/rust</a></p>
<h1 id="watch">Watch</h1>
<p><strong><a rel="noopener" target="_blank" href="https://www.youtube.com/watch?v=DLRfT44e8uQ&t=879s">Microservices: A Retrospective</a></strong> - One of the greatest presentations I have seen on the state of and history of microservices.
It provides a critical analysis of the proposed benefits of Microservices and the ways in which those implementing Microservice architectures have often failed to achieve those benefits.
<strong>I absolutely love this talk.</strong></p>
<p><strong><a rel="noopener" target="_blank" href="https://www.youtube.com/watch?v=sSm2dRarhPo">Microservices + Events + Docker = A Perfect Trio</a></strong> - Rewatching this a year after my first viewing.
Even if you're not implementing microservices or have no interest in learning about them, microservices can teach you a lot about best practice software development techniques, particularly for achieving scale.</p>
<h1 id="listen">Listen</h1>
<p><strong><a rel="noopener" target="_blank" href="https://pca.st/oe8iyhk8">Invest Like the Best: Investing Pre-Company w/ Matt Clifford</a></strong> - I had never heard of this type of investing, providing a grant to individuals before they have a business or even an idea.
Great thoughts on the value individuals can bring even though they may lack a solid plan.</p>
<p><strong><a rel="noopener" target="_blank" href="https://pca.st/twsgriuh">All Hands on Tech: Why 2020 is the year of Kubernetes w/ Kelsey Hightower</a></strong> - Relatively short, compared to the next two.
A higher level conversation surrounding the evolution of Kubernetes and the value it currently provides to those who chose to run it.</p>
<p><strong><a rel="noopener" target="_blank" href="https://pca.st/qlwr1xh4">Software Engineering Daily: Kubernetes Progress w/ Kelsey Hightower</a></strong> - 1 hour long and touching on all things Kubernetes with Kelsey's unique perspective from the Google Cloud Side.</p>
<p><strong><a rel="noopener" target="_blank" href="https://pca.st/8zqdv8ne">Go Time: Cloudy with a chance of Kelsey Hightower</a></strong> - Kelsey's doing the rounds this month.
The most laidback of the four Kelseycasts, general ideas around the design of Kubernetes.
I'm starting to feel like Kubernetes is the operating system of the compute cloud.</p>
<p><strong><a rel="noopener" target="_blank" href="https://pca.st/qlwr1xh4">Software Engineering Daily: Kubernetes Progress w/ Kelsey Hightower</a></strong> - Another one.
I have no idea why I listened to 4 hours of Kelsey Hightower talking about Kubernetes.</p>
<p><strong><a rel="noopener" target="_blank" href="https://pca.st/rn3kbqhi">Software Engineering Daily: Amazon EC2 w/ Dave Brown</a></strong> - A great look at the history of some Amazon Compute products and how cloud providers optimize VM's and minimize latency.</p>
<h1 id="software-and-libraries">Software and Libraries</h1>
<p><strong><a rel="noopener" target="_blank" href="https://github.com/mgdm/htmlq">htmlq</a></strong> - 'Like jq, but for HTML.' Enables querying HTML by selectors like id and tag. Has not been updated in 8 months. Written in Rust.</p>
<p><strong><a rel="noopener" target="_blank" href="https://www.unisonweb.org/">The Unison Programming Language</a></strong> - A really interesting new language that provides one killer, as far as I know, previously unseen feature.
I don't think this language will go mainstream but some of the ideas pioneered here might make it into future mainstream languages.
The scratch based code editing, ie. you have no code directory, completely changes the developer ergonomics and, in my mind, poses the largest barrier to adoption of this language.
<a rel="noopener" target="_blank" href="https://news.ycombinator.com/item?id=22009912">Discussion on HN</a></p>
<p><strong><a rel="noopener" target="_blank" href="https://github.com/grafana/tanka">Tanka</a></strong> - 'Flexible, reusable and concise configuration for Kubernetes.'
From Grafana, announcement linked above.
If I need to start back up a Kubernetes cluster I'll definitely look at this vs Helm.
Grafana is a tool I love and Grafana has also put out a lot of great open-source tools recently such as <a rel="noopener" target="_blank" href="https://github.com/grafana/loki">Loki</a>.
It will be interesting to see whether this can garner any adoption.
<a rel="noopener" target="_blank" href="https://tanka.dev/">See tanka.dev</a></p>
<p><strong><a rel="noopener" target="_blank" href="https://github.com/hyperium/tonic">Tonic: Rust GRPC with Async/Await</a></strong> - Amazing to see usable and fast Rust libraries using async/await.
It sounds like a lot of people are waiting on better async/await based libraries to make the leap to full Rust on the server.
Tonic releasing as v0.1 with async/await is going to change the game.
<a rel="noopener" target="_blank" href="https://luciofran.co/tonic-0-1-release/">v0.1 Announcement</a>.
<a rel="noopener" target="_blank" href="https://reddit.com/r/rust/comments/eomgrr/tonic_01_has_arrived/">Discussion on r/rust</a></p>
<p><strong><a rel="noopener" target="_blank" href="https://github.com/cloudflare/boringtun/">BoringTun</a></strong> - 'Userspace WireGuard® Implementation in Rust.'
Cloudflare is definitely embracing Rust and Open Source.
Wireguard is great, I use it, and the potential improvements that might come from a Rust based implementation, over the default wireguard-go userspace implementation, seem worthwhile.
Progress seems to have ceased since November 2019.</p>
<p><strong><a rel="noopener" target="_blank" href="https://github.com/slog-rs/slog">Slog</a></strong> - 'Structured, contextual, extensible, composable logging for Rust'
Having spent a lot of time writing Go over the past few years, I began to look for a configurable logger a bit like <a rel="noopener" target="_blank" href="https://github.com/sirupsen/logrus">logrus</a>.
Slog seems to be a standout, with 808 stars.</p>
<p><strong><a rel="noopener" target="_blank" href="https://github.com/Nemo157/cargo-lichking">Cargo Lichking</a></strong> - 'Automated license checking for Rust.
<code>cargo lichking</code> is a Cargo subcommand that checks licensing information for dependencies.'
License checking is always a pain but an important part of open sourcing any project, this tool seems to make Rust license checking easier.</p>
<h1 id="recommended-sources-to-follow">Recommended Sources to Follow</h1>
<p>Below are a few media sources and voices I follow.</p>
<h2 id="blogs">Blogs</h2>
<ul>
<li><strong><a rel="noopener" target="_blank" href="https://endler.dev/">Matthias Endler</a></strong>: Rust developer and host of 'Hello, Rust!'</li>
<li><strong><a rel="noopener" target="_blank" href="http://paulgraham.com/">Paul Graham</a></strong>: Member of YC, offers insightful well written posts about business and software.</li>
<li><strong><a rel="noopener" target="_blank" href="https://victorzhou.com/">Victor Zhou</a></strong>: Recent Princeton CS Graduate publishing informative guides with some focus on Machine Learning.</li>
<li><strong><a rel="noopener" target="_blank" href="https://campoy.cat/">Francesc Campoy</a></strong>: Gopher and JustForFunc host.</li>
<li><strong><a rel="noopener" target="_blank" href="https://deterministic.space/">Deterministic.Space - Pascal Hertleif's blog (g/KillerCup)</a></strong>: Mostly Rust stuff.</li>
</ul>
<h2 id="newsletters">Newsletters</h2>
<ul>
<li><strong><a rel="noopener" target="_blank" href="https://this-week-in-rust.org/">This Week In Rust</a></strong> - Rust news every week.</li>
<li><strong><a rel="noopener" target="_blank" href="https://ethhub.substack.com/">EthHub Weekly</a></strong> - Weekly Ethereum updates, a quick paragraph summarising each headline.</li>
</ul>
<h2 id="podcasts">Podcasts</h2>
<ul>
<li><strong><a rel="noopener" target="_blank" href="https://changelog.com/podcast">The Changelog</a></strong>: 'Conversations with the hackers, leaders, and innovators of software development.'</li>
<li><strong><a rel="noopener" target="_blank" href="https://softwareengineeringdaily.com/category/all-episodes/exclusive-content/Podcast">Software Engineering Daily</a></strong>: Daily conversations covering anything Software Development related.</li>
<li><strong><a rel="noopener" target="_blank" href="https://linuxunplugged.com/">Linux Unplugged</a></strong>: A Jupiter Broadcasting show. Relaxed, focused on Linux but touches on all things Unix and Open Source.</li>
<li><strong><a rel="noopener" target="_blank" href="http://investorfieldguide.com/podcast/">Invest Like the Best</a></strong>: Finance and investing podcast often featuring Crypto.</li>
<li><strong><a rel="noopener" target="_blank" href="https://pca.st/3Gld">Y Combinator</a></strong>: Conversations with Y Combinator founders.</li>
<li><strong><a rel="noopener" target="_blank" href="https://pca.st/1uHy">Into the Ether</a></strong>: 'Focusing on all things Ethereum, the leading blockchain for decentralized applications.'</li>
</ul>
Monthlog 02: December 20192020-01-03T00:00:00+13:002020-01-03T00:00:00+13:00https://hugoreeves.com/posts/monthlog/02/<p>This is the <strong>02</strong> installment in my <strong>'Monthlog'</strong> - a public list of blog posts, announcements, software, libraries, videos and podcasts that catch my attention each month.
I hope that regular readers will skim through the listings and find one, or multiple, things that pique their interest.</p>
<p><strong>Note:</strong> Posts are not ordered in any particular way.
If you find an article you think I might like, send it to me via one of the messaging channels on my homepage.</p>
<h1 id="read">Read</h1>
<p><strong><a rel="noopener" target="_blank" href="https://deque.blog/2017/08/17/a-study-of-4-money-class-designs-featuring-martin-fowler-kent-beck-and-ward-cunningham-implementations/">Implementing Currency Classes in Code</a></strong> - Directed here by a link in the Idiomatic Rust talk linked below.
Will incorporate some of the ideas into Earl.</p>
<p><strong><a rel="noopener" target="_blank" href="https://github.com/rust-unofficial/patterns">Rust Patterns</a></strong> - Interesting reference material.
I particularly liked the Visitor pattern.</p>
<p><strong><a rel="noopener" target="_blank" href="https://blog.gopheracademy.com/advent-2019/cmdline/">Gopher Academy: Writing Friendly Command Line Applications</a></strong></p>
<p><strong><a rel="noopener" target="_blank" href="https://blog.burntsushi.net/rust-error-handling/">BurntSushi: Rust Error Handling</a></strong> - A great introduction to rust error handling that covers a variety of approaches.</p>
<p><strong><a rel="noopener" target="_blank" href="https://cfsamson.gitbook.io/green-threads-explained-in-200-lines-of-rust/background-information">Green Threads Explained in 200 Lines of Rust</a></strong></p>
<p><strong><a rel="noopener" target="_blank" href="https://victorzhou.com/blog/avoid-premature-optimization/">Victor Zhou: Avoid Premature Optimization</a></strong> - A story of optimizing too early without knowing where optimization is required.</p>
<p><strong><a rel="noopener" target="_blank" href="https://increment.com/teams/a-guide-to-distributed-teams/">A Guide to Distributed Teams</a></strong></p>
<p><strong><a rel="noopener" target="_blank" href="https://markosaric.com/google-amp">How to fight back against Google AMP</a></strong> - While AMP does offer benefits to web users, it's also a very contentious topic. <a rel="noopener" target="_blank" href="https://news.ycombinator.com/item?id=21712733">Discussion</a></p>
<p><strong><a rel="noopener" target="_blank" href="https://chasewilson.dev/blog/slowest-quicksort/">Chase Wilson: Slowest Quicksort in Rust</a></strong> - A guide to making your Rust code worse.</p>
<p><strong><a rel="noopener" target="_blank" href="https://2019.stateofjs.com/">2019 State of JS</a></strong> - Annual and always good to keep an eye on.
No matter where you work on the stack - backend, frontend, full-stack - Javascript drives a lot of change that will eventually impact you.
Check this out to see where things are going.</p>
<p><strong><a rel="noopener" target="_blank" href="https://medium.com/@kentbeck_7670/test-desiderata-94150638a4b3">Test Desiderata</a></strong> - Short and sharp. Revisit and hopefully improve your view of software testing.</p>
<p><strong><a rel="noopener" target="_blank" href="https://deterministic.space/how-to-order-rust-code.html">How to order Rust Code</a></strong> - Brief thoughts from Pascal on structuring Rust code. An avoid this, do that, kind of article.</p>
<p><strong><a rel="noopener" target="_blank" href="https://gen.medium.com/my-semester-with-the-snowflakes-888285f0e662">My Semester with the Snowflakes: A Veteran's Experience at Yale</a></strong> -
Essentially a 50-year-old Veteran's experience going to a top College with some high achieving Gen-Zs. A great read.</p>
<h1 id="watch">Watch</h1>
<p><strong><a rel="noopener" target="_blank" href="https://www.youtube.com/watch?v=0W20GPEqbcU">Pascal Hertleif: Declarative programming in Rust</a></strong> - From KillerCup, good to watch and see common functional patterns.</p>
<p><strong><a rel="noopener" target="_blank" href="https://www.youtube.com/watch?v=P2mooqNMxMs">Matthias Endler - Idiomatic Rust</a></strong> - Title says it all. <a rel="noopener" target="_blank" href="https://archive.fosdem.org/2018/schedule/event/rust_idiomatic/attachments/slides/2555/export/events/attachments/rust_idiomatic/slides/2555/Idiomatic_Rust___Matthias_Endler___FOSDEM_2018.pdf">View the slides</a></p>
<h1 id="listen">Listen</h1>
<p><strong><a rel="noopener" target="_blank" href="https://pca.st/yvzt5h4d">Go Time: Graph Databases with Francesc Campoy</a></strong> - Great introduction to graph databases by one of my favourite Gophers, Francesc Campoy.
Learn about dgraph's experience building a modern open source graph database, <a rel="noopener" target="_blank" href="https://github.com/dgraph-io/dgraph">Dgraph</a>, in Go.</p>
<p><strong><a rel="noopener" target="_blank" href="https://pca.st/ur8qpust">Invest Like the Best: All Things FinTech Investing with Ben Savage</a></strong> - Invest like the best is a great podcast and this episode offers particular insight into the entire world of FinTech. The future-focused discussion surrounding Crypto and new financial instruments is particularly interesting.</p>
<p><strong><a rel="noopener" target="_blank" href="https://pca.st/7movkplu">Invest Like the Best: How to Build a Great Product</a></strong></p>
<h1 id="software-and-libraries">Software and Libraries</h1>
<p><strong><a rel="noopener" target="_blank" href="https://github.com/nushell/nushell">Nu Shell</a></strong> - Discovered this a couple of months ago but it needs a mention.
I think of this as an attempt to turn your shell into an easily queryable API.
A bit like Powershell for Unix.
Written in Rust, not quite stable yet but inspiring a lot of buzz.
I look forward to following its development and adoption.</p>
<p><strong><a rel="noopener" target="_blank" href="https://starship.rs/">Starship RS</a></strong> - Discovered a few months ago after a Linux Unplugged episode.
An amazing cross shell prompt, I use it in fish, written in Rust.
I highly recommend, hopefully, it takes off.</p>
<p><strong><a rel="noopener" target="_blank" href="https://github.com/boyter/scc">SCC</a></strong> - A command line lines of code counter, similar to <a rel="noopener" target="_blank" href="https://github.com/XAMPPRocky/tokei">Tokei</a> (what I use) but with some extra features.
Written in Go.
Benchmarks 17% faster than Tokei on the Linux kernel repo.</p>
<p><strong><a rel="noopener" target="_blank" href="https://github.com/imsnif/bandwhich">Bandwhich, formerly "what"</a></strong> - Linux and MacOS CLI written in rust.
Displays bandwidth usage by process.
Renamed for 2020 from <em>what</em> to <em>bandwhich</em>.
Already packaged for Nix!</p>
<h1 id="recommended-sources-to-follow">Recommended Sources to Follow</h1>
<p>Below are a few media sources and voices I follow.</p>
<h2 id="blogs">Blogs</h2>
<ul>
<li><strong><a rel="noopener" target="_blank" href="https://endler.dev/">Matthias Endler</a></strong>: Rust developer and host of 'Hello, Rust!'</li>
<li><strong><a rel="noopener" target="_blank" href="http://paulgraham.com/">Paul Graham</a></strong>: Member of YC, offers insightful well written posts about business and software.</li>
<li><strong><a rel="noopener" target="_blank" href="https://campoy.cat/">Francesc Campoy</a></strong>: Gopher and JustForFunc host.</li>
<li><strong><a rel="noopener" target="_blank" href="https://deterministic.space/">Deterministic.Space - Pascal Hertleif's blog (g/KillerCup)</a></strong>: Mostly Rust stuff.</li>
<li><strong><a rel="noopener" target="_blank" href="https://this-week-in-rust.org/">This Week In Rust</a></strong></li>
<li><strong><a rel="noopener" target="_blank" href="https://ethhub.substack.com/">EthHub Weekly</a></strong></li>
</ul>
<h2 id="podcasts">Podcasts</h2>
<ul>
<li><strong><a rel="noopener" target="_blank" href="https://changelog.com/podcast">The Changelog</a></strong>: 'Conversations with the hackers, leaders, and innovators of software development.'</li>
<li><strong><a rel="noopener" target="_blank" href="https://linuxunplugged.com/">Linux Unplugged</a></strong>: A Jupiter Broadcasting show. Relaxed, focused on Linux but touches on all things Unix and Open Source.</li>
<li><strong><a rel="noopener" target="_blank" href="http://investorfieldguide.com/podcast/">Invest Like the Best</a></strong>: Finance and investing podcast often featuring Crypto.</li>
<li><strong><a rel="noopener" target="_blank" href="https://pca.st/1uHy">Into the Ether</a></strong>: 'Focusing on all things Ethereum, the leading blockchain for decentralized applications.'</li>
</ul>
Monthlog 01: November 20192019-11-30T00:00:00+00:002019-11-30T00:00:00+00:00https://hugoreeves.com/posts/monthlog/01/<p>This is the <strong>01</strong> installment in my <strong>'Monthlog'</strong> - a public list of blog posts, announcements, software, libraries, videos and podcasts that catch my attention each month.
I hope that regular readers will skim through the listings and find one, or multiple, things that pique their interest.</p>
<p><strong>Note:</strong> Posts are not ordered in any particular way.
If you find an article you think I might like, send it to me via one of the messaging channels on my homepage.</p>
<h1 id="reading">Reading</h1>
<ul>
<li><a rel="noopener" target="_blank" href="https://americanexpress.io/choosing-go/">American Express: Choosing Go</a>: Possibly the best article I have seen concisely outlining the common attractions of Go, and, in this case, why Go is an attractive language at American Express. <a rel="noopener" target="_blank" href="https://www.reddit.com/r/golang/comments/e1xri3/choosing_go_at_american_express/">Discussion</a>.</li>
<li><a rel="noopener" target="_blank" href="https://research.swtch.com/deps">Russ Cox's article on 'Our Software Dependency Problem'</a>: A good read for just about any dev. Outlines some of the challenges of software dependency.</li>
<li><a rel="noopener" target="_blank" href="https://blog.dgraph.io/post/releasing-badger-v2/">Releasing BadgerDB 2.0</a>: BadgerDB adds encryption at rest, compression and caching. <a rel="noopener" target="_blank" href="https://www.reddit.com/r/golang/comments/dypxr6/releasing_badgerdb_v20_compression_encryption_and/">Discussion</a>.</li>
<li><a rel="noopener" target="_blank" href="https://gohugo.io/news/0.60.0-relnotes/">Hugo v0.60</a>: A switch to CommonMark conformant GoldMark. This blog is now using v0.60. <a rel="noopener" target="_blank" href="https://www.reddit.com/r/golang/comments/e2hgwd/hugo_v0600_has_been_released_now_commonmark/">Discussion</a>.</li>
<li><a rel="noopener" target="_blank" href="https://www.mountaingoatsoftware.com/agile/user-stories">Agile User Stories</a>: How to write User Stories to define software functionality. Reading up on this as I want to formalize some of the necessary workflows for Earl.</li>
<li><a rel="noopener" target="_blank" href="https://matthewkmayer.github.io/blag/public/post/tdd-with-rust/">Rust TDD</a>: Interested in using TDD more.</li>
<li><a rel="noopener" target="_blank" href="https://trunkbaseddevelopment.com/">Trunk Based Development</a>: A git workflow that aims to minimize merge conflicts, primarily for small teams. Interesting, merges can be scary.</li>
<li><a rel="noopener" target="_blank" href="https://medium.com/@sidneyliebrand/how-fzf-and-ripgrep-improved-my-workflow-61c7ca212861">Medium: FZF + Ripgrep Workflow</a>: I read this a while ago but thought I'd link it here. Useful to tune vim with new fuzzy finding tools.</li>
</ul>
<h1 id="software-and-libraries">Software and Libraries</h1>
<p><strong><a rel="noopener" target="_blank" href="https://github.com/sharkdp/hyperfine">Hyperfine</a></strong> - Another Rust CLI tool from <a rel="noopener" target="_blank" href="https://github.com/sharkdp">SharkDP</a>.
Hyperfine benchmarks and compares the runtime of different shell commands, and offers a really simple <code>command X is X.XX times faster than command Y</code> result.</p>
<p><strong><a rel="noopener" target="_blank" href="https://github.com/r-darwish/topgrade">Topgrade</a></strong> - Rust CLI tool that updates packages across a number of package managers all at once.
Added to my home-manager setup and now in use on my Darwin and NixOS systems.</p>
<p><strong><a rel="noopener" target="_blank" href="https://github.com/dgraph-io/ristretto">Ristretto</a></strong> - Golang Library from D-Graph that implements a 'high performance memory-bound cache'.</p>
<p><strong><a rel="noopener" target="_blank" href="https://github.com/dgraph-io/badger">Badger</a></strong> - More from D-Graph, a Go Library offering a 'fast key-value DB'.
I tried this for the Earl project and enjoyed the initial experience.</p>
<p><strong><a rel="noopener" target="_blank" href="https://github.com/spacejam/sled">Sled</a></strong> - Rust Library offering a fast Key-Value store, still in beta, self-described as 'the champagne of beta embedded databases'.
I'm looking at this for the Rust test implementation of Earl.</p>
<h1 id="recommended-sources-to-follow">Recommended Sources to Follow</h1>
<p>Below are a few media sources and voices I follow.</p>
<h2 id="blogs">Blogs</h2>
<ul>
<li><strong><a rel="noopener" target="_blank" href="https://endler.dev/">Matthias Endler</a></strong>: Rust developer and host of 'Hello, Rust!'</li>
<li><strong><a rel="noopener" target="_blank" href="http://paulgraham.com/">Paul Graham</a></strong>: Member of YC, offers insightful well written posts about business and software.</li>
<li><strong><a rel="noopener" target="_blank" href="https://campoy.cat/">Francesc Campoy</a></strong>: Gopher and JustForFunc host.</li>
<li><strong><a rel="noopener" target="_blank" href="https://deterministic.space/">Deterministic.Space - Pascal Hertleif's blog (g/KillerCup)</a></strong>: Mostly Rust stuff.</li>
<li><strong><a rel="noopener" target="_blank" href="https://this-week-in-rust.org/">This Week In Rust</a></strong></li>
<li><strong><a rel="noopener" target="_blank" href="https://ethhub.substack.com/">EthHub Weekly</a></strong></li>
</ul>
<h2 id="podcasts">Podcasts</h2>
<ul>
<li><strong><a rel="noopener" target="_blank" href="https://changelog.com/podcast">The Changelog</a></strong>: 'Conversations with the hackers, leaders, and innovators of software development.'</li>
<li><strong><a rel="noopener" target="_blank" href="https://linuxunplugged.com/">Linux Unplugged</a></strong>: A Jupiter Broadcasting show. Relaxed, focused on Linux but touches on all things Unix and Open Source.</li>
<li><strong><a rel="noopener" target="_blank" href="http://investorfieldguide.com/podcast/">Invest Like the Best</a></strong>: Finance and investing podcast often featuring Crypto.</li>
<li><strong><a rel="noopener" target="_blank" href="https://pca.st/1uHy">Into the Ether</a></strong>: 'Focusing on all things Ethereum, the leading blockchain for decentralized applications.'</li>
</ul>
Earl Devlog 01: An Introduction2019-11-27T00:00:00+00:002019-11-27T00:00:00+00:00https://hugoreeves.com/projects/earl/devlog-01/<p>Earl is a free open-source MIT licensed finance tool currently in development.
Inspired by projects including <a rel="noopener" target="_blank" href="https://www.ledger-cli.org/">Ledger</a>, the objective of Earl is to track personal assets, expenses, income, and capital gains across a variety of accounts.
In this first devlog, I would like to set out the primary objectives of Earl alongside the planned methods to meet these objectives. </p>
<p>Compared to current plaintext based accounting options such as Ledger and GUI centric tools like <a rel="noopener" target="_blank" href="https://gnucash.org/">GNU Cash</a>, Earl aims to meet a slightly different set of goals.
These goals and the corresponding solutions are outlined below in <strong>Objective: Solution</strong> form.</p>
<ol>
<li><strong>Full history and rollback</strong>: An event-based log used to construct ledger state.</li>
<li><strong>Automated asset value calculation and transaction imports</strong>: A clean consumable API to enable separate programs to add to and read from the ledger.</li>
<li><strong>Multiple frontend applications</strong>: A focus on separating concerns, enabling distinct CLI, GUI, and web-based implementations dependant on the core library.</li>
</ol>
<h1 id="considering-each-objective">Considering each objective</h1>
<p>It's important to clarify the rationale behind each of these objectives and the means of achieving the objectives. Before beginning, it would be useful to define some shared vocabulary.</p>
<ul>
<li>Ledger - The ledger represents all accounting data, at it's most simplistic, it is a record of debits and credits between accounts, transactions.</li>
<li>Transaction - A single instance of a set of debits and credits between accounts that must balance according to double-entry principles.</li>
<li>Commodity - Taken from Ledger jargon, a commodity represents any unit of account. Currency, shares in a company and crypto tokens are all considered commodities.</li>
<li>Price Entry - A point in time exchange rate relationship between two commodities.</li>
<li>Log - An Event that marks a change to the ledger. One log type may be <code>TransactionCreated</code>, representing a new transaction in the ledger.</li>
<li>Logstore - A persistent storage system that maintains an ordered list of logs. The log store is read from to construct the current state of the ledger.</li>
</ul>
<h2 id="objective-1-full-history-and-rollback">Objective 1: Full history and rollback</h2>
<p>Ensuring historic data is not removed or lost, and guaranteeing the traceability of records is a core component of accounting and tracking personal finances.
If historic records are lost, trust in an accounting ledger is lost. Likewise, if records can be edited without a clear log of all edits, the previous state of a ledger is lost.</p>
<p>Earl constructs the state of the ledger by replaying each log in order from the first log.
Where tools like Ledger CLI present a single document representing the current Ledger state, relying on VCS for history, Earl will enable a better understanding of each edit made to the ledger.
For example, a Transaction being added to the ledger is represented by a <code>TransactionCreated</code> log appended to the Logstore.
A later edit to the same transaction would be represented by a <code>TransactionModification</code> log appended to the logstore.
The Ledger, constructed from this ordered list of logs, could show the current transaction and optionally be queried to show each version of the transaction before and after every modification event.</p>
<p>Furthermore, because each log is identified by a unique hash, it would be trivial to roll back the ledger or view its entire state at a certain point in time by simply passing the hash of the log that should be used as the cutoff point.</p>
<h2 id="objective-2-automated-asset-value-calculation-and-transaction-imports">Objective 2: Automated asset value calculation and transaction imports</h2>
<p>It should be trivial for a user to keep their transactions and the real current value of all their assets up to date.
To implement fetching logic - retrieving commodity prices from an API like Yahoo Finance - into Earl would bloat the core CLI and necessitate updates to the binary even if the core accounting logic remains unchanged.
Fetching of price entry data and transactions should be completed by third-party tools calling into the core of Earl.
This can be achieved by presenting a clean and simple API at the boundary of the core Earl logic, this API should look something like the following Go interface.
<strong>Note</strong>: The callee does not need to consider how these operations translate into state checking and on-disk logs.</p>
<pre style="background-color:#1e1e1e;">
<code class="language-go" data-lang="go"><span style="color:#569cd6;">type </span><span style="color:#4ec9b0;">ModelInterface </span><span style="color:#569cd6;">interface </span><span style="color:#dcdcdc;">{
AddAuthor(authordID </span><span style="color:#569cd6;">UUID</span><span style="color:#dcdcdc;">, authorName string) error
RemoveAuthor(authorID </span><span style="color:#569cd6;">UUID</span><span style="color:#dcdcdc;">) error
AddEntry(entry </span><span style="color:#569cd6;">Entry</span><span style="color:#dcdcdc;">) error
RemoveEntry(entryID </span><span style="color:#569cd6;">UUID</span><span style="color:#dcdcdc;">) error
AddCommodityValueEntry(
commodityA </span><span style="color:#569cd6;">UUID</span><span style="color:#dcdcdc;">,
commodityB </span><span style="color:#569cd6;">UUID</span><span style="color:#dcdcdc;">,
aToBRate float32
) (</span><span style="color:#569cd6;">UUID</span><span style="color:#dcdcdc;">, error)
RemoveCommdityValueEntry(</span><span style="color:#569cd6;">entryID</span><span style="color:#dcdcdc;">) error
}
</span></code></pre><h2 id="objective-3-multiple-frontend-applications">Objective 3: Multiple frontend applications</h2>
<p>I would be comfortable using a CLI, but most individuals are not.</p>
<p>Ensuring the core library is completely self-contained and presents a clean, consumable API enables anyone to implement a frontend for Earl - meeting users wherever they are most comfortable.
Initially, Earl will be CLI based but I'm interested in implementing a local server to deliver an Elm webapp that interacts with Earl.
This kind of functionality would ship in a separate binary.
Ideally, a native GTK app should be written.</p>
<h1 id="the-target-use-case">The Target Use Case</h1>
<p>It's a good thing to set out the initial target use-case for any program. I'll do this by writing <a rel="noopener" target="_blank" href="https://www.mountaingoatsoftware.com/agile/user-stories">User Stories</a> for each use case.</p>
<ul>
<li><strong>As an</strong> individual, <strong>I want</strong> current and historical asset value information <strong>so that</strong> I can track the value of my portfolio over time.</li>
<li><strong>As a</strong> non-technical user, <strong>I want</strong> a variety of friendly GUI tools available on most platforms <strong>so that</strong> I can interact with the accounting tool in a way that feels within my technical abilities.</li>
<li><strong>As a</strong> compliance conscious accountant, <strong>I want</strong> the ability to see historic edits to records and to never lose entries <strong>so that</strong> I can trace the origins of all data.</li>
</ul>
<h1 id="implementation">Implementation</h1>
<p>Currently, I'm split between Rust and Go for the implementation of Earl.
Go has the advantage in that I am most familiar with Go and it seems to be the more popular language.
I've written some Rust and want to spend more time learning and writing it, however, I'm yet to implement a large project in Rust and am not entirely sure of the language best practices.
In the long run, I think a Rust implementation will be easier to maintain but a Go implementation could be more attractive to outside contributions and dependent applications.</p>
<p>I'm going to continue developing Rust and Go implementations side by side to try and make up my mind.</p>
<h1 id="why-do-this">Why do this?</h1>
<p>Managing your money should be free.
The ability to sanely organize your finances - budget, manage debt, and track investments - for free enables people to better control their lives.
Beyond these motivations, Earl is something I want.
I need a way to track my finances and want to make a programmable accounting tool that others can build on.</p>
<h2 id="notes">Notes</h2>
<p>For investment purposes, I'd like to be able to record notes, alongside transactions, detailing the rationale behind my decision making.
This is something that I am considering implementing as a first-class component of Earl - arbitrary notes that may be connected to a transaction.</p>
<h2 id="cryptocurrency">Cryptocurrency</h2>
<p>Tracking cryptocurrency transactions is a challenging issue.
You need to consider the fees of each transaction, the exact time of execution, and the value of outbound and inbound tokens or currency.
The need to carefully track all transactions continues to grow as tax regulations on crypto investments become more defined.
A key aim of Earl, which stems from a part of my use case, is to be able to intelligently account for crypto portfolios.
Once Earl is stable, this can be achieved through a new CLI that calls into the core of Earl; separating this kind of logic, fetching transactions, ensures the base Earl CLI remains lean whilst greater functionality can be achieved through extra tools.</p>
Continuously Delivering this Blog with Nix, Hugo and CircleCI2019-09-05T00:00:00+00:002019-09-05T00:00:00+00:00https://hugoreeves.com/posts/2019/continuously-delivering-this-blog-with-nix-hugo-and-circleci/<p><strong>NOTE</strong>: Some details outlined here are now out of date.
I have transitioned to <a href="https://getzola.org" target="_blank">Zola</a> instead of GoHugo.
This was a change primarily made out of interest, I have no complaints about GoHugo.
The nix and CircleCI build/deploy system remains unchanged.</p>
<p>Having established this blog, I figured I should briefly explain how it's built, deployed and hosted using some of my favourite tools, <strong>Nix, GoHugo and CircleCI</strong>.
Most of my setup comes directly from <a rel="noopener" target="_blank" href="https://kalbas.it/2019/02/26/manage-a-static-website-with-hugo-and-nix/">this article on the blog kalbas.it</a>.
This post includes more information regarding continous deployment, using CircleCI, to a static site host, Netlify.</p>
<p>This blog is built using <a rel="noopener" target="_blank" href="https://gohugo.io">Hugo</a> and I use CircleCI to continuously deploy a static version of the blog to Netlify.
In order to see new content or edits applied to the production version of the blog the following things happen...</p>
<ol>
<li>I write a post or make edits</li>
<li>I commit and push the changes, <code>git add .</code> + <code>git commit [...]</code> + <code>git push</code></li>
<li>CircleCI automatically starts a build and deploy pipeline</li>
<li>The build deploy pipeline completes by pushing the statically built site to Netlify</li>
</ol>
<p>The power of CircleCI, being able to automatically publish changes to the live blog, is amazing and greatly reduces the overhead of each successive addition or edit I make.
<strong>I don't need to think about deployment, I just write content, save the changes to GitHub and the rest is automatic.</strong>
To do Continuous Delivery with CircleCI properly I use a <strong>reproducible</strong> package management system called <a rel="noopener" target="_blank" href="https://nixos.org">Nix</a>; Nix ensures a consistent build environment that can be used by the CI system and locally.</p>
<h2 id="building-locally">Building Locally</h2>
<p>Building and serving the blog locally is easy if you have the Hugo binary installed, however, I want to make sure that when I build the site within a CD pipeline the exact same binary for hugo is used.
To do this, I use a nix-shell derivation that refers to a pinned version of nixpkgs and automatically downloads and links a pinned version of the site theme into the <code>themes/</code> directory.</p>
<pre style="background-color:#1e1e1e;">
<code class="language-nix" data-lang="nix"><span style="color:#569cd6;">let
</span><span style="color:#608b4e;"># See https://nixos.wiki/wiki/FAQ/Pinning_Nixpkgs for more information on pinning
</span><span style="color:#92caf4;">nixpkgs </span><span style="color:#569cd6;">= builtins.</span><span style="color:#dcdcdc;">fetchTarball {
</span><span style="color:#608b4e;"># Descriptive name to make the store path easier to identify
</span><span style="color:#92caf4;">name </span><span style="color:#569cd6;">= </span><span style="color:#d69d85;">"nixpkgs-unstable-2019-07-31"</span><span style="color:#dcdcdc;">; </span><span style="color:#608b4e;"># Commit hash for nixos-unstable as of 2019-02-26
</span><span style="color:#92caf4;">url </span><span style="color:#569cd6;">= </span><span style="background-color:#282828;color:#d69d85;">https://github.com/NixOS/nixpkgs/archive/c0e56afddbcf6002e87a5ab0e8e17f381e3aa9bd.tar.gz</span><span style="color:#dcdcdc;">;
</span><span style="color:#608b4e;"># Hash obtained using `nix-prefetch-url --unpack <url>`
</span><span style="color:#92caf4;">sha256 </span><span style="color:#569cd6;">= </span><span style="color:#d69d85;">"1zg28j760qgjncqrf4wyb7ijzhnz0ljyvhvv87m578c7s84i851l"</span><span style="color:#dcdcdc;">;
};
</span><span style="color:#569cd6;">in
</span><span style="color:#dcdcdc;">{ pkgs </span><span style="color:#569cd6;">? </span><span style="color:#dcdcdc;">import nixpkgs {} }:
</span><span style="color:#569cd6;">with </span><span style="color:#dcdcdc;">pkgs;
</span><span style="color:#569cd6;">let
</span><span style="color:#92caf4;">hugo-theme-hello-friend-ng </span><span style="color:#569cd6;">= </span><span style="color:#dcdcdc;">runCommand </span><span style="color:#d69d85;">"hugo-theme-hello-friend-ng" </span><span style="color:#dcdcdc;">{
</span><span style="color:#92caf4;">pinned </span><span style="color:#569cd6;">= builtins.</span><span style="color:#dcdcdc;">fetchTarball {
</span><span style="color:#608b4e;"># Descriptive name to make the store path easier to identify
</span><span style="color:#92caf4;">name </span><span style="color:#569cd6;">= </span><span style="color:#d69d85;">"hugo-theme-hello-friend-ng-2019-08-01"</span><span style="color:#dcdcdc;">;
</span><span style="color:#608b4e;"># Commit hash for hugo-theme-terminal as of 2019-02-25
</span><span style="color:#92caf4;">url </span><span style="color:#569cd6;">= </span><span style="background-color:#282828;color:#d69d85;">https://github.com/rhazdon/hugo-theme-hello-friend-ng/archive/091ba7b1d2836ebf1defa1908020524174df6353.tar.gz</span><span style="color:#dcdcdc;">;
</span><span style="color:#608b4e;"># Hash obtained using `nix-prefetch-url --unpack <url>`
</span><span style="color:#92caf4;">sha256 </span><span style="color:#569cd6;">= </span><span style="color:#d69d85;">"04hsr2wj8jxvql6cqasc56gcy5jhnf74aqcswn5jh2rmiskljdmk"</span><span style="color:#dcdcdc;">;
};
</span><span style="color:#92caf4;">patches </span><span style="color:#569cd6;">= </span><span style="color:#dcdcdc;">[];
</span><span style="color:#92caf4;">preferLocalBuild </span><span style="color:#569cd6;">= true</span><span style="color:#dcdcdc;">;
}
</span><span style="color:#d69d85;">''
cp -r $pinned $out
chmod -R u+w $out
for p in $patches; do
echo "Applying patch $p"
patch -d $out -p1 < "$p"
done
''</span><span style="color:#dcdcdc;">;
</span><span style="color:#569cd6;">in
</span><span style="color:#dcdcdc;">mkShell {
</span><span style="color:#92caf4;">buildInputs </span><span style="color:#569cd6;">= </span><span style="color:#dcdcdc;">[
hugo
nodePackages</span><span style="color:#569cd6;">.</span><span style="color:#dcdcdc;">node2nix
];
</span><span style="color:#92caf4;">shellHook </span><span style="color:#569cd6;">= </span><span style="color:#d69d85;">''
mkdir -p themes
ln -snf "${</span><span style="color:#dcdcdc;">hugo-theme-hello-friend-ng</span><span style="color:#d69d85;">}" themes/hugo-theme-hello-friend-ng
''</span><span style="color:#dcdcdc;">;
}
</span></code></pre>
<p>The important part in the above is defining <code>nixpkgs</code> using the <code>builtins.fetchTarball</code> function; this ensures the download matches the predetermined hash and therefore ensures that the packages defined in <code>mkShell { buildInputs: [ hugo ] }</code> are always consistent. </p>
<p>I can activate this shell locally using <code>nix-shell</code> which provides an environment with the pinned hugo package in <code>$PATH</code>.</p>
<pre style="background-color:#1e1e1e;">
<code class="language-bash" data-lang="bash"><span style="color:#dcdcdc;">$ which hugo
$ nix-shell
=>
</span><span style="color:#569cd6;">[</span><span style="color:#dcdcdc;">nix</span><span style="color:#569cd6;">-</span><span style="color:#dcdcdc;">shell:blog</span><span style="color:#569cd6;">]</span><span style="color:#dcdcdc;">$ which hugo
=> /nix/store/mjiyzf8sms6jgn62yl7scpp5kzh4vhd4-hugo-0.55.4/bin/hugo
[nix-shell:blog]$ exit
$ which hugo
</span></code></pre>
<p>This means that I can remove hugo from my global path or update my global version of hugo, but within the context of this nix-shell I will always have a consistent version.
In practice, instead of using <code>nix-shell</code> whenever I want to use this consistent shell environment, I use direnv to activate the shell automatically; expect a better explanation of this soon.
The key here is that I can use this same nix-shell derivation within the CI build scripts to ensure builds of the site in CI and locally are using the same tools and binaries.</p>
<ol>
<li>Build the site using <code>nix-shell --run "hugo"</code></li>
<li>Serve the site using <code>nix-shell --run "hugo serve"</code></li>
</ol>
<h2 id="circleci">CircleCI</h2>
<p>I won't dive into linking CircleCI to a GitHub repository here, it's a simple process, however, in order to have the site build using CircleCI properly I need to define a CI configuration in <code>$(blog-root)/.circleci/config.yml</code>.
CircleCI uses this <code>config.yml</code> file to determine when to run builds and how to run them.
First of all, I only want to run the build deploy job on the master branch, so I specify that at the start.
To build the blog with the nix tools I use the <code>lnl7/nix:2019-05-04</code> docker image, this image includes the nix tools.
I update the tools and then install some common utilities missing by default.
The build config so far looks like...</p>
<pre style="background-color:#1e1e1e;">
<code class="language-yml" data-lang="yml"><span style="background-color:#282828;color:#569cd6;">version</span><span style="color:#dcdcdc;">: </span><span style="color:#b5cea8;">2
</span><span style="background-color:#282828;color:#569cd6;">jobs</span><span style="color:#dcdcdc;">:
</span><span style="background-color:#282828;color:#569cd6;">build</span><span style="color:#dcdcdc;">:
</span><span style="background-color:#282828;color:#569cd6;">branches</span><span style="color:#dcdcdc;">:
</span><span style="background-color:#282828;color:#569cd6;">only</span><span style="color:#dcdcdc;">:
- </span><span style="background-color:#282828;color:#569cd6;">master</span><span style="color:#dcdcdc;">
</span><span style="background-color:#282828;color:#569cd6;">docker</span><span style="color:#dcdcdc;">:
- </span><span style="background-color:#282828;color:#569cd6;">image</span><span style="color:#dcdcdc;">: </span><span style="background-color:#282828;color:#569cd6;">lnl7/nix:2019-05-04</span><span style="color:#dcdcdc;">
</span><span style="background-color:#282828;color:#569cd6;">steps</span><span style="color:#dcdcdc;">:
- </span><span style="background-color:#282828;color:#569cd6;">run</span><span style="color:#dcdcdc;">:
</span><span style="background-color:#282828;color:#569cd6;">name</span><span style="color:#dcdcdc;">: </span><span style="background-color:#282828;color:#569cd6;">Install dependencies</span><span style="color:#dcdcdc;">
</span><span style="background-color:#282828;color:#569cd6;">command</span><span style="color:#dcdcdc;">: </span><span style="color:#569cd6;">|
</span><span style="background-color:#282828;color:#d69d85;"> nix-channel --update
nix-env -u
nix-env -iA \
nixpkgs.gitMinimal \
nixpkgs.nodejs-10_x \
nixpkgs.openssh \
nixpkgs.yarn \
nixpkgs.gnutar \
nixpkgs.curl \
nixpkgs.findutils \
nixpkgs.glibc \
nixpkgs.gnugrep \
nixpkgs.gnused \
nixpkgs.gzip
</span></code></pre>
<p>To actually build the blog I add a step named 'Build', this uses the <code>nix-shell --run "hugo"</code> command.
It is important to note here that in the above 'Install dependencies' step, the nix tools are updated along with nixpkgs but these updates won't spillover and affect the site build itself, because of the consistent nix-shell that is used.
Using the nix-shell command here loads the <code>shell.nix</code> file and will download the pinned nixpkgs version and themes, this means that the shell environment that runs <code>hugo</code> to build the site is exactly the same as the local nix-shell I use to build the site.</p>
<pre style="background-color:#1e1e1e;">
<code class="language-yml" data-lang="yml"><span style="color:#dcdcdc;">- </span><span style="background-color:#282828;color:#569cd6;">run</span><span style="color:#dcdcdc;">:
</span><span style="background-color:#282828;color:#569cd6;">name</span><span style="color:#dcdcdc;">: </span><span style="background-color:#282828;color:#569cd6;">Build</span><span style="color:#dcdcdc;">
</span><span style="background-color:#282828;color:#569cd6;">command</span><span style="color:#dcdcdc;">: </span><span style="color:#569cd6;">|
</span><span style="background-color:#282828;color:#d69d85;"> nix-shell --pure --run "hugo"
</span></code></pre>
<p>The final component of the deploy is the 'Deploy' step.
This step uses a nix shell called <code>./ci-shell.nix</code> to run the npm command <code>netlify deploy</code>.
Even though this step relies on a npm package, node2nix can be used to make the step reproducible by converting the node lockfile into a nix derivation that pins each dependency.
To do this I installed the dependencies I wanted by running <code>npm install netlify npx</code> and then ran <code>node2nix</code>. <code>node2nix</code> creates a few files, the important one is <code>./default.nix</code> (I renamed this file to <code>ci-shell.nix</code> for clarity), if I use nix-shell to enter into this shell environment, all the node dependencies and a consistent node version will be provided in a reproduceable way, regardless of what is installed locally.
The CircleCI build config utilizes this shell in the final step, to run <code>npx netlify deploy [...]</code></p>
<pre style="background-color:#1e1e1e;">
<code class="language-yml" data-lang="yml"><span style="color:#dcdcdc;">- </span><span style="background-color:#282828;color:#569cd6;">run</span><span style="color:#dcdcdc;">:
</span><span style="background-color:#282828;color:#569cd6;">name</span><span style="color:#dcdcdc;">: </span><span style="background-color:#282828;color:#569cd6;">Deploy</span><span style="color:#dcdcdc;">
</span><span style="background-color:#282828;color:#569cd6;">command</span><span style="color:#dcdcdc;">: </span><span style="color:#569cd6;">|
</span><span style="background-color:#282828;color:#d69d85;"> nix-shell -A shell --pure ./ci-shell.nix --run "npx netlify deploy --dir=public --message=\"$CIRCLE_SHA1\" --prod"
</span></code></pre>
<p>The final <code>.circleci/config.yml</code> file is...</p>
<pre style="background-color:#1e1e1e;">
<code class="language-yml" data-lang="yml"><span style="background-color:#282828;color:#569cd6;">version</span><span style="color:#dcdcdc;">: </span><span style="color:#b5cea8;">2
</span><span style="background-color:#282828;color:#569cd6;">jobs</span><span style="color:#dcdcdc;">:
</span><span style="background-color:#282828;color:#569cd6;">build</span><span style="color:#dcdcdc;">:
</span><span style="background-color:#282828;color:#569cd6;">branches</span><span style="color:#dcdcdc;">:
</span><span style="background-color:#282828;color:#569cd6;">only</span><span style="color:#dcdcdc;">:
- </span><span style="background-color:#282828;color:#569cd6;">master</span><span style="color:#dcdcdc;">
</span><span style="background-color:#282828;color:#569cd6;">docker</span><span style="color:#dcdcdc;">:
- </span><span style="background-color:#282828;color:#569cd6;">image</span><span style="color:#dcdcdc;">: </span><span style="background-color:#282828;color:#569cd6;">lnl7/nix:2019-05-04</span><span style="color:#dcdcdc;">
</span><span style="background-color:#282828;color:#569cd6;">steps</span><span style="color:#dcdcdc;">:
- </span><span style="background-color:#282828;color:#569cd6;">run</span><span style="color:#dcdcdc;">:
</span><span style="background-color:#282828;color:#569cd6;">name</span><span style="color:#dcdcdc;">: </span><span style="background-color:#282828;color:#569cd6;">Install dependencies</span><span style="color:#dcdcdc;">
</span><span style="background-color:#282828;color:#569cd6;">command</span><span style="color:#dcdcdc;">: </span><span style="color:#569cd6;">|
</span><span style="background-color:#282828;color:#d69d85;"> nix-channel --update
nix-env -u
nix-env -iA \
nixpkgs.gitMinimal \
nixpkgs.nodejs-10_x \
nixpkgs.openssh \
nixpkgs.yarn \
nixpkgs.gnutar \
nixpkgs.curl \
nixpkgs.findutils \
nixpkgs.glibc \
nixpkgs.gnugrep \
nixpkgs.gnused \
nixpkgs.gzip
</span><span style="color:#dcdcdc;"> - </span><span style="background-color:#282828;color:#569cd6;">checkout</span><span style="color:#dcdcdc;">
- </span><span style="background-color:#282828;color:#569cd6;">run</span><span style="color:#dcdcdc;">:
</span><span style="background-color:#282828;color:#569cd6;">name</span><span style="color:#dcdcdc;">: </span><span style="background-color:#282828;color:#569cd6;">Build</span><span style="color:#dcdcdc;">
</span><span style="background-color:#282828;color:#569cd6;">command</span><span style="color:#dcdcdc;">: </span><span style="color:#569cd6;">|
</span><span style="background-color:#282828;color:#d69d85;"> nix-shell --pure --run "hugo"
</span><span style="color:#dcdcdc;"> - </span><span style="background-color:#282828;color:#569cd6;">run</span><span style="color:#dcdcdc;">:
</span><span style="background-color:#282828;color:#569cd6;">name</span><span style="color:#dcdcdc;">: </span><span style="background-color:#282828;color:#569cd6;">Deploy</span><span style="color:#dcdcdc;">
</span><span style="background-color:#282828;color:#569cd6;">command</span><span style="color:#dcdcdc;">: </span><span style="color:#569cd6;">|
</span><span style="background-color:#282828;color:#d69d85;"> nix-shell -A shell --pure ./ci-shell.nix --run "npx netlify deploy --dir=public --message=\"$CIRCLE_SHA1\" --prod"
</span></code></pre>
<p>Once this config file is committed to source and CircleCI is set up to build the repository, any new commits that are pushed to master will fire off the build pipeline and the updated blog should be deployed to Netlify.</p>
<h2 id="summary">Summary</h2>
<p>Using a build pipeline to continuously deploy my blog helps to reduce the burden of making a new post or an edit to the source.
Nix helps in this process by ensuring that the commands run in the build pipeline use the exact same dependencies as the commands I run locally, this is achieved through pinning a version of nixpkgs.</p>
Backups with Restic2019-08-15T00:00:00+00:002019-08-15T00:00:00+00:00https://hugoreeves.com/posts/2019/backups-with-restic/<p><a rel="noopener" target="_blank" href="https://github.com/restic/restic">Restic</a> is a powerful CLI based backup tool written in Go that I use regularly across my Darwin laptop and NixOS desktop.
The important features of restic are.</p>
<ul>
<li>A variety of storage providers available for your backup 'repositories', Local, AWS S3 conformant, <strong>Google Cloud Storage (My preference).</strong></li>
<li><strong>Deduplication</strong> of file chunks, greatly reducing the size of incremental backups.</li>
<li>A single repository can be shared by a group of machines to enable greater deduplication, the same file on two machines is only stored once.</li>
<li>Repositories are <strong>encrypted at rest</strong> so an attacker cannot simply steal access to your backup repo and read your data.</li>
</ul>
<p>In this post, I'll outline how I use restic on a regular basis using a custom bash script.
But first, let's get set up with restic.</p>
<h2 id="installing-and-getting-setup">Installing and Getting Setup</h2>
<p>The <a rel="noopener" target="_blank" href="https://restic.readthedocs.io/">official restic documentation</a> is a great place to look if you get stuck at some point in this article.</p>
<p>First, install restic. Restic is available using most package managers, and as always I would recommend using a package manager so you can keep restic up to date.</p>
<p>You can install restic in the following ways.</p>
<pre style="background-color:#1e1e1e;">
<code class="language-bash" data-lang="bash"><span style="color:#608b4e;"># Using nix, my preferred method
</span><span style="color:#dcdcdc;">nix-env -i restic
</span><span style="color:#608b4e;"># Using Homebrew
</span><span style="color:#dcdcdc;">brew install restic
</span><span style="color:#608b4e;"># Using pacman
</span><span style="color:#dcdcdc;">pacman -S restic
</span></code></pre>
<p>I use two different repositories for backups, a locally attached external hard drive (referred to as <strong>Public Drive</strong>) and a Google Cloud Storage bucket (<strong>GCS</strong>) which is a relatively low cost highly reliable and <strong>offsite</strong> blob storage option.
The offsite nature of the GCS bucket is key.
Restic has native support for local filesystem directories as backup repositories (obviously) but also ships with support for GCS buckets.
You can follow the restic documentation for an explanation of setting up a basic local repository, but there's a lot that can be done with a bit of shell scripting to make backing up easy.</p>
<p>The key thing to note is that the repository-specific parts of a restic command can be set using environment variables.
For example, the repository password can be sourced from a 'password-command' which can be set using <code>RESTIC_PASSWORD_COMMAND</code> and when using a GCS bucket, restic relies upon the envar <code>GOOGLE_PROJECT_ID</code></p>
<h2 id="a-shell-function">A Shell Function</h2>
<p>The first step I took to making backups easy was creating a fish shell function to include the necessary restic environment variables for my GCS repository.</p>
<pre style="background-color:#1e1e1e;">
<code class="language-fish" data-lang="fish"><span style="color:#569cd6;">function </span><span style="color:#dcdcdc;">restic-gcs
set -lx GOOGLE_PROJECT_ID REDACTED
set -lx GOOGLE_APPLICATION_CREDENTIALS $HOME/.config/restic/envs/gcs/gcs-service-key.json
set -lx GS_CONNECTIONS </span><span style="color:#b5cea8;">50
</span><span style="color:#dcdcdc;">set -lx RESTIC_REPOSITORY gs:REDACTED:/
set -lx RESTIC_PASSWORD_COMMAND </span><span style="color:#d69d85;">"gopass-password-only password"
</span><span style="color:#dcdcdc;">set -lx KEEP_LAST </span><span style="color:#b5cea8;">3
</span><span style="color:#dcdcdc;">set -lx RETENTION_HOURS </span><span style="color:#b5cea8;">7
</span><span style="color:#dcdcdc;">set -lx RETENTION_DAYS </span><span style="color:#b5cea8;">7
</span><span style="color:#dcdcdc;">set -lx RETENTION_WEEKS </span><span style="color:#b5cea8;">7
</span><span style="color:#dcdcdc;">set -lx RETENTION_MONTHS </span><span style="color:#b5cea8;">18
</span><span style="color:#dcdcdc;">set -lx RETENTION_YEARS </span><span style="color:#b5cea8;">20
</span><span style="color:#dcdcdc;">restic </span><span style="color:#e3bbab;">\
</span><span style="color:#dcdcdc;">--option gs.connections=$GS_CONNECTIONS </span><span style="color:#e3bbab;">\
</span><span style="color:#dcdcdc;">$argv
</span><span style="color:#569cd6;">end
</span></code></pre>
<p>The <code>set -lx</code> statements are the fish equivalent of <code>export</code> but scoped to the local function.
The function, once placed in <code>~/.config/fish/functions</code> can be invoked using <code>restic-gcs</code> with all arguments <code>$argv</code> being passed to restic within the function, which contains the appropriate envars.</p>
<p>Running <code>restic-gcs init</code> will create the repository and <code>restic-gcs {backup, forget, snapshots}</code> will all work conveniently without the need to continually set the envars and pass excess options.</p>
<h2 id="one-step-further-a-script-to-simplify-common-operations">One step further: a script to simplify common operations</h2>
<p>My next objective was to create a <strong>portable (can be used on multiple machines)</strong> script that allows convenient backups of common directories using a specified repo.
The script I wrote is called <code>back</code> and is deployed to <code>~/.config/scripts/shared/misc/back</code> using my <a href="/posts/2019/nix-home">dotfile setup</a>.
I wanted to use the following argument structure for the script <code>back {repo} {operation: backup-full-home, backup-limited-home, forget-prune}</code></p>
<p>The repo specific and machine specific requirements include...</p>
<ul>
<li>Machine
<ul>
<li>Specify paths and files to backup per machine</li>
<li>Specify paths and files to ignore per machine</li>
</ul>
</li>
<li>Repo
<ul>
<li>Specify repository, password command, retention policy, etc. per repo</li>
</ul>
</li>
</ul>
<p>I decided that the machine specific includes and excludes should be files located in <code>~/.config/restic/includes</code> and <code>~/.config/restic/excludes</code> respectively: this means the files can be deployed separately based on the machine without having to change the env files.
The env file for each repo is located under <code>~/.config/restic/envs/{repo}/env.sh</code></p>
<h3 id="the-env-file">The Env file</h3>
<p>The env file is used by each supported repo to source the appropriate envars.
Much like the previous fish shell script, the GCS env file is pretty simple.</p>
<pre style="background-color:#1e1e1e;">
<code class="language-bash" data-lang="bash"><span style="color:#608b4e;">#!/usr/bin/env bash
# ~/.config/restic/envs/gcs/env.sh
</span><span style="color:#569cd6;">export </span><span style="color:#dcdcdc;">GOOGLE_PROJECT_ID=</span><span style="background-color:#282828;color:#d69d85;">REDACTED</span><span style="color:#dcdcdc;">
</span><span style="color:#569cd6;">export </span><span style="color:#dcdcdc;">GOOGLE_APPLICATION_CREDENTIALS=</span><span style="background-color:#282828;color:#d69d85;">"$</span><span style="background-color:#282828;color:#dcdcdc;">HOME</span><span style="background-color:#282828;color:#d69d85;">/.config/restic/envs/gcs/gcs-service-key.json"</span><span style="color:#dcdcdc;">
</span><span style="color:#569cd6;">export </span><span style="color:#dcdcdc;">GS_CONNECTIONS=</span><span style="background-color:#282828;color:#d69d85;">50</span><span style="color:#dcdcdc;">
</span><span style="color:#569cd6;">export </span><span style="color:#dcdcdc;">RESTIC_REPOSITORY=</span><span style="background-color:#282828;color:#d69d85;">gs:REDACTED:/</span><span style="color:#dcdcdc;">
</span><span style="color:#569cd6;">export </span><span style="color:#dcdcdc;">RESTIC_PASSWORD_COMMAND=</span><span style="background-color:#282828;color:#d69d85;">"gopass-password-only password"</span><span style="color:#dcdcdc;">
</span><span style="color:#569cd6;">export </span><span style="color:#dcdcdc;">KEEP_LAST=</span><span style="background-color:#282828;color:#d69d85;">3</span><span style="color:#dcdcdc;">
</span><span style="color:#569cd6;">export </span><span style="color:#dcdcdc;">RETENTION_HOURS=</span><span style="background-color:#282828;color:#d69d85;">7</span><span style="color:#dcdcdc;">
</span><span style="color:#569cd6;">export </span><span style="color:#dcdcdc;">RETENTION_DAYS=</span><span style="background-color:#282828;color:#d69d85;">7</span><span style="color:#dcdcdc;">
</span><span style="color:#569cd6;">export </span><span style="color:#dcdcdc;">RETENTION_WEEKS=</span><span style="background-color:#282828;color:#d69d85;">7</span><span style="color:#dcdcdc;">
</span><span style="color:#569cd6;">export </span><span style="color:#dcdcdc;">RETENTION_MONTHS=</span><span style="background-color:#282828;color:#d69d85;">18</span><span style="color:#dcdcdc;">
</span><span style="color:#569cd6;">export </span><span style="color:#dcdcdc;">RETENTION_YEARS=</span><span style="background-color:#282828;color:#d69d85;">20</span><span style="color:#dcdcdc;">
</span></code></pre>
<p>This script (exporting a bunch of envars) can be appropriately sourced by the <code>back</code> script.</p>
<h3 id="the-include-exclude-files">The Include/Exclude files</h3>
<p>The include and exclude files are used by the back scripts <code>backup-limited-home</code>, <code>backup-home</code>, and <code>backup-full-home</code> commands.
These files determine which directories should be backed up and which files should be excluded.
You can read more about includes and excludes <a rel="noopener" target="_blank" href="https://restic.readthedocs.io/en/latest/040_backup.html#including-and-excluding-files">here</a>.</p>
<pre style="background-color:#1e1e1e;">
<code><span style="color:#dcdcdc;"># ~/.config/restic/includes/limited-home
/Users/x/.config/
/Users/x/.password-store/
/Users/x/wallpapers/
/Users/x/nix-home/
/Users/x/notes/
# ~/.config/restic/excludes/full-home
video/
Bin/
Applications/
Library/
.Trash/
.android/
.cache/
.cocoapods/
.nix-profile/
devel/**/node_modules/
devel/**/bin/
devel/**/vendor/
devel/**/.venv/
devel/go/bin/
devel/go/pkg/
</span></code></pre>
<p>Using my dotfile deployment setup, I deploy different include/exclude files on a per device basis.</p>
<h3 id="the-script">The script</h3>
<p>The script itself utilizes an array to store the arguments passed to restic and two switches based on <code>$1</code> and <code>$2</code> to append arguments and source envs based on the repo, <code>$1</code>, and command <code>$2</code>
I'm not going to explain the specifics of writing a script like this.
Hopefully, this shell script makes sense to you.</p>
<pre style="background-color:#1e1e1e;">
<code class="language-bash" data-lang="bash"><span style="color:#608b4e;">#!/usr/bin/env bash
# Run a restic backup command using the correct repo and environment values
</span><span style="color:#dcdcdc;">set -e -o pipefail
</span><span style="color:#608b4e;"># Args to be passed to the restic invocation
</span><span style="color:#dcdcdc;">args=()
</span><span style="color:#608b4e;"># The repo is the first argument
</span><span style="color:#569cd6;">case </span><span style="color:#dcdcdc;">$1 </span><span style="color:#569cd6;">in
</span><span style="color:#dcdcdc;">gcs</span><span style="color:#569cd6;">)
</span><span style="color:#dcdcdc;">source $HOME/.config/restic/envs/gcs/env.sh
echo </span><span style="color:#d69d85;">"Running command using GCS, repository: $</span><span style="color:#dcdcdc;">RESTIC_REPOSITORY</span><span style="color:#d69d85;">"
</span><span style="color:#608b4e;"># Add Args
</span><span style="color:#dcdcdc;"> args+=( </span><span style="color:#d69d85;">"--option" "gs.connections=$</span><span style="color:#dcdcdc;">GS_CONNECTIONS</span><span style="color:#d69d85;">" </span><span style="color:#dcdcdc;">)
;;
public-drive </span><span style="color:#569cd6;">|</span><span style="color:#dcdcdc;"> pd</span><span style="color:#569cd6;">)
</span><span style="color:#dcdcdc;">source $HOME/.config/restic/envs/backup-drive/env.sh
echo </span><span style="color:#d69d85;">"Running command using backup drive filesystem, repository: $</span><span style="color:#dcdcdc;">RESTIC_REPOSITORY</span><span style="color:#d69d85;">"
</span><span style="color:#dcdcdc;">;;
</span><span style="color:#569cd6;">*)
</span><span style="color:#dcdcdc;">echo </span><span style="color:#d69d85;">"The first argument is the repository to use for the backup, the options are..."
</span><span style="color:#dcdcdc;">echo </span><span style="color:#d69d85;">"gcs: Google cloud storage repository."
</span><span style="color:#dcdcdc;">echo </span><span style="color:#d69d85;">"pd | public-drive: Public hard drive mounted at /Volumes/public"
</span><span style="color:#dcdcdc;">exit
;;
</span><span style="color:#569cd6;">esac
</span><span style="color:#608b4e;"># The command to execute comes second
</span><span style="color:#569cd6;">case </span><span style="color:#dcdcdc;">$2 </span><span style="color:#569cd6;">in
</span><span style="color:#dcdcdc;">backup-limited-home </span><span style="color:#569cd6;">|</span><span style="color:#dcdcdc;"> blh</span><span style="color:#569cd6;">)
</span><span style="color:#dcdcdc;">echo </span><span style="color:#d69d85;">"Backing up limited home."
</span><span style="color:#dcdcdc;">echo </span><span style="color:#d69d85;">"Directories: ~/.config/ ~/.password-store/ ~/wallpapers/ ~/notes/"
</span><span style="color:#608b4e;"># Add Args
</span><span style="color:#dcdcdc;"> args+=( </span><span style="color:#d69d85;">'backup' </span><span style="color:#dcdcdc;">)
args+=( </span><span style="color:#d69d85;">'--tag' 'limited-home' </span><span style="color:#dcdcdc;">)
args+=( </span><span style="color:#d69d85;">"--files-from" "$</span><span style="color:#dcdcdc;">HOME</span><span style="color:#d69d85;">/.config/restic/includes/limited-home" </span><span style="color:#dcdcdc;">)
;;
backup-home </span><span style="color:#569cd6;">|</span><span style="color:#dcdcdc;"> bh</span><span style="color:#569cd6;">)
</span><span style="color:#dcdcdc;">echo </span><span style="color:#d69d85;">"Backing up important user data home directories."
</span><span style="color:#dcdcdc;">echo </span><span style="color:#d69d85;">"Directories: ~/.config/ ~/.password-store/ ~/wallpapers/ ~/notes/ ~/scripts/ ~/dotfiles/ ~/drive ~/devel ~/Music"
</span><span style="color:#608b4e;"># Add Args
</span><span style="color:#dcdcdc;"> args+=( </span><span style="color:#d69d85;">'backup' </span><span style="color:#dcdcdc;">)
args+=( </span><span style="color:#d69d85;">'--tag' 'home' </span><span style="color:#dcdcdc;">)
args+=( </span><span style="color:#d69d85;">'--exclude-file' "$</span><span style="color:#dcdcdc;">HOME</span><span style="color:#d69d85;">/.config/restic/excludes/home" </span><span style="color:#dcdcdc;">)
args+=( </span><span style="color:#d69d85;">"--files-from" "$</span><span style="color:#dcdcdc;">HOME</span><span style="color:#d69d85;">/.config/restic/includes/home" </span><span style="color:#dcdcdc;">)
;;
backup-full-home </span><span style="color:#569cd6;">|</span><span style="color:#dcdcdc;"> bfh</span><span style="color:#569cd6;">)
</span><span style="color:#dcdcdc;">echo </span><span style="color:#d69d85;">"Backing up full home directory"
</span><span style="color:#dcdcdc;">echo </span><span style="color:#d69d85;">"Excluding files using: $</span><span style="color:#dcdcdc;">HOME</span><span style="color:#d69d85;">/.config/restic/excludes/full-home"
</span><span style="color:#dcdcdc;">args+=( </span><span style="color:#d69d85;">'backup' </span><span style="color:#dcdcdc;">)
args+=( </span><span style="color:#d69d85;">'--tag' 'full-home' </span><span style="color:#dcdcdc;">)
args+=( </span><span style="color:#d69d85;">"$</span><span style="color:#dcdcdc;">HOME</span><span style="color:#d69d85;">" </span><span style="color:#dcdcdc;">)
args+=( </span><span style="color:#d69d85;">"--exclude-file" "$</span><span style="color:#dcdcdc;">HOME</span><span style="color:#d69d85;">/.config/restic/excludes/full-home"</span><span style="color:#dcdcdc;">)
;;
forget </span><span style="color:#569cd6;">|</span><span style="color:#dcdcdc;"> f</span><span style="color:#569cd6;">)
</span><span style="color:#dcdcdc;">echo </span><span style="color:#d69d85;">"Forgetting old snapshots"
</span><span style="color:#dcdcdc;">args+=(
</span><span style="color:#d69d85;">"forget"
"--host" "$</span><span style="color:#dcdcdc;">hostname</span><span style="color:#d69d85;">"
"--group-by" "paths"
"--keep-last" "$</span><span style="color:#dcdcdc;">KEEP_LAST</span><span style="color:#d69d85;">"
"--keep-hourly" "$</span><span style="color:#dcdcdc;">RETENTION_HOURS</span><span style="color:#d69d85;">"
"--keep-daily" "$</span><span style="color:#dcdcdc;">RETENTION_DAYS</span><span style="color:#d69d85;">"
"--keep-weekly" "$</span><span style="color:#dcdcdc;">RETENTION_WEEKS</span><span style="color:#d69d85;">"
"--keep-monthly" "$</span><span style="color:#dcdcdc;">RETENTION_MONTHS</span><span style="color:#d69d85;">"
"--keep-yearly" "$</span><span style="color:#dcdcdc;">RETENTION_YEARS</span><span style="color:#d69d85;">"
</span><span style="color:#dcdcdc;">)
;;
forget-prune </span><span style="color:#569cd6;">|</span><span style="color:#dcdcdc;"> fp</span><span style="color:#569cd6;">)
</span><span style="color:#dcdcdc;">echo </span><span style="color:#d69d85;">"Forgetting and pruning old snapshots"
</span><span style="color:#dcdcdc;">args+=(
</span><span style="color:#d69d85;">"forget"
"--prune"
"--host" "$</span><span style="color:#dcdcdc;">hostname</span><span style="color:#d69d85;">"
"--group-by" "paths"
"--keep-last" "$</span><span style="color:#dcdcdc;">KEEP_LAST</span><span style="color:#d69d85;">"
"--keep-hourly" "$</span><span style="color:#dcdcdc;">RETENTION_HOURS</span><span style="color:#d69d85;">"
"--keep-daily" "$</span><span style="color:#dcdcdc;">RETENTION_DAYS</span><span style="color:#d69d85;">"
"--keep-weekly" "$</span><span style="color:#dcdcdc;">RETENTION_WEEKS</span><span style="color:#d69d85;">"
"--keep-monthly" "$</span><span style="color:#dcdcdc;">RETENTION_MONTHS</span><span style="color:#d69d85;">"
"--keep-yearly" "$</span><span style="color:#dcdcdc;">RETENTION_YEARS</span><span style="color:#d69d85;">"
</span><span style="color:#dcdcdc;">)
;;
</span><span style="color:#569cd6;">*)
</span><span style="color:#dcdcdc;">echo </span><span style="color:#d69d85;">"The second argument is the operation to run, the options are..."
</span><span style="color:#dcdcdc;">echo </span><span style="color:#d69d85;">"blh | backup-limited-home: Backup a small selection of home folders, mainly configuration files."
</span><span style="color:#dcdcdc;">echo </span><span style="color:#d69d85;">"bfh | backup-full-home: Backup the entire home directory, exclude some large directories like ~/Library/"
</span><span style="color:#dcdcdc;">echo </span><span style="color:#d69d85;">"bh | backup-home: Backup home files containing important user documents, this includes folders like ~/Desktop, ~/Documents and ~/drive"
</span><span style="color:#dcdcdc;">echo </span><span style="color:#d69d85;">"f | forget: Forgets snapshots according to the retention policies"
</span><span style="color:#dcdcdc;">echo </span><span style="color:#d69d85;">"fp | forget-prune: Like forget but also prunes unused data from the repository"
</span><span style="color:#dcdcdc;">exit
;;
</span><span style="color:#569cd6;">esac
</span><span style="color:#dcdcdc;">restic </span><span style="color:#d69d85;">"${</span><span style="color:#dcdcdc;">args[@]</span><span style="color:#d69d85;">}"
</span></code></pre><h2 id="usage">Usage</h2>
<p>The script is complete.
The main purpose of the script is to make it easy to run common backups and tasks.
Instead of running <code>restic-gcs backup ~/.config ~/wallpapers ~/notes --exclude ...</code> which has already been simplified using the fish shell function, I can write <code>back gcs blh</code></p>
<pre style="background-color:#1e1e1e;">
<code class="language-bash" data-lang="bash"><span style="color:#dcdcdc;">=> back
The first argument is the repository to use for the backup, the options are...
gcs: Google cloud storage repository.
pd </span><span style="color:#569cd6;">| </span><span style="color:#dcdcdc;">public-drive: Public hard drive mounted at /Volumes/public
=> back gcs
Running command using GCS, repository: gs:REDACTED:/
The second argument is the operation to run, the options are...
blh </span><span style="color:#569cd6;">| </span><span style="color:#dcdcdc;">backup-limited-home: Backup a small selection of home folders, mainly configuration files.
bfh </span><span style="color:#569cd6;">| </span><span style="color:#dcdcdc;">backup-full-home: Backup the entire home directory, exclude some large directories like ~/Library/
bh </span><span style="color:#569cd6;">| </span><span style="color:#dcdcdc;">backup-home: Backup home files containing important user documents, this includes folders like ~/Desktop, ~/Documents and ~/drive
f </span><span style="color:#569cd6;">| </span><span style="color:#dcdcdc;">forget: Forgets snapshots according to the retention policies
fp </span><span style="color:#569cd6;">| </span><span style="color:#dcdcdc;">forget-prune: Like forget but also prunes unused data from the repository
=> back gcs blh
Running command using GCS, repository: gs:REDACTED:/
Backing up limited home.
Directories: ~/.config/ ~/.password-store/ ~/wallpapers/ ~/notes/
Files: 13 new, 10 changed, 13684 unmodified
Dirs: 0 new, 2 changed, 0 unmodified
Added to the repo: 3.322 KiB
processed 13707 files, 564.171 MiB in 0:07
snapshot REDACTED saved
</span></code></pre>
<p>The fish shell function is still just as important though, I commonly run operations such as the following.</p>
<pre style="background-color:#1e1e1e;">
<code class="language-bash" data-lang="bash"><span style="color:#dcdcdc;">=> restic-gcs snapshots -c --group-by tags,host
snapshots for (host </span><span style="color:#569cd6;">[</span><span style="color:#dcdcdc;">some</span><span style="color:#569cd6;">-</span><span style="color:#dcdcdc;">device</span><span style="color:#569cd6;">]</span><span style="color:#dcdcdc;">, tags </span><span style="color:#569cd6;">[</span><span style="color:#dcdcdc;">home</span><span style="color:#569cd6;">]</span><span style="color:#dcdcdc;">):
...
...
...
snapshots for (host </span><span style="color:#569cd6;">[</span><span style="color:#dcdcdc;">place</span><span style="color:#569cd6;">]</span><span style="color:#dcdcdc;">, tags </span><span style="color:#569cd6;">[</span><span style="color:#dcdcdc;">limited</span><span style="color:#569cd6;">-</span><span style="color:#dcdcdc;">home</span><span style="color:#569cd6;">]</span><span style="color:#dcdcdc;">):
ID Time Host Tags
--------------------------------------------------
REDACTED 2019-XX-XX XX:41:00 place limited-home
REDACTED 2019-XX-XX XX:32:15 place limited-home
REDACTED 2019-XX-XX XX:23:29 place limited-home
REDACTED 2019-XX-XX XX:10:51 place limited-home
REDACTED 2019-XX-XX XX:12:24 place limited-home
REDACTED 2019-XX-XX XX:59:51 place limited-home
REDACTED 2019-XX-XX XX:29:22 place limited-home
REDACTED 2019-XX-XX XX:21:01 place limited-home
REDACTED 2019-XX-XX XX:50:46 place limited-home
REDACTED 2019-XX-XX XX:03:22 place limited-home
REDACTED 2019-XX-XX XX:36:51 place limited-home
REDACTED 2019-XX-XX XX:48:00 place limited-home
REDACTED 2019-XX-XX XX:29:41 place limited-home
REDACTED 2019-XX-XX XX:52:05 place limited-home
REDACTED 2019-XX-XX XX:43:22 place limited-home
--------------------------------------------------
15 snapshots
</span></code></pre><h2 id="that-s-it">That's it</h2>
<p>Backups for me are now easy and convenient.
I can make offsite backups to GCS using WiFi.
Making frequent backups over the internet is often much easier than plugging in a single hard drive at different times.</p>
Your home in Nix (dotfile management)2019-08-01T11:45:00+12:002019-08-01T11:45:00+12:00https://hugoreeves.com/posts/2019/nix-home/<p><strong>Updated 2021/02/02:</strong> I have now moved to a new system I'm calling Elemental.
Expect an explanation post soon.
You can find the Elemental repo at <a rel="noopener" target="_blank" href="https://github.com/hugoreeves/elemental">gh:hugoreeves/elemental</a>.
This post now serves as an account of how I previously managed my dotfiles with Nix.</p>
<p>Anyone who spends a significant amount of time in the terminal or developing applications on more than one device has come across the challenge of portable user configuration management.
The files used to configure tools like your shell, fish in my case, and your editor, neovim, are commonly referred to as 'dotfiles' and usually live within <code>~/.config/</code>
Everyone tends to have their own unique solution to the problem; throughout most of 2018 and the start of 2019 I used the git bare repo approach described in this <a rel="noopener" target="_blank" href="https://www.atlassian.com/git/tutorials/dotfiles">Atlassian Doc</a>.
This solution served me well for a while, I could use a single repo per machine to store my dotfiles which enabled all the benefits of version control.
The big issue was that I had to keep my Darwin and Arch/NixOS configuration separate because many configs needed to be tailored to the individual system.
This made it particularly hard to keep common configs like my <a rel="noopener" target="_blank" href="https://github.com/HugoReeves/nix-home/tree/26b92f051c264a5391ae55531be7916d5051ce5f/program/editor/neovim/configs">Neovim config</a> in sync across Darwin and Linux.</p>
<p>It's safe to say that managing dotfiles is a tough problem and I wasn't happy with my git bare repo solution.
After recently getting started with and learning to love <a rel="noopener" target="_blank" href="https://nixos.org"><strong>Nix/NixOS</strong></a>, installing NixOS on my desktop and Nix on my Darwin machine, I had a renewed interest in improving my dotfile management.
NixOS allows you to define your system configuration, system users, desktop environments, bootloader, etc, using the declarative Nix language and enables atomic updates that can be reliably rolled back.
Using this ability I was able to successfully create a portable system configuration, that could be deployed using shared elements such as the Desktop Environment, to multiple computers running NixOS.
Now, I wanted to do the same for my dotfiles.</p>
<h2 id="defining-my-problem">Defining my problem</h2>
<p>Ideally we want a single repository that enables sharing configuration and installed programs across any *nix operating system that supports nix.
We must cater to an installation characterized as such.</p>
<ul>
<li>Multiple independent hardware devices. Refered to as <strong>machines</strong>.</li>
<li>Multiple "desktop" environments, Darwin (MacOS), bspwm, kde, etc. Lets call these <strong>roles</strong>.</li>
<li>Multiple users with specific package requirements. Referred to as <strong>users</strong>.</li>
</ul>
<h2 id="defining-a-solution">Defining a solution</h2>
<p>Packages and settings should be installed/set depending on the selected, machine, role and user.
Each of these three components, machine, role and user, can select the packages they require and override shared settings.
After cloning the nixpkgs repository, a single file should be edited to compose the hardware, role and user.</p>
<h2 id="finding-the-right-tools">Finding the right tools</h2>
<p>When searching for dotfile management using nix, the number one tool that appears is <a rel="noopener" target="_blank" href="https://github.com/rycee/home-manager">Rycee's Home Manager</a>.
This tool allows you to define settings for supported programs and services using nix expressions in a way comparable to NixOS configuration files.
For example, you can install some user packages and configure your <code>.gitconfig</code> using a nix expression like this.</p>
<pre style="background-color:#1e1e1e;">
<code class="language-nix" data-lang="nix"><span style="color:#dcdcdc;">{ config</span><span style="color:#569cd6;">, </span><span style="color:#dcdcdc;">pkgs</span><span style="color:#569cd6;">, ... </span><span style="color:#dcdcdc;">}:
{
</span><span style="color:#92caf4;">home</span><span style="color:#dcdcdc;">.</span><span style="color:#92caf4;">packages </span><span style="color:#569cd6;">= with </span><span style="color:#dcdcdc;">pkgs; [
</span><span style="color:#608b4e;"># Rust CLI Tools! I love rust.
</span><span style="color:#dcdcdc;">exa
bat
tokei
xsv
fd
</span><span style="color:#608b4e;"># Development
</span><span style="color:#dcdcdc;">neovim
tmux
jq
git-crypt
</span><span style="color:#608b4e;"># Files
</span><span style="color:#dcdcdc;">zstd
restic
</span><span style="color:#608b4e;"># Media
</span><span style="color:#dcdcdc;">youtube-dl
imagemagick
</span><span style="color:#608b4e;"># Overview
</span><span style="color:#dcdcdc;">htop
wtf
lazygit
neofetch
</span><span style="color:#608b4e;"># Jokes
</span><span style="color:#dcdcdc;">fortune
figlet
lolcat
];
</span><span style="color:#92caf4;">programs</span><span style="color:#dcdcdc;">.</span><span style="color:#92caf4;">git </span><span style="color:#569cd6;">= </span><span style="color:#dcdcdc;">{
</span><span style="color:#92caf4;">enable </span><span style="color:#569cd6;">= true</span><span style="color:#dcdcdc;">;
</span><span style="color:#92caf4;">userEmail </span><span style="color:#569cd6;">= </span><span style="color:#d69d85;">"user@email.com"</span><span style="color:#dcdcdc;">;
</span><span style="color:#92caf4;">userName </span><span style="color:#569cd6;">= </span><span style="color:#d69d85;">"user"</span><span style="color:#dcdcdc;">;
</span><span style="color:#92caf4;">signing</span><span style="color:#dcdcdc;">.</span><span style="color:#92caf4;">key </span><span style="color:#569cd6;">= </span><span style="color:#d69d85;">"GPG-KEY-ID"</span><span style="color:#dcdcdc;">;
</span><span style="color:#92caf4;">signing</span><span style="color:#dcdcdc;">.</span><span style="color:#92caf4;">signByDefault </span><span style="color:#569cd6;">= true</span><span style="color:#dcdcdc;">;
};
}
</span></code></pre>
<p>There's <a rel="noopener" target="_blank" href="https://rycee.gitlab.io/home-manager/options.html">good documentation</a> of all the options you can use within Home Manager.
Now it's time to implement our solution.</p>
<h2 id="implementing-a-solution">Implementing a solution</h2>
<p>Let's start with an entry point, <code>~/.config/nixpkgs/home.nix</code>, this is the file that home-manager uses by default as it's entry point.</p>
<pre style="background-color:#1e1e1e;">
<code class="language-nix" data-lang="nix"><span style="color:#608b4e;"># ~/.config/nixpkgs/home.nix
</span><span style="color:#dcdcdc;">{ config</span><span style="color:#569cd6;">, </span><span style="color:#dcdcdc;">pkgs</span><span style="color:#569cd6;">, ... </span><span style="color:#dcdcdc;">}:
{
</span><span style="color:#608b4e;"># Let Home Manager install and manage itself.
</span><span style="color:#92caf4;">programs</span><span style="color:#dcdcdc;">.</span><span style="color:#92caf4;">home-manager</span><span style="color:#dcdcdc;">.</span><span style="color:#92caf4;">enable </span><span style="color:#569cd6;">= true</span><span style="color:#dcdcdc;">;
</span><span style="color:#92caf4;">imports </span><span style="color:#569cd6;">= </span><span style="color:#dcdcdc;">[
</span><span style="background-color:#282828;color:#d69d85;">./machine/apollo.nix</span><span style="color:#dcdcdc;">
</span><span style="background-color:#282828;color:#d69d85;">./role/darwin-laptop/index.nix</span><span style="color:#dcdcdc;">
</span><span style="background-color:#282828;color:#d69d85;">./user/x.nix</span><span style="color:#dcdcdc;">
];
}
</span></code></pre>
<p>I have actually symlinked <code>~/.config/nixpkgs</code> to <code>~/nix-home</code> just to make it easier to <code>cd</code> into the repo from a new shell.</p>
<h3 id="machine-configuration">Machine Configuration</h3>
<p>There isn't much required in terms of machine level configuration, so this file will be left more or less empty.</p>
<pre style="background-color:#1e1e1e;">
<code class="language-nix" data-lang="nix"><span style="color:#608b4e;"># ~/.config/nixpkgs/machine/apollo.nix
</span><span style="color:#dcdcdc;">{ config</span><span style="color:#569cd6;">, </span><span style="color:#dcdcdc;">lib</span><span style="color:#569cd6;">, </span><span style="color:#dcdcdc;">pkgs</span><span style="color:#569cd6;">, ... </span><span style="color:#dcdcdc;">}:
{
</span><span style="color:#92caf4;">nixpkgs</span><span style="color:#dcdcdc;">.</span><span style="color:#92caf4;">config</span><span style="color:#dcdcdc;">.</span><span style="color:#92caf4;">allowUnfree </span><span style="color:#569cd6;">= true</span><span style="color:#dcdcdc;">;
}
</span></code></pre><h3 id="role-configuration">Role Configuration</h3>
<p>The role configuration contains config that is specific to the GUI/DE of the system.</p>
<p>I use <a rel="noopener" target="_blank" href="https://github.com/jwilm/alacritty">Alacritty</a> as my terminal, because it's a GUI app I want to place it's configuration in the role configuration. Here, I'm creating the role configuration <code>~/.config/nixpkgs/role/darwin-laptop/index.nix</code>.</p>
<p>Home Manager has built in support for Alacritty, this means you can define your <code>~/.config/alacritty/alacritty.yml</code> using a nix expression. A simple version of our role configuration, only setting Alacritty settings might look something like this.</p>
<pre style="background-color:#1e1e1e;">
<code class="language-nix" data-lang="nix"><span style="color:#608b4e;"># ~/.config/nixpkgs/role/darwin-laptop/index.nix
</span><span style="color:#dcdcdc;">{ config</span><span style="color:#569cd6;">, </span><span style="color:#dcdcdc;">lib</span><span style="color:#569cd6;">, </span><span style="color:#dcdcdc;">pkgs</span><span style="color:#569cd6;">, ... </span><span style="color:#dcdcdc;">}:
{
</span><span style="color:#92caf4;">programs</span><span style="color:#dcdcdc;">.</span><span style="color:#92caf4;">alacritty </span><span style="color:#569cd6;">= </span><span style="color:#dcdcdc;">{
</span><span style="color:#92caf4;">enable </span><span style="color:#569cd6;">= true</span><span style="color:#dcdcdc;">;
</span><span style="color:#92caf4;">settings </span><span style="color:#569cd6;">= </span><span style="color:#dcdcdc;">{
</span><span style="color:#92caf4;">font</span><span style="color:#dcdcdc;">.</span><span style="color:#92caf4;">size </span><span style="color:#569cd6;">= </span><span style="color:#b5cea8;">11</span><span style="color:#dcdcdc;">;
</span><span style="color:#92caf4;">shell</span><span style="color:#dcdcdc;">.</span><span style="color:#92caf4;">program </span><span style="color:#569cd6;">= </span><span style="color:#d69d85;">"/usr/local/bin/fish"</span><span style="color:#dcdcdc;">;
};
};
}
</span></code></pre>
<p>Here, the settings will overwrite the default alacritty settings.</p>
<p>If your setup can be defined using only one role, ie. you only operate one distinct desktop configuration, defining program settings in your role file might work. However, we want to make our dotfiles portable, ideally we should have a shared set of Alacritty settings that can be imported into each role for which we want to use Alacritty, each role file should also be able to override some shared settings where necessary.</p>
<p>To achieve this, we'll create a file <code>~/.config/nixpkgs/program/terminal/alacritty/default-settings.nix</code> and populate it our Alacritty configuration.</p>
<pre style="background-color:#1e1e1e;">
<code class="language-nix" data-lang="nix"><span style="color:#608b4e;"># ~/.config/nixpkgs/program/terminal/alacritty/default-settings.nix
</span><span style="color:#dcdcdc;">{
</span><span style="color:#92caf4;">env </span><span style="color:#569cd6;">= </span><span style="color:#dcdcdc;">{
</span><span style="color:#d69d85;">"TERM" </span><span style="color:#569cd6;">= </span><span style="color:#d69d85;">"xterm-256color"</span><span style="color:#dcdcdc;">;
};
</span><span style="color:#92caf4;">background_opacity </span><span style="color:#569cd6;">= </span><span style="color:#b5cea8;">0</span><span style="color:#569cd6;">.</span><span style="color:#b5cea8;">95</span><span style="color:#dcdcdc;">;
</span><span style="color:#92caf4;">window </span><span style="color:#569cd6;">= </span><span style="color:#dcdcdc;">{
</span><span style="color:#92caf4;">padding</span><span style="color:#dcdcdc;">.</span><span style="color:#92caf4;">x </span><span style="color:#569cd6;">= </span><span style="color:#b5cea8;">10</span><span style="color:#dcdcdc;">;
</span><span style="color:#92caf4;">padding</span><span style="color:#dcdcdc;">.</span><span style="color:#92caf4;">y </span><span style="color:#569cd6;">= </span><span style="color:#b5cea8;">10</span><span style="color:#dcdcdc;">;
</span><span style="color:#92caf4;">decorations </span><span style="color:#569cd6;">= </span><span style="color:#d69d85;">"buttonless"</span><span style="color:#dcdcdc;">;
};
</span><span style="color:#92caf4;">font </span><span style="color:#569cd6;">= </span><span style="color:#dcdcdc;">{
</span><span style="color:#92caf4;">size </span><span style="color:#569cd6;">= </span><span style="color:#b5cea8;">12</span><span style="color:#569cd6;">.</span><span style="color:#b5cea8;">0</span><span style="color:#dcdcdc;">;
</span><span style="color:#92caf4;">use_thin_strokes </span><span style="color:#569cd6;">= true</span><span style="color:#dcdcdc;">;
</span><span style="color:#92caf4;">normal</span><span style="color:#dcdcdc;">.</span><span style="color:#92caf4;">family </span><span style="color:#569cd6;">= </span><span style="color:#d69d85;">"FuraCode Nerd Font"</span><span style="color:#dcdcdc;">;
</span><span style="color:#92caf4;">bold</span><span style="color:#dcdcdc;">.</span><span style="color:#92caf4;">family </span><span style="color:#569cd6;">= </span><span style="color:#d69d85;">"FuraCode Nerd Font"</span><span style="color:#dcdcdc;">;
</span><span style="color:#92caf4;">italic</span><span style="color:#dcdcdc;">.</span><span style="color:#92caf4;">family </span><span style="color:#569cd6;">= </span><span style="color:#d69d85;">"FuraCode Nerd Font"</span><span style="color:#dcdcdc;">;
};
</span><span style="color:#92caf4;">cursor</span><span style="color:#dcdcdc;">.</span><span style="color:#92caf4;">style </span><span style="color:#569cd6;">= </span><span style="color:#d69d85;">"Beam"</span><span style="color:#dcdcdc;">;
</span><span style="color:#92caf4;">shell </span><span style="color:#569cd6;">= </span><span style="color:#dcdcdc;">{
</span><span style="color:#92caf4;">program </span><span style="color:#569cd6;">= </span><span style="color:#d69d85;">"fish"</span><span style="color:#dcdcdc;">;
</span><span style="color:#92caf4;">args </span><span style="color:#569cd6;">= </span><span style="color:#dcdcdc;">[
</span><span style="color:#d69d85;">"-C"
"neofetch"
</span><span style="color:#dcdcdc;">];
};
</span><span style="color:#92caf4;">colors </span><span style="color:#569cd6;">= </span><span style="color:#dcdcdc;">{
</span><span style="color:#608b4e;"># Default colors
</span><span style="color:#92caf4;">primary </span><span style="color:#569cd6;">= </span><span style="color:#dcdcdc;">{
</span><span style="color:#92caf4;">background </span><span style="color:#569cd6;">= </span><span style="color:#d69d85;">"0x1b182c"</span><span style="color:#dcdcdc;">;
</span><span style="color:#92caf4;">foreground </span><span style="color:#569cd6;">= </span><span style="color:#d69d85;">"0xcbe3e7"</span><span style="color:#dcdcdc;">;
};
</span><span style="color:#608b4e;"># Normal colors
</span><span style="color:#92caf4;">normal </span><span style="color:#569cd6;">= </span><span style="color:#dcdcdc;">{
</span><span style="color:#92caf4;">black </span><span style="color:#569cd6;">= </span><span style="color:#d69d85;">"0x100e23"</span><span style="color:#dcdcdc;">;
</span><span style="color:#92caf4;">red </span><span style="color:#569cd6;">= </span><span style="color:#d69d85;">"0xff8080"</span><span style="color:#dcdcdc;">;
</span><span style="color:#92caf4;">green </span><span style="color:#569cd6;">= </span><span style="color:#d69d85;">"0x95ffa4"</span><span style="color:#dcdcdc;">;
</span><span style="color:#92caf4;">yellow </span><span style="color:#569cd6;">= </span><span style="color:#d69d85;">"0xffe9aa"</span><span style="color:#dcdcdc;">;
</span><span style="color:#92caf4;">blue </span><span style="color:#569cd6;">= </span><span style="color:#d69d85;">"0x91ddff"</span><span style="color:#dcdcdc;">;
</span><span style="color:#92caf4;">magenta </span><span style="color:#569cd6;">= </span><span style="color:#d69d85;">"0xc991e1"</span><span style="color:#dcdcdc;">;
</span><span style="color:#92caf4;">cyan </span><span style="color:#569cd6;">= </span><span style="color:#d69d85;">"0xaaffe4"</span><span style="color:#dcdcdc;">;
</span><span style="color:#92caf4;">white </span><span style="color:#569cd6;">= </span><span style="color:#d69d85;">"0xcbe3e7"</span><span style="color:#dcdcdc;">;
};
</span><span style="color:#608b4e;"># Bright colors
</span><span style="color:#92caf4;">bright </span><span style="color:#569cd6;">= </span><span style="color:#dcdcdc;">{
</span><span style="color:#92caf4;">black </span><span style="color:#569cd6;">= </span><span style="color:#d69d85;">"0x565575"</span><span style="color:#dcdcdc;">;
</span><span style="color:#92caf4;">red </span><span style="color:#569cd6;">= </span><span style="color:#d69d85;">"0xff5458"</span><span style="color:#dcdcdc;">;
</span><span style="color:#92caf4;">green </span><span style="color:#569cd6;">= </span><span style="color:#d69d85;">"0x62d196"</span><span style="color:#dcdcdc;">;
</span><span style="color:#92caf4;">yellow </span><span style="color:#569cd6;">= </span><span style="color:#d69d85;">"0xffb378"</span><span style="color:#dcdcdc;">;
</span><span style="color:#92caf4;">blue </span><span style="color:#569cd6;">= </span><span style="color:#d69d85;">"0x65b2ff"</span><span style="color:#dcdcdc;">;
</span><span style="color:#92caf4;">magenta </span><span style="color:#569cd6;">= </span><span style="color:#d69d85;">"0x906cff"</span><span style="color:#dcdcdc;">;
</span><span style="color:#92caf4;">cyan </span><span style="color:#569cd6;">= </span><span style="color:#d69d85;">"0x63f2f1"</span><span style="color:#dcdcdc;">;
</span><span style="color:#92caf4;">white </span><span style="color:#569cd6;">= </span><span style="color:#d69d85;">"0xa6b3cc"</span><span style="color:#dcdcdc;">;
};
};
}
</span></code></pre>
<p>Now, we can import the shared alacritty settings into our role file. We'll also overwrite some of the settings where neccesary. <code>lib.attrsets.recursiveUpdate</code> performs a deep merge of <code>arg1</code> with <code>arg2</code> overwriting values.</p>
<pre style="background-color:#1e1e1e;">
<code class="language-nix" data-lang="nix"><span style="color:#608b4e;"># ~/.config/nixpkgs/role/darwin-laptop/index.nix
</span><span style="color:#dcdcdc;">{ config</span><span style="color:#569cd6;">, </span><span style="color:#dcdcdc;">lib</span><span style="color:#569cd6;">, </span><span style="color:#dcdcdc;">pkgs</span><span style="color:#569cd6;">, ... </span><span style="color:#dcdcdc;">}:
{
</span><span style="color:#92caf4;">nixpkgs</span><span style="color:#dcdcdc;">.</span><span style="color:#92caf4;">config</span><span style="color:#dcdcdc;">.</span><span style="color:#92caf4;">allowUnfree </span><span style="color:#569cd6;">= true</span><span style="color:#dcdcdc;">;
</span><span style="color:#92caf4;">programs</span><span style="color:#dcdcdc;">.</span><span style="color:#92caf4;">alacritty </span><span style="color:#569cd6;">= </span><span style="color:#dcdcdc;">{
</span><span style="color:#92caf4;">enable </span><span style="color:#569cd6;">= true</span><span style="color:#dcdcdc;">;
</span><span style="color:#92caf4;">settings </span><span style="color:#569cd6;">= </span><span style="color:#dcdcdc;">lib</span><span style="color:#569cd6;">.</span><span style="color:#dcdcdc;">attrsets</span><span style="color:#569cd6;">.</span><span style="color:#dcdcdc;">recursiveUpdate (import </span><span style="background-color:#282828;color:#d69d85;">../../program/terminal/alacritty/default-settings.nix</span><span style="color:#dcdcdc;">) {
</span><span style="color:#92caf4;">shell</span><span style="color:#dcdcdc;">.</span><span style="color:#92caf4;">program </span><span style="color:#569cd6;">= </span><span style="color:#d69d85;">"/usr/local/bin/fish"</span><span style="color:#dcdcdc;">;
};
};
</span><span style="color:#92caf4;">home</span><span style="color:#dcdcdc;">.</span><span style="color:#92caf4;">file</span><span style="color:#dcdcdc;">.</span><span style="color:#d69d85;">".hammerspoon"</span><span style="color:#dcdcdc;">.</span><span style="color:#92caf4;">source </span><span style="color:#569cd6;">= </span><span style="background-color:#282828;color:#d69d85;">../../de/darwin-only/hammerspoon</span><span style="color:#dcdcdc;">;
}
</span></code></pre>
<p>You may have noticed this last statement in the file <code>home.file.".hammerspoon".source = ../../de/darwin-only/hammerspoon;</code> This statement sources (copies file/s) from the local directory path <code>../../de/darwin-only/hammerspoon</code> into the home directory path <code>~/.hammerspoon</code> This is the primary method of sharing config files that cannot be configured using home manager. Hammerspoon is a utility app that I use on Darwin that allows binding custom keyboard shortcuts to lua scripts.</p>
<h3 id="user-configuration">User Configuration</h3>
<p>User configuration stores common elements for your userspace that are platform independent.</p>
<p>I store my git configuration, and cli tools in the user configuration. The two imports, <code>neovim/default.nix</code> and <code>tmux/default.nix</code> are just nix expressions that source my <code>~/.config/neovim/</code> and <code>~/.config/tmux/tmux.conf</code> files. The <code>.vimrc</code> files for neovim are stored under <code>~/.config/nixpkgs/program/editor/neovim/config-files/*</code>.</p>
<p>Whenever I want to edit my neovim configuration I have to edit a file like <code>~/.config/nixpkgs/program/editor/neovim/config-files/keybinds.vimrc</code> and then run <code>home-manager switch</code> to have the files sourced into the <code>~/.config/neovim</code> folder. This may sound like a pain, having to run a command to deploy your changes each time you make them, but for me the advantages of having a single repo for cross os/de config management outweigh this slight pain point.</p>
<pre style="background-color:#1e1e1e;">
<code class="language-nix" data-lang="nix"><span style="color:#608b4e;"># ~/.config/nixpkgs/user/x.nix
</span><span style="color:#dcdcdc;">{ config</span><span style="color:#569cd6;">, </span><span style="color:#dcdcdc;">pkgs</span><span style="color:#569cd6;">, ... </span><span style="color:#dcdcdc;">}:
{
</span><span style="color:#92caf4;">imports </span><span style="color:#569cd6;">= </span><span style="color:#dcdcdc;">[
</span><span style="background-color:#282828;color:#d69d85;">../program/editor/neovim/default.nix</span><span style="color:#dcdcdc;">
</span><span style="background-color:#282828;color:#d69d85;">../program/terminal/tmux/default.nix</span><span style="color:#dcdcdc;">
];
</span><span style="color:#92caf4;">home</span><span style="color:#dcdcdc;">.</span><span style="color:#92caf4;">packages </span><span style="color:#569cd6;">= with </span><span style="color:#dcdcdc;">pkgs; [
</span><span style="color:#608b4e;"># Rust CLI Tools! I love rust.
</span><span style="color:#dcdcdc;">exa
bat
tokei
xsv
fd
</span><span style="color:#608b4e;"># Development
</span><span style="color:#dcdcdc;">neovim
tmux
jq
git-crypt
dnsutils
whois
</span><span style="color:#608b4e;"># Files
</span><span style="color:#dcdcdc;">zstd
restic
brig
ipfs
</span><span style="color:#608b4e;"># Media
</span><span style="color:#dcdcdc;">youtube-dl
imagemagick
</span><span style="color:#608b4e;"># Overview
</span><span style="color:#dcdcdc;">htop
wtf
lazygit
neofetch
</span><span style="color:#608b4e;"># Jokes
</span><span style="color:#dcdcdc;">fortune
figlet
lolcat
];
</span><span style="color:#92caf4;">programs</span><span style="color:#dcdcdc;">.</span><span style="color:#92caf4;">git </span><span style="color:#569cd6;">= </span><span style="color:#dcdcdc;">{
</span><span style="color:#92caf4;">enable </span><span style="color:#569cd6;">= true</span><span style="color:#dcdcdc;">;
</span><span style="color:#92caf4;">userEmail </span><span style="color:#569cd6;">= </span><span style="color:#d69d85;">"hugolreeves@gmail.com"</span><span style="color:#dcdcdc;">;
</span><span style="color:#92caf4;">userName </span><span style="color:#569cd6;">= </span><span style="color:#d69d85;">"Hugo Reeves"</span><span style="color:#dcdcdc;">;
</span><span style="color:#92caf4;">signing</span><span style="color:#dcdcdc;">.</span><span style="color:#92caf4;">key </span><span style="color:#569cd6;">= </span><span style="color:#d69d85;">"738A0BE6D8D8AE7D"</span><span style="color:#dcdcdc;">;
</span><span style="color:#92caf4;">signing</span><span style="color:#dcdcdc;">.</span><span style="color:#92caf4;">signByDefault </span><span style="color:#569cd6;">= true</span><span style="color:#dcdcdc;">;
};
}
</span></code></pre><h3 id="setting-up-a-new-system">Setting up a new system</h3>
<p>Now, my dotfiles have been properly split up and modularized so that I can compose a deployment of dotfiles and packages on any unix distribution with the ability to override shared configuration depending on the platform.</p>
<p>On a new system with nix installed, say, my NixOS machine, I can simply clone my nix-home repository into <code>~/.config/nixpkgs</code> and create a new <code>home.nix</code> file. Within this file I can import the <code>user/x.nix</code> config I use on Darwin and create a new role, <code>role/bspwm-workstation/index.nix</code>, and machine, <code>machine/boron.nix</code>, config. Within the workstation file, I can import the shared Alacritty configuration and overwrite some of the settings where necessary.</p>
<pre style="background-color:#1e1e1e;">
<code class="language-nix" data-lang="nix"><span style="color:#608b4e;"># ~/.config/nixpkgs/role/bspwm-workstation/index.nix
</span><span style="color:#dcdcdc;">{ config</span><span style="color:#569cd6;">, </span><span style="color:#dcdcdc;">lib</span><span style="color:#569cd6;">, </span><span style="color:#dcdcdc;">pkgs</span><span style="color:#569cd6;">, </span><span style="color:#dcdcdc;">attrsets</span><span style="color:#569cd6;">, ... </span><span style="color:#dcdcdc;">}:
{
</span><span style="color:#92caf4;">home</span><span style="color:#dcdcdc;">.</span><span style="color:#92caf4;">packages </span><span style="color:#569cd6;">= with </span><span style="color:#dcdcdc;">pkgs; [
dunst
compton
];
</span><span style="color:#92caf4;">services </span><span style="color:#569cd6;">= </span><span style="color:#dcdcdc;">{
</span><span style="color:#92caf4;">polybar </span><span style="color:#569cd6;">= </span><span style="color:#dcdcdc;">{
</span><span style="color:#92caf4;">enable </span><span style="color:#569cd6;">= true</span><span style="color:#dcdcdc;">;
</span><span style="color:#92caf4;">config </span><span style="color:#569cd6;">= </span><span style="background-color:#282828;color:#d69d85;">../../de/bars/polybar/boron-config</span><span style="color:#dcdcdc;">;
</span><span style="color:#92caf4;">script </span><span style="color:#569cd6;">= </span><span style="color:#d69d85;">"polybar top &"</span><span style="color:#dcdcdc;">;
};
};
</span><span style="color:#92caf4;">programs</span><span style="color:#dcdcdc;">.</span><span style="color:#92caf4;">alacritty </span><span style="color:#569cd6;">= </span><span style="color:#dcdcdc;">{
</span><span style="color:#92caf4;">enable </span><span style="color:#569cd6;">= true</span><span style="color:#dcdcdc;">;
</span><span style="color:#92caf4;">settings </span><span style="color:#569cd6;">= </span><span style="color:#dcdcdc;">lib</span><span style="color:#569cd6;">.</span><span style="color:#dcdcdc;">attrsets</span><span style="color:#569cd6;">.</span><span style="color:#dcdcdc;">recursiveUpdate (import </span><span style="background-color:#282828;color:#d69d85;">../../program/terminal/alacritty/default-settings.nix</span><span style="color:#dcdcdc;">) {
</span><span style="color:#92caf4;">font</span><span style="color:#dcdcdc;">.</span><span style="color:#92caf4;">size </span><span style="color:#569cd6;">= </span><span style="color:#b5cea8;">11</span><span style="color:#dcdcdc;">;
</span><span style="color:#92caf4;">font</span><span style="color:#dcdcdc;">.</span><span style="color:#92caf4;">user_thin_strokes </span><span style="color:#569cd6;">= false</span><span style="color:#dcdcdc;">;
</span><span style="color:#92caf4;">window </span><span style="color:#569cd6;">= </span><span style="color:#dcdcdc;">{
</span><span style="color:#92caf4;">decorations </span><span style="color:#569cd6;">= </span><span style="color:#d69d85;">"full"</span><span style="color:#dcdcdc;">;
};
};
};
</span><span style="color:#92caf4;">xdg</span><span style="color:#dcdcdc;">.</span><span style="color:#92caf4;">configFile </span><span style="color:#569cd6;">= </span><span style="color:#dcdcdc;">{
</span><span style="color:#d69d85;">"dunst/dunstrc"</span><span style="color:#dcdcdc;">.</span><span style="color:#92caf4;">source </span><span style="color:#569cd6;">= </span><span style="background-color:#282828;color:#d69d85;">../../de/notifications/dunst/dunstrc</span><span style="color:#dcdcdc;">;
</span><span style="color:#d69d85;">"compton/compton.conf"</span><span style="color:#dcdcdc;">.</span><span style="color:#92caf4;">source </span><span style="color:#569cd6;">= </span><span style="background-color:#282828;color:#d69d85;">../../de/compositors/compton/boron-compton.conf</span><span style="color:#dcdcdc;">;
};
}
</span></code></pre><h2 id="summary">Summary</h2>
<p>I think I'm finally happy.
Nix and home-manager make it possible to store all of my dotfiles in a single repo and on a single branch.
Separating my dependency path into the machine, role, user, system allows host specific adjustments to the a configuration.
Now, if I update my neovim config on one system, and check the changes into github, on another system I can just run <code>cd ~/.config/nixpkgs; git pull; home-manager switch</code></p>
<p>I encourage you to checkout my <strong>nix-home</strong> repo if this system interests you.</p>
<ul>
<li><a rel="noopener" target="_blank" href="https://github.com/HugoReeves/nix-home/tree/12ffc891358898733f26e149a9a4c423b638401a">Locked version as of the writting of this post</a></li>
<li><a rel="noopener" target="_blank" href="https://github.com/HugoReeves/nix-home/">Current master branch</a></li>
</ul>