<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>NixOS on paradigmatic.systems</title>
    <link>https://paradigmatic.systems/tags/nixos/</link>
    <description>Recent content in NixOS on paradigmatic.systems</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-us</language>
    <lastBuildDate>Wed, 13 Aug 2025 04:30:00 +0000</lastBuildDate><atom:link href="https://paradigmatic.systems/tags/nixos/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Nix: the Language, the Tool, the Package Repo, the OS</title>
      <link>https://paradigmatic.systems/posts/nix-nixpkgs-nixos/</link>
      <pubDate>Wed, 13 Aug 2025 04:30:00 +0000</pubDate>
      
      <guid>https://paradigmatic.systems/posts/nix-nixpkgs-nixos/</guid>
      <description>&lt;p&gt;There&amp;rsquo;s a lot going on in the Nix ecosystem. If you haven&amp;rsquo;t slogged through &lt;a href=&#34;https://edolstra.github.io/pubs/phd-thesis.pdf&#34;&gt;the thesis&lt;/a&gt; then it might seem downright opaque. This is my attempt at an easy explainer for newcomers.&lt;/p&gt;
&lt;h2 id=&#34;the-tool-and-the-language&#34;&gt;The Tool and the Language&lt;/h2&gt;
&lt;p&gt;Let&amp;rsquo;s bootstrap ourselves with some circular facts.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Nix is a &lt;em&gt;tool&lt;/em&gt; for building (or &amp;ldquo;packaging&amp;rdquo;) &lt;em&gt;software components&lt;/em&gt; using instructions expressed in the Nix &lt;em&gt;language&lt;/em&gt;.
The Nix language is even able to &lt;a href=&#34;https://github.com/NixOS/nix/blob/master/flake.nix&#34;&gt;package&lt;/a&gt; the Nix tool (which is mostly written in C++), thus closing the epistemological loop.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>There&rsquo;s a lot going on in the Nix ecosystem. If you haven&rsquo;t slogged through <a href="https://edolstra.github.io/pubs/phd-thesis.pdf">the thesis</a> then it might seem downright opaque. This is my attempt at an easy explainer for newcomers.</p>
<h2 id="the-tool-and-the-language">The Tool and the Language</h2>
<p>Let&rsquo;s bootstrap ourselves with some circular facts.</p>
<blockquote>
<p>Nix is a <em>tool</em> for building (or &ldquo;packaging&rdquo;) <em>software components</em> using instructions expressed in the Nix <em>language</em>.
The Nix language is even able to <a href="https://github.com/NixOS/nix/blob/master/flake.nix">package</a> the Nix tool (which is mostly written in C++), thus closing the epistemological loop.</p></blockquote>
<p>The language features first-class treatment of filesystem paths and URLs (to source code and tarballs, for example).
Nix <em>expressions</em> are evaluated in a hermetic environment with no path variables and no files. All outside references get copied into content-addressed folders in the <em>store</em>, and marked as build-time <em>dependencies</em> in any <em>derivation</em> that gets defined. Retained <em>runtime</em> dependencies are calculated by scanning the actual binary for store paths.</p>
<h2 id="the-build">The Build</h2>
<p>The component is the result of <em>realizing</em> the derivation. That means grabbing all the store path contents and combining them in the prescribed way. Imagine you have 3 components that are build-time dependencies:</p>
<ol>
<li>A compiler</li>
<li>Source code</li>
<li>A bash script that uses the compiler to build the source</li>
</ol>
<p>The derivation describes where to find these, and the (obvious) way that they fit together. The result is content-addressed with a hash based on all its dependencies, and placed in the store.</p>
<h2 id="nixpkgs">nixpkgs</h2>
<p>It turns out this scheme is highly flexible and repeatable.
<a href="https://github.com/NixOS/nixpkgs">nixpkgs</a> is a repo full of Nix expressions for over 120,000 packages. You can pull any one of them into an ephemeral shell to try it out, or install it system-wide if you&rsquo;re using:</p>
<h2 id="nixos">NixOS</h2>
<p>Finally, notice that &ldquo;<em>software components</em>&rdquo; could have a very broad definition. So broad, in fact, to include an entire OS with all of the installed programs and services. That&rsquo;s what NixOS is: A Linux distro defined entirely in Nix and built around the <code>/nix/store</code> path model instead of the more usual <a href="https://en.wikipedia.org/wiki/Filesystem_Hierarchy_Standard">FHS</a>.  I&rsquo;ve written <a href="/posts/first-principles-infrastructure">a bit</a> about how the Nix <em>module</em> system helps encapsulate complex system recipes into simple one-liners.</p>
<p>All my homies use NixOS. To paraphrase from <a href="https://joshblais.com/blog/nixos-is-the-endgame-of-distrohopping/">NixOS is the endgame of distrohopping </a>:</p>
<h3 id="no-more-configuration-drift---solved-">No more configuration drift - solved ✅</h3>
<h3 id="works-on-my-machine---solved-">“Works on my machine!” - solved ✅</h3>
<h3 id="dependency-hell---solved-">Dependency Hell - solved ✅</h3>
<h3 id="virtual-and-development-environments---solved-">Virtual and development environments - solved ✅</h3>
<h3 id="package-management---solved-">package management - solved ✅</h3>
<h2 id="ready-to-go-deeper">Ready to go deeper?</h2>
<p>To get started I highly recommend working through the <a href="https://nix.dev/tutorials/">tutorials at nix.dev</a>!</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>First Principles Infrastructure: Why NixOS Beats Containers and Clouds in 2025</title>
      <link>https://paradigmatic.systems/posts/first-principles-infrastructure/</link>
      <pubDate>Mon, 11 Aug 2025 14:30:00 +0000</pubDate>
      
      <guid>https://paradigmatic.systems/posts/first-principles-infrastructure/</guid>
      <description>&lt;p&gt;In the marketplace of developer skills, there&amp;rsquo;s a certain category that I&amp;rsquo;m long-term bearish on.  They don&amp;rsquo;t warrant investing free time trying to level up. Devs should limit their exposure to the minimum necessary to do their job. I&amp;rsquo;m talking about tools like Docker, Kubernetes, and the intricate managed hosting platforms of Azure and AWS. These are tools that help manage&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;social problems caused by scaling organizations to thousands of engineers&lt;/li&gt;
&lt;li&gt;existing complexity&lt;/li&gt;
&lt;li&gt;laziness or desire to throw money at a problem rather than solve it&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;While they do solve real technical problems, I&amp;rsquo;ll argue here that there&amp;rsquo;s superior tooling for most use cases outside of big tech and legacy systems.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>In the marketplace of developer skills, there&rsquo;s a certain category that I&rsquo;m long-term bearish on.  They don&rsquo;t warrant investing free time trying to level up. Devs should limit their exposure to the minimum necessary to do their job. I&rsquo;m talking about tools like Docker, Kubernetes, and the intricate managed hosting platforms of Azure and AWS. These are tools that help manage</p>
<ul>
<li>social problems caused by scaling organizations to thousands of engineers</li>
<li>existing complexity</li>
<li>laziness or desire to throw money at a problem rather than solve it</li>
</ul>
<p>While they do solve real technical problems, I&rsquo;ll argue here that there&rsquo;s superior tooling for most use cases outside of big tech and legacy systems.</p>
<h1 id="containerize-or-modularize">Containerize or Modularize?</h1>
<blockquote>
<p>We need deployment consistency and environment isolation, and containers solve those!</p></blockquote>
<p>The 2016 essay <a href="https://catern.com/docker.html">Docker Considered Harmful</a> explains how Linux primitives solve the same problems in a more robust way. One valid criticism of this is that Docker can get a junior developer productive more quickly without needing to learn about arcane system settings.</p>
<p>Fine, so we need an abstraction to work with.</p>
<p>Does the abstraction need to expose us to a bloated ecosystem prone to drift? What if it could evaluate to the precise, minimal, and correct system without introducing overhead? What if it&rsquo;s a <a href="https://xeiaso.net/talks/2024/nix-docker-build/">better Docker image builder than Docker&rsquo;s image builder</a>?</p>
<p>Enter Nix with its <a href="https://nix.dev/tutorials/module-system/index.html">module system</a>. Nix approaches the &ldquo;dependency hell&rdquo; problem from first principles. It requires a radically different mental model, which is itself a social organization problem. This model, by the way, is laid out best in Eelco Dolstra&rsquo;s <a href="https://edolstra.github.io/pubs/phd-thesis.pdf">2006 PHD Thesis (PDF)</a>.</p>
<p>When you think about</p>
<ul>
<li>polyglot system with multiple language ecosystems working together</li>
<li>co-existing packages with conflicting dependencies (i.e dfferent versions of python)</li>
</ul>
<p>do you get a headache thinking about all the setup? Well then you should probably swallow some Nix pills. No other tool can encapsulate cross-ecosystem practices and Linux expertise so cleanly. A simple configuration change like</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-nix" data-lang="nix"><span style="display:flex;"><span>services<span style="color:#f92672">.</span>postgres<span style="color:#f92672">.</span>enable <span style="color:#f92672">=</span> <span style="color:#66d9ef">true</span>;
</span></span></code></pre></div><p>is the tip of a carefully crafted reproducible iceberg. This line of code hides a host of system-level changes including</p>
<ul>
<li>User and groups setup with correct isolation and permissions</li>
<li>Directory structure with ownership and permissions</li>
<li>Initialization, default template databases</li>
<li>SystemD service with correct dependencies, start order, lifecycle and recovery
and much more!</li>
</ul>
<p>It&rsquo;s a massive setup process that would normally be done manually, maybe captured in brittle shell scripts, or containerized. But here it&rsquo;s a one-liner, and it&rsquo;s exposed for use as a declarative model that allows completely deterministic and atomic system upgrades!</p>
<p>So while containers provide language-agnostic deployment, Nix achieves the same universality at the package level while maintaining better reproducibility and lower overhead. You can even spit out a Docker image as an afterthought if that&rsquo;s what you really need.</p>
<h1 id="cluster-or-cluster">Cluster or Cluster*@!#?</h1>
<blockquote>
<p>We need service discovery, load balancing, and observability! Kubernetes provides these with a vast ecosystem of battle-tested tools, and its nice declarative operator pattern for nearly every infrastructure need.</p></blockquote>
<p>The infrastructure problem is solved by creating different problems: cognitive overhead, ecosystem lock-in, long development cycles, and significant cost markup. There are compelling reasons to look for a better alternative.</p>
<p>Well, the largest package repo in the world (Nixpkgs) has nice <a href="https://search.nixos.org/options?channel=25.05&amp;from=0&amp;size=50&amp;sort=relevance&amp;type=packages">modules</a> defined for over 20,000 world-class open-source tools. With a 3-line change to your system configuration, you&rsquo;re now building a robust set of tools:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-nix" data-lang="nix"><span style="display:flex;"><span>services <span style="color:#f92672">=</span> {
</span></span><span style="display:flex;"><span>  nginx<span style="color:#f92672">.</span>enable <span style="color:#f92672">=</span> <span style="color:#66d9ef">true</span>;      <span style="color:#75715e">#Load balancing</span>
</span></span><span style="display:flex;"><span>  consul<span style="color:#f92672">.</span>enable <span style="color:#f92672">=</span> <span style="color:#66d9ef">true</span>;     <span style="color:#75715e">#Service discovery</span>
</span></span><span style="display:flex;"><span>  prometheus<span style="color:#f92672">.</span>enable <span style="color:#f92672">=</span> <span style="color:#66d9ef">true</span>; <span style="color:#75715e">#Observability</span>
</span></span><span style="display:flex;"><span>  <span style="color:#75715e">#You&#39;ll want to configure these, of course.</span>
</span></span></code></pre></div><p>But that&rsquo;s not it. The <a href="https://nix.dev/manual/nix/2.28/command-ref/new-cli/nix3-flake.html#flake-format">Nix flake output schema</a> specifies <code>nixosConfigurations</code> as a key. Note the plural. So you might do something like:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-nix" data-lang="nix"><span style="display:flex;"><span>nixosConfigurations <span style="color:#f92672">=</span> {
</span></span><span style="display:flex;"><span>  web <span style="color:#f92672">=</span> mkNode <span style="color:#e6db74">&#34;web&#34;</span> {
</span></span><span style="display:flex;"><span>    services<span style="color:#f92672">.</span>nginx<span style="color:#f92672">.</span>enable <span style="color:#f92672">=</span> <span style="color:#66d9ef">true</span>;
</span></span><span style="display:flex;"><span>    services<span style="color:#f92672">.</span>nginx<span style="color:#f92672">.</span>virtualHosts<span style="color:#f92672">.</span><span style="color:#e6db74">&#34;web&#34;</span> <span style="color:#f92672">=</span> {
</span></span><span style="display:flex;"><span>      locations<span style="color:#f92672">.</span><span style="color:#e6db74">&#34;/api/&#34;</span> <span style="color:#f92672">=</span> {
</span></span><span style="display:flex;"><span>      proxyPass <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;http://</span><span style="color:#e6db74">${</span>cluster<span style="color:#f92672">.</span>db<span style="color:#f92672">.</span>ip<span style="color:#e6db74">}</span><span style="color:#e6db74">:5000/&#34;</span>;
</span></span><span style="display:flex;"><span>    };
</span></span><span style="display:flex;"><span>    app<span style="color:#f92672">.</span>db_address <span style="color:#f92672">=</span> cluster<span style="color:#f92672">.</span>db<span style="color:#f92672">.</span>ip
</span></span><span style="display:flex;"><span>  };
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  db <span style="color:#f92672">=</span> mkNode <span style="color:#e6db74">&#34;db&#34;</span> {
</span></span><span style="display:flex;"><span>    services<span style="color:#f92672">.</span>postgresql<span style="color:#f92672">.</span>enable <span style="color:#f92672">=</span> <span style="color:#66d9ef">true</span>;
</span></span><span style="display:flex;"><span>    services<span style="color:#f92672">.</span>postgresql<span style="color:#f92672">.</span>enableTCPIP <span style="color:#f92672">=</span> <span style="color:#66d9ef">true</span>;
</span></span><span style="display:flex;"><span>    services<span style="color:#f92672">.</span>postgresql<span style="color:#f92672">.</span>authentication <span style="color:#f92672">=</span> <span style="color:#e6db74">&#39;&#39;
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">      host all all </span><span style="color:#e6db74">${</span>cluster<span style="color:#f92672">.</span>web<span style="color:#f92672">.</span>ip<span style="color:#e6db74">}</span><span style="color:#e6db74">/32 trust
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">      &#39;&#39;</span>;
</span></span><span style="display:flex;"><span>    api<span style="color:#f92672">.</span>enable <span style="color:#f92672">=</span> <span style="color:#66d9ef">true</span>
</span></span><span style="display:flex;"><span>  };
</span></span><span style="display:flex;"><span>};
</span></span></code></pre></div><p>where the 2 nodes configurations make them aware of each other.</p>
<p>The same flake can even include</p>
<ul>
<li>integration tests using the insanely powerful <a href="https://nixcademy.com/posts/nixos-integration-tests/">integration test driver</a></li>
<li>deployment metadata with <a href="/posts/setting-up-deploy-rs">deploy-rs</a> to deploy the whole cluster with 1 command</li>
</ul>
<p>So the question then becomes, do you have a nest of messy legacy code and need to throw money at scaling it up? Or do you have the luxury of using the tools directly and scaling piecewise as needs arise?</p>
<h1 id="summary">Summary</h1>
<p>It&rsquo;s never going to be easy to retrofit legacy enterprise systems. But for designing new systems, the NixOS advantage is massive. Your entire system configuration, from kernel to application dependencies to infrastructure services, is a single, reproducible, version-controlled artifact. It allows for</p>
<ul>
<li>One deployment mechanism</li>
<li>Deterministic deployments</li>
<li>Exact parity between development and production</li>
</ul>
<p>and most importantly, a level of autonomy and sovereignty that you yield when your system is built on unstable abstractions.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Setting up deploy-rs for NixOS</title>
      <link>https://paradigmatic.systems/posts/setting-up-deploy-rs/</link>
      <pubDate>Thu, 30 Jan 2025 14:30:00 +0000</pubDate>
      
      <guid>https://paradigmatic.systems/posts/setting-up-deploy-rs/</guid>
      <description>&lt;p&gt;Our starting point here is &lt;a href=&#34;https://paradigmatic.systems/posts/provisioning-nixos-node-digital-ocean&#34;&gt;a node that is freshly infected with NixOS&lt;/a&gt;. For changing the system, we have 2 options.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;SSH in and edit the configuration files (or copy them over) and then run &lt;code&gt;nixos-rebuild switch&lt;/code&gt; which triggers the node to pull and build all the necessary items.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Check and build the configuration locally, and copy the entire closure across.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;At a glance there might not be an advantage to one or the other. But consider if you&amp;rsquo;re deploying custom content that isn&amp;rsquo;t part of nixOS builtin configuration. To use method (1) you would need to clone all your repos on the server to be able to rebuild. Then every update requires you to ssh in and pull.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Our starting point here is <a href="/posts/provisioning-nixos-node-digital-ocean">a node that is freshly infected with NixOS</a>. For changing the system, we have 2 options.</p>
