<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: José Luis Lafuente</title>
    <description>The latest articles on DEV Community by José Luis Lafuente (@jlesquembre).</description>
    <link>https://dev.to/jlesquembre</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F210025%2F141e3be1-7685-45c5-94b8-1db8f1cd0692.jpg</url>
      <title>DEV Community: José Luis Lafuente</title>
      <link>https://dev.to/jlesquembre</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jlesquembre"/>
    <language>en</language>
    <item>
      <title>Custom Clojure helpers in your REPL</title>
      <dc:creator>José Luis Lafuente</dc:creator>
      <pubDate>Mon, 07 Mar 2022 00:00:00 +0000</pubDate>
      <link>https://dev.to/jlesquembre/custom-clojure-helpers-in-your-repl-1l27</link>
      <guid>https://dev.to/jlesquembre/custom-clojure-helpers-in-your-repl-1l27</guid>
      <description>&lt;h2&gt;
  
  
  The problem #
&lt;/h2&gt;

&lt;p&gt;Over time, I wrote several Clojure helper functions I use while I'm writing new code. I want to load those helpers every time I start a Clojure REPL. How can I make those helpers available in any Clojure project I'm working on? Especially in 3rd party projects I don't control.&lt;/p&gt;

&lt;h2&gt;
  
  
  The solution #
&lt;/h2&gt;

&lt;p&gt;Traditionally, Clojure developers put development utilities in a &lt;code&gt;user.clj&lt;/code&gt; file, since Clojure automatically loads any &lt;code&gt;user.clj&lt;/code&gt; found in the classpath. In recent Clojure versions, Clojure CLI was introduced, and now we can call any Clojure function from the command line. Knowing that, a better alternative is to move all our helpers to their own project, and to create an alias in our &lt;code&gt;~/.config/clojure/deps.edn&lt;/code&gt; for those utilities.&lt;/p&gt;

&lt;p&gt;As an example, let's suppose this is the main file for my helpers project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;ns&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;local-utils&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;defn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;init&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="no"&gt;:keys&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;println&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"Loading helpers..."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;load-file&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can add an alias in our &lt;code&gt;deps.edn&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:aliases&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:user&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:exec-fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;local-utils/init&lt;/span&gt;&lt;span class="w"&gt;
         &lt;/span&gt;&lt;span class="no"&gt;:extra-deps&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;me.lafuente/clj-dev-utils&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:local/root&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"$HOME/projects/clj-dev-utils"&lt;/span&gt;&lt;span class="p"&gt;}}}}}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, in any project, we can do &lt;code&gt;clj -X:foo:bar:user :main "path/to/main.clj"&lt;/code&gt;. In this example, we are just printing a message before loading the main entry point, but we can do whatever we want.&lt;/p&gt;

&lt;p&gt;My personal Clojure helpers are here: &lt;a href="https://github.com/jlesquembre/clj-dev-utils"&gt;https://github.com/jlesquembre/clj-dev-utils&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;My &lt;code&gt;init&lt;/code&gt; function loads some helper utilities, initializes &lt;a href="https://github.com/djblue/portal"&gt;portal&lt;/a&gt;, enables &lt;a href="https://github.com/metosin/malli"&gt;malli&lt;/a&gt; instrumentation (if present in the classpath) and starts a &lt;a href="https://nrepl.org/"&gt;nREPL&lt;/a&gt; server. We can also provide the main function to be loaded.&lt;/p&gt;

&lt;p&gt;A library I'm using for my helpers is &lt;a href="https://github.com/gfredericks/dot-slash-2"&gt;https://github.com/gfredericks/dot-slash-2&lt;/a&gt; With it, I can create aliases under the &lt;code&gt;.&lt;/code&gt; namespace. For example, &lt;code&gt;./sh&lt;/code&gt; points to &lt;code&gt;clojure.java.shell/sh&lt;/code&gt;. The &lt;code&gt;.&lt;/code&gt; namespace is loaded automatically, so I can evaluate &lt;code&gt;(./sh "ls")&lt;/code&gt; in any file without an explicit &lt;code&gt;require&lt;/code&gt;&lt;/p&gt;

</description>
      <category>clojure</category>
    </item>
    <item>
      <title>Custom home-manager installation with NixOS</title>
      <dc:creator>José Luis Lafuente</dc:creator>
      <pubDate>Tue, 21 Jul 2020 00:00:00 +0000</pubDate>
      <link>https://dev.to/jlesquembre/custom-home-manager-installation-with-nixos-32kk</link>
      <guid>https://dev.to/jlesquembre/custom-home-manager-installation-with-nixos-32kk</guid>
      <description>&lt;p&gt;Recently I hear about &lt;a href="https://github.com/ryantm/home-manager-template"&gt;home-manager-template&lt;/a&gt;. The project rationale resonates with me. In fact, I did something similiar on my NixOS &lt;code&gt;configuration.nix&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Apart of trying to make the &lt;a href="https://rycee.gitlab.io/home-manager/"&gt;home-manager&lt;/a&gt; installation more reproducible, my goals are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Install &lt;a href="https://rycee.gitlab.io/home-manager/"&gt;home-manager&lt;/a&gt; from my system &lt;code&gt;configuration.nix&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Use &lt;a href="https://rycee.gitlab.io/home-manager/"&gt;home-manager&lt;/a&gt; from a git checkout. That makes easier for me to test new ideas or patches.&lt;/li&gt;
&lt;li&gt;Don't repeat my self. I don't want to define the same variable at the system level and in &lt;a href="https://rycee.gitlab.io/home-manager/"&gt;home-manager&lt;/a&gt;, e.g.: my username or my hostname.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To accomplish that, I have the following function in my &lt;code&gt;configuration.nix&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight nix"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt;
  &lt;span class="nv"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"john"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nv"&gt;userHome&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"/home/&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;user&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nv"&gt;hostName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"laptop"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nv"&gt;home-manager&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;home-manager-path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;config-path&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt;
    &lt;span class="kr"&gt;assert&lt;/span&gt; &lt;span class="kr"&gt;builtins&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;typeOf&lt;/span&gt; &lt;span class="nv"&gt;home-manager-path&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kr"&gt;assert&lt;/span&gt; &lt;span class="kr"&gt;builtins&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;typeOf&lt;/span&gt; &lt;span class="nv"&gt;config-path&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nv"&gt;pkgs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;callPackage&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sx"&gt;/.&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nv"&gt;home-manager-path&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;"/home-manager"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;home-manager-path&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;overrideAttrs&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;old&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nv"&gt;nativeBuildInputs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;pkgs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;makeWrapper&lt;/span&gt; &lt;span class="p"&gt;];&lt;/span&gt;
      &lt;span class="nv"&gt;buildCommand&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
        &lt;span class="kd"&gt;let&lt;/span&gt;
          &lt;span class="nv"&gt;home-mananger-bootstrap&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;pkgs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;writeTextFile&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nv"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"home-manager-bootstrap.nix"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="nv"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;''&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;              { config, pkgs, ... }:&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;              {&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;                # Home Manager needs a bit of information about you and the&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;                # paths it should manage.&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;                home.username = "&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;user&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;";&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;                home.homeDirectory = "&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;userHome&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;";&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;                home.sessionVariables.HOSTNAME = "&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;hostName&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;";&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;                imports = [ &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;config-path&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; ];&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;              }&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;            ''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          &lt;span class="p"&gt;};&lt;/span&gt; &lt;span class="kn"&gt;in&lt;/span&gt;
        &lt;span class="s2"&gt;''&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;          &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;old&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;buildCommand&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;          wrapProgram $out/bin/home-manager --set HOME_MANAGER_CONFIG "&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;home-mananger-bootstrap&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;        ''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="kn"&gt;in&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nv"&gt;users&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;users&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;user&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;home&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;userHome&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;packages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;home-manager&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;home-manager-path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;userHome&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/home-manager"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nv"&gt;config-path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;builtins&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kr"&gt;toString&lt;/span&gt; &lt;span class="sx"&gt;../home-manager&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;"/&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;hostName&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.nix"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Let's break that code to understand what is happening.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight nix"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt;
  &lt;span class="nv"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"john"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nv"&gt;userHome&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"/home/&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;user&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nv"&gt;hostName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"laptop"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;First I define some variables I'll use later. It is possible to define a function where you pass them as arguments, but for now I'm just using a let block.&lt;/p&gt;






&lt;div class="highlight"&gt;&lt;pre class="highlight nix"&gt;&lt;code&gt;  &lt;span class="nv"&gt;home-manager&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;home-manager-path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;config-path&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt;
    &lt;span class="kr"&gt;assert&lt;/span&gt; &lt;span class="kr"&gt;builtins&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;typeOf&lt;/span&gt; &lt;span class="nv"&gt;home-manager-path&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kr"&gt;assert&lt;/span&gt; &lt;span class="kr"&gt;builtins&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;typeOf&lt;/span&gt; &lt;span class="nv"&gt;config-path&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now I define a function responsible for installing &lt;a href="https://rycee.gitlab.io/home-manager/"&gt;home-manager&lt;/a&gt; . It takes 2 arguments, &lt;code&gt;home-manager-path&lt;/code&gt; (path to my local &lt;a href="https://rycee.gitlab.io/home-manager/"&gt;home-manager&lt;/a&gt; git checkout) and &lt;code&gt;config-path&lt;/code&gt; (path to my main &lt;a href="https://rycee.gitlab.io/home-manager/"&gt;home-manager&lt;/a&gt; configuration file, usually called &lt;code&gt;home.nix&lt;/code&gt;). I'm also type-checking the arguments.&lt;/p&gt;






&lt;div class="highlight"&gt;&lt;pre class="highlight nix"&gt;&lt;code&gt;    &lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nv"&gt;pkgs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;callPackage&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sx"&gt;/.&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nv"&gt;home-manager-path&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;"/home-manager"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;home-manager-path&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;overrideAttrs&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;old&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;I'm calling the derivation provided by &lt;a href="https://rycee.gitlab.io/home-manager/"&gt;home-manager&lt;/a&gt;, it is defined here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/rycee/home-manager/blob/master/home-manager/default.nix"&gt;https://github.com/rycee/home-manager/blob/master/home-manager/default.nix&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Notice that it takes one argument, &lt;code&gt;path&lt;/code&gt;, the path to my local &lt;a href="https://rycee.gitlab.io/home-manager/"&gt;home-manager&lt;/a&gt; checkout. Since I need further customization, I use the &lt;code&gt;overrideAttrs&lt;/code&gt; function to produce a new derivation based on the original one.&lt;/p&gt;






&lt;div class="highlight"&gt;&lt;pre class="highlight nix"&gt;&lt;code&gt;      &lt;span class="nv"&gt;nativeBuildInputs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;pkgs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;makeWrapper&lt;/span&gt; &lt;span class="p"&gt;];&lt;/span&gt;
      &lt;span class="nv"&gt;buildCommand&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
        &lt;span class="kd"&gt;let&lt;/span&gt;
          &lt;span class="nv"&gt;home-mananger-bootstrap&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;pkgs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;writeTextFile&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
           &lt;span class="c"&gt;# ...&lt;/span&gt;
          &lt;span class="p"&gt;};&lt;/span&gt; &lt;span class="kn"&gt;in&lt;/span&gt;
        &lt;span class="s2"&gt;''&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;          &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;old&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;buildCommand&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;          wrapProgram $out/bin/home-manager --set HOME_MANAGER_CONFIG "&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;home-mananger-bootstrap&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;        ''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;These are the arguments for &lt;code&gt;overrideAttrs&lt;/code&gt;. Since I want to wrap &lt;a href="https://rycee.gitlab.io/home-manager/"&gt;home-manager&lt;/a&gt;, I need &lt;code&gt;pkgs.makeWrapper&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I'm extending the build command. I'm calling the original &lt;a href="https://rycee.gitlab.io/home-manager/"&gt;home-manager&lt;/a&gt; build command, and then wrapping it to set the environment variable &lt;code&gt;HOME_MANAGER_CONFIG&lt;/code&gt; to a file that I'm generating with the &lt;code&gt;writeTextFile&lt;/code&gt; helper function. More details on that later. Notice that &lt;code&gt;HOME_MANAGER_CONFIG&lt;/code&gt; is the entrypoint for &lt;a href="https://rycee.gitlab.io/home-manager/"&gt;home-manager&lt;/a&gt;, usually that file is &lt;code&gt;home.nix&lt;/code&gt;.&lt;/p&gt;






&lt;div class="highlight"&gt;&lt;pre class="highlight nix"&gt;&lt;code&gt;          &lt;span class="nv"&gt;home-mananger-bootstrap&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;pkgs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;writeTextFile&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nv"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"home-manager-bootstrap.nix"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="nv"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;''&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;              { config, pkgs, ... }:&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;              {&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;                # Home Manager needs a bit of information about you and the&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;                # paths it should manage.&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;                home.username = "&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;user&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;";&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;                home.homeDirectory = "&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;userHome&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;";&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;                home.sessionVariables.HOSTNAME = "&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;hostName&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;";&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;                imports = [ &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;config-path&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; ];&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;              }&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;            ''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This is how I'm generating the main the entrypoint file for &lt;a href="https://rycee.gitlab.io/home-manager/"&gt;home-manager&lt;/a&gt;. It's a &lt;code&gt;.nix&lt;/code&gt; file itself, which is added to the nix store. When I generate my NixOS configuration, with &lt;code&gt;nixos-rebuild build&lt;/code&gt;, I know the value for some of the variables needed by &lt;a href="https://rycee.gitlab.io/home-manager/"&gt;home-manager&lt;/a&gt;, like my username or the hostname. I'm taking advange of that to generate a minimal &lt;code&gt;home.nix&lt;/code&gt; file, where the values for that variables are injected, and then I'm importing my real &lt;a href="https://rycee.gitlab.io/home-manager/"&gt;home-manager&lt;/a&gt; configuration (defined by the &lt;code&gt;config-path&lt;/code&gt; variable)&lt;/p&gt;






