<?xml version="1.0" encoding="UTF-8"?><?xml-stylesheet href="/rss/styles.xsl" type="text/xsl"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Yuki&apos;s Notes</title><description>The writings of a computer hobbyist dork</description><link>https://yukiisbo.red/</link><item><title>Writings</title><link>https://yukiisbo.red/notes/writings/</link><guid isPermaLink="true">https://yukiisbo.red/notes/writings/</guid><pubDate>Sat, 06 Mar 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Hello world, I’m back with more text.&lt;/p&gt;
&lt;p&gt;I hope you don’t miss me while I’m gone.&lt;/p&gt;
&lt;p&gt;Though, I really doubt that you even realize I’m here.&lt;/p&gt;
&lt;p&gt;Who knows, really?&lt;/p&gt;
&lt;p&gt;So, anyway, I started this &lt;a href=&quot;https://github.com/writeas/writefreely&quot;&gt;writefreely&lt;/a&gt; instance mainly because I want
an improved blogging/writing experience which integrates with the
Fediverse.&lt;/p&gt;
&lt;p&gt;I’m rather tired of static site generators. They always feel too
static and lack interactivity which made writing not satisfying for me
as I have no idea what people think about my writings.&lt;/p&gt;
&lt;p&gt;I find myself preferring to write more stuff on Mastodon than my blog
mainly because of the interactivity that I get vs my old static blog.&lt;/p&gt;
&lt;p&gt;I hope that you’ve enjoyed my shitty long texts as there would
hopefully be more.&lt;/p&gt;
&lt;p&gt;The static blog will stay just as an archive, maybe.&lt;/p&gt;
&lt;p&gt;So, this is writings, a place where I post long text onto. I hope it
serves you well.&lt;/p&gt;
&lt;p&gt;My style of writing will be very casual with some f-bombs peppered in.
I wouldn’t try to pretend to be serious like some sort of wiki page
since well, I suck at it and it just wouldn’t be me anyway.&lt;/p&gt;
&lt;p&gt;That’s it really, See ya soon.&lt;/p&gt;
&lt;p&gt;I’m always available at &lt;code&gt;@yuki_is_bored@bsd.network&lt;/code&gt;.&lt;/p&gt;</content:encoded></item><item><title>Surviving Docker: Packaging penguins into boxes</title><link>https://yukiisbo.red/notes/surviving-docker/</link><guid isPermaLink="true">https://yukiisbo.red/notes/surviving-docker/</guid><pubDate>Thu, 11 Mar 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Docker is typically known as the tool for managing and running
containers in Linux.&lt;/p&gt;
&lt;p&gt;However, a lot of people seem to have misunderstood what it is used for
and why it has seemingly taken center stage in the Linux world.&lt;/p&gt;
&lt;p&gt;For those coming from the world of BSD, Solaris, or OpenVZ might see the
word ‘container’ and get confused once they try Docker. It looks very
familiar but somewhat foreign at the same time.&lt;/p&gt;
&lt;p&gt;For those who are creating web applications might have issues with the
development to deployment cycle and would like to have a more straight
forward method.&lt;/p&gt;
&lt;p&gt;So, what is Docker exactly, what problem does it solve, and how can it
help you?&lt;/p&gt;
&lt;h1 id=&quot;difficulty-of-delivering-software&quot;&gt;Difficulty of delivering software&lt;/h1&gt;
&lt;p&gt;The problem which Docker solves since the beginning of the project is a
rather tricky one: How to deliver software and have it running on
production?&lt;/p&gt;
&lt;p&gt;The problem might seem easy: you can just compile the software, package
the binary, and just install it on the server.&lt;/p&gt;
&lt;p&gt;Easy, right?&lt;/p&gt;
&lt;p&gt;But in reality, there’s always this lingering problem: How do you make
sure that everything works?&lt;/p&gt;
&lt;p&gt;Here’s a common scenario:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The server runs RHEL.&lt;/li&gt;
&lt;li&gt;RHEL ships version 1.0 of a library.&lt;/li&gt;
&lt;li&gt;Meanwhile Sam who’s using Arch Linux has version 1.5 installed on his
machine.&lt;/li&gt;
&lt;li&gt;Turns out there’s a change between 1.0 and 1.5 that caused a nasty,
yet minute bug.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is the infamous “it works on my machine” issue. Typically, those
kind of bugs are very hard to find as the developer cannot reproduce
them on their machines locally and only see it happening once it is
deployed.&lt;/p&gt;
&lt;p&gt;The typical solution was to use virtual machines. Instead of just
delivering packages or binaries, why not use virtual machines images
like an appliance?&lt;/p&gt;
&lt;p&gt;The virtual machine image will be pre-configured with everything you
need to run the software: the Linux distribution, the libraries and the
software itself.&lt;/p&gt;
&lt;p&gt;The server operator only needs to run the virtual machine on the server
with a couple configurations and the app will simply run.&lt;/p&gt;
&lt;p&gt;And now the developers can test by building the virtual machine image on
their machines and run it.&lt;/p&gt;
&lt;p&gt;Solved, right? Well…&lt;/p&gt;
&lt;p&gt;Janice is using a laptop running Fedora and she can’t run virtual
machines because she doesn’t have a lot of RAM, and the server operator
found out that the staging server is incapable of running virtual
machines for the same reason.&lt;/p&gt;
&lt;p&gt;Damn, well, we can always just ask Sam to do final tests on his machine
locally but that’s looking bad on the
&lt;a href=&quot;https://en.wikipedia.org/wiki/Bus_factor&quot;&gt;bus factor&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;However, all developers should be able to test their changes locally on
their machines to determine if everything is running correctly.&lt;/p&gt;
&lt;h2 id=&quot;containers-as-a-medium-to-deliver-items&quot;&gt;Containers as a medium to deliver items&lt;/h2&gt;
&lt;p&gt;Shipping companies solve this issue by using ISO containers. ISO
containers are fixed and standardized units. The standard itself defines
the size of these containers, the maximum weight, and many other
intricate details.&lt;/p&gt;
&lt;p&gt;As the sender, All you need to do is to put your stuff inside of it and
ask the shipping company to deliver it to the receiver.&lt;/p&gt;
&lt;p&gt;For the shipping company, they really don’t have to care about what’s
inside of it. As long as you put it in a standard ISO container, they’ll
be able to ship it on boats, trucks, and cargo planes.&lt;/p&gt;
&lt;p&gt;These boats, trucks and cargo planes are constructed to support these
standard containers and are designed around it. They typically have bays
or racks for it and have a known maximum capacity based on the amount of
containers it can carry.&lt;/p&gt;
&lt;p&gt;Thanks to the ISO container revolution, The entire shipping
infrastructure has improved and been simplified drastically as it only
has to worry about the delivery of the ISO container, not the contents
of it.&lt;/p&gt;
&lt;p&gt;So, why don’t we have something like containers to deliver software?&lt;/p&gt;
&lt;p&gt;The container can simply contain a lightweight Linux installation, the
required libraries along with the software itself.&lt;/p&gt;
&lt;p&gt;And we can easily run it on all the developers machines and servers
without having to worry about which flavour of Linux they’re running.&lt;/p&gt;
&lt;h2 id=&quot;docker-images-as-a-medium-to-deliver-software&quot;&gt;Docker images as a medium to deliver software&lt;/h2&gt;
&lt;p&gt;Docker images contain the software preinstalled with the libraries which
that software requires.&lt;/p&gt;
&lt;p&gt;With the image, you can launch a container which will run the image and
the software within it.&lt;/p&gt;
&lt;p&gt;With Docker installed, You can try it now:&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;console&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; docker run hello-world&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Unable to find image &amp;#39;hello-world:latest&amp;#39; locally&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;latest: Pulling from library/hello-world&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;b8dfde127a29: Pull complete&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Digest: sha256:308866a43596e83578c7dfa15e27a73011bdd402185a84c5cd7f32a88b501a24&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Status: Downloaded newer image for hello-world:latest&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Hello from Docker!&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;This message shows that your installation appears to be working correctly.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;To generate this message, Docker took the following steps:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt; 1. The Docker client contacted the Docker daemon.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt; 2. The Docker daemon pulled the &amp;quot;hello-world&amp;quot; image from the Docker Hub.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;    (amd64)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt; 3. The Docker daemon created a new container from that image which runs the&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;    executable that produces the output you are currently reading.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt; 4. The Docker daemon streamed that output to the Docker client, which sent it&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;    to your terminal.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;To try something more ambitious, you can run an Ubuntu container with:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt; $ docker run -it ubuntu bash&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Share images, automate workflows, and more with a free Docker ID:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt; https://hub.docker.com/&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;For more examples and ideas, visit:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt; https://docs.docker.com/get-started/&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You just launched a Docker container with the &lt;code&gt;hello-world&lt;/code&gt; Docker image
which executes the &lt;code&gt;hello-world&lt;/code&gt; binary.&lt;/p&gt;
&lt;p&gt;If you want to explore what the environment within the container is
like, you can do the following:&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;console&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; docker run -it --rm ubuntu bash&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Unable to find image &amp;#39;ubuntu:latest&amp;#39; locally&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;latest: Pulling from library/ubuntu&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;5d3b2c2d21bb: Pull complete&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;3fc2062ea667: Pull complete&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;75adf526d75b: Pull complete&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Digest: sha256:b4f9e18267eb98998f6130342baacaeb9553f136142d40959a1b46d6401f0f2b&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Status: Downloaded newer image for ubuntu:latest&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;root@c7556396d607:/&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;#&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Notes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;The &lt;code&gt;-i&lt;/code&gt; flag indicates interactive. In simple terms, this will allow
you to send inputs to the running programs.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The &lt;code&gt;-t&lt;/code&gt; flag indicates that a TTY needs to be allocated for the
container.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If you don’t understand what “TTY” means, don’t worry, it is simply
required by a lot of interactive command line applications. In
practice, every time you run a container with interactivity, you
always do &lt;code&gt;-it&lt;/code&gt; together.&lt;/li&gt;
&lt;li&gt;If you really want to know what this “TTY” business is about, see
&lt;a href=&quot;https://en.wikipedia.org/wiki/Virtual_console&quot;&gt;virtual console&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The &lt;code&gt;--rm&lt;/code&gt; flag indicates that the container should be removed once
it’s stopped.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&quot;docker-in-practice&quot;&gt;Docker in practice&lt;/h1&gt;
&lt;p&gt;Before we dig any deeper, let’s make a simple web application and make a
Docker image for it.&lt;/p&gt;
&lt;p&gt;This application will use Python and the Flask micro web framework.&lt;/p&gt;
&lt;p&gt;First, make an empty folder and place &lt;code&gt;app.py&lt;/code&gt; with the following
content:&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; socket&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; flask &lt;/span&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; Flask&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;app &lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; Flask&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt;__name__&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;@&lt;/span&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;app&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;route&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F40064&quot;&gt;def&lt;/span&gt;&lt;span style=&quot;color:#0057D1&quot;&gt; hello&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;():&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#F40064&quot;&gt; f&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;&amp;#39;Hello from &lt;/span&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;socket&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;gethostname&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;!&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Don’t forget the &lt;code&gt;requirements.txt&lt;/code&gt; which lists the required
dependencies. Place this in the same folder as &lt;code&gt;app.py&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;flask==1.1.2&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can try running the application locally with &lt;code&gt;flask run&lt;/code&gt; (assuming
you’ve installed the dependencies on your machine!) but it’s not that
important.&lt;/p&gt;
&lt;p&gt;Docker images are created with the help of Dockerfile. Dockerfiles are
simply recipes to build the Docker image.&lt;/p&gt;
&lt;p&gt;Here’s the Dockerfile for our small project:&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;dockerfile&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;# Use python:3 as the base of our image&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;FROM&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; python:3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;# Expose port 5000, used by flask as a port to listen&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;EXPOSE&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; 5000&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;# Create an APP_DIR environment variable&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;ENV&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; APP_DIR=/opt/app&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;# Set our current working directory to $APP_DIR&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;WORKDIR&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; $APP_DIR&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;# Copy only requirements.txt and install the dependencies&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;# This is a common trick used to save space!&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;COPY&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; requirements.txt $APP_DIR&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;RUN&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; pip install -r requirements.txt&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;# Copy the entire project&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;COPY&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; . $APP_DIR&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;# Execute `flask run --host=0.0.0.0` when you run the container&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;CMD&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;&amp;quot;flask&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;&amp;quot;run&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;&amp;quot;--host=0.0.0.0&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can see that the image is based of an existing Docker image which
has Python installed.&lt;/p&gt;
&lt;p&gt;There are also plenty of other “base” images for various
languages/frameworks, such as &lt;a href=&quot;https://hub.docker.com/_/node&quot;&gt;node&lt;/a&gt;, &lt;a href=&quot;https://hub.docker.com/_/go&quot;&gt;go&lt;/a&gt;, &lt;a href=&quot;https://hub.docker.com/_/rust&quot;&gt;rust&lt;/a&gt; and also for Linux
distributions as well, like &lt;a href=&quot;https://hub.docker.com/_/debian&quot;&gt;debian&lt;/a&gt;, &lt;a href=&quot;https://hub.docker.com/_/ubuntu&quot;&gt;ubuntu&lt;/a&gt;, &lt;a href=&quot;https://hub.docker.com/opensuse/leap&quot;&gt;opensuse/leap&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;After that, we set the &lt;a href=&quot;https://en.wikipedia.org/wiki/Working_directory&quot;&gt;working directory&lt;/a&gt; to &lt;code&gt;/opt/app&lt;/code&gt; where our
application will live, install the dependencies with &lt;code&gt;pip&lt;/code&gt;, copy the
project to the image and set a command to run.&lt;/p&gt;
&lt;p&gt;Before we continue, Here’s the directory tree to ensure that everything
is setup correctly.&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;my_first_docker&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;├── app.py&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;├── Dockerfile&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;└── requirements.txt&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now we can just run &lt;code&gt;docker build&lt;/code&gt; to build the image.&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;console&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; docker build -t my_first_docker &lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt;.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Sending build context to Docker daemon  4.608kB&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Step 1/8 : FROM python:3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;3: Pulling from library/python&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;0ecb575e629c: Already exists&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;7467d1831b69: Already exists&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;feab2c490a3c: Already exists&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;f15a0f46f8c3: Already exists&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;937782447ff6: Already exists&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;e78b7aaaab2c: Already exists&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;b68a1c52a41c: Pull complete&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;ddcd772f47ec: Pull complete&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;aef84dafa567: Pull complete&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Digest: sha256:2c9e0841ab570f51f28891513c4d9b02e13954fa2453df909e0a6bbfbbaaaad3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Status: Downloaded newer image for python:3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt; ---&amp;gt; 254d4a8a8f31&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Step 2/8 : EXPOSE 5000&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt; ---&amp;gt; Running in 8bed4e787093&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Removing intermediate container 8bed4e787093&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt; ---&amp;gt; 160558bc30bc&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Step 3/8 : ENV APP_DIR=/opt/app&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt; ---&amp;gt; Running in fa0520760ded&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Removing intermediate container fa0520760ded&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt; ---&amp;gt; 44e688dfb794&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Step 4/8 : WORKDIR $APP_DIR&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt; ---&amp;gt; Running in 9e9b1f7ffd1a&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Removing intermediate container 9e9b1f7ffd1a&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt; ---&amp;gt; 54658db77948&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Step 5/8 : COPY requirements.txt $APP_DIR&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt; ---&amp;gt; 5a16c297f492&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Step 6/8 : RUN pip install -r requirements.txt&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt; ---&amp;gt; Running in f4820ea014d0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Collecting flask==1.1.2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  Downloading Flask-1.1.2-py2.py3-none-any.whl (94 kB)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Collecting Jinja2&amp;gt;=2.10.1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  Downloading Jinja2-2.11.3-py2.py3-none-any.whl (125 kB)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Collecting Werkzeug&amp;gt;=0.15&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  Downloading Werkzeug-1.0.1-py2.py3-none-any.whl (298 kB)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Collecting itsdangerous&amp;gt;=0.24&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  Downloading itsdangerous-1.1.0-py2.py3-none-any.whl (16 kB)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Collecting click&amp;gt;=5.1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  Downloading click-7.1.2-py2.py3-none-any.whl (82 kB)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Collecting MarkupSafe&amp;gt;=0.23&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  Downloading MarkupSafe-1.1.1-cp39-cp39-manylinux2010_x86_64.whl (32 kB)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Installing collected packages: MarkupSafe, Werkzeug, Jinja2, itsdangerous, click, flask&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Successfully installed Jinja2-2.11.3 MarkupSafe-1.1.1 Werkzeug-1.0.1 click-7.1.2 flask-1.1.2 itsdangerous-1.1.0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Removing intermediate container f4820ea014d0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt; ---&amp;gt; d704783885b1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Step 7/8 : COPY . $APP_DIR&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt; ---&amp;gt; c6a6b299293a&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Step 8/8 : CMD [&amp;quot;flask&amp;quot;, &amp;quot;run&amp;quot;, &amp;quot;--host=0.0.0.0&amp;quot;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt; ---&amp;gt; Running in 299dd52ed30a&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Removing intermediate container 299dd52ed30a&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt; ---&amp;gt; 4fa03655dab1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Successfully built 4fa03655dab1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Successfully tagged my_first_docker:latest&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Notes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;-t&lt;/code&gt; flag signifies the image tag we want, essentially a name for
the image we’re creating.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;.&lt;/code&gt; just says to build the image using the files of the current
working directory.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can see that it runs each step of the Dockerfile inside intermediate
containers. In each step, it performs the action in an intermediate
container which will create an image layer that will be used for the
next step. This cycle continues until the last step, whose layer will be
used as the final image. After the image is built, it will be tagged
when asked.&lt;/p&gt;
&lt;p&gt;You can confirm this by running &lt;code&gt;docker history&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;console&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; docker history my_first_docker&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;IMAGE          CREATED         CREATED BY                           SIZE&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;4fa03655dab1   2 minutes ago   #(nop)  CMD [&amp;quot;flask&amp;quot; &amp;quot;run&amp;quot; &amp;quot;--hos…   0B&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;c6a6b299293a   2 minutes ago   #(nop) COPY dir:81a839249fd7a77dd…   673B&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;d704783885b1   2 minutes ago   pip install -r requirements.txt      9.83MB&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;5a16c297f492   2 minutes ago   #(nop) COPY file:118b963683835467…   13B&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;54658db77948   2 minutes ago   #(nop) WORKDIR /opt/app              0B&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;44e688dfb794   2 minutes ago   #(nop)  ENV APP_DIR=/opt/app         0B&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;160558bc30bc   2 minutes ago   #(nop)  EXPOSE 5000                  0B&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;254d4a8a8f31   2 weeks ago     #(nop)  CMD [&amp;quot;python3&amp;quot;]              0B&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;&amp;lt;missing&amp;gt;      2 weeks ago     set -ex;   wget -O get-pip.py &amp;quot;$P…   8.01MB&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;&amp;lt;missing&amp;gt;      2 weeks ago     #(nop)  ENV PYTHON_GET_PIP_SHA256…   0B&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;&amp;lt;missing&amp;gt;      2 weeks ago     #(nop)  ENV PYTHON_GET_PIP_URL=ht…   0B&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;&amp;lt;missing&amp;gt;      2 weeks ago     #(nop)  ENV PYTHON_PIP_VERSION=21…   0B&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;&amp;lt;missing&amp;gt;      2 weeks ago     cd /usr/local/bin  &amp;amp;&amp;amp; ln -s idle3…   32B&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;&amp;lt;missing&amp;gt;      2 weeks ago     set -ex   &amp;amp;&amp;amp; wget -O python.tar.x…   55.8MB&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;&amp;lt;missing&amp;gt;      2 weeks ago     #(nop)  ENV PYTHON_VERSION=3.9.2     0B&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;&amp;lt;missing&amp;gt;      4 weeks ago     #(nop)  ENV GPG_KEY=E3FF2839C048B…   0B&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;&amp;lt;missing&amp;gt;      4 weeks ago     apt-get update &amp;amp;&amp;amp; apt-get install…   18MB&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;&amp;lt;missing&amp;gt;      4 weeks ago     #(nop)  ENV LANG=C.UTF-8             0B&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;&amp;lt;missing&amp;gt;      4 weeks ago     #(nop)  ENV PATH=/usr/local/bin:/…   0B&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;&amp;lt;missing&amp;gt;      4 weeks ago     set -ex;  apt-get update;  apt-ge…   510MB&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;&amp;lt;missing&amp;gt;      4 weeks ago     apt-get update &amp;amp;&amp;amp; apt-get install…   146MB&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;&amp;lt;missing&amp;gt;      4 weeks ago     set -ex;  if ! command -v gpg &amp;gt; /…   17.5MB&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;&amp;lt;missing&amp;gt;      4 weeks ago     set -eux;  apt-get update;  apt-g…   16.5MB&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;&amp;lt;missing&amp;gt;      4 weeks ago     #(nop)  CMD [&amp;quot;bash&amp;quot;]                 0B&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;&amp;lt;missing&amp;gt;      4 weeks ago     #(nop) ADD file:8f75f11b2bd2d50e5…   114MB&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can see how much space each layer takes by looking at the size. This
is how Docker saves on storage space, if a layer already exists on the
machine, it is simply reused.&lt;/p&gt;
&lt;p&gt;This means if you already pulled &lt;code&gt;python:3&lt;/code&gt; and want to pull another
Docker image which uses &lt;code&gt;python:3&lt;/code&gt; as a base, it will only pull the
extra layers introduced by the new image instead of everything.&lt;/p&gt;
&lt;p&gt;The layers that are indicated as &lt;code&gt;&amp;lt;missing&amp;gt;&lt;/code&gt; are simply the layers from
the &lt;code&gt;python:3&lt;/code&gt; image we used as the base. You can also see how
&lt;code&gt;python:3&lt;/code&gt; is made and notice that it uses &lt;code&gt;ubuntu&lt;/code&gt; as the base.&lt;/p&gt;
&lt;p&gt;Now, let’s run our image as a container:&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;console&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; docker run -p 8000:5000 my_first_docker&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt; * Environment: production&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;   WARNING: This is a development server. Do not use it in a production deployment.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;   Use a production WSGI server instead.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt; * Debug mode: off&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt; * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This will run the &lt;code&gt;my_first_docker&lt;/code&gt; image that you’ve created and
performs port forwarding from port &lt;code&gt;8000&lt;/code&gt; of your machine to port &lt;code&gt;5000&lt;/code&gt;
of the container.&lt;/p&gt;
&lt;p&gt;Now, you should be able to visit the running website by going to
&lt;a href=&quot;http://127.0.0.1:8000&quot;&gt;https://127.0.0.1:8000&lt;/a&gt;
and see &lt;code&gt;Hello from &amp;lt;container hash&amp;gt;!&lt;/code&gt; on your web browser.&lt;/p&gt;
&lt;p&gt;On another terminal, you can see the running Docker containers with
&lt;code&gt;docker ps&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;console&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; docker ps&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;CONTAINER ID   IMAGE             COMMAND                  CREATED         STATUS         PORTS                    NAMES&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;6ded79639a17   my_first_docker   &amp;quot;flask run --host=0.…&amp;quot;   5 seconds ago   Up 4 seconds   0.0.0.0:8000-&amp;gt;5000/tcp   nice_bassi&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;From here, you can see essential info such as container ID, image,
status, ports and names.&lt;/p&gt;
&lt;p&gt;If a container name is not given, Docker will generate a name typically
composed of two random words.&lt;/p&gt;
&lt;p&gt;You can also see that Docker performs port forwarding from 0.0.0.0:8000
to port 5000 of the container.&lt;/p&gt;
&lt;p&gt;What if you want to run something in the running container, like a shell
to debug something. You can use &lt;code&gt;docker exec&lt;/code&gt; to do this.&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;console&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; docker exec -it nice_bassi bash&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;root@6ded79639a17:/opt/app&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; ls&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Dockerfile  __pycache__  app.py  requirements.txt&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;root@6ded79639a17:/opt/app&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;#&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To stop the container, you can use &lt;code&gt;docker stop&lt;/code&gt; or press &lt;code&gt;CTRL-C&lt;/code&gt; on
the terminal with the container running.&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;console&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; docker stop nice_bassi&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;nice_bassi&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you check &lt;code&gt;docker ps&lt;/code&gt; now, you might see that the list is empty,
since &lt;code&gt;docker ps&lt;/code&gt; doesn’t include stopped containers by default. To do
that you need to add the &lt;code&gt;-a&lt;/code&gt; flag which means “all”.&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;console&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; docker ps -a&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;CONTAINER ID   IMAGE             COMMAND                  CREATED         STATUS                     PORTS     NAMES&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;6ded79639a17   my_first_docker   &amp;quot;flask run --host=0.…&amp;quot;   6 minutes ago   Exited (0) 3 seconds ago             nice_bassi&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now you can see that it is stopped. When stopped, the container is still
resident on storage, you can start it again with &lt;code&gt;docker start&lt;/code&gt; and
check with &lt;code&gt;docker ps&lt;/code&gt; to see that the container is running.&lt;/p&gt;
&lt;p&gt;To actually remove the container, you need to use &lt;code&gt;docker rm&lt;/code&gt;. However,
you need to stop it first.&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;console&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; docker rm nice_bassi&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;nice_bassi&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can export your created image to a tar archive with &lt;code&gt;docker save&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;console&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; docker save -o exported_my_first_docker.tar my_first_docker&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; ls -lh exported_my_first_docker.tar&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;-rw------- 1 yuki yuki 877M Mar 11 19:00 exported_my_first_docker.tar&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;However, the common way to deliver Docker images is by using registries.
There are various online registry services such as
&lt;a href=&quot;https://hub.docker.com&quot;&gt;Docker Hub&lt;/a&gt;, &lt;a href=&quot;https://quay.io/&quot;&gt;Quay&lt;/a&gt;, &lt;a href=&quot;https://github.com/features/packages&quot;&gt;GitHub Packages&lt;/a&gt;, and &lt;a href=&quot;https://docs.gitlab.com/ee/user/packages/container_registry/&quot;&gt;GitLab Registry&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This is an example of me pushing the image to my personal Docker
registry.&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;console&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; # First, I need to login to my registry&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; docker login registry.yukiisbo.red&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Username: yuki&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Password:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Login Succeeded&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; # We need to tag the image to match the repository in the registry&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; docker image tag my_first_docker registry.yukiisbo.red/yuki/my_first_docker&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; # Now we can push it to the registry :-)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; docker push registry.yukiisbo.red/yuki/my_first_docker&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Congratulations, you have learned the basics of Docker and most of the
commands that you will use!&lt;/p&gt;
&lt;p&gt;In practice, the entire image creation process is automated using
&lt;a href=&quot;https://en.wikipedia.org/wiki/Continuous_integration&quot;&gt;continuous integration&lt;/a&gt;. See &lt;a href=&quot;https://docs.gitlab.com/ee/ci/docker/using_docker_build.html&quot;&gt;Use Docker to build Docker images&lt;/a&gt; from
GitLab for an example.&lt;/p&gt;
&lt;p&gt;Another helpful command that I’ll introduce to you is &lt;code&gt;docker inspect&lt;/code&gt;.
&lt;code&gt;docker inspect&lt;/code&gt;, as the name implies, is used to inspect stuff in
Docker. This means you can use it to inspect images, containers,
networks and everything else.&lt;/p&gt;
&lt;p&gt;Try running &lt;code&gt;docker inspect my_first_docker&lt;/code&gt; to inspect the image or
inspect the container.&lt;/p&gt;
&lt;h1 id=&quot;stateless-containers&quot;&gt;Stateless Containers&lt;/h1&gt;
&lt;p&gt;Docker containers are stateless. This means that all data
created/modified in the container will be deleted and aren’t permanent.
This is what stateless means and all Docker containers are expected to
be stateless.&lt;/p&gt;
&lt;p&gt;In comparison to stateful where all of the data are expected to be saved
and permanent (persistent). With Docker containers, this is not the
case, new data written or modified will be wiped clean once the
container is stopped/removed, it shouldn’t be expected that the data
will be safe.&lt;/p&gt;
&lt;p&gt;You might ask: “Well, how do I use Docker to run databases?”&lt;/p&gt;
&lt;p&gt;The answer is to this problem by using Docker volumes or bind-mounts.&lt;/p&gt;
&lt;h2 id=&quot;storing-stateful-data-with-bind-mounts&quot;&gt;Storing stateful data with bind-mounts.&lt;/h2&gt;
&lt;p&gt;Bind mounts allows “binding” a part of the host filesystem to the
container’s filesystem. In simple terms, you give the container access
to a folder on the host machine.&lt;/p&gt;
&lt;p&gt;If you’ve used “shared folders” in virtual machines, you can think of
them as effectively the same thing.&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;console&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; mkdir white_hole&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; docker run -it --rm -v ./white_hole:/opt/black_hole ubuntu bash&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You use the &lt;code&gt;-v&lt;/code&gt; flag to perform a bind mount, the example above will
bind the &lt;code&gt;white_hole&lt;/code&gt; folder created on host to &lt;code&gt;/opt/black_hole&lt;/code&gt; in the
container.&lt;/p&gt;
&lt;p&gt;Once you stop the container, you could see that all of your data is safe
as it is stored on the &lt;code&gt;white_hole&lt;/code&gt; folder instead of the container.&lt;/p&gt;
&lt;h2 id=&quot;storing-stateful-data-with-docker-volumes&quot;&gt;Storing stateful data with Docker volumes&lt;/h2&gt;
&lt;p&gt;Docker volumes is similar to bind-mounts but the folder is managed by
Docker.&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;console&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; docker volume create another_white_hole&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; docker run -it --rm -v another_white_hole:/opt/black_hole ubuntu bash&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You could see that it’s very similar to bind mounts but instead of
creating a folder in the filesystem, we use Docker to create the folder.&lt;/p&gt;
&lt;p&gt;In my experience, this is preferred to standard bind mounts because of
it’s lower maintenance overhead, plus everything would be handled
through docker.&lt;/p&gt;
&lt;p&gt;To remove the volume, it’s a simple &lt;code&gt;docker volume rm&lt;/code&gt; command away:&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;console&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; docker volume rm another_white_hole&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;another_white_hole&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you want to manipulate the contents (files, permissions, etc), you
would need to launch a container which mounts the volume.&lt;/p&gt;
&lt;p&gt;The general rule of thumb that I have is to use Docker volumes whenever
possible unless I actually need to use bind mount (reasons such as using
another drive, programs on host which requires manipulating the files,
etc).&lt;/p&gt;
&lt;h1 id=&quot;container-networking&quot;&gt;Container networking&lt;/h1&gt;
&lt;p&gt;We can now run containers and store data persistently but of course, all
modern server software require other software to work (i.e Wordpress
requires a database to work).&lt;/p&gt;
&lt;p&gt;You might think to create a mega container with an
&lt;a href=&quot;https://en.wikipedia.org/wiki/Init&quot;&gt;init&lt;/a&gt; system which launches a web
server, a database server, a SSH server, etc but this is not how you
should use Docker.&lt;/p&gt;
&lt;p&gt;This is the major difference in methodology when comparing against other
container technologies where they’re used to separate different
environments for resource isolation or security.&lt;/p&gt;
&lt;p&gt;In Docker, containers are used as a platform to deliver and run
applications. While it is possible to use Docker containers for resource
isolation and security, it is not the main issue which it aims to solve.&lt;/p&gt;
&lt;p&gt;So, instead of the traditional approach, in Docker, you typically run
one software on one container.&lt;/p&gt;
&lt;p&gt;Let’s run Wordpress as an example.&lt;/p&gt;
&lt;p&gt;To run Wordpress, it requires a MySQL/MariaDB database server and a
place to store data for both the database server and Wordpress itself.&lt;/p&gt;
&lt;p&gt;So, here’s the bill of material:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;A container which runs Wordpress.&lt;/li&gt;
&lt;li&gt;Another container which runs a MySQL/MariaDB database server.&lt;/li&gt;
&lt;li&gt;A volume for the database to store the data.&lt;/li&gt;
&lt;li&gt;Another volume for Wordpress to store media.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Here, we’re missing a way for both containers to communicate with each
other. In order to do just that, we will be creating a Docker network,
specifically bridge network.&lt;/p&gt;
&lt;p&gt;Docker network by default are bridge networks which behaves similar to a
router with your containers connected to it.&lt;/p&gt;
&lt;p&gt;There are other types of Docker networks (typically referred to as
drivers) such as host, overlay, etc but we’ll only focus on bridge in
this article.&lt;/p&gt;
&lt;p&gt;Now, let’s add a network to our bill of materials.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;A container which runs Wordpress.&lt;/li&gt;
&lt;li&gt;Another container which runs a MySQL/MariaDB database server.&lt;/li&gt;
&lt;li&gt;A volume for the database to store the data.&lt;/li&gt;
&lt;li&gt;Another volume for Wordpress to store media.&lt;/li&gt;
&lt;li&gt;A network for the containers to use for communication.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Perfect, let’s create the network and volumes.&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;console&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; docker network create cool_wordpress&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;cool_wordpress&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; docker volume create cool_wordpress_db_data&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;cool_wordpress_db_data&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; docker volume create cool_wordpress_site_data&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;cool_wordpress_site_data&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Awesome, let’s start our database server. We’ll be using MariaDB which
already has an official image on Docker Hub:
&lt;a href=&quot;https://hub.docker.com/_/mariadb&quot;&gt;https://hub.docker.com/_/mariadb&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Looking at the docs in the Docker Hub page, we need to declare settings
via environment variables.&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;console&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; docker run -e MYSQL_DATABASE&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;wordpress&lt;/span&gt;&lt;span style=&quot;color:#0057D1&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;           -e MYSQL_USER=wordpress \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;           -e MYSQL_PASSWORD=wordpress \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;           -e MYSQL_RANDOM_ROOT_PASSWORD=yes \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;           --network cool_wordpress \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;           -v cool_wordpress_db_data:/var/lib/mysql \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;           --name cool_wordpress_db \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;           -d \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;           mariadb&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Notes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;-e&lt;/code&gt; flags are used to define environment variables in the
following form &lt;code&gt;VARIABLE_NAME=VALUE&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;--network&lt;/code&gt; flag is used to define which network the container
should attach to.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;--name&lt;/code&gt; flag is used to name the container instead of using a
randomly generated name.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;-d&lt;/code&gt; flag is used to run the container in the background instead
of “attaching” to it.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can check whether the database is running with &lt;code&gt;docker logs&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;console&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; docker logs cool_wordpress_db&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;2021-03-15 16:23:08 0 [Note] Reading of all Master_info entries succeeded&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;2021-03-15 16:23:08 0 [Note] Added new Master_info &amp;#39;&amp;#39; to hash table&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;2021-03-15 16:23:08 0 [Note] mysqld: ready for connections.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Version: &amp;#39;10.5.9-MariaDB-1:10.5.9+maria~focal&amp;#39;  socket: &amp;#39;/run/mysqld/mysqld.sock&amp;#39;  port: 3306  mariadb.org binary distribution&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can add the &lt;code&gt;-f&lt;/code&gt; flag if you want to “follow” the logs instead of
exiting. If it’s too long, you can also add &lt;code&gt;--tail=10&lt;/code&gt; to only show the
last 10 lines.&lt;/p&gt;
&lt;p&gt;Wordpress also has an official image on Docker Hub:
&lt;a href=&quot;https://hub.docker.com/_/wordpress&quot;&gt;https://hub.docker.com/_/wordpress&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Lets start it up!&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;console&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; docker run -e WORDPRESS_DB_HOST&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;cool_wordpress_db&lt;/span&gt;&lt;span style=&quot;color:#0057D1&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;           -e WORDPRESS_DB_USER=wordpress \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;           -e WORDPRESS_DB_PASSWORD=wordpress \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;           -e WORDPRESS_DB_NAME=wordpress \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;           --network cool_wordpress \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;           -v cool_wordpress_site_data:/var/www/html \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;           -p 8081:80 \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;           --name cool_wordpress_app \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;           -d \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;           wordpress&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Important thing to note is that other containers can be reached via its
name (see &lt;code&gt;WORDPRESS_DB_HOST&lt;/code&gt;) as long they’re within the same network.&lt;/p&gt;
&lt;p&gt;Wordpress should now be running on port 8081: &lt;a href=&quot;http://127.0.0.1:8081&quot;&gt;http://127.0.0.1:8081&lt;/a&gt; and
you should be greeted with Wordpress’ setup wizard.&lt;/p&gt;
&lt;p&gt;Congratulations, you just launched an entire website with a database and
stateful storage with Docker.&lt;/p&gt;
&lt;p&gt;I’ve said that other container technologies use containers to have
separate environments.&lt;/p&gt;
&lt;p&gt;In Docker, we achieve a similar effect with Docker networks to isolate
different resources. With Docker networks, you can group containers
together within the same network so they’re able to reach other
containers as resources (i.e database servers, object storage servers,
etc).&lt;/p&gt;
&lt;p&gt;A common use for this is having different networks for different
environment when developing an application. In this case, you would have
three networks for development, staging, and production.&lt;/p&gt;
&lt;p&gt;Another common use is to isolate different “services” such as your
Wordpress website, your Nextcloud server, and your Minecraft server. You
don’t want your Wordpress website nor Minecraft server to communicate
with the database server of your Nextcloud. So, you isolate them by
having three networks: one for Wordpress, another one for Nextcloud, and
the last one for Minecraft.&lt;/p&gt;
&lt;h2 id=&quot;orchestrating-docker-containers&quot;&gt;Orchestrating Docker containers&lt;/h2&gt;
&lt;p&gt;At this point, you might find the entire &lt;code&gt;docker volume create&lt;/code&gt;,
&lt;code&gt;docker network create&lt;/code&gt; and &lt;code&gt;docker run&lt;/code&gt; process to be very tedious and
annoying. Not to mention you have to delete, stop, restart one-by-one.&lt;/p&gt;
&lt;p&gt;Well, there’s a tool called &lt;a href=&quot;https://docs.docker.com/compose/&quot;&gt;Docker
compose&lt;/a&gt; which aims to make it less annoying by using YAML files to
declare a “stack”.&lt;/p&gt;
&lt;p&gt;You can think a stack as a set of containers, volumes, and networks that
are required to run your application.&lt;/p&gt;
&lt;p&gt;Reusing our Wordpress example, this is what a &lt;code&gt;docker-compose.yml&lt;/code&gt; file
looks like:&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;yaml&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C99&quot;&gt;version&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C99&quot;&gt;services&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C99&quot;&gt;  db&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C99&quot;&gt;    image&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt; mariadb&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C99&quot;&gt;    environment&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;      -&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt; MYSQL_DATABASE=wordpress&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;      -&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt; MYSQL_USER=wordpress&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;      -&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt; MYSQL_PASSWORD=wordpress&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;      -&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt; MYSQL_RANDOM_ROOT_PASSWORD=yes&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C99&quot;&gt;    volumes&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;      -&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt; db_data:/var/lib/mysql&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C99&quot;&gt;  app&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C99&quot;&gt;    image&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt; wordpress&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C99&quot;&gt;    ports&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;      -&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt; 8082:80&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C99&quot;&gt;    environment&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;      -&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt; WORDPRESS_DB_HOST=db&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;      -&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt; WORDPRESS_DB_USER=wordpress&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;      -&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt; WORDPRESS_DB_PASSWORD=wordpress&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;      -&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt; WORDPRESS_DB_NAME=wordpress&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C99&quot;&gt;    volumes&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;      -&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt; site_data:/var/www/html&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C99&quot;&gt;volumes&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C99&quot;&gt;  db_data&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt; {}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C99&quot;&gt;  site_data&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt; {}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Simply place the example above inside a folder named &lt;code&gt;awesome_wordpress&lt;/code&gt;
as a file named &lt;code&gt;docker-compose.yml&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;To launch the site, you run &lt;code&gt;docker-compose up&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;console&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; docker-compose up -d&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Creating network &amp;quot;awesome_wordpress_default&amp;quot; with the default driver&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Creating volume &amp;quot;awesome_wordpress_db_data&amp;quot; with default driver&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Creating volume &amp;quot;awesome_wordpress_site_data&amp;quot; with default driver&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Creating awesome_wordpress_app_1 ... done&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Creating awesome_wordpress_db_1  ... done&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;-d&lt;/code&gt; flag is used here so it doesn’t attach my terminal to the
containers logs. You can view the logs with &lt;code&gt;docker-compose logs&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;You should be able to access the site on port 8082:
&lt;a href=&quot;http://127.0.0.1:8082&quot;&gt;http://127.0.0.1:8082&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To stop the site, you use &lt;code&gt;docker-compose stop&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;console&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; docker-compose stop&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Stopping awesome_wordpress_db_1  ... done&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Stopping awesome_wordpress_app_1 ... done&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To remove the containers and network, you use &lt;code&gt;docker-compose down&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;console&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; docker-compose down&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Removing awesome_wordpress_db_1  ... done&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Removing awesome_wordpress_app_1 ... done&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Removing network awesome_wordpress_default&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you want to remove the volumes as well, simply add the &lt;code&gt;-v&lt;/code&gt; flag.&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;console&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; docker-compose down -v&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Removing network awesome_wordpress_default&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;WARNING: Network awesome_wordpress_default not found.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Removing volume awesome_wordpress_db_data&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Removing volume awesome_wordpress_site_data&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;There you go, much simpler, right?&lt;/p&gt;
&lt;p&gt;There are a couple details that I’d like to point out quickly:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;All resources (containers, volumes, and networks) have
&lt;code&gt;awesome_wordpress&lt;/code&gt; at the beginning of their names.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;This prefix is called a project name and Docker compose use the
folder name where &lt;code&gt;docker-compose.yml&lt;/code&gt; resides by default.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Without an explicit declaration of the network, Docker compose creates
a default network for you and attaches all of the container to the
created network.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Both volume declaration are defined as &lt;code&gt;{}&lt;/code&gt;. This is the defaults
works fine for our needs, we don’t need any specific config.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;You can leave them empty but I prefer having &lt;code&gt;{}&lt;/code&gt; so it’ll be
explicit to people reading the file.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;You don’t need to use the entire container name
(&lt;code&gt;awesome_wordpress_db_1&lt;/code&gt;) when communicating with another container.
You can use the service name instead.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;This is possible as you can define aliases for the container within
the network.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you see the container names, they have &lt;code&gt;_1&lt;/code&gt; at the end (suffix). This
is because Docker compose uses the notion of services instead of
containers directly.&lt;/p&gt;
&lt;p&gt;“Why is this important?”, you might ask.&lt;/p&gt;
&lt;p&gt;This is because you can “scale” services, meaning launching multiple
containers for a service. This is called “horizontal scaling” as you
scale by having multiple instance of a component. Very helpful when you
want to share the load across multiple web servers.&lt;/p&gt;
&lt;p&gt;While I’m not certain how well Wordpress scales horizontally, we can do
it with &lt;code&gt;docker-compose scale&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;console&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; docker-compose scale app&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;4&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This will fail as port 8082 is used by the application, so further
configuration is required (in this case, setting up a reverse proxy/load
balancer) which we will not cover here.&lt;/p&gt;
&lt;p&gt;While we’re here, lets say you want to change the port for Wordpress
from 8082 to 80 (assuming port 80 is free).&lt;/p&gt;
&lt;p&gt;Simply change &lt;code&gt;8082:80&lt;/code&gt; to &lt;code&gt;80:80&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;console&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;version: &amp;#39;3&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;services:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  db:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;    image: mariadb&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;    environment:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;      - MYSQL_DATABASE=wordpress&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;      - MYSQL_USER=wordpress&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;      - MYSQL_PASSWORD=wordpress&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;      - MYSQL_RANDOM_ROOT_PASSWORD=yes&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;    volumes:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;      - db_data:/var/lib/mysql&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  app:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;    image: wordpress&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;    ports:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;      - 80:80&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;    environment:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;      - WORDPRESS_DB_HOST=db&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;      - WORDPRESS_DB_USER=wordpress&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;      - WORDPRESS_DB_PASSWORD=wordpress&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;      - WORDPRESS_DB_NAME=wordpress&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;    volumes:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;      - site_data:/var/www/html&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;volumes:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  db_data: {}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  site_data: {}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Update it with &lt;code&gt;docker-compose up&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;console&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; docker-compose up -d&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Recreating awesome_wordpress_app_1 ... done&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can see that it only updates &lt;code&gt;app&lt;/code&gt; and leave &lt;code&gt;db&lt;/code&gt; alone. Cool,
right?&lt;/p&gt;
&lt;p&gt;Congratulations, you just orchestrated an entire Wordpress website with
the power of Docker compose!&lt;/p&gt;
&lt;p&gt;You have seen two methods to deploy things with Docker: Docker compose
and docker run.&lt;/p&gt;
&lt;p&gt;Personally, I typically define stacks and deploy things using Docker
compose and only use &lt;code&gt;docker run&lt;/code&gt; when I need to make one-off containers
for testing, debugging, etc.&lt;/p&gt;
&lt;p&gt;I like Docker compose more mainly because it’s declarative as I simply
need to define what I want instead of writing long commands. It’s just
much simpler and fits the task of long running services.&lt;/p&gt;
&lt;h1 id=&quot;closing&quot;&gt;Closing&lt;/h1&gt;
&lt;p&gt;This is the end of this article.&lt;/p&gt;
&lt;p&gt;While I could go on about Docker’s internals among other things, I think
it would be better for that to be a separate post or you can simply
explore on your own, besides practice is the best teacher.&lt;/p&gt;
&lt;p&gt;There are a couple of small things which I haven’t covered but I think
it’s better for you to find those things on your own as you need them.&lt;/p&gt;
&lt;p&gt;I recommend checking out
&lt;a href=&quot;https://docs.docker.com/compose/compose-file/compose-file-v3/&quot;&gt;Compose
file version 3 reference&lt;/a&gt; for various other things that you can do with
Docker.&lt;/p&gt;
&lt;h1 id=&quot;remarks&quot;&gt;Remarks&lt;/h1&gt;
&lt;p&gt;This is an addition I made on the 13th of August while writing an
article on my series about Nix. I should’ve done it earlier but only
realised it now.&lt;/p&gt;
&lt;p&gt;I would like to thanks those who has reviewed this article and given
me their input:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Lucy Firman (&lt;a href=&quot;https://github.com/lxcyp&quot;&gt;@lxcyp&lt;/a&gt; on GitHub)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you’re one of those who has reviewed this article and would like to
be credited, please let me know. :)&lt;/p&gt;</content:encoded></item><item><title>Qubi Research Program Postmortem</title><link>https://yukiisbo.red/notes/qubi-research-postmortem/</link><guid isPermaLink="true">https://yukiisbo.red/notes/qubi-research-postmortem/</guid><pubDate>Sat, 26 Jun 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Hello world,&lt;/p&gt;
&lt;p&gt;After a long 8 week hiatus, I’m finally back with a new game on
itch.io.&lt;/p&gt;
&lt;p&gt;It’s called “Qubi Research Program” which is a rather “unique” typing
game. I came up with the idea for it after reading the theme for the
&lt;a href=&quot;https://itch.io/jam/mini-jam-83-dread&quot;&gt;83rd Mini Jam&lt;/a&gt; which was “Dread”.&lt;/p&gt;
&lt;p&gt;With the word “Dread” in mind, I immediately thought about a shitty
office job which one require in order to survive. Wouldn’t it be silly
to have a game which replicate &lt;a href=&quot;https://en.wikipedia.org/wiki/The_Stanley_Parable#Gameplay_and_synopsis&quot;&gt;Stanley’s job&lt;/a&gt; but have the dreadful
feeling of living within a broken system as &lt;a href=&quot;https://en.wikipedia.org/wiki/Papers,_Please&quot;&gt;Papers, Please&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id=&quot;proof-of-concept&quot;&gt;Proof of concept&lt;/h1&gt;
&lt;p&gt;During this time, I was learning &lt;a href=&quot;https://nim-lang.org/&quot;&gt;Nim&lt;/a&gt; and &lt;a href=&quot;https://www.raylib.com/&quot;&gt;Raylib&lt;/a&gt; so I decided to
quickly make a proof-of-concept.&lt;/p&gt;

&lt;video controls&gt;&lt;source src=&quot;/_astro/qubi_poc.cztiCliX.mp4&quot; type=&quot;video/mp4&quot;/&gt;&lt;p&gt;Your browser does not support the video tag.&lt;/p&gt;&lt;/video&gt;
&lt;p&gt;The proof-of-concept is only the typing game part, just to see how it
feels but the idea is there.&lt;/p&gt;
&lt;p&gt;At the end of each work day, the player is awarded with a compensation
based on the amount of words you’ve written. Each typo made are fined.&lt;/p&gt;
&lt;p&gt;The game grows difficult each day as you have to pay various bills and
make sure that your account isn’t surpassing the fixed overdraft
limit.&lt;/p&gt;
&lt;p&gt;My close friends liked the idea and told me that I should make it even
if it couldn’t submit it for the 83rd Mini Jam.&lt;/p&gt;
&lt;p&gt;The game uses the same common English words dictionary as &lt;a href=&quot;https://xkcd.com/1133/&quot;&gt;Up Goer Five&lt;/a&gt;
and &lt;a href=&quot;https://blog.xkcd.com/2015/05/13/new-book-thing-explainer/&quot;&gt;Thing Explainer&lt;/a&gt;. The reason is simply that I want to only use
words which everyone have heard and used before.&lt;/p&gt;
&lt;h1 id=&quot;initial-foothold&quot;&gt;Initial foothold&lt;/h1&gt;
&lt;p&gt;I started writing the game on Friday, 25 June 2021. I decided to do it
on a public repository in my personal GitLab instance because why not.&lt;/p&gt;
&lt;p&gt;There’s not a lot of games written in Nim surprisingly so I think it
could serve as a relatively complete example of a simple game.&lt;/p&gt;
&lt;p&gt;I started by writing a simple Hello World and a Nix shell environment
which have Nim and Emscripten.&lt;/p&gt;
&lt;p&gt;Emscripten / WASM has proven to be quite annoying at times. One of the
annoyances is the cooperative multitasking model which cause the
entire program to freeze if it is shoved to the background. I’m not
sure how to fix this bug and couldn’t really find any good references
on how to fix it.&lt;/p&gt;
&lt;p&gt;However, once I have a working toolchain setup and make it possible to
build within Nix &lt;em&gt;imperatively&lt;/em&gt;, it goes smooth sailing.&lt;/p&gt;
&lt;h1 id=&quot;constructing-the-foundation&quot;&gt;Constructing the Foundation&lt;/h1&gt;
&lt;p&gt;The architecture of the game is very simple. It uses screens which
encapsulates a state along with methods for screen initialisation,
update and deinitialisation. Each screen are simply a subclass of the
Screen abstract class. No fancy ECS required for something simple and
quick.&lt;/p&gt;
&lt;p&gt;While I am not a fan of object-oriented programming, something like
this shows why OOP can be good sometimes especially when you need to
encapsulate both a state and an interface.&lt;/p&gt;
&lt;p&gt;I start to appreciate Nim’s approach in making both functional /
imperative / object-oriented approach work together nicely.&lt;/p&gt;
&lt;p&gt;In particular, I like that &lt;code&gt;f(x)&lt;/code&gt; is the same as &lt;code&gt;x.f&lt;/code&gt;. This is similar to
the pipeline operator which are popular in functional programming
languages. This makes &lt;code&gt;f(g(h(x)))&lt;/code&gt; readable by transforming it to
&lt;code&gt;x.h.g.f&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Of course, there are a lot of things inside Nim which I love: Portable
compiler, Sum types/ADTs, Macros, Syntax clarity, Infix functions,
etc.&lt;/p&gt;
&lt;p&gt;Honestly, I wish more programming languages reflects Haskell’s syntax
clarity. I hate those which have a lot of noise such as Rust. However,
I think I’ll use Nim for things which does not make sense to do in
Haskell.&lt;/p&gt;
&lt;h1 id=&quot;basic-gameplay&quot;&gt;Basic Gameplay&lt;/h1&gt;
&lt;p&gt;Porting the code from the proof-of-concept to the foundation is fairly
simple. Most of it just moving the stateful variables within the
encapsulated state of the GameScreen class.&lt;/p&gt;
&lt;p&gt;Once that’s done, I just started working on the “Day End Screen” and
the “Game Over Screen”. The game progress is saved outside of the
encapsulated state. In other words, they’re just global variables.&lt;/p&gt;
&lt;p&gt;While a lot of people cringe at mutable global variables, it’s fine
for something quick and dirty and who cares, really. I’m not writing
software, I’m writing games.&lt;/p&gt;
&lt;p&gt;After I got the basic gameplay / minimum viable product, I
immediately share it with close friends.&lt;/p&gt;
&lt;h1 id=&quot;balancing&quot;&gt;Balancing&lt;/h1&gt;
&lt;p&gt;Originally, I planned to have a day to be a minute but during initial
playtesting, I deemed it to be too long so I cut it in half. a week
was 5 days but it is also too long, I end up cutting it down to 3 days.&lt;/p&gt;
&lt;p&gt;So in this game, a day is 30 seconds and a week is 3 days. You also
pay rent every week which increases every week too. I would like for
the game to also last a bit long but not too long, unless you really
want to.&lt;/p&gt;
&lt;p&gt;You get 1 point for each word done but you’re fined 2 points for each
error you made. While this seem excessive, this is deliberate to make
it difficult and have that “dreadful” feeling.&lt;/p&gt;
&lt;p&gt;The initial version was fairly difficult even for accurate/fast
typists. No one was able to surpass 15 days / 7 minutes of gameplay.&lt;/p&gt;
&lt;p&gt;To balance, I start by laying down some ground rules. I think it’s
unreasonable to have a speed of 1 word a second. So, I cut it down by
20% in order to have a bit more room for errors. In the real world,
rent is ideally at most 60% of your income. With the daily goal value
in place, I simply make the initial rent to be 60% of the weekly goal.&lt;/p&gt;
&lt;p&gt;In the real world, 10% rent increase is excessive but this is a game
and games need to be short so 10% it is.&lt;/p&gt;
&lt;p&gt;With the balanced changes in place, it is now easy to hit more than 30
days. Nice, now I have more room to make the game more difficult&lt;/p&gt;
&lt;h1 id=&quot;increasing-difficulty&quot;&gt;Increasing Difficulty&lt;/h1&gt;
&lt;p&gt;The first thing I did is to have the duration of each day randomized
to destroy the 30 second rhythm.&lt;/p&gt;
&lt;p&gt;Second, I want to shuffle the characters in a word which reflects
&lt;a href=&quot;https://en.wikipedia.org/wiki/Typoglycemia&quot;&gt;Typoglycemia&lt;/a&gt; / &lt;a href=&quot;https://en.wikipedia.org/wiki/Transposed_letter_effect&quot;&gt;Transposed letter effect&lt;/a&gt;. This is to make it even more
annoying once you have the rhythm and expectation to write English
words.&lt;/p&gt;
&lt;p&gt;Third, like in “Papers, Please”, I want to have “surprise costs”.
Paying for random things such as coffee, parking, and student loans.&lt;/p&gt;
&lt;p&gt;The factor of each “surprise cost” is simply a prime number from 2
to 59. At each the end of the work day, A random value from 2 to 100
is generated and if it’s multiple of a suprise cost’s factor, the
surprise cost is added. I’m too lazy to do something proper and this
will do just fine.&lt;/p&gt;
&lt;h1 id=&quot;end&quot;&gt;End&lt;/h1&gt;

&lt;video controls&gt;&lt;source src=&quot;/_astro/qubi_final.ByCz22sB.mp4&quot; type=&quot;video/mp4&quot;/&gt;&lt;p&gt;Your browser does not support the video tag.&lt;/p&gt;&lt;/video&gt;
&lt;p&gt;I think I’m done with this game. It’s fairly short and simple and it
is more of an excercise for me in learning Nim and Raylib.&lt;/p&gt;
&lt;p&gt;I love both Nim and Raylib and I think I have found a good stack to
write small games with. I hope with all of this that I will start
creating games a bit more frequently. No promises though :-)&lt;/p&gt;
&lt;p&gt;Thanks for reading this rather messy and all-over-the-place of a
postmortem. As of writing, it is 5 AM in the morning and I’ve been
awake since 12 PM. I should go to bed…&lt;/p&gt;
&lt;p&gt;The game is available on &lt;a href=&quot;https://yukiisbored.itch.io/qubi-research&quot;&gt;itch.io&lt;/a&gt; and its source code (ISC) is
available on &lt;a href=&quot;https://github.com/yukiisbored/qubi&quot;&gt;GitHub&lt;/a&gt;.&lt;/p&gt;</content:encoded></item><item><title>Spice up with Nix: The issues with traditional software deployment</title><link>https://yukiisbo.red/notes/spice-up-with-nix-traditional-software-deployment/</link><guid isPermaLink="true">https://yukiisbo.red/notes/spice-up-with-nix-traditional-software-deployment/</guid><description>In this article, we explore the inherent issue with package managers like apt and containers like Snap, Docker, AppImage.</description><pubDate>Sat, 04 Sep 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;In this article, we will explore the issues with traditional methods
of installing software.&lt;/p&gt;
&lt;p&gt;This includes using distribution package managers such as apt, dnf,
pacman and third-party ones like MacPorts and Homebrew.&lt;/p&gt;
&lt;p&gt;In addition, we will take a look at containerized solutions and their
issues.&lt;/p&gt;
&lt;h1 id=&quot;the-problem-with-traditional-software-deployment&quot;&gt;The problem with traditional software deployment&lt;/h1&gt;
&lt;p&gt;In the &lt;a href=&quot;https://edolstra.github.io/pubs/phd-thesis.pdf&quot;&gt;Nix thesis&lt;/a&gt;, &lt;a href=&quot;https://edolstra.github.io/&quot;&gt;Eelco Dostra&lt;/a&gt; potrayed how ancient the current
methods of software deployment is by comparing it to how software
developers used to manage and allocate memory in Assembly.&lt;/p&gt;
&lt;p&gt;You don’t need to know how memory is managed in Assembly as I will
illustrate the issue without even mentioning it.&lt;/p&gt;
&lt;p&gt;The filesystem of a typical &lt;a href=&quot;https://stackoverflow.com/a/4715413&quot;&gt;*nix system&lt;/a&gt; (i.e Linux, macOS) is
essentially free-form with loosely defined &lt;a href=&quot;https://en.wikipedia.org/wiki/Linux_Standard_Base&quot;&gt;“standards”&lt;/a&gt; and
&lt;a href=&quot;https://man.openbsd.org/hier.7&quot;&gt;“conventions”&lt;/a&gt; adopted by system administrators, software developers,
and package maintainers.&lt;/p&gt;
&lt;p&gt;In this case, filesystem refers to how files are structured on your
system, like the &lt;code&gt;/bin/&lt;/code&gt; folder contains program binaries and your
personal “home” folder is inside the &lt;code&gt;/home/&lt;/code&gt; folder.&lt;/p&gt;
&lt;p&gt;If you want to see how different this can be, see how files are
structured in &lt;a href=&quot;https://developer.apple.com/library/archive/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/FileSystemOverview/FileSystemOverview.html&quot;&gt;macOS&lt;/a&gt; and a typical &lt;a href=&quot;https://help.ubuntu.com/community/LinuxFilesystemTreeOverview&quot;&gt;Linux distribution&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;You might argue that they shouldn’t be compared but they both share a
lot of the same software (i.e &lt;a href=&quot;https://formulae.brew.sh/formula/docker#default&quot;&gt;Docker in macOS with Homebrew&lt;/a&gt; and &lt;a href=&quot;https://packages.ubuntu.com/hirsute/docker.io&quot;&gt;Docker
in Ubuntu&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Even then, it’s not like every distributions of Linux follow a &lt;a href=&quot;https://en.wikipedia.org/wiki/Linux_Standard_Base#Limitations_on_Debian&quot;&gt;rigid
and well-defined standard&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Some of you may have strong opinions about where software should be
installed on your system.&lt;/p&gt;
&lt;p&gt;Perhaps, you have a rigid rule where all user-compiled software must
be stored inside a single prefix like &lt;code&gt;/usr/local/&lt;/code&gt; or isolated nicely
inside their own prefixes (i.e &lt;a href=&quot;https://www.nginx.com/resources/wiki/start/topics/tutorials/gettingstarted/#installation&quot;&gt;&lt;code&gt;/usr/local/nginx/&lt;/code&gt;&lt;/a&gt;, &lt;a href=&quot;https://developer.android.com/studio/install#linux&quot;&gt;&lt;code&gt;/opt/android/&lt;/code&gt;&lt;/a&gt;,
&lt;a href=&quot;https://www.linode.com/docs/guides/how-to-set-up-minecraft-server-on-ubuntu-or-debian&quot;&gt;&lt;code&gt;/home/minecraft/&lt;/code&gt;&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;In the end, these are choices driven by opinions which are made by
different parties.&lt;/p&gt;
&lt;p&gt;Now, as a software developer, how do you handle this mess?&lt;/p&gt;
&lt;p&gt;Let’s take a fairly simple example: a Python script.&lt;/p&gt;
&lt;p&gt;It’s nothing complicated, something that is written by someone who’s
new to Python:&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;#!/usr/bin/python&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F40064&quot;&gt;def&lt;/span&gt;&lt;span style=&quot;color:#0057D1&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;():&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;    for&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; i &lt;/span&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; range&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 11&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C99&quot;&gt;        print&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F40064&quot;&gt;f&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;&amp;#39;Counting down &lt;/span&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;i&lt;/span&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;...&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; __name__&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt; ==&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt; &amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;__main__&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;    main&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That’s a fairly simple, isn’t it?&lt;/p&gt;
&lt;p&gt;But look at the &lt;a href=&quot;https://en.wikipedia.org/wiki/Shebang_(Unix)&quot;&gt;shebang&lt;/a&gt; (&lt;code&gt;#!&lt;/code&gt;), the script has a major assumption of
where Python is installed.&lt;/p&gt;
&lt;p&gt;It expects it to be installed at &lt;code&gt;/usr/bin/python&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;However, the script uses a feature which only exists in Python 3.&lt;/p&gt;
&lt;p&gt;If you’re running a system that’s in the “Python is Python 3” club, it
may work for you.&lt;/p&gt;
&lt;p&gt;But for a lot of people, &lt;code&gt;python&lt;/code&gt; is not &lt;code&gt;python3&lt;/code&gt;, it’s still &lt;code&gt;python2&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;console&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; python --version&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Python 2.7.18&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; ./script.py&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  File &amp;quot;./script.py&amp;quot;, line 5&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;    print(f&amp;#39;Counting down {i}...&amp;#39;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;                                ^&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;SyntaxError: invalid syntax&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The reason for this is mainly for compatibility as Python 3 introduced
a lot of features which &lt;a href=&quot;https://confluence.ecmwf.int/display/UDOC/Migration+to+Python+3&quot;&gt;breaks its backwards-compatibility with
Python 2&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To fix this issue, the shebang must use &lt;code&gt;/usr/bin/python3&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;#!/usr/bin/python3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F40064&quot;&gt;def&lt;/span&gt;&lt;span style=&quot;color:#0057D1&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;():&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;    for&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; i &lt;/span&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; range&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 11&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C99&quot;&gt;        print&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F40064&quot;&gt;f&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;&amp;#39;Counting down &lt;/span&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;i&lt;/span&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;...&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; __name__&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt; ==&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt; &amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;__main__&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;    main&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, you encounter a different issue: Some people use various flavors
of BSDs (including macOS) instead of Linux.&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;console&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; ./script.py&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;zsh: ./script.py: bad interpreter: /usr/bin/python3: no such file or directory&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Unlike Linux, BSDs has a monolithic approach where it is not just a
kernel but also encapsulates everything which makes a complete BSD
system.&lt;/p&gt;
&lt;p&gt;In this case, “everything” could be anything from the basic core
utilities (&lt;code&gt;cat&lt;/code&gt;, &lt;code&gt;grep&lt;/code&gt;, &lt;code&gt;ls&lt;/code&gt;, etc.) to &lt;a href=&quot;https://man.openbsd.org/sndiod.8&quot;&gt;an audio server&lt;/a&gt; or even &lt;a href=&quot;https://man.openbsd.org/httpd.8&quot;&gt;a
ready-to-use HTTP server&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This is why Linux distributions exists, someone need to construct a
complete system with the Linux kernel and additional essential
components.&lt;/p&gt;
&lt;p&gt;Because of BSD’s monolithic approach, third-party software are always
installed under a separate prefix (such as &lt;code&gt;/usr/local/&lt;/code&gt;) because &lt;code&gt;/usr/&lt;/code&gt;
is occupied by software provided by the operating system.&lt;/p&gt;
&lt;p&gt;However, you can’t always assume that the software will be in
&lt;code&gt;/usr/local/&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In macOS which lacks an official package manager from Apple, macOS
users uses a third-party package manager such as &lt;a href=&quot;https://brew.sh/&quot;&gt;Homebrew&lt;/a&gt;, &lt;a href=&quot;https://www.macports.org/&quot;&gt;MacPorts&lt;/a&gt;,
and &lt;a href=&quot;https://www.pkgsrc.org/&quot;&gt;pkgsrc&lt;/a&gt; which installs software &lt;a href=&quot;https://guide.macports.org/chunked/reference.variables.html&quot;&gt;in&lt;/a&gt; &lt;a href=&quot;https://www.netbsd.org/docs/pkgsrc/configuring.html&quot;&gt;different&lt;/a&gt; &lt;a href=&quot;https://docs.brew.sh/FAQ#why-should-i-install-homebrew-in-the-default-location&quot;&gt;places&lt;/a&gt; within the
filesystem.&lt;/p&gt;
&lt;p&gt;In a NetBSD system, there are two prefixes for third-party software:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;a href=&quot;https://www.netbsd.org/docs/pkgsrc/files.html&quot;&gt;&lt;code&gt;/usr/pkg/&lt;/code&gt; prefix&lt;/a&gt; for software that are installed by
pkgsrc.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;/usr/local/&lt;/code&gt; prefix for software that are compiled and
installed by the user.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With this new knowledge and realisation of the issue, you look around
to find if there’s a simple solution.&lt;/p&gt;
&lt;p&gt;After all, this should be a solved problem, right?&lt;/p&gt;
&lt;p&gt;After a while, you’ll find &lt;a href=&quot;https://man.openbsd.org/env.1&quot;&gt;env&lt;/a&gt; which is a loose convention adopted by
&lt;a href=&quot;https://www.freebsd.org/cgi/man.cgi?query=env&amp;apropos=0&amp;sektion=0&amp;manpath=FreeBSD+13.0-RELEASE+and+Ports&amp;arch=default&amp;format=html&quot;&gt;most&lt;/a&gt; &lt;a href=&quot;https://ss64.com/osx/env.html&quot;&gt;*nix&lt;/a&gt; &lt;a href=&quot;https://nixdoc.net/man-pages/HP-UX/man1/env.1.html&quot;&gt;systems&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;/usr/bin/env&lt;/code&gt; is a program that will direct the user to run the right
program, no matter how the system is configured. Just give it a name
of the executable and it will find and execute it for you.&lt;/p&gt;
&lt;p&gt;Perfect, simply replace your &lt;code&gt;/usr/bin/python3&lt;/code&gt; with &lt;code&gt;/usr/bin/env python3&lt;/code&gt; and now it works.&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;#!/usr/bin/env python3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F40064&quot;&gt;def&lt;/span&gt;&lt;span style=&quot;color:#0057D1&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;():&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;    for&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; i &lt;/span&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; range&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 11&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C99&quot;&gt;        print&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#F40064&quot;&gt;f&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;&amp;#39;Counting down &lt;/span&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;i&lt;/span&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;...&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; __name__&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt; ==&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt; &amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;__main__&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;    main&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Oh no, you realize another issue: the script requires at least Python
3.6 because it uses &lt;a href=&quot;https://www.python.org/dev/peps/pep-0498/&quot;&gt;f-strings&lt;/a&gt;.&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;console&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; python3 --version&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Python 3.5.9&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; ./script.py&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  File &amp;quot;./script.py&amp;quot;, line 5&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;    print(f&amp;#39;Counting down {i}...&amp;#39;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;                                ^&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;SyntaxError: invalid syntax&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Well, as the developer, you can choose to be ignorant and simply
state: “Your system is obselete if it doesn’t have at least Python
3.6”.&lt;/p&gt;
&lt;p&gt;Even then, what about system distributions that ships multiple versions
of Python?&lt;/p&gt;
&lt;p&gt;Package repositories such as the ones used in macOS Homebrew, FreeBSD,
and OpenBSD ships multiple versions of Python, Ruby, Node, PHP, and
others.&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;console&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; uname -s&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;OpenBSD&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; pkg_info -Q python&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;python-2.7.18p1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;python-3.8.10&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;python-3.9.5&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; type -a python3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;python3 not found&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; type -a python3.8&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;python3.8 is /usr/local/bin/python3.8&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; type -a python3.9&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;python3.9 is /usr/local/bin/python3.9&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The binaries for them are typically separated using the version as a
suffix (i.e &lt;code&gt;python37&lt;/code&gt;, &lt;code&gt;python38&lt;/code&gt;, &lt;code&gt;python39&lt;/code&gt;)&lt;/p&gt;
&lt;p&gt;So, how do you assume what &lt;code&gt;python3&lt;/code&gt; will be?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Is &lt;code&gt;python3&lt;/code&gt; the latest version?&lt;/li&gt;
&lt;li&gt;Is it something in between that’s chosen by the system
administrator?&lt;/li&gt;
&lt;li&gt;Is it the oldest available version for compatibility?&lt;/li&gt;
&lt;li&gt;Does it even exist at all?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As you can see, this is the very issue with traditional software
deployment and why it can feel ancient at times.&lt;/p&gt;
&lt;p&gt;You would like to believe that the solution simple and common.
However, as you gaze down the abyss of software deployment, you start
to realize that it is bottomless.&lt;/p&gt;
&lt;p&gt;We haven’t started using third-party Python libraries or even native
libraries.&lt;/p&gt;
&lt;p&gt;This is just a simple script which requires a Python interpreter
that’s at least version 3.6.&lt;/p&gt;
&lt;p&gt;In many ways, this was someone’s “Hello, World!”.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;What if we require libraries like &lt;a href=&quot;https://docs.python-requests.org/en/master/&quot;&gt;requests&lt;/a&gt;?&lt;/li&gt;
&lt;li&gt;What if we require programs like &lt;a href=&quot;http://ffmpeg.org/&quot;&gt;FFmpeg&lt;/a&gt; and &lt;a href=&quot;https://imagemagick.org/index.php&quot;&gt;ImageMagick&lt;/a&gt;?&lt;/li&gt;
&lt;li&gt;What if we require data files like game assets?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is a universal issue that affects everyone.&lt;/p&gt;
&lt;p&gt;From the first-year computer science student to the experienced
veteran administrator, no one is able to pursue their adventures
without having to plunge deep into the abyss of software deployment.&lt;/p&gt;
&lt;h1 id=&quot;the-problem-with-traditional-packages&quot;&gt;The problem with traditional packages&lt;/h1&gt;
&lt;p&gt;Most system distributions ships third-party software.&lt;/p&gt;
&lt;p&gt;They could be &lt;a href=&quot;https://docs.freebsd.org/en/books/handbook/ports/#ports-using&quot;&gt;a recipe&lt;/a&gt; that the user can execute to download, compile,
and install third-party software.&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;console&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; cd /usr/ports/misc/hello/&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; make&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;===&amp;gt;  License GPLv3+ accepted by the user&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;===&amp;gt;   hello-2.10_1 depends on file: /usr/local/sbin/pkg - found&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;=&amp;gt; hello-2.10.tar.gz doesn&amp;#39;t seem to exist in /usr/ports/distfiles/.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;=&amp;gt; Attempting to fetch https://ftpmirror.gnu.org/hello/hello-2.10.tar.gz&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;hello-2.10.tar.gz                                      708 kB 3368 kBps    00s&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;===&amp;gt; Fetching all distfiles required by hello-2.10_1 for building&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;===&amp;gt;  Extracting for hello-2.10_1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;=&amp;gt; SHA256 Checksum OK for hello-2.10.tar.gz.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;===&amp;gt;  Patching for hello-2.10_1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;===&amp;gt;   hello-2.10_1 depends on package: gmake&amp;gt;=4.3 - found&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;===&amp;gt;  Configuring for hello-2.10_1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;===&amp;gt;  Building for hello-2.10_1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;====&amp;gt; Compressing man pages (compress-man)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; doas make install&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;===&amp;gt;  Installing for hello-2.10_1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; hello&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Hello, world!&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Or, they could be &lt;a href=&quot;https://rpm.org/about.html&quot;&gt;a binary package&lt;/a&gt; which the user can easily install
with a tool.&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;console&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; doas pkg install hello&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Updating HardenedBSD repository catalogue...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;HardenedBSD repository is up to date.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;All repositories are up to date.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;The following 1 package(s) will be affected (of 0 checked):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;New packages to be INSTALLED:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;        hello: 2.10_1 [HardenedBSD]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Number of packages to be installed: 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;56 KiB to be downloaded.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Proceed with this action? [y/N]: y&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;[1/1] Fetching hello-2.10_1.txz: 100%   56 KiB  56.9kB/s    00:01&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Checking integrity... done (0 conflicting)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;[1/1] Installing hello-2.10_1...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;[1/1] Extracting hello-2.10_1: 100%&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; hello&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Hello, world!&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;These packages are maintained by the &lt;a href=&quot;https://nm.debian.org/public/people/dm_all/&quot;&gt;humble package maintainers&lt;/a&gt; who
risk their lives deep within the abyss in order to help users install
third-party software with little to no pain.&lt;/p&gt;
&lt;p&gt;Often times, package maintainers are required to &lt;a href=&quot;https://salsa.debian.org/apache-team/apache2/-/tree/master/debian/patches&quot;&gt;write patches&lt;/a&gt; to make
software work.&lt;/p&gt;
&lt;p&gt;With the Python script example we did, they might write a patch to
make it use the exact version of Python and explicitly declare which
version of Python is required for the package.&lt;/p&gt;
&lt;p&gt;For a lot of people, this works just fine.&lt;/p&gt;
&lt;p&gt;Simply install the software you need from the package manager present
in your system.&lt;/p&gt;
&lt;p&gt;But here’s the issue, what if the software is not available from the
package manager?&lt;/p&gt;
&lt;p&gt;Well, as a user, you have two choices:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Compile and install it by hand.&lt;/li&gt;
&lt;li&gt;Dive into the abyss and become a package maintainer.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;None of the two choices are particularly good.&lt;/p&gt;
&lt;p&gt;Becoming a package maintainer is hard as you have to be ready for the
following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Follow the latest version of the software.&lt;/li&gt;
&lt;li&gt;Write patches to make it work.&lt;/li&gt;
&lt;li&gt;In addition, follow the dependencies of the software.&lt;/li&gt;
&lt;li&gt;Write patches to make the dependencies work.&lt;/li&gt;
&lt;li&gt;And repeat.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you compile and install it by hand, you’re on your own:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;You have the responsibility of maintaining the software locally.&lt;/li&gt;
&lt;li&gt;You have to make sure that it doesn’t conflict with anything on the
system.&lt;/li&gt;
&lt;li&gt;You have to make sure that the dependencies that it requires are
there.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Essentially, you have to become the package maintainer for your own
system and what if you need it in another system? Tough luck.&lt;/p&gt;
&lt;p&gt;This issue has spawned three new trends:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The infamous &lt;code&gt;curl | sh&lt;/code&gt; installer.&lt;/li&gt;
&lt;li&gt;Package managers which are specific to a particular programming
language (i.e &lt;a href=&quot;https://www.npmjs.com/&quot;&gt;npm&lt;/a&gt;, &lt;a href=&quot;https://pypi.org/project/pip/&quot;&gt;pip&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Using containers as a medium to deliver and run software.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&quot;the-problem-with-curl--sh-installers-and-language-specific-package-managers&quot;&gt;The problem with &lt;code&gt;curl | sh&lt;/code&gt; installers and language-specific package managers&lt;/h1&gt;
&lt;p&gt;The &lt;code&gt;curl | sh&lt;/code&gt; installer is simply a small script that checks the state
of your system and perform the proper installation procedure based on
your system.&lt;/p&gt;
&lt;p&gt;The main problem with &lt;code&gt;curl | sh&lt;/code&gt; is &lt;a href=&quot;https://github.com/djm/pipe-to-sh-poc&quot;&gt;their unsafe nature&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;As the script is able to &lt;a href=&quot;https://gist.github.com/yukiisbored/fdc4f7b48aba79f7fcdba84a18769464&quot;&gt;do anything&lt;/a&gt; to your system, it is no
different to a &lt;a href=&quot;https://en.wikipedia.org/wiki/Self-XSS&quot;&gt;Self-XSS&lt;/a&gt; attack.&lt;/p&gt;
&lt;p&gt;Because it is a shell script, it cannot be limited to only perform the
tasks necessary to achieve the goal of installing the software.&lt;/p&gt;
&lt;p&gt;The programming language specific package managers has the issue of
limited reach.&lt;/p&gt;
&lt;p&gt;For example, if you’re installing a library to interact with a MySQL
database, you might need to have the necessary MySQL native libraries
to be installed which is out of reach for the language specific
package managers.&lt;/p&gt;
&lt;p&gt;However, both have share a major issue due to the lack of isolation:
file conflicts.&lt;/p&gt;
&lt;p&gt;For example, you’ve installed the &lt;a href=&quot;https://docker-py.readthedocs.io/en/stable/&quot;&gt;Docker SDK for Python&lt;/a&gt; via pip but
you need to install &lt;a href=&quot;https://docs.docker.com/compose/&quot;&gt;Docker Compose&lt;/a&gt; via your system’s package manager.&lt;/p&gt;
&lt;p&gt;As Docker compose requires the Docker SDK, it also need the SDK to be
installed from the system’s package manager.&lt;/p&gt;
&lt;p&gt;The Docker SDK package from the system’s package manager cannot be
installed because it is conflicting with the Docker SDK installed by
pip.&lt;/p&gt;
&lt;p&gt;Or, it will install but you will have two separate versions of the
same package which will cause weird issues: Which version of the
Docker SDK will docker-compose use?&lt;/p&gt;
&lt;p&gt;The common solution for this is to install it on separated prefixes.&lt;/p&gt;
&lt;p&gt;For example, in Python, software developers typically setup separate,
local, and isolated prefixes called &lt;a href=&quot;https://docs.python.org/3/tutorial/venv.html&quot;&gt;Virtual environments&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The same mechanic is present in &lt;code&gt;curl | sh&lt;/code&gt; installers, they commonly
use local separate prefixes (i.e &lt;code&gt;~/.cargo/&lt;/code&gt; which is used by &lt;a href=&quot;https://rustup.rs/&quot;&gt;rustup&lt;/a&gt;).&lt;/p&gt;
&lt;h1 id=&quot;the-problem-with-containers&quot;&gt;The problem with containers&lt;/h1&gt;
&lt;p&gt;Application containers such as Docker, &lt;a href=&quot;https://snapcraft.io/&quot;&gt;Snap&lt;/a&gt;, &lt;a href=&quot;https://flatpak.org/&quot;&gt;Flatpak&lt;/a&gt; and &lt;a href=&quot;https://appimage.org/&quot;&gt;AppImage&lt;/a&gt;
require some form of file system isolation.&lt;/p&gt;
&lt;p&gt;This is because they not only ship the software but also an entire
system tailored for running the software.&lt;/p&gt;
&lt;p&gt;You can see this in action with &lt;a href=&quot;https://github.com/wagoodman/dive&quot;&gt;Docker images&lt;/a&gt; which is a tarball
archive of a tailored Linux system made to run a specific piece of
software.&lt;/p&gt;
&lt;p&gt;In macOS, they use something similar called &lt;a href=&quot;https://en.wikipedia.org/wiki/Bundle_(macOS)&quot;&gt;Application bundles&lt;/a&gt; which
are just folders filled with the necessary data files, libraries, and
binaries.&lt;/p&gt;
&lt;p&gt;This means that software that are distributed through these mediums
takes a lot of storage space.&lt;/p&gt;
&lt;p&gt;For a lot of people, this is not an issue because for them storage is
cheap.&lt;/p&gt;
&lt;p&gt;However, as someone who has lived their life in Indonesia with slow
4G, most of my computing time is taken by the simple task of
downloading software.&lt;/p&gt;
&lt;p&gt;To mitigate the issue, they have solutions which reduces the download
size:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Docker images are composed of layers which can be shared across
images.&lt;/li&gt;
&lt;li&gt;macOS provides &lt;a href=&quot;https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/OSX_Technology_Overview/SystemFrameworks/SystemFrameworks.html&quot;&gt;Frameworks&lt;/a&gt; which are simply bundles of popular
libraries which third-party applications can use.&lt;/li&gt;
&lt;li&gt;Flatpak share a similar system to macOS framework called &lt;a href=&quot;https://docs.flatpak.org/en/latest/basic-concepts.html#runtimes&quot;&gt;Runtimes&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;But in the end, these are still compromises and they won’t guarantee
that you won’t redownload the same files.&lt;/p&gt;
&lt;h1 id=&quot;closing&quot;&gt;Closing&lt;/h1&gt;
&lt;p&gt;As you can see, the current method of installing software is
fundamentally flawed as it requires knowing the state of the
system which will guide you to make the necessary changes that allows
the software to be installed.&lt;/p&gt;
&lt;p&gt;Package managers simply automate the installation process to the point
where anyone can install easily without having to know much about the
system.&lt;/p&gt;
&lt;p&gt;However, package managers can only target a specific system (i.e
Ubuntu or Arch) and the same packages can’t be shared between
different systems (ex. you can’t use Arch packages in Ubuntu).&lt;/p&gt;
&lt;p&gt;&lt;code&gt;curl | sh&lt;/code&gt; installers are another form of automation with the caveat
that they have unlimited reach and control on the system which is
fundamentally unsafe.&lt;/p&gt;
&lt;p&gt;Ultimately, they can’t be trusted to only perform the tasks required
to install the software but this unlimited reach is required in order
for it to know the current state of your system.&lt;/p&gt;
&lt;p&gt;Programming language specific package managers doesn’t really solve
this issue as they have a very limited reach by design in order to not
break your system. They only care about the environment for the
specific programming language it was made for.&lt;/p&gt;
&lt;p&gt;Application containers and bundles are working around the issue by
shipping a complete system with the software you need. This results in
wasting a lot of resources which renders it unaccessible to a lot of
people.&lt;/p&gt;
&lt;p&gt;There are plenty more of other issues with the current methods such as
the requirement of trusting the humble package maintainers.&lt;/p&gt;
&lt;p&gt;There have been cases where you can’t trust them like the &lt;a href=&quot;https://www.theregister.com/2015/06/26/googles_not_listening_binary_blob_banished_from_chromium_build/&quot;&gt;chromium
binary blob scandal&lt;/a&gt; that has impacted Debian.&lt;/p&gt;
&lt;p&gt;This demonstrate the fact that a malicious agent only need to attack
the few humble package maintainers.&lt;/p&gt;
&lt;p&gt;As a user, it’s not easy to audit binaries especially when &lt;a href=&quot;https://wiki.debian.org/ReproducibleBuilds&quot;&gt;they’re not
reproducible&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;You can choose to build and install everything from source like &lt;a href=&quot;https://www.gentoo.org/&quot;&gt;Gentoo&lt;/a&gt;
but that takes &lt;a href=&quot;https://randomascii.wordpress.com/2020/03/30/big-project-build-times-chromium/&quot;&gt;a huge chunk of time&lt;/a&gt; which is a luxury that not
everyone has.&lt;/p&gt;
&lt;p&gt;You can build your own trusted build cluster and share the resulting
binaries but that costs money to buy the necessary hardware and labor
to maintain it.&lt;/p&gt;
&lt;p&gt;In the end, I hope this is enough for you to consider that there’s a need
for a new way of installing software.&lt;/p&gt;
&lt;p&gt;In the next article, we will explore how Nix solves all of the
fundamental issues with traditional software deployment by introducing
a new model called functional software deployment.&lt;/p&gt;</content:encoded></item><item><title>Spice up with Nix: Scripts with magical dependencies</title><link>https://yukiisbo.red/notes/spice-up-with-nix-scripts/</link><guid isPermaLink="true">https://yukiisbo.red/notes/spice-up-with-nix-scripts/</guid><description>In this article, we explore how Nix can make it easier to share and run scripts without having to deal with the pain of installing dependencies.</description><pubDate>Mon, 09 Aug 2021 00:00:00 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;Hey there,&lt;/p&gt;
&lt;p&gt;Instead of reading this outdated article, I highly recommend consulting
&lt;a href=&quot;https://nix.dev&quot;&gt;nix.dev&lt;/a&gt;’s &lt;a href=&quot;https://nix.dev/tutorials/first-steps/&quot;&gt;First Steps&lt;/a&gt; which is official documentation!&lt;/p&gt;
&lt;p&gt;Feel free to continue reading this if you want to see my personal take on the subject :)&lt;/p&gt;
&lt;p&gt;Thanks.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I wrote this cool script which shows you a list of letters and their
frequency in English.&lt;/p&gt;
&lt;p&gt;Check it!&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;#!/usr/bin/env python3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; requests                &lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;# Required to communicate via HTTP&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; pandas                  &lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;# Required to mangle with spreadsheets&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; bs4 &lt;/span&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; BeautifulSoup  &lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;# Required to parse HTML&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;# Let&amp;#39;s download the Letter frequency page from Wikipedia&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;r &lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; requests&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;https://en.wikipedia.org/wiki/Letter_frequency&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;assert&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; r&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;status_code &lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 200&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;# Use BeautifulSoup to parse HTML&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;s &lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; BeautifulSoup&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;r&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;text&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt; &amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;html.parser&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;# Find the last table in the page&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;res &lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; str&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;s&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;findAll&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;table&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt; {&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt; &amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;wikitable&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;})[&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;# Let&amp;#39;s convert that HTML table to a Pandas DataFrame&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;res &lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; pandas&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;read_html&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;res&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;)[&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;# We&amp;#39;re only interested in English and the first 25 letters.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;res &lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; res&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;[[&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;Letter&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt; &amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;English&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;]][&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt;26&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;# Properly handle the percentage in the table&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;res&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;English&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; res&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;English&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;].&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;str&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;rstrip&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;%&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;astype&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;float&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt; /&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 100.0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;# Sort it&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;res &lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; res&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;sort_values&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;by&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;English&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; ascending&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;False&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;# Show it to the user&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C99&quot;&gt;print&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;res&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Cool, right?&lt;/p&gt;
&lt;p&gt;Oh, you don’t have Python on your machine?&lt;/p&gt;
&lt;p&gt;Maybe, you don’t have the libraries it requires like &lt;a href=&quot;https://docs.python-requests.org/en/master/&quot;&gt;requests&lt;/a&gt;,
&lt;a href=&quot;https://pandas.pydata.org/&quot;&gt;pandas&lt;/a&gt;, and &lt;a href=&quot;https://www.crummy.com/software/BeautifulSoup/bs4/doc/&quot;&gt;BeautifulSoup&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Ah, it doesn’t run on your machine because you only have a different
version of those libraries?&lt;/p&gt;
&lt;h1 id=&quot;instant-runtime-environments-for-scripts-with-nix&quot;&gt;Instant runtime environments for scripts with Nix&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;If you don’t have Nix installed on your machine, &lt;a href=&quot;https://nixos.org/download.html&quot;&gt;install it now&lt;/a&gt;!&lt;/p&gt;
&lt;p&gt;It won’t break your system, I promise!&lt;/p&gt;
&lt;p&gt;As of writing, Nix runs well on macOS and Linux.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Nix can be used to setup a temporary runtime environment with all of
the dependencies which your script need.&lt;/p&gt;
&lt;p&gt;Simply use &lt;code&gt;nix-shell&lt;/code&gt; as an interpreter in the shebang (&lt;code&gt;#!&lt;/code&gt;) of your script.&lt;/p&gt;
&lt;p&gt;Using the script I’ve written above instead of using Python which is
installed on the machine:&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;#!/usr/bin/env python3&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Replace with &lt;code&gt;nix-shell&lt;/code&gt; and then give a list of packages to &lt;code&gt;nix-shell&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;#! /usr/bin/env nix-shell&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;#! nix-shell -i python -p python38 python38Packages.requests python38Packages.beautifulsoup4 python38Packages.pandas&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;#! nix-shell -I nixpkgs=https://github.com/NixOS/nixpkgs/archive/refs/tags/21.05.tar.gz&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Let’s break it down on what each line means!&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;#! /usr/bin/env nix-shell&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The first line simply tells your shell to use nix-shell as the
interpreter for this script, nothing new here. Not that different how
Python scripts are executed!&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;#! nix-shell -i python -p python38 python38Packages.requests python38Packages.beautifulsoup4 python38Packages.pandas&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This line seems scary but no worries. We are simply passing arguments
to &lt;code&gt;nix-shell&lt;/code&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;-i python&lt;/code&gt; tells Nix which interpreter to use. In this case, we’re
using &lt;code&gt;python&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-p python38 python38Packages...&lt;/code&gt; tells Nix which packages are
required for this script.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It’s not that different to a recipe.&lt;/p&gt;
&lt;p&gt;Instead of only containing instructions on what to do, with Nix, we
are able to give a list of ingredients and what to use in order to
perform the instructions!&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;#! nix-shell -I nixpkgs=https://github.com/NixOS/nixpkgs/archive/refs/tags/21.05.tar.gz&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This line looks scary but no worries, it’s simple.&lt;/p&gt;
&lt;p&gt;We’re telling Nix which version of the &lt;a href=&quot;https://github.com/NixOS/nixpkgs&quot;&gt;Nix packages collection
(nixpkgs)&lt;/a&gt; to use. In this case, we are using version 21.05.&lt;/p&gt;
&lt;p&gt;This is how we can pin our dependencies to ensure the person who are
running the script are running the exact version of the dependencies
that I works on my machine.&lt;/p&gt;
&lt;p&gt;This also ensures that even if you read this 5 or even 10 years in the
future, the script will still run with the same set of dependencies.&lt;/p&gt;
&lt;p&gt;So, here’s the final script after we spice it up with Nix:&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;#! /usr/bin/env nix-shell&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;#! nix-shell -i python -p python38 python38Packages.requests python38Packages.beautifulsoup4 python38Packages.pandas&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;#! nix-shell -I nixpkgs=https://github.com/NixOS/nixpkgs/archive/refs/tags/21.05.tar.gz&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; requests                &lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;# Required to communicate via HTTP&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; pandas                  &lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;# Required to mangle with spreadsheets&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; bs4 &lt;/span&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; BeautifulSoup  &lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;# Required to parse HTML&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;# Let&amp;#39;s download the Letter frequency page from Wikipedia&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;r &lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; requests&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;https://en.wikipedia.org/wiki/Letter_frequency&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;assert&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; r&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;status_code &lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 200&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;# Use BeautifulSoup to parse HTML&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;s &lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; BeautifulSoup&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;r&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;text&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt; &amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;html.parser&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;# Find the last table in the page&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;res &lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; str&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;s&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;findAll&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;table&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt; {&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt; &amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;wikitable&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;})[&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;# Let&amp;#39;s convert that HTML table to a Pandas DataFrame&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;res &lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; pandas&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;read_html&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;res&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;)[&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;# We&amp;#39;re only interested in English and the first 25 letters.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;res &lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; res&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;[[&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;Letter&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt; &amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;English&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;]][&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt;26&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;# Properly handle the percentage in the table&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;res&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;English&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; res&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;English&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;].&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;str&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;rstrip&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;%&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;astype&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;float&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt; /&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 100.0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;# Sort it&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;res &lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; res&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;sort_values&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;by&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;English&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; ascending&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;False&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;# Show it to the user&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C99&quot;&gt;print&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;res&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Only by changing that single line to three lines, this script will now
run on any machine with Nix installed and it will automagically
resolve the dependencies magically!&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;console&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; head -n3 cool-script.py&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;#! /usr/bin/env nix-shell&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;#! nix-shell -i python -p python38 python38Packages.requests python38Packages.beautifulsoup4 python38Packages.pandas&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;#! nix-shell -I nixpkgs=https://github.com/NixOS/nixpkgs/archive/refs/tags/21.05.tar.gz&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; ./cool-script.py&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;these 85 paths will be fetched (132.87 MiB download, 693.09 MiB unpacked):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  /nix/store/0b90d74742wl9vpy0vpd89k6cks9xvd9-bash-interactive-4.4-p23-man&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  /nix/store/zsh6dmqlp15yzj3mgq3zv212waz12lbk-python3.8-urllib3-1.26.4&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;copying path &amp;#39;/nix/store/lp6ccpip5ygq0k813gyb9m4iashzk2r0-bash-interactive-4.4-p23-doc&amp;#39; from &amp;#39;https://hydra.iohk.io&amp;#39;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;copying path &amp;#39;/nix/store/4dlhsl4kxp9p632mbv1rcq9kjc0y6zdy-stdenv-linux&amp;#39; from &amp;#39;https://hydra.iohk.io&amp;#39;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;   Letter  English&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;4       e  0.12702&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;19      t  0.09056&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;0       a  0.08167&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;14      o  0.07507&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;8       i  0.06966&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;13      n  0.06749&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;18      s  0.06327&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;7       h  0.06094&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;17      r  0.05987&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;3       d  0.04253&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;11      l  0.04025&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;2       c  0.02782&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;20      u  0.02758&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;12      m  0.02406&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;22      w  0.02360&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;5       f  0.02228&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;6       g  0.02015&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;24      y  0.01974&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;15      p  0.01929&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;1       b  0.01492&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;21      v  0.00978&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;10      k  0.00772&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;9       j  0.00153&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;23      x  0.00150&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;16      q  0.00095&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;25      z  0.00074&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can see, Nix will magically prepare a temporary environment
with the dependencies for your script.&lt;/p&gt;
&lt;p&gt;Wait, does this mean Nix has installed those dependencies and Python?&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;console&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; python3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Python 3.8.9 (default, Apr  2 2021, 11:20:07)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;[GCC 10.3.0] on linux&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Type &amp;quot;help&amp;quot;, &amp;quot;copyright&amp;quot;, &amp;quot;credits&amp;quot; or &amp;quot;license&amp;quot; for more information.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;&amp;gt;&amp;gt;&amp;gt; import requests&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Traceback (most recent call last):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  File &amp;quot;&amp;lt;stdin&amp;gt;&amp;quot;, line 1, in &amp;lt;module&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;ModuleNotFoundError: No module named &amp;#39;requests&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;&amp;gt;&amp;gt;&amp;gt; import pandas&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Traceback (most recent call last):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  File &amp;quot;&amp;lt;stdin&amp;gt;&amp;quot;, line 1, in &amp;lt;module&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;ModuleNotFoundError: No module named &amp;#39;pandas&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;&amp;gt;&amp;gt;&amp;gt; import bs4&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Traceback (most recent call last):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  File &amp;quot;&amp;lt;stdin&amp;gt;&amp;quot;, line 1, in &amp;lt;module&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;ModuleNotFoundError: No module named &amp;#39;bs4&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can see, it didn’t alter your system. Your system is safe.&lt;/p&gt;
&lt;h1 id=&quot;only-python-nope&quot;&gt;Only Python? Nope.&lt;/h1&gt;
&lt;p&gt;This is not limited to only Python. You can use it with everything.&lt;/p&gt;
&lt;p&gt;You want to use it in a shell script which require programs to be
present on the system? No problem.&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;shell&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;#! /usr/bin/env nix-shell&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;#! nix-shell -i bash -p gnat mktemp&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;#! nix-shell -I nixpkgs=https://github.com/NixOS/nixpkgs/archive/refs/tags/21.05.tar.gz&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;# Make a temp folder&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;WORKDIR&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;=$(&lt;/span&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;mktemp&lt;/span&gt;&lt;span style=&quot;color:#D17C00&quot;&gt; -d&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;# Go to the temp directory&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;pushd &lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;${&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;WORKDIR&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;# Write some code&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;cat&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt; &amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt; hello.adb&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt; &amp;lt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;EOF&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;with Text_IO; use Text_IO;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;procedure hello is&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;begin&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;   Put_Line(&amp;quot;Hello, world!&amp;quot;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;end hello;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;EOF&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;# Compile it with GNAT&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;gnatmake&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt; hello.adb&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;# Run it&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;./hello&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;# Go back to the previous directory&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;popd&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;# Copy the executable&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;cp&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;${&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;WORKDIR&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;/hello&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt; ./hello&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;# Remove the temp folder&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;rm&lt;/span&gt;&lt;span style=&quot;color:#D17C00&quot;&gt; -rf&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;${&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;WORKDIR&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;j&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;console&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; ./cool.sh&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;these 9 paths will be fetched (46.63 MiB download, 226.41 MiB unpacked):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  /nix/store/1977rsramab0ks7bk3fxjd91kf1ddxy1-libmpc-1.2.1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  /nix/store/v07f9gbkizyfcz98ssyhbq5jr6x823lm-gmp-6.2.1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;copying path &amp;#39;/nix/store/by026wm1s9phidfb96l5gcxyylly9j5y-expand-response-params&amp;#39; from &amp;#39;https://hydra.iohk.io&amp;#39;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;copying path &amp;#39;/nix/store/a7y4ng9g8jn1vm5p6l34nbg8ns5ml7f2-gnat-wrapper-9.3.0&amp;#39; from &amp;#39;https://cache.nixos.org&amp;#39;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;/run/user/1000/tmp.Q6gesiZ73k ~&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;gcc -c -I/nix/store/9b5w72pds7z3mj2bplx97yn9vpz5x0zl-gnat-9.3.0/lib/gcc/x86_64-unknown-linux-gnu/9.3.0/adainclude -I/nix/store/9b5w72pds7z3mj2bplx97yn9vpz5x0zl-gnat-9.3.0/lib/gcc/x86_64-unknown-linux-gnu/9.3.0/adalib hello.adb&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;/nix/store/a7y4ng9g8jn1vm5p6l34nbg8ns5ml7f2-gnat-wrapper-9.3.0/bin/gnatbind -I/nix/store/9b5w72pds7z3mj2bplx97yn9vpz5x0zl-gnat-9.3.0/lib/gcc/x86_64-unknown-linux-gnu/9.3.0/adainclude -I/nix/store/9b5w72pds7z3mj2bplx97yn9vpz5x0zl-gnat-9.3.0/lib/gcc/x86_64-unknown-linux-gnu/9.3.0/adalib -x hello.ali&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;/nix/store/a7y4ng9g8jn1vm5p6l34nbg8ns5ml7f2-gnat-wrapper-9.3.0/bin/gnatlink hello.ali&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Hello, world!&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;~&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; ls ./hello&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;./hello&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; ./hello&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Hello, world!&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Did Nix just prepare an environment with the GNU Ada Toolchain and
then run a script which compile an Ada program which runs?&lt;/p&gt;
&lt;p&gt;Yes, it did.&lt;/p&gt;
&lt;p&gt;What about something niche?&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;haskell&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;! /usr/bin/env nix-shell&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;! nix-shell -i runhaskell -p ghc&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;! nix-shell -I nixpkgs=https://github.com/NixOS/nixpkgs/archive/refs/tags/21.05.tar.gz&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;nums&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt; ::&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color:#F40064&quot;&gt;Int&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;nums &lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt;1780&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1693&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1830&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1756&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1858&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1868&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1968&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1809&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1996&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1962&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1800&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1974&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C99&quot;&gt;        1805&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1795&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt;  170&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1684&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1659&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1713&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1848&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1749&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1717&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1734&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt;  956&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1782&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C99&quot;&gt;        1834&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1785&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1786&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1994&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1652&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1669&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1812&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1954&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1984&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1665&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1987&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1562&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C99&quot;&gt;        2004&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 2010&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1551&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt;  961&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1854&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 2005&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1883&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1965&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt;  475&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1776&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1791&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt;  262&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C99&quot;&gt;        1912&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1227&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1486&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1989&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1857&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt;  825&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1683&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1991&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1875&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1982&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1654&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1767&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C99&quot;&gt;        1673&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1973&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1886&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1731&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1745&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1770&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1995&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1721&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1662&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1679&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1783&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1999&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C99&quot;&gt;        1889&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1746&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1902&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 2003&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1698&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1794&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1798&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1951&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1953&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 2007&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1899&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1658&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C99&quot;&gt;        1705&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt;   62&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1819&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1708&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1666&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 2006&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1763&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1732&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1613&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1841&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1747&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1489&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C99&quot;&gt;        1845&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 2008&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1885&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 2002&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1735&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1656&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1771&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1950&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1704&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1737&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1748&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1759&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C99&quot;&gt;        1802&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 2000&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1955&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1738&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1761&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1765&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1853&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1900&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1709&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1979&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1911&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1775&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C99&quot;&gt;        1813&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1949&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1966&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1774&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1977&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1757&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1992&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 2009&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1956&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1840&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1988&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1985&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C99&quot;&gt;        1993&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1718&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1976&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1078&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1997&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1897&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1792&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1790&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1801&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1871&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1727&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1700&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C99&quot;&gt;        1485&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt;  942&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1686&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1859&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1676&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt;  802&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1952&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1998&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1961&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1844&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1808&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1703&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C99&quot;&gt;        1980&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1766&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1963&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1849&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1670&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1716&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1957&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1660&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1816&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1762&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1829&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt;  526&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C99&quot;&gt;         359&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 2001&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1874&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1778&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1873&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1511&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1810&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1699&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1970&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1690&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1978&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1892&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C99&quot;&gt;        1691&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1781&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1777&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1975&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1967&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1694&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1969&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1959&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1910&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1826&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1672&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1655&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C99&quot;&gt;        1839&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1986&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1872&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1983&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1981&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1972&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1772&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 1760&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;solution&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt; ::&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color:#F40064&quot;&gt;Int&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt; -&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#F40064&quot;&gt; Int&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;solution xs &lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;  head&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;    [&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; x &lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; y &lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; z&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;      |&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; x &lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;&amp;lt;-&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; xs&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;        y &lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;&amp;lt;-&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; xs&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;        z &lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;&amp;lt;-&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; xs&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;        x &lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; y &lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; z &lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 2020&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;    ]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;main&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt; ::&lt;/span&gt;&lt;span style=&quot;color:#F40064&quot;&gt; IO&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt; ()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;main &lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; print &lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; solution nums&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;console&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; ./day1-part2-aoc.hs&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;these 4 paths will be fetched (138.01 MiB download, 1870.79 MiB unpacked):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  /nix/store/1pfdb37qm067ib7dnj5arbhl5q2kam3l-libffi-3.3-dev&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  /nix/store/55ysfrn085k1lsya0c2msm6npi7x6ihh-ghc-8.10.4-doc&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  /nix/store/f2psw0phlmp7h7gk14rfsqdmjz4d1arb-gmp-6.2.1-dev&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  /nix/store/mcm0wvsqcwqaxsp8fnwmknmpi0a196w6-ghc-8.10.4&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;copying path &amp;#39;/nix/store/55ysfrn085k1lsya0c2msm6npi7x6ihh-ghc-8.10.4-doc&amp;#39; from &amp;#39;https://cache.nixos.org&amp;#39;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;copying path &amp;#39;/nix/store/f2psw0phlmp7h7gk14rfsqdmjz4d1arb-gmp-6.2.1-dev&amp;#39; from &amp;#39;https://hydra.iohk.io&amp;#39;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;copying path &amp;#39;/nix/store/1pfdb37qm067ib7dnj5arbhl5q2kam3l-libffi-3.3-dev&amp;#39; from &amp;#39;https://hydra.iohk.io&amp;#39;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;copying path &amp;#39;/nix/store/mcm0wvsqcwqaxsp8fnwmknmpi0a196w6-ghc-8.10.4&amp;#39; from &amp;#39;https://cache.nixos.org&amp;#39;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;200878544&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can see, it works for any language. Simply check if your
favorite language and libraries are packaged: &lt;a href=&quot;https://search.nixos.org/packages&quot;&gt;search.nixos.org&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id=&quot;closing&quot;&gt;Closing&lt;/h1&gt;
&lt;p&gt;This is the first in a series of article that I will be publishing
more regularly.&lt;/p&gt;
&lt;p&gt;It is based of a mega draft I have written about Nix which was written
in the same style of &lt;a href=&quot;https://notes.yukiisbo.red/posts/2021/03/Surviving_Docker.html&quot;&gt;the Docker article&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;However, due to the massive differences in Nix vs other existing
package managers, it has grown to a rather massive and daunting draft
(1787 lines, 7265 words, 68436 characters).&lt;/p&gt;
&lt;p&gt;Because it would be a massive article and a huge turn off for a lot of
people due to its size, I will be breaking it down into smaller
bite-sized posts like this one.&lt;/p&gt;
&lt;p&gt;I will start with practical examples on how Nix can help in a lot of
real-world situations. In fact, I have delivered a couple of real
world projects on production with Nix and at work, we are now happily
using Nix by default.&lt;/p&gt;
&lt;p&gt;Once that’s done, we will dive head first and see how Nix works. I
hope you’ll find it interesting and this has been one of the longest
writing projects that I’ve done with so much research!&lt;/p&gt;
&lt;p&gt;Thanks for reading and I hope you’ll be there on the next one!&lt;/p&gt;</content:encoded></item><item><title>Spice up with Nix: Instant Development Environments</title><link>https://yukiisbo.red/notes/spice-up-with-nix-shells/</link><guid isPermaLink="true">https://yukiisbo.red/notes/spice-up-with-nix-shells/</guid><description>It&apos;s no secret that installing new tools when starting out in your journey is hard. In this article, we explore how Nix can make that easier for you.</description><pubDate>Fri, 13 Aug 2021 00:00:00 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;Hey there,&lt;/p&gt;
&lt;p&gt;Instead of reading this outdated article, I highly recommend consulting
&lt;a href=&quot;https://nix.dev&quot;&gt;nix.dev&lt;/a&gt;’s &lt;a href=&quot;https://nix.dev/tutorials/first-steps/&quot;&gt;First Steps&lt;/a&gt; which is official documentation!&lt;/p&gt;
&lt;p&gt;Feel free to continue reading this if you want to see my personal take on the subject :)&lt;/p&gt;
&lt;p&gt;Thanks.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;This article assumes you have installed &lt;a href=&quot;https:https://nixos.org/&quot;&gt;Nix&lt;/a&gt; on your machine.&lt;/p&gt;
&lt;p&gt;You can install it by running:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;$ curl -L https://nixos.org/nix/install | sh&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;It works on both Linux and macOS and it won’t break your system, I
promise!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The beginning of your journey as a programmer is always difficult.&lt;/p&gt;
&lt;p&gt;Before you even start programming, you have to install a bunch of
tools.&lt;/p&gt;
&lt;p&gt;When you are not familiar with the programming language, this issue
becomes exponentionally harder as you are not familiar with the
potential pitfalls.&lt;/p&gt;
&lt;p&gt;The fact that not everyone is running the same operating system is
also hard.&lt;/p&gt;
&lt;p&gt;Your coworkers runs macOS and they can’t help you because you’re
running Ubuntu.&lt;/p&gt;
&lt;p&gt;That person you met on Discord runs Arch Linux and tells you to simply
move to Manjaro.&lt;/p&gt;
&lt;p&gt;But you don’t want to change your operating system or buy a new
machine, you already have everything you need personally and
everything is already nicely configured for you.&lt;/p&gt;
&lt;p&gt;Why should this be difficult? Couldn’t this be easier?&lt;/p&gt;
&lt;h1 id=&quot;instant-development-environments-with-nix&quot;&gt;Instant (development) environments with Nix&lt;/h1&gt;
&lt;p&gt;Let me demonstrate how Nix can solve this issue:&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;nix&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color:#A018FF;font-style:italic&quot;&gt; pkgs&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt; ?&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; import&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt; &amp;lt;nixpkgs&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt; {}}:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;let&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;  # Python 3.8 environment with all of the packages I require&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C99&quot;&gt;  pythonEnv&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; pkgs&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;python38&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;withPackages &lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#A018FF;font-style:italic&quot;&gt;ps&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt; [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;    # Scientific python essentials&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;    ps&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;numpy&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;    ps&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;scipy&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;    ps&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;pandas&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;    ps&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;matplotlib&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;    # Grab samples from the net via Python&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;    ps&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;requests&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;    ps&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;beautifulsoup4&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;    # Need this to make the samples more bearable&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;    ps&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;nltk&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;    # Notebook editing&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;    ps&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;jupyter&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;    ps&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;ipython&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;  ]);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;in&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;pkgs&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;mkShell &lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C99&quot;&gt;  packages&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt; [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;    pythonEnv        &lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;# The Python 3.8 environment I made.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;    # Useful tools to grab samples from the net quickly&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;    pkgs&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;wget&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;    pkgs&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;curl&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;    pkgs&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;httpie      &lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;# I&amp;#39;m not good at `curl&amp;#39;. This might help me.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;    # Download audio/video samples from the net&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;    pkgs&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;youtube-dl&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;    pkgs&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;ffmpeg&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;  ];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Create an empty folder and save the snippet above as &lt;code&gt;shell.nix&lt;/code&gt; inside
it.&lt;/p&gt;
&lt;p&gt;Once that’s done, open a terminal, navigate to the folder, and then
run &lt;code&gt;nix-shell&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;console&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; python&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Python 3.8.9 (default, Apr  2 2021, 11:20:07)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;[GCC 10.3.0] on linux&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Type &amp;quot;help&amp;quot;, &amp;quot;copyright&amp;quot;, &amp;quot;credits&amp;quot; or &amp;quot;license&amp;quot; for more information.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;&amp;gt;&amp;gt;&amp;gt; import numpy&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Traceback (most recent call last):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  File &amp;quot;&amp;lt;stdin&amp;gt;&amp;quot;, line 1, in &amp;lt;module&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;ModuleNotFoundError: No module named &amp;#39;numpy&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; jupyter&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;zsh: command not found: jupyter&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; youtube-dl&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;zsh: command not found: youtube-dl&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; ls&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;shell.nix&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; nix-shell&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;this derivation will be built:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  /nix/store/h3kw8zi4pi6j0p4pnrlfv4qlix0gil0d-python3-3.8.9-env.drv&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;these 126 paths will be fetched (100.55 MiB download, 512.38 MiB unpacked):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  /nix/store/00cxgc94bssinmw330mkf22kiggmpyhc-python3.8-nbclient-0.5.3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  /nix/store/zzcilkahrnzk9wh7902zmxgwrsks5bjs-libgcrypt-1.9.3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;copying path &amp;#39;/nix/store/wzach25vwapl3sa6f7gylqank3jhhsin-bash-interactive-4.4-p23-dev&amp;#39; from &amp;#39;https://cache.nixos.org&amp;#39;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;copying path &amp;#39;/nix/store/f7j87bxvkvs9i6z91nfnrwnd8ngn9s6q-python3.8-jupyter-1.0.0&amp;#39; from &amp;#39;https://cache.nixos.org&amp;#39;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;building &amp;#39;/nix/store/h3kw8zi4pi6j0p4pnrlfv4qlix0gil0d-python3-3.8.9-env.drv&amp;#39;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;created 642 symlinks in user environment&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;[nix-shell:~/trash/python-science]&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; python&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Python 3.8.9 (default, Apr  2 2021, 11:20:07)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;[GCC 10.3.0] on linux&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Type &amp;quot;help&amp;quot;, &amp;quot;copyright&amp;quot;, &amp;quot;credits&amp;quot; or &amp;quot;license&amp;quot; for more information.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;&amp;gt;&amp;gt;&amp;gt; import numpy&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;&amp;gt;&amp;gt;&amp;gt; numpy.array([1,2,3,4,5])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;array([1, 2, 3, 4, 5])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;[nix-shell:~/trash/python-science]&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; youtube-dl&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Usage: youtube-dl [OPTIONS] URL [URL...]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;youtube-dl: error: You must provide at least one URL.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Type youtube-dl --help to see a list of all options.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;[nix-shell:~/trash/python-science]&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; jupyter notebook&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;[I 11:07:53.286 NotebookApp] Serving notebooks from local directory: /home/yuki/trash/python-science&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;[I 11:07:53.287 NotebookApp] Jupyter Notebook 6.3.0 is running at:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;[I 11:07:53.287 NotebookApp] http://localhost:8888/?token=f9b1...d05e&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;[I 11:07:53.287 NotebookApp]  or http://127.0.0.1:8888/?token=f9b1...d05e&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;[I 11:07:53.287 NotebookApp] Use Control-C to stop this server and shut down all kernels (twice to skip confirmation).&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;[C 11:07:53.371 NotebookApp]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;    To access the notebook, open this file in a browser:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;        file:///home/yuki/.local/share/jupyter/runtime/nbserver-160202-open.html&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;    Or copy and paste one of these URLs:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;        http://localhost:8888/?token=f9b1...d05e&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;     or http://127.0.0.1:8888/?token=f9b1...d05e&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Congratulations, you’re now ready to start your data scientist
journey.&lt;/p&gt;
&lt;p&gt;Seriously, just like that and you’re ready to start doing the things
that data scientists do.&lt;/p&gt;
&lt;p&gt;With only Nix, you’re able to launch a shell environment with not only
Python and additional libraries but also jupyter, ffmpeg, youtube-dl,
curl, wget, httpie.&lt;/p&gt;
&lt;p&gt;It didn’t ask you to even run with &lt;code&gt;sudo&lt;/code&gt; nor nag you about confusing
missing library errors, it just works and all you need is Nix and a
&lt;code&gt;shell.nix&lt;/code&gt; file.&lt;/p&gt;
&lt;h1 id=&quot;what-does-shellnix-do&quot;&gt;What does &lt;code&gt;shell.nix&lt;/code&gt; do?&lt;/h1&gt;
&lt;p&gt;Glancing &lt;code&gt;shell.nix&lt;/code&gt;, you might be able to guess what it is doing.&lt;/p&gt;
&lt;p&gt;You’re essentially giving Nix a shopping list of what you need in your
shell environment.&lt;/p&gt;
&lt;p&gt;You might think the syntax looks weird in comparison to a lot of
similar package managers and I agree.&lt;/p&gt;
&lt;p&gt;That’s because Nix made their own programming language called the Nix
expression language.&lt;/p&gt;
&lt;p&gt;The purpose of this language are mainly to build software and launch
shell environments.&lt;/p&gt;
&lt;p&gt;Let’s break it down:&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;nix&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color:#A018FF;font-style:italic&quot;&gt; pkgs&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt; ?&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; import&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt; &amp;lt;nixpkgs&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt; {}}:&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;                           # (1)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;let&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C99&quot;&gt;  pythonEnv&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; pkgs&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;python38&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;withPackages &lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#A018FF;font-style:italic&quot;&gt;ps&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;          # (2)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;    # Scientific python essentials&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;    ps&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;numpy&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;    ps&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;scipy&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;    ps&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;pandas&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;    ps&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;matplotlib&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;    # Grab samples from the net via Python&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;    ps&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;requests&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;    ps&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;beautifulsoup4&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;    # Need this to make the samples more bearable&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;    ps&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;nltk&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;    # Notebook editing&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;    ps&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;jupyter&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;    ps&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;ipython&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;  ]);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;in&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;pkgs&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;mkShell &lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;                                           # (3)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C99&quot;&gt;  packages&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;                                           # (4)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;    pythonEnv&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;    pkgs&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;wget&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;    pkgs&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;curl&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;    pkgs&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;httpie&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;    pkgs&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;youtube-dl&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;    pkgs&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;ffmpeg&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;  ];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;In this line, we’re importing the &lt;a href=&quot;https://github.com/NixOS/nixpkgs&quot;&gt;Nix package collection&lt;/a&gt; (nixpkgs).&lt;/p&gt;
&lt;p&gt;Reading it, you might think this is how you define imports but
actually, this is how you define lambda functions in Nix.&lt;/p&gt;
&lt;p&gt;Your &lt;code&gt;shell.nix&lt;/code&gt; file actually define a single function which takes
&lt;code&gt;pkgs&lt;/code&gt; as an argument but also provide a default value.&lt;/p&gt;
&lt;p&gt;This is practically similar to the following example in Python:&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F40064&quot;&gt;def&lt;/span&gt;&lt;span style=&quot;color:#0057D1&quot;&gt; shell&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#A018FF;font-style:italic&quot;&gt;pkgs&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;import_pkgs&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;()):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;    ...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Nix is a functional programming language so variables are defined
inside a &lt;code&gt;let&lt;/code&gt; block. These variables will be exposed inside the &lt;code&gt;in&lt;/code&gt;
block.&lt;/p&gt;
&lt;p&gt;We define a variable called &lt;code&gt;pythonEnv&lt;/code&gt; which takes the result of the
&lt;code&gt;pkgs.python38.withPackages&lt;/code&gt; function. This function returns an
altered Python package with the Python libraries we’ve defined.&lt;/p&gt;
&lt;p&gt;Function calls in Nix doesn’t use parentheses similar to Haskell
and Ruby. You simply pass the arguments to it separated by
whitespaces.&lt;/p&gt;
&lt;p&gt;The argument we pass is actually another function which takes a
single argument called &lt;code&gt;ps&lt;/code&gt; and returns a list of Python
libraries/packages.&lt;/p&gt;
&lt;p&gt;You might be confused why it needs to be a function and that’s
because this allows multiple Python versions since not all Python
versions share the same collection of packages.&lt;/p&gt;
&lt;p&gt;You can test this theory yourself: Replace &lt;code&gt;python38&lt;/code&gt; with
&lt;code&gt;python39&lt;/code&gt; and run &lt;code&gt;nix-shell&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;nix&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color:#A018FF;font-style:italic&quot;&gt; pkgs&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt; ?&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; import&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt; &amp;lt;nixpkgs&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt; {}}:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;let&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C99&quot;&gt;  pythonEnv&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; pkgs&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;python39&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;withPackages &lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#A018FF;font-style:italic&quot;&gt;ps&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt; [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;    # Scientific python essentials&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;    ps&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;numpy&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;    ...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Now that we have &lt;code&gt;pythonEnv&lt;/code&gt; nicely defined in the &lt;code&gt;let&lt;/code&gt; block, we can
use it inside the &lt;code&gt;in&lt;/code&gt; block.&lt;/p&gt;
&lt;p&gt;Here we’re calling the &lt;code&gt;pkgs.mkShell&lt;/code&gt; function which allow us to make
a shell environment with Nix.&lt;/p&gt;
&lt;p&gt;As you can see from the one marked &lt;code&gt;(2)&lt;/code&gt; and this one, functions
don’t require the &lt;code&gt;return&lt;/code&gt; keyword and will return the enclosed
expression.&lt;/p&gt;
&lt;p&gt;This is similar to Haskell and Ruby.&lt;/p&gt;
&lt;p&gt;In this case, our massive &lt;code&gt;shell.nix&lt;/code&gt; function returns the result of
&lt;code&gt;pkgs.mkShell&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;In here, we simply define the packages the shell environment need
to contain.&lt;/p&gt;
&lt;p&gt;We pass our &lt;code&gt;pythonEnv&lt;/code&gt; package and lists more packages which are
non-Python utilities/libraries that are helpful to us.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h1 id=&quot;reducing-duplicate-code-using-the-with-statement&quot;&gt;Reducing duplicate code using the &lt;code&gt;with&lt;/code&gt; statement&lt;/h1&gt;
&lt;p&gt;Reading the &lt;code&gt;shell.nix&lt;/code&gt;, you might be annoyed by its repetitiveness such
as the repeating &lt;code&gt;ps&lt;/code&gt; and &lt;code&gt;pkgs&lt;/code&gt; scattered everywhere.&lt;/p&gt;
&lt;p&gt;The Nix expression language provides you with a helpful tool: the &lt;code&gt;with&lt;/code&gt;
statement.&lt;/p&gt;
&lt;p&gt;Here’s an example of it in use:&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;nix&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color:#A018FF;font-style:italic&quot;&gt; pkgs&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt; ?&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; import&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt; &amp;lt;nixpkgs&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt; {}}:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;let&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C99&quot;&gt;  pythonEnv&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; pkgs&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;python38&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;withPackages &lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#A018FF;font-style:italic&quot;&gt;ps&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#D17C00&quot;&gt; with&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; ps; &lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;[&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;    # Scientific python essentials&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;    numpy&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;    scipy&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;    pandas&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;    matplotlib&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;    # Grab samples from the net via Python&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;    requests&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;    beautifulsoup4&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;    # Need this to make the samples more bearable&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;    nltk&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;    # Notebook editing&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;    jupyter&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;    ipython&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;  ]);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;in&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;pkgs&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;mkShell &lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C99&quot;&gt;  packages&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#D17C00&quot;&gt; with&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; pkgs; &lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;[&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;    pythonEnv&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;    wget&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;    curl&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;    httpie&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;    youtube-dl&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;    ffmpeg&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;  ];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can see, using the &lt;code&gt;with&lt;/code&gt; statement we can omit the &lt;code&gt;pkgs&lt;/code&gt; and &lt;code&gt;ps&lt;/code&gt;,
nice.&lt;/p&gt;
&lt;p&gt;What it does is simply pepper in the &lt;code&gt;pkgs.&lt;/code&gt; and &lt;code&gt;ps.&lt;/code&gt; when it is
required.&lt;/p&gt;
&lt;p&gt;If you’re still confused, we’ll demonstrate it by taking a part of the
previous snippet:&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;nix&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F40064;font-style:italic&quot;&gt;in&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;pkgs&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;mkShell &lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C99&quot;&gt;  packages&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#D17C00&quot;&gt; with&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; pkgs; &lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;[&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;    pythonEnv&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;    wget&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;    curl&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;    httpie&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;    youtube-dl&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;    ffmpeg&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;  ];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When Nix sees the &lt;code&gt;with&lt;/code&gt; statement, it will add the &lt;code&gt;pkgs&lt;/code&gt; prefix when
required.&lt;/p&gt;
&lt;p&gt;This is how Nix will evaluate the &lt;code&gt;with&lt;/code&gt; statement to:&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;nix&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F40064;font-style:italic&quot;&gt;in&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;pkgs&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;mkShell &lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C99&quot;&gt;  packages&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt; [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;    pythonEnv&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;    pkgs&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;wget&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;    pkgs&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;curl&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;    pkgs&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;httpie&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;    pkgs&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;youtube-dl&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;    pkgs&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;ffmpeg&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;  ];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Nix simply checks whether each variable exists. If not, it will add the
&lt;code&gt;pkgs&lt;/code&gt; prefix. If it exists, it will leave them alone.&lt;/p&gt;
&lt;p&gt;In fact, we can go even further and remove all mention of pkgs using a
single &lt;code&gt;with&lt;/code&gt; statement:&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;nix&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color:#A018FF;font-style:italic&quot;&gt; pkgs&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt; ?&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; import&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt; &amp;lt;nixpkgs&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt; {}}:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;with&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; pkgs;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;let&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C99&quot;&gt;  pythonEnv&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; python38&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;withPackages &lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#A018FF;font-style:italic&quot;&gt;ps&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#D17C00&quot;&gt; with&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; ps; &lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;[&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;    # Scientific python essentials&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;    numpy&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;    scipy&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;    pandas&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;    matplotlib&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;    # Grab samples from the net via Python&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;    requests&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;    beautifulsoup4&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;    # Need this to make the samples more bearable&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;    nltk&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;    # Notebook editing&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;    jupyter&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;    ipython&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;  ]);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;in&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;mkShell &lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C99&quot;&gt;  packages&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt; [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;    pythonEnv&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;    wget&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;    curl&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;    httpie&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;    youtube-dl&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;    ffmpeg&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;  ];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h1 id=&quot;learning-more-about-the-nix-expression-language&quot;&gt;Learning more about the Nix expression language&lt;/h1&gt;
&lt;p&gt;It might be difficult for you to wrap your head around the weird
language, especially if you’re not familiar with functional
programming.&lt;/p&gt;
&lt;p&gt;Don’t worry, you will get used to it soon enough.&lt;/p&gt;
&lt;p&gt;To follow this and future articles in the series, you don’t need to
master the Nix expression language. This series targeted to those who
have 0 knowledge about Nix but have &lt;em&gt;some&lt;/em&gt; experience in programming.&lt;/p&gt;
&lt;p&gt;However, if you want to learn more about the language itself, check
out &lt;a href=&quot;https://nixos.org/guides/nix-pills/basics-of-language.html&quot;&gt;Nix pills&lt;/a&gt;, &lt;a href=&quot;https://nixos.wiki/wiki/Nix_Expression_Language&quot;&gt;Nix wiki&lt;/a&gt;, and &lt;a href=&quot;https://nixos.org/manual/nix/stable/#ch-expression-language&quot;&gt;Nix manual&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;You can also learn by reading the packages inside the &lt;a href=&quot;https://github.com/NixOS/nixpkgs&quot;&gt;Nix package
collection&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;You can search via &lt;a href=&quot;https://search.nixos.org/packages&quot;&gt;search.nixos.org&lt;/a&gt; and click on “Source” on the
result:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/_astro/search-nix-source.BsKKNx6l_2aNuJG.webp&quot; alt=&quot;Result of &apos;waffle&apos; in search.nixos.org with the source link highlighted&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; width=&quot;1234&quot; height=&quot;671&quot;&gt;&lt;/p&gt;
&lt;h1 id=&quot;where-does-nixpkgs-come-from&quot;&gt;Where does &lt;code&gt;nixpkgs&lt;/code&gt; come from?&lt;/h1&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;nix&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color:#A018FF;font-style:italic&quot;&gt; pkgs&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt; ?&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; import&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt; &amp;lt;nixpkgs&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt; {}}:&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Reading the snippet above, you might wonder where &lt;code&gt;nixpkgs&lt;/code&gt; is located.&lt;/p&gt;
&lt;p&gt;The answer to that is simple: Nix channels.&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;console&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; nix-channel --list&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;nixpkgs https://nixos.org/channels/nixos-21.05&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Nix channel is similar to the list of repositories that can be found
in other package managers (ex. &lt;code&gt;/etc/apt/sources.list&lt;/code&gt; in
Debian/Ubuntu).&lt;/p&gt;
&lt;p&gt;This is all well and good but there’s you will encounter the following
issue: Each Nix user may have different versions &lt;code&gt;nixpkgs&lt;/code&gt; present.&lt;/p&gt;
&lt;p&gt;As of writing, I’m running version 21.05 of &lt;code&gt;nixpkgs&lt;/code&gt; but you might be
using a newer version of &lt;code&gt;nixpkgs&lt;/code&gt; or maybe even the &lt;code&gt;unstable&lt;/code&gt; branch.&lt;/p&gt;
&lt;p&gt;This means that your shell environment may break in the future because
nixpkgs will be different or it will break on someone else’s machine
because they have a different value for nixpkgs.&lt;/p&gt;
&lt;h1 id=&quot;ensuring-reproducibility-by-pinning-with-niv&quot;&gt;Ensuring reproducibility by pinning with &lt;code&gt;niv&lt;/code&gt;&lt;/h1&gt;
&lt;p&gt;Package managers such as npm solves this issue by introducing
dependency pinning.&lt;/p&gt;
&lt;p&gt;Essentially, your will have something called a lock file which
accompanies your list of dependencies.&lt;/p&gt;
&lt;p&gt;The lock file contains the same list of dependencies but in addition,
it contains the exact version used when you were defining the
dependencies for your project.&lt;/p&gt;
&lt;p&gt;This ensures that in the future, you will use the exact same set of
dependencies which introduces reproducibility.&lt;/p&gt;
&lt;p&gt;With Nix since most of your packages will originate from &lt;code&gt;nixpkgs&lt;/code&gt;, you
only need to pin &lt;code&gt;nixpkgs&lt;/code&gt; itself.&lt;/p&gt;
&lt;p&gt;As of writing, Nix does not have this functionality built-in. However,
it is available as an experimental feature called &lt;a href=&quot;https://www.tweag.io/blog/2020-05-25-flakes/&quot;&gt;flakes&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Because flakes is still experimental, in this article, we will use &lt;a href=&quot;https://github.com/nmattia/niv&quot;&gt;Niv&lt;/a&gt;
instead which adds dependency pinning to Nix.&lt;/p&gt;
&lt;p&gt;You can install niv easily by running the following command:&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;console&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; nix-env -iA nixpkgs.niv&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you don’t want to install and just want to use it temporarily, you
can launch a Nix shell with only niv installed:&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;console&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; nix-shell -p niv&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We will be modifying &lt;code&gt;shell.nix&lt;/code&gt; and introduce dependency pinning.&lt;/p&gt;
&lt;p&gt;Open a terminal with Niv present and navigate to the folder with
the deduplicated version of &lt;code&gt;shell.nix&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;First, we run &lt;code&gt;niv init&lt;/code&gt; to start the setup process:&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;console&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; ls&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;shell.nix&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; niv init&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Initializing&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  Creating nix/sources.nix&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  Creating nix/sources.json&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  Importing &amp;#39;niv&amp;#39; ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  Adding package niv&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;    Writing new sources file&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  Done: Adding package niv&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  Importing &amp;#39;nixpkgs&amp;#39; ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  Adding package nixpkgs&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;    Writing new sources file&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  Done: Adding package nixpkgs&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Done: Initializing&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; ls&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;nix  shell.nix&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; ls nix&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;sources.json  sources.nix&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Niv has started a new Niv project and added both &lt;code&gt;nixpkgs&lt;/code&gt; and &lt;code&gt;niv&lt;/code&gt; as
dependencies.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;nix/sources.nix&lt;/code&gt; file is a small vendored library which reads the
&lt;code&gt;nix/sources.json&lt;/code&gt;. You will see how it is used later.&lt;/p&gt;
&lt;p&gt;The dependencies are listed in &lt;code&gt;nix/sources.json&lt;/code&gt; and you can use &lt;code&gt;niv show&lt;/code&gt; to see what’s inside:&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;console&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; niv show&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;nixpkgs&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  homepage:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  url: https://github.com/NixOS/nixpkgs/archive/eb73405ecceb1dc505b7cbbd234f8f94165e2696.tar.gz&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  owner: NixOS&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  branch: release-20.03&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  url_template: https://github.com/&amp;lt;owner&amp;gt;/&amp;lt;repo&amp;gt;/archive/&amp;lt;rev&amp;gt;.tar.gz&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  repo: nixpkgs&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  type: tarball&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  sha256: 06k21wbyhhvq2f1xczszh3c2934p0m02by3l2ixvd6nkwrqklax7&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  description: Nix Packages collection&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  rev: eb73405ecceb1dc505b7cbbd234f8f94165e2696&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;niv&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  homepage: https://github.com/nmattia/niv&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  url: https://github.com/nmattia/niv/archive/e0ca65c81a2d7a4d82a189f1e23a48d59ad42070.tar.gz  owner: nmattia&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  branch: master&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  url_template: https://github.com/&amp;lt;owner&amp;gt;/&amp;lt;repo&amp;gt;/archive/&amp;lt;rev&amp;gt;.tar.gz&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  repo: niv&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  type: tarball&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  sha256: 1pq9nh1d8nn3xvbdny8fafzw87mj7gsmp6pxkdl65w2g18rmcmzx&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  description: Easy dependency management for Nix projects&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  rev: e0ca65c81a2d7a4d82a189f1e23a48d59ad42070&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can see, it pins both nixpkgs and niv to an exact version, see
the &lt;code&gt;url&lt;/code&gt; and &lt;code&gt;rev&lt;/code&gt; which targets a specific commit.&lt;/p&gt;
&lt;p&gt;However, if you take a look inside nixpkgs’s branch, you see that it
uses the 20.03 version.&lt;/p&gt;
&lt;p&gt;That’s very outdated. Let’s fix that and update it to 21.05.&lt;/p&gt;
&lt;p&gt;We can update dependencies with &lt;code&gt;niv update&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;console&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; niv update nixpkgs -b release-21.05&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Update nixpkgs&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Done: Update nixpkgs&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; niv show&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;nixpkgs&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  homepage:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  url: https://github.com/NixOS/nixpkgs/archive/2d6ab6c6b92f7aaf8bc53baba9754b9bfdce56f2.tar.gz&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  owner: NixOS&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  branch: release-21.05&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  url_template: https://github.com/&amp;lt;owner&amp;gt;/&amp;lt;repo&amp;gt;/archive/&amp;lt;rev&amp;gt;.tar.gz&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  repo: nixpkgs&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  type: tarball&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  sha256: 1aafqly1mcqxh0r15mrlsrs4znldhm7cizsmfp3d25lqssay6gjd&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  description: Nix Packages collection&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  rev: 2d6ab6c6b92f7aaf8bc53baba9754b9bfdce56f2&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Wonderful.&lt;/p&gt;
&lt;p&gt;However, we are not done yet. &lt;code&gt;shell.nix&lt;/code&gt; didn’t import the nixpkgs
defined in &lt;code&gt;nix/sources.json&lt;/code&gt;. Let’s modify it.&lt;/p&gt;
&lt;p&gt;This is how we import nixpkgs from &lt;code&gt;nix/sources.nix&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;nix&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;let&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;  # Use nixpkgs from Niv&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C99&quot;&gt;  sources&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; import&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt; ./nix/sources.nix&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;                     # (1) We import the sources.nix library.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C99&quot;&gt;  pkgs&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; import&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; sources&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;nixpkgs &lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;{};&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;                       # (2) We import nixpkgs from it.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C99&quot;&gt;  pythonEnv&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; pkgs&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;python38&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;withPackages &lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#A018FF;font-style:italic&quot;&gt;ps&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#D17C00&quot;&gt; with&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; ps; &lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;  # (3) This needs pkgs to be added explicitly&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;    ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;  ]);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;in&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;with&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; pkgs;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;mkShell &lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;  ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can see the lambda function definition is replaced by defining
&lt;code&gt;pkgs&lt;/code&gt; as a variable inside the let block.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;The &lt;code&gt;nix/sources.nix&lt;/code&gt; library is imported and assigned as the &lt;code&gt;sources&lt;/code&gt;
variable.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;nix/sources.nix&lt;/code&gt; returns a set of the dependencies as defined inside
&lt;code&gt;nix/sources.json&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;We take &lt;code&gt;nixpkgs&lt;/code&gt; from &lt;code&gt;sources&lt;/code&gt; and import it.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;We also moved &lt;code&gt;with pkgs;&lt;/code&gt; inside the in block.&lt;/p&gt;
&lt;p&gt;This is because we can’t put &lt;code&gt;with pkgs;&lt;/code&gt; midway in our let block and
pkgs is only exposed inside the in block.&lt;/p&gt;
&lt;p&gt;Because of this, we readd the &lt;code&gt;pkgs&lt;/code&gt; prefix for &lt;code&gt;pythonEnv&lt;/code&gt;. Nothing is
changed in the &lt;code&gt;mkShell&lt;/code&gt; thanks to &lt;code&gt;with pkgs;&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;With all of this in place, we can be certain that our shell
environment is reproducible even in the future with newer versions of
nixpkgs.&lt;/p&gt;
&lt;p&gt;Let’s take a test drive:&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;console&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; cat shell.nix&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;let&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  # Use nixpkgs from Niv&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  sources = import ./nix/sources.nix;  # We import the sources.nix library.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  pkgs = import sources.nixpkgs {};    # We import nixpkgs from it.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; nix-shell&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;this derivation will be built:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  /nix/store/mc3lh57blikblbrj19m17cyh5c5qaprp-python3-3.8.9-env.drv&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;these 239 paths will be fetched (156.50 MiB download, 857.66 MiB unpacked):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  /nix/store/04b8w8yy6qzvdbrn3rsqkc9splcvs0cj-python3.8-kiwisolver-1.3.1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  /nix/store/zzv3axnas822sm1h05y0r9djnk73m4kj-libICE-1.0.10&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;copying path &amp;#39;/nix/store/i7ra1fy8gxcmvpzzxihy25hd3jspzvpw-curl-7.76.1-man&amp;#39; from &amp;#39;https://cache.nixos.org&amp;#39;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;copying path &amp;#39;/nix/store/rcbkp2r2ifnll4b8hxjwd5yzxr9dvvk0-python3.8-jupyter-1.0.0&amp;#39; from &amp;#39;https://cache.nixos.org&amp;#39;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;building &amp;#39;/nix/store/mc3lh57blikblbrj19m17cyh5c5qaprp-python3-3.8.9-env.drv&amp;#39;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;created 644 symlinks in user environment&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;[nix-shell:~/trash/python-science]&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; python&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Python 3.8.9 (default, Apr  2 2021, 11:20:07)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;[GCC 10.3.0] on linux&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Type &amp;quot;help&amp;quot;, &amp;quot;copyright&amp;quot;, &amp;quot;credits&amp;quot; or &amp;quot;license&amp;quot; for more information.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;&amp;gt;&amp;gt;&amp;gt; import nltk&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;[nix-shell:~/trash/python-science]&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; jupyter --version&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;jupyter core     : 4.7.1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;jupyter-notebook : 6.3.0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;qtconsole        : 5.0.3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;ipython          : 7.21.0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;ipykernel        : 5.5.0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;jupyter client   : 6.1.12&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;jupyter lab      : not installed&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;nbconvert        : 6.0.7&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;ipywidgets       : 7.6.3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;nbformat         : 5.1.2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;traitlets        : 5.0.5&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Awesome, it’s up and running again!&lt;/p&gt;
&lt;p&gt;You can even downgrade to an older version of nixpkgs with &lt;code&gt;niv update&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;console&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; niv update nixpkgs -b release-20.09&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Update nixpkgs&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Done: Update nixpkgs&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; nix-shell&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;these 2 derivations will be built:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  /nix/store/7zw4ijckcacgij9jqfa9wjinh7qa7b7v-builder.pl.drv&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  /nix/store/6lmimxdpdgxr6wsa3y2fpy2n79wvmg81-python3-3.8.8-env.drv&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;these 344 paths will be fetched (266.92 MiB download, 1345.74 MiB unpacked):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  /nix/store/021jdajrghabnh8p6rvqidgr04rjahrz-gdk-pixbuf-2.40.0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  /nix/store/zxp8i14r9ngq8hmbbb9h4x4mhmxiyvy2-python3.8-nbformat-5.0.7&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;copying path &amp;#39;/nix/store/ma08l3jqjhx8b4400x1bb5kvzjb500dp-python3.8-pyOpenSSL-19.1.0&amp;#39; from &amp;#39;https://hydra.iohk.io&amp;#39;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;copying path &amp;#39;/nix/store/rj663ln3skd12irz0z0sx133p065v4a8-python3.8-jupyter-1.0.0&amp;#39; from &amp;#39;https://cache.nixos.org&amp;#39;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;building &amp;#39;/nix/store/6lmimxdpdgxr6wsa3y2fpy2n79wvmg81-python3-3.8.8-env.drv&amp;#39;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;created 640 symlinks in user environment&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;[nix-shell:~/trash/python-science]&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; python&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Python 3.8.9 (default, Apr  2 2021, 11:20:07)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;[GCC 10.3.0] on linux&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Type &amp;quot;help&amp;quot;, &amp;quot;copyright&amp;quot;, &amp;quot;credits&amp;quot; or &amp;quot;license&amp;quot; for more information.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;&amp;gt;&amp;gt;&amp;gt; import nltk&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Traceback (most recent call last):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  File &amp;quot;&amp;lt;stdin&amp;gt;&amp;quot;, line 1, in &amp;lt;module&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;ModuleNotFoundError: No module named &amp;#39;nltk&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;[nix-shell:~/trash/python-science]&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; jupyter --version&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;The program &amp;#39;jupyter&amp;#39; is not in your PATH. It is provided by several packages.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;You can make it available in an ephemeral shell by typing one of the following:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  nix-shell -p ihaskell&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  nix-shell -p python38Packages.jupyter_core&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  nix-shell -p python39Packages.jupyter_core&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Wait, it failed?&lt;/p&gt;
&lt;p&gt;Also, it’s Python 3.8.9, not 3.8.8.&lt;/p&gt;
&lt;p&gt;Oh, it’s because the &lt;code&gt;packages&lt;/code&gt; argument in &lt;code&gt;pkgs.mkShell&lt;/code&gt; was introduced
in nixpkgs version 21.05 and isn’t present in version 20.09.&lt;/p&gt;
&lt;p&gt;Let’s fix that by replacing the &lt;code&gt;packages&lt;/code&gt; argument in pkgs.mkShell to
&lt;code&gt;buildInputs&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;nix&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;let&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;  ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;in&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;with&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; pkgs;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;mkShell &lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;  # We change from `packages&amp;#39; to `buildInputs&amp;#39;.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;  # Don&amp;#39;t ask why it was called that for `pkgs.mkShell&amp;#39;.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C99&quot;&gt;  buildInputs&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt; [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;    pythonEnv&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;    ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;  ];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Let’s test it out:&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;console&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; nix-shell&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;these 12 paths will be fetched (1.63 MiB download, 7.00 MiB unpacked):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  /nix/store/3354dzy157x0kijm6pv5khzfx6hf5h8n-nghttp2-1.41.0-dev&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  /nix/store/yi6x0zkhyl6g516c97q1cazpfvv11j4a-curl-7.74.0-dev&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;copying path &amp;#39;/nix/store/is2d41x8qkx4gd27i8r45q45kv0dynbn-curl-7.74.0-man&amp;#39; from &amp;#39;https://hydra.iohk.io&amp;#39;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;copying path &amp;#39;/nix/store/yi6x0zkhyl6g516c97q1cazpfvv11j4a-curl-7.74.0-dev&amp;#39; from &amp;#39;https://hydra.iohk.io&amp;#39;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;[nix-shell:~/trash/python-science]&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; python&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Python 3.8.8 (default, Feb 19 2021, 11:04:50)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;[GCC 9.3.0] on linux&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Type &amp;quot;help&amp;quot;, &amp;quot;copyright&amp;quot;, &amp;quot;credits&amp;quot; or &amp;quot;license&amp;quot; for more information.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;&amp;gt;&amp;gt;&amp;gt; import nltk&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;[nix-shell:~/trash/python-science]&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; jupyter&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;usage: jupyter [-h] [--version] [--config-dir] [--data-dir] [--runtime-dir] [--paths] [--json] [subcommand]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;jupyter: error: one of the arguments --version subcommand --config-dir --data-dir --runtime-dir --paths is required&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;[nix-shell:~/trash/python-science]&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; jupyter --version&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;jupyter core     : 4.6.3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;jupyter-notebook : 6.1.4&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;qtconsole        : 4.7.6&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;ipython          : 7.17.0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;ipykernel        : 5.2.1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;jupyter client   : 6.1.7&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;jupyter lab      : not installed&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;nbconvert        : 5.6.1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;ipywidgets       : 7.5.1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;nbformat         : 5.0.7&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;traitlets        : 4.3.3&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Cool, it works.&lt;/p&gt;
&lt;p&gt;As you can see, it’s quite important to pin your dependencies in order
to ensure reproducibility.&lt;/p&gt;
&lt;p&gt;You would rather not have things broken at random simply because of
factors that you are not aware of.&lt;/p&gt;
&lt;p&gt;Also, people can use the shell environment without having Niv
installed on their machine. They only require to have Nix installed on
their machine.&lt;/p&gt;
&lt;p&gt;This is thanks to the vendored library which allows Nix to read the
&lt;code&gt;nix/sources.json&lt;/code&gt; file.&lt;/p&gt;
&lt;h1 id=&quot;closing&quot;&gt;Closing&lt;/h1&gt;
&lt;p&gt;This is the second article in my series about Nix. Hurrah!&lt;/p&gt;
&lt;p&gt;As you can see, this series aims for a more practical approach which
can serve as references to people who are new to Nix.&lt;/p&gt;
&lt;p&gt;Or to put it in another way, this link of this article will be copy
pasted by me everytime someone ask ‘how do I XYZ with Nix?” ;)&lt;/p&gt;
&lt;p&gt;Let me know what you think so far, my contacts are available in
&lt;a href=&quot;https://yukiisbo.red&quot;&gt;yukiisbo.red&lt;/a&gt; (Discord is rather inactive, though).&lt;/p&gt;
&lt;p&gt;Thanks for reading and I hope you’ll be there on the next one!&lt;/p&gt;
&lt;h1 id=&quot;remarks&quot;&gt;Remarks&lt;/h1&gt;
&lt;p&gt;I should’ve done this much earlier but I never thought about doing it
until now. Sorry about that.&lt;/p&gt;
&lt;p&gt;I would like to thank to those who has reviewed and given me their
input during the writing of this article:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Ben Siraphob (&lt;a href=&quot;https://github.com/siraben&quot;&gt;@siraben&lt;/a&gt; at GitHub)&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title>Mic Check</title><link>https://yukiisbo.red/notes/mic-check/</link><guid isPermaLink="true">https://yukiisbo.red/notes/mic-check/</guid><pubDate>Sat, 17 Dec 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Test, test, hello, is this thing still on?&lt;/p&gt;
&lt;p&gt;I’ve recently made a big shift on this website by moving from &lt;a href=&quot;https://orgmode.org&quot;&gt;org-mode&lt;/a&gt; to
&lt;a href=&quot;https://gatsbyjs.com/&quot;&gt;Gatsby&lt;/a&gt; and merge it with &lt;a href=&quot;https://yukiisbo.red&quot;&gt;yukiisbo.red&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id=&quot;why-move-away-from-org-mode&quot;&gt;Why move away from org-mode?&lt;/h1&gt;
&lt;p&gt;While I still prefer org-mode to write plain-text documents, its ecosystem for
creating a complete static website (i.e. not just a single page HTML document)
to be very lacking and require additional engineering work.&lt;/p&gt;
&lt;p&gt;I’ve made &lt;a href=&quot;https://github.com/yukiisbored/dot/blob/e5cd9a2daa881211620a853ceed14e4620767944/doom/.doom.d/config.el#L30-L165&quot;&gt;one&lt;/a&gt; before using &lt;a href=&quot;https://orgmode.org/manual/Publishing.html&quot;&gt;org-publish&lt;/a&gt; and following a
write-up by &lt;a href=&quot;https://iotcl.com&quot;&gt;Toon Claes&lt;/a&gt; for his blog &lt;a href=&quot;https://writepermission.com&quot;&gt;writepermission.com&lt;/a&gt;. It works well for
the most part and I used that for a while.&lt;/p&gt;
&lt;p&gt;However, while it was nice that my blog reflects my Emacs configuration but it
has lead to a mountain of annoyances which results in requiring a mountain of
&lt;a href=&quot;https://github.com/yukiisbored/dot/commit/73b2fb607f9d65fdd4f7c3bcce6eb5f286d4e13f#d02f092fbb5b886b250c938b8cac972ef49a22ef_195_191&quot;&gt;hacks to tame this dynamic&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In addition, embedding content other than text with this setup is painful which
led me to barely use mediums other than text in my posts.&lt;/p&gt;
&lt;p&gt;While this whole thing isn’t an excuse for me to be on a long hiatus in terms of
writing, it left a nagging feeling in my mind for a long time and became one of
the main deterrents when writing.&lt;/p&gt;
&lt;h1 id=&quot;what-led-me-to-move-away-from-org-mode-to-gatsby&quot;&gt;What led me to move away from org-mode to Gatsby?&lt;/h1&gt;
&lt;p&gt;Recently, I started working with the &lt;a href=&quot;https://nixos.org/community/teams/documentation.html&quot;&gt;Nix Documentation Team&lt;/a&gt; on &lt;a href=&quot;https://nix.dev&quot;&gt;nix.dev&lt;/a&gt; which
uses the &lt;a href=&quot;https://www.sphinx-doc.org/en/master/&quot;&gt;Sphinx&lt;/a&gt; static site generator. I’m not a stranger to it as I worked
with it when I was working in the &lt;a href=&quot;https://github.com/coala/coala&quot;&gt;coala&lt;/a&gt; project. While it’s not perfect, I
felt more productive using it.&lt;/p&gt;
&lt;p&gt;It led me to consider dropping org-mode for my website. I was considering
&lt;a href=&quot;https://ablog.readthedocs.io/&quot;&gt;ablog&lt;/a&gt; which is an extension for Sphinx to make it for blogging. That felt like
a hack so I put it at the back burner.&lt;/p&gt;
&lt;p&gt;Then, I got reminded of &lt;a href=&quot;https://gatsbyjs.com/&quot;&gt;Gatsby&lt;/a&gt; which is a static site generator that uses &lt;a href=&quot;https://reactjs.org/&quot;&gt;React&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id=&quot;why-gatsby&quot;&gt;Why Gatsby?&lt;/h1&gt;
&lt;p&gt;I typically avoid &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks&quot;&gt;client-side frameworks&lt;/a&gt; (CSF) as they tend to bloat the website with a
mountain of unnecessary JavaScript and render the website unusable for people
who doesn’t use JavaScript using extensions like &lt;a href=&quot;https://noscript.net&quot;&gt;NoScript&lt;/a&gt; or “limited” web
browsers like &lt;a href=&quot;https://www.netsurf-browser.org&quot;&gt;NetSurf&lt;/a&gt; and &lt;a href=&quot;https://lynx.browser.org&quot;&gt;Lynx&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;However, it seems a lot of things has changed in the frontend world. &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Glossary/SPA&quot;&gt;Single Page
Application&lt;/a&gt; (SPA), where JavaScript is necessary to render entire web pages
client-side, has stopped becoming the only thing available when using CSFs to
create entire websites.&lt;/p&gt;
&lt;p&gt;I have heard of &lt;a href=&quot;https://www.gatsbyjs.com/docs/conceptual/rendering-options/#server-side-rendering-ssr&quot;&gt;Server Side Rendering&lt;/a&gt; (SSR) before but I tend to not use them
as they used to be really complicated. Even then, the idea of running a server
that does computation to build web pages on the fly from JavaScript code is
overkill. Especially when those pages would’ve been static HTML documents if it
wasn’t for CSFs.&lt;/p&gt;
&lt;p&gt;However, today, &lt;a href=&quot;https://www.gatsbyjs.com/docs/conceptual/rendering-options/#static-site-generation-ssg&quot;&gt;Static Site Generation&lt;/a&gt; (SSG) with CSFs has become a lot more
accessible, thanks to tools like Gatsby and &lt;a href=&quot;https://kit.svelte.dev&quot;&gt;SvelteKit&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This approach essentially boils your components written in JavaScript with CSFs
to static HTML first and then introduces bits of JavaScript on top of them.&lt;/p&gt;
&lt;p&gt;Therefore, it makes JavaScript not a requirement for visitors while still
allowing you to still use the rich ecosystem of CSFs.&lt;/p&gt;
&lt;p&gt;Before you had to use tools like &lt;a href=&quot;https://jekyllrb.com&quot;&gt;Jekyll&lt;/a&gt;, &lt;a href=&quot;https://gohugo.io&quot;&gt;Hugo&lt;/a&gt;, and others which I never
liked mainly because they tend to force your hand to follow their pre-built
structures or use a [terrible template language].&lt;/p&gt;
&lt;p&gt;To be fair, I dislike every single template language (ex. &lt;a href=&quot;https://pypi.org/project/Jinja2/&quot;&gt;Jinja2&lt;/a&gt; and &lt;a href=&quot;https://www.gnu.org/software/m4/&quot;&gt;m4&lt;/a&gt;)
because they essentially work like a parasite whose terrible language embeds
itself inside your documents (HTML markup or even source code). In addition,
they’re unaware of what they’re actually manipulating other than they’re just
plain text files, therefore unaware of details in your document like semantics.&lt;/p&gt;
&lt;p&gt;I personally prefer an approach with &lt;a href=&quot;https://en.wikipedia.org/wiki/Domain-specific_language&quot;&gt;domain-specific languages&lt;/a&gt; (DSL) where you
represent your problem using a purpose-built language for the domain. You can
see this in action with tools such as &lt;a href=&quot;https://dhall-lang.org&quot;&gt;Dhall&lt;/a&gt;, &lt;a href=&quot;https://hackage.haskell.org/package/lucid&quot;&gt;Lucid&lt;/a&gt;, &lt;a href=&quot;https://laravel.com/docs/9.x/queries&quot;&gt;Laravel’s Query Builder&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Naturally, I like &lt;a href=&quot;https://reactjs.org/docs/introducing-jsx.html&quot;&gt;JSX&lt;/a&gt; which is an HTML embedded domain-specific language that
boils down into JavaScript expressions that generates &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Glossary/DOM&quot;&gt;HTML DOM&lt;/a&gt;. This is
possible thanks to &lt;a href=&quot;https://babeljs.io&quot;&gt;Babel&lt;/a&gt; using a &lt;a href=&quot;https://babeljs.io/docs/en/babel-plugin-transform-react-jsx#docsNav&quot;&gt;transformer&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Because at the end of the day it’s just JavaScript extensions, you can &lt;a href=&quot;https://reactjs.org/docs/lists-and-keys.html#rendering-multiple-components&quot;&gt;reuse
the capabilities&lt;/a&gt; of the JavaScript language and libraries to manipulate DOMs.&lt;/p&gt;
&lt;p&gt;In addition, the &lt;a href=&quot;https://www.typescriptlang.org/docs/handbook/jsx.html#basic-usage&quot;&gt;TypeScript version&lt;/a&gt; (TSX) introduces &lt;a href=&quot;https://www.typescriptlang.org/docs/handbook/jsx.html#type-checking&quot;&gt;types&lt;/a&gt; to JSX (and HTML)
which makes it really pleasant to use.&lt;/p&gt;
&lt;p&gt;In conclusion, I use Gatsby because it allows me to use the React ecosystem
while still making the site usable to those who prefer to not run JavaScript.&lt;/p&gt;
&lt;h1 id=&quot;why-javascript&quot;&gt;Why JavaScript?&lt;/h1&gt;
&lt;p&gt;A lot of people will disagree with my choice as they simply dislike/hate
JavaScript and refuse to use anything from its ecosystem.&lt;/p&gt;
&lt;p&gt;Recently, I’ve grown to dislike &lt;a href=&quot;https://en.wikipedia.org/wiki/Dogma&quot;&gt;dogmas&lt;/a&gt; (ex. JavaScript sucks and harmful).&lt;/p&gt;
&lt;p&gt;By their nature, they blanket over a large scope without actually giving any
meaningful thought other than writing long winded rant-ridden opinionated essays
on “why &lt;code&gt;$THING&lt;/code&gt; sucks and harmful”.&lt;/p&gt;
&lt;p&gt;I believe it’s much more productive to make decisions for problems based on
research that is relevant to the problem at hand and realize that ultimately
every single decision is a compromise and there’s no such thing as a “correct”
decision. The pursuit of perfection is a fool’s errand.&lt;/p&gt;
&lt;p&gt;If you’d like an example when dogmas lead to bad decisions, I recommend reading
&lt;a href=&quot;https://journal.stuffwithstuff.com&quot;&gt;Robert Nystrom&lt;/a&gt;’s &lt;a href=&quot;http://craftinginterpreters.com/jumping-back-and-forth.html#design-note&quot;&gt;Considering GOTO Harmful&lt;/a&gt; and watching &lt;a href=&quot;https://www.youtube.com/@Tantacrul&quot;&gt;Tantacrul&lt;/a&gt;’s &lt;a href=&quot;https://www.youtube.com/watch?v=S-3wEC6Fj_8&quot;&gt;Music
Software &amp;amp; Interface Design: Steinberg’s Dorico&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Ultimately, I chose Gatsby because my main focus for this project is making
written content for y’all to read.&lt;/p&gt;
&lt;p&gt;And for my particular use case and preferences, I believe it allows me to spend
more time writing than everything else related to running a website like this.&lt;/p&gt;
&lt;p&gt;The fact that I can reuse the rich ecosystem that surrounds the React framework
allows me to write less code and more posts.&lt;/p&gt;
&lt;h1 id=&quot;is-gatsby-perfect&quot;&gt;Is Gatsby perfect?&lt;/h1&gt;
&lt;p&gt;Hell no.&lt;/p&gt;
&lt;p&gt;It took me a lot of time to convert my org blog posts into &lt;a href=&quot;https://mdxjs.com&quot;&gt;MDX&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;It doesn’t help that I kept stumbling upon arcane unhelpful error messages, such
as:&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;console&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; npm run develop&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;success onPreExtractQueries - 0.002s&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;success extract queries from components - 1.869s&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;success write out requires - 0.007s&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt; ERROR #gatsby-plugin-mdx_10001  PLUGIN&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Failed to compile the file &amp;quot;/home/yuki/src/git.yukiisbo.red/yuki/nextgen/notes/mic-check/index.mdx&amp;quot;. Original error message:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Could not parse expression with acorn: Unexpected token&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt; ERROR  UNKNOWN&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Module build failed (from ./node_modules/gatsby/dist/utils/babel-loader.js):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;SyntaxError: /home/yuki/src/git.yukiisbo.red/yuki/nextgen/notes/mic-check/index.mdx: Invalid left-hand side in prefix operation. (1:2)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; 1 &lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;|&lt;/span&gt;&lt;span style=&quot;color:#0057D1&quot;&gt; ---&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;    |   ^&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  2 | title: &amp;quot;Mic Check&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  3 | date: &amp;quot;2022-12-17&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  4 | slug: &amp;quot;mic-check&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;not finished Building development bundle - 2.233s&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It doesn’t indicate which line resulted in the error nor does it provide any
helpful indication.&lt;/p&gt;
&lt;p&gt;It throws this whenever MDX is unable to parse your “Markdown” file (despite
them being valid Markdown, so this issue is mainly because their parser is bad).&lt;/p&gt;
&lt;p&gt;It really feels like we’ve reverted back to the 80s with Commodore BASIC where
syntax errors just results in a single cryptic message: &lt;code&gt;SYNTAX ERROR&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Also, I learned the hard way that when &lt;code&gt;gatsby-config.ts&lt;/code&gt; results in an error,
it will spam errors that are way more unhelpful because they’re unrelated to the
actual issue.&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;console&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; npm run develop&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;success source and transform nodes - 0.071s&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;success building schema - 0.219s&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;success createPages - 0.005s&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt; ERROR #85923  GRAPHQL.VALIDATION&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;There was an error in your GraphQL query:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Cannot query field &amp;quot;allMdx&amp;quot; on type &amp;quot;Query&amp;quot;.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;If you don&amp;#39;t expect &amp;quot;allMdx&amp;quot; to exist on the type &amp;quot;Query&amp;quot; it is most likely a typo. However, if you expect &amp;quot;allMdx&amp;quot; to exist there are a couple of solutions to common problems:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;- If you added a new data source and/or changed something inside gatsby-node/gatsby-config, please try a restart of your development server.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;- You want to optionally use your field &amp;quot;allMdx&amp;quot; and right now it is not used anywhere.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;It is recommended to explicitly type your GraphQL schema if you want to use optional fields.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;File: node_modules/gatsby-plugin-page-creator/create-pages-from-collection-builder.js:45:13&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;See our docs page for more info on this error: https://gatsby.dev/creating-type-definitions&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt; ERROR #gatsby-plugin-page-creator_12103  PLUGIN&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;PageCreator: Tried to create pages from the collection builder.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Unfortunately, the query came back empty. There may be an error in your query:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Cannot query field &amp;quot;allMdx&amp;quot; on type &amp;quot;Query&amp;quot;.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;File: src/pages/notes/{mdx.frontmatter__slug}.tsx&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In addition, &lt;code&gt;console.log&lt;/code&gt; doesn’t work inside &lt;code&gt;gatsby-config.ts&lt;/code&gt; so good luck!&lt;/p&gt;
&lt;p&gt;While this was an absolute pain in the ass, now that everything is setup, the
end result is quite pleasant.&lt;/p&gt;
&lt;h1 id=&quot;why-the-merge-with-yukiisbored&quot;&gt;Why the merge with yukiisbo.red?&lt;/h1&gt;
&lt;p&gt;It was quite painful to maintain two different websites uses different tools to
maintain.&lt;/p&gt;
&lt;p&gt;At the same time, having two websites on two domains feels dumb, especially when
I typically “promote” one over the other.&lt;/p&gt;
&lt;p&gt;Therefore, I felt merging them both under one repository and one domain to be
the way to go.&lt;/p&gt;
&lt;p&gt;Now that it’s been more than a year since I stopped using social
medias like Twitter and Mastodon, this website is pretty much the only public
space that is my own where I express myself and I’d like to keep it that way.&lt;/p&gt;
&lt;h1 id=&quot;whats-next&quot;&gt;What’s next?&lt;/h1&gt;
&lt;p&gt;I’m really hoping to write more in the near future.&lt;/p&gt;

&lt;p&gt;Currently, on my spare time, I’m busy working on documentation with the &lt;a href=&quot;https://nixos.org/community/teams/documentation.html&quot;&gt;Nix
Documentation Team&lt;/a&gt; and my main focus for now is on the &lt;a href=&quot;https://nix.dev&quot;&gt;nix.dev&lt;/a&gt; website.&lt;/p&gt;
&lt;p&gt;Other than that, my job title and responsibility changed in my &lt;a href=&quot;https://founderblocks.io&quot;&gt;workplace&lt;/a&gt;. I’m
now the Chief Technical Officer and I need to get used to that title or find an
alternative title that isn’t grand.&lt;/p&gt;
&lt;p&gt;Anyway, that’s all for now. See you next time. Hopefully.&lt;/p&gt;</content:encoded></item><item><title>Spice up with Nix: The Functional Software Deployment Model</title><link>https://yukiisbo.red/notes/spice-up-with-nix-functional-software-deployment/</link><guid isPermaLink="true">https://yukiisbo.red/notes/spice-up-with-nix-functional-software-deployment/</guid><description>In this article, we discuss the foundation of Nix and how does its radically different ideas solve the issues present in existing solutions.</description><pubDate>Wed, 26 Jan 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Unlike traditional package managers, Nix is a package manager which
doesn’t directly modify your system.&lt;/p&gt;
&lt;p&gt;Software which are managed by Nix are stored in a component store
located in &lt;code&gt;/nix/store/&lt;/code&gt;, instead of modifying &lt;code&gt;/usr/&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;But what is a component, exactly? Let’s take a peek inside the
component store.&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;console&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; ls -l /nix/store &lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;|&lt;/span&gt;&lt;span style=&quot;color:#0057D1&quot;&gt; head&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;total 112536&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;-r--r--r--  1 root root     1542 janv.  1  1970 001gp43bjqzx60cg345n2slzg7131za8-nix-nss-open-files.patch&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;-r--r--r--  1 root root       80 janv.  1  1970 003y7nllp3cxm5ww1q6xmygi81hhzgzn-dap-mode-recipe&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;-r--r--r--  1 root root     6619 janv.  1  1970 006s9a9y6iiqmsv7wm2ncm3m5lwhkv3i-libgccjit-10.3.0.drv&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;-r--r--r--  1 root root     3853 janv.  1  1970 007nl7dl9inal3xkca396ssxs416ggrd-python3.8-networkx-2.6.3.drv&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;-r--r--r--  1 root root     1670 janv.  1  1970 00nkk559kqmp7wcyq4vcvxhhk1rcjind-net-tools-2.10.drv&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;-r--r--r--  1 root root      437 janv.  1  1970 00qr10y7z2fcvrp9b2m46710nkjvj55z-update-autotools-gnu-config-scripts.sh&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;-r--r--r--  1 root root     2785 janv.  1  1970 00xlf60cvvppcn845dk30ra5kmmihspb-sqlite-simple-0.4.18.0.tar.gz.drv&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;-r--r--r--  1 root root    10225 janv.  1  1970 011y6iy6lh7qdwxwmm6yg3nslbxkcbkr-tdigest-0.2.1.1.drv&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;-r--r--r--  1 root root     1747 janv.  1  1970 0140ckl854jk2lnr65khhxjv3vwcvycj-docbook-xml-4.2.drv&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Inside the component store, you’ll encounter a bunch of files and
folders. You start to question, “what’s up with the hashes?”.&lt;/p&gt;
&lt;p&gt;Before that, let’s see the contents of a random component.&lt;/p&gt;
&lt;p&gt;In the Nix store, you find a folder named with something that you
recognize.&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;console&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; ls /nix/store/ &lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;|&lt;/span&gt;&lt;span style=&quot;color:#0057D1&quot;&gt; grep&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt; &amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;python3-3.9.6$&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;5bh6rpya1ar6l49vrhx1rg58dsa42906-python3-3.9.6&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; ls -l /nix/store/5bh6rpya1ar6l49vrhx1rg58dsa42906-python3-3.9.6&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;total 20&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;dr-xr-xr-x 2 root root 4096 janv.  1  1970 bin&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;dr-xr-xr-x 3 root root 4096 janv.  1  1970 include&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;dr-xr-xr-x 4 root root 4096 janv.  1  1970 lib&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;dr-xr-xr-x 2 root root 4096 janv.  1  1970 nix-support&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;dr-xr-xr-x 4 root root 4096 janv.  1  1970 share&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; ls -l /nix/store/5bh6rpya1ar6l49vrhx1rg58dsa42906-python3-3.9.6/bin&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;total 36&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;lrwxrwxrwx 1 root root     8 janv.  1  1970 2to3 -&amp;gt; 2to3-3.9&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;-r-xr-xr-x 1 root root   148 janv.  1  1970 2to3-3.9&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;lrwxrwxrwx 1 root root     7 janv.  1  1970 idle -&amp;gt; idle3.9&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;lrwxrwxrwx 1 root root     7 janv.  1  1970 idle3 -&amp;gt; idle3.9&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;-r-xr-xr-x 1 root root   146 janv.  1  1970 idle3.9&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;lrwxrwxrwx 1 root root     8 janv.  1  1970 pydoc -&amp;gt; pydoc3.9&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;lrwxrwxrwx 1 root root     8 janv.  1  1970 pydoc3 -&amp;gt; pydoc3.9&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;-r-xr-xr-x 1 root root   131 janv.  1  1970 pydoc3.9&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;lrwxrwxrwx 1 root root     9 janv.  1  1970 python -&amp;gt; python3.9&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;lrwxrwxrwx 1 root root     9 janv.  1  1970 python3 -&amp;gt; python3.9&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;-r-xr-xr-x 1 root root 16392 janv.  1  1970 python3.9&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;-r-xr-xr-x 1 root root  3290 janv.  1  1970 python3.9-config&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;lrwxrwxrwx 1 root root    16 janv.  1  1970 python3-config -&amp;gt; python3.9-config&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;lrwxrwxrwx 1 root root    16 janv.  1  1970 python-config -&amp;gt; python3.9-config&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Wait, this looks similar to a prefix. It has similar structure to
&lt;code&gt;/usr/&lt;/code&gt; but it only contains Python 3.9.6, nothing else.&lt;/p&gt;
&lt;p&gt;If you check the libraries of the Python binary, it simply refers to
library files stored inside other components.&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;console&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; ldd /nix/store/5bh6rpya1ar6l49vrhx1rg58dsa42906-python3-3.9.6/bin/python3.9&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;    linux-vdso.so.1 (0x00007ffce636f000)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;    libpython3.9.so.1.0 =&amp;gt; /nix/store/5bh6rpya1ar6l49vrhx1rg58dsa42906-python3-3.9.6/lib/libpython3.9.so.1.0 (0x00007fb1b3fe9000)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;    libpthread.so.0 =&amp;gt; /nix/store/z56jcx3j1gfyk4sv7g8iaan0ssbdkhz1-glibc-2.33-56/lib/libpthread.so.0 (0x00007fb1b3fc9000)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;    libdl.so.2 =&amp;gt; /nix/store/z56jcx3j1gfyk4sv7g8iaan0ssbdkhz1-glibc-2.33-56/lib/libdl.so.2 (0x00007fb1b3fc4000)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;    libcrypt.so.1 =&amp;gt; /nix/store/z56jcx3j1gfyk4sv7g8iaan0ssbdkhz1-glibc-2.33-56/lib/libcrypt.so.1 (0x00007fb1b3f8a000)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;    libncursesw.so.6 =&amp;gt; /nix/store/72vdginhi637lxyii5fnpmvf4jzc4gbk-ncurses-6.2/lib/libncursesw.so.6 (0x00007fb1b3f18000)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;    libutil.so.1 =&amp;gt; /nix/store/z56jcx3j1gfyk4sv7g8iaan0ssbdkhz1-glibc-2.33-56/lib/libutil.so.1 (0x00007fb1b3f11000)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;    libm.so.6 =&amp;gt; /nix/store/z56jcx3j1gfyk4sv7g8iaan0ssbdkhz1-glibc-2.33-56/lib/libm.so.6 (0x00007fb1b3dd0000)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;    libgcc_s.so.1 =&amp;gt; /nix/store/z56jcx3j1gfyk4sv7g8iaan0ssbdkhz1-glibc-2.33-56/lib/libgcc_s.so.1 (0x00007fb1b3db6000)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;    libc.so.6 =&amp;gt; /nix/store/z56jcx3j1gfyk4sv7g8iaan0ssbdkhz1-glibc-2.33-56/lib/libc.so.6 (0x00007fb1b3bf1000)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;    /nix/store/z56jcx3j1gfyk4sv7g8iaan0ssbdkhz1-glibc-2.33-56/lib/ld-linux-x86-64.so.2 =&amp;gt; /lib64/ld-linux-x86-64.so.2 (0x00007fb1b43cb000)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So, with the massive hype around Nix, it’s just another package
manager which installs each software into their own prefixes like
&lt;a href=&quot;https://brew.sh/&quot;&gt;Homebrew&lt;/a&gt;?&lt;/p&gt;
&lt;p&gt;Well, not really.&lt;/p&gt;
&lt;h1 id=&quot;the-one-simple-trick&quot;&gt;The one simple trick&lt;/h1&gt;
&lt;p&gt;Let’s go back to the previous question: why are hashes used as a
prefix?&lt;/p&gt;
&lt;p&gt;Do you recall &lt;a href=&quot;https://notes.yukiisbo.red/posts/2021/09/Spice_up_with_Nix_Traditional_Software_Deployment.html&quot;&gt;the issues&lt;/a&gt; with the simple Python script we made?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The problem with different systems having software installed in
different places.&lt;/li&gt;
&lt;li&gt;The problem with different versions or variants of the same
software.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Nix solves the issues mentioned above by storing components in a
deterministic path which are prefixed with a cryptographic hash.&lt;/p&gt;
&lt;p&gt;The hash itself is generated based on the inputs (i.e source code,
build flags, dependencies) used to build the component.&lt;/p&gt;
&lt;p&gt;If any of the inputs changed (ex. one of its dependencies was
updated), the hash will be different which will result in a different
path.&lt;/p&gt;
&lt;p&gt;This simple trick allows for multiple variants of the same software to
be installed along with their dependencies being exact and
deterministic to the ones used when they’re built.&lt;/p&gt;
&lt;h1 id=&quot;getting-your-hands-dirty-with-nix&quot;&gt;Getting your hands dirty with Nix&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Follow me!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;You can follow along the demonstrations shown in the article.&lt;/p&gt;
&lt;p&gt;If you’re running any Linux distribution on a 64-bit Intel/AMD
machine, you’ll see that the paths shown in the demonstrations will be
the same.&lt;/p&gt;
&lt;p&gt;If you’re using another operating system and/or another architecture,
the paths will be different. However, you can still follow along!&lt;/p&gt;
&lt;p&gt;Have fun!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;To demonstrate the deterministic and exact nature of Nix, let’s
package a piece of software with Nix.&lt;/p&gt;
&lt;p&gt;We could package &lt;a href=&quot;https://www.gnu.org/software/hello/&quot;&gt;GNU Hello&lt;/a&gt; like everyone else but I find it rather
overused and doesn’t demonstrate Nix’s strengths.&lt;/p&gt;
&lt;p&gt;Personally, I’m in store for something complex that would make package
maintainers cry.&lt;/p&gt;
&lt;p&gt;So, I made a piece of software called &lt;a href=&quot;https://github.com/yukiisbored/youtube-launcher&quot;&gt;“YouTube Launcher”&lt;/a&gt; which
provides a simple user interface to watch YouTube videos without a web
browser!&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;#!/usr/bin/env python&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; urllib&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;parse &lt;/span&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; urlparse&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; PyQt5&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;QtWidgets &lt;/span&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; QApplication&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; QWidget&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; QVBoxLayout&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; QLineEdit&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; QPushButton&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; QMessageBox&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; PyQt5&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;QtCore &lt;/span&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; QProcess&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;app &lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; QApplication&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;([])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F40064&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt; Youtube&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;QWidget&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F40064&quot;&gt;    def&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; __init__&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#A018FF;font-style:italic&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C99&quot;&gt;        super&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt;__init__&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;        layout &lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; QVBoxLayout&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;        self&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;textbox &lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; QLineEdit&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;https://www.youtube.com/watch?v=fjuJgqrZSIk&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;        layout&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;addWidget&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;textbox&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;        button &lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; QPushButton&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;Watch&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;        button&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;clicked&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;connect&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;__watch&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;        layout&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;addWidget&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;button&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;        self&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;setLayout&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;layout&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;        self&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;setWindowTitle&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;YouTube Launcher&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#F40064;font-style:italic&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;        self&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;resize&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt;512&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 100&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;        self&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;show&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F40064&quot;&gt;    def&lt;/span&gt;&lt;span style=&quot;color:#0057D1&quot;&gt; __watch&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#A018FF;font-style:italic&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;        url &lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; urlparse&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;textbox&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;text&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;())&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;        if&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;url&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;netloc&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;lower&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;()&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt; in&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;www.youtube.com&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt; &amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;youtube.com&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt; and&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;            url&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;path &lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt; &amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;/watch&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt; and&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; url&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;query&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;startswith&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;v=&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt; and&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C99&quot;&gt;            len&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;url&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;query&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt; &amp;gt;&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; 2&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;            QProcess&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;startDetached&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;mpv&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;url&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;geturl&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;()])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;            app&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;exit&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;        else&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;            msg &lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; QMessageBox&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;            msg&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;setIcon&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;QMessageBox&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;Critical&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;            msg&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;setText&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;The URL is not a valid YouTube video URL&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;            msg&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;setWindowTitle&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;Error&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;            msg&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;setStandardButtons&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;QMessageBox&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;Ok&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;            msg&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;exec&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F40064&quot;&gt;def&lt;/span&gt;&lt;span style=&quot;color:#0057D1&quot;&gt; main&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;():&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;    window &lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; Youtube&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;    app&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;exec&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; __name__&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt; ==&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt; &amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;__main__&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;    main&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You don’t need to save the snippet above, it shown here only for
reference. The entire source code is available at
&lt;a href=&quot;https://github.com/yukiisbored/youtube-launcher&quot;&gt;git.yukiisbo.red/yuki/youtube-launcher&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;So, what are the pain points of this program?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It is written in Python 3.&lt;/li&gt;
&lt;li&gt;It uses Qt 5 via the PyQt5 library.&lt;/li&gt;
&lt;li&gt;It executes mpv which requires YouTube support to be enabled.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Much more complex than our previous Python script.&lt;/p&gt;
&lt;p&gt;So, here’s the Nix file to build and package the software:&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;nix&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;let&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C99&quot;&gt;  pkgs&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; import&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;builtins&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;fetchTarball &lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C99&quot;&gt;    url&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;https://github.com/NixOS/nixpkgs/archive/60cce7e5e1fdf62421ef6d4184ee399b46209366.tar.gz&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C99&quot;&gt;    sha256&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;100xrb925cana1kfd0c7gwkjjalq891vfgr0rn1gl9j8gp3l3gx6&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;  })&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt; {};&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C99&quot;&gt;  mpv&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; pkgs&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;wrapMpv pkgs&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;mpv-unwrapped &lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; youtubeSupport&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#D17C00&quot;&gt; true&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt; };&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;in&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;pkgs&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;python38Packages&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;buildPythonApplication &lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C99&quot;&gt;  pname&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;youtube-launcher&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C99&quot;&gt;  version&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;0.1&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C99&quot;&gt;  src&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; pkgs&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;fetchFromGitHub &lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C99&quot;&gt;    owner&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;yukiisbored&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C99&quot;&gt;    repo&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;youtube-launcher&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C99&quot;&gt;    rev&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;04322fbe3f3c1d9a7c620147c2380cd770cb505a&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C99&quot;&gt;    sha256&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;043sj6p47s8jk9sj9qnbshzjvxix1pfwzkpwbc5f9dqk5yxgnq13&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;  };&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C99&quot;&gt;  buildInputs&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; mpv &lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C99&quot;&gt;  propagatedBuildInputs&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#D17C00&quot;&gt; with&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; pkgs&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;python38Packages; &lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; pyqt5 &lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C99&quot;&gt;  nativeBuildInputs&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#D17C00&quot;&gt; with&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; pkgs&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;libsForQt5&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;qt5; &lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; qtbase wrapQtAppsHook &lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C99&quot;&gt;  postPatch&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt; &amp;#39;&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;    substituteInPlace youtube_launcher.py \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;      --replace &amp;quot;&amp;#39;mpv&amp;#39;&amp;quot; &amp;quot;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;${&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;mpv&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;/bin/mpv&amp;#39;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;  &amp;#39;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C99&quot;&gt;  preFixup&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt; &amp;#39;&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;    makeWrapperArgs+=(&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;&amp;#39;&amp;#39;$&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;{qtWrapperArgs[@]}&amp;quot;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;  &amp;#39;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To build, create an empty folder and save the snippet above as
&lt;code&gt;default.nix&lt;/code&gt; inside it.&lt;/p&gt;
&lt;p&gt;Now, run &lt;code&gt;nix-build&lt;/code&gt; to build the package.&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;console&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; mkdir -p experiments/youtube&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; cd experiments/youtube&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; ls&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; nano default.nix&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; nix-build &lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt;.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;these 4 derivations will be built:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  /nix/store/vv23rn1fqfx2b7sb6n8z3qpqi9r1m5vw-builder.pl.drv&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  /nix/store/5ia4ma9b96kg620k7k0w9xhgqajd828n-youtube-launcher-0.1.drv&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;these 335 paths will be fetched (204.35 MiB download, 984.31 MiB unpacked):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  /nix/store/03bbr1dba98kzmx364yv4dwhvssc1g1w-libxkbcommon-1.3.0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  /nix/store/zpbhr2v6x7dijfvw3w9xpbrvhp9z6gzw-hook&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;copying path &amp;#39;/nix/store/6c5x1d03c5323lsbr2il8w1gwf83cqjj-python-remove-bin-bytecode-hook&amp;#39; from &amp;#39;https://hydra.iohk.io&amp;#39;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;copying path &amp;#39;/nix/store/an3gwsbssydlcwlafznv0lisq7c8hy5p-mpv-0.33.1&amp;#39; from &amp;#39;https://cache.nixos.org&amp;#39;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;building &amp;#39;/nix/store/vv23rn1fqfx2b7sb6n8z3qpqi9r1m5vw-builder.pl.drv&amp;#39;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;building &amp;#39;/nix/store/sd5x742zvdhrm0ysx4xivyaf51qm98w7-lua-5.2.4-env.drv&amp;#39;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;created 12 symlinks in user environment&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;building &amp;#39;/nix/store/7imvh7yyv754jjvaqd7cgvd196xcixsj-mpv-with-scripts-0.33.1.drv&amp;#39;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;building &amp;#39;/nix/store/5ia4ma9b96kg620k7k0w9xhgqajd828n-youtube-launcher-0.1.drv&amp;#39;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;/nix/store/y1aimywh5ff57pv2azg705hlkcciy2dn-youtube-launcher-0.1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It’s built and the resulting component is stored inside
&lt;code&gt;/nix/store/y1aimywh5ff57pv2azg705hlkcciy2dn-youtube-launcher-0.1&lt;/code&gt; as
indicated by the last line of &lt;code&gt;nix-build&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Now, you can run the software by running
&lt;code&gt;./result/bin/youtube-launcher&lt;/code&gt; inside the same folder as &lt;code&gt;default.nix&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;console&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; ls -l&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;total 8&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;-rw-rw-r-- 1 yuki yuki 1001 janv. 24 13:09 default.nix&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;lrwxrwxrwx 1 yuki yuki   64 janv. 24 13:11 result -&amp;gt; /nix/store/y1aimywh5ff57pv2azg705hlkcciy2dn-youtube-launcher-0.1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; ./result/bin/youtube-launcher&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The OpenGL problem on non-NixOS&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;As of writing, if you’re not running NixOS or macOS (untested), mpv
will fallback to software rendering as it fails to use any hardware
acceleration which results in poor performance.&lt;/p&gt;
&lt;p&gt;This is not entirely the fault of Nix / nixpkgs but rather due to how
hardware accelerated graphics works in Linux and other *nix which uses
Linux DRI/Mesa architecture.&lt;/p&gt;
&lt;p&gt;The issue is currently tracked as &lt;a href=&quot;https://github.com/NixOS/nixpkgs/issues/9415&quot;&gt;#62177&lt;/a&gt; in nixpkgs. There are hacks
to workaround this issue, most notably the &lt;a href=&quot;https://github.com/guibou/nixGL&quot;&gt;nixGL&lt;/a&gt; wrapper.&lt;/p&gt;
&lt;p&gt;If you’d like to learn more about how hardware accelerated graphics
work, I recommend the &lt;a href=&quot;https://en.wikipedia.org/wiki/Direct_Rendering_Infrastructure&quot;&gt;Wikipedia article on DRI&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If you want to get your hands dirty, I challenge you to write a
program which obtains an OpenGL/Vulkan context and render a cube
without X11/GLX nor a Wayland compositor. Have fun! ;-)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;video controls&gt;&lt;source src=&quot;/_astro/nixdemo.DgzilSkh.webm&quot; type=&quot;video/webm&quot;/&gt;&lt;p&gt;Your browser does not support the video tag.&lt;/p&gt;&lt;/video&gt;
&lt;p&gt;It works and you can watch YouTube videos with it by copy-pasting a
YouTube URL into the text box and click the “Watch” button. Awesome.&lt;/p&gt;
&lt;p&gt;But, why does it work?&lt;/p&gt;
&lt;p&gt;This is a rather tame Python script which does a lot of bad practices:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It assumes &lt;code&gt;python&lt;/code&gt; is Python 3.&lt;/li&gt;
&lt;li&gt;It assumes mpv is in &lt;code&gt;PATH&lt;/code&gt; and is capable of playing YouTube videos.&lt;/li&gt;
&lt;li&gt;It relies on Qt which requires native libraries.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Let’s take a peek at the binary.&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;console&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; cat ./result/bin/youtube-launcher&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;#! /nix/store/kxj6cblcsd1qcbbxlmbswwrn89zcmgd6-bash-4.4-p23/bin/bash -e&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;export PATH=&amp;#39;/nix/store/4s0h5aawbap3xhldxhcijvl26751qrjr-python3-3.8.9/bin:/nix/store/y1aimywh5ff57pv2azg705hlkcciy2dn-youtube-launcher-0.1/bin:/nix/store/kv3wcr31ba5r2hglaz5d73mg084ld820-qtdeclarative-5.15.2-bin/bin:/nix/store/1p93bdjv1h6dqc7lbykj54mp7d64vl4c-python3.8-PyQt5-5.15.2/bin&amp;#39;${PATH:+&amp;#39;:&amp;#39;}$PATH&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;export PYTHONNOUSERSITE=&amp;#39;true&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;export QT_PLUGIN_PATH=&amp;#39;/nix/store/cgpka5n7m8l31i6j9f5b071l8alqzq6v-qtbase-5.15.2-bin/lib/qt-5.15.2/plugins&amp;#39;${QT_PLUGIN_PATH:+&amp;#39;:&amp;#39;}$QT_PLUGIN_PATH&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;export QT_PLUGIN_PATH=&amp;#39;/nix/store/k5f31g4g5s7agb7yahlsi4w7jz15516x-qtsvg-5.15.2-bin/lib/qt-5.15.2/plugins&amp;#39;${QT_PLUGIN_PATH:+&amp;#39;:&amp;#39;}$QT_PLUGIN_PATH&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;export QT_PLUGIN_PATH=&amp;#39;/nix/store/kv3wcr31ba5r2hglaz5d73mg084ld820-qtdeclarative-5.15.2-bin/lib/qt-5.15.2/plugins&amp;#39;${QT_PLUGIN_PATH:+&amp;#39;:&amp;#39;}$QT_PLUGIN_PATH&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;export QML2_IMPORT_PATH=&amp;#39;/nix/store/kv3wcr31ba5r2hglaz5d73mg084ld820-qtdeclarative-5.15.2-bin/lib/qt-5.15.2/qml&amp;#39;${QML2_IMPORT_PATH:+&amp;#39;:&amp;#39;}$QML2_IMPORT_PATH&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;export QML2_IMPORT_PATH=&amp;#39;/nix/store/9r1hhbk3r9jv9dcnd3z59jyjs1k08r8p-qtquickcontrols-5.15.2/lib/qt-5.15.2/qml&amp;#39;${QML2_IMPORT_PATH:+&amp;#39;:&amp;#39;}$QML2_IMPORT_PATH&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;export QT_PLUGIN_PATH=&amp;#39;/nix/store/psvnd1d97brqwgw9c8qhw4l85nlvpn6y-qtwayland-5.15.2-bin/lib/qt-5.15.2/plugins&amp;#39;${QT_PLUGIN_PATH:+&amp;#39;:&amp;#39;}$QT_PLUGIN_PATH&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;export QML2_IMPORT_PATH=&amp;#39;/nix/store/psvnd1d97brqwgw9c8qhw4l85nlvpn6y-qtwayland-5.15.2-bin/lib/qt-5.15.2/qml&amp;#39;${QML2_IMPORT_PATH:+&amp;#39;:&amp;#39;}$QML2_IMPORT_PATH&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;exec -a &amp;quot;$0&amp;quot; &amp;quot;/nix/store/y1aimywh5ff57pv2azg705hlkcciy2dn-youtube-launcher-0.1/bin/.youtube-launcher-wrapped&amp;quot;  &amp;quot;$@&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is a wrapper which Nix generated to run the software we built.&lt;/p&gt;
&lt;p&gt;Everything in here uses the deterministic path generated by Nix which
has the characteristic cryptographic hash prefix.&lt;/p&gt;
&lt;p&gt;As you can see, it defines various environment variables required to
run the application such as &lt;code&gt;PATH&lt;/code&gt; which includes the exact version of
Python required along with a bunch of other variables to make Qt
applications work.&lt;/p&gt;
&lt;p&gt;That last &lt;code&gt;exec&lt;/code&gt; line executes our Python script, right?&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;console&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; cat /nix/store/y1aimywh5ff57pv2azg705hlkcciy2dn-youtube-launcher-0.1/bin/.youtube-launcher-wrapped&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;#!/nix/store/4s0h5aawbap3xhldxhcijvl26751qrjr-python3-3.8.9/bin/python3.8&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;- coding: utf-8 -&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;-&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;import sys;import site;import functools;sys.argv[0] = &amp;#39;/nix/store/y1aimywh5ff57pv2azg705hlkcciy2dn-youtube-launcher-0.1/bin/youtube-launcher&amp;#39;;functools.reduce(lambda k, p: site.addsitedir(p, k), [&amp;#39;/nix/store/y1aimywh5ff57pv2azg705hlkcciy2dn-youtube-launcher-0.1/lib/python3.8/site-packages&amp;#39;,&amp;#39;/nix/store/qldagg1vs1y4j36jnchbhqihjj68q9qd-python3.8-dbus-python-1.2.16/lib/python3.8/site-packages&amp;#39;,&amp;#39;/nix/store/wp81ms43wsvrc3qxnfx1bz3ksdyc756y-python3.8-PyQt5_sip-12.8.1/lib/python3.8/site-packages&amp;#39;,&amp;#39;/nix/store/1p93bdjv1h6dqc7lbykj54mp7d64vl4c-python3.8-PyQt5-5.15.2/lib/python3.8/site-packages&amp;#39;], site._init_pathinfo());&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;import re&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;import sys&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;from youtube_launcher import main&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;if __name__ == &amp;#39;__main__&amp;#39;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;    sys.argv[0] = re.sub(r&amp;#39;(-script\.pyw|\.exe)?$&amp;#39;, &amp;#39;&amp;#39;, sys.argv[0])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;    sys.exit(main())&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Nope, it’s another wrapper written in Python generated by Nix.&lt;/p&gt;
&lt;p&gt;The shebang is now deterministic to the exact version of Python used
for this program.&lt;/p&gt;
&lt;p&gt;The line with &lt;code&gt;import sys; import site;&lt;/code&gt; defines the entire Python site
path.&lt;/p&gt;
&lt;p&gt;If you are unfamiliar, in Python, the site path defines a list of
paths where it can find Python libraries, similar to the &lt;code&gt;PATH&lt;/code&gt;
environment variable.&lt;/p&gt;
&lt;p&gt;With that in mind, the wrapper adds a bunch of path determistic paths
to the runtime dependencies.&lt;/p&gt;
&lt;p&gt;In the end, it imported our main function and execute it.&lt;/p&gt;
&lt;p&gt;So, where is our script?&lt;/p&gt;
&lt;p&gt;Let’s look deeper.&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;console&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; cat ./result/lib/python3.8/site-packages/youtube_launcher.py&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;#!/usr/bin/env python&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;from urllib.parse import urlparse&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QLineEdit, QPushButton, QMessageBox&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;from PyQt5.QtCore import QProcess&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;app = QApplication([])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;There it is!&lt;/p&gt;
&lt;p&gt;Reading the source code, it’s a bit different.&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;python&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;QProcess&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;startDetached&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;/nix/store/p7csiywv541jnvrgah93p7zjvq8lkwkq-mpv-with-scripts-0.33.1/bin/mpv&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;url&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;geturl&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;()])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The line which executes mpv was changed to use the deterministic path
for the mpv binary.&lt;/p&gt;
&lt;p&gt;While we’re here, we can even ask Nix to tell us what are the direct
runtime dependencies of the component:&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;console&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; nix-store --query --references ./result&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;/nix/store/kxj6cblcsd1qcbbxlmbswwrn89zcmgd6-bash-4.4-p23&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;/nix/store/4s0h5aawbap3xhldxhcijvl26751qrjr-python3-3.8.9&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;/nix/store/1p93bdjv1h6dqc7lbykj54mp7d64vl4c-python3.8-PyQt5-5.15.2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;/nix/store/9r1hhbk3r9jv9dcnd3z59jyjs1k08r8p-qtquickcontrols-5.15.2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;/nix/store/cgpka5n7m8l31i6j9f5b071l8alqzq6v-qtbase-5.15.2-bin&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;/nix/store/k5f31g4g5s7agb7yahlsi4w7jz15516x-qtsvg-5.15.2-bin&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;/nix/store/kv3wcr31ba5r2hglaz5d73mg084ld820-qtdeclarative-5.15.2-bin&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;/nix/store/wp81ms43wsvrc3qxnfx1bz3ksdyc756y-python3.8-PyQt5_sip-12.8.1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;/nix/store/cvwc3r4dcjjsa6vb50idlc4q171whvgl-python3.8-PyQt5-5.15.2-dev&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;/nix/store/p7csiywv541jnvrgah93p7zjvq8lkwkq-mpv-with-scripts-0.33.1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;/nix/store/psvnd1d97brqwgw9c8qhw4l85nlvpn6y-qtwayland-5.15.2-bin&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;/nix/store/qldagg1vs1y4j36jnchbhqihjj68q9qd-python3.8-dbus-python-1.2.16&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;/nix/store/y1aimywh5ff57pv2azg705hlkcciy2dn-youtube-launcher-0.1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So, as demonstrated, the resulting built component uses deterministic
paths for its runtime dependencies.&lt;/p&gt;
&lt;p&gt;However, Nix isn’t the one doing the paths replacement and wrapping on
its own.&lt;/p&gt;
&lt;p&gt;Instead, it is our Nix file which defines the build process that does
all of the legwork to make this happen.&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;nix&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;let&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;  ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;in&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;pkgs&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;python38Packages&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;buildPythonApplication &lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C99&quot;&gt;  pname&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;youtube-launcher&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C99&quot;&gt;  version&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;0.1&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;  ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The Python wrapper is done by &lt;code&gt;buildPythonApplication&lt;/code&gt; function from
the &lt;a href=&quot;https://github.com/NixOS/nixpkgs&quot;&gt;Nix package collection&lt;/a&gt; (nixpkgs) which we used to build our
package.&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;nix&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;let&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;  ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;in&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;pkgs&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;python38Packages&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;buildPythonApplication &lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;  ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F40064;font-style:italic&quot;&gt;  nativeBuildInputs&lt;/span&gt;&lt;span style=&quot;color:#F40064;font-style:italic&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#F40064;font-style:italic&quot;&gt; with&lt;/span&gt;&lt;span style=&quot;color:#F40064;font-style:italic&quot;&gt; pkgs.libsForQt5.qt5;&lt;/span&gt;&lt;span style=&quot;color:#F40064;font-style:italic&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color:#F40064;font-style:italic&quot;&gt; ...&lt;/span&gt;&lt;span style=&quot;color:#F40064;font-style:italic&quot;&gt; wrapQtAppsHook&lt;/span&gt;&lt;span style=&quot;color:#F40064;font-style:italic&quot;&gt; ];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F40064;font-style:italic&quot;&gt;  ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F40064;font-style:italic&quot;&gt;  preFixup&lt;/span&gt;&lt;span style=&quot;color:#F40064;font-style:italic&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#F40064;font-style:italic&quot;&gt; &amp;#39;&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F40064;font-style:italic&quot;&gt;    makeWrapperArgs+=(&amp;quot;&amp;#39;&amp;#39;${qtWrapperArgs[@]&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#F40064;font-style:italic&quot;&gt;&amp;quot;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F40064;font-style:italic&quot;&gt;  &amp;#39;&amp;#39;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F40064;font-style:italic&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The Qt 5 wrapper is done by &lt;code&gt;wrapQtAppsHook&lt;/code&gt; component from nixpkgs
which we included as a dependency.&lt;/p&gt;
&lt;p&gt;Because we’re using multiple wrappers, we need to add the Qt wrapper
during the &lt;code&gt;preFixup&lt;/code&gt; phase.&lt;/p&gt;
&lt;p&gt;Now, what about mpv?&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;nix&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;let&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;  ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C99&quot;&gt;  mpv&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; pkgs&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;wrapMpv pkgs&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;mpv-unwrapped &lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; youtubeSupport&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#D17C00&quot;&gt; true&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt; };&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;in&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;pkgs&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;python38Packages&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;buildPythonApplication &lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;  ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F40064;font-style:italic&quot;&gt;  buildInputs&lt;/span&gt;&lt;span style=&quot;color:#F40064;font-style:italic&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#F40064;font-style:italic&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color:#F40064;font-style:italic&quot;&gt; mpv&lt;/span&gt;&lt;span style=&quot;color:#F40064;font-style:italic&quot;&gt; ];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F40064;font-style:italic&quot;&gt;  ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F40064;font-style:italic&quot;&gt;  postPatch&lt;/span&gt;&lt;span style=&quot;color:#F40064;font-style:italic&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#F40064;font-style:italic&quot;&gt; &amp;#39;&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F40064;font-style:italic&quot;&gt;    substituteInPlace&lt;/span&gt;&lt;span style=&quot;color:#F40064;font-style:italic&quot;&gt; youtube_launcher.py&lt;/span&gt;&lt;span style=&quot;color:#F40064;font-style:italic&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F40064;font-style:italic&quot;&gt;      --replace&lt;/span&gt;&lt;span style=&quot;color:#F40064;font-style:italic&quot;&gt; &amp;quot;&amp;#39;mpv&amp;#39;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#F40064;font-style:italic&quot;&gt; &amp;quot;&amp;#39;${mpv&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#F40064;font-style:italic&quot;&gt;/bin/mpv&amp;#39;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F40064;font-style:italic&quot;&gt;  &amp;#39;&amp;#39;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F40064;font-style:italic&quot;&gt;  ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F40064;font-style:italic&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;First, we define a variable inside &lt;code&gt;let&lt;/code&gt; to determine which exact
version of mpv is required since we need YouTube support to be
enabled.&lt;/p&gt;
&lt;p&gt;Then, we define it as a dependency for our package inside &lt;code&gt;buildInputs&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In the &lt;code&gt;postPatch&lt;/code&gt; phase, we use &lt;code&gt;subtituteInPlace&lt;/code&gt; to replace instances
of &lt;code&gt;&amp;#39;mpv&amp;#39;&lt;/code&gt; inside the &lt;code&gt;youtube_launcher.py&lt;/code&gt; script with &lt;code&gt;&amp;#39;${mpv}/bin/mpv&amp;#39;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;In the Nix expression language, &lt;code&gt;${mpv}&lt;/code&gt; is string interpolation. In
this case, it will be changed to the determinstic path of the mpv
component.&lt;/p&gt;
&lt;p&gt;And there you go, with that one simple trick of using hashes, Nix
ensures dependencies are deterministic on runtime.&lt;/p&gt;
&lt;p&gt;Making sure the binary builds of your software uses the same exact set
of binaries when it was built.&lt;/p&gt;
&lt;p&gt;Still don’t believe me?&lt;/p&gt;
&lt;p&gt;Let’s update our package to use Python 3.9 and see what happens.&lt;/p&gt;
&lt;p&gt;With &lt;code&gt;default.nix&lt;/code&gt; opened, replace all instances of &lt;code&gt;python38&lt;/code&gt; with
&lt;code&gt;python39&lt;/code&gt; and then build with &lt;code&gt;nix-build&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;console&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; sed -i.orig &lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;s/python38/python39/g&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; default.nix&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; cat default.nix&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;let&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;in&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;pkgs.python39Packages.buildPythonApplication {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  propagatedBuildInputs = with pkgs.python39Packages; [ pyqt5 ];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; nix-build&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;this derivation will be built:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  /nix/store/p33jvlyqgfw3pg9yg16cygd4dczla0ap-youtube-launcher-0.1.drv&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;these 18 paths will be fetched (17.11 MiB download, 93.61 MiB unpacked):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  /nix/store/44l3f1rsghmympim9jbffgfxdcshiz5f-python3.9-pip-21.0.1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  /nix/store/y4j4k0l6w941wriprxz13dhvz896lw3m-tzdata-2020f&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;copying path &amp;#39;/nix/store/76rqrmaxqb7pmrgd9zwbap983aarjidr-python-remove-tests-dir-hook&amp;#39; from &amp;#39;https://cache.nixos.org&amp;#39;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;copying path &amp;#39;/nix/store/dkmbkkax4vqbmc6y1dqqhg9xi9yc23wj-python3.9-PyQt5-5.15.2-dev&amp;#39; from &amp;#39;https://cache.nixos.org&amp;#39;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;building &amp;#39;/nix/store/p33jvlyqgfw3pg9yg16cygd4dczla0ap-youtube-launcher-0.1.drv&amp;#39;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;/nix/store/prrc01g09l1pma21qndg835jfcsi6xb2-youtube-launcher-0.1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; ./result/bin/youtube-launcher&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It still works and it uses Python 3.9.&lt;/p&gt;
&lt;p&gt;Also, the resulting path is now different instead of
&lt;code&gt;/nix/store/y1aimywh5ff57pv2azg705hlkcciy2dn-youtube-launcher-0.1&lt;/code&gt;, it
is now
&lt;code&gt;/nix/store/prrc01g09l1pma21qndg835jfcsi6xb2-youtube-launcher-0.1&lt;/code&gt;
because the input changed.&lt;/p&gt;
&lt;p&gt;When you check the runtime dependencies, only those which are related
to Python are changed.&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;console&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; nix-store --query --references ./result&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;/nix/store/9r1hhbk3r9jv9dcnd3z59jyjs1k08r8p-qtquickcontrols-5.15.2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;/nix/store/cgpka5n7m8l31i6j9f5b071l8alqzq6v-qtbase-5.15.2-bin&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;/nix/store/kxj6cblcsd1qcbbxlmbswwrn89zcmgd6-bash-4.4-p23&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;/nix/store/fn2kv4wn3n4kpv6sb96cp9hi65ra9zb1-python3-3.9.4&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;/nix/store/k5f31g4g5s7agb7yahlsi4w7jz15516x-qtsvg-5.15.2-bin&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;/nix/store/kv3wcr31ba5r2hglaz5d73mg084ld820-qtdeclarative-5.15.2-bin&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;/nix/store/ndaj0cmm8j833y3fp346vbh9xmnsqwbp-python3.9-PyQt5-5.15.2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;/nix/store/xdd39p2zsgypr0cyiiqkzcg1bxsrdpp5-python3.9-PyQt5_sip-12.8.1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;/nix/store/dkmbkkax4vqbmc6y1dqqhg9xi9yc23wj-python3.9-PyQt5-5.15.2-dev&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;/nix/store/p7csiywv541jnvrgah93p7zjvq8lkwkq-mpv-with-scripts-0.33.1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;/nix/store/psvnd1d97brqwgw9c8qhw4l85nlvpn6y-qtwayland-5.15.2-bin&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;/nix/store/q0vfa5rm0y62knfhk582fzw2rlrzdmgg-python3.9-dbus-python-1.2.16&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;/nix/store/prrc01g09l1pma21qndg835jfcsi6xb2-youtube-launcher-0.1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In addition, it uses the same exact Qt and mpv components as the
Python 3.8 version.&lt;/p&gt;
&lt;p&gt;Thanks to the lack of filesystem isolation, you didn’t download a
different version of Qt nor mpv since it uses the same one.&lt;/p&gt;
&lt;p&gt;You can explore the resulting component on your own and use
specialized tools like &lt;a href=&quot;https://diffoscope.org/&quot;&gt;diffoscope&lt;/a&gt;. But, at the end of the day, you’ll
reach the same conclusion.&lt;/p&gt;
&lt;p&gt;Want to proof Nix’s deterministic nature?&lt;/p&gt;
&lt;p&gt;Just revert back to the old version which uses Python 3.8.&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;console&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; ls&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;default.nix  default.nix.orig  result&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; mv default.nix.orig default.nix&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; cat default.nix&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;let&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;in&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;pkgs.python38Packages.buildPythonApplication {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  propagatedBuildInputs = with pkgs.python38Packages; [ pyqt5 ];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; nix-build&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;/nix/store/y1aimywh5ff57pv2azg705hlkcciy2dn-youtube-launcher-0.1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And we’re back to the old component, the path is the same too.&lt;/p&gt;
&lt;p&gt;Still skeptical? You think that because it is cached inside the Nix
store that it results in the same path?&lt;/p&gt;
&lt;p&gt;Let’s perform garbage collection to wipe every unused components and
then rebuild to proof that it is deterministic and the same Nix file
will always build the same exact component.&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;console&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; rm result&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; nix-collect-garbage -d&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;removing old generations of profile /nix/var/nix/profiles/per-user/yuki/profile&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;finding garbage collector roots...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;removing stale link from &amp;#39;/nix/var/nix/gcroots/auto/y3scm0nhz4gacw17lpf0mg03r8f9l65i&amp;#39; to &amp;#39;/home/yuki/trash/result&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;deleting garbage...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;deleting &amp;#39;/nix/store/4dlhsl4kxp9p632mbv1rcq9kjc0y6zdy-stdenv-linux&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;deleting unused links...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;note: currently hard linking saves -0.01 MiB&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;186 store paths deleted, 578.66 MiB freed&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; ls&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;default.nix&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; nix-build&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;this derivation will be built:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  /nix/store/5ia4ma9b96kg620k7k0w9xhgqajd828n-youtube-launcher-0.1.drv&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;these 113 paths will be fetched (75.82 MiB download, 384.18 MiB unpacked):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  /nix/store/07j6d0lr6p1gjxi2qhf6wn88nl81x5jj-perl-5.32.1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;copying path &amp;#39;/nix/store/6c5x1d03c5323lsbr2il8w1gwf83cqjj-python-remove-bin-bytecode-hook&amp;#39; from &amp;#39;https://hydra.iohk.io&amp;#39;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;building &amp;#39;/nix/store/5ia4ma9b96kg620k7k0w9xhgqajd828n-youtube-launcher-0.1.drv&amp;#39;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;/nix/store/y1aimywh5ff57pv2azg705hlkcciy2dn-youtube-launcher-0.1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can see, it’s still the same.&lt;/p&gt;
&lt;p&gt;In case you didn’t know, I originally wrote this article when the
latest version of nixpkgs is v21.05.&lt;/p&gt;
&lt;p&gt;Now, in January 2022, the latest version is v21.11. You can try to
modify the &lt;code&gt;default.nix&lt;/code&gt; to use v21.11 instead of v21.05:&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;nix&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;let&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C99&quot;&gt;  pkgs&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt; import&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;builtins&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;fetchTarball &lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C99&quot;&gt;    url&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;https://github.com/NixOS/nixpkgs/archive/4f6d8095fd51.tar.gz&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C99&quot;&gt;    sha256&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;14sm0bjjcmi9qmznwy3nkd2vbhj5xcshgm54a5wiprl9ssvxqw53&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;  })&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt; {};&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;  ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;in&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;  ...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Using the change above, try building it on your machine. I can
guarantee the path will be &lt;code&gt;/nix/store/w94hyhds5dc0rv4plsp11y8nm6jnv354-youtube-launcher-0.1&lt;/code&gt; on
linux/amd64.&lt;/p&gt;
&lt;h1 id=&quot;the-basic-building-blocks-of-nix&quot;&gt;The basic building blocks of Nix&lt;/h1&gt;
&lt;p&gt;At this point, you might think that Nix is a very complex piece of
software.&lt;/p&gt;
&lt;p&gt;After all, when we’re packaging software, we need to write a script in
a weird bespoke programming language!&lt;/p&gt;
&lt;p&gt;While yes, this article has demonstrated that you are required to
write Nix expressions (&lt;code&gt;.nix&lt;/code&gt; files we’ve written) to do anything with
Nix.&lt;/p&gt;
&lt;p&gt;However, beneath the seemingly complex language, you’ll see that the
very foundation of Nix are built with basic fundamental building
blocks.&lt;/p&gt;
&lt;p&gt;With that in mind, you have seen things we’ve achieved with Nix
expressions: launching an environment with additional software to
build and package complex software. However, how does it all work?&lt;/p&gt;
&lt;h1 id=&quot;instatiation&quot;&gt;Instatiation&lt;/h1&gt;
&lt;p&gt;First, Nix expressions are translated to derivations in a process
called “instatiation”.&lt;/p&gt;
&lt;p&gt;A careful reader might notice this term being mentioned a lot when
we demonstrate Nix: &lt;code&gt;.drv&lt;/code&gt; files and the word “derivation” scattered
throughout from Nix’s outputs.&lt;/p&gt;
&lt;p&gt;What are they? Let’s take a look!&lt;/p&gt;
&lt;p&gt;We use our previous Nix expression which packages the YouTube Launcher
app we just made (without the modifications) and use &lt;code&gt;nix-instantiate&lt;/code&gt;
to perform only the instatiation process.&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;console&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; nix-instantiate default.nix&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;/nix/store/5ia4ma9b96kg620k7k0w9xhgqajd828n-youtube-launcher-0.1.drv&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;After running the command, it outputs the path within the Nix store of
the resulting derivation. Let’s see what’s inside!&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;console&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; cat /nix/store/5ia4ma9b96kg620k7k0w9xhgqajd828n-youtube-launcher-0.1.drv&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;Derive([(&amp;quot;out&amp;quot;,&amp;quot;/nix/store/y1aimywh5ff57pv2azg705hlkcciy2dn-youtube-launcher-0.1&amp;quot;,&amp;quot;&amp;quot;,&amp;quot;&amp;quot;)],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Oh wow, this looks rather daunting. No worries, &lt;code&gt;nix show-derivation&lt;/code&gt;
will pretty print it for you!&lt;/p&gt;
&lt;p&gt;Just give the path to the derivation to &lt;code&gt;nix show-derivation&lt;/code&gt;, like so:&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;console&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; nix show-derivation /nix/store/5ia4ma9b96kg620k7k0w9xhgqajd828n-youtube-launcher-0.1.drv&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  &amp;quot;/nix/store/5ia4ma9b96kg620k7k0w9xhgqajd828n-youtube-launcher-0.1.drv&amp;quot;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;    &amp;quot;outputs&amp;quot;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;      &amp;quot;out&amp;quot;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;        &amp;quot;path&amp;quot;: &amp;quot;/nix/store/y1aimywh5ff57pv2azg705hlkcciy2dn-youtube-launcher-0.1&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;      }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;    },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;    &amp;quot;inputSrcs&amp;quot;: [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;      &amp;quot;/nix/store/64fk9k7an4gyn7qgr85p42s8763yc56q-source&amp;quot;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;      &amp;quot;/nix/store/9krlzvny65gdc8s7kpb6lkx8cd02c25b-default-builder.sh&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;    ],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;    &amp;quot;inputDrvs&amp;quot;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;      &amp;quot;/nix/store/2zjvqfjg2pww4lkafw2x4ni450a2w8hx-setuptools-setup-hook.drv&amp;quot;: [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;        &amp;quot;out&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;      ],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;      ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;      &amp;quot;/nix/store/wrnnl82wk8lz8wqgcrh8kii0kfjnl875-hook.drv&amp;quot;: [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;        &amp;quot;out&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;      ]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;    },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;    &amp;quot;system&amp;quot;: &amp;quot;x86_64-linux&amp;quot;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;    &amp;quot;builder&amp;quot;: &amp;quot;/nix/store/kxj6cblcsd1qcbbxlmbswwrn89zcmgd6-bash-4.4-p23/bin/bash&amp;quot;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;    &amp;quot;args&amp;quot;: [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;      &amp;quot;-e&amp;quot;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;      &amp;quot;/nix/store/9krlzvny65gdc8s7kpb6lkx8cd02c25b-default-builder.sh&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;    ],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;    &amp;quot;env&amp;quot;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;      &amp;quot;LANG&amp;quot;: &amp;quot;C.UTF-8&amp;quot;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;      &amp;quot;buildInputs&amp;quot;: &amp;quot;/nix/store/p7csiywv541jnvrgah93p7zjvq8lkwkq-mpv-with-scripts-0.33.1&amp;quot;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;      &amp;quot;builder&amp;quot;: &amp;quot;/nix/store/kxj6cblcsd1qcbbxlmbswwrn89zcmgd6-bash-4.4-p23/bin/bash&amp;quot;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;       ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;      &amp;quot;strictDeps&amp;quot;: &amp;quot;1&amp;quot;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;      &amp;quot;system&amp;quot;: &amp;quot;x86_64-linux&amp;quot;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;      &amp;quot;version&amp;quot;: &amp;quot;0.1&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It’s a rather massive JSON file. Let’s break it down.&lt;/p&gt;
&lt;h2 id=&quot;the-outputs-outputs&quot;&gt;The outputs (&lt;code&gt;outputs&lt;/code&gt;)&lt;/h2&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;json&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;outputs&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C9988&quot;&gt;  &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt;out&lt;/span&gt;&lt;span style=&quot;color:#008C9988&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C9988&quot;&gt;    &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt;path&lt;/span&gt;&lt;span style=&quot;color:#008C9988&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;/nix/store/y1aimywh5ff57pv2azg705hlkcciy2dn-youtube-launcher-0.1&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;outputs&lt;/code&gt; section defines the deterministic path of the output of
this derivation. The process is simply called “building”.&lt;/p&gt;
&lt;p&gt;Nix builds the derivation and then store its outputs to the path
defined here.&lt;/p&gt;
&lt;h2 id=&quot;the-inputs-inputsrcs-inputdrvs&quot;&gt;The inputs (&lt;code&gt;inputSrcs&lt;/code&gt;, &lt;code&gt;inputDrvs&lt;/code&gt;)&lt;/h2&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;json&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;inputSrcs&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;[&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;  &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;/nix/store/64fk9k7an4gyn7qgr85p42s8763yc56q-source&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;  &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;/nix/store/9krlzvny65gdc8s7kpb6lkx8cd02c25b-default-builder.sh&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;inputSrcs&lt;/code&gt; defines the path of the source code within the Nix store and
a builder script which will be executed.&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;json&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;inputDrvs&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F40064;font-style:italic&quot;&gt;  ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C9988&quot;&gt;  &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt;/nix/store/457yxakhv0lc3df8jlb9cz0q8fk44lns-qtbase-5.15.2.drv&lt;/span&gt;&lt;span style=&quot;color:#008C9988&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt; [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;    &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;dev&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;  ],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C9988&quot;&gt;  &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt;/nix/store/6pa9w933ipkki2rxxw57qpqy4ngs8q6a-python3-3.8.9.drv&lt;/span&gt;&lt;span style=&quot;color:#008C9988&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt; [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;    &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;out&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;  ],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F40064;font-style:italic&quot;&gt;  ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C9988&quot;&gt;  &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt;/nix/store/7imvh7yyv754jjvaqd7cgvd196xcixsj-mpv-with-scripts-0.33.1.drv&lt;/span&gt;&lt;span style=&quot;color:#008C9988&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt; [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;    &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;out&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;  ],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F40064;font-style:italic&quot;&gt;  ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C9988&quot;&gt;  &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt;/nix/store/jv2c1byik9bpq87rj4vzfd6p6gf9m5cj-python3.8-PyQt5-5.15.2.drv&lt;/span&gt;&lt;span style=&quot;color:#008C9988&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt; [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;    &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;dev&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;  ],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F40064;font-style:italic&quot;&gt;  ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;inputDrvs&lt;/code&gt; defines the inputs or dependencies to build this derivation.&lt;/p&gt;
&lt;p&gt;It mentions other components via their respective derivations (note
the &lt;code&gt;.drv&lt;/code&gt; prefix).&lt;/p&gt;
&lt;p&gt;You might be wondering why some have &lt;code&gt;out&lt;/code&gt;, &lt;code&gt;dev&lt;/code&gt;, &lt;code&gt;lib&lt;/code&gt; or even multiple of
them.&lt;/p&gt;
&lt;p&gt;That’s because derivations can have multiple outputs and the list with
&lt;code&gt;out&lt;/code&gt;, &lt;code&gt;dev&lt;/code&gt; tells Nix which outputs of the derivations to use.&lt;/p&gt;
&lt;p&gt;You can see how it compares by running &lt;code&gt;nix show-derivation /nix/store/457yxakhv0lc3df8jlb9cz0q8fk44lns-qtbase-5.15.2.drv&lt;/code&gt; but I
won’t be getting into it in here.&lt;/p&gt;
&lt;h2 id=&quot;the-environment-system-builder-args-env&quot;&gt;The environment (&lt;code&gt;system&lt;/code&gt;, &lt;code&gt;builder&lt;/code&gt;, &lt;code&gt;args&lt;/code&gt;, &lt;code&gt;env&lt;/code&gt;)&lt;/h2&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;json&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;system&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;x86_64-linux&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;builder&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;/nix/store/kxj6cblcsd1qcbbxlmbswwrn89zcmgd6-bash-4.4-p23/bin/bash&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;args&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;[&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;  &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;-e&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;  &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;/nix/store/9krlzvny65gdc8s7kpb6lkx8cd02c25b-default-builder.sh&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;env&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C9988&quot;&gt;  &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt;LANG&lt;/span&gt;&lt;span style=&quot;color:#008C9988&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;C.UTF-8&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C9988&quot;&gt;  &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt;buildInputs&lt;/span&gt;&lt;span style=&quot;color:#008C9988&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;/nix/store/p7csiywv541jnvrgah93p7zjvq8lkwkq-mpv-with-scripts-0.33.1&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C9988&quot;&gt;  &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt;builder&lt;/span&gt;&lt;span style=&quot;color:#008C9988&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;/nix/store/kxj6cblcsd1qcbbxlmbswwrn89zcmgd6-bash-4.4-p23/bin/bash&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F40064;font-style:italic&quot;&gt;  ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C9988&quot;&gt;  &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt;doInstallCheck&lt;/span&gt;&lt;span style=&quot;color:#008C9988&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C9988&quot;&gt;  &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#008C9988&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;youtube-launcher-0.1&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C9988&quot;&gt;  &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt;nativeBuildInputs&lt;/span&gt;&lt;span style=&quot;color:#008C9988&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;...&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C9988&quot;&gt;  &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt;outputs&lt;/span&gt;&lt;span style=&quot;color:#008C9988&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;out&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C9988&quot;&gt;  &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt;patches&lt;/span&gt;&lt;span style=&quot;color:#008C9988&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt; &amp;quot;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C9988&quot;&gt;  &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt;pname&lt;/span&gt;&lt;span style=&quot;color:#008C9988&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;youtube-launcher&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C9988&quot;&gt;  &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt;postFixup&lt;/span&gt;&lt;span style=&quot;color:#008C9988&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;wrapPythonPrograms&lt;/span&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;\n&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C9988&quot;&gt;  &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt;postPatch&lt;/span&gt;&lt;span style=&quot;color:#008C9988&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;substituteInPlace youtube_launcher.py &lt;/span&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;\\\n&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;  --replace &lt;/span&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;\&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;&amp;#39;mpv&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;\&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D17C00&quot;&gt; \&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;&amp;#39;/nix/store/p7csiywv541jnvrgah93p7zjvq8lkwkq-mpv-with-scripts-0.33.1/bin/mpv&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;\&amp;quot;\n&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C9988&quot;&gt;  &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt;preFixup&lt;/span&gt;&lt;span style=&quot;color:#008C9988&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;makeWrapperArgs+=(&lt;/span&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;\&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;${qtWrapperArgs[@]}&lt;/span&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;\&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;\n&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C9988&quot;&gt;  &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt;propagatedBuildInputs&lt;/span&gt;&lt;span style=&quot;color:#008C9988&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;/nix/store/cvwc3r4dcjjsa6vb50idlc4q171whvgl-python3.8-PyQt5-5.15.2-dev /nix/store/4s0h5aawbap3xhldxhcijvl26751qrjr-python3-3.8.9&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C9988&quot;&gt;  &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt;propagatedNativeBuildInputs&lt;/span&gt;&lt;span style=&quot;color:#008C9988&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt; &amp;quot;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C9988&quot;&gt;  &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt;src&lt;/span&gt;&lt;span style=&quot;color:#008C9988&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;/nix/store/64fk9k7an4gyn7qgr85p42s8763yc56q-source&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C9988&quot;&gt;  &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt;stdenv&lt;/span&gt;&lt;span style=&quot;color:#008C9988&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;/nix/store/4dlhsl4kxp9p632mbv1rcq9kjc0y6zdy-stdenv-linux&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C9988&quot;&gt;  &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt;strictDeps&lt;/span&gt;&lt;span style=&quot;color:#008C9988&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C9988&quot;&gt;  &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt;system&lt;/span&gt;&lt;span style=&quot;color:#008C9988&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;x86_64-linux&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C9988&quot;&gt;  &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt;version&lt;/span&gt;&lt;span style=&quot;color:#008C9988&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;0.1&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here we see &lt;code&gt;system&lt;/code&gt;, &lt;code&gt;builder&lt;/code&gt;, and &lt;code&gt;args&lt;/code&gt;, what’s up with these?&lt;/p&gt;
&lt;p&gt;You might be able to guess on your own but here’s an explaination:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;system&lt;/code&gt; defines which exact architecture/operating system this
derivation is for.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;In the early days of Nix, &lt;code&gt;builder&lt;/code&gt; was originally used to defined the
script used to build the derivation.&lt;/p&gt;
&lt;p&gt;This script was made along with the expression but this was changed
in later versions to use a generic builder script which we’ll see
later.&lt;/p&gt;
&lt;p&gt;Nowadays, it always points to the bash shell interpreter.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;args&lt;/code&gt; defines the command arguments to pass to the builder. Because
of the change mentioned before, this simply tells the bash
interpreter to execute the generic builder script.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;env&lt;/code&gt; defines all of the environment variable that will be setup for
the builder.&lt;/p&gt;
&lt;p&gt;To ensure reproducibility, before running the build script, Nix
prepares a clean slate which involves removing all environment
variables.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;something-about-environment-variables&quot;&gt;Something about environment variables&lt;/h2&gt;
&lt;p&gt;Have you noticed something perculiar with &lt;code&gt;env&lt;/code&gt;?&lt;/p&gt;
&lt;p&gt;If you read the &lt;code&gt;env&lt;/code&gt; section carefully, you see that it contains code
we’ve written in the Nix expression like the &lt;code&gt;postPatch&lt;/code&gt; and
&lt;code&gt;preFixup&lt;/code&gt; section.&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;json&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;postPatch&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;substituteInPlace youtube_launcher.py &lt;/span&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;\\\n&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;  --replace &lt;/span&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;\&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;&amp;#39;mpv&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;\&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D17C00&quot;&gt; \&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;&amp;#39;/nix/store/p7csiywv541jnvrgah93p7zjvq8lkwkq-mpv-with-scripts-0.33.1/bin/mpv&amp;#39;&lt;/span&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;\&amp;quot;\n&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;preFixup&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;makeWrapperArgs+=(&lt;/span&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;\&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;${qtWrapperArgs[@]}&lt;/span&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;\&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;\n&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;nix&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;let&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;  ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;in&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;pkgs&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;python38Packages&lt;/span&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;buildPythonApplication &lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A018FF&quot;&gt;  ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F40064;font-style:italic&quot;&gt;  postPatch&lt;/span&gt;&lt;span style=&quot;color:#F40064;font-style:italic&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#F40064;font-style:italic&quot;&gt; &amp;#39;&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F40064;font-style:italic&quot;&gt;    substituteInPlace&lt;/span&gt;&lt;span style=&quot;color:#F40064;font-style:italic&quot;&gt; youtube_launcher.py&lt;/span&gt;&lt;span style=&quot;color:#F40064;font-style:italic&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F40064;font-style:italic&quot;&gt;      --replace&lt;/span&gt;&lt;span style=&quot;color:#F40064;font-style:italic&quot;&gt; &amp;quot;&amp;#39;mpv&amp;#39;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#F40064;font-style:italic&quot;&gt; &amp;quot;&amp;#39;${mpv&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#F40064;font-style:italic&quot;&gt;/bin/mpv&amp;#39;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F40064;font-style:italic&quot;&gt;  &amp;#39;&amp;#39;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F40064;font-style:italic&quot;&gt;  preFixup&lt;/span&gt;&lt;span style=&quot;color:#F40064;font-style:italic&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#F40064;font-style:italic&quot;&gt; &amp;#39;&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F40064;font-style:italic&quot;&gt;    makeWrapperArgs+=(&amp;quot;&amp;#39;&amp;#39;${qtWrapperArgs[&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;@&lt;/span&gt;&lt;span style=&quot;color:#F40064;font-style:italic&quot;&gt;]}&amp;quot;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F40064;font-style:italic&quot;&gt;  &amp;#39;&amp;#39;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F40064;font-style:italic&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;After seeing all this, you realize that all of that seemingly complex
language ends up as a bunch environment variables in the end?&lt;/p&gt;
&lt;p&gt;Yeah, pretty much.&lt;/p&gt;
&lt;p&gt;Since we don’t seem to find anything that performs the build, let’s
take a peek inside the generic build script itself?&lt;/p&gt;
&lt;p&gt;What kind of magic is it doing?&lt;/p&gt;
&lt;h1 id=&quot;realization&quot;&gt;Realization&lt;/h1&gt;
&lt;p&gt;Reading to the massive Nix derivation for a second time, we see the
location of the build script from &lt;code&gt;args&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;json&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;args&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;[&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F40064;font-style:italic&quot;&gt;  ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;  &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;/nix/store/9krlzvny65gdc8s7kpb6lkx8cd02c25b-default-builder.sh&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;console&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; cat /nix/store/9krlzvny65gdc8s7kpb6lkx8cd02c25b-default-builder.sh&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;source $stdenv/setup&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;genericBuild&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Just two lines of shell? Seriously?&lt;/p&gt;
&lt;p&gt;Okay, we see that it sources another shell script called
&lt;code&gt;$stdenv/setup&lt;/code&gt;. Knowing that it mentions an environment variable called
&lt;code&gt;stdenv&lt;/code&gt;, let’s check its value from the derivation.&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;json&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;env&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F40064;font-style:italic&quot;&gt;  ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C9988&quot;&gt;  &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt;stdenv&lt;/span&gt;&lt;span style=&quot;color:#008C9988&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;/nix/store/4dlhsl4kxp9p632mbv1rcq9kjc0y6zdy-stdenv-linux&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F40064;font-style:italic&quot;&gt;  ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So, it’s another component in the Nix store, let’s take a peek inside.&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;console&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; ls /nix/store/4dlhsl4kxp9p632mbv1rcq9kjc0y6zdy-stdenv-linux/&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;nix-support  setup&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; cat /nix/store/4dlhsl4kxp9p632mbv1rcq9kjc0y6zdy-stdenv-linux/setup&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;export SHELL=/nix/store/kxj6cblcsd1qcbbxlmbswwrn89zcmgd6-bash-4.4-p23/bin/bash&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;initialPath=&amp;quot;/nix/store/a4v1akahda85rl9gfphb07zzw79z8pb1-coreutils-8.32 ...&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;defaultNativeBuildInputs=&amp;quot;/nix/store/yayg9xvxq3f8avpvw81p7a45zqadpgvb-patchelf-0.12 ...&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;defaultBuildInputs=&amp;quot;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; Make &lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;strip&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; produce deterministic output, by setting&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; timestamps etc. to a fixed value.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;commonStripFlags=&amp;quot;--enable-deterministic-archives&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;export NIX_ENFORCE_PURITY=&amp;quot;${NIX_ENFORCE_PURITY-1}&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;export NIX_ENFORCE_NO_NATIVE=&amp;quot;${NIX_ENFORCE_NO_NATIVE-1}&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;NIX_LIB64_IN_SELF_RPATH=1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It’s a massive bash script which actually performs the build. This is
it: the generic builder.&lt;/p&gt;
&lt;p&gt;As you can see, unlike &lt;code&gt;curl | sh&lt;/code&gt; installers, the Nix expression
language has a very limited scope of what it can actually do.&lt;/p&gt;
&lt;p&gt;The build process is a two-stage approach:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Instatiation&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Outside the Nix store, Nix expressions are translated
to Nix derivations. The resulting derivation is then placed inside
the Nix store.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Realization&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Within the Nix store, the derivation is read by the builder which
will execute the builder script and the derivation’s outputs from
the build process will be stored inside the Nix store.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This entire process will never touch any other part of your system and
everything is nicely encapsulated.&lt;/p&gt;
&lt;p&gt;To guarantee this, Nix performs &lt;a href=&quot;https://search.nixos.org/options?channel=21.05&amp;show=nix.useSandbox&amp;from=0&amp;size=50&amp;sort=relevance&amp;query=sandbox&quot;&gt;Sandboxing&lt;/a&gt; which isolates the build
process from the host system.&lt;/p&gt;
&lt;h1 id=&quot;the-standard-environment&quot;&gt;The Standard Environment&lt;/h1&gt;
&lt;p&gt;However, as you can see, all of this relies on &lt;code&gt;stdenv&lt;/code&gt;. What is that?&lt;/p&gt;
&lt;p&gt;As the name implies, it is the standard environment provided by
nixpkgs to build all software with Nix.&lt;/p&gt;
&lt;p&gt;This was originally made because it was impossible to rely on the
&lt;a href=&quot;https://en.wikipedia.org/wiki/Linux_Standard_Base&quot;&gt;“Linux Standard Base”&lt;/a&gt; of the present host system to serve as the
stable basis to build software upon. Therefore, Nix made its own
standard environment where it serves as the foundation of all software
built by it.&lt;/p&gt;
&lt;p&gt;This basic foundation contains the basic set of utilities required to
build everything, such as GCC compiler, bash shell interpreter, GNU
coreutils, make, patch, etc.&lt;/p&gt;
&lt;p&gt;In order to be able to use and install software Nix, you need a
prebuilt standard environment for your system.&lt;/p&gt;
&lt;p&gt;We won’t be covering how the standard environment is bootstrapped and
built in this article. If you’re interested, the &lt;a href=&quot;https://github.com/NixOS/nixpkgs/tree/e38de71da886e5ccd3642e05614547261384457d/pkgs/stdenv&quot;&gt;stdenv package source&lt;/a&gt;
in nixpkgs is a good starting point.&lt;/p&gt;
&lt;p&gt;In terms of trusted binaries, stdenv is the only component inside
Nix’s ecosystem that you need to trust.&lt;/p&gt;
&lt;p&gt;However, this situation is much better than other package managers
which require you to trust individual packages which are uploaded by
their respective maintainers.&lt;/p&gt;
&lt;p&gt;This requirement of trusting package maintainer uploads has spawned
scandals such as &lt;a href=&quot;https://www.theregister.com/2015/06/17/debian_chromium_hubbub/&quot;&gt;the infamous Chromium binary blob drama which
happened in Debian in 2015&lt;/a&gt; and nowadays, a lot of &lt;a href=&quot;https://github.com/cloudflare/binary-install&quot;&gt;the same thing is
happening within the npm ecosystem&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In Nix, other than the standard environment, you’re not required to
trust the binaries which are delivered to you. You have the choice to
build everything on your machine, Gentoo style.&lt;/p&gt;
&lt;p&gt;Just go to &lt;code&gt;nix.conf&lt;/code&gt; and remove &lt;code&gt;https://cache.nixos.org&lt;/code&gt; from
&lt;code&gt;substituters&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;ini&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;substituters&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; https://cache.nixos.org/&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;trusted-public-keys&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; cache.nixos.org-1:&lt;/span&gt;&lt;span style=&quot;color:#D17C00&quot;&gt;6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#16181A&quot;&gt;...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The location of &lt;code&gt;nix.conf&lt;/code&gt; varies on how Nix is installed.&lt;/p&gt;
&lt;p&gt;They’re either in &lt;code&gt;/etc/nix/nix.conf&lt;/code&gt; or &lt;code&gt;~/.config/nix/nix.conf&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If you’re running NixOS or use home-manager, you need to modify
&lt;code&gt;configuration.nix&lt;/code&gt; or &lt;code&gt;home.nix&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Once stdenv is present in your Nix store, you can completely detach
yourself from the Nix binary cache and build every single thing on
your own.&lt;/p&gt;
&lt;p&gt;However, unlike binary repos, you shouldn’t need to worry about the
Nix binary cache.&lt;/p&gt;
&lt;p&gt;Remember, one of Nix goals is to be able to reproduce the same exact
output every time, bit by bit. So, in case the cache is serving
malformed binaries, you can &lt;a href=&quot;https://nixos.org/manual/nix/unstable/advanced-topics/diff-hook.html&quot;&gt;check and verify&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;According to &lt;a href=&quot;https://r13y.com/&quot;&gt;r13y.com&lt;/a&gt;, as of writing, the NixOS unstable ISO is 100%
reproduced exactly the same, at different times, on different systems.&lt;/p&gt;
&lt;p&gt;When this is not the case, most of the time it caused by &lt;a href=&quot;https://r13y.com/diff/d6e61deed4ecd52b09d31fa9d5e1168d36971787c5a86e3a65a86f9931794cfb-f9bb7d64a8908529aee04fd0e6ec2380c9726cf3454bb8b32e8457ee51ba80a4.html&quot;&gt;manpage
generation&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id=&quot;binary-cache&quot;&gt;Binary cache&lt;/h1&gt;
&lt;p&gt;I’ve mentioned the binary cache previously but what is it exactly?&lt;/p&gt;
&lt;p&gt;It is essentially an accessible Nix store that is used to download
built components from.&lt;/p&gt;
&lt;p&gt;While you might think it’s a binary repository, I hope after reading
this far, you’ll realize that it’s not really a component.&lt;/p&gt;
&lt;p&gt;A more accurate analogy would be an &lt;a href=&quot;https://docs.gitlab.com/ee/ci/pipelines/job_artifacts.html&quot;&gt;artifact store&lt;/a&gt; of a typical
&lt;a href=&quot;https://en.wikipedia.org/wiki/Continuous_integration&quot;&gt;continuous integration&lt;/a&gt; setup.&lt;/p&gt;
&lt;p&gt;In case you aren’t familiar, in short, continuous integration is an
automated system where it builds source code regularly following each
iteration of the source code as it change.&lt;/p&gt;
&lt;p&gt;After the build process is done and passes successfully, it will end
up with fresly built binaries which will be then stored inside an
artifact store where developers or highly technical users can access
to test the new bleeding edge version of the software as if they’re
fresh out of the oven.&lt;/p&gt;
&lt;p&gt;In fact, this is how the Nix community builds their entire package
collection, nixpkgs. &lt;a href=&quot;https://github.com/NixOS/hydra&quot;&gt;Hydra&lt;/a&gt; is the continuous build system which
regularly follow and build the entire Nix packages collection.&lt;/p&gt;
&lt;p&gt;The result of each build is submitted to the massive central Nix
binary cache instance which anyone can use to download the latest
bleeding edge software without having to build on their own machine.&lt;/p&gt;
&lt;p&gt;Recalling how the derivation contains the output path before it is
even built, you can see how Nix knows which files to download from the
binary cache.&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;json&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;outputs&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C9988&quot;&gt;  &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt;out&lt;/span&gt;&lt;span style=&quot;color:#008C9988&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C9988&quot;&gt;    &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt;path&lt;/span&gt;&lt;span style=&quot;color:#008C9988&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt; &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;/nix/store/y1aimywh5ff57pv2azg705hlkcciy2dn-youtube-launcher-0.1&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Same goes with the dependencies, the &lt;code&gt;inputDrvs&lt;/code&gt; defines which
derivations are used as the inputs for the software.&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;json&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;inputDrvs&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F40064;font-style:italic&quot;&gt;  ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C9988&quot;&gt;  &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt;/nix/store/457yxakhv0lc3df8jlb9cz0q8fk44lns-qtbase-5.15.2.drv&lt;/span&gt;&lt;span style=&quot;color:#008C9988&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt; [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;    &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;dev&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;  ],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C9988&quot;&gt;  &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt;/nix/store/6pa9w933ipkki2rxxw57qpqy4ngs8q6a-python3-3.8.9.drv&lt;/span&gt;&lt;span style=&quot;color:#008C9988&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt; [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;    &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;out&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;  ],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F40064;font-style:italic&quot;&gt;  ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C9988&quot;&gt;  &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt;/nix/store/7imvh7yyv754jjvaqd7cgvd196xcixsj-mpv-with-scripts-0.33.1.drv&lt;/span&gt;&lt;span style=&quot;color:#008C9988&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt; [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;    &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;out&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;  ],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F40064;font-style:italic&quot;&gt;  ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008C9988&quot;&gt;  &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008C99&quot;&gt;/nix/store/jv2c1byik9bpq87rj4vzfd6p6gf9m5cj-python3.8-PyQt5-5.15.2.drv&lt;/span&gt;&lt;span style=&quot;color:#008C9988&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#7B8496&quot;&gt; [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;    &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#008B0C&quot;&gt;dev&lt;/span&gt;&lt;span style=&quot;color:#008B0C88&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;  ],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F40064;font-style:italic&quot;&gt;  ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt;,&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Simply read each derivations in the list and do the same process again
until you have a list of components that can be downloaded from the
binary cache and components that needs to be built. Obviously,
components which are already present in your system’s Nix store don’t
need to be rebuilt/redownloaded.&lt;/p&gt;
&lt;p&gt;The deterministic nature reduces the amount of software required to be
downloaded and built therefore we save time, storage, bandwidth, and
compute resources.&lt;/p&gt;
&lt;p&gt;For private or propriertary projects, you can run your own Nix binary
cache for your organization. However, this is out of scope for this
article. The easiest way is to use a hosted service like &lt;a href=&quot;https://www.cachix.org/&quot;&gt;Cachix&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;However, you don’t need a binary cache to transfer built components
across machines. You can simply copy them manually with &lt;code&gt;nix-copy-closure&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;astro-code cyberdream-light&quot; style=&quot;background-color:#ffffff;color:#16181a;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;console&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; ls /nix/store/y1aimywh5ff57pv2azg705hlkcciy2dn-youtube-launcher-0.1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;ls: cannot access &amp;#39;/nix/store/y1aimywh5ff57pv2azg705hlkcciy2dn-youtube-launcher-0.1&amp;#39;: No such file or directry&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; nix-copy-closure --from yuki@neru \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  /nix/store/y1aimywh5ff57pv2azg705hlkcciy2dn-youtube-launcher-0.1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#7B8496&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#16181A&quot;&gt; nix-copy-closure --to yuki@kuzuha \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0057D1&quot;&gt;  /nix/store/y1aimywh5ff57pv2azg705hlkcciy2dn-youtube-launcher-0.1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;By the way, you can only share built components to other machines
which are the same system and architecture (i.e Linux/amd64 machines
can transfer to another Linux/amd64 machine but not to macOS/arm64
machines). The same is true for binary caches. So, keep that in mind!&lt;/p&gt;
&lt;h1 id=&quot;distro-independent&quot;&gt;Distro-independent&lt;/h1&gt;
&lt;p&gt;Since the beginning, Nix is a package manager that works along side
your existing one. In fact, the &lt;a href=&quot;https://edolstra.github.io/pubs/nixos-jfp-final.pdf&quot;&gt;NixOS paper&lt;/a&gt; was published 4 years
after the Nix paper.&lt;/p&gt;
&lt;p&gt;Because of this, packages in Nix are vendor-independent and
theoretically can be used in any UNIX-like operating systems and
computer architectures.&lt;/p&gt;
&lt;p&gt;As of writing, officially, nixpkgs and hydra (nixpkgs’ main binary
cache and build cluster) supports Linux on ARM and Intel/AMD along
with macOS on Intel and even Apple Sillicon!&lt;/p&gt;
&lt;p&gt;However, people have made Nix packages build on &lt;a href=&quot;https://github.com/NixOS/nixpkgs/blob/0f1204bd2be0ca1ea60b70d6d1eb7a11077f6986/lib/systems/doubles.nix#L8-L57&quot;&gt;all sorts of weird
operating system and architecture combinations&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This allow you to choose which system you want to use without having
to worry about software availability.&lt;/p&gt;
&lt;p&gt;As of writing, according to &lt;a href=&quot;https://repology.org/repositories/statistics/total&quot;&gt;Repology&lt;/a&gt;, nixpkgs unstable sits at the
number 1 spot for total number of projects packaged. So, I’m fairly
certain every free and open source that you need is available in
nixpkgs.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Tired of Arch Linux breaking again? Why not move to something
stabler like RHEL, Debian, or SUSE and just use Nix for the
additional software you need/want.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Stuck on RHEL, Debian stable, or SLE because of work and tired of
using 2-4 years old version of your favorite software? Just fire up
Nix and grab everything you need without any risks.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Do you need a specific version of software at work, like PHP 5 for
legacy code, but your coworkers are using macOS and various Linux
distros? Just use Nix and create a &lt;a href=&quot;https://notes.yukiisbo.red/posts/2021/08/Spice_up_with_Nix_Shells.html&quot;&gt;Nix shell environment&lt;/a&gt; for them!&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Personally, after discovering the power of Nix, I simply stopped using
rolling release distros like Arch Linux or Gentoo “unstable” or Debian
sid.&lt;/p&gt;
&lt;p&gt;As of writing, I’m currently using Ubuntu 20.04 LTS or Debian stable
under WSL and just use Nix for the additional software I need, it’s
lovely not having to fuss about my system.&lt;/p&gt;
&lt;h1 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;As you can see, Nix nicely solve &lt;a href=&quot;https://notes.yukiisbo.red/posts/2021/09/Spice_up_with_Nix_Traditional_Software_Deployment.html&quot;&gt;the common issues with traditional
software deployment methods&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The cryptographic hashes are used to guarantee that software are built
with the exact same inputs (dependencies, build options, source code,
etc) and avoids collision with other versions of the same software.&lt;/p&gt;
&lt;p&gt;The hashes are then used to make deterministic paths which ensure the
built software uses the exact version of libraries that it needs. In
fact, Nix determines runtime dependencies for a built component simply
by scanning the build output for the &lt;code&gt;/nix/store/...&lt;/code&gt; patterns.&lt;/p&gt;
&lt;p&gt;The same Nix expression can be shared to other systems without having
to worry too much about system specific detail.&lt;/p&gt;
&lt;p&gt;Nix’s deterministic nature and the power leveraged by binary caches
allows you to avoid building the same software twice. In addition, the
entire process guarantees that you only download and build the
components you actually need on runtime.&lt;/p&gt;
&lt;p&gt;Outside of the second stage of the build process, Nix doesn’t use any
containerization nor namespacing tricks, thus reducing the overhead
and doesn’t require giving normal users &lt;a href=&quot;https://book.hacktricks.xyz/linux-unix/privilege-escalation/docker-breakout/docker-breakout-privilege-escalation&quot;&gt;“root”-like access&lt;/a&gt; just to run
a piece of software.&lt;/p&gt;
&lt;p&gt;In fact, with the sandboxing done by the build process, the generic
builder, and how derivations are made from Nix expressions, Nix
ensures that building software doesn’t tamper with your system and
leave it completely untouched.&lt;/p&gt;
&lt;p&gt;After reading this article, I hope you realize how radically different
Nix is and how its very foundation is able to solve problems which are
common with previous methods of installing software.&lt;/p&gt;
&lt;h1 id=&quot;addendum-the-imperfections&quot;&gt;Addendum: The Imperfections&lt;/h1&gt;
&lt;p&gt;However, like many things, Nix is not perfect.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;For a lot of people, especially those who aren’t familiar with
functional programming, find the Nix expression language to be an
unnecessary learning curve.&lt;/p&gt;
&lt;p&gt;For something that’s meant to build and package software, I wish it
uses something that’s more familiar, such as &lt;a href=&quot;https://rpm-packaging-guide.github.io/#working-with-spec-files&quot;&gt;rpm spec&lt;/a&gt; and &lt;a href=&quot;https://github.com/openbsd/ports/blob/2c5e6b8b54eaf67cda70925c783f12e603b57e3b/multimedia/mpv/Makefile&quot;&gt;BSD-style
Makefiles&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Since Nix relies on cryptographic hashes and deterministic paths to
guarantee the inputs used when building a component, what happens
when a common dependency like OpenSSL receives a minor update?&lt;/p&gt;
&lt;p&gt;It means that an enormous amount of software which uses it directly
or indirectly will need to be rebuilt which also means that people
have to redownload a bunch of the same software.&lt;/p&gt;
&lt;p&gt;This landslide effect doesn’t exist in more traditional approaches
to software packaging as the package maintainer can simply check
whether the current build of the application works with the newer
version of OpenSSL. Therefore, only the packages which fail will
need to be rebuild and updated.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There are many other imperfections like these within the Nix
ecosystem. However, in comparison to the alternatives, they’re much
more easier to solve than the foundational problems with traditional
approaches.&lt;/p&gt;
&lt;p&gt;Since Nix only cares about the derivation, it doesn’t care how it was
made. In fact, this is how &lt;a href=&quot;https://guix.gnu.org/&quot;&gt;GNU Guix&lt;/a&gt; came to be. They forked Nix
(&lt;code&gt;nix-daemon&lt;/code&gt;) and replaced the language with Scheme/Guile which is easy
to do, thanks to the basic fundamental building blocks of Nix.&lt;/p&gt;
&lt;p&gt;While the second one is more difficult to solve, there’s a solution in
the works called content-addressed storage. How it works is out of
scope of this article but the people at &lt;a href=&quot;https://www.tweag.io/&quot;&gt;Tweag&lt;/a&gt; wrote &lt;a href=&quot;https://www.tweag.io/blog/2020-09-10-nix-cas/&quot;&gt;a short article
about it&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Knowing the people within the community, I’m fairly confident that
most of these imperfections will be solved one way or another.&lt;/p&gt;</content:encoded></item><item><title>Notes</title><link>https://yukiisbo.red/notes/notes/</link><guid isPermaLink="true">https://yukiisbo.red/notes/notes/</guid><pubDate>Mon, 07 Jun 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Hello, is this thing on?&lt;/p&gt;
&lt;p&gt;Hi, I’m back after 3 months of absolute silence. I hope you’re doing
well despite these trying times.&lt;/p&gt;
&lt;h1 id=&quot;yet-another-new-writing-platform-really&quot;&gt;Yet another new writing platform, really?&lt;/h1&gt;
&lt;p&gt;Look, I really did believe &lt;a href=&quot;https://writefreely.org/&quot;&gt;Writefreely&lt;/a&gt; will be the end of it all but
sadly, I ended up having mixed opinions about it.&lt;/p&gt;
&lt;p&gt;This weekend, I found out that the entire thing broke on its own and
locked me out of my own drafts because of an update which adds OAuth
functionality, fun.&lt;/p&gt;
&lt;p&gt;It lacks a lot of things that I consider good software require, most
notably, in this case: any form of update guides.&lt;/p&gt;
&lt;p&gt;Seriously though, I thought that this software would allow me to write
stuff quickly but in reality, it doesn’t.&lt;/p&gt;
&lt;h1 id=&quot;back-to-emacs-then&quot;&gt;Back to Emacs, then&lt;/h1&gt;
&lt;p&gt;Recently, I’m back to Emacs with org-mode. However, unlike before, I’m
actually using something built-into org-mode rather than using
something like Hugo/Jekyll which has sub-par support.&lt;/p&gt;
&lt;p&gt;Honestly, I feel dumb for not discovering thing much much earlier but
only a couple hours ago, I discovered &lt;a href=&quot;https://github.com/emacs-china/org-mode/blob/master/lisp/ox-publish.el&quot;&gt;ox-publish.el&lt;/a&gt; which adds
website publishing functionality to Org!&lt;/p&gt;
&lt;p&gt;I just finished setting stuff up and migrated my old posts from the
awful Writefreely instance of this thing. While I was considering
migrating posts from &lt;a href=&quot;https://blog.yukiisbo.red&quot;&gt;my old blog&lt;/a&gt;, I decided not to mainly because
it’ll be a chore making it ‘look’ the same.&lt;/p&gt;
&lt;h1 id=&quot;general-updates&quot;&gt;General updates&lt;/h1&gt;
&lt;p&gt;I’ve been really busy these past months and will be busy for the next
couple more months with personal stuff.&lt;/p&gt;
&lt;p&gt;However, I should have more free time in a couple of weeks which
should allow me to have much more intimate writing sessions and
overall more time for personal development.&lt;/p&gt;
&lt;h1 id=&quot;writing-bucket-list-nix&quot;&gt;Writing Bucket list: Nix&lt;/h1&gt;
&lt;p&gt;I always been considering writing a blog post about Nix, the
package manager which utilizes the purely functional deployment model.&lt;/p&gt;
&lt;p&gt;However, I don’t think I’m experienced enough with Nix to be writing
posts about it, especially considering its intimate situation of
lacking major documentation.&lt;/p&gt;
&lt;p&gt;Some people may think that I should &lt;em&gt;still&lt;/em&gt; write about it but I want to
write something extensive and in-depth about it because it truly
deserves the attention and care.&lt;/p&gt;
&lt;p&gt;For now, if you’re an introduction to Nix, I recommend the &lt;a href=&quot;https://nixos.org/guides/nix-pills/index.html&quot;&gt;Nix Pills&lt;/a&gt;
series or even the original papers: &lt;a href=&quot;https://edolstra.github.io/pubs/phd-thesis.pdf&quot;&gt;The Purely Functional Software
Deployment Model&lt;/a&gt;, &lt;a href=&quot;https://edolstra.github.io/pubs/nixos-jfp-final.pdf&quot;&gt;NixOS: A Purely Functional Linux Distribution&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I describe the current situation with Nix to be similar to early
Haskell (pre-Real World Haskell) where you really need to dig through
papers, source code, mailing lists, etc. to find quality and accurate
information.&lt;/p&gt;
&lt;p&gt;I really do hope someone out there is writing a book about Nix but I
could see why no one is currently doing it as it is still in
early-late development stages. Hopefully, it’ll mature once &lt;a href=&quot;https://serokell.io/blog/practical-nix-flakes&quot;&gt;Nix Flakes&lt;/a&gt;
is not locked away behind the experimental gate :-)&lt;/p&gt;
&lt;h1 id=&quot;new-computer-setup&quot;&gt;New computer setup&lt;/h1&gt;
&lt;p&gt;I replaced my desktop with a new lightweight 14” laptop. It’s a Clevo
NV41MB which I bought from &lt;a href=&quot;https://www.pcw.fr/portables-pro/2342-clevo-nv41-serie-pro-14-intel-tigerlake-11th-gen-video-intel-iris-graphics-a-gtx1650-ti.html&quot;&gt;PCW.fr&lt;/a&gt;. It’s a pretty nice configuration
with 1 TB NVMe, 11th Gen Core i5, 16 GB of DDR4 RAM.&lt;/p&gt;
&lt;p&gt;I’m running Windows 10 as the primary operating system, mainly because
I need to run a notable amount of applications that only run on
Windows.&lt;/p&gt;
&lt;p&gt;Yes, Wine and Proton exists but sadly, they don’t suffice with my
requirements.&lt;/p&gt;
&lt;p&gt;On Windows, I use Windows Subsystem for Linux extensively to run Linux
applications, most notably GNU Emacs in GUI mode. I run &lt;a href=&quot;https://x410.dev/&quot;&gt;X410&lt;/a&gt; as my X11
server in order to enable GUI applications on WSL.&lt;/p&gt;
&lt;p&gt;I know there’s &lt;a href=&quot;https://github.com/microsoft/wslg&quot;&gt;WSLg&lt;/a&gt; but it’s not ready for prime time, yet.&lt;/p&gt;
&lt;p&gt;OpenBSD is installed as a secondary operating system that I use
sometimes. It runs quite stable, however, Intel Xe Graphics is known to
be buggy everywhere so yeah but surprisingly, a lot stabler than my
adventures with amdgpu, so that’s something!&lt;/p&gt;
&lt;p&gt;Also, yes, convieniences such as Wi-Fi, suspend, etc works fine as far
as I can tell. I have some annoyances with my keyboard not working
sometimes on X11 but I’m not sure if that’s because I’m running my
keyboard via my Thunderbolt Dock or something else. Oh well.&lt;/p&gt;
&lt;h1 id=&quot;anything-else&quot;&gt;Anything else…&lt;/h1&gt;
&lt;p&gt;Well, I don’t know anything else that I would like to share in this
rather lengthy blog post but I’ll just stop here.&lt;/p&gt;
&lt;p&gt;See you later,&lt;/p&gt;
&lt;p&gt;Yuki.&lt;/p&gt;</content:encoded></item><item><title>End of an era</title><link>https://yukiisbo.red/notes/end-of-an-era/</link><guid isPermaLink="true">https://yukiisbo.red/notes/end-of-an-era/</guid><pubDate>Mon, 12 Jun 2023 00:00:00 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;: I will stop self-hosting services as my priorities in life has changed which resulted in me not having the time and willpower to maintain them.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Well, this is it: The end of an era, no more working as a system administrator and site-reliability engineer for myself.&lt;/p&gt;
&lt;p&gt;I guess a bit of a background is warranted, so lets do that.&lt;/p&gt;
&lt;h1 id=&quot;background&quot;&gt;Background&lt;/h1&gt;
&lt;p&gt;Growing up, I was always the odd one out. I was completely enamored with computers and always have dreamed about working with them day to day as a job.
If you were there during those time, you’d know that computers was the subject that I always love talking about.&lt;/p&gt;
&lt;p&gt;I love learning the history of computers and how things came to be, learning how to use various operating systems, tools, and programming languages, and also getting into the nitty gritty of how stuff works.&lt;/p&gt;
&lt;p&gt;One of the things I liked growing up was watching videos on YouTube about hacking game consoles, writing operating systems, etc. These subjects always run around in my head subconciously and once I had the chance to do them, I was estatic.&lt;/p&gt;
&lt;p&gt;During the boom of Minecraft, I learned how to setup a Minecraft server and started what was &lt;a href=&quot;https://github.com/yukiisbored/blog/blob/master/content/posts/my-minecraft-days.md&quot;&gt;one of the more popular Minecraft servers in Indonesia&lt;/a&gt;. From there, I learned how to administer systems, mitigate against attacks (because yes, they did happen), write server code, etc.&lt;/p&gt;
&lt;p&gt;Ultimately, what once was a mere hobby for me led to where I am today. Today, I’m working at a &lt;a href=&quot;https://founderblocks.io&quot;&gt;German-based software house&lt;/a&gt; where I do the things that I dreamed of doing as a kid: administering systems and infrastructure and writing code. Today, I would be lying if I say that I don’t like doing it, I still do.&lt;/p&gt;
&lt;p&gt;However, now as an adult, a lot of things in my life has changed and one of them is how I value time and ultimately my priorities in life.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Today, I’m at the point where I’d rather not touch the computer after work.&lt;/li&gt;
&lt;li&gt;I no longer have the patience to use a &lt;a href=&quot;https://github.com/yukiisbored/blog/blob/master/content/posts/liberating-your-android.md&quot;&gt;degoogled Android phone&lt;/a&gt;, I use an iPhone now.&lt;/li&gt;
&lt;li&gt;I stopped using “public” social medias like &lt;a href=&quot;https://bsd.network/@yuki_is_bored/109366588425401717&quot;&gt;Twitter and Fediverse&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;I stopped &lt;a href=&quot;https://marc.info/?a=166534124300001&amp;r=1&amp;w=2&quot;&gt;daily driving FreeBSD/OpenBSD&lt;/a&gt;, I use Fedora or Windows now.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now, I’m planning to stop self-hosting services. I know there are some people out there who would think that I’m a hypocrite for “not standing up to my values” but the thing is people change, it’s just a part of life and this is how it came to be for me. Whether people think that I’m becoming a better/worse person is irrelevant because ultimately, this is my life and only I decide how I spend it.&lt;/p&gt;
&lt;p&gt;I’m not saying that this is objectively the best way to do things because the nature of these decisions are personal and only you can answer them, don’t accept the idea that there’s an objective “best way” whether it’s because of some moral value, technical reasons, or whatever because objectively, there isn’t.&lt;/p&gt;
&lt;p&gt;If you can self-host your service, live your life free from big tech companies, good, I’m happy that it works for you. However, and this is something I also learned myself, stop telling other people to be like you and realize everyone has different needs and goals, just because it works for you, doesn’t mean it’ll work for everyone.&lt;/p&gt;
&lt;p&gt;Also, I’m not always like this. If you know me for long enough, you know that I used to be the person who preach such things to other people and suggest them to do the things which I perceive as the best way of doing things. And yeah, as mentioned before, I changed and I realized that this is not true and I’m sorry.&lt;/p&gt;
&lt;h1 id=&quot;shifting-priorities&quot;&gt;Shifting priorities&lt;/h1&gt;
&lt;p&gt;So what’s up? What made me take this leap in my life?&lt;/p&gt;
&lt;p&gt;As you now know, I mostly spent my childhood, teenage, and young adult years with computers because it was the thing that I’m passionate about.&lt;/p&gt;
&lt;p&gt;Today, well, I’ve been wanting to branch out to more creative pursuits. I started learning things like mechanical engineering, pixel art, music composition and production, and game development. And well, from there, I made things:&lt;/p&gt;

&lt;video controls&gt;&lt;source src=&quot;/_astro/coolvase.DN7rl0c9.mp4&quot; type=&quot;video/mp4&quot;/&gt;&lt;p&gt;Your browser does not support the video tag.&lt;/p&gt;&lt;/video&gt;
&lt;iframe frameborder=&quot;0&quot; src=&quot;https://itch.io/embed/1651718?link_color=aa00ff&quot; width=&quot;100%&quot; height=&quot;167&quot;&gt;&lt;a href=&quot;https://yukiisbored.itch.io/qwe&quot;&gt;QWE by Yuki&lt;/a&gt;&lt;/iframe&gt;
&lt;p&gt;At the end of the day, I find myself more satisfied and happier creating things more than just mere computer programs.
Doing this kind of stuff takes a lot of time and dedication hence why for the past couple of months I’ve been thinking about how I want to spend my time.
Ultimately, I find myself being annoyed with being a system administrator of one for myself so yeah, this month I decided to simply stop doing it and I’m looking forward to how things go from here.&lt;/p&gt;
&lt;h1 id=&quot;changes&quot;&gt;Changes&lt;/h1&gt;
&lt;p&gt;With my big server shutting down at the end of this month, a couple of things are changing:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;All of my personal projects are on GitHub.
&lt;ul&gt;
&lt;li&gt;Originally, I was thinking about moving to sr.ht since I like the simplicity of it but they don’t support Git LFS yet.&lt;/li&gt;
&lt;li&gt;Then, I was thinking about moving to GitLab SaaS but &lt;a href=&quot;https://about.gitlab.com/pricing/faq-paid-storage-transfer/&quot;&gt;the costs for Git LFS&lt;/a&gt; are too much for me.&lt;/li&gt;
&lt;li&gt;On Matrix, I moved from &lt;code&gt;@yuki:backalley.club&lt;/code&gt; to &lt;code&gt;@yukiisbored:matrix.org&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;I’ll no longer be available on XMPP.
&lt;ul&gt;
&lt;li&gt;While there’s a lot of open XMPP servers, I decided to simply stop using it since I don’t communicate with a lot of people there and the clients for iOS are not good.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Old websites like &lt;code&gt;blog.yukiisbo.red&lt;/code&gt; will be shutdown.
&lt;ul&gt;
&lt;li&gt;I don’t know if I’ll move their content to this site but the content will be available in source form on GitHub.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Of course, there are plenty of other things changing but I won’t be mentioning them here since they’re only relevant to me and ever since I stopped using public social medias, I’d like to keep my life more private instead of sharing everything.&lt;/p&gt;
&lt;h1 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;If there’s anything you should pick up from this, it should be the fact that you should live your life how you want it to be instead of giving control over it to others.
Ultimately, only you know what is best for you.&lt;/p&gt;
&lt;p&gt;This doesn’t mean that you should be immune to criticism or suggestions, far from that.
Instead, spend time to learn more about yourself, get to know about yourself better, and learn to accept yourself.
It won’t be easy but it’s worth it, I promise.&lt;/p&gt;
&lt;p&gt;From there, you can start and figure out what you’re comfortable with, what works best for you, and your boundaries.
And most importantly: remember, there’s no right/wrong answer.&lt;/p&gt;</content:encoded></item><item><title>Fine-grained controls and why we don&apos;t need it</title><link>https://yukiisbo.red/notes/fine-grained-controls-and-why-we-dont-need-it/</link><guid isPermaLink="true">https://yukiisbo.red/notes/fine-grained-controls-and-why-we-dont-need-it/</guid><pubDate>Fri, 12 May 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I feel like when it comes to permissions and security, we often fall into the
believe that the more fine-grain control we have, the better.&lt;/p&gt;
&lt;p&gt;In reality, this just leave them &lt;a href=&quot;https://www.documentcloud.org/documents/20399900-fbi_flash_sonarqube_access_bc&quot;&gt;ripe to abuse&lt;/a&gt; as more often than not, we’ll
simply leave them to the (often bad) defaults as changing them is hard:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/_astro/jenkins_role.CAguXlbq_ZtlCb4.webp&quot; alt=&quot;Jenkins Role-Based Strategy plugin&apos;s interface. It is composed of 3 different sections. Each section has a matrix of checkboxes used for defining roles and permission set for each role&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; width=&quot;1055&quot; height=&quot;1216&quot;&gt;&lt;/p&gt;
&lt;p&gt;A simple glance is enough to invoke &lt;a href=&quot;https://en.wikipedia.org/wiki/Analysis_paralysis&quot;&gt;analysis paralysis&lt;/a&gt; as you stand there
trying to understand what the fuck do any of these mean.&lt;/p&gt;
&lt;p&gt;It’s the same reason why I have a distinct distaste for software like
&lt;a href=&quot;https://www.sonarsource.com/products/sonarqube/&quot;&gt;Sonarqube&lt;/a&gt;, &lt;a href=&quot;https://www.jenkins.io/&quot;&gt;Jenkins&lt;/a&gt;, &lt;a href=&quot;https://wiki.freebsd.org/Capsicum&quot;&gt;Capciscum&lt;/a&gt;, &lt;a href=&quot;https://selinuxproject.org/page/Main_Page&quot;&gt;SELinux&lt;/a&gt;. Controlling over them feels like
wielding a &lt;a href=&quot;https://finalfantasy.fandom.com/wiki/Buster_Sword&quot;&gt;buster sword&lt;/a&gt;, with its sheer weight and unbalanced nature.&lt;/p&gt;
&lt;p&gt;Compare Jenkins’ Role Controls to Sentry’s:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/_astro/sentry_role.BTujzNRW_nbvXR.webp&quot; alt=&quot;A list of predefined roles to assign a user with names such as &amp;#34;Billing&amp;#34;, &amp;#34;Member&amp;#34;, &amp;#34;Admin&amp;#34;, &amp;#34;Manager&amp;#34;, and &amp;#34;Owner&amp;#34;. Each role has a short description.&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; width=&quot;1181&quot; height=&quot;466&quot;&gt;&lt;/p&gt;
&lt;p&gt;Clear distinct roles each with a clear description.&lt;/p&gt;
&lt;p&gt;But how about clients or contractors? We don’t want them to be able to see
everything.&lt;/p&gt;
&lt;p&gt;Sentry’s solution is simple, they have the concept of teams:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/_astro/sentry_role_teams.BpmlM4KT_20UU3U.webp&quot; alt=&quot;The same interface from the previous picture but uncropped to show a list of teams assigned to a user&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; fetchpriority=&quot;auto&quot; width=&quot;1181&quot; height=&quot;584&quot;&gt;&lt;/p&gt;
&lt;p&gt;Projects belongs to teams, members are part of teams, each members’ role is set
at the organization level.&lt;/p&gt;
&lt;p&gt;When you think about it, this pretty much covers most use cases.&lt;/p&gt;
&lt;p&gt;A solution which gives users total freedom to do whatever they want is an easy
way to express a middle finger towards usability and user/developer experience.&lt;/p&gt;
&lt;p&gt;Sure, it’s cheap to establish and execute at the beginning during the initial
development of the project, but just imagine the sheer amount of human lives
wasted at maintaining this ugly beast of complexity once it is implemented?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;As a user, you’re faced with an unwieldy system that feels like you need to
have a degree for.&lt;/li&gt;
&lt;li&gt;As a developer, you’re faced with covering all possible use cases and being
faced with ridiculous edge cases.&lt;/li&gt;
&lt;li&gt;As customer support, you’re faced with numerous calls which lasts for hours
covering the intricacies of the system and guiding them to avoid pitfalls.&lt;/li&gt;
&lt;li&gt;As a technical writer, trying to come up with a digestible document for an
inhumane system.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Overall, I feel like both as developers and project managers, it is our sacred
duty to root out all complexity as much as possible.&lt;/p&gt;
&lt;p&gt;People don’t throw money for complexity, they throw money at tools which helps
them achieve their goals with the least amount of misery.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;But our competition has a lot of fine-grained complexity and sheer amount of features!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Look at &lt;a href=&quot;https://www.canva.com/&quot;&gt;Canva&lt;/a&gt; and &lt;a href=&quot;https://www.figma.com/&quot;&gt;Figma&lt;/a&gt; and ask why users prefer them over &lt;a href=&quot;https://www.adobe.com/products/photoshop.html&quot;&gt;Photoshop&lt;/a&gt;,
&lt;a href=&quot;https://www.adobe.com/products/indesign.html&quot;&gt;InDesign&lt;/a&gt;, and &lt;a href=&quot;https://www.adobe.com/products/illustrator.html&quot;&gt;Illustrator&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The reason is simple, they’re more approachable while still allowing them to
achieve their goals without &lt;a href=&quot;https://en.wiktionary.org/wiki/footgun&quot;&gt;footgunning&lt;/a&gt; themselves.&lt;/p&gt;
&lt;p&gt;You don’t gain market adoption by being equal. You do it by making your shit
stand out and making a constrained product which allow people to achieve the
same goals is one of the best way to do it.&lt;/p&gt;</content:encoded></item></channel></rss>