<ol>
<li>
<p>SSH in and edit the configuration files (or copy them over) and then run <code>nixos-rebuild switch</code> which triggers the node to pull and build all the necessary items.</p>
</li>
<li>
<p>Check and build the configuration locally, and copy the entire closure across.</p>
</li>
</ol>
<p>At a glance there might not be an advantage to one or the other. But consider if you&rsquo;re deploying custom content that isn&rsquo;t part of nixOS builtin configuration. To use method (1) you would need to clone all your repos on the server to be able to rebuild. Then every update requires you to ssh in and pull.</p>
<p>That&rsquo;s why (2) is the much better option. We will use <a href="https://github.com/serokell/deploy-rs">deploy-rs</a> to implement it on DigitalOcean.</p>
<h3 id="1-enable-flakes-on-the-server">1) Enable flakes on the server</h3>
<p>If you followed the previous instructions you&rsquo;ve got a local folder full of configuration pulled from your node. Go ahead and turn that into a git repo before getting too far into this.</p>
<p>Adjust your <code>configuration.nix</code></p>
<pre tabindex="0"><code>{ pkgs, ... }: {
  imports = [
    ./hardware-configuration.nix
    ./networking.nix
  ];

  environment.systemPackages = with pkgs; [ vim ];

  boot.tmp.cleanOnBoot = true;
  zramSwap.enable = true;
  networking.hostName = &#34;your-hostname&#34;;
  networking.domain = &#34;&#34;;
  services.openssh.enable = true;
  users.users.root.openssh.authorizedKeys.keys = [&#39;&#39;your key here&#39;&#39; ];
  system.stateVersion = &#34;25.05&#34;;

  nix.settings.experimental-features = [ &#34;nix-command&#34; &#34;flakes&#34; ];
}
</code></pre><p>The main changes are to add the content of <code>host.nix</code> (personal preference but you can go ahead and delete that), and enable the flakes feature. Push the whole configuration folder back up and do a rebuild:</p>
<pre tabindex="0"><code>rsync -av --delete --exclude=&#39;.git&#39; ./ [node-name]:/etc/nixos/
ssh [node-name] &#34;sudo nixos-rebuild switch --flake /etc/nixos#default&#34;
</code></pre><h3 id="2-wrap-the-original-configuration-in-a-flake">2) Wrap the original configuration in a flake</h3>
<p>Now, working locally again, create a new <code>flake.nix</code>:</p>
<pre tabindex="0"><code>{
  description = &#34;NixOS configuration&#34;;

  inputs = {
    nixpkgs.url = &#34;github:nixos/nixpkgs/nixos-25.05&#34;;
    deploy-rs = {
      url = &#34;github:serokell/deploy-rs&#34;;
      inputs.nixpkgs.follows = &#34;nixpkgs&#34;;
    };
  };

  outputs = { self, nixpkgs, deploy-rs }: let
    system = &#34;x86_64-linux&#34;;
  in {
    nixosConfigurations.default = nixpkgs.lib.nixosSystem {
      inherit system;
      modules = [
        ./configuration.nix
      ];
    };

    deploy.nodes.default = {
      hostname = &#34;[node-name]&#34;;
      profiles.system = {
        sshUser = &#34;root&#34;;
        path = deploy-rs.lib.${system}.activate.nixos self.nixosConfigurations.default;
        user = &#34;root&#34;;
      };
    };
    checks = builtins.mapAttrs (system: deployLib: deployLib.deployChecks self.deploy) deploy-rs.lib;
  };
}
</code></pre><p>This flake:</p>
<ol>
<li>wraps the original system, importing it to <code>nixosConfigurations.default</code>.</li>
<li>describes the deployment target in <code>deploy.nodes.default</code>.</li>
</ol>
<h3 id="3-deploy-it">3) Deploy it</h3>
<p>You can run <code>deploy-rs</code> straight from github:</p>
<p><code>nix run github:serokell/deploy-rs .#default</code></p>
<p>or hit a <code>nix profile install github:serokell/deploy-rs</code> so that you can just use the <code>deploy</code> command.</p>
<p>This should succeed and leave your server right where you started (since the actual configuration is unchanged), but now you have a nice flake to work with locally.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Provisioning a NixOS node in DigitalOcean</title>
      <link>https://paradigmatic.systems/posts/provisioning-nixos-node-digital-ocean/</link>
      <pubDate>Tue, 28 Jan 2025 14:30:00 +0000</pubDate>
      
      <guid>https://paradigmatic.systems/posts/provisioning-nixos-node-digital-ocean/</guid>
      <description>&lt;p&gt;Here&amp;rsquo;s an easy way to get a NixOS node spun up using &lt;a href=&#34;https://github.com/elitak/nixos-infect&#34;&gt;nixos-infect&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;1-set-up-a-new-droplet&#34;&gt;1) Set up a new droplet&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Choose Ubuntu 22.04&lt;/li&gt;