&lt;div class="highlight"&gt;&lt;pre class="highlight nix"&gt;&lt;code&gt;&lt;span class="kn"&gt;in&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nv"&gt;users&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;users&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;user&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;home&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;userHome&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;packages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;home-manager&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;home-manager-path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;userHome&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/home-manager"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nv"&gt;config-path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;builtins&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kr"&gt;toString&lt;/span&gt; &lt;span class="sx"&gt;../home-manager&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;"/&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;hostName&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.nix"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The last step, this is how I install &lt;a href="https://rycee.gitlab.io/home-manager/"&gt;home-manager&lt;/a&gt; from my NixOS &lt;code&gt;configuration.nix&lt;/code&gt;. I'm just adding the package returned by my &lt;code&gt;home-manager&lt;/code&gt; function. The 2 arguments to the functions are the path to my local &lt;a href="https://rycee.gitlab.io/home-manager/"&gt;home-manager&lt;/a&gt; checkout and the path to my &lt;code&gt;home.nix&lt;/code&gt; file.&lt;/p&gt;

</description>
      <category>homemanager</category>
      <category>nixos</category>
    </item>
    <item>
      <title>Running a local dns and web server</title>
      <dc:creator>José Luis Lafuente</dc:creator>
      <pubDate>Wed, 24 Jun 2020 00:00:00 +0000</pubDate>
      <link>https://dev.to/jlesquembre/running-a-local-dns-and-web-server-3e4l</link>
      <guid>https://dev.to/jlesquembre/running-a-local-dns-and-web-server-3e4l</guid>
      <description>&lt;p&gt;As a software developer, I run multiple web services to be accessed only from localhost. While it is possible to access them on &lt;code&gt;http://localhost&lt;/code&gt;, I prefer to have more descriptive urls, like &lt;code&gt;http://docs.local&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I'm going to describe my &lt;a href="https://nixos.org/"&gt;NixOS&lt;/a&gt; setup to resolve &lt;code&gt;.local&lt;/code&gt; domains to localhost and access my local web server. I'm using &lt;a href="https://coredns.io/"&gt;CoreDNS&lt;/a&gt; and &lt;a href="https://caddyserver.com/"&gt;Caddy&lt;/a&gt; to accomplish it. Keep in mind that while I'm showing nix configuration snippets, you could extract the configuration files and run a similar setup in any Linux distribution.&lt;/p&gt;

&lt;p&gt;It is interesting to notice that &lt;a href="https://coredns.io/"&gt;CoreDNS&lt;/a&gt; started its life as a fork of &lt;a href="https://caddyserver.com/"&gt;Caddy&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  DNS server #
&lt;/h1&gt;

&lt;p&gt;While I could use &lt;a href="http://www.thekelleys.org.uk/dnsmasq/doc.html"&gt;dnsmasq&lt;/a&gt;, I wanted to try a newer DNS server, &lt;a href="https://coredns.io/"&gt;CoreDNS&lt;/a&gt;. Let's start the service with some custom configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;services.coredns.enable = true;services.coredns.config = '' . { # Cloudflare and Google forward . 1.1.1.1 1.0.0.1 8.8.8.8 8.8.4.4 cache } local { template IN A { answer "{{ .Name }} 0 IN A 127.0.0.1" } } '';
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The first block will forward all the DNS requests to Cloudflare and Google DNS servers, and the results will be cached (1 hour by default)&lt;/p&gt;

&lt;p&gt;The second block returns an A record with value &lt;code&gt;127.0.0.1&lt;/code&gt; for any request for a &lt;code&gt;.local&lt;/code&gt; domain.&lt;/p&gt;

