<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="/feed-styles.xsl" type="text/xsl"?><feed xmlns="http://www.w3.org/2005/Atom"><title>Alan Pearce</title><link rel="alternate" type="text/html" href="https://alanpearce.eu/"></link><id>tag:alanpearce.eu,2014-06-07:feed</id><updated>2026-02-06T15:42:00Z</updated><entry><title>scriptura: a cozy corner for your scripts</title><link rel="alternate" type="text/html" href="https://alanpearce.eu/post/scriptura/"></link><id>tag:alanpearce.eu,2014-06-07:scriptura</id><updated>2026-02-06T15:42:00Z</updated><content type="html">&lt;p&gt;I’ve created a new little tool to help run and manage scripts in a folder tree, called &lt;a href=&#34;https://git.alin.ovh/scriptura&#34;&gt;scriptura&lt;/a&gt;. It is based on the idea behind &lt;a href=&#34;https://github.com/ianthehenry/sd&#34;&gt;sd&lt;/a&gt; and is made for fish users.&lt;/p&gt;&#xA;&lt;p&gt;Given a script folder like so:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-console&#34;&gt;$ set -x SCRIPTURA_ROOT ~/scripts&#xA;$ tree ~/scripts&#xA;~/scripts&#xA;├── os&#xA;│   └── update&#xA;│       ├── linde&#xA;│       └── r5 -&amp;gt; linde&#xA;└── scriptura&#xA;    └── tree&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;If I type in &lt;code&gt;scriptura run os update linde&lt;/code&gt;, it will run the script at  &lt;code&gt;~/scripts/os/update/linde&lt;/code&gt;, whilst providing tab completion for each element. Pressing tab after a script has been resolved will first add &lt;code&gt;--&lt;/code&gt; to clearly show the end of the script part of the command line, then use the default shell filename completion.&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-console&#34;&gt;$ scriptura run os update linde -- &amp;lt;tab&amp;gt;&#xA;bin/        flake.nix  LICENSES/  private/    scripts/  system/&#xA;flake.lock  lib/       packages/  REUSE.toml  secrets/  user/&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;The usage information gives more detail on what can be done.&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-console&#34;&gt;$ scriptura&#xA;Usage: scriptura &amp;lt;subcommand&amp;gt; &amp;lt;script_name&amp;gt;&#xA;SCRIPTURA_ROOT: ~/scripts&#xA;&#xA;Subcommands:&#xA;&#xA;  run          Run a script&#xA;  help         Display help information&#xA;  new          Create new script&#xA;  edit         Edit existing script&#xA;  which        Display script path&#xA;  cat          Display script content&#xA;  cmd          Execute shell command from target directory&#xA;&#xA;User Subcommands:&#xA;&#xA;  tree         print a tree of files under $SCRIPTURA_ROOT&#xA;&#xA;Scripts:&#xA;&#xA;os ...       -- os commands&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;h2 id=&#34;typing-shortcuts&#34;&gt;Typing shortcuts&lt;/h2&gt;&#xA;&lt;p&gt;To reduce the amount of typing required, I have set the following aliases.&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-fish&#34;&gt;alias sfm=&amp;quot;scriptura&amp;quot;&#xA;alias sf=&amp;quot;scriptura run&amp;quot;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;The fish completion system handles these well: &lt;code&gt;sf &amp;lt;tab&amp;gt;&lt;/code&gt; will show me scripts to be run, whereas &lt;code&gt;sfm&lt;/code&gt; will show me the subcommands of the tool.&lt;/p&gt;&#xA;&lt;h2 id=&#34;documenting-scripts&#34;&gt;Documenting scripts&lt;/h2&gt;&#xA;&lt;p&gt;To aid documentation, &lt;code&gt;scriptura&lt;/code&gt; will look in a couple of places:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;an adjacent file with the &lt;code&gt;.help&lt;/code&gt; extension&lt;/li&gt;&#xA;&lt;li&gt;comments inside the script (currently only supports one comment syntax &lt;code&gt;#&lt;/code&gt;)&#xA;Additionally, folders can be documented by adding a file called &lt;code&gt;help&lt;/code&gt;.&#xA;This information is then provided during tab completion, via the &lt;code&gt;help&lt;/code&gt; subcommand or when listing scripts (the default action if a the command line does not resolve to a script).&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;language-support&#34;&gt;Language support&lt;/h2&gt;&#xA;&lt;p&gt;Whilst scriptura is written in fish, scripts don&amp;rsquo;t have to be; it&amp;rsquo;s just the default. &lt;code&gt;scriptura new&lt;/code&gt; will create scripts with a fish shebang, which can be freely edited. I also plan to add a command-line option to set a different interpreter.&lt;/p&gt;&#xA;&lt;h2 id=&#34;changes-from-sd&#34;&gt;Changes from sd&lt;/h2&gt;&#xA;&lt;p&gt;The &lt;a href=&#34;https://ianthehenry.com/posts/sd-my-script-directory/&#34;&gt;blog post version of &lt;code&gt;sd&lt;/code&gt;&lt;/a&gt; and the version &lt;a href=&#34;https://github.com/ianthehenry/sd&#34;&gt;published to Github&lt;/a&gt; already differ in that the blog post version uses subcommands like &lt;code&gt;sd new&lt;/code&gt;, whereas the Github version uses flags for actions that don&amp;rsquo;t involve running a script (e.g. &lt;code&gt;sd --new&lt;/code&gt;). I prefer the subcommand style, at least when there is a short alias to the &lt;code&gt;run&lt;/code&gt; subcommand.&lt;/p&gt;&#xA;&lt;p&gt;Additionally, I&amp;rsquo;ve added some new features.&lt;/p&gt;&#xA;&lt;h2 id=&#34;new-features&#34;&gt;New features&lt;/h2&gt;&#xA;&lt;h3 id=&#34;tab-completion-after-new&#34;&gt;Tab completion after &lt;code&gt;new&lt;/code&gt;&lt;/h3&gt;&#xA;&lt;p&gt;The &lt;code&gt;new&lt;/code&gt; subcommand invokes the underlying command&amp;rsquo;s tab-completion after a script name is given:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-console&#34;&gt;$ scriptura new mac svc restart -- launchctl k&amp;lt;tab&amp;gt;&#xA;kickstart  (Forces an existing service to start)&#xA;kill    (Sends a signal to the service instance)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;h3 id=&#34;run-ad-hoc-commands-in-the-script-root&#34;&gt;Run ad-hoc commands in the script root&lt;/h3&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-console&#34;&gt;$ scriptura cmd tree&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;will run the &lt;code&gt;tree&lt;/code&gt; command with the working directory set to &lt;code&gt;$SCRIPTURA_ROOT&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;h3 id=&#34;custom-subcommands&#34;&gt;Custom subcommands&lt;/h3&gt;&#xA;&lt;p&gt;One thing that I thought would be useful is a &lt;code&gt;tree&lt;/code&gt; subcommand. However, I don&amp;rsquo;t want to force that on any other potential users. Whilst I could have settled with the &lt;code&gt;cmd&lt;/code&gt; subcommand mentioned in the previous section, I decided I wanted it to be even easier.&#xA;Scripts under the special &lt;em&gt;scriptura&lt;/em&gt; subdirectory are exposed as subcommands, which pass flags to the underlying command and interpret positional arguments as script path components:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-console&#34;&gt;# create a new script at ~/scripts/scriptura/tree which just calls tree&#xA;$ scriptura new scriptura tree -- tree&#xA;$ scriptura tree&#xA;.&#xA;├── os&#xA;│   └── update&#xA;│       ├── linde&#xA;│       └── r5 -&amp;gt; linde&#xA;└── scriptura&#xA;    └── tree&#xA;&#xA;4 directories, 3 files&#xA;$ scriptura tree -L1 os&#xA;os&#xA;└── update&#xA;&#xA;2 directories, 0 files&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;h2 id=&#34;motivation&#34;&gt;Motivation&lt;/h2&gt;&#xA;&lt;p&gt;Recently, I found &lt;a href=&#34;https://github.com/ianthehenry/sd&#34;&gt;sd&lt;/a&gt;, which is designed to help run and manage scripts under a specific directory tree.&lt;/p&gt;&#xA;&lt;p&gt;There are two reasons I’m not using this tool directly:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;It’s called &lt;code&gt;sd&lt;/code&gt;, which is a name that’s already taken on my system by another tool: &lt;a href=&#34;https://github.com/chmln/sd&#34;&gt;sd (sed alternative)&lt;/a&gt;.&lt;/li&gt;&#xA;&lt;li&gt;It doesn’t ship with completions for the &lt;code&gt;fish&lt;/code&gt; shell. There was a gist with these, but it seems to have disappeared. The completions are, in my opinion, the biggest feature.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Also, I expected a fish implementation to be easier to read and write, as well as not requiring so many external command calls.&lt;/p&gt;&#xA;&lt;p&gt;In the introductory &lt;a href=&#34;https://ianthehenry.com/posts/sd-my-script-directory/&#34;&gt;blog post&lt;/a&gt;, Ian writes &lt;q&gt;It’s not really a thing. It’s more of an idea. You can implement it yourself in one sitting, if you want.&lt;/q&gt;.&lt;/p&gt;&#xA;&lt;p&gt;It took me more than one sitting, but I enjoyed it.&lt;/p&gt;&#xA;&lt;h2 id=&#34;try-it-out&#34;&gt;Try it out&lt;/h2&gt;&#xA;&lt;p&gt;Visit the repository for installation instructions, including a &lt;a href=&#34;https://nix-community.github.io/home-manager/&#34;&gt;home-manager&lt;/a&gt; module:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://git.alin.ovh/scriptura/&#34;&gt;git.alin.ovh&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://codeberg.org/alinnow/scriptura&#34;&gt;codeberg&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://git.sr.ht/~alinnow/scriptura&#34;&gt;sr.ht&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</content><author><name>Alan Pearce</name></author></entry><entry><title>Avoiding Linguistic Misunderstandings</title><link rel="alternate" type="text/html" href="https://alanpearce.eu/post/avoiding-linguistic-misunderstandings/"></link><id>tag:alanpearce.eu,2014-06-07:avoiding-linguistic-misunderstandings</id><updated>2025-04-15T00:00:00Z</updated><content type="html">&lt;p&gt;Recently, I’ve been noticing more linguistic misunderstandings and it prompted me to make changes to how I communicate in order to reduce the likelihood of such misunderstandings.&lt;/p&gt;&#xA;&lt;h2 id=&#34;spell-out-initialisms&#34;&gt;Spell out initialisms&lt;/h2&gt;&#xA;&lt;p&gt;Unless 100% sure that the other party knows the same initialisms I do, I try to avoid them. I recently saw someone mention ‘SA’ in a group as referring to social anxiety, which led to some confusion as other participants thought about &lt;a href=&#34;https://en.wiktionary.org/wiki/SA#English&#34;&gt;other meanings&lt;/a&gt;. If I’m talking to a web developer, then of course CSS and HTML don’t need to be spelled out.&lt;/p&gt;&#xA;&lt;p&gt;I would also like to suggest that anybody that likes to use internet or generational slang to have their device expand these into their full forms rather than assuming that the other party has the same expansion in mind. I have noticed more difficulty communicating with younger people because they know a different set of initialisms than I do.&lt;/p&gt;&#xA;&lt;h2 id=&#34;use-generic-names&#34;&gt;Use generic names&lt;/h2&gt;&#xA;&lt;p&gt;It&amp;rsquo;s a phone, not an iPhone. Whilst in this case it&amp;rsquo;s not too unreasonable to assume that anyone reading this knows what an iPhone is, this isn&amp;rsquo;t always true. Not everyone has the same knowledge of brands and products. Worse yet, not every region has the same brand or product names for the same products. In the United Kingdom, I grew up knowing what a Pritt Stick was, but most people in other regions will have no idea (it’s a stick of paper glue).&lt;/p&gt;&#xA;&lt;h2 id=&#34;prefer-laypersons-terms&#34;&gt;Prefer layperson’s terms&lt;/h2&gt;&#xA;&lt;p&gt;I once worked in a company providing loans to businesses. Every month there was a company meeting to provide updates from the various departments and I would often hear terms like ‘deliquency’ or ‘origination’ that I am not used to. Since my work wasn’t particularly related to loans, I wasn’t familiar with the terms and would have to ask or look them up later. I think that it’s something that contributed to my feeling of not really being a part of the company and also meant that I wasn’t able to follow the content of the meetings very well, at least in the beginning.&#xA;I see a little irony in this, because I believe that people often prefer to adopt the specialised terms to try to signal being part of a group, but it can have the opposite effect on people who are not familiar with such terms.&lt;/p&gt;&#xA;</content><author><name>Alan Pearce</name></author></entry><entry><title>Announcing Searchix: Nix ecosystem search</title><link rel="alternate" type="text/html" href="https://alanpearce.eu/post/searchix/"></link><id>tag:alanpearce.eu,2014-06-07:searchix</id><updated>2024-07-11T13:05:00Z</updated><content type="html">&lt;p&gt;I decided to create a search tool for NixOS, nix-darwin and&#xA;home-manager options and packages, potentially with more sources to&#xA;come.&lt;/p&gt;&#xA;&lt;p&gt;I called it &lt;a href=&#34;https://searchix.ovh/&#34;&gt;Searchix&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;For NixOS options and packages,&#xA;&lt;a href=&#34;https://search.nixos.org&#34;&gt;search.nixos.org&lt;/a&gt; already exists (and works&#xA;better than Searchix), whereas for home-manager and nix-darwin, I&#xA;couldn&amp;rsquo;t manage to find a web-based search tool that&amp;rsquo;s still&#xA;online&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;. So I wrote one.&lt;/p&gt;&#xA;&lt;p&gt;What I&amp;rsquo;m happy about with it is that it doesn&amp;rsquo;t &lt;em&gt;require&lt;/em&gt; JavaScript,&#xA;but, if it&amp;rsquo;s enabled, makes things a little bit better.  It&amp;rsquo;s only my&#xA;second project in Golang, so I still have things to learn, but I&#xA;definitely think I will enjoy using this language further.&lt;/p&gt;&#xA;&lt;p&gt;It still has quite a bit of room for improvement, but I&amp;rsquo;ve been using&#xA;it quite a lot recently, which leads me to think that other people&#xA;might like to use it, too.&lt;/p&gt;&#xA;&lt;p&gt;If anyone would like to contribute, raise an issue, or host an&#xA;instance themselves, the &lt;a href=&#34;https://codeberg.org/alanpearce/searchix/&#34;&gt;project site and source code are on codeberg&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;&#xA;&lt;hr&gt;&#xA;&lt;ol&gt;&#xA;&lt;li id=&#34;fn:1&#34;&gt;&#xA;&lt;p&gt;I found &lt;a href=&#34;https://home-manager-options.extranix.com/&#34;&gt;Home Manager Option Search&lt;/a&gt; after I&#xA;started this project, but nothing for nix-darwin.&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;/div&gt;&#xA;</content><author><name>Alan Pearce</name></author></entry><entry><title>When Tailscale MagicDNS isn’t</title><link rel="alternate" type="text/html" href="https://alanpearce.eu/post/when-tailscale-magicdns-isn&#39;t/"></link><id>tag:alanpearce.eu,2014-06-07:when-tailscale-magicdns-isn&#39;t</id><updated>2024-06-23T08:57:00Z</updated><summary>Frustrations of a NixOS user</summary><content type="html">&lt;p&gt;On a router, I have &lt;a href=&#34;https://dnsmasq.org/doc.html&#34;&gt;dnsmasq&lt;/a&gt; and &lt;a href=&#34;https://knot-resolver.readthedocs.io/en/stable/&#34;&gt;kresd&lt;/a&gt; as DNS servers. Dnsmasq is accessible on the LAN interface and forwards queries to kresd, which is accessible on the loopback interface.  This has been working for a long time.&lt;/p&gt;&#xA;&lt;p&gt;I recently set up &lt;a href=&#34;https://tailscale.com/&#34;&gt;Tailscale&lt;/a&gt; and was confused as to why &lt;a href=&#34;https://tailscale.com/kb/1081/magicdns&#34;&gt;MagicDNS&lt;/a&gt; wasn’t working on this one device (I have two other NixOS devices that didn’t have any problems). I’m no stranger to investigating these problems, after using and tinkering with networking on Linux/FreeBSD for many years and if there’s a problem, &lt;a href=&#34;https://isitdns.com/&#34;&gt;it’s always DNS&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;p&gt;My first look at &lt;code&gt;/etc/resolv.conf&lt;/code&gt; suggested things should be fine, I thought.&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;# Generated by resolvconf&#xA;search my-network.ts.net&#xA;nameserver 127.0.0.1&#xA;nameserver ::1&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;div data-fence=&#34;0&#34; class=&#34;aside&#34;&gt;&#xA;&lt;p&gt;‘why is this even generated by &lt;code&gt;resolvconf&lt;/code&gt;?’, I ask myself: this is a router with a static networking configuration and custom upstream nameservers. I’ll investigate that later, I tell myself.&lt;/p&gt;&#xA;&lt;/div&gt;&#xA;&lt;p&gt;I eventually realised that it should be using 100.100.100.100 for two reasons.&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;A working machine’s &lt;code&gt;/etc/resolv.conf&lt;/code&gt; contains:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;# Generated by resolvconf&#xA;search my-network.ts.net&#xA;nameserver 100.100.100.100&#xA;options edns0&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;The Tailscale dashboard gives me a &lt;em&gt;hint&lt;/em&gt; under the nameservers section:&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;h3 id=&#34;nameservers&#34;&gt;Nameservers&lt;/h3&gt;&#xA;&lt;p&gt;Set the nameservers used by devices on your network to resolve DNS queries. &lt;a href=&#34;https://tailscale.com/kb/1054/dns&#34;&gt;Learn more ↗&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;em&gt;my-network&lt;/em&gt;.ts.net ✨MagicDNS&lt;br&gt;&#xA;100.100.100.100&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;The &lt;a href=&#34;https://tailscale.com/kb/1054/dns&#34;&gt;linked documentation (DNS in Tailscale)&lt;/a&gt;  doesn’t even mention 100.100.100.100, nor does the documentation for &lt;a href=&#34;https://tailscale.com/kb/1081/magicdns&#34;&gt;MagicDNS&lt;/a&gt;. It is explained as &lt;a href=&#34;https://tailscale.com/blog/2021-09-private-dns-with-magicdns#how-magicdns-works&#34;&gt;part of a blog post under the heading ‘how MagicDNS works’&lt;/a&gt;, but that’s not the first place I’d look.&lt;/p&gt;&#xA;&lt;p&gt;This led me to try to find what might be responsible for the &lt;code&gt;nameserver 127.0.0.1&lt;/code&gt; setting:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;I checked for systemd-resolved, but it wasn’t that (the nameserver would have been 127.0.0.53 if it were).&lt;/li&gt;&#xA;&lt;li&gt;I didn’t think it was anything to do with dnsmasq because that’s configured to use the LAN interface, not the loopback.&lt;/li&gt;&#xA;&lt;li&gt;I didn’t think it was kresd either, since another device uses kresd, but does not have the problem. kresd is not listening on a loopback address on the default port 53 on either machine, meaning that if it were doing this, DNS resolution would have been broken on both machines for a long time.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Eventually I stumbled upon something that worked: setting &lt;code&gt;networking.resolvconf.useLocalResolver = false&lt;/code&gt;. I then started to investigate in order to open an issue with NixOS, but found things got more confusing and I forgot why I was shaving a yak&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;&#xA;&lt;hr&gt;&#xA;&lt;h3 id=&#34;unexpected-behaviours&#34;&gt;Unexpected behaviours&lt;/h3&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;The NixOS kresd module &lt;a href=&#34;https://github.com/NixOS/nixpkgs/blob/bfb7a882678e518398ce9a31a881538679f6f092/nixos/modules/services/networking/kresd.nix#L113&#34;&gt;blindly sets &lt;code&gt;networking.resolvconf.useLocalResolver&lt;/code&gt; to default to &lt;code&gt;true&lt;/code&gt;&lt;/a&gt; because &lt;a href=&#34;https://github.com/NixOS/nixpkgs/pull/124391&#34;&gt;someone ran into resolver loops&lt;/a&gt; and this was accepted on the grounds that it’s &lt;a href=&#34;https://github.com/NixOS/nixpkgs/pull/124391#pullrequestreview-667950510&#34;&gt;‘good to be consistent’ (with pdns-recursor, for example)&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;I consider this &lt;a href=&#34;https://en.wikipedia.org/wiki/Action_at_a_distance#%22Spooky_action_at_a_distance%22&#34;&gt;&amp;ldquo;spooky action at a distance&amp;rdquo;&lt;/a&gt;.  I do not think it should do this, but I can see how it &lt;em&gt;could&lt;/em&gt; be helpful. In enough cases, though? I’m not sure.&lt;/li&gt;&#xA;&lt;li&gt;In my case, kresd was &lt;em&gt;never even listening&lt;/em&gt; on localhost port 53, meaning that this default setting would have led to a broken DNS setup, which at least would at least have led me to investigate the right thing at that time.&#xA;:::{.aside}&#xA;Why didn’t it, then?&#xA;:::&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;The NixOS dnsmasq module sets &lt;a href=&#34;https://github.com/NixOS/nixpkgs/blob/7780e5160e011b39019797a4c4b1a4babc80d1bf/nixos/modules/services/networking/dnsmasq.nix#L150-L151&#34;&gt;&lt;code&gt;networking.resolvconf.useLocalResolver = true&lt;/code&gt; if &lt;code&gt;services.dnsmasq.resolveLocalQueries = true&lt;/code&gt;&lt;/a&gt;. This is at least less spooky and distant, but still faulty.&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;I had indeed set &lt;code&gt;services.dnsmasq.resolveLocalQueries = true&lt;/code&gt;, because I would like to be able to &lt;code&gt;ping foo.lan&lt;/code&gt; on the router and it made that possible.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;My erroneous assumption was likely that this setting changes the system nameserver to match the listen address of dnsmasq, rather than setting &lt;code&gt;networking.resolvconf.useLocalResolver&lt;/code&gt;. Setting  &lt;code&gt;resolveLocalQueries = false&lt;/code&gt; was one of the first things I tried and it didn’t make a difference, which was unexpected (because kresd was setting it).&lt;/p&gt;&#xA;&lt;div data-fence=&#34;1&#34; class=&#34;aside&#34;&gt;&#xA;&lt;p&gt;If that weren’t enough, &lt;a href=&#34;https://github.com/NixOS/nixpkgs/blob/7780e5160e011b39019797a4c4b1a4babc80d1bf/nixos/modules/services/networking/dnsmasq.nix#L138-L139&#34;&gt;&lt;code&gt;services.dnsmasq.resolveLocalQueries&lt;/code&gt; sets &lt;code&gt;networking.nameservers&lt;/code&gt; to include 127.0.0.1&lt;/a&gt;, which makes things more confusing, and is wrong because I haven’t configured dnsmasq to listen on this address.&lt;/p&gt;&#xA;&lt;/div&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;dnsmasq’s &lt;code&gt;--interface=&amp;lt;interface name&amp;gt;&lt;/code&gt; setting doesn’t work either as I expected or as it is &lt;a href=&#34;https://dnsmasq.org/docs/dnsmasq-man.html&#34;&gt;documented&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;-i, &amp;ndash;interface=&amp;lt;interface name&amp;gt;&lt;/strong&gt;&lt;br&gt;&#xA;Listen only on the specified interface(s).&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;I had this set to listen &lt;em&gt;only&lt;/em&gt; on the LAN interface and I could see it nevertheless listening on &lt;code&gt;*:53&lt;/code&gt; in &lt;code&gt;lsof&lt;/code&gt;, rather than the addresses of the LAN interface.&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;This behaviour &lt;em&gt;is&lt;/em&gt; mentioned, under a different option, &lt;code&gt;--bind-interfaces&lt;/code&gt;:&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;On systems which support it, dnsmasq binds the wildcard address, even when it is listening on only some interfaces. It then discards requests that it shouldn’t reply to. This has the advantage of working even when interfaces come and go and change address. This option forces dnsmasq to really bind only the interfaces it is listening on. &lt;em&gt;About the only time when this is useful is when running another nameserver (or another instance of dnsmasq) on the same machine&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;I had enabled this setting when I set up kresd on the machine, because the last sentence applies to my case and interfaces are not ‘coming and going’&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;. The naming is weird as it would suggest it works like &lt;code&gt;--interface&lt;/code&gt;; namely that &lt;code&gt;--bind-interfaces=&amp;lt;interface name&amp;gt;&lt;/code&gt; would be a reasonable use. Alas, it is a boolean flag and takes no value.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Even when &lt;code&gt;--interface&lt;/code&gt; and &lt;code&gt;--bind-interfaces&lt;/code&gt; &lt;em&gt;are&lt;/em&gt; set, dnsmasq decides to ignore my intent and explicitly listen on loopback. This is weird, but, guess what, documented back under &lt;code&gt;--interface&lt;/code&gt;:&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Dnsmasq automatically adds the loopback (local) interface to the list of interfaces to use when the &lt;strong&gt;&amp;ndash;interface&lt;/strong&gt; option is used.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;div data-fence=&#34;1&#34; class=&#34;aside&#34;&gt;&#xA;&lt;p&gt;This explains why enabling kresd didn’t break things before; dnsmasq was listening on 127.0.0.1, even though I thought I had told it not to.&lt;/p&gt;&#xA;&lt;/div&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;The option name &lt;code&gt;networking.resolvconf.useLocalResolver&lt;/code&gt; and its &lt;a href=&#34;https://search.nixos.org/options?channel=unstable&amp;amp;show=networking.resolvconf.useLocalResolver&amp;amp;from=0&amp;amp;size=50&amp;amp;sort=relevance&amp;amp;type=packages&amp;amp;query=uselocalresolver&#34;&gt;documentation&lt;/a&gt; are unclear.&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Use local DNS server for resolving.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;This sentence adds no additional data not present in the option name. Local to what? I’m on a &lt;em&gt;Local&lt;/em&gt; Area Network and wish to use a DNS server on the LAN, should I enable this? No, that’s not what this option is for. It could mean local to &lt;em&gt;this host&lt;/em&gt;, looking at &lt;a href=&#34;https://github.com/NixOS/nixpkgs/blob/bfb7a882678e518398ce9a31a881538679f6f092/nixos/modules/config/resolvconf.nix#L29-L32&#34;&gt;its usage&lt;/a&gt;. (I deliberately avoided combining the words ‘local’ and ‘host’, for reasons below)&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Even if it had a clearer name like &lt;code&gt;useLocalhostResolver&lt;/code&gt;, the inaccuracy would remain, as &lt;code&gt;getent hosts localhost&lt;/code&gt; and &lt;code&gt;getent ahosts localhost&lt;/code&gt; both prefer ::1 over 127.0.0.1, not the other way around.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;What would have happened if I had enabled this setting with a server listening on ::1 and &lt;em&gt;not&lt;/em&gt; 127.0.0.1? It would work, but not be the best setting as applications would attempt to reach a nameserver that is not listening on 127.0.0.1.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;It might be confusing to reference a hostname when talking about nameserver reachability, since an IP address is required to reach a nameserver and a nameserver &lt;del&gt;is&lt;/del&gt; &lt;ins&gt;could be&lt;/ins&gt; required to resolve a hostname. Setting &lt;code&gt;nameserver localhost&lt;/code&gt; in &lt;code&gt;/etc/resolv.conf&lt;/code&gt; won’t work, I &lt;em&gt;thought&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;I tried it. Neovim didn’t highlight it as an error&lt;sup id=&#34;fnref:3&#34;&gt;&lt;a href=&#34;#fn:3&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;3&lt;/a&gt;&lt;/sup&gt; and it did &lt;strong&gt;not&lt;/strong&gt; break name resolution, presumably because &lt;a href=&#34;https://github.com/NixOS/nixpkgs/blob/bfb7a882678e518398ce9a31a881538679f6f092/nixos/modules/config/networking.nix#L179-L182&#34;&gt;&lt;code&gt;localhost&lt;/code&gt; is added to &lt;code&gt;/etc/hosts&lt;/code&gt;&lt;/a&gt; &lt;em&gt;and&lt;/em&gt; is a &lt;a href=&#34;https://www.man7.org/linux/man-pages/man8/nss-myhostname.8.html&#34;&gt;special case in &lt;code&gt;nss-myhostname&lt;/code&gt;&lt;/a&gt;, the existence of which I might not have known had I not set up &lt;a href=&#34;https://en.wikipedia.org/wiki/Multicast_DNS&#34;&gt;multicast DNS&lt;/a&gt; to resolve &lt;code&gt;.local&lt;/code&gt; hostnames in &lt;code&gt;/etc/nsswitch.conf&lt;/code&gt; in the past,&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;The hostnames &amp;ldquo;localhost&amp;rdquo; and &amp;ldquo;localhost.localdomain&amp;rdquo; (as&#xA;well as any hostname ending in &amp;ldquo;.localhost&amp;rdquo; or&#xA;&amp;ldquo;.localhost.localdomain&amp;rdquo;) are resolved to the IP addresses&#xA;127.0.0.1 and ::1.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;Why is localhost added to &lt;code&gt;/etc/hosts&lt;/code&gt; if it’s handled by &lt;code&gt;nss-myhostname&lt;/code&gt; in &lt;code&gt;/etc/nsswitch.conf?&lt;/code&gt;? The man page of &lt;code&gt;nsswitch.conf&lt;/code&gt; (&lt;a href=&#34;https://www.man7.org/linux/man-pages/man5/nsswitch.conf.5.html&#34;&gt;mirror&lt;/a&gt;) gives a small clue:&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;code&gt;/etc/nsswitch.conf&lt;/code&gt; is used by the GNU C Library and certain&#xA;other applications&lt;sup id=&#34;fnref:4&#34;&gt;&lt;a href=&#34;#fn:4&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;4&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;Why isn’t even the choice of a name resolution mechanism for &lt;em&gt;localhost&lt;/em&gt; unified in 2024?&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;I tried on macOS and iOS. Both allow setting a named nameserver in the GUI, which surprised me. I remember that on earlier versions of Windows (at least on XP, Vista and 7) there were special input boxes that exclusively allowed an IPv4 address, although there was a separate dialogue to input IPv6 addresses. I wonder if that allows hostnames or not, but I don’t have Windows running at the moment to check.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Setting &lt;code&gt;networking.resolvconf.enable = false&lt;/code&gt; doesn’t appear to do.. well.. anything.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;The &lt;em&gt;generated by resolvconf&lt;/em&gt; comment in &lt;code&gt;/etc/resolv.conf&lt;/code&gt; remains, as do the previous nameserver entries.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;code&gt;/run/current-system/sw/bin/resolvconf&lt;/code&gt; is not removed.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;code&gt;man resolvconf&lt;/code&gt; has content (because it’s a link to &lt;code&gt;man resolvectl&lt;/code&gt;, which is part of &lt;code&gt;systemd-resolved&lt;/code&gt;, which isn’t even enabled on this system)&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;I was surprised that &lt;code&gt;/etc/resolv.conf&lt;/code&gt; was writable at all, as &lt;del&gt;all&lt;/del&gt; &lt;ins&gt;many&lt;/ins&gt; files under &lt;code&gt;/etc/&lt;/code&gt; are symlinks to their namesakes under &lt;code&gt;/etc/static&lt;/code&gt;, which itself is a symlink to a folder in the nix store which contains… more symlinks. Here I use &lt;code&gt;resolvconf.conf&lt;/code&gt; as an example, i.e. the configuration of &lt;code&gt;resolvconf&lt;/code&gt;, the program that manages &lt;code&gt;resolv.conf&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt; rwxrwxrwx 1 root root  27 May 26 23:14 /etc/resolvconf.conf -&amp;gt; /etc/static/resolvconf.conf&#xA;lrwxrwxrwx 1 root root  51 May 26 23:14 /etc/static -&amp;gt; /nix/store/pm0yi93ak5kcvfmidv5lckzfixrh2gck-etc/etc/&#xA;lrwxrwxrwx 4 root root  63 Jan  1  1970 /nix/store/pm0yi93ak5kcvfmidv5lckzfixrh2gck-etc/etc/resolvconf.conf -&amp;gt; /nix/store/kf0lrhiqqqrc6w96h4qm0sysffnccx2d-etc-resolvconf.conf&#xA;-r--r--r-- 3 root root 518 Jan  1  1970 /nix/store/kf0lrhiqqqrc6w96h4qm0sysffnccx2d-etc-resolvconf.conf&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;That’s too much indirection for me. If &lt;a href=&#34;https://en.wikipedia.org/wiki/Fundamental_theorem_of_software_engineering&#34;&gt;‘we can solve any problem by introducing an extra level of indirection’&lt;/a&gt;, this suggests that &lt;em&gt;at least three&lt;/em&gt; problems have been solved here.&lt;/p&gt;&#xA;&lt;p&gt;Isn’t it odd that the symlinks are writable to all? I know that &lt;code&gt;/nix/store&lt;/code&gt; is a read-only filesystem, but it looks odd. Upon searching the web for information, I was directed to the &lt;a href=&#34;https://www.gnu.org/software/coreutils/manual/html_node/chmod-invocation.html&#34;&gt;coreutils &lt;code&gt;chmod&lt;/code&gt; documentation&lt;/a&gt;:&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;code&gt;chmod&lt;/code&gt;  doesn’t change the permissions of symbolic links; the &lt;code&gt;chmod&lt;/code&gt; system call cannot change their permissions on most systems, and most systems ignore permissions of symbolic links&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;&lt;em&gt;Most&lt;/em&gt; systems? What does this mean? Is it based on the filesystem used? I would assume that it doesn’t mean ’this is the case on Linux’ given the reference to the system call of the same name and that Linux was not mentioned. The man page for the system call mentions&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;em&gt;flags&lt;/em&gt; can either be 0, or include the following flag:&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;br&gt;&#xA;&lt;strong&gt;AT_SYMLINK_NOFOLLOW&lt;/strong&gt;&lt;br&gt;&#xA;If pathname is a symbolic link, do not dereference it:&#xA;instead operate on the link itself.  This flag is not&#xA;currently implemented.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;The default value of &lt;code&gt;networking.resolvconf.enable&lt;/code&gt;  is &lt;a href=&#34;https://search.nixos.org/options?channel=unstable&amp;amp;show=networking.resolvconf.enable&amp;amp;from=0&amp;amp;size=50&amp;amp;sort=relevance&amp;amp;type=packages&amp;amp;query=networking.resolvconf.enable&#34;&gt;&lt;code&gt;!(config.environment.etc ? &amp;quot;resolv.conf&amp;quot;)&lt;/code&gt;&lt;/a&gt;, which I understand as &lt;em&gt;if the content of &lt;code&gt;resolv.conf&lt;/code&gt; isn’t otherwise assigned&lt;/em&gt;.&lt;/li&gt;&#xA;&lt;li&gt;There are values in &lt;code&gt;networking.nameservers&lt;/code&gt;, but these aren’t used as content for &lt;code&gt;resolv.conf&lt;/code&gt;, which I thought would have been reasonable.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;What &lt;em&gt;is&lt;/em&gt; the point of &lt;code&gt;networking.resolvconf.enable&lt;/code&gt;, then? And what about &lt;code&gt;networking.nameservers&lt;/code&gt;? Where do its values even go? &lt;sup id=&#34;fnref:5&#34;&gt;&lt;a href=&#34;#fn:5&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;5&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;This issue pushed me to drop flakes on the router so that &lt;code&gt;nixos-option&lt;/code&gt; would help me as &lt;a href=&#34;https://github.com/NixOS/nixpkgs/issues/97855&#34;&gt;it does not support flakes&lt;/a&gt;&lt;sup id=&#34;fnref:6&#34;&gt;&lt;a href=&#34;#fn:6&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;6&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;The Tailscale module &lt;a href=&#34;https://github.com/NixOS/nixpkgs/blob/7780e5160e011b39019797a4c4b1a4babc80d1bf/nixos/modules/services/networking/tailscale.nix#L87&#34;&gt;adds &lt;code&gt;resolvconf&lt;/code&gt; to its path conditionally&lt;/a&gt;. The &lt;a href=&#34;https://github.com/NixOS/nixpkgs/commit/922351ec866dcfe1dca4d190bfd3c360933e5cd0&#34;&gt;commit adding this condition&lt;/a&gt; explains that ‘trying to use [resolvconf] always fails because&#xA;&lt;code&gt;/etc/resolvconf.conf&lt;/code&gt; contains an &lt;code&gt;exit 1&lt;/code&gt;’, which sounds perfectly reasonable.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;If &lt;code&gt;resolvconf&lt;/code&gt; weren’t in tailscaled’s path, Tailscale would fall back to overwriting resolv.conf, which I found out about because it is a common enough problem/question to warrant &lt;a href=&#34;https://tailscale.com/kb/1235/resolv-conf&#34;&gt;a heading and its own page&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;p&gt;This document is the most concise and informative clarification of my original issue; the last paragraph tells me everything I needed to know:&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Even if you set &lt;code&gt;--accept-dns=false&lt;/code&gt;, Tailscale’s MagicDNS server still replies at &lt;code&gt;100.100.100.100&lt;/code&gt; (or &lt;code&gt;fd7a:115c:a1e0::53&lt;/code&gt;), as long as MagicDNS is enabled on the tailnet. If you’d like to manually configure your DNS configuration, you can point &lt;code&gt;*.ts.net&lt;/code&gt; queries at &lt;code&gt;100.100.100.100&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;Sadly I didn’t look at this page earlier as Tailscale isn’t the one overwriting &lt;code&gt;/etc/resolv.conf&lt;/code&gt;: it would have set the nameserver to be &lt;code&gt;100.100.100.100&lt;/code&gt; in that case. Its behaviour is reasonable as ‘there are &lt;a href=&#34;https://tailscale.com/blog/sisyphean-dns-client-linux&#34;&gt;an incredible number of ways&lt;/a&gt; to configure DNS on Linux’.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;This blog post suggests that the upcoming (as of April 2021) Tailscale 1.8 will use/prefer using &lt;code&gt;systemd-resolved&lt;/code&gt; to configure the system resolver&lt;/li&gt;&#xA;&lt;li&gt;It convinced me that &lt;code&gt;systemd-resolved&lt;/code&gt; would be the right choice even on a router as the nameserver should depend on the interface. Thanks &lt;a href=&#34;https://xeiaso.net/&#34;&gt;Xe&lt;/a&gt;, I always like your posts!&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;This should be the end of my issues now then, right?&lt;/p&gt;&#xA;&lt;p&gt;What happens when I enable &lt;code&gt;systemd-resolved&lt;/code&gt; and disable &lt;code&gt;resolvconf&lt;/code&gt;? The hilarity continues:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;# resolv.conf(5) file generated by tailscale&#xA;# For more info, see https://tailscale.com/s/resolvconf-overwrite&#xA;# DO NOT EDIT THIS FILE BY HAND -- CHANGES WILL BE OVERWRITTEN&#xA;nameserver 100.100.100.100&#xA;search my-network.ts.net lan my-network.ts.net&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;I expected Tailscale not to overwrite &lt;code&gt;resolv.conf&lt;/code&gt; in this scenario, but instead configure &lt;code&gt;systemd-resolved&lt;/code&gt; (Adding the tailnet to the search domains without checking its presence is yet another issue). I think it’s a race condition that &lt;code&gt;tailscaled&lt;/code&gt; won that might have been caused by NixOS starting the services at the same time, however &lt;code&gt;tailscaled.service&lt;/code&gt; has &lt;code&gt;After=systemd-resolved.service&lt;/code&gt;. Restarting &lt;code&gt;systemd-resolved&lt;/code&gt; &lt;em&gt;then&lt;/em&gt; &lt;code&gt;tailscaled&lt;/code&gt; explicitly did the right thing:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;# This is /run/systemd/resolve/stub-resolv.conf managed by man:systemd-resolved(8).&#xA;# Do not edit.&#xA;# [...]&#xA;nameserver 127.0.0.53&#xA;options edns0 trust-ad&#xA;search lan my-network.ts.net&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;DNS can be confusing sometimes!&lt;/p&gt;&#xA;&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;&#xA;&lt;hr&gt;&#xA;&lt;ol&gt;&#xA;&lt;li id=&#34;fn:1&#34;&gt;&#xA;&lt;p&gt;Whilst checking to see if &lt;a href=&#34;https://en.wiktionary.org/wiki/yak_shaving&#34;&gt;yak shaving&lt;/a&gt; was the right turn of phrase, Wiktionary suggested &lt;a href=&#34;https://en.wiktionary.org/wiki/when_you%27re_up_to_your_neck_in_alligators,_it%27s_hard_to_remember_that_your_initial_objective_was_to_drain_the_swamp#English&#34;&gt;‘when you&amp;rsquo;re up to your neck in alligators, it&amp;rsquo;s hard to remember that your initial objective was to drain the swamp’&lt;/a&gt; which would be more fitting, but I first learned of this expression today and don’t think it’s as widely-known.&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li id=&#34;fn:2&#34;&gt;&#xA;&lt;p&gt;Since the router has a dynamic &lt;del&gt;public&lt;/del&gt; &lt;ins&gt;CGNAT&lt;/ins&gt; IP address, it’s true that the addresses are changing, but that’s not relevant to dnsmasq given that it was not ever configured to listen on this interface.&amp;#160;&lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li id=&#34;fn:3&#34;&gt;&#xA;&lt;p&gt;vim’s syntax highlighting in &lt;code&gt;/etc/resolv.conf&lt;/code&gt; marks &lt;code&gt;nameserver localhost&lt;/code&gt; as an error, which is neat, but somewhat inaccurate here, as this does not appear to be invalid.&amp;#160;&lt;a href=&#34;#fnref:3&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li id=&#34;fn:4&#34;&gt;&#xA;&lt;p&gt;As a Wikipedia editor would ask, &lt;em&gt;which&lt;/em&gt;?&amp;#160;&lt;a href=&#34;#fnref:4&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li id=&#34;fn:5&#34;&gt;&#xA;&lt;p&gt;I &lt;a href=&#34;https://github.com/search?q=repo%3ANixOS%2Fnixpkgs+networking.nameservers&amp;amp;type=code&#34;&gt;searched nixpkgs on Github&lt;/a&gt; and found it amusing that all the results where it is set correctly are &lt;em&gt;in tests&lt;/em&gt;, but the other results show hardcoded definitions.&amp;#160;&lt;a href=&#34;#fnref:5&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li id=&#34;fn:6&#34;&gt;&#xA;&lt;p&gt;After reading through the issue, the title does not appear to be accurate given that there are workarounds, however, upon loading the page and seeing that the issue is open since 2020 and has a small scroll bar, indicating many comments, it’s easy to be drawn to the assumption that it continues to be an issue.&amp;#160;&lt;a href=&#34;#fnref:6&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;/div&gt;&#xA;</content><author><name>Alan Pearce</name></author></entry><entry><title>Homesteading</title><link rel="alternate" type="text/html" href="https://alanpearce.eu/post/homesteading/"></link><id>tag:alanpearce.eu,2014-06-07:homesteading</id><updated>2023-09-22T10:09:22.141Z</updated><summary>Running my own code</summary><content type="html">&lt;p&gt;I switched away from &lt;a href=&#34;https://www.getzola.org/&#34;&gt;Zola&lt;/a&gt; and made my own &lt;a href=&#34;https://git.alanpearce.eu/website/tree/main/&#34;&gt;static site builder&lt;/a&gt; that uses only HTML templates. I&amp;rsquo;ve been wanting to do this since at least 2017, when I started to work on a &lt;a href=&#34;https://git.alanpearce.eu/archive/homestead/tree/2017/&#34;&gt;homestead project&lt;/a&gt;, which I didn&amp;rsquo;t quite finish.&lt;/p&gt;&#xA;&lt;p&gt;The recent release of &lt;a href=&#34;https://bun.sh/&#34;&gt;Bun&lt;/a&gt;, which touts itself as an &amp;ldquo;all-in-one JavaScript toolkit&amp;rdquo; encouraged me to play around with it.  I have to say, I am surprised by how energising it was; an antidote to the &amp;ldquo;JavaScript fatigue&amp;rdquo; I&amp;rsquo;ve read about and definitely experienced.&lt;/p&gt;&#xA;&lt;p&gt;I decided that I&amp;rsquo;d start by serving my site using Bun&amp;rsquo;s web server, then I added site generation later. I have been intrigued by the idea of DOM templating ever since I read about it on &lt;a href=&#34;https://camendesign.com/dom_templating&#34;&gt;Camen Design&lt;/a&gt; &lt;a href=&#34;https://camendesign.com/code/dom_templating/domtemplate_v4.rem&#34;&gt;in 2012&lt;/a&gt; and I&amp;rsquo;ve enjoyed putting it into practice.&lt;/p&gt;&#xA;</content><author><name>Alan Pearce</name></author></entry><entry><title>Running NixOS on a NanoPi R5S</title><link rel="alternate" type="text/html" href="https://alanpearce.eu/post/nixos-on-nanopi-r5s/"></link><id>tag:alanpearce.eu,2014-06-07:nixos-on-nanopi-r5s</id><updated>2023-07-30T08:51:46Z</updated><content type="html">&lt;p&gt;I managed to get &lt;a href=&#34;https://nixos.org&#34;&gt;NixOS&lt;/a&gt; running on my &lt;a href=&#34;https://www.friendlyelec.com/index.php?route=product/product&amp;amp;product_id=287&#34;&gt;NanoPi R5S&lt;/a&gt; (&lt;a href=&#34;https://wiki.friendlyelec.com/wiki/index.php/NanoPi_R5S&#34;&gt;FriendlyElec Wiki&lt;/a&gt;).&lt;/p&gt;&#xA;&lt;p&gt;Firstly, I flashed a pre-built stock Debian image from &lt;a href=&#34;https://github.com/inindev/nanopi-r5&#34;&gt;inindev&lt;/a&gt; to an SD card. This can be used as a rescue system later on.&lt;/p&gt;&#xA;&lt;p&gt;From that SD card, I then flashed the same system onto the internal &lt;abbr title=&#34;embedded MultiMediaCard&#34;&gt;eMMC&lt;/abbr&gt; Storage. I only really needed to this to ensure UBoot was correctly installed; I think there will be an easier way to do it.&lt;/p&gt;&#xA;&lt;p&gt;I had nix already installed on the &lt;abbr title=&#34;Non-Volatile Memory Express&#34;&gt;NVMe&lt;/abbr&gt; &lt;abbr title=&#34;Solid-State Drive&#34;&gt;SSD&lt;/abbr&gt; along with a home directory. I bind-mounted &lt;code&gt;/nix&lt;/code&gt; and &lt;code&gt;/home&lt;/code&gt; following the fstab I had previously set up:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-conf&#34;&gt;UUID=replaceme  /mnt    ext4    relatime,lazytime   0 2&#xA;/mnt/nix        /nix    none    defaults,bind       0 0&#xA;/mnt/srv        /srv    none    defaults,bind       0 0&#xA;/mnt/home       /home   none    defaults,bind       0 0&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;I then created a user for myself using that home directory, I had full access to nix in the new Debian environment. This meant I had access to &lt;code&gt;nixos-install&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;p&gt;I wanted to use the &lt;a href=&#34;https://u-boot.readthedocs.io/en/latest/develop/distro.html#boot-configuration-files&#34;&gt;extlinux support in UBoot&lt;/a&gt;, so I made &lt;code&gt;/mnt/boot&lt;/code&gt; point to &lt;code&gt;/boot&lt;/code&gt; on the &lt;abbr&gt;eMMC&lt;/abbr&gt;:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-sh&#34;&gt;mkdir /mnt/{emmc,boot}&#xA;mount LABEL=rootfs /mnt/emmc&#xA;mount --bind /mnt/emmc /mnt/boot&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;aside&gt;&#xA;One could &lt;em&gt;probably&lt;/em&gt; delete everything else on the &lt;abbr&gt;eMMC&lt;/abbr&gt; and move the contents of &lt;code&gt;/mnt/emmc/boot&lt;/code&gt; to &lt;code&gt;/mnt/emmc&lt;/code&gt;, thus obviating the need to bind-mount &lt;code&gt;/boot&lt;/code&gt;&#xA;&lt;/aside&gt;&#xA;&lt;p&gt;I ran &lt;code&gt;nixos-generate-config&lt;/code&gt; as usual, which set up the mount points in &lt;code&gt;hardware-configuration.nix&lt;/code&gt; correctly. &lt;code&gt;configuration.nix&lt;/code&gt; needed a bit of tweaking. My first booting configuration was something like this, mostly borrowed from &lt;a href=&#34;https://github.com/inindev/nanopi-r5/issues/11#issue-1789308883&#34;&gt;Artem Boldariev&amp;rsquo;s comment&lt;/a&gt;:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-nix&#34;&gt;{ config&#xA;, pkgs&#xA;, lib&#xA;, ...&#xA;}:&#xA;let&#xA;  fsTypes = [ &amp;quot;f2fs&amp;quot; &amp;quot;ext&amp;quot; &amp;quot;exfat&amp;quot; &amp;quot;vfat&amp;quot; ];&#xA;in&#xA;{&#xA;  imports = [ ./hardware-configuration.nix ];&#xA;  boot = {&#xA;    kernelPackages = pkgs.linuxKernel.packages.linux_6_4;&#xA;&#xA;    # partial Rockchip related changes from Debian 12 kernel version 6.1&#xA;    # Also, see here:&#xA;    # https://discourse.nixos.org/t/how-to-provide-missing-headers-to-a-kernel-build/11422/3&#xA;    kernelPatches = [&#xA;      {&#xA;        name = &amp;quot;rockchip-config.patch&amp;quot;;&#xA;        patch = null;&#xA;        extraConfig = &#39;&#39;&#xA;          PHY_ROCKCHIP_PCIE Y&#xA;          PCIE_ROCKCHIP_EP y&#xA;          PCIE_ROCKCHIP_DW_HOST y&#xA;          ROCKCHIP_VOP2 y&#xA;        &#39;&#39;;&#xA;      }&#xA;      {&#xA;        name = &amp;quot;status-leds.patch&amp;quot;;&#xA;        patch = null;&#xA;        # old:&#xA;        # LEDS_TRIGGER_NETDEV y&#xA;        extraConfig = &#39;&#39;&#xA;          LED_TRIGGER_PHY y&#xA;          USB_LED_TRIG y&#xA;          LEDS_BRIGHTNESS_HW_CHANGED y&#xA;          LEDS_TRIGGER_MTD y&#xA;        &#39;&#39;;&#xA;      }&#xA;    ];&#xA;    &#xA;    supportedFilesystems = fsTypes;&#xA;    initrd.supportedFilesystems = fsTypes;&#xA;&#xA;    initrd.availableKernelModules = [&#xA;      ## Rockchip&#xA;      ## Storage&#xA;      &amp;quot;sdhci_of_dwcmshc&amp;quot;&#xA;      &amp;quot;dw_mmc_rockchip&amp;quot;&#xA;&#xA;      &amp;quot;analogix_dp&amp;quot;&#xA;      &amp;quot;io-domain&amp;quot;&#xA;      &amp;quot;rockchip_saradc&amp;quot;&#xA;      &amp;quot;rockchip_thermal&amp;quot;&#xA;      &amp;quot;rockchipdrm&amp;quot;&#xA;      &amp;quot;rockchip-rga&amp;quot;&#xA;      &amp;quot;pcie_rockchip_host&amp;quot;&#xA;      &amp;quot;phy-rockchip-pcie&amp;quot;&#xA;      &amp;quot;phy_rockchip_snps_pcie3&amp;quot;&#xA;      &amp;quot;phy_rockchip_naneng_combphy&amp;quot;&#xA;      &amp;quot;phy_rockchip_inno_usb2&amp;quot;&#xA;      &amp;quot;dwmac_rk&amp;quot;&#xA;      &amp;quot;dw_wdt&amp;quot;&#xA;      &amp;quot;dw_hdmi&amp;quot;&#xA;      &amp;quot;dw_hdmi_cec&amp;quot;&#xA;      &amp;quot;dw_hdmi_i2s_audio&amp;quot;&#xA;      &amp;quot;dw_mipi_dsi&amp;quot;&#xA;    ];&#xA;    loader = {&#xA;      timeout = 3;&#xA;      grub.enable = false;&#xA;      generic-extlinux-compatible = {&#xA;        enable = true;&#xA;        useGenerationDeviceTree = true;&#xA;      };&#xA;    };&#xA;  };&#xA;  # this file is from debian and should be in /boot/&#xA;  hardware.deviceTree.name = &amp;quot;../../rk3568-nanopi-r5s.dtb&amp;quot;;&#xA;  # Most Rockchip CPUs (especially with hybrid cores) work best with &amp;quot;schedutil&amp;quot;&#xA;  powerManagement.cpuFreqGovernor = &amp;quot;schedutil&amp;quot;;&#xA;  &#xA;  boot.kernelParams = [&#xA;    &amp;quot;console=tty1&amp;quot;&#xA;    &amp;quot;console=ttyS2,1500000&amp;quot;&#xA;    &amp;quot;earlycon=uart8250,mmio32,0xfe660000&amp;quot;&#xA;  ];&#xA;  # Let&#39;s blacklist the Rockchips RTC module so that the&#xA;  # battery-powered HYM8563 (rtc_hym8563 kernel module) will be used&#xA;  # by default&#xA;  boot.blacklistedKernelModules = [ &amp;quot;rtc_rk808&amp;quot; ];&#xA;&#xA;  # ... typical config omitted for brevity&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;Due to the custom kernel configuration, building takes a while. I set up a &lt;a href=&#34;https://nixos.org/manual/nix/stable/advanced-topics/distributed-builds.html&#34;&gt;distributed build&lt;/a&gt; to speed things up, using a &lt;a href=&#34;https://www.hetzner.com/cloud&#34;&gt;Hetzner Cloud&lt;/a&gt; CAX21 ARM64 instance (although I could have used an x86_64 system with one of the methods mentioned on the &lt;a href=&#34;https://nixos.wiki/wiki/NixOS_on_ARM#Build_your_own_image_natively&#34;&gt;NixOS on ARM NixOS wiki page&lt;/a&gt;). This made for a very long &lt;code&gt;nixos-install&lt;/code&gt; command line:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-sh&#34;&gt;sudo env PATH=$PATH =nixos-install --root /mnt --no-channel-copy --channel https://nixos.org/channels/nixos-23.05 --option builders&#39;ssh://my-host aarch64-linux /root/.ssh/id_pappel_nixpkgs 4 2 big-parallel&#39; --option builders-use-substitutes true --max-jobs 0&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;I added &lt;code&gt;setenv bootmeths &amp;quot;extlinux&amp;quot;&lt;/code&gt; to &lt;code&gt;/boot/boot.txt&lt;/code&gt; and ran &lt;code&gt;/boot/mkscr.sh&lt;/code&gt; as root to ensure that UBoot would search for the &lt;code&gt;extlinux.conf&lt;/code&gt; file&lt;/p&gt;&#xA;</content><author><name>Alan Pearce</name></author></entry><entry><title>Now on three continents</title><link rel="alternate" type="text/html" href="https://alanpearce.eu/post/now-on-three-continents/"></link><id>tag:alanpearce.eu,2014-06-07:now-on-three-continents</id><updated>2023-07-02T07:55:35Z</updated><summary>This website is now hosted on three continents</summary><content type="html">&lt;p&gt;This website is now hosted on three continents.&lt;/p&gt;&#xA;&lt;p&gt;I recently changed the hosting for this site to &lt;a href=&#34;http://fly.io&#34;&gt;fly&lt;/a&gt;, since I was rather intrigued by the idea of being able to run three small &lt;abbr&gt;VMs&lt;/abbr&gt; (&lt;dfn id=&#34;VMs&#34;&gt;Virtual Machines&lt;/dfn&gt;) worldwide for free. I would gladly have paid a small amount for their services. If they didn&amp;rsquo;t have a free allowance for &lt;abbr&gt;VMs&lt;/abbr&gt; then it would only be around $6 a month, so I&amp;rsquo;m not worried about them removing the free allowance.&lt;/p&gt;&#xA;&lt;p&gt;Previously it was running on one &lt;a href=&#34;https://www.hetzner.com&#34;&gt;Hetzner&lt;/a&gt; &lt;abbr title=&#34;Virtual Machine&#34;&gt;VM&lt;/abbr&gt; in Nuremberg, Germany that I set up and maintained myself. The maintenance wasn&amp;rsquo;t a problem for me, but rather the idea of slow loading times for anyone reading this outside of Europe.&lt;/p&gt;&#xA;&lt;p&gt;American visitors should notice a definite speedup now, as there&amp;rsquo;s a server on the west coast and for the few visitors in the Asia-Pacific region, there&amp;rsquo;s also a server in Australia. I kept track of the response time before and after the change using the &lt;a href=&#34;https://onlineornot.com/&#34;&gt;Online or not&lt;/a&gt; &lt;a href=&#34;https://onlineornot.com/do-i-need-a-cdn&#34;&gt;Do I need a CDN?&lt;/a&gt; tool, which you can see in the table below (measured in &lt;abbr title=&#34;milliseconds&#34;&gt;ms&lt;/abbr&gt;)&lt;/p&gt;&#xA;&lt;table&gt;&#xA;&lt;thead&gt;&#xA;&lt;tr&gt;&#xA;&lt;th&gt;Region&lt;/th&gt;&#xA;&lt;th&gt;Before&lt;/th&gt;&#xA;&lt;th&gt;After&lt;/th&gt;&#xA;&lt;/tr&gt;&#xA;&lt;/thead&gt;&#xA;&lt;tbody&gt;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;Europe (Frankfurt)&lt;/td&gt;&#xA;&lt;td&gt;62&lt;/td&gt;&#xA;&lt;td&gt;32&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;US East (N. Virginia)&lt;/td&gt;&#xA;&lt;td&gt;348&lt;/td&gt;&#xA;&lt;td&gt;185&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;US West (N. California)&lt;/td&gt;&#xA;&lt;td&gt;503&lt;/td&gt;&#xA;&lt;td&gt;61&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;Asia Pacific (Tokyo)&lt;/td&gt;&#xA;&lt;td&gt;732&lt;/td&gt;&#xA;&lt;td&gt;251&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;Asia Pacific (Sydney)&lt;/td&gt;&#xA;&lt;td&gt;1114&lt;/td&gt;&#xA;&lt;td&gt;76&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;p&gt;I do find it rather amusing that I spend more time tinkering with the site than actually posting anything, but, for once, tinkering has actually led to me posting something (this post). I would like to think that this might encourage me to post more in the future, but only time will tell.&lt;/p&gt;&#xA;</content><author><name>Alan Pearce</name></author></entry><entry><title>Postfix on a NixOS null client with external catch-all</title><link rel="alternate" type="text/html" href="https://alanpearce.eu/post/postfix-as-null-client-with-external-catchall/"></link><id>tag:alanpearce.eu,2014-06-07:postfix-as-null-client-with-external-catchall</id><updated>2020-09-11T16:49:00Z</updated><content type="html">&lt;p&gt;I wanted to set up a server so that any local email (e.g. generated by cron jobs/systemd timers) would be forwarded to an external address, regardless of the user.  I also wanted the from address to keep the system hostname whilst not allowing any external use of the mailserver.&lt;/p&gt;&#xA;&lt;p&gt;It took me a while to figure out how to this, so I thought I&amp;rsquo;d share my method.&lt;/p&gt;&#xA;&lt;p&gt;Here&amp;rsquo;s the config that can be used to do this on any NixOS host, after redefining the first two variables.&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-txt,linenos,hl_lines=2-3&#34;&gt;services.postfix = let&#xA;  localUser = &amp;quot;example-user&amp;quot;;&#xA;  forwardingAddress = &amp;quot;user@external.domain&amp;quot;;&#xA;in&#xA;{&#xA;  enable = true;&#xA;  destination = [];&#xA;  domain = config.networking.domain;&#xA;  virtual = &#39;&#39;&#xA;    @${config.networking.hostName}.${config.networking.domain} ${localUser}&#xA;    ${localUser} ${forwardingAddress}&#xA;  &#39;&#39;;&#xA;  config = {&#xA;    inet_interfaces = &amp;quot;loopback-only&amp;quot;;&#xA;  };&#xA;};&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;Emails to any user without a domain part are all sent to the forwarding address with a clear &lt;em&gt;from&lt;/em&gt; address (e.g. &lt;code&gt;System administrator &amp;lt;root@host.example.com&amp;gt;&lt;/code&gt;).&lt;/p&gt;&#xA;&lt;h2 id=&#34;background&#34;&gt;Background&lt;/h2&gt;&#xA;&lt;p&gt;First, the basic setup for a null client can be found in the &lt;a href=&#34;http://www.postfix.org/STANDARD_CONFIGURATION_README.html#null_client&#34;&gt;postfix documentation&lt;/a&gt;. The example config would be translated into NixOS like so:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-txt&#34;&gt;services.postfix = {&#xA;  enable = true;&#xA;  destination = [];&#xA;  domain = config.networking.domain;&#xA;  origin = config.networking.domain;&#xA;  relayHost = config.networking.domain;&#xA;  lookupMX = true;&#xA;  config = {&#xA;    inet_interfaces = &amp;quot;loopback-only&amp;quot;;&#xA;  };&#xA;};&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;However, this rewrites user@hostname.example.com to user@example.com (due to &lt;code&gt;origin&lt;/code&gt; on line 5).  I wanted to be able to see which host a mail concerns.&lt;/p&gt;&#xA;</content><author><name>Alan Pearce</name></author></entry><entry><title>A simple, powerful self-hosted git setup</title><link rel="alternate" type="text/html" href="https://alanpearce.eu/post/self-hosted-git/"></link><id>tag:alanpearce.eu,2014-06-07:self-hosted-git</id><updated>2017-06-04T10:33:02Z</updated><summary>I describe my git server setup (using cgit and gitolite), and what it allows</summary><content type="html">&lt;p&gt;I had been using &lt;a href=&#34;https://gogs.io/&#34; title=&#34;Go Git Service&#34;&gt;gogs&lt;/a&gt; for about a year.  It worked reasonably&#xA;well, as it focuses on being a lightweight self-hosted GitHub&#xA;replacement.  However, that wasn&amp;rsquo;t really what I wanted.  I just&#xA;wanted to host my own projects, I didn&amp;rsquo;t need things like issues, pull&#xA;requests or wikis.&lt;/p&gt;&#xA;&lt;p&gt;I recently switched to &lt;a href=&#34;http://gitolite.com/gitolite/&#34;&gt;gitolite&lt;/a&gt; and &lt;a href=&#34;https://git.zx2c4.com/cgit/&#34;&gt;cgit&lt;/a&gt;, as they were even&#xA;lighter on resources, don&amp;rsquo;t require another login and work without&#xA;an external database.  Gitolite is unusual in its configuration: it&#xA;creates a git repository with its configuration file.  I will describe&#xA;how I use them, rather than how to set them up, as they both have&#xA;enough documentation on that.&lt;/p&gt;&#xA;&lt;p&gt;My gitolite configuration file looks like this:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;repo gitolite-admin&#xA;    RW+     =   alan&#xA;&#xA;repo dotfiles&#xA;    C   =   alan&#xA;    RW+ =   alan&#xA;    R   =   READERS&#xA;    option hook.post-update   =    github-mirror&#xA;&#xA;repo [a-z].*&#xA;    C   =   alan&#xA;    RW+ =   CREATOR&#xA;    RW  =   WRITERS&#xA;    R   =   READERS&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;The first block just allows me to work with the configuration&#xA;repository, as the initial setup only enables one specific public SSH&#xA;key, whereas I have three keys that I configure gitolite with.&lt;/p&gt;&#xA;&lt;p&gt;The second configures my dotfiles specifically.  Naturally, I should&#xA;be the only person with read/write access.  The &lt;code&gt;R = READERS&lt;/code&gt; line&#xA;allows remote configuration of read permissions via &lt;code&gt;ssh $DOMAIN perms&lt;/code&gt; (explained further below).  The last line runs a mirror script&#xA;(just &lt;code&gt;git push --mirror…&lt;/code&gt;) so that&#xA;my &lt;a href=&#34;https://github.com/alanpearce/dotfiles&#34;&gt;dotfiles repository on GitHub&lt;/a&gt; is updated when I&#xA;push to my private version.&lt;/p&gt;&#xA;&lt;h2 id=&#34;wild-or-magic-repositories&#34;&gt;Wild (or magic) repositories&lt;/h2&gt;&#xA;&lt;p&gt;The third block is where things get interesting.  gitolite has a&#xA;feature called &lt;a href=&#34;http://gitolite.com/gitolite/wild/&#34;&gt;wildrepos&lt;/a&gt;, which allows configuring a set of&#xA;repositories at once, using a regular expression to match the&#xA;repository name.&lt;/p&gt;&#xA;&lt;p&gt;The really nice thing here is that the repository need not exist&#xA;before applying the configuration.  Therefore, the line &lt;code&gt;C = alan&lt;/code&gt;&#xA;means that I can create a remote repository automatically by cloning a&#xA;repository URL that doesn&amp;rsquo;t already exist.&#xA;I can clone and create a new repo simultaneously like so:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;cd ~/projects&#xA;git clone alanpearce.eu:some-new-repository&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;But with &lt;a href=&#34;https://github.com/motemen/ghq&#34;&gt;ghq&lt;/a&gt;, which I &lt;a href=&#34;/post/repository-management-with-ghq/&#34; title=&#34;Repository management with ghq&#34;&gt;blogged about before&lt;/a&gt;, I don&amp;rsquo;t&#xA;have to concern myself with where to put the repository:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;$ ghq get alanpearce.eu:some-new-repository&#xA;     clone ssh://alanpearce.eu/some-new-repository -&amp;gt; /Volumes/Code/projects/alanpearce.eu/some-new-repository&#xA;       git clone ssh://alanpearce.eu/some-new-repository /Volumes/Code/projects/alanpearce.eu/some-new-repository&#xA;Cloning into &#39;/Volumes/Code/projects/alanpearce.eu/some-new-repository&#39;...&#xA;Initialized empty Git repository in /var/lib/gitolite/repositories/some-new-repository.git/&#xA;warning: You appear to have cloned an empty repository.&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;The nice URLs come from this piece of my SSH configuration:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;Host alanpearce.eu&#xA;  HostName git.alanpearce.eu&#xA;  User gitolite&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;h2 id=&#34;configuring-wild-repositories&#34;&gt;Configuring wild repositories&lt;/h2&gt;&#xA;&lt;p&gt;This repository would be private by default, but I can change that by an&#xA;SSH command.  Here&amp;rsquo;s how I would do it:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;ssh alanpearce.eu perms some-new-repository + READERS gitweb&#xA;ssh alanpearce.eu perms some-new-repository + READERS daemon&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;The first command makes it visible in cgit, whilst the second makes it&#xA;clonable via &lt;code&gt;git://&lt;/code&gt; url.  I can make a repository&#xA;publically-clonable, but invisible on cgit by only allowing the &lt;code&gt;daemon&lt;/code&gt;&#xA;user and not &lt;code&gt;gitweb&lt;/code&gt;, if I wanted.&lt;/p&gt;&#xA;&lt;p&gt;I can also add or change the description of a repository shown on cgit like&#xA;so:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;ssh alanpearce.eu desc some-new-repository &#39;A new repository&#39;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;All the remote commands exposed by gitolite are described in the&#xA;&lt;code&gt;help&lt;/code&gt; command e.g. &lt;code&gt;ssh alanpearce.eu help&lt;/code&gt;&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;hello alan, this is gitolite@oak running gitolite3 (unknown) on git 2.12.2&#xA;&#xA;list of remote commands available:&#xA;&#xA;&#x9;D&#xA;&#x9;desc&#xA;&#x9;help&#xA;&#x9;info&#xA;&#x9;motd&#xA;&#x9;perms&#xA;&#x9;writable&#xA;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;&#xA;&lt;p&gt;I much prefer creating repositories in this way.  It&amp;rsquo;s much simpler&#xA;and allows me to get on with working on the repositories rather than&#xA;going through a multi-step process in a web browser.&lt;/p&gt;&#xA;&lt;p&gt;With cgit and gitolite, I have a minimal setup, that does exactly what&#xA;I want, without consuming many system resources with daemons.&lt;/p&gt;&#xA;</content><author><name>Alan Pearce</name></author></entry><entry><title>Repository management with ghq</title><link rel="alternate" type="text/html" href="https://alanpearce.eu/post/repository-management-with-ghq/"></link><id>tag:alanpearce.eu,2014-06-07:repository-management-with-ghq</id><updated>2017-05-06T21:31:51Z</updated><content type="html">&lt;p&gt;I recently encountered &lt;a href=&#34;https://github.com/motemen/ghq&#34;&gt;ghq&lt;/a&gt;, a tool for automatically organising VCS-backed&#xA;projects automatically.  Give it a repository URL, it will clone a project to&#xA;your projects dir (set by &lt;code&gt;$GHQ_ROOT&lt;/code&gt;) like so:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-sh&#34;&gt;$ ghq get https://github.com/motemen/ghq&#xA;# Runs `git clone https://github.com/motemen/ghq ~/.ghq/github.com/motemen/ghq`&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;I don&amp;rsquo;t like the idea of having projects hidden away, so I set&#xA;&lt;code&gt;$GHQ_ROOT&lt;/code&gt; to &lt;code&gt;$HOME/projects&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;p&gt;From there, the &lt;code&gt;list&lt;/code&gt; and &lt;code&gt;look&lt;/code&gt; subcommands allow listing&#xA;repositories and visiting them in the shell (actually a subshell).&lt;/p&gt;&#xA;&lt;p&gt;I wanted a nicer way to visit project directories.  Since I&amp;rsquo;m&#xA;using &lt;a href=&#34;https://github.com/junegunn/fzf&#34;&gt;fzf&lt;/a&gt; as a fuzzy-finder, I thought it would be nice to use it&#xA;for this.  I created a simple function, &lt;code&gt;fp&lt;/code&gt; (find project) to do that:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-sh&#34;&gt;fp () {&#xA;  ghq look $(ghq list | fzf +m)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;I ran into some issues with the subshell of &lt;code&gt;ghq look&lt;/code&gt; and wondered&#xA;whether it might be possible to create a zsh command to remove the&#xA;need for a subshell.&lt;/p&gt;&#xA;&lt;p&gt;I found that &lt;code&gt;fzf&lt;/code&gt; includes a &lt;a href=&#34;https://github.com/junegunn/fzf/blob/337cdbb37c1efc49b09b4cacc6e9ee1369c7d76d/shell/key-bindings.zsh#L40-L54&#34;&gt;cd-widget function&lt;/a&gt; and created&#xA;something similar that uses &lt;code&gt;ghq&lt;/code&gt; instead of &lt;code&gt;find&lt;/code&gt;:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-sh&#34;&gt;cd-project-widget () {&#xA;  local cmd=&amp;quot;ghq list&amp;quot;&#xA;  setopt localoptions pipefail 2&amp;gt; /dev/null&#xA;  local dir=&amp;quot;$(eval &amp;quot;$cmd&amp;quot; | FZF_DEFAULT_OPTS=&amp;quot;--height ${FZF_TMUX_HEIGHT:-40%} --reverse $FZF_DEFAULT_OPTS $FZF_ALT_C_OPTS&amp;quot; fzf +m)&amp;quot;&#xA;  if [[ -z &amp;quot;$dir&amp;quot; ]]; then&#xA;    zle redisplay&#xA;    return 0&#xA;  fi&#xA;  cd $(ghq list --full-path | grep &amp;quot;$dir&amp;quot;)&#xA;  local ret=$?&#xA;  zle reset-prompt&#xA;  typeset -f zle-line-init &amp;gt;/dev/null &amp;amp;&amp;amp; zle zle-line-init&#xA;  return $ret&#xA;}&#xA;zle -N cd-project-widget&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;It should be quite simple to modify it to work with other&#xA;fuzzy-finders.  The basic idea is to show the output of &lt;code&gt;ghq list&lt;/code&gt; for&#xA;selection, and use &lt;code&gt;ghq list --full-path&lt;/code&gt; with the selected candidate&#xA;to print the correct directory for &lt;code&gt;cd&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;p&gt;What&amp;rsquo;s really nice about this, is that I can bind it to a key&#xA;sequence:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-sh&#34;&gt;bindkey &#39;\es&#39; cd-project-widget&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;Now I can press &lt;code&gt;M-s&lt;/code&gt; in a shell, start typing &amp;ldquo;nixfiles&amp;rdquo; and press enter to &lt;code&gt;cd&lt;/code&gt;&#xA;to my &lt;a href=&#34;https://git.alanpearce.eu/dotfiles&#34;&gt;nixfiles&lt;/a&gt; project. Pretty neat!&lt;/p&gt;&#xA;</content><author><name>Alan Pearce</name></author></entry><entry><title>Back again</title><link rel="alternate" type="text/html" href="https://alanpearce.eu/post/back-again/"></link><id>tag:alanpearce.eu,2014-06-07:back-again</id><updated>2017-05-06T14:55:57Z</updated><summary>I&#39;m back</summary><content type="html">&lt;p&gt;I&amp;rsquo;ve not made any posts for quite some time.  My life has changed&#xA;quite a bit, I&amp;rsquo;ve emigrated from the UK and it&amp;rsquo;s only now that I&amp;rsquo;m&#xA;starting to feel more settled.&lt;/p&gt;&#xA;&lt;p&gt;I hope to start posting a bit more often.  Hopefully this post,&#xA;despite being light on content, will help me to get back into the&#xA;sharing mindset.&lt;/p&gt;&#xA;</content><author><name>Alan Pearce</name></author></entry><entry><title>Cedit and Paredit</title><link rel="alternate" type="text/html" href="https://alanpearce.eu/post/cedit-and-paredit/"></link><id>tag:alanpearce.eu,2014-06-07:cedit-and-paredit</id><updated>2014-08-04T07:10:14Z</updated><summary>Cedit and paredit for structural editing</summary><content type="html">&lt;p&gt;I recently discovered &lt;a href=&#34;https://github.com/zk-phi/cedit&#34;&gt;cedit&lt;/a&gt;, which provides some structural&#xA;commands for editing c-like languages.  (See this&#xA;&lt;a href=&#34;http://emacsrocks.com/e14.html&#34;&gt;Emacs Rocks! episode&lt;/a&gt; if you&amp;rsquo;re not familiar with the concept:&#xA;it introduces &lt;a href=&#34;http://www.emacswiki.org/emacs/ParEdit&#34;&gt;paredit&lt;/a&gt;, a structural editing mode for lisps).&lt;/p&gt;&#xA;&lt;p&gt;So, it deals with curly braces and semicolons, keeping things balanced&#xA;and correct as show in its &lt;a href=&#34;https://github.com/zk-phi/cedit#readme&#34;&gt;screencast&lt;/a&gt;. It mentions that it&#xA;integrates with &lt;a href=&#34;http://www.emacswiki.org/emacs/ParEdit&#34;&gt;paredit&lt;/a&gt; rather than duplicating &lt;em&gt;all&lt;/em&gt; its&#xA;functionality.  After setting up cedit, I decided to try enabling&#xA;paredit alongside cedit and disabling autopair.  Once I did,&#xA;however, I noticed an annoying formatting issue: If I were to type&#xA;&lt;code&gt;foo&lt;/code&gt; and then &lt;code&gt;(&lt;/code&gt;, paredit would format this as &lt;code&gt;foo ()&lt;/code&gt;, which makes&#xA;sense, considering that paredit is written for lisps — s-expressions&#xA;are usually separated by spaces — but not so much for c-like languages.&lt;/p&gt;&#xA;&lt;p&gt;I was thinking about disabling paredit and going back to autopair,&#xA;when I decided to look through the configuration variables for&#xA;paredit.  Turns out it provides&#xA;&lt;code&gt;paredit-space-for-delimiter-predicates&lt;/code&gt;, which is a list of functions&#xA;that control whether a space should be inserted.  So, solving the&#xA;formatting issue turned out to be pretty simple:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(defun ap/cedit-space-delimiter-p (endp delimiter)&#xA;&amp;quot;Don&#39;t insert a space before delimiters in c-style modes&amp;quot;&#xA;(not cedit-mode))&#xA;(add-to-list &#39;paredit-space-for-delimiter-predicates #&#39;ap/cedit-space-delimiter-p)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;Hopefully that saves someone some time if they try to use the two&#xA;together.&lt;/p&gt;&#xA;</content><author><name>Alan Pearce</name></author></entry><entry><title>Emacs Package Archive Statistics</title><link rel="alternate" type="text/html" href="https://alanpearce.eu/post/emacs-package-archive-statistics/"></link><id>tag:alanpearce.eu,2014-06-07:emacs-package-archive-statistics</id><updated>2014-07-19T13:19:54Z</updated><summary>Working out which package archives I&#39;m using</summary><content type="html">&lt;p&gt;I use &lt;a href=&#34;https://github.com/cask/cask/&#34;&gt;cask&lt;/a&gt; for managing the dependencies of my Emacs&#xA;configuration.  Whenever I opened my &lt;code&gt;Cask&lt;/code&gt; file, I wondered if I&#xA;really was using all the sources I had defined:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(source gnu)&#xA;(source marmalade)&#xA;(source melpa)&#xA;(source melpa-stable)&#xA;(source org)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;It seemed quite strange that we have so many package repositories in&#xA;the Emacs world and I&amp;rsquo;m not even using all of them.  I find this state&#xA;less than ideal, much as&#xA;&lt;a href=&#34;http://blog.jorgenschaefer.de/2014/06/the-sorry-state-of-emacs-lisp-package.html&#34;&gt;Jorgen Schäfer details&lt;/a&gt;.  My ideal&#xA;package repository would be once that works with VCS releases, mostly&#xA;because it&amp;rsquo;s a much simpler process to work with than having to sign&#xA;up to yet another website just to upload a package, then ensure it&amp;rsquo;s&#xA;kept up-to-date on every release.&lt;/p&gt;&#xA;&lt;p&gt;As such, I prefer the concepts behing &lt;a href=&#34;https://melpa.org/&#34;&gt;MELPA&lt;/a&gt; and &lt;a href=&#34;http://stable.melpa.org/&#34;&gt;MELPA Stable&lt;/a&gt; to&#xA;those of &lt;a href=&#34;http://marmalade-repo.org/&#34;&gt;Marmalade&lt;/a&gt;.  &lt;a href=&#34;http://elpa.gnu.org/packages/&#34;&gt;GNU ELPA&lt;/a&gt; doesn&amp;rsquo;t appear to allow any&#xA;submissions and &lt;a href=&#34;http://orgmode.org/elpa.html&#34;&gt;org&lt;/a&gt; is specific to &lt;a href=&#34;http://orgmode.org/&#34;&gt;org-mode&lt;/a&gt;.  I&amp;rsquo;ve&#xA;also noticed that many packages I find and use are on github and so&#xA;work with the &lt;a href=&#34;https://melpa.org/&#34;&gt;MELPA&lt;/a&gt; system.  However, I don&amp;rsquo;t like &lt;a href=&#34;https://melpa.org/&#34;&gt;MELPA&amp;rsquo;s&lt;/a&gt;&#xA;versioning: it just gets the latest code and puts the build date in&#xA;the version, meaning that packages could break at any time.&lt;/p&gt;&#xA;&lt;p&gt;So, ideally I would use &lt;a href=&#34;http://stable.melpa.org/&#34;&gt;MELPA Stable&lt;/a&gt; as much as possible and reduce my&#xA;usage of &lt;a href=&#34;http://marmalade-repo.org/&#34;&gt;Marmalade&lt;/a&gt; and &lt;a href=&#34;https://melpa.org/&#34;&gt;MELPA&lt;/a&gt;.  &lt;a href=&#34;http://elpa.gnu.org/packages/&#34;&gt;GNU ELPA&lt;/a&gt; doesn&amp;rsquo;t appear to have&#xA;many packages, but I wasn&amp;rsquo;t sure if I was using any.&#xA;I couldn&amp;rsquo;t see the information listed in the &lt;code&gt;*Packages*&lt;/code&gt; buffer, so I&#xA;decided to try to figure out how to generate some usage statistics.&lt;/p&gt;&#xA;&lt;p&gt;I found &lt;a href=&#34;http://stackoverflow.com/questions/13866848/how-to-save-a-list-of-all-the-installed-packages-in-emacs-24&#34;&gt;how to get a list of installed packages&lt;/a&gt;, but that just gives&#xA;a list:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(ace-jump-mode ag auto-compile auto-indent-mode autopair ...)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;I needed to get more information about those packages.  I looked at&#xA;where &lt;code&gt;list-packages&lt;/code&gt; gets that information from.  It seems that&#xA;&lt;code&gt;package-archive-contents&lt;/code&gt; is a list of cons cells:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(org-plus-contrib .&#xA;&#x9;&#x9;&#x9;&#x9;  [(20140714)&#xA;&#x9;&#x9;&#x9;&#x9;  nil &amp;quot;Outline-based notes management and organizer&amp;quot; tar &amp;quot;org&amp;quot;])&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;Then created a function to loop over the contents of&#xA;&lt;code&gt;package-activated-list&lt;/code&gt;, retrieving the corresponding contents of&#xA;&lt;code&gt;package-archive-contents&lt;/code&gt;:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(defun package-list-installed ()&#xA;  (loop for pkg in package-activated-list&#xA;        collect (assq pkg package-archive-contents)))&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;This generates a list of arrays from &lt;code&gt;package-archive-contents&lt;/code&gt;.&#xA;There are some helper functions in package.el such as&#xA;&lt;code&gt;package-desc-kind&lt;/code&gt;.  &lt;code&gt;package-desc-archive&lt;/code&gt; was exactly what I&#xA;needed.  I happened to be using a pretest version of Emacs at the time&#xA;and didn&amp;rsquo;t know that it&amp;rsquo;s not in 24.3, so I just made sure it was defined:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(if (not (fboundp #&#39;package-desc-archive))&#xA;    (defsubst package-desc-archive (desc)&#xA;      (aref desc (1- (length desc)))))&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;Weirdly, some of the arrays (seemingly the ones from the&#xA;&lt;a href=&#34;http://orgmode.org/elpa.html&#34;&gt;org archive&lt;/a&gt;) had a different length, but the repository/archive was&#xA;always the last element, which is why I used &lt;code&gt;(1- (length ))&lt;/code&gt; and not&#xA;a constant, like the other &lt;code&gt;package-desc-*&lt;/code&gt; functions.&lt;/p&gt;&#xA;&lt;p&gt;To generate a list of statistics, I just needed to loop over the&#xA;installed packages from &lt;code&gt;package-list-installed&lt;/code&gt; and update a count&#xA;for each archive:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(defun package-archive-stats ()&#xA;  (let ((archives (makehash))&#xA;        (assoc &#39;()))&#xA;    (dolist (arc package-archives)&#xA;      (puthash (car arc) 0 archives))&#xA;    (maphash (lambda (k v)&#xA;               (setq assoc (cons (cons k v) assoc)))&#xA;             (dolist (pkg (-filter #&#39;identity (package-list-installed)) archives)&#xA;               (let ((pkg-arc (package-desc-archive (cdr pkg))))&#xA;                 (incf (gethash pkg-arc archives)))))&#xA;    assoc))&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;Running this gives a list of cons cells:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;((&amp;quot;gnu&amp;quot; . 0)&#xA; (&amp;quot;org&amp;quot; . 1)&#xA; (&amp;quot;melpa-stable&amp;quot; . 2)&#xA; (&amp;quot;melpa&amp;quot; . 106)&#xA; (&amp;quot;marmalade&amp;quot; . 1))&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;I wrapped it in an interactive function so that I could check the&#xA;numbers quickly:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(defun package-show-archive-stats ()&#xA;  (interactive)&#xA;  (message &amp;quot;%s&amp;quot; (package-archive-stats)))&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;With that, I removed &lt;code&gt;(source gnu)&lt;/code&gt; from my &lt;code&gt;Cask&lt;/code&gt; file.  Now I had&#xA;another question.  What package was installed from &lt;a href=&#34;http://marmalade-repo.org/&#34;&gt;marmalade&lt;/a&gt;?  In&#xA;the lisp fashion, I created yet another function:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(defun package-show-installed-from-archive (archive)&#xA;  (interactive (list (helm-comp-read &amp;quot;Archive: &amp;quot; (mapcar #&#39;car package-archives)&#xA;                                      :must-match t)))&#xA;  (let ((from-arc (mapcar #&#39;car&#xA;                          (--filter (equalp (package-desc-archive (cdr it)) archive)&#xA;                                    (package-list-installed)))))&#xA;    (if (called-interactively-p)&#xA;        (message &amp;quot;%s&amp;quot; from-arc)&#xA;      from-arc)))&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;(Non-helm users can replace &lt;code&gt;helm-comp-read&lt;/code&gt; with&#xA;&lt;code&gt;ido-completing-read&lt;/code&gt; or similar)&lt;/p&gt;&#xA;&lt;p&gt;Running this with the argument &lt;code&gt;&amp;quot;marmalade&amp;quot;&lt;/code&gt; gives:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(php-extras)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;I checked on &lt;a href=&#34;http://stable.melpa.org/&#34;&gt;MELPA Stable&lt;/a&gt; and &lt;a href=&#34;https://melpa.org/&#34;&gt;MELPA&lt;/a&gt;, but it&amp;rsquo;s not available&#xA;there.  Given that I use &lt;a href=&#34;https://github.com/arnested/php-extras&#34;&gt;php-extras&lt;/a&gt; quite a bit at work, I can&amp;rsquo;t remove&#xA;&lt;a href=&#34;http://marmalade-repo.org/&#34;&gt;marmalade&lt;/a&gt; just yet.  However, as it&amp;rsquo;s a git repository, it should be&#xA;easy for me to create a recipe for MELPA.  Then I can remove marmalade&#xA;from my &lt;a href=&#34;https://github.com/cask/cask/&#34;&gt;cask&lt;/a&gt; configuration.  Hooray for simplification!&lt;/p&gt;&#xA;&lt;p&gt;Hopefully, packaging in Emacs will become simpler in the future.&#xA;There are some interesting things in 24.4 like pinning packages to a&#xA;repository, which would allow &lt;a href=&#34;http://stable.melpa.org/&#34;&gt;MELPA Stable&lt;/a&gt; to be used even when&#xA;&lt;a href=&#34;https://melpa.org/&#34;&gt;MELPA&lt;/a&gt; defines the same package with a higher &amp;ldquo;version&amp;rdquo;.&lt;/p&gt;&#xA;</content><author><name>Alan Pearce</name></author></entry><entry><title>Opening Projects with Projectile</title><link rel="alternate" type="text/html" href="https://alanpearce.eu/post/opening-projects-with-projectile/"></link><id>tag:alanpearce.eu,2014-06-07:opening-projects-with-projectile</id><updated>2014-07-12T09:12:34Z</updated><content type="html">&lt;p&gt;I use &lt;a href=&#34;https://github.com/bbatsov/projectile&#34;&gt;Projectile&lt;/a&gt; for working with projects in Emacs.  It&amp;rsquo;s really good at finding files in projects, working with source code indexes (I use &lt;a href=&#34;https://www.gnu.org/software/global/&#34;&gt;Global&lt;/a&gt;), and with its &lt;a href=&#34;https://github.com/nex3/perspective-el&#34;&gt;perspective&lt;/a&gt; support, it&amp;rsquo;s also great at separating projects into workspaces.  However, I&amp;rsquo;ve always felt it lacking in actually opening projects.  I tend to work on different projects all the time and &lt;code&gt;projectile-switch-project&lt;/code&gt; only tracks projects once they&amp;rsquo;ve been opened initially (despite the name, it works across Emacs sessions).&lt;/p&gt;&#xA;&lt;p&gt;With this in mind, I decided to try to add support for opening projects under a given subdirectory, e.g. &lt;code&gt;~/projects&lt;/code&gt;, regardless of whether or not I&amp;rsquo;ve visited them before.&lt;/p&gt;&#xA;&lt;p&gt;I saw that projectile uses &lt;a href=&#34;https://github.com/magnars/dash.el&#34;&gt;Dash.el&lt;/a&gt; in some places, and after reading about &lt;a href=&#34;https://en.wikipedia.org/wiki/Anaphoric_macro&#34;&gt;anaphoric macros&lt;/a&gt;, I decided that I&amp;rsquo;d try to use them to aid me.&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(defun ap/subfolder-projects (dir)&#xA;  (--map (file-relative-name it dir)&#xA;         (-filter (lambda (subdir)&#xA;                    (--reduce-from (or acc (funcall it subdir)) nil&#xA;                                   projectile-project-root-files-functions))&#xA;                  (-filter #&#39;file-directory-p (directory-files dir t &amp;quot;\\&amp;lt;&amp;quot;)))))&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;First, this filters the non-special files under &lt;code&gt;dir&lt;/code&gt;, filtering non-directories.  Then it runs the list of &lt;code&gt;projectile-project-root-files-functions&lt;/code&gt; on it to determine if it looks like a projectile project.  To make the list more readable, it makes the filenames relative to the passed-in directory.  It runs like this:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(ap/subfolder-projects &amp;quot;~/projects&amp;quot;) =&amp;gt;&#xA;(&amp;quot;dotfiles&amp;quot; &amp;quot;ggtags&amp;quot; …)&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;So, we&amp;rsquo;ve got ourselves a list, but now we need to be able to open the project that&amp;rsquo;s there, even though the folders are relative.&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(defun ap/open-subfolder-project (from-dir &amp;amp;optional arg)&#xA;  (let ((project-dir (projectile-completing-read &amp;quot;Open project: &amp;quot;&#xA;                                     (ap/subfolder-projects from-dir))))&#xA;    (projectile-switch-project-by-name (expand-file-name project-dir from-dir) arg)))&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;By wrapping the call to &lt;code&gt;ap/subfolder-projects&lt;/code&gt; in another function that takes the same directory argument, we can re-use the project parent directory and expand the selected project name into an absolute path before passing it to &lt;code&gt;projectile-switch-project-by-name&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;p&gt;We get support for multiple completion systems for free, since projectile has a wrapper function that works with the default system, ido, &lt;a href=&#34;https://github.com/d11wtq/grizzl&#34;&gt;grizzl&lt;/a&gt; and recently, &lt;a href=&#34;https://github.com/emacs-helm/helm&#34;&gt;helm&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;p&gt;Then I defined some helper functions to make it easy to open work and home projects.&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(defvar work-project-directory &amp;quot;~/work&amp;quot;)&#xA;(defvar home-project-directory &amp;quot;~/projects&amp;quot;)&#xA;&#xA;(defun ap/open-work-project (&amp;amp;optional arg)&#xA;  (interactive &amp;quot;P&amp;quot;)&#xA;  (ap/open-subfolder-project work-project-directory arg))&#xA;&#xA;(defun ap/open-home-project (&amp;amp;optional arg)&#xA;  (interactive &amp;quot;P&amp;quot;)&#xA;  (ap/open-subfolder-project home-project-directory arg))&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;I could probably simplify this with a macro, but I&amp;rsquo;m not sure that there&amp;rsquo;s much advantage in it.  I only have two project types right now, after all.&lt;/p&gt;&#xA;&lt;p&gt;With this all set up, whenever I want to start working on a project I just type &lt;code&gt;M-x home RET&lt;/code&gt; to call up the list.&lt;/p&gt;&#xA;&lt;p&gt;I also considered trying to add all the projects under a directory to the projectile known project list.  I didn&amp;rsquo;t find it quite as easy to use, but it&amp;rsquo;s available below if anyone would prefer that style.&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-lisp&#34;&gt;(defun ap/-add-known-subfolder-projects (dir)&#xA;  (-map #&#39;projectile-add-known-project (--map (concat (file-name-as-directory dir) it) (ap/subfolder-projects dir))))&#xA;&#xA;(defun ap/add-known-subfolder-projects ()&#xA;  (interactive)&#xA;  (ap/-add-known-subfolder-projects (ido-read-directory-name &amp;quot;Add projects under: &amp;quot;)))&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;</content><author><name>Alan Pearce</name></author></entry><entry><title>Cloning Similar Git Repositories</title><link rel="alternate" type="text/html" href="https://alanpearce.eu/post/git-cloning-similar-repositories/"></link><id>tag:alanpearce.eu,2014-06-07:git-cloning-similar-repositories</id><updated>2014-06-22T08:35:24Z</updated><summary>Speed up cloning of similar git repositories</summary><content type="html">&lt;p&gt;With multiple similar git repositories, for example where a base repository contains a framework or base system installation and other repositories are created from that repository, it&amp;rsquo;s possible to save some time when cloning down another repository by using the &lt;code&gt;reference&lt;/code&gt; option to &lt;a href=&#34;https://www.kernel.org/pub/software/scm/git/docs/git-clone.html&#34;&gt;git-clone&lt;/a&gt;:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;git clone git@github.com/my/repo --reference another-repo&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;(Where &lt;code&gt;another-repo&lt;/code&gt; points to a local version of a repository.)&lt;/p&gt;&#xA;&lt;p&gt;The reference here doesn&amp;rsquo;t have to be the base repository itself, it could just be another variant of it.  The speedup can be quite dramatic if the repositories have megabytes of shared history, from minutes to seconds.&lt;/p&gt;&#xA;&lt;p&gt;On a related note, I&amp;rsquo;m surprised that &lt;a href=&#34;https://github.com&#34;&gt;GitHub&lt;/a&gt; doesn&amp;rsquo;t allow for multiple renamed forks, which would be very useful in this scenario.  &lt;a href=&#34;https://bitbucket.org/&#34;&gt;BitBucket&lt;/a&gt; does support this, however.  It even has a &amp;lsquo;sync&amp;rsquo; button for pulling updates from the base into the child repositories, which is very useful, especially for those who prefer GUIs over CLIs.&lt;/p&gt;&#xA;</content><author><name>Alan Pearce</name></author></entry><entry><title>A New Site</title><link rel="alternate" type="text/html" href="https://alanpearce.eu/post/a-new-site/"></link><id>tag:alanpearce.eu,2014-06-07:a-new-site</id><updated>2014-06-07T20:16:16Z</updated><summary>I made a website.</summary><content type="html">&lt;p&gt;I finally got around to making a website.  I decided to use &lt;a href=&#34;https://gohugo.io&#34;&gt;Hugo&lt;/a&gt; with a slightly-modified &lt;a href=&#34;https://github.com/spf13/hyde&#34;&gt;Hyde theme&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;Someday I&amp;rsquo;ll make my own theme, probably using &lt;a href=&#34;http://learnboost.github.io/stylus/&#34;&gt;Stylus&lt;/a&gt; for CSS processing. But for now, this will do.  The more important thing is just to create some content.&lt;/p&gt;&#xA;</content><author><name>Alan Pearce</name></author></entry></feed>