&lt;li&gt;Add SSH keys for something you have a local IdentityFile for.&lt;/li&gt;
&lt;li&gt;Under &amp;ldquo;Advanced Options&amp;rdquo; -&amp;gt; &amp;ldquo;Add initialization scripts&amp;rdquo; paste&lt;/li&gt;
&lt;/ul&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;#cloud-config
write_files:
- path: /etc/nixos/host.nix
  permissions: &amp;#39;0644&amp;#39;
  content: |
    {pkgs, ...}:
    {
      environment.systemPackages = with pkgs; [ vim ];
    }
runcmd:
  - curl https://raw.githubusercontent.com/elitak/nixos-infect/master/nixos-infect | PROVIDER=digitalocean NIXOS_IMPORT=./host.nix NIX_CHANNEL=nixos-25.05 bash 2&amp;gt;&amp;amp;1 | tee /tmp/infect.log
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;2-ssh-in-and-copy-config-down&#34;&gt;2) SSH in and copy config down&lt;/h3&gt;
&lt;p&gt;Add the node&amp;rsquo;s SSH config to ~/.ssh/config&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Here&rsquo;s an easy way to get a NixOS node spun up using <a href="https://github.com/elitak/nixos-infect">nixos-infect</a>.</p>
<h3 id="1-set-up-a-new-droplet">1) Set up a new droplet</h3>
<ul>
<li>Choose Ubuntu 22.04</li>
<li>Add SSH keys for something you have a local IdentityFile for.</li>
<li>Under &ldquo;Advanced Options&rdquo; -&gt; &ldquo;Add initialization scripts&rdquo; paste</li>
</ul>
<pre tabindex="0"><code>#cloud-config
write_files:
- path: /etc/nixos/host.nix
  permissions: &#39;0644&#39;
  content: |
    {pkgs, ...}:
    {
      environment.systemPackages = with pkgs; [ vim ];
    }