&lt;p&gt;So far, so good, we have a local DNS server up and running. Now we need to configure our network manager to use that DNS server. If you are on &lt;a href="https://nixos.org/"&gt;NixOS&lt;/a&gt;, that's pretty easy:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;networking.networkmanager.insertNameservers = ["127.0.0.1"];
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h1&gt;
  
  
  Web server #
&lt;/h1&gt;

&lt;p&gt;I could use &lt;a href="https://nginx.org/en/docs/"&gt;nginx&lt;/a&gt;, but I decided to use &lt;a href="https://caddyserver.com/"&gt;Caddy&lt;/a&gt; instead because it comes with an HTTP API out of the box. I'm not explaining it in this post, but &lt;a href="https://caddyserver.com/"&gt;Caddy&lt;/a&gt;'s API opens the door to many interesting possibilities.&lt;/p&gt;

&lt;p&gt;Let's take a look our &lt;code&gt;Caddyfile&lt;/code&gt; configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://docs.local { root * /path/to/dir file_server } 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Here we are saying that all requests to &lt;code&gt;http://docs.local&lt;/code&gt; should serve static files located at &lt;code&gt;/path/to/dir&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Until &lt;a href="https://github.com/NixOS/nixpkgs/pull/86686"&gt;#86686&lt;/a&gt; is merged, you need to create your own systemd unit to start &lt;a href="https://caddyserver.com/"&gt;Caddy&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let caddyConfig = pkgs.writeText "Caddyfile" '' http://docs.local { root * /path/to/dir file_server } '';in{ systemd.services.caddy = { description = "Caddy web server"; after = ["network-online.target"]; wants = ["network-online.target"]; wantedBy = ["multi-user.target"]; serviceConfig = { User = "caddy"; Group = "caddy"; ExecStart = '' ${pkgs.caddy2}/bin/caddy run --config ${caddyConfig} --adapter caddyfile ''; ExecReload = '' ${pkgs.caddy2}/bin/caddy reload --config ${caddyConfig} --adapter caddyfile ''; TimeoutStopSec = "5s"; LimitNOFILE = 1048576; LimitNPROC = 512; PrivateTmp = true; ProtectSystem = "full"; AmbientCapabilities = "cap_net_bind_service"; }; }; users.users.caddy = { group = "caddy"; uid = config.ids.uids.caddy; home = caddyDir; createHome = true; extraGroups = ["users"]; }; users.groups.caddy.gid = config.ids.uids.caddy;}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



</description>
      <category>dns</category>
      <category>nix</category>
      <category>webserver</category>
    </item>
    <item>
      <title>GitHub actions with Docker and Nix</title>
      <dc:creator>José Luis Lafuente</dc:creator>
      <pubDate>Thu, 11 Jun 2020 00:00:00 +0000</pubDate>
      <link>https://dev.to/jlesquembre/github-actions-with-docker-and-nix-36jm</link>
      <guid>https://dev.to/jlesquembre/github-actions-with-docker-and-nix-36jm</guid>
      <description>&lt;p&gt;I created my first GitHub action: &lt;a href="https://github.com/jlesquembre/clojars-publish-action"&gt;clojars publish action&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To see an example in action, you can go to &lt;a href="https://github.com/jlesquembre/dummy-clj"&gt;jlesquembre/dummy-clj&lt;/a&gt; and take a look to the actions tab.&lt;/p&gt;

&lt;p&gt;GitHub actions can run in Docker containers, so I created a Docker image. At first, I went to Docker hub and looked for the clojure images, but I realized that I also needed to install maven. There is also a maven image, but since I need maven &lt;strong&gt;and&lt;/strong&gt; clojure on the container, the only option was to create my own image based on the official ones and install the other dependency manually.&lt;/p&gt;

&lt;p&gt;Then, I remembered about an interesting project I hear about, &lt;a href="https://nixery.dev/"&gt;Nixery&lt;/a&gt;. With it, you can create Docker images based on &lt;a href="https://nixos.org/"&gt;NixOS&lt;/a&gt;, and it makes really easy to install dependecies. In my case, I just needed this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FROM nixery.dev/shell/maven/clojure
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Done, you alredy have a container with some basic linux utilities, maven and clojure. If you need to install something else, just add &lt;code&gt;/other-dep&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Since I'm already a &lt;a href="https://nixos.org/"&gt;NixOS&lt;/a&gt; user, it is a really good solution for me. It gives me an easy way to install dependecies, on the linux distribution I know the best.&lt;/p&gt;

</description>
      <category>github</category>
      <category>automation</category>
      <category>docker</category>
      <category>clojure</category>
    </item>
  </channel>
</rss>