runcmd:
  - curl https://raw.githubusercontent.com/elitak/nixos-infect/master/nixos-infect | PROVIDER=digitalocean NIXOS_IMPORT=./host.nix NIX_CHANNEL=nixos-25.05 bash 2&gt;&amp;1 | tee /tmp/infect.log
</code></pre><h3 id="2-ssh-in-and-copy-config-down">2) SSH in and copy config down</h3>
<p>Add the node&rsquo;s SSH config to ~/.ssh/config</p>
<pre tabindex="0"><code>Host [node-name]
        HostName [IP-address]
        User root
        IdentityFile ~/.ssh/[identity]
</code></pre><p>Now you should be able to <code>ssh [node-name]</code> and <code>cat /etc/nixos/configuration.nix</code> to see your new system.</p>
<p>Start a new directory for containing the node&rsquo;s configuration locally. Maybe call it <code>[node-name]-deployment</code>.</p>
<p>On the server, run
<code>scp [node-name]:/etc/nixos/* .</code>.</p>
<p>Now you&rsquo;ve got the remote configuration in hand. If you wanted to alter the node, the naive way to do it is edit the configuration, push it back over, and run <code>sudo nixos-rebuild switch</code>. But there&rsquo;s a better way to approach this that involves building the system locally. We&rsquo;ll continue in <a href="/posts/setting-up-deploy-rs">setting up deploy-rs</a>.</p>
]]></content:encoded>
    </item>
    
  </channel>
</rss>
