<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Aditya's blog]]></title><description><![CDATA[Who tricked sands into thinking?]]></description><link>https://hashnode.adityakumar.xyz</link><generator>RSS for Node</generator><lastBuildDate>Fri, 16 Oct 2026 14:59:28 GMT</lastBuildDate><atom:link href="https://hashnode.adityakumar.xyz/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Use GUI Programs in Incus Container]]></title><description><![CDATA[If you've ever faced the challenge of running graphical user interface (GUI) programs within a container, fear not! While it may seem like a daunting task at first, with this comprehensive guide, we'll walk through the process using Incus Container. ...]]></description><link>https://hashnode.adityakumar.xyz/use-gui-programs-in-incus-container</link><guid isPermaLink="true">https://hashnode.adityakumar.xyz/use-gui-programs-in-incus-container</guid><category><![CDATA[incus ]]></category><category><![CDATA[containers]]></category><dc:creator><![CDATA[Aditya Kumar]]></dc:creator><pubDate>Sun, 28 Apr 2024 04:24:50 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/NndKt2kF1L4/upload/eef94a6b4f393c15862c52a03222d378.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>If you've ever faced the challenge of running graphical user interface (GUI) programs within a container, fear not! While it may seem like a daunting task at first, with this comprehensive guide, we'll walk through the process using Incus Container. We will set up and configure your environment to run GUI-based applications seamlessly in a virtualized space. Let's get started!</p>
<h2 id="heading-create-a-gui-profile">Create a GUI profile</h2>
<p>To begin, you must create a new profile specifically for managing GUI programs within the Incus container. This can be done using the following command:</p>
<pre><code class="lang-bash">incus profile create gui
</code></pre>
<p>And edit with <code>incnus profile edit gui</code>. Throw the following contents in and save it.</p>
<pre><code class="lang-yaml"><span class="hljs-attr">config:</span>
  <span class="hljs-attr">environment.DISPLAY:</span> <span class="hljs-string">:0</span>
<span class="hljs-attr">description:</span> <span class="hljs-string">""</span>
<span class="hljs-attr">devices:</span>
  <span class="hljs-attr">X0:</span>
    <span class="hljs-attr">bind:</span> <span class="hljs-string">container</span>
    <span class="hljs-attr">connect:</span> <span class="hljs-string">unix:@/tmp/.X11-unix/X0</span>
    <span class="hljs-attr">listen:</span> <span class="hljs-string">unix:@/tmp/.X11-unix/X0</span>
    <span class="hljs-attr">security.gid:</span> <span class="hljs-string">"1000"</span>
    <span class="hljs-attr">security.uid:</span> <span class="hljs-string">"1000"</span>
    <span class="hljs-attr">type:</span> <span class="hljs-string">proxy</span>
  <span class="hljs-attr">mygpu:</span>
    <span class="hljs-attr">type:</span> <span class="hljs-string">gpu</span>
<span class="hljs-attr">name:</span> <span class="hljs-string">gui</span>
</code></pre>
<p>We are using host's display so we will be using sockets.</p>
<h2 id="heading-add-nixos-configuration">Add NixOS configuration</h2>
<p>Now add the following in <code>configuration.nix</code>, rebuild and switch.</p>
<pre><code class="lang-nix">users.users.<span class="hljs-attr">root</span> = {
  <span class="hljs-attr">subUidRanges</span> = [
    {
      <span class="hljs-attr">count</span> = <span class="hljs-number">1000</span>;
      <span class="hljs-attr">startUid</span> = <span class="hljs-number">1000</span>;
    }
  ];
  <span class="hljs-attr">subGidRanges</span> = [
    {
      <span class="hljs-attr">count</span> = <span class="hljs-number">1000</span>;
      <span class="hljs-attr">startGid</span> = <span class="hljs-number">1000</span>;
    }
  ];
};
</code></pre>
<p>This update enables the matching of users and groups between your host machine and container.</p>
<h2 id="heading-configure-default-incus-settings">Configure default Incus settings</h2>
<p>Create or edit the <code>~/.config/incus/default.conf</code> file to provide default settings tailored specifically for running GUI applications within an Incus container. Add these configurations to your <code>default.conf</code>:</p>
<pre><code class="lang-yaml"><span class="hljs-comment">## For regular unpriv containers:</span>
<span class="hljs-comment">#incus.id_map = u 0 100000 65536</span>
<span class="hljs-comment">#incus.id_map = g 0 100000 65536</span>
<span class="hljs-comment">## For GUI upriv containers</span>
<span class="hljs-string">incus.idmap</span> <span class="hljs-string">=</span> <span class="hljs-string">u</span> <span class="hljs-number">0</span> <span class="hljs-number">100000</span> <span class="hljs-number">1000</span>
<span class="hljs-string">incus.idmap</span> <span class="hljs-string">=</span> <span class="hljs-string">g</span> <span class="hljs-number">0</span> <span class="hljs-number">100000</span> <span class="hljs-number">1000</span>
<span class="hljs-string">incus.idmap</span> <span class="hljs-string">=</span> <span class="hljs-string">u</span> <span class="hljs-number">1000 </span><span class="hljs-number">1000 </span><span class="hljs-number">1</span>
<span class="hljs-string">incus.idmap</span> <span class="hljs-string">=</span> <span class="hljs-string">g</span> <span class="hljs-number">1000 </span><span class="hljs-number">1000 </span><span class="hljs-number">1</span>
<span class="hljs-string">incus.idmap</span> <span class="hljs-string">=</span> <span class="hljs-string">u</span> <span class="hljs-number">1001 </span><span class="hljs-number">101001</span> <span class="hljs-number">64535</span>
<span class="hljs-string">incus.idmap</span> <span class="hljs-string">=</span> <span class="hljs-string">g</span> <span class="hljs-number">1001 </span><span class="hljs-number">101001</span> <span class="hljs-number">64535</span>
<span class="hljs-string">incus.mount.entry</span> <span class="hljs-string">=</span> <span class="hljs-string">/dev/dri</span> <span class="hljs-string">dev/dri</span> <span class="hljs-string">none</span> <span class="hljs-string">bind,optional,create=dir</span>
<span class="hljs-string">incus.mount.entry</span> <span class="hljs-string">=</span> <span class="hljs-string">/dev/snd</span> <span class="hljs-string">dev/snd</span> <span class="hljs-string">none</span> <span class="hljs-string">bind,optional,create=dir</span>
<span class="hljs-string">incus.mount.entry</span> <span class="hljs-string">=</span> <span class="hljs-string">/tmp/.X11-unix</span> <span class="hljs-string">tmp/.X11-unix</span> <span class="hljs-string">none</span> <span class="hljs-string">bind,optional,create=dir</span>
<span class="hljs-string">incus.mount.entry</span> <span class="hljs-string">=</span> <span class="hljs-string">/dev/video0</span> <span class="hljs-string">dev/video0</span> <span class="hljs-string">none</span> <span class="hljs-string">bind,optional,create=file</span>
</code></pre>
<p>These configurations allow for the proper mapping of GUI applications within Incus and provide mounting entries that correspond to essential devices required by these programs (e.g., graphics card drivers).</p>
<p>On host machine, run</p>
<pre><code class="lang-bash">xhost +<span class="hljs-built_in">local</span>:
</code></pre>
<p>Add your container to <code>gui</code> profile:</p>
<pre><code class="lang-bash">incus profile add &lt;container&gt; gui
</code></pre>
<h2 id="heading-running-x-server-inside-your-container">Running X Server Inside Your Container:</h2>
<p>Now that you've set up your profile, it's time to install an X server inside your container to render graphical elements on the GUI applications. The installation process may vary depending on your distribution and version. For example, if using Arch Linux, run these commands:</p>
<pre><code class="lang-bash">yay -S xorg-server xorg-xauth xorg-drivers mesa-utils
</code></pre>
<p>This will install X server components required to render the GUI elements for your applications within Incus.</p>
<h2 id="heading-executing-a-gui-program-in-your-container">Executing a GUI Program in Your Container</h2>
<p>Finally, let's test our setup by running an example GUI program inside the container with the appropriate user permissions. To do this, use the following command:</p>
<pre><code class="lang-bash">incus <span class="hljs-built_in">exec</span> &lt;container&gt; --user 1000 -- glxgears
</code></pre>
<p>After executing the above command, you should see a window displaying spinning gears from the GLXGEARS program - indicating that your GUI application is now successfully running within Incus Container.</p>
<p>Happy hacking!</p>
]]></content:encoded></item><item><title><![CDATA[Mount Shared Directories in Incus]]></title><description><![CDATA[When working with containers, managing file sharing between the host system and container can often pose a challenge. However, there is an easy-to-use solution that simplifies this process using just one line of code! This blog post will guide you on...]]></description><link>https://hashnode.adityakumar.xyz/mount-shared-directories-in-incus</link><guid isPermaLink="true">https://hashnode.adityakumar.xyz/mount-shared-directories-in-incus</guid><category><![CDATA[incus ]]></category><category><![CDATA[containers]]></category><dc:creator><![CDATA[Aditya Kumar]]></dc:creator><pubDate>Sat, 27 Apr 2024 18:32:13 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/1cqIcrWFQBI/upload/f26bfb52a21d32bc31f6c58ba5225397.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>When working with containers, managing file sharing between the host system and container can often pose a challenge. However, there is an easy-to-use solution that simplifies this process using just one line of code! This blog post will guide you on how to share files effortlessly by leveraging Incus’s <code>incus config</code> command.</p>
<h2 id="heading-the-one-liner-solution">The One Liner Solution:</h2>
<p>If you’re looking to share a specific directory containing your container data, here is the one-liner syntax for adding the file source and path within the container configuration:</p>
<pre><code class="lang-plaintext">incus config device add &lt;container&gt; &lt;device name&gt; &lt;device type&gt; source=/&lt;path/to/directory/&gt; path=/&lt;mount/point/in/container&gt;
</code></pre>
<p>To give you a better understanding, let’s look at an example. Suppose we have a container named <code>container1</code> and want to share files located in the <code>/srv/movies</code> directory with a mount point of <code>/mnt/movies</code> within the container itself:</p>
<pre><code class="lang-plaintext">incus config device add container1 movies disk source=/srv/movies path=/mnt/movies
</code></pre>
<h2 id="heading-alternative-method-for-advanced-users">Alternative Method for Advanced Users:</h2>
<p>If you’re feeling adventurous and want to directly edit the configuration, Incus provides an alternative method. With this approach, you can leverage YAML syntax within your container configuration file with <code>incus config edit &lt;container&gt;</code>. Here is how it works using our previous example:</p>
<pre><code class="lang-yaml"><span class="hljs-attr">dveices:</span>
  <span class="hljs-attr">movies:</span>
    <span class="hljs-attr">path:</span> <span class="hljs-string">/mnt/movies</span>
    <span class="hljs-attr">source:</span> <span class="hljs-string">/srv/movies</span>
    <span class="hljs-attr">type:</span> <span class="hljs-string">disk</span>
</code></pre>
<p>Happy hacking!</p>
]]></content:encoded></item><item><title><![CDATA[Install Incus on NixOS]]></title><description><![CDATA[Incus, a manager and hypervisor for system containers (LXC) and virtual machines (QEMU), is an excellent tool for managing and orchestrating your applications and services. It is a fork of LXD by the original maintainers.
I found the documentation re...]]></description><link>https://hashnode.adityakumar.xyz/install-incus-on-nixos</link><guid isPermaLink="true">https://hashnode.adityakumar.xyz/install-incus-on-nixos</guid><category><![CDATA[incus ]]></category><category><![CDATA[NixOS]]></category><dc:creator><![CDATA[Aditya Kumar]]></dc:creator><pubDate>Thu, 29 Feb 2024 17:44:51 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/jOqJbvo1P9g/upload/6a01b0908045174ea5c13bd1f81668fa.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Incus, a manager and hypervisor for system containers (LXC) and virtual machines (QEMU), is an excellent tool for managing and orchestrating your applications and services. It is a fork of LXD by the original maintainers.</p>
<p>I found the documentation regarding NixOS lacking and thought I should put it somewhere for future reference. If you have experience with LXD, it will mostly be similar but expect things to get different as time passes.</p>
<h2 id="heading-installation">Installation</h2>
<p>Incus is already present in <code>nixpkgs</code> and can be installed by adding</p>
<pre><code class="lang-nix">virtualisation.incus.<span class="hljs-attr">enable</span> = <span class="hljs-literal">true</span>
</code></pre>
<p>to your <code>configuration.nix</code>. Consider adding yourself to <code>incus-admin</code> group to avoid using <code>sudo</code> every time. It can be done by</p>
<pre><code class="lang-nix">users.user.USER.<span class="hljs-attr">extraGroups</span> = [ <span class="hljs-string">"incus-admin"</span> ];
</code></pre>
<p>Of course, replace <code>USER</code> with your username.</p>
<p>You need IP forwarding for NAT'ing to work</p>
<pre><code class="lang-nix">boot.kernel.<span class="hljs-attr">sysctl</span> = {
    <span class="hljs-string">"net.ipv4.conf.all.forwarding"</span> = <span class="hljs-literal">true</span>;
    <span class="hljs-string">"net.ipv4.default.forwarding"</span> = <span class="hljs-literal">true</span>;
};
</code></pre>
<p>Enable kernel module for IP forwarding to work</p>
<pre><code class="lang-nix">boot.<span class="hljs-attr">kernelModules</span> = [ <span class="hljs-string">"nf_nat_ftp"</span> ];
</code></pre>
<p>Set up a bridge</p>
<pre><code class="lang-nix">networking.<span class="hljs-attr">bridges</span> = { incusbr0.<span class="hljs-attr">interfaces</span> = []; };
</code></pre>
<p>This is used to provide NAT'd internet to the guest. It is manipulated directly by incus, so no need to specify any bridged interfaces here.</p>
<p>Add firewall rules to enable networking in the container</p>
<pre><code class="lang-nix">networking.firewall.<span class="hljs-attr">extraCommands</span> = <span class="hljs-string">''
    iptables -A INPUT incusbr0 -j ACCEPT
    iptables -A FORWARD -o incusbr0 -j ACCEPT
    iptables -A FORWARD -i incusbr0 -j ACCEPT
    iptables -A OUTPUT -o incusbr0 -j ACCEPT
''</span>;
</code></pre>
<p>Enable lxcfs to use it</p>
<pre><code class="lang-nix">virtualisation.lxc.lxcfs.<span class="hljs-attr">enable</span> = <span class="hljs-literal">true</span>;
</code></pre>
<p>Now switch to the new configuration with</p>
<pre><code class="lang-nix">nixos-rebuild switch
</code></pre>
<h2 id="heading-setting-up-incus">Setting up incus</h2>
<p>Incus requires initial setup for networking and storage. It can be done interactively by running</p>
<pre><code class="lang-bash">incus admin init
</code></pre>
<p>List all available images</p>
<pre><code class="lang-bash">incus image list images:
</code></pre>
<p>Create a new image <code>alpine</code> based on Alpine Linux</p>
<pre><code class="lang-bash">incus launch images:alpine/3.19 alpine
</code></pre>
<p>Interact with the newly created image</p>
<pre><code class="lang-bash">incus <span class="hljs-built_in">exec</span> alpine -- ash
</code></pre>
<p>This will drop you in an <code>ash</code> shell in the container.</p>
<p>You can copy containers by running</p>
<pre><code class="lang-bash">incus copy <span class="hljs-variable">$CONTAINER1</span> <span class="hljs-variable">$CONTAINER2</span>
</code></pre>
<p>List containers</p>
<pre><code class="lang-bash">incus list
</code></pre>
<p>Stop container</p>
<pre><code class="lang-bash">incus stop <span class="hljs-variable">$CONTAINER</span>
</code></pre>
<p>Delete container</p>
<pre><code class="lang-bash">incus delete <span class="hljs-variable">$CONTAINER</span>
</code></pre>
<h2 id="heading-configuration">Configuration</h2>
<p>Launch a new container with resource constrants</p>
<pre><code class="lang-bash">incus launch images:alpine/3.19 alp1 --config limits.cpu=1 --config limits.memory=192MiB
</code></pre>
<p>Check configuration</p>
<pre><code class="lang-bash">incus config show alp1
</code></pre>
<p>Update configuration</p>
<pre><code class="lang-bash">incus config <span class="hljs-built_in">set</span> alp1 limits.memory=128MiB
</code></pre>
<h2 id="heading-interaction">Interaction</h2>
<p>Run arbitrary commands</p>
<pre><code class="lang-bash">incus <span class="hljs-built_in">exec</span> alpine -- apk update
</code></pre>
<p>Pull a file from container</p>
<pre><code class="lang-bash">incus file pull alpine/etc/hosts .
</code></pre>
<p>Push file back to the container</p>
<pre><code class="lang-bash">incus file push hosts alpine/etc/hosts
</code></pre>
<h2 id="heading-snapshots">Snapshots</h2>
<p>Create a snapshot</p>
<pre><code class="lang-bash">incus snapshot create alpine alpine_snapshot
</code></pre>
<p>Restore the container to the snapshot</p>
<pre><code class="lang-bash">incus snapshot restore alpine alpine_snapshot
</code></pre>
<p>Delete the snapshot</p>
<pre><code class="lang-bash">incus delete alpine/alpine_snapshot
</code></pre>
<h2 id="heading-references">References</h2>
<ol>
<li><p><a target="_blank" href="https://discourse.nixos.org/t/howto-setup-lxd-on-nixos-with-nixos-guest-using-unmanaged-bridge-network-interface/21591">Howto setup LXD on NixOS with NixOS guest using unmanaged bridge network interface</a></p>
</li>
<li><p><a target="_blank" href="https://linuxcontainers.org/incus/docs/main/tutorial/first_steps/">First steps with Incus</a></p>
</li>
</ol>
]]></content:encoded></item><item><title><![CDATA[Make Bash prettier on NixOS]]></title><description><![CDATA[Using ble.sh and Starship.
Bash by itself is pretty basic. Syntax highlighting, auto-suggestion and history matching are pretty helpful features in any shell. Users might be worried about the bloat these features bring and add delay to the startup of...]]></description><link>https://hashnode.adityakumar.xyz/make-bash-prettier-on-nixos</link><guid isPermaLink="true">https://hashnode.adityakumar.xyz/make-bash-prettier-on-nixos</guid><category><![CDATA[NixOS]]></category><category><![CDATA[Bash]]></category><dc:creator><![CDATA[Aditya Kumar]]></dc:creator><pubDate>Thu, 29 Feb 2024 17:00:33 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/XJXWbfSo2f0/upload/86f07a7d9d46f9d5c0e46e086042ba3d.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Using <a target="_blank" href="http://ble.sh"><code>ble.sh</code></a> and Starship.</p>
<p>Bash by itself is pretty basic. Syntax highlighting, auto-suggestion and history matching are pretty helpful features in any shell. Users might be worried about the bloat these features bring and add delay to the startup of the shell.</p>
<p>I've been using these features for quite a while and have yet to see a performance hit. So it should be safe to assume you won't be having any of these problems either.</p>
<p>The reason why I am configuring bash instead of using other shells that have a better support these features is <code>nix develop</code> and <code>nix shell</code> expect bash and most of its functionalities are built around bash. So I do not recommend using a different shell for these.</p>
<h2 id="heading-bleshhttpblesh"><a target="_blank" href="http://ble.sh"><code>ble.sh</code></a></h2>
<p><a target="_blank" href="http://ble.sh">ble.sh</a> or <em>Bash Line Editor</em> is a command line editor written in pure Bash and replaces GNU Readline. Although it is written in Bash, it relies on POSIX <code>stty</code> to set up TTY states before and after the execution of user commands.</p>
<p>Installing <a target="_blank" href="http://ble.sh"><code>ble.sh</code></a> on NixOS is pretty straight forward as documented in the git repo.</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Spawn a development shell to bring in dependencies</span>
nix develop nixpkgs<span class="hljs-comment">#bash</span>
<span class="hljs-comment"># Bring build dependencies to path</span>
nix shell nixpkgs<span class="hljs-comment">#git nixpkgs#gnumake</span>

<span class="hljs-comment"># Try without installing</span>
git <span class="hljs-built_in">clone</span> --recursive --depth 1 --shallow-submodules https://github.com/akinomyoga/ble.sh.git
make -C ble.sh
<span class="hljs-built_in">source</span> ble.sh/out/ble.sh

<span class="hljs-comment"># Install to ~/.bashrc</span>
git <span class="hljs-built_in">clone</span> --recursive --depth 1 --shallow-submodules https://github.com/akinomyoga/ble.sh.git
make -C ble.sh install PREFIX=~/.<span class="hljs-built_in">local</span>
<span class="hljs-built_in">echo</span> <span class="hljs-string">'source ~/.local/share/blesh/ble.sh'</span> &gt;&gt; ~/.bashrc
</code></pre>
<p>Now add the following line to <code>home.nix</code>:</p>
<pre><code class="lang-nix">programs.<span class="hljs-attr">bash</span> = {
    <span class="hljs-attr">bashrcExtra</span> = <span class="hljs-string">''
        . ~/.bashrc
    ''</span>;
};
</code></pre>
<p>Switch to the new configuration:</p>
<pre><code class="lang-bash">home-manager switch
</code></pre>
<p>Now the changes should persist across sessions.</p>
<p><a target="_blank" href="http://ble.sh"><code>ble.sh</code></a> brings syntax highlighting, auto-completion, auto-suggestion, menu-complete and more.</p>
<h2 id="heading-starship">Starship</h2>
<p><a target="_blank" href="https://starship.rs">Starship</a> customizes shell prompt. The defaults are surprisingly sane for what it does. It is fast and does not get in the way. The prompt changes based on your directory. You can install it by adding it to <code>home.nix</code>:</p>
<pre><code class="lang-nix">home.<span class="hljs-attr">packages</span> = <span class="hljs-keyword">with</span> pkgs; [ starship ];
</code></pre>
<p>Append the line to <code>~/.bashrc</code></p>
<pre><code class="lang-bash"><span class="hljs-built_in">eval</span> <span class="hljs-string">"<span class="hljs-subst">$(starship init bash)</span>"</span>
</code></pre>
<p>Personally, I never felt the need to change it but you can choose from the <a target="_blank" href="https://starship.rs/config/">many existing configurations</a>. Oh, and have <a target="_blank" href="https://www.nerdfonts.com/">Nerd Font</a> enabled.</p>
<p><img src="https://blog.adityakumar.xyz/img/bash-nixos.png" alt="Screenshot of shell featuring Starship and ble.sh" /></p>
]]></content:encoded></item><item><title><![CDATA[Troubleshooting Internet Connectivity Issues in Virtual Machines (VMs) and Docker Containers]]></title><description><![CDATA[The ability to run virtual machines (VMs) and docker containers is an integral part of today’s modern computing landscape. However, issues with internet connectivity inside these environments often cause significant inconvenience for users who depend...]]></description><link>https://hashnode.adityakumar.xyz/troubleshooting-internet-connectivity-issues-in-virtual-machines-vms-and-docker-containers</link><guid isPermaLink="true">https://hashnode.adityakumar.xyz/troubleshooting-internet-connectivity-issues-in-virtual-machines-vms-and-docker-containers</guid><category><![CDATA[libvirt]]></category><category><![CDATA[Docker]]></category><dc:creator><![CDATA[Aditya Kumar]]></dc:creator><pubDate>Wed, 03 Jan 2024 10:06:17 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/h3vT1Kp0FxA/upload/e16f621a851da8e3ba0f01d08ada0964.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The ability to run virtual machines (VMs) and docker containers is an integral part of today’s modern computing landscape. However, issues with internet connectivity inside these environments often cause significant inconvenience for users who depend on this technology for their daily operations or development workflows. In this article, I will discuss about a specific issue I faced while working on NixOS and Archlinux distributions where internet access was not available within libvirt VMs and docker containers. I’ll also detail the investigation process that eventually led to identifying and resolving the problem.</p>
<h2 id="heading-problem-statement-amp-initial-investigation">Problem Statement &amp; Initial Investigation</h2>
<p>Before I begin, I must state that I am using libvirt, docker and NetworkManager. Maybe the problem lies somewhere else if you are using something else like wpa_supplicant or systemd-resolved.</p>
<p>Recently I faced an issue where I could not access the internet within libvirt VMs and docker containers on both NixOS and Archlinux distributions. I had already explored several potential solutions, including checking iptables configurations, but found no blockages of internet traffic. The realization that the same problem occurred in different operating systems suggested that it was more likely an issue with network configuration rather than software faults.</p>
<p>Initial Steps Taken:</p>
<ol>
<li><p>Examine <code>ip a</code> and <code>ip r</code> outputs for further information regarding network interfaces, IP addresses, and routes.</p>
</li>
<li><p>Check iptables configurations for any blockages or misconfigurations that might be affecting internet access within the VMs/containers.</p>
</li>
<li><p>Look into Ubuntu-related threads to compare similar issues with different operating systems to determine if it’s a configuration problem.</p>
</li>
<li><p>Research networkmanager, libvirt, and docker to better understand their interplay in managing networking aspects of virtual environments and containers.</p>
</li>
<li><p>Investigate possible solutions by modifying configurations based on user experience, documentation, and other online resources.</p>
</li>
</ol>
<h2 id="heading-resolving-the-issue-the-solution-found">Resolving the Issue: The Solution Found</h2>
<p>After a thorough examination of different potential causes and attempting several fixes, I stumbled upon an effective solution for the networking issues in VMs and containers. By adding <code>virbr0</code> and <code>docker0</code> as unmanaged interfaces within networkmanager configuration, I was able to successfully manage internet connectivity across these environments without interference from libvirt or docker.</p>
<p>Add the following line to <code>configuration.nix</code>:</p>
<pre><code class="lang-nix">networking.networkmanager.<span class="hljs-attr">unamaged</span> = [ <span class="hljs-string">"virbr0"</span> <span class="hljs-string">"docker0"</span> ];
</code></pre>
<p>For other distributions using NetworkManager, see <a target="_blank" href="https://linux.die.net/man/5/networkmanager.conf">NetworkManager.conf(5)</a> and <a target="_blank" href="https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/configuring_and_managing_networking/configuring-networkmanager-to-ignore-certain-devices_configuring-and-managing-networking">RedHat documentation</a>:</p>
<pre><code class="lang-ini"><span class="hljs-section">[keyfile]</span> <span class="hljs-attr">unmanaged-devices</span>=interface-name:virbr0<span class="hljs-comment">;interface-name:docker0</span>
</code></pre>
<h2 id="heading-key-learnings-amp-takeaways">Key Learnings &amp; Takeaways:</h2>
<ul>
<li><p>Virtual bridges should be managed automatically by software like libvirt; manual configurations could lead to unexpected consequences and complications in networking settings.</p>
</li>
<li><p>Adding another bridge is not a suitable solution for resolving connectivity issues within VMs/containers, as this may create additional complexity and introduce potential conflicts with other network management systems.</p>
</li>
<li><p>While libvirt automatically configures dnsmasq to establish internet access in virtual machines, it’s essential to understand how these components interact to maintain a stable connection across different environments.</p>
</li>
<li><p>It is crucial for users facing similar networking issues to approach the problem from multiple angles and carefully evaluate potential solutions before making any changes. This ensures an informed decision-making process that prioritizes stability, security, and usability within their computing environment.</p>
</li>
</ul>
<h2 id="heading-a-question-remains">A question remains</h2>
<p>Why did the problem surface only now? I have been using NetworkManager for a few years. Maybe something changed on their side.</p>
]]></content:encoded></item><item><title><![CDATA[LUKS Encryption]]></title><description><![CDATA[I’ve been using LUKS for quite a while so thought might as well put it here.
LUKS Explained
LUKS (Linux Unified Key Setup) encryption refers to a secure, flexible, and robust full-disk encryption system designed for Linux operating systems. It provid...]]></description><link>https://hashnode.adityakumar.xyz/luks-encryption</link><guid isPermaLink="true">https://hashnode.adityakumar.xyz/luks-encryption</guid><category><![CDATA[Linux]]></category><category><![CDATA[encryption]]></category><dc:creator><![CDATA[Aditya Kumar]]></dc:creator><pubDate>Fri, 22 Dec 2023 12:11:18 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/mT7lXZPjk7U/upload/d2dc780ecff7075542ff42e9870cf157.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I’ve been using LUKS for quite a while so thought might as well put it here.</p>
<h2 id="heading-luks-explained">LUKS Explained</h2>
<p>LUKS (Linux Unified Key Setup) encryption refers to a secure, flexible, and robust full-disk encryption system designed for Linux operating systems. It provides an additional layer of security by encrypting the entire storage device or partition instead of just individual files or directories within the file system hierarchy. This makes it much more difficult for unauthorized access or data theft, ensuring privacy and protection against potential threats from malicious actors.</p>
<p>In simple terms, LUKS creates a secure encryption key that is required to decrypt your encrypted storage device before you can use it normally. The process of turning on this security feature starts with initializing the disk partition you want to protect using the ‘cryptsetup’ command line tool. Once initialized, you will need to create a strong passphrase or enter the encryption key which is used for unlocking the encrypted data later when you need access to your system.</p>
<p>LUKS uses AES (Advanced Encryption Standard) and two other ciphers - Serpent and Twofish as its primary options, although users can choose different encryption algorithms based on their requirements and preferences. The LUKS standard also offers several modes of operation including:</p>
<ol>
<li><p>XTS Mode with a 512-bit key size: This is the default mode for LUKS, providing strong security without sacrificing performance. It uses the AES block cipher in an XEX (XOR Encrypted eXchange) mode and combines two keys to encrypt each data block.</p>
</li>
<li><p>CBC Mode with a 512-bit key size: This is an alternative mode that employs standard Cipher Block Chaining encryption. While it offers slightly less security compared to XTS, its performance may be faster on older hardware since the algorithm is simpler and requires fewer computational resources.</p>
</li>
<li><p>LRW Mode with a 512-bit key size: This provides an option for compatibility with Microsoft Windows BitLocker Drive Encryption (BDE). It uses AES in Cipher Feedback mode, which ensures that changes to one data block do not affect other blocks’ encryption state.</p>
</li>
</ol>
<p>It is essential to note that once a storage device or partition has been encrypted using LUKS, it will remain encrypted even if the system crashes or shuts down unexpectedly without saving the unlocking key properly. In this case, you would need the passphrase or recovery keys (optional) to regain access and recover your data.</p>
<h2 id="heading-luks2-over-luks">LUKS2 over LUKS</h2>
<p>Although LUKS was initially introduced with the intention of providing an easy-to-use, flexible and secure mechanism to protect sensitive information stored on hard drives or other storage devices, over time, two main versions have been developed – LUKS1 (the original version) and LUKS2 (the newer enhanced version).</p>
<p>LUKS2 (Linux Unified Key Setup version 2) is a cryptographic disk encryption system designed specifically for Linux operating systems, which provides an extra layer of security by encrypting the data stored on your hard drive or other storage devices. It was created to improve upon its predecessor, LUKS1, by offering better usability and more advanced features like key wrapping and full-disk encryption capabilities.</p>
<p>LUKS2 functions as a framework that provides a standardized method of creating and managing encrypted partitions on your system. When you use LUKS2 to encrypt your hard drive or partition, the data stored within it is encoded with complex algorithms making it unreadable without access to its encryption key. This means that even if someone gains physical access to your storage device, they will not be able to read the information unless they have the correct decryption key.</p>
<p>LUKS1 has several limitations:</p>
<ul>
<li><p><strong>Weak key management:</strong> Luks1 uses a fixed-size key for all devices, which can be problematic in scenarios where multiple users need to access the same device or when data ownership changes.</p>
</li>
<li><p><strong>No support for multi-factor authentication (MFA):</strong> LUKS1 does not provide any built-in MFA capabilities, which can be a significant security concern in today’s threat landscape.</p>
</li>
</ul>
<p>LUKS2 offers several advantages over LUKS1:</p>
<ul>
<li><p><strong>Better performance:</strong> One of the main improvements in LUKS2 is the reduced performance impact on the system during encryption and decryption processes. With LUKS1, there was a noticeable slowdown in system performance when dealing with encrypted disks. In contrast, LUKS2 has been optimized to provide better performance without compromising security, making it more suitable for everyday use.</p>
</li>
<li><p><strong>Improved security:</strong> LUKS2 includes several new security features compared to LUKS1. For instance, the new version supports per-file encryption and decryption, allowing users to encrypt individual files or directories rather than entire disks. This can be particularly useful when dealing with sensitive data that does not require full disk encryption. Additionally, LUKS2 has been updated to support the latest cryptographic algorithms, such as ChaCha20, which provides enhanced security compared to older ciphers like AES.</p>
</li>
<li><p><strong>Multi-factor authentication (MFA):</strong> LUKS2 provides built-in MFA capabilities through the use of hardware security tokens or other trusted authenticators, enhancing overall security posture.</p>
</li>
<li><p><strong>Enhanced support for larger drives:</strong> LUKS2 has been optimized for modern storage devices (e.g., SSDs) with higher capacities, ensuring faster encryption/decryption times and better performance under heavy workloads.</p>
</li>
<li><p><strong>Key Management:</strong> Another significant advantage of LUKS2 is its improved key management capabilities. In comparison to LUKS1’s limited key handling options (where you either needed to remember your passphrase or use a single keyfile), LUKS2 provides more flexibility with multiple key slots and the ability to use different keys for each slot, thus improving data security and making it easier to rotate encryption keys. This feature helps in better management of encryption keys and reduces the risk associated with storing sensitive information on a computer system.</p>
</li>
<li><p><strong>Flexible key sizes:</strong> LUKS2 supports flexible key sizes (e.g., 128-bit, 256-bit), enabling more secure key storage and reducing the risk of key exposure. It also allows multiple users to share a single device while maintaining individual access control.</p>
</li>
<li><p><strong>Compatibility:</strong> As LUKS1 was developed years before LUKS2, there is often compatibility issue when working across different Linux distributions. In contrast, LUKS2 has been designed to be more compatible with multiple versions of Linux and various other operating systems like FreeBSD, NetBSD, and OpenSolaris, thus making it an ideal choice for users who need their encryption solution to work seamlessly across diverse platforms.</p>
</li>
<li><p><strong>Integration:</strong> One of the key selling points of LUKS2 is its integration with full disk encryption tools such as dm-crypt (Device Mapper Cryptographic Volume Manager) and cryptsetup, which are used by most Linux distributions for handling encrypted partitions. This makes it easier to implement and maintain encryption on multiple systems using the same encryption methodology.</p>
</li>
<li><p><strong>Efficiency:</strong> LUKS2 provides better performance in terms of encryption and decryption processes compared to its predecessor. While both versions are known to have minimal impact on system performance when idle, LUKS1’s XTS mode can be a bit slower during data read or write operations due to the requirement for additional metadata processing that isn’t present in AES-XTS encryption used by LUKS2.</p>
</li>
<li><p><strong>Enhanced support for larger drives:</strong> LUKS2 has been optimized for modern storage devices (e.g., SSDs) with higher capacities, ensuring faster encryption/decryption times and better performance under heavy workloads.</p>
</li>
<li><p><strong>Backwards compatibility:</strong> Although LUKS2 is not directly compatible with LUKS1, you can use the <code>cryptsetup</code> command alongside the original LUKS for a transition period. This allows users to gradually migrate their systems from LUKS1 to LUKS2 without losing access to existing encrypted volumes or experiencing any performance issues during the transition.</p>
</li>
</ul>
<p>LUKS serves as an essential tool in protecting data stored on your storage devices by providing powerful encryption capabilities with enhanced flexibility, compatibility, and security features. Its integration into popular Linux distributions and ease of use make it a valuable addition to any system administrator’s arsenal when securing sensitive information.</p>
]]></content:encoded></item><item><title><![CDATA[Linux From Scratch: Reasons You Should and Should Not Use It]]></title><description><![CDATA[Linux from Scratch (LFS) is a project that provides a step-by-step guide for building a completely customized Linux system from scratch, including building the Linux kernel, selecting and configuring hardware, writing system scripts, and more. LFS is...]]></description><link>https://hashnode.adityakumar.xyz/linux-from-scratch-reasons-you-should-and-should-not-use-it</link><guid isPermaLink="true">https://hashnode.adityakumar.xyz/linux-from-scratch-reasons-you-should-and-should-not-use-it</guid><category><![CDATA[LFS]]></category><dc:creator><![CDATA[Aditya Kumar]]></dc:creator><pubDate>Fri, 14 Jul 2023 07:19:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/505eectW54k/upload/6e0ae3d3dfdf5e63d38da4f71ea1aaa9.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Linux from Scratch (LFS) is a project that provides a step-by-step guide for building a completely customized Linux system from scratch, including building the Linux kernel, selecting and configuring hardware, writing system scripts, and more. LFS is designed for advanced Linux users who are looking to learn more about the inner workings of the Linux operating system and how to build a customized Linux distribution.</p>
<p>The project aims to create a custom Linux distribution from scratch. LFS provides users with a fully customizable and optimized Linux system that can be tailored to their specific needs and preferences.</p>
<h2 id="heading-the-lfs-project-explained">The LFS Project Explained</h2>
<p>It is designed to provide users with a fully customizable and optimized Linux system that can be tailored to their specific needs and preferences. The project provides a wide range of options for customizing the system, including the choice of base operating system, the selection of packages to be installed, and the configuration of various system settings. This process also enables developers to learn how to create their own custom distributions or modify existing ones.</p>
<p>LFS is a great resource for anyone who wants to learn more about building a Linux system from scratch. The project provides detailed instructions and scripts that make the process easy to follow, even for beginners. Additionally, the project provides a community of users who can offer support and guidance as needed.</p>
<p>The main goal of LFS is to teach users about Linux by having them compile and configure each component of the operating system manually, which helps to gain a deeper understanding of the system. By following the LFS book, users can learn about the Linux kernel, GNU tools, libraries, and other essential components.</p>
<p>The project begins with building the Linux kernel, which involves downloading the kernel source code, configuring it, and building it on your system. From there, you can add additional packages and software to your system, including a web server, a database server, and other applications.</p>
<p>It also encourages users to customize their system by writing their own scripts, configuring their own init scripts, and even adding their own custom applications. The LFS community provides detailed documentation on how to build and configure a custom Linux system, and the project is designed to be a learning experience for advanced Linux users.</p>
<p>It’s important to note that LFS is not intended for beginners, as it requires a solid understanding of Linux and experience with the command line. However, those who are willing to invest time and effort can gain valuable knowledge and experience by participating in this project.</p>
<h2 id="heading-a-gist">A gist</h2>
<p>The Linux From Scratch project starts by providing a detailed book, available online, that serves as a comprehensive guide for building a Linux system from scratch. The book outlines the process of manually building and configuring each component of the system, including the kernel, core libraries, and essential utilities. By following the instructions in the book, users gain a deep understanding of the Linux system and its components.</p>
<p>The process begins by setting up a minimal host system, which is typically an existing Linux distribution or Unix-like environment. The host system provides the necessary tools and utilities required for compiling the source code and building the LFS system. Once the host system is prepared, the LFS book guides users through the steps of creating a temporary system, which includes compiling and installing the basic toolchain, such as the GCC compiler and GNU Binutils.</p>
<p>After setting up the temporary system, the book walks users through the process of compiling and installing the Linux kernel. This involves configuring the kernel according to the desired system specifications and hardware, compiling it, and installing it onto the target system. From there, users proceed to compile and install various core libraries, such as glibc (GNU C Library), which provide essential functionality to the system.</p>
<p>As the process continues, users gradually build and configure additional components, including system utilities, shell, boot scripts, and configuration files. The LFS book provides clear instructions and explanations for each step, allowing users to understand the purpose and functionality of each component they are building.</p>
<p>By following the Linux From Scratch project, users gain a comprehensive understanding of the Linux system from the ground up. They learn about the intricacies of compilation, linking, dependency management, and configuration. Furthermore, LFS allows users to create a highly customizable Linux system, tailored to their specific needs, preferences, and desired level of system complexity.</p>
<p>It’s worth noting that Linux From Scratch is primarily intended for educational purposes and as a learning experience. It requires a significant time commitment and a strong willingness to delve into the technical details of the system. While it can be a valuable exercise in understanding Linux internals, it may not be practical or necessary for every user or development scenario.</p>
<p>Additionally, LFS is part of a broader family of related projects, such as Beyond Linux From Scratch (BLFS), which expands on the initial LFS system by providing instructions for installing and configuring additional software packages and building a more complete Linux distribution.</p>
<h2 id="heading-is-linux-from-scratch-lfs-a-good-way-to-learn-linux">Is Linux from Scratch (LFS) a good way to learn Linux?</h2>
<p>Linux from Scratch (LFS) can be a good way to learn Linux if you are an advanced user looking to dive deep into the inner workings of the Linux operating system. LFS provides a step-by-step guide for building a completely customized Linux system from scratch, which can be a rewarding learning experience if you are interested in learning more about Linux.</p>
<p>Like already highlighted, LFS is not for everyone. It requires a significant amount of time and effort to complete, and it can be challenging for beginners who are just getting started with Linux. If you are new to Linux, there are other resources and courses that may be more appropriate for your skill level and learning style.</p>
<p>In general, LFS is a good way to learn Linux if you are already familiar with the basics of Linux and are looking for a more hands-on, in-depth learning experience.</p>
<p>With that being said, let’s dive into why you should and should not use Linux From Scratch.</p>
<hr />
<p>Using Linux From Scratch (LFS) offers several advantages and disadvantages. Let’s highlight some of the reasons why one should and should not use LFS:</p>
<h2 id="heading-reasons-to-use-linux-from-scratch">Reasons to use Linux From Scratch:</h2>
<h3 id="heading-knowledge-and-understanding">Knowledge and understanding</h3>
<p>Building your own Linux distribution from scratch provides a deep understanding of the inner workings of Linux, which can be beneficial for system administrators, developers, and enthusiasts alike.</p>
<p>By engaging in the Linux From Scratch (LFS) project, you have the opportunity to acquire a wealth of knowledge and understanding in several key areas. Firstly, you will gain a deep comprehension of Linux internals and the underlying mechanisms of the operating system. Through the process of building a Linux system from scratch, you will explore concepts such as process management, memory management, file systems, device drivers, and networking. This knowledge empowers you to have a comprehensive understanding of how the different components of a Linux system interact and work together.</p>
<p>Secondly, LFS enables you to develop proficiency in building and compiling software from source code. You will become familiar with essential tools like the GNU Compiler Collection (GCC), make, and various libraries. This expertise is valuable for working with custom software, optimizing performance, and resolving issues related to software compilation and linking.</p>
<p>The project also provides you with a solid understanding of dependency management. By manually managing dependencies during the LFS process, you will learn how to identify, resolve, and satisfy library and package dependencies. This knowledge is instrumental in dealing with complex software ecosystems and ensuring the compatibility of different software components.</p>
<p>Moreover, LFS fosters your ability to configure and customize a Linux system to suit specific requirements. You will gain insights into the configuration options and parameters that impact performance, security, and functionality. This skill is particularly useful for developing software in specialized environments or when working with unique system requirements.</p>
<p>As you encounter challenges and overcome obstacles during the LFS journey, you will enhance your troubleshooting and debugging skills. You will develop the ability to diagnose and resolve issues related to compilation, configuration, and integration of various components. This aptitude for troubleshooting is highly valuable in maintaining and managing Linux systems in real-world scenarios.</p>
<p>The knowledge gained through Linux From Scratch contributes to strengthening your system administration skills. You will become adept at package management, user management, system configuration, and maintenance. You will acquire the expertise to manage system services, create custom startup scripts, and fine-tune the system for optimal performance. These skills are highly relevant for professional Linux system administration roles.</p>
<p>Completing the Linux From Scratch project signifies a significant achievement. It demonstrates your in-depth understanding of the Linux system and the ability to construct a fully functional and customized Linux distribution from source code. This accomplishment showcases your expertise in Linux internals, software development, and system administration, making you an attractive candidate for roles involving Linux kernel development, device driver development, embedded systems, system administration, or software development in resource-constrained environments.</p>
<h3 id="heading-customization">Customization</h3>
<p>With LFS, you have full control over the selection and configuration of every component in your system. Customization in this context refers to tailoring the system’s components, configuration, and settings according to your preferences, needs, and intended use. It allows you to have full control over the software packages, kernel configuration, system services, and user environment.</p>
<p>Customization is helpful because it enables you to create a Linux system that is optimized for your specific use case. Whether you are developing software, setting up a server, or configuring an embedded system, being able to tailor the system to your exact needs can lead to improved performance, enhanced security, and increased productivity. You can selectively include or exclude software packages, fine-tune system parameters, and optimize resource utilization based on the specific requirements of your project or environment.</p>
<p>From a career perspective, proficiency in customization gained through Linux From Scratch can be highly beneficial. It showcases your ability to understand and manipulate the intricacies of a Linux system, highlighting your expertise in system administration, software development, or specialized fields like embedded systems. Employers often value individuals who can create tailored and efficient systems, as it demonstrates resourcefulness, problem-solving skills, and the ability to adapt to different scenarios.</p>
<p>The process of customization in LFS entails configuring various components of the Linux system. This includes selecting the appropriate software packages, setting up kernel options, configuring system services, creating custom startup scripts, and establishing user environments. The LFS book provides guidance on these customization steps, allowing you to make informed decisions and apply modifications to suit your specific requirements.</p>
<p>By engaging in customization through Linux From Scratch, you achieve a higher degree of control and ownership over your Linux system. You gain a deeper understanding of the interactions between different components, and you become proficient in managing software, system configuration, and user environments. Additionally, you develop the skills necessary to troubleshoot, adapt, and fine-tune the system for optimal performance.</p>
<p>Furthermore, the ability to customize a Linux system demonstrates your adaptability and flexibility in working with different software ecosystems and environments. It allows you to address specific challenges and requirements that may arise in your career, enabling you to take on diverse projects and contribute effectively to various development or system administration tasks.</p>
<h3 id="heading-security">Security</h3>
<p>By building your own distribution, you can ensure that only the necessary and trusted components are included, reducing potential security risks.</p>
<p>LFS empasizes on security. In this context, security refers to the implementation of measures and practices to protect the Linux system from unauthorized access, data breaches, and other potential security threats. LFS enables users to build a secure foundation for their Linux system by allowing them to make informed decisions regarding security-related configurations, software choices, and system hardening techniques.</p>
<p>Security is of utmost importance in the technology industry, and particularly in the realm of Linux systems. With the increasing reliance on digital infrastructure, the potential risks and threats to information security have become more prevalent. Cyberattacks, data breaches, and malicious activities can have severe consequences, including compromised sensitive data, financial losses, reputational damage, and legal implications. Therefore, organizations and individuals alike prioritize security to safeguard their systems, protect valuable assets, and maintain the privacy and trust of their users.</p>
<p>By using LFS, you have the opportunity to enhance security in your Linux system. You can make conscious decisions about security-related configurations during the build process, such as enabling secure kernel options, carefully selecting software packages with strong security track records, and properly configuring system services. LFS also provides insights into system hardening techniques, such as setting up appropriate user permissions, implementing secure network configurations, and applying access controls.</p>
<p>The knowledge and experience gained through implementing security practices in Linux From Scratch can significantly benefit your career. Employers highly value individuals who can demonstrate a strong understanding of security principles and possess the skills to build secure systems. In many organizations, security is a top priority, and having expertise in this area can make you an attractive candidate for roles such as system administrator, network security specialist, or software developer focused on secure coding practices.</p>
<p>Implementing security in LFS entails making informed choices and applying security best practices throughout the system configuration and software selection processes. This may involve researching security vulnerabilities, understanding the security implications of different configuration options, and staying updated with security-related developments and patches in the Linux community. Additionally, it involves being proactive in following security guidelines, industry standards, and best practices when it comes to securing the Linux system.</p>
<p>By emphasizing security in Linux From Scratch, you achieve a higher level of confidence in the security posture of your Linux system. You gain practical experience in implementing security measures, understanding security trade-offs, and making informed decisions that align with your security requirements. Additionally, you develop a comprehensive understanding of security concepts and practices, which can be applied not only in the LFS context but also in various professional settings where security is a critical concern.</p>
<h3 id="heading-learning-experience">Learning experience</h3>
<p>LFS serves as a practical learning tool for those who want to gain hands-on experience with Linux system administration and understand the concepts behind it.</p>
<p>The project offers a valuable learning experience in the realm of Linux development and system administration. A learning experience refers to the process of gaining knowledge, skills, and practical insights through hands-on involvement in building a Linux system from scratch. LFS provides a structured and comprehensive approach that allows individuals to delve into the intricacies of the Linux operating system, understand its components, and develop a deep understanding of its inner workings.</p>
<p>A robust learning experience is crucial for professional and personal growth. It equips individuals with the knowledge and skills needed to excel in their careers and adapt to the ever-evolving technology landscape. In the case of LFS, the learning experience contributes to a multitude of benefits.</p>
<p>Firstly, the learning experience gained through LFS provides a thorough understanding of Linux internals. By actively participating in building a Linux system, individuals gain insights into core concepts such as process management, memory management, file systems, device drivers, and networking. This knowledge forms a solid foundation for further exploration and specialization in Linux development or system administration.</p>
<p>Secondly, the hands-on nature of the learning experience enhances practical skills. Through LFS, individuals develop proficiency in compiling software, managing dependencies, configuring system components, and troubleshooting issues that may arise during the build process. These practical skills are highly transferable and can be applied to various real-world scenarios, such as software development, system administration, or embedded systems.</p>
<p>Furthermore, the learning experience in LFS cultivates a mindset of continuous learning and exploration. Building a Linux system from scratch requires researching, understanding documentation, and actively seeking solutions to challenges encountered along the way. This mindset of curiosity and self-directed learning is invaluable in the technology industry, where new technologies and methodologies continuously emerge. It empowers individuals to stay up-to-date, adapt to changes, and remain effective in their careers.</p>
<p>The learning experience gained through LFS can have a positive impact on your career. It showcases your commitment to professional development, your ability to tackle complex projects, and your dedication to understanding the underlying mechanisms of the Linux system. Employers often value individuals who possess a deep understanding of the technologies they work with, as it demonstrates expertise and a strong foundation for problem-solving.</p>
<p>The learning experience in LFS entails actively engaging with the project’s resources, including the comprehensive book that provides step-by-step instructions and explanations. It involves following the instructions, researching and exploring concepts further, experimenting with different configurations, and troubleshooting any issues that arise. It is a self-driven and immersive process that encourages critical thinking, problem-solving, and the acquisition of practical skills.</p>
<p>By engaging in the learning experience provided by Linux From Scratch, you achieve a comprehensive understanding of the Linux system, gain practical skills applicable to various technology domains, and foster a mindset of continuous learning. You develop expertise in Linux internals, software compilation, configuration, and troubleshooting, positioning yourself for career advancement in Linux development, system administration, or related fields. Additionally, the learning experience hones your ability to adapt to new technologies and environments, ensuring long-term professional growth and success.</p>
<h3 id="heading-performance">Performance</h3>
<p>A custom-built LFS system can potentially offer better performance since you can optimize the chosen components for your specific hardware.</p>
<p>Using Linux From Scratch (LFS) can lead to improved performance in your Linux system. Performance refers to the system’s ability to efficiently utilize its resources, such as processing power, memory, and storage, to deliver optimal speed, responsiveness, and overall system efficiency. Achieving good performance is essential for maximizing productivity, user satisfaction, and system reliability.</p>
<p>Performance is crucial because it directly impacts the user experience and the efficiency of computing tasks. A system with good performance responds quickly to user input, runs applications smoothly, and completes tasks in a timely manner. This translates to increased productivity, reduced waiting times, and an overall more satisfying computing experience.</p>
<p>Despite advancements in hardware capabilities, performance optimization remains relevant. While hardware may be more powerful, software systems continue to evolve and become more complex, often demanding greater resources. Poorly optimized software can still lead to sluggish performance, even on powerful hardware.</p>
<p>Caring about performance is important because it allows you to leverage the full potential of your hardware investment. By optimizing the Linux system through LFS, you can ensure that system resources are efficiently utilized, leading to faster application execution, reduced latency, and improved overall system responsiveness. This is particularly crucial in resource-constrained environments, such as embedded systems or cloud computing, where efficient resource usage translates to cost savings and improved user experience.</p>
<p>Performance optimization is also important from a scalability perspective. In scenarios where systems need to handle a growing number of users, requests, or data, well-optimized systems can scale more effectively, accommodating increased workloads without significant performance degradation. This scalability is vital for systems that need to handle high-demand scenarios or rapidly evolving business needs.</p>
<p>Caring about performance and possessing the skills to optimize it can significantly benefit your career. Employers value professionals who can deliver efficient and high-performing systems, as it directly impacts business productivity and user satisfaction. Performance optimization skills are highly sought after in roles such as software engineering, system administration, cloud infrastructure management, and embedded systems development.</p>
<p>Achieving performance optimization through Linux From Scratch entails various aspects. It involves carefully selecting and configuring software components to minimize resource usage and eliminate unnecessary overhead. Optimizing compiler flags and build options can help generate more efficient executable code. Fine-tuning kernel parameters, memory management settings, and system services can also contribute to performance improvements. Additionally, leveraging performance analysis tools and techniques to identify bottlenecks and optimize critical sections of code or system configurations is essential.</p>
<p>By investing in performance optimization through Linux From Scratch, you achieve a Linux system that is finely tuned to maximize resource utilization, minimize latency, and enhance overall system responsiveness. You gain practical experience in performance analysis, optimization techniques, and system tuning, which are highly applicable in real-world scenarios. Moreover, you position yourself as a skilled professional capable of delivering high-performing systems, which can contribute to career growth, increased job opportunities, and recognition in the technology industry.</p>
<h3 id="heading-complete-control">Complete Control</h3>
<p>Building a Linux system from scratch using Linux From Scratch gives you complete control over every aspect of your system. You can customize it to your specific needs, ensuring that it includes only the components and features you require.</p>
<p>LFS provides you with complete control over your Linux system. Complete control means having the ability to make informed decisions and have full autonomy over the components, configurations, and functionalities of your Linux system. It allows you to tailor the system precisely to your needs, preferences, and specific use cases.</p>
<p>While vendors and distribution maintainers are knowledgeable about computers and their respective products, having complete control over your Linux system offers several advantages. First and foremost, it allows you to customize the system according to your specific requirements. You can choose the software packages, libraries, and kernel options that best suit your needs, ensuring optimal performance, functionality, and security.</p>
<p>Having complete control also enables you to avoid unnecessary bloat and overhead. By selectively including only the components you need, you can create a lean and efficient system that minimizes resource usage. This is particularly important in resource-constrained environments, where efficient utilization of hardware resources is critical for performance and cost-effectiveness.</p>
<p>Furthermore, complete control provides the flexibility to experiment, innovate, and adapt. You are not limited to the choices and configurations offered by vendors or predefined distributions. Instead, you can explore different software combinations, experiment with cutting-edge technologies, and fine-tune the system to optimize performance for your specific use cases. This flexibility allows you to stay ahead of the curve and adapt to changing requirements and emerging technologies.</p>
<p>While vendors may have extensive knowledge and expertise, having complete control over your Linux system empowers you to take ownership and responsibility for its configuration and management. It allows you to better understand the system’s inner workings, gain insights into Linux internals, and sharpen your problem-solving skills. This knowledge and experience are highly valuable in roles such as system administration, software development, or specialized fields like embedded systems.</p>
<p>Having the ability to exercise complete control over your Linux system through LFS entails actively engaging in the process of building the system from scratch. It involves following the detailed instructions provided in the LFS book, making informed decisions regarding software packages, configurations, and optimizations, and actively troubleshooting any issues that arise. This hands-on approach fosters a deeper understanding of the Linux ecosystem, its components, and their interdependencies.</p>
<p>By achieving complete control over your Linux system through LFS, you gain a sense of ownership and mastery over the system. You acquire a comprehensive understanding of Linux internals, practical experience in system configuration and management, and the ability to customize the system to your exact specifications. This achievement can positively impact your career by demonstrating your expertise, problem-solving abilities, and adaptability to different environments. Employers value professionals who possess a deep understanding of the technologies they work with, and having complete control over your Linux system positions you as a knowledgeable and resourceful candidate.</p>
<h3 id="heading-deep-understanding">Deep Understanding</h3>
<p>By manually compiling and configuring each component of your Linux system, you gain a deep understanding of how it works. This knowledge can be invaluable for troubleshooting, optimizing performance, and expanding your Linux administration skills.</p>
<p>Using Linux From Scratch (LFS) offers the benefit of gaining a deep understanding of a Linux system. Deep understanding refers to a comprehensive knowledge of the inner workings, components, and interactions within a Linux system. It entails understanding core concepts, such as process management, memory management, file systems, networking, and device drivers.</p>
<p>While offloading tasks to professionals can be a viable option, caring about deep understanding of a Linux system brings several advantages. First and foremost, it empowers you to have greater control and autonomy over your systems. It allows you to make informed decisions, troubleshoot issues independently, and tailor the system to meet your specific requirements. This level of control can be invaluable when working on specialized projects, developing custom software, or managing complex environments.</p>
<p>Deep understanding of a Linux system also enhances your problem-solving abilities. It equips you with the knowledge and skills to diagnose and resolve issues efficiently. By comprehending the inner workings of the system, you can effectively troubleshoot, optimize performance, and identify root causes of problems. This problem-solving capability is highly valuable in various technology roles, including system administration, software development, and technical support.</p>
<p>Furthermore, a deep understanding of a Linux system fosters continuous learning and adaptability. It enables you to stay up-to-date with the latest technologies, security practices, and emerging trends within the Linux ecosystem. This adaptability allows you to tackle new challenges, explore cutting-edge technologies, and remain relevant in an ever-evolving industry.</p>
<p>Having a deep understanding of a Linux system can significantly benefit your career. It demonstrates your expertise and proficiency in Linux development, system administration, or related fields. Employers often value individuals who possess a strong foundation and in-depth knowledge of the technologies they work with. Your deep understanding can set you apart as a skilled professional capable of handling complex projects, troubleshooting critical issues, and making informed decisions.</p>
<p>Gaining a deep understanding of a Linux system through LFS entails actively engaging with the project’s resources, such as the LFS book. It involves following the step-by-step instructions, researching concepts further, and exploring the underlying principles behind each component. It also entails hands-on experience in configuring, compiling, and managing the system, as well as troubleshooting issues that may arise during the process.</p>
<p>By achieving a deep understanding of a Linux system through LFS, you achieve a solid foundation of knowledge and practical skills. You gain insights into Linux internals, develop problem-solving capabilities, and become proficient in system configuration and management. This achievement can contribute to career advancement, open doors to new opportunities, and increase your value as a technology professional. Moreover, the deep understanding you acquire positions you as a resourceful, adaptable, and knowledgeable individual in the Linux ecosystem.</p>
<h3 id="heading-minimalistic-approach">Minimalistic Approach</h3>
<p>Linux From Scratch follows a minimalistic approach, allowing you to create a lightweight and streamlined Linux system. This can be beneficial for resource-constrained environments or specialized use cases where efficiency is crucial.</p>
<p>LFS offers the benefit of adopting a minimalistic approach to building a Linux system. In this context, minimalistic approach refers to constructing a system that contains only the necessary components and avoids unnecessary bloat or overhead. It focuses on simplicity, efficiency, and resource optimization by including only what is essential for the system’s intended purpose.</p>
<p>Caring about minimalism in LFS is beneficial for several reasons. Firstly, a minimalistic approach allows for better resource utilization. By excluding unnecessary software packages and components, the system becomes leaner, resulting in reduced memory usage, faster boot times, and improved overall system performance. This efficiency is particularly important in resource-constrained environments, embedded systems, or scenarios where optimal resource utilization is critical.</p>
<p>Additionally, minimalism helps to reduce attack surfaces and enhance security. By including only essential components, the system minimizes the number of potential vulnerabilities, reducing the likelihood of security breaches. Fewer software packages mean fewer opportunities for exploitation, making the system more robust and easier to secure.</p>
<p>Caring about minimalism can also lead to easier system maintenance and management. With fewer components to manage and update, it becomes simpler to ensure system stability, apply patches, and keep the system up-to-date. The reduced complexity makes troubleshooting and resolving issues more straightforward, saving time and effort in the long run.</p>
<p>Adopting a minimalistic approach can also be valuable for your career. Employers often value professionals who understand the importance of resource optimization, system efficiency, and security. Demonstrating knowledge and skills in building lean and minimalistic systems can set you apart as someone who is meticulous, detail-oriented, and adept at streamlining processes and reducing unnecessary complexities.</p>
<p>To embrace the minimalistic approach in LFS, you will carefully select the necessary software packages and components required for your specific needs. This involves making informed decisions about which components to include, configuring them appropriately, and excluding anything that is not essential. It also entails researching and understanding the dependencies and interactions between different components to ensure a cohesive and functional system.</p>
<p>By adopting a minimalistic approach through LFS, you achieve a system that is optimized for efficiency, resource utilization, and security. You gain practical experience in system configuration, package selection, and dependency management. This achievement can positively impact your career by showcasing your ability to design and build lean, secure, and well-optimized systems. Moreover, the minimalistic approach demonstrates your attention to detail, ability to make informed decisions, and commitment to delivering high-quality solutions.</p>
<h3 id="heading-stability">Stability</h3>
<p>Building your own Linux system from scratch allows you to implement security measures and configure the system for optimal stability. You have full control over the software versions, patches, and security configurations, reducing the risk of vulnerabilities.</p>
<p>LFS can provide the benefit of stability in your Linux system. Stability refers to the reliability and consistency of the system’s performance, functionality, and behavior over time. A stable system minimizes unexpected crashes, errors, and inconsistencies, allowing for smooth and uninterrupted operation.</p>
<p>Caring about stability is important because it ensures the reliability and predictability of your system. A stable system enables you to have confidence in the performance and functionality of your Linux environment, minimizing downtime, data loss, and disruptions in critical operations. Stability is particularly crucial in professional settings where system failures can have significant consequences, such as financial losses, compromised data integrity, and negative impacts on user experience.</p>
<p>While vendors invest in maintaining the stability of their distributions, there are benefits to resorting to your own build of LFS. Building your own system through LFS gives you a deeper understanding and control over the components and configurations. It allows you to select and configure each component according to your specific needs, preferences, and use cases. This level of control empowers you to fine-tune the system for stability, ensuring that it is optimized for your specific requirements.</p>
<p>Moreover, by building your own system, you can avoid potential stability issues caused by unnecessary or conflicting software packages or configurations. Vendors strive to maintain stability in their distributions, but the vast array of available software and the complexity of system configurations can still introduce potential issues. With LFS, you have the ability to carefully select and configure components, minimizing the risk of instability caused by unwanted software interactions or conflicts.</p>
<p>Caring about stability through LFS can be beneficial for your career. Employers highly value professionals who can deliver stable and reliable systems, as it directly impacts business continuity and user satisfaction. By demonstrating expertise in building stable systems, you position yourself as a skilled professional capable of designing, managing, and troubleshooting stable environments. This expertise is highly relevant in roles such as system administration, software development, or technical support.</p>
<p>To achieve stability in LFS, you will follow the step-by-step instructions provided in the LFS book and make informed decisions regarding the selection and configuration of software components. This entails researching the stability track records of various software packages, understanding potential compatibility issues, and applying best practices for system stability. Additionally, it involves actively testing, monitoring, and optimizing the system to ensure reliable and consistent performance.</p>
<p>By achieving stability through LFS, you achieve a Linux system that is tailored to your specific requirements and optimized for stability. You gain practical experience in system configuration, package selection, and stability testing. This achievement can positively impact your career by showcasing your ability to build and manage stable systems. Moreover, the emphasis on stability demonstrates your attention to detail, commitment to quality, and dedication to providing reliable solutions.</p>
<h2 id="heading-reasons-not-to-use-linux-from-scratch">Reasons not to use Linux From Scratch</h2>
<p>Enough about reasons to use LFS. Every coin has two sides. Linux From Scratch comes with its own share of problems. Let’s have a look at some of those.</p>
<h3 id="heading-time-consuming">Time-consuming</h3>
<p>Building a Linux distribution from scratch requires a significant investment of time and effort, especially for those new to Linux.</p>
<p>Using LFS can be time-consuming due to the comprehensive nature of the process and the level of involvement required. The time it takes to complete LFS can vary depending on factors such as the individual’s familiarity with Linux, technical proficiency, hardware specifications, and the complexity of the desired system configuration.</p>
<p>On an average machine, the process of building a Linux system with LFS can take several days or even weeks. This estimate includes time for reading and understanding the LFS book, following the instructions, resolving any encountered issues, and configuring the system to meet specific requirements. Additionally, the time required for software compilation and package installation can also contribute to the overall duration.</p>
<p>Whether the time investment is worth it depends on individual circumstances and objectives. LFS is primarily designed as a learning experience to gain a deep understanding of the Linux system and its components. If you are passionate about Linux, enjoy hands-on exploration, and are seeking a comprehensive understanding of the system, the time spent on LFS can be highly rewarding. It provides valuable insights into Linux internals, software compilation, system configuration, and troubleshooting, which can enhance your knowledge and skills in Linux development or system administration.</p>
<p>However, if your primary goal is to quickly set up a functional Linux system without delving into low-level details, or if time constraints are a significant consideration, then the time-consuming nature of LFS may not be ideal. In such cases, opting for a pre-packaged Linux distribution that aligns with your needs and provides a balance between customization and convenience may be a more practical choice.</p>
<p>It’s important to carefully assess your priorities, objectives, and available resources before embarking on the LFS journey. Consider whether the learning experience, deep understanding, and customization options provided by LFS align with your goals and justify the time investment. Additionally, evaluate alternative solutions and pre-packaged distributions to determine if they offer a better balance between time, convenience, and customization for your specific requirements.</p>
<h3 id="heading-steep-learning-curve">Steep learning curve</h3>
<p>LFS assumes a certain level of knowledge about Linux, and beginners may find it challenging to navigate through the process.</p>
<p>The steep learning curve is one of the limitations associated with using Linux From Scratch (LFS). It refers to the level of knowledge and expertise required to successfully complete the LFS project. LFS assumes a certain level of familiarity with Linux, system administration, and software development concepts.</p>
<p>The learning curve arises because LFS is intended to be a comprehensive learning experience rather than a straightforward, beginner-friendly process. It requires individuals to understand and apply concepts such as compiling software from source code, configuring system components, managing dependencies, and troubleshooting potential issues that may arise during the build process. This can be challenging for those who are new to Linux or lack prior experience in system administration.</p>
<p>The steep learning curve can be a significant limitation depending on individual circumstances and goals. For individuals who are new to Linux or have limited technical experience, the learning curve may pose a significant challenge and may require investing additional time and effort to grasp the necessary concepts. It can be overwhelming to navigate through the extensive documentation, comprehend complex instructions, and troubleshoot issues without prior knowledge or experience.</p>
<p>However, for individuals who are passionate about Linux, eager to deepen their understanding, and willing to invest the time and effort required, the steep learning curve can be a valuable aspect of LFS. It offers an opportunity to gain in-depth knowledge of Linux internals, software development practices, system configuration, and troubleshooting techniques. The learning experience derived from overcoming the learning curve can lead to enhanced skills, confidence, and expertise in Linux development and system administration.</p>
<p>Whether the steep learning curve is worth it depends on individual goals, interests, and available resources. If you are motivated by the prospect of a hands-on learning experience, enjoy diving into technical details, and are committed to building a solid foundation of Linux knowledge, then the effort to overcome the learning curve can be highly rewarding. It provides a deeper understanding of the Linux system, practical skills, and a sense of accomplishment.</p>
<p>However, if your primary objective is to quickly set up a functional Linux system without investing significant time in learning the intricacies of Linux internals, or if time constraints are a critical consideration, then the steep learning curve of LFS may be a significant limitation. In such cases, alternative solutions like pre-packaged Linux distributions that provide a balance between customization and convenience may be more suitable.</p>
<h3 id="heading-limited-support">Limited support</h3>
<p>Since LFS is a do-it-yourself project, you won’t have access to official support from a commercial Linux distribution, which might make troubleshooting more difficult.</p>
<p>Another limitation of using Linux From Scratch (LFS) is the limited support associated with the project. Limited support means that LFS does not have a dedicated support team or a large community of users compared to mainstream Linux distributions. While there is a supportive community of LFS enthusiasts, the resources and availability of immediate assistance may be more limited compared to widely-used distributions.</p>
<p>The limited support can be a significant consideration, particularly for those who prefer or require prompt assistance or comprehensive documentation for troubleshooting issues. With LFS, resolving problems or addressing specific configuration challenges may require more self-reliance, independent research, and problem-solving skills.</p>
<p>In contrast, mainstream Linux distributions have dedicated support teams, larger communities, and extensive documentation readily available. These distributions often offer comprehensive support channels, including forums, mailing lists, and official documentation, allowing users to seek assistance and find solutions to common problems more easily.</p>
<p>The limited support associated with LFS gives an edge to vendors of mainstream distributions. Vendors have dedicated teams working on maintaining the distribution, providing support, addressing security vulnerabilities, and ensuring compatibility across a wide range of hardware and software. They have the resources and expertise to quickly respond to issues, provide updates, and offer guidance to users.</p>
<p>However, whether the limited support of LFS is a significant limitation depends on individual circumstances and requirements. For those who enjoy the challenge of independent problem-solving, have a strong understanding of Linux, and are motivated by the learning experience that LFS offers, the limited support may not be a major concern. The self-sufficiency and independence gained through LFS can be a rewarding aspect, allowing individuals to develop their skills, explore solutions, and deepen their understanding of the Linux system.</p>
<p>Whether the limited support is worth it ultimately depends on individual needs and preferences. If immediate support and comprehensive documentation are critical, and there are time constraints or business requirements that necessitate prompt assistance, then relying on a mainstream Linux distribution with extensive support infrastructure may be more suitable.</p>
<h3 id="heading-complexity">Complexity</h3>
<p>Manually configuring and compiling each component can be complex and error-prone, which may lead to frustration for novice users.</p>
<p>Complexity refers to the intricate and involved nature of the LFS process, which can be challenging for individuals who are new to Linux or lack extensive technical knowledge. LFS requires a deep understanding of Linux internals, system configuration, software compilation, and troubleshooting.</p>
<p>The complexity of LFS can be a barrier for newcomers or those seeking a quick and straightforward solution. It requires individuals to invest time and effort in comprehending the detailed instructions provided in the LFS book, researching concepts, and troubleshooting issues that may arise during the build process. The level of technical expertise required to successfully complete LFS can be daunting, especially for individuals who are not familiar with Linux or system administration practices.</p>
<p>In contrast, vendors of mainstream Linux distributions deal with complexity by providing pre-packaged distributions that abstract much of the underlying intricacies. Vendors simplify the user experience by offering user-friendly installers, automated configuration tools, and pre-configured software stacks. They streamline the process of setting up a functional Linux system, reducing the complexity for users who prefer a more straightforward and convenient approach.</p>
<p>The edge that vendors gain from dealing with complexity is the ability to cater to a broader user base. By simplifying the installation and configuration process, vendors make Linux more accessible to a wider range of users, including those with limited technical expertise. The ease of use, comprehensive documentation, and user-friendly interfaces offered by vendors can lower the barrier of entry for Linux adoption, attracting a larger user community.</p>
<p>Whether the complexity of LFS is worth it depends on individual circumstances and objectives. LFS is primarily designed as a learning experience to gain a deep understanding of the Linux system and its components. If you are passionate about Linux, enjoy hands-on exploration, and are seeking a comprehensive understanding of the system, the complexity of LFS can be an acceptable trade-off.</p>
<p>However, for individuals who prioritize simplicity, convenience, or have specific time constraints, the complexity of LFS may not be worth it. Mainstream Linux distributions offer pre-packaged solutions that provide a balance between customization and convenience, eliminating the need to navigate the intricacies of building a Linux system from scratch.</p>
<h3 id="heading-availability-of-ready-made-solutions">Availability of ready-made solutions</h3>
<p>There are numerous Linux distributions available that cater to various needs and preferences, making it easier for users to choose an existing solution rather than building one from scratch.</p>
<p>One of the limitations of using Linux From Scratch (LFS) is the availability of ready-made solutions. This refers to the fact that LFS requires individuals to build a Linux system from scratch, which can be time-consuming and demanding. In contrast, there are pre-packaged Linux distributions readily available that offer a range of features, software packages, and configurations out of the box.</p>
<p>The availability of ready-made solutions is important because it provides convenience, time savings, and ease of use. Pre-packaged Linux distributions, such as Ubuntu, Fedora, or Debian, have undergone extensive development, testing, and refinement by dedicated teams. They offer a wealth of pre-configured software packages, desktop environments, and system settings, making it easier for users to get up and running quickly.</p>
<p>Ready-made solutions also provide a wide range of additional benefits. They often include comprehensive documentation, user-friendly installation processes, automatic hardware detection, and package management systems for easy software installation and updates. They have established support channels, vibrant communities, and extensive repositories of software packages and applications, enhancing the overall user experience.</p>
<p>While LFS offers the advantage of customization and a deep understanding of the Linux system, the availability of ready-made solutions is worth considering depending on individual needs and priorities. Using a pre-packaged Linux distribution can save time, provide a reliable and well-supported system, and offer a rich ecosystem of tools and resources. This is particularly valuable for those who prioritize convenience, require a stable and feature-rich environment, or have limited time or technical expertise.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this blog post, we explored the benefits and limitations of using Linux From Scratch. LFS offers benefits such as knowledge, customization, security, learning experience, performance, control, stability, and minimalism, providing deep insights into Linux internals, tailored systems, enhanced security, learning opportunities, optimized performance, autonomy, reliability, and resource efficiency. However, LFS also has limitations including time consumption, steep learning curve, limited support, complexity, and absence of ready-made solutions. The decision to use LFS depends on individual goals, technical expertise, time availability, and the trade-off between customization and convenience, with pre-packaged distributions offering a more convenient alternative. Ultimately, the choice between LFS and pre-packaged distributions should consider individual circumstances, preferences, and the desired balance between customization, time investment, convenience, and support availability.</p>
]]></content:encoded></item><item><title><![CDATA[Create Reproducible Python Environments With mach-nix]]></title><description><![CDATA[Python is a popular and versatile programming language that is widely used for data science, web development, machine learning and more. However, managing python environments and dependencies can be a challenging task, especially when you want to ens...]]></description><link>https://hashnode.adityakumar.xyz/create-reproducible-python-environments-with-mach-nix</link><guid isPermaLink="true">https://hashnode.adityakumar.xyz/create-reproducible-python-environments-with-mach-nix</guid><category><![CDATA[Nix]]></category><dc:creator><![CDATA[Aditya Kumar]]></dc:creator><pubDate>Sat, 24 Jun 2023 16:28:37 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1688709506510/bbd93688-27d3-4301-ad73-a66e6b692d49.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Python is a popular and versatile programming language that is widely used for data science, web development, machine learning and more. However, managing python environments and dependencies can be a challenging task, especially when you want to ensure reproducibility and portability across different platforms and machines.</p>
<p>One common way to create python environments is to use tools like pip, virtualenv, pipenv or poetry. These tools allow you to specify your dependencies in a requirements.txt file or a similar format, and then install them in a virtual environment. However, these tools often suffer from some drawbacks, such as:
</p>
<ul>
<li>They rely on the availability and consistency of online repositories, which may change or disappear over time.</li>
<li>They do not guarantee that the same versions of packages and their dependencies will be installed on different machines or platforms.</li>
<li>They do not handle non-python dependencies or system libraries very well.</li>
<li>They may require additional tools or layers of virtualization to work properly.</li>
</ul>
<p>Another way to create python environments is to use nix, a revolutionary build system that is known to achieve great reproducibility and portability. Nix allows you to declare your dependencies in a nix expression, and then build them in a sandboxed environment that is isolated from the rest of the system. Nix also caches the build results and allows you to share them with others. However, nix also has some drawbacks, such as:</p>
<ul>
<li>It has a steep learning curve and a different syntax than python.</li>
<li>It requires you to write nix expressions for each python package you want to use, which can be tedious and error-prone.</li>
<li>It may not support all the python packages or versions that you need.</li>
</ul>
<p>This is where mach-nix comes in. Mach-nix is a project that aims to make it easy to create and share reproducible python environments or packages using nix. Mach-nix can install packages from three different sources: pypi, conda and nixpkgs. It also supports hardware optimizations, cross platform support, private packages and tweaking build parameters. You can use mach-nix with a simple requirements.txt file or a more advanced nix expression.</p>
<p>In this blog post, I will show you how to use mach-nix to create a python environment for a simple web application that uses Flask and requests.</p>
<h2 id="heading-installing-mach-nix">Installing mach-nix</h2>
<p>To use mach-nix, you need to have nix installed on your system. You can install nix by following the instructions on https://nixos.org/download.html.</p>
<p>Once you have nix installed, you can install mach-nix by running the following command:</p>
<pre><code class="lang-bash">nix-env -iA mach-nix -f https://github.com/DavHau/mach-nix/tarball/3.5.0
</code></pre>
<p>This will install mach-nix version 3.5.0 on your system. You can check the latest version of mach-nix on its GitHub page: https://github.com/DavHau/mach-nix.</p>
<h2 id="heading-creating-a-requirementstxt-file">Creating a requirements.txt file</h2>
<p>The simplest way to use mach-nix is to create a requirements.txt file that lists the python packages you want to use. For example, for our web application, we need Flask and requests. We can create a requirements.txt file with the following content:</p>
<pre><code class="lang-txt">Flask
requests
</code></pre>
<h2 id="heading-creating-a-python-environment-with-mach-nix">Creating a python environment with mach-nix</h2>
<p>To create a python environment with mach-nix, we can use the <code>mach-nix.mkPython</code> function. This function takes a list of requirements as an argument and returns a derivation that contains the python interpreter and the installed packages.</p>
<p>We can write a nix expression that uses <code>mach-nix.mkPython</code> as follows:</p>
<pre><code class="lang-nix"><span class="hljs-keyword">let</span>
  <span class="hljs-comment"># Import mach-nix</span>
  <span class="hljs-attr">mach-nix</span> = <span class="hljs-built_in">import</span> (<span class="hljs-built_in">builtins</span>.fetchGit {
    <span class="hljs-attr">url</span> = <span class="hljs-string">"https://github.com/DavHau/mach-nix"</span>;
    <span class="hljs-attr">ref</span> = <span class="hljs-string">"refs/tags/3.5.0"</span>;
  }) {};
<span class="hljs-keyword">in</span>
  <span class="hljs-comment"># Create a python environment with our requirements</span>
  mach-nix.mkPython {
    <span class="hljs-attr">requirements</span> = <span class="hljs-built_in">builtins</span>.readFile ./requirements.txt;
  }
</code></pre>
<p>We can save this expression in a file called <code>default.nix</code>.</p>
<h2 id="heading-building-and-entering-the-python-environment">Building and entering the python environment</h2>
<p>To build and enter the python environment, we can run the following command:</p>
<pre><code class="lang-bash">nix-shell default.nix
</code></pre>
<p>This will download and build the required packages and then drop us into a shell where we can access the python interpreter and the installed packages.</p>
<p>We can verify that we have Flask and requests available by running:</p>
<pre><code class="lang-bash">python -c <span class="hljs-string">"import flask; import requests; print(flask.__version__, requests.__version__)"</span>
</code></pre>
<p>This should print something like:</p>
<pre><code class="lang-bash">2.0.2 2.26.0
</code></pre>
<h2 id="heading-writing-a-simple-web-application">Writing a simple web application</h2>
<p>Now that we have our python environment ready, we can write a simple web application that uses Flask and requests. For example, we can create a file called <code>app.py</code> with the following content:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> flask <span class="hljs-keyword">import</span> Flask, request, jsonify
<span class="hljs-keyword">import</span> requests

app = Flask(__name__)

<span class="hljs-meta">@app.route("/")</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">index</span>():</span>
    <span class="hljs-keyword">return</span> <span class="hljs-string">"Hello, world!"</span>

<span class="hljs-meta">@app.route("/weather")</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">weather</span>():</span>
    city = request.args.get(<span class="hljs-string">"city"</span>, <span class="hljs-string">"London"</span>)
    api_key = <span class="hljs-string">"your_api_key_here"</span>
    url = <span class="hljs-string">f"https://api.openweathermap.org/data/2.5/weather?q=<span class="hljs-subst">{city}</span>&amp;appid=<span class="hljs-subst">{api_key}</span>"</span>
    response = requests.get(url)
    data = response.json()
    <span class="hljs-keyword">return</span> jsonify(data)
</code></pre>
<p>This web application has two routes: <code>/</code> and <code>/weather</code>. The <code>/</code> route returns a simple greeting message. The <code>/weather</code> route takes a city name as a query parameter and returns the current weather data from the OpenWeather API. You need to replace <code>your_api_key_here</code> with your own API key, which you can get from https://openweathermap.org/api.</p>
<h2 id="heading-running-the-web-application">Running the web application</h2>
<p>To run the web application, we can use the <code>flask</code> command from our python environment:</p>
<pre><code class="lang-bash">FLASK_APP=app.py flask run
</code></pre>
<p>This will start a development server on http://localhost:5000.</p>
<p>We can test our web application by opening http://localhost:5000 in a browser or using a tool like curl:</p>
<pre><code class="lang-bash">curl http://localhost:5000
</code></pre>
<p>This should return:</p>
<pre><code class="lang-bash">Hello, world!
</code></pre>
<p>We can also test the <code>/weather</code> route by passing a city name as a query parameter:</p>
<pre><code class="lang-bash">curl http://localhost:5000/weather?city=New%20York
</code></pre>
<p>This should return something like:</p>
<pre><code class="lang-json">{<span class="hljs-attr">"base"</span>:<span class="hljs-string">"stations"</span>,<span class="hljs-attr">"clouds"</span>:{<span class="hljs-attr">"all"</span>:<span class="hljs-number">75</span>},<span class="hljs-attr">"cod"</span>:<span class="hljs-number">200</span>,<span class="hljs-attr">"coord"</span>:{<span class="hljs-attr">"lat"</span>:<span class="hljs-number">40.7143</span>,<span class="hljs-attr">"lon"</span>:<span class="hljs-number">-74.006</span>},<span class="hljs-attr">"dt"</span>:<span class="hljs-number">1639764799</span>,<span class="hljs-attr">"id"</span>:<span class="hljs-number">5128581</span>,<span class="hljs-attr">"main"</span>:{<span class="hljs-attr">"feels_like"</span>:<span class="hljs-number">276.05</span>,<span class="hljs-attr">"humidity"</span>:<span class="hljs-number">69</span>,<span class="hljs-attr">"pressure"</span>:<span class="hljs-number">1016</span>,<span class="hljs-attr">"temp"</span>:<span class="hljs-number">278.15</span>,<span class="hljs-attr">"temp_max"</span>:<span class="hljs-number">279.82</span>,<span class="hljs-attr">"temp_min"</span>:<span class="hljs-number">276.48</span>},<span class="hljs-attr">"name"</span>:<span class="hljs-string">"New York"</span>,<span class="hljs-attr">"sys"</span>:{<span class="hljs-attr">"country"</span>:<span class="hljs-string">"US"</span>,<span class="hljs-attr">"id"</span>:<span class="hljs-number">2039034</span>,<span class="hljs-attr">"sunrise"</span>:<span class="hljs-number">1639734157</span>,<span class="hljs-attr">"sunset"</span>:<span class="hljs-number">1639767679</span>,<span class="hljs-attr">"type"</span>:<span class="hljs-number">2</span>},<span class="hljs-attr">"timezone"</span>:<span class="hljs-number">-18000</span>,<span class="hljs-attr">"visibility"</span>:<span class="hljs-number">10000</span>,<span class="hljs-attr">"weather"</span>:[{<span class="hljs-attr">"description"</span>:<span class="hljs-string">"broken clouds"</span>,<span class="hljs-attr">"icon"</span>:<span class="hljs-string">"04n"</span>,<span class="hljs-attr">"id"</span>:<span class="hljs-number">803</span>,<span class="hljs-attr">"main"</span>:<span class="hljs-string">"Clouds"</span>}],<span class="hljs-attr">"wind"</span>:{<span class="hljs-attr">"deg"</span>:<span class="hljs-number">280</span>,<span class="hljs-attr">"gust"</span>:<span class="hljs-number">11.32</span>,<span class="hljs-attr">"speed"</span>:<span class="hljs-number">7.72</span>}}
</code></pre>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this blog post, we have seen how to use mach-nix to create reproducible python environments with nix. We have created a simple web application that uses Flask and requests and ran it from our python environment.</p>
<p>Mach-nix is a powerful and easy-to-use tool that can help you manage your python projects and dependencies in a reliable and portable way. You can learn more about mach-nix and its features on its GitHub page: https://github.com/DavHau/mach-nix.</p>
]]></content:encoded></item><item><title><![CDATA[Fediverse Explained]]></title><description><![CDATA[The internet is dominated by a few giant platforms that control most of the online content and communication. Facebook, Twitter, YouTube, Instagram, and others have billions of users who depend on them for social networking, entertainment, news, and ...]]></description><link>https://hashnode.adityakumar.xyz/fediverse-explained</link><guid isPermaLink="true">https://hashnode.adityakumar.xyz/fediverse-explained</guid><category><![CDATA[Fediverse]]></category><category><![CDATA[decentralization]]></category><category><![CDATA[activitypub]]></category><dc:creator><![CDATA[Aditya Kumar]]></dc:creator><pubDate>Sat, 24 Jun 2023 13:50:29 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1688709687622/039ea6d0-75e1-4c2f-891a-48990ae780c8.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The internet is dominated by a few giant platforms that control most of the online content and communication. Facebook, Twitter, YouTube, Instagram, and others have billions of users who depend on them for social networking, entertainment, news, and more. But what if there was a way to escape the walled gardens of these corporations and join a more open, diverse, and decentralized web? That's where the <strong>Fediverse</strong> comes in.</p>
<p>The Fediverse (a portmanteau of "federation" and "universe") is an ensemble of federated (i.e. interconnected) servers that are used for web publishing (i.e. social networking, microblogging, blogging, or websites) and file hosting, which, while independently hosted, can communicate with each other. The Fediverse is a network of diverse and decentralized platforms that offer users more control over their data, privacy, and online interactions.</p>
<h2 id="heading-how-does-the-fediverse-work">How Does the Fediverse Work?</h2>
<p>The Fediverse works by using open communication protocols that allow different software packages to exchange information across servers. These protocols include ActivityPub, Diaspora, OStatus, Zot, and others. Each server (also called an instance) hosts a number of user accounts that can create and share content with other accounts on the same or different instances. Users can also follow accounts from other instances and interact with them through comments, likes, reblogs, etc.</p>
<p>The Fediverse is not controlled by any central authority or corporation. Each instance is run by its own administrator who sets the rules and policies for their community. Users can choose an instance that suits their preferences and needs, or even host their own instance if they have the technical skills and resources. This way, the Fediverse fosters diversity, freedom of expression, and self-governance.</p>
<h2 id="heading-what-can-you-do-on-the-fediverse">What Can You Do on the Fediverse?</h2>
<p>The Fediverse offers a variety of platforms for different purposes and audiences. Some of them are:</p>
<ul>
<li><p><strong>Mastodon</strong>: A microblogging platform similar to Twitter, where users can post short messages (called toots) with media attachments and hashtags. Mastodon has a unique feature called the local timeline, which shows all the posts from the users on the same instance. Mastodon also supports content warnings, lists, polls, and emoji reactions.</p>
</li>
<li><p><strong>Pleroma</strong>: Another microblogging platform that is compatible with Mastodon, but with a smaller server footprint and more customization options. Pleroma also has a rich text editor, chat functionality, and support for multiple accounts.</p>
</li>
<li><p><strong>Pixelfed</strong>: A photo-sharing platform similar to Instagram, where users can post images and videos with filters, captions, and mentions. Pixelfed also has features like stories, collections, albums, and discover pages.</p>
</li>
<li><p><strong>PeerTube</strong>: A video-sharing platform similar to YouTube, where users can upload and watch videos without ads or tracking. PeerTube uses peer-to-peer technology to reduce bandwidth costs and censorship risks. PeerTube also has features like live streaming, playlists, subtitles, and comments.</p>
</li>
<li><p><strong>Friendica</strong>: A social networking platform similar to Facebook, where users can post status updates, photos, events, polls, and more. Friendica also has features like groups, pages, forums, calendars, and contacts.</p>
</li>
<li><p><strong>Hubzilla</strong>: A versatile platform that combines social networking, blogging, file storage, wiki editing, and more. Hubzilla also has features like channels, clones, webpages, nomadic identity, and access control lists.</p>
</li>
</ul>
<p>These are just some examples of the many platforms available on the Fediverse. You can find more platforms on <a target="_blank" href="https://fediverse.party/">fediverse.party</a>, a website that showcases different Fediverse projects.</p>
<h2 id="heading-how-to-join-the-fediverse">How to Join the Fediverse?</h2>
<p>To join the Fediverse, you need to choose a platform and an instance that you like. You can browse different instances on <a target="_blank" href="https://joinmastodon.org/">joinmastodon.org</a>, <a target="_blank" href="https://the-federation.info/">the-federation.info</a>, <a target="_blank" href="https://fediverse.network/">fediverse.network</a>, or <a target="_blank" href="https://fediscan.xyz/">fediscan.xyz</a>. You can also use <a target="_blank" href="https://trunk.madnificent.space/">trunk.madnificent.space</a> to find people to follow based on your interests.</p>
<p>Once you have chosen an instance, you need to create an account with a username and a password. You will also get a unique identifier that looks like an email address (e.g. @user@instance.tld). This identifier is how you can be found and followed by other users on the Fediverse.</p>
<p>After creating your account, you can start posting content, following other accounts, and exploring the Fediverse.</p>
<h2 id="heading-why-join-the-fediverse">Why Join the Fediverse?</h2>
<p>The Fediverse is a great alternative to mainstream social media platforms that are often plagued by issues like censorship, surveillance, monetization, and centralization. The Fediverse gives you more choice, control, and creativity over your online presence and interactions. You can join communities that share your values and interests, or create your own. You can also enjoy a more diverse and respectful online environment, where you can learn from different perspectives and cultures.</p>
<p>The Fediverse is also a way to support free and open-source software, which is developed by volunteers and funded by donations. By joining the Fediverse, you are contributing to a more democratic and sustainable web.</p>
<p>So what are you waiting for? Join the Fediverse today and discover a whole new world of possibilities!</p>
<ul>
<li><p><a target="_blank" href="https://en.wikipedia.org/wiki/Fediverse">Fediverse - Wikipedia</a>.</p>
</li>
<li><p><a target="_blank" href="https://www.makeuseof.com/what-is-the-fediverse-and-can-it-decentralize-the-web/">What Is the Fediverse and Can It Decentralize the Web? - MUO</a>.</p>
</li>
<li><p><a target="_blank" href="https://fediverse.party/">Fediverse.Party - explore federated networks</a>.</p>
</li>
<li><p><a target="_blank" href="https://joinfediverse.wiki/What_is_the_Fediverse%3F">What is the Fediverse? - Join the Fediverse</a>.</p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Push Git Repo to Two Remotes]]></title><description><![CDATA[Sometimes you may want to push your code to two different remote repositories, for example, if you want to use one service for hosting your code and another for deploying it. In this post, I will show you how to do that using git.

Adding Multiple Pu...]]></description><link>https://hashnode.adityakumar.xyz/push-git-repo-to-two-remotes</link><guid isPermaLink="true">https://hashnode.adityakumar.xyz/push-git-repo-to-two-remotes</guid><category><![CDATA[Git]]></category><dc:creator><![CDATA[Aditya Kumar]]></dc:creator><pubDate>Sat, 24 Jun 2023 12:45:43 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/EUzk9BIEq6M/upload/25be6636e7f6e2f6e1bfbd30286d4002.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Sometimes you may want to push your code to two different remote repositories, for example, if you want to use one service for hosting your code and another for deploying it. In this post, I will show you how to do that using git.
</p>
<h2 id="heading-adding-multiple-push-urls">Adding Multiple Push URLs</h2>
<p>The easiest way to push your code to two remotes is to add multiple push URLs for a given remote. For example, if you have a remote called <code>origin</code> that points to your main repository, you can add another push URL for a different repository using this command:</p>
<pre><code class="lang-bash">git remote set-url --add --push origin git://existing/repo.git
git remote set-url --add --push origin git://another/repo.git
</code></pre>
<p>This will add a second push URL to your <code>origin</code> remote, so when you run <code>git push origin</code>, it will push your code to both repositories. You can verify the current push URLs for a remote by running <code>git remote -v</code>.</p>
<p>You can add as many push URLs as you want for a single remote, but keep in mind that this will affect all the branches that use that remote as their upstream. If you want more fine-grained control over which branches go to which remotes, you can use the next method.</p>
<h2 id="heading-creating-separate-branches">Creating Separate Branches</h2>
<p>Another way to push your code to two remotes is to create separate branches for each remote and set their upstreams accordingly. For example, if you have a branch called <code>master</code> that you want to push to your main repository, and another branch called <code>deployment</code> that you want to push to your deployment repository, you can do something like this:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># create the deployment branch from master</span>
git checkout -b deployment master

<span class="hljs-comment"># add the deployment remote</span>
git remote add deployment git://another/repo.git

<span class="hljs-comment"># set the upstream for the deployment branch</span>
git push --set-upstream deployment deployment
</code></pre>
<p>This will create a new branch called <code>deployment</code> that tracks the <code>deployment</code> remote, and push it there. Now, whenever you want to update your deployment repository, you can simply run <code>git push</code> from the <code>deployment</code> branch.</p>
<p>You can also merge changes from your <code>master</code> branch into your <code>deployment</code> branch before pushing, or use rebase or cherry-pick if you prefer. The advantage of this method is that you can have different histories and configurations for each remote.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this post, I showed you two ways to push your code to two remotes using git: adding multiple push URLs for a single remote, or creating separate branches for each remote. Both methods have their pros and cons, so choose the one that suits your workflow best.</p>
<p>I hope you found this post useful and learned something new.</p>
<h2 id="heading-references">References</h2>
<ul>
<li><a target="_blank" href="https://leighmcculloch.com/posts/git-push-to-multiple-remotes-at-once/">Git: Push to multiple remotes at once - Leigh McCulloch</a>.</li>
<li><a target="_blank" href="https://stackoverflow.com/questions/14290113/git-pushing-code-to-two-remotes">github - Git - Pushing code to two remotes - Stack Overflow</a>.</li>
<li><a target="_blank" href="https://www.howtogeek.com/devops/how-to-use-git-with-multiple-remote-repositories/">How To Use git with Multiple Remote Repositories - How-To Geek</a>.</li>
<li><a target="_blank" href="https://stackoverflow.com/questions/5620525/git-pushing-to-two-repos-in-one-command">Git: Pushing to two repos in one command - Stack Overflow</a>.</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Nix Shells: What they are and how to use them]]></title><description><![CDATA[Nix is a powerful tool for managing software dependencies and reproducible environments. One of the features of Nix is the ability to create and enter interactive shells that provide a specific set of tools and variables for a given project or task. ...]]></description><link>https://hashnode.adityakumar.xyz/nix-shells-what-they-are-and-how-to-use-them</link><guid isPermaLink="true">https://hashnode.adityakumar.xyz/nix-shells-what-they-are-and-how-to-use-them</guid><category><![CDATA[Nix]]></category><dc:creator><![CDATA[Aditya Kumar]]></dc:creator><pubDate>Sat, 24 Jun 2023 05:51:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1688709926098/b710b2d4-b7e8-41a3-902b-0322702563e8.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Nix is a powerful tool for managing software dependencies and reproducible environments. One of the features of Nix is the ability to create and enter interactive shells that provide a specific set of tools and variables for a given project or task. In this post, I will explain what are the different types of Nix shells, how they work, and how to use them effectively.</p>

<h2 id="heading-nix-shell">nix-shell</h2>
<p><code>nix-shell</code> is the original command for creating and entering Nix shells. It takes a Nix expression as an argument, which can be either a file name (such as <code>shell.nix</code> or <code>default.nix</code>), a derivation (such as <code>nixpkgs#hello</code>), or an arbitrary expression (such as <code>-p python3</code>). <code>nix-shell</code> then builds the expression and starts a Bash subshell with the environment variables and shell functions set up according to the expression.</p>
<p>For example, if you have a <code>shell.nix</code> file in your project directory that looks like this:</p>
<pre><code class="lang-nix">{ pkgs ? <span class="hljs-built_in">import</span> &lt;nixpkgs&gt; {} }:

pkgs.mkShell {
  <span class="hljs-attr">buildInputs</span> = [
    pkgs.python3
    pkgs.python3Packages.numpy
    pkgs.python3Packages.pandas
  ];
}
</code></pre>
<p>You can run <code>nix-shell</code> in the same directory and get a shell with Python 3 and its packages available:</p>
<pre><code class="lang-bash">$ nix-shell
[nix-shell:~/my-project]$ python3
Python 3.10.11 (main, Apr  4 2023, 22:10:32) [GCC 12.2.0] on linux
Type <span class="hljs-string">"help"</span>, <span class="hljs-string">"copyright"</span>, <span class="hljs-string">"credits"</span> or <span class="hljs-string">"license"</span> <span class="hljs-keyword">for</span> more information.
&gt;&gt;&gt; import numpy
&gt;&gt;&gt; import pandas
&gt;&gt;&gt;
</code></pre>
<p>You can also use <code>nix-shell</code> to run a single command in a Nix shell, without entering it interactively. For example, you can run <code>nix-shell -p curl --run "curl https://nixos.org"</code> to download the NixOS homepage using the <code>curl</code> package from Nixpkgs.</p>
<p><code>nix-shell</code> has some options that modify its behavior, such as:</p>
<ul>
<li><code>--pure</code>: Clear the entire environment (except those specified with --keep) before entering the shell. This ensures that the shell is isolated from any impurities from the parent environment, such as system packages or environment variables.</li>
<li><code>--run</code>: Run the specified command inside the shell, instead of starting an interactive shell.</li>
<li><code>--command</code> or <code>-c</code>: Similar to --run, but allows multiple commands to be executed sequentially.</li>
<li><code>--keep</code> or <code>-k</code>: Keep the specified environment variable when entering the shell.</li>
<li><code>--arg</code>: Pass an argument to the Nix expression that defines the shell.</li>
<li><code>--argstr</code>: Similar to --arg, but passes a string argument.</li>
</ul>
<h2 id="heading-nix-shell-1">nix shell</h2>
<p><code>nix shell</code> is a newer command that is part of the new Nix user interface introduced in Nix 2.0. It is similar to <code>nix-shell</code>, but has some differences and advantages. <code>nix shell</code> takes one or more installables as arguments, which can be either flake outputs (such as <code>.#hello</code> or <code>nixpkgs#firefox</code>) or legacy packages (such as <code>hello</code> or <code>firefox</code>). <code>nix shell</code> then builds and installs these installables into a temporary profile, and starts a Bash subshell with these installables available in <code>$PATH</code>.</p>
<p>For example, you can run <code>nix shell nixpkgs#python3 nixpkgs#python3Packages.numpy --command "python3 -c 'import numpy; print(numpy.__version__)'"</code> to print the version of numpy using Python 3 from Nixpkgs.</p>
<p><code>nix shell</code> has some advantages over <code>nix-shell</code>, such as:</p>
<ul>
<li>It supports flakes, which are a new way of defining and composing Nix projects with improved reproducibility and composability.</li>
<li>It does not require a <code>shell.nix</code> or <code>default.nix</code> file to exist in the current directory. You can specify any installable from any source as an argument.</li>
<li>It does not use Bash-specific features to set up the environment, which makes it more portable and compatible with other shells.</li>
<li>It does not leak any build-time dependencies into the shell environment, which makes it more lightweight and minimal.</li>
</ul>
<p>However, <code>nix shell</code> also has some limitations compared to <code>nix-shell</code>, such as:</p>
<ul>
<li>It does not support arbitrary Nix expressions as arguments. You can only use installables that are defined in flakes or in Nixpkgs.</li>
<li>It does not support setting up environment variables or shell functions that are not related to the installables. For example, you cannot use <code>nix shell</code> to set up a PostgreSQL service or a Python virtual environment.</li>
<li>It does not support running a specific phase of a derivation, such as configure or build. You can only run the final result of the derivation.</li>
</ul>
<h2 id="heading-nix-develop">nix develop</h2>
<p><code>nix develop</code> is another new command that is part of the new Nix user interface. It is similar to <code>nix shell</code>, but instead of providing a minimal environment with only the installables in <code>$PATH</code>, it provides a full-fledged build environment that is nearly identical to what Nix would use to build the installables. Inside this shell, environment variables and shell functions are set up so that you can interactively and incrementally build your project.</p>
<p>For example, if you have a <code>flake.nix</code> file in your project directory that looks like this:</p>
<pre><code class="lang-nix">{
  inputs.nixpkgs.<span class="hljs-attr">url</span> = <span class="hljs-string">"github:NixOS/nixpkgs/nixos-unstable"</span>;

  <span class="hljs-attr">outputs</span> = { self, nixpkgs }: {

    packages.x86_64-linux.<span class="hljs-attr">hello</span> = nixpkgs.legacyPackages.x86_64-linux.hello;

    devShell.<span class="hljs-attr">x86_64-linux</span> = nixpkgs.legacyPackages.x86_64-linux.mkShell {
      <span class="hljs-attr">buildInputs</span> = [
        nixpkgs.legacyPackages.x86_64-linux.hello
      ];
    };

  };
}
</code></pre>
<p>You can run <code>nix develop</code> in the same directory and get a shell with the build environment of the hello package.</p>
<p>You can also use <code>nix develop</code> to run a single command in a Nix shell, without entering it interactively. For example, you can run <code>nix develop .#hello --command "hello"</code> to run the hello program from the flake output.</p>
<p><code>nix develop</code> has some advantages over <code>nix-shell</code>, such as:</p>
<ul>
<li>It supports flakes, which are a new way of defining and composing Nix projects with improved reproducibility and composability.</li>
<li>It does not require a <code>shell.nix</code> or <code>default.nix</code> file to exist in the current directory. You can specify any flake output as an argument.</li>
<li>It does not use Bash-specific features to set up the environment, which makes it more portable and compatible with other shells.</li>
<li>It allows you to run specific phases of a derivation, such as configure or build, by using options like <code>--configure</code> or <code>--build</code>.</li>
</ul>
<p>However, <code>nix develop</code> also has some limitations compared to <code>nix-shell</code>, such as:</p>
<ul>
<li>It does not support arbitrary Nix expressions as arguments. You can only use flake outputs that are derivations.</li>
<li>It does not support installing multiple installables into the same shell. You can only use one flake output as an argument.</li>
<li>It does not support setting up environment variables or shell functions that are not related to the derivation. For example, you cannot use <code>nix develop</code> to set up a PostgreSQL service or a Python virtual environment.</li>
</ul>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this post, I have explained what are the different types of Nix shells, how they work, and how to use them effectively. <code>nix-shell</code> is the original command for creating and entering Nix shells based on arbitrary Nix expressions. <code>nix shell</code> is a newer command for creating and entering minimal shells based on installables.</p>
<h2 id="heading-references">References</h2>
<ul>
<li><a target="_blank" href="https://discourse.nixos.org/t/nix-shells-tips-tricks-and-best-practices/22332">Nix shells - tips, tricks, and best practices - NixOS Discourse</a>.</li>
<li><a target="_blank" href="https://nixos.org/manual/nix/unstable/command-ref/new-cli/nix3-develop.html">nix develop - Nix Reference Manual - NixOS Linux</a>.</li>
<li><a target="_blank" href="https://nixos.wiki/wiki/Development_environment_with_nix-shell">Development environment with nix-shell - NixOS Wiki</a>.</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Enable Bluetooth in Nixos]]></title><description><![CDATA[NixOS is a Linux distribution that is built on the Nix package manager. It allows you to declaratively specify your system configuration in a file called /etc/nixos/configuration.nix and then apply it with a single command. This makes NixOS very repr...]]></description><link>https://hashnode.adityakumar.xyz/enable-bluetooth-in-nixos</link><guid isPermaLink="true">https://hashnode.adityakumar.xyz/enable-bluetooth-in-nixos</guid><category><![CDATA[Nix]]></category><category><![CDATA[bluetooth]]></category><dc:creator><![CDATA[Aditya Kumar]]></dc:creator><pubDate>Sat, 24 Jun 2023 04:45:14 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/9jLI9Ux6IFo/upload/54a8ba4dc55189a4cb71936bcc9b7ae1.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>NixOS is a Linux distribution that is built on the Nix package manager. It allows you to declaratively specify your system configuration in a file called /etc/nixos/configuration.nix and then apply it with a single command. This makes NixOS very reproducible, reliable and customizable.</p>
<p>One of the features that you might want to enable on your NixOS system is Bluetooth support. Bluetooth is a wireless technology that allows you to connect various devices such as keyboards, mice, headphones, speakers and more. In this blog post, I will show you how to enable Bluetooth support on NixOS and how to pair and connect your Bluetooth devices.</p>

<h2 id="heading-enabling-bluetooth-support">Enabling Bluetooth Support</h2>
<p>To enable Bluetooth support on NixOS, you need to add the following line to your /etc/nixos/configuration.nix file:</p>
<pre><code class="lang-nix">hardware.bluetooth.<span class="hljs-attr">enable</span> = <span class="hljs-literal">true</span>;
</code></pre>
<p>This will enable the hardware.bluetooth module that provides the necessary drivers and services for Bluetooth. You can also customize some options such as the device name, the pin code and the power management settings. For more details, you can check the <a target="_blank" href="https://nixos.wiki/wiki/Bluetooth">NixOS Wiki</a>.</p>
<p>If you want to check the battery status of your Bluetooth devices, you need to enable the experimental feature of BlueZ by adding the following snippet to your configuration.nix file:</p>
<pre><code class="lang-nix">hardware.<span class="hljs-attr">bluetooth</span> = {
  <span class="hljs-attr">enable</span> = <span class="hljs-literal">true</span>;
  <span class="hljs-attr">settings</span> = {
    <span class="hljs-attr">General</span> = {
      <span class="hljs-attr">Experimental</span> = <span class="hljs-string">"true"</span>;
    };
  };
};
</code></pre>
<p>This will allow you to use the bluetooth-battery python script or the GNOME extension to see the battery level of your devices.</p>
<p>After adding the lines to your configuration.nix file, you need to run the following command as root to apply the changes:</p>
<pre><code class="lang-bash">nixos-rebuild switch
</code></pre>
<p>This will rebuild your system configuration and activate the new settings. You can also use <code>nixos-rebuild test</code> or <code>nixos-rebuild boot</code> if you want to test or boot into the new configuration without switching to it immediately.</p>
<h3 id="heading-checking-bluetooth-device-battery-status">Checking Bluetooth Device Battery Status</h3>
<h2 id="heading-pairing-bluetooth-devices">Pairing Bluetooth Devices</h2>
<p>After enabling Bluetooth support on NixOS, you need to pair your Bluetooth devices with your NixOS machine. There are two ways to do this: using a graphical user interface (GUI) or using a command line tool.</p>
<h3 id="heading-using-a-gui">Using a GUI</h3>
<p>If you are using a desktop environment that provides a Bluetooth management GUI, such as GNOME, KDE or Cinnamon, you can use it to pair your devices. You can usually find the Bluetooth icon in the system tray or the settings menu. You can click on it and then select "Add Device" or "Set Up New Device" to start the pairing process. You will see a list of available devices and you can select the one you want to pair with. You might need to enter a pin code or confirm the pairing on both devices.</p>
<p>If your desktop environment does not provide a Bluetooth management GUI, you can additionally enable the blueman service in your configuration.nix file with the following line:</p>
<pre><code class="lang-nix">services.blueman.<span class="hljs-attr">enable</span> = <span class="hljs-literal">true</span>;
</code></pre>
<p>This will install and enable blueman, a GTK-based Bluetooth manager that provides blueman-applet and blueman-manager. You can run blueman-applet to show the Bluetooth icon in the system tray and blueman-manager to open a window where you can manage your devices. You can use them in a similar way as described above.</p>
<h3 id="heading-using-bluetoothctl">Using bluetoothctl</h3>
<p>Alternatively, you can pair your devices from the command line using bluetoothctl, a tool that is part of the BlueZ package. BlueZ is the official Linux Bluetooth protocol stack and it provides various utilities and libraries for Bluetooth functionality.</p>
<p>To use bluetoothctl, you need to open a terminal and run it with:</p>
<pre><code class="lang-bash">bluetoothctl
</code></pre>
<p>This will start an interactive shell where you can enter various commands to control your Bluetooth devices. You will see something like this:</p>
<pre><code class="lang-bash">Agent registered
[bluetooth]<span class="hljs-comment">#</span>
</code></pre>
<p>The <code>[bluetooth]#</code> prompt indicates that you are in bluetoothctl mode. You can type <code>help</code> to see a list of available commands and their descriptions. Some of the most useful commands are:</p>
<ul>
<li><code>power on</code>: Turns on the Bluetooth controller.</li>
<li><code>agent on</code>: Enables the default agent that handles pairing requests.</li>
<li><code>default-agent</code>: Sets the default agent as the default one.</li>
<li><code>scan on</code>: Starts scanning for nearby devices.</li>
<li><code>pair [hex-address]</code>: Pairs with the device with the given hexadecimal address.</li>
<li><code>connect [hex-address]</code>: Connects to the device with the given hexadecimal address.</li>
<li><code>trust [hex-address]</code>: Trusts the device with the given hexadecimal address so that it automatically connects when available.</li>
<li><code>info [hex-address]</code>: Shows information about the device with the given hexadecimal address.</li>
<li><code>devices</code>: Shows a list of paired devices.</li>
<li><code>remove [hex-address]</code>: Removes the device with the given hexadecimal address from the list of paired devices.</li>
<li><code>quit</code>: Exits bluetoothctl mode.</li>
</ul>
<p>To pair a device with bluetoothctl, you need to follow these steps:</p>
<ol>
<li>Turn on the Bluetooth controller with <code>power on</code>.</li>
<li>Enable the default agent with <code>agent on</code> and <code>default-agent</code>.</li>
<li>Start scanning for nearby devices with <code>scan on</code>.</li>
<li>Put your device in pairing mode and wait for its hexadecimal address to appear in the output of bluetoothctl.</li>
<li>Pair with the device with <code>pair [hex-address]</code> where you replace [hex-address] with the actual address of your device.</li>
<li>Connect to the device with <code>connect [hex-address]</code>.</li>
<li>Trust the device with <code>trust [hex-address]</code> if you want it to automatically connect when available.</li>
</ol>
<p>You can also use tab completion to enter the hexadecimal address of your device more easily. For example, if your device's address is 11:22:33:44:55:66, you can type <code>pair 11</code> and then press tab to complete the rest of the address.</p>
<h2 id="heading-using-bluetooth-devices">Using Bluetooth Devices</h2>
<p>After pairing and connecting your Bluetooth devices, you can use them as normal. For example, if you paired a Bluetooth keyboard or mouse, you can use them to input commands or move the cursor. If you paired a Bluetooth headset or speaker, you can use them to listen to audio or make calls.</p>
<p>If you are using a Bluetooth headset with PulseAudio, you will need to enable both hardware.pulseaudio.enable and hardware.bluetooth.enable in your configuration.nix file as follows:</p>
<pre><code class="lang-nix">hardware.pulseaudio.<span class="hljs-attr">enable</span> = <span class="hljs-literal">true</span>;
hardware.bluetooth.<span class="hljs-attr">enable</span> = <span class="hljs-literal">true</span>;
</code></pre>
<p>This will allow Bluetooth audio devices to be used with PulseAudio, the sound server that handles audio playback and recording on NixOS. You will also need to restart PulseAudio with:</p>
<pre><code class="lang-bash">systemctl --user daemon-reload; systemctl --user restart pulseaudio
</code></pre>
<p>You can verify that PulseAudio has loaded the Bluetooth module by running:</p>
<pre><code class="lang-bash">pactl list | grep -i <span class="hljs-string">'Name.*module.*blue'</span>
</code></pre>
<p>Bluetooth modules should be present in the list. You can also use tools like pavucontrol or pactl to manage your audio devices and streams.</p>
<p>If your Bluetooth headset has buttons for pause/play or to skip to the next track, you can use them to control media players that support the dbus-based MPRIS standard, such as VLC, Spotify or Rhythmbox. To make this work, you need to use mpris-proxy that is part of the BlueZ package. You can enable it as a systemd user service in your configuration.nix file with the following snippet:</p>
<pre><code class="lang-nix">systemd.user.services.<span class="hljs-attr">mpris-proxy</span> = {
  Unit.<span class="hljs-attr">Description</span> = <span class="hljs-string">"Mpris proxy"</span>;
  Unit.<span class="hljs-attr">After</span> = [ <span class="hljs-string">"network.target"</span> <span class="hljs-string">"sound.target"</span> ];
  Service.<span class="hljs-attr">ExecStart</span> = <span class="hljs-string">"<span class="hljs-subst">${pkgs.bluez}</span>/bin/mpris-proxy"</span>;
  Install.<span class="hljs-attr">WantedBy</span> = [ <span class="hljs-string">"default.target"</span> ];
};
</code></pre>
<p>This will start mpris-proxy as a daemon that translates Bluetooth headset button events into MPRIS commands for media players.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this blog post, I showed you how to enable Bluetooth support on NixOS and how to pair and connect your Bluetooth devices. I also showed you how to use Bluetooth headsets with PulseAudio and how to control media players with Bluetooth headset buttons. I hope you found this post useful and informative.</p>
]]></content:encoded></item><item><title><![CDATA[Nix Flakes - A Way to Manage Nix Projects]]></title><description><![CDATA[Nix is a powerful package manager that allows you to build, run, and deploy software in a reproducible and declarative way. However, until recently, Nix had some limitations when it came to managing dependencies, composing projects, and delivering so...]]></description><link>https://hashnode.adityakumar.xyz/nix-flakes-a-way-to-manage-nix-projects</link><guid isPermaLink="true">https://hashnode.adityakumar.xyz/nix-flakes-a-way-to-manage-nix-projects</guid><category><![CDATA[Nix]]></category><dc:creator><![CDATA[Aditya Kumar]]></dc:creator><pubDate>Sun, 18 Jun 2023 06:42:38 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1688710486477/4dc83ef2-463a-4069-88bc-3e4f54cefdb0.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Nix is a powerful package manager that allows you to build, run, and deploy software in a reproducible and declarative way. However, until recently, Nix had some limitations when it came to managing dependencies, composing projects, and delivering software to users. In this blog post, we will introduce nix flakes, a new experimental feature that aims to solve these problems and improve the usability and composability of Nix.
</p>
<h2 id="heading-nix-flakes-explained">Nix flakes explained</h2>
<p>A flake is a source tree (such as a Git repository) that contains a file named <code>flake.nix</code> in its root directory. This file provides a standardized interface to Nix artifacts such as packages, NixOS modules, or Nix functions. A flake can have dependencies on other flakes, which are specified using a URL-like syntax. For example, <code>github:NixOS/nixpkgs</code> refers to the nixpkgs flake hosted on GitHub.</p>
<p>A flake also has a lock file named <code>flake.lock</code> that pins the exact revisions of its dependencies to ensure reproducible evaluation. The lock file can be updated programmatically using the <code>nix flake update</code> command.</p>
<p>Flakes are evaluated in a hermetic way, meaning that they don't depend on any external factors such as environment variables, command-line arguments, or the system type. This makes them more reliable and portable across different platforms and environments.</p>
<h2 id="heading-using-nix-flakes">Using nix flakes</h2>
<p>To use nix flakes, you need to install an experimental version of Nix that supports them. You can get it from nixpkgs by running:</p>
<pre><code class="lang-bash">nix-shell -I nixpkgs=channel:nixos-23.05 --packages nixUnstable
</code></pre>
<p>You also need to enable the experimental features in your <code>~/.config/nix/nix.conf</code> file by adding:</p>
<pre><code class="lang-nix"><span class="hljs-attr">experimental-features</span> = nix-command flakes
</code></pre>
<p>Once you have nix flakes enabled, you can create a new flake by running:</p>
<pre><code class="lang-bash">nix flake init
</code></pre>
<p>This will generate a <code>flake.nix</code> file with some basic attributes:</p>
<pre><code class="lang-nix">{
  <span class="hljs-attr">description</span> = <span class="hljs-string">"A very basic flake"</span>;

  inputs.nixpkgs.<span class="hljs-attr">url</span> = <span class="hljs-string">"github:NixOS/nixpkgs/nixos-unstable"</span>;

  <span class="hljs-attr">outputs</span> = { self, nixpkgs }: {

    <span class="hljs-comment"># A Nix package</span>
    packages.x86_64-linux.<span class="hljs-attr">hello</span> = nixpkgs.legacyPackages.x86_64-linux.hello;

    <span class="hljs-comment"># A NixOS module</span>
    nixosModules.<span class="hljs-attr">hello</span> =
      { pkgs, ... }: {
        environment.<span class="hljs-attr">systemPackages</span> = [ pkgs.hello ];
      };
  };
}
</code></pre>
<p>The <code>description</code> attribute is a string that describes the flake. The <code>inputs</code> attribute is an attribute set of all the dependencies of the flake. In this case, we only have one dependency: the nixpkgs flake. The <code>outputs</code> attribute is a function that takes an attribute set of all the realized inputs and returns another attribute set with the artifacts produced by the flake.</p>
<p>In this example, we have two outputs: a Nix package named <code>hello</code> and a NixOS module named <code>hello</code>. The package is defined using the <code>nixpkgs.legacyPackages</code> attribute, which provides access to the packages defined in nixpkgs. The module is defined as a function that takes <code>pkgs</code> and other arguments and returns a NixOS configuration.</p>
<p>To build the package, we can run:</p>
<pre><code class="lang-bash">nix build .<span class="hljs-comment">#hello</span>
</code></pre>
<p>This will build the hello package defined in the current flake (denoted by <code>.</code>) and store it in the Nix store. We can also run it directly by using:</p>
<pre><code class="lang-bash">nix run .<span class="hljs-comment">#hello</span>
</code></pre>
<p>This will build and run the hello package without installing it.</p>
<p>To use the module, we can create a <code>configuration.nix</code> file that imports it:</p>
<pre><code class="lang-nix">{ config, pkgs, ... }:

{
  <span class="hljs-attr">imports</span> = [ ./flake.nix ];

  <span class="hljs-comment"># Other configuration options...</span>
}
</code></pre>
<p>Then we can build and activate our system configuration by running:</p>
<pre><code class="lang-bash">nixos-rebuild switch --flake .
</code></pre>
<p>This will use the current flake as the source of our system configuration and apply it to our machine.</p>
<h2 id="heading-how-to-compose-nix-flakes">How to compose nix flakes?</h2>
<p>One of the main advantages of nix flakes is that they allow us to compose different Nix projects in a modular and declarative way. For example, suppose we want to use a flake that provides some useful Nix functions, such as <code>flake-utils</code>:</p>
<pre><code class="lang-nix">{
  <span class="hljs-attr">description</span> = <span class="hljs-string">"A flake with some useful Nix functions"</span>;

  inputs.flake-utils.<span class="hljs-attr">url</span> = <span class="hljs-string">"github:numtide/flake-utils"</span>;

  <span class="hljs-attr">outputs</span> = { self, nixpkgs, flake-utils }: {

    <span class="hljs-comment"># A Nix package</span>
    packages.x86_64-linux.<span class="hljs-attr">hello</span> = nixpkgs.legacyPackages.x86_64-linux.hello;

    <span class="hljs-comment"># A NixOS module</span>
    nixosModules.<span class="hljs-attr">hello</span> =
      { pkgs, ... }: {
        environment.<span class="hljs-attr">systemPackages</span> = [ pkgs.hello ];
      };

    <span class="hljs-comment"># A function that creates a flake from a simple Nixpkgs overlay</span>
    <span class="hljs-attr">overlayFlake</span> = flake-utils.lib.simpleFlake;
  };
}
</code></pre>
<p>Here we have added a new input for the <code>flake-utils</code> flake and a new output for the <code>overlayFlake</code> function. This function takes a simple Nixpkgs overlay and returns a flake that provides packages and apps based on it.</p>
<p>We can use this function to create another flake that uses an overlay to customize some packages:</p>
<pre><code class="lang-nix">{
  <span class="hljs-attr">description</span> = <span class="hljs-string">"A flake that uses an overlay to customize some packages"</span>;

  inputs.nixpkgs.<span class="hljs-attr">url</span> = <span class="hljs-string">"github:NixOS/nixpkgs/nixos-unstable"</span>;
  inputs.flake-<span class="hljs-keyword">with</span>-functions.<span class="hljs-attr">url</span> = <span class="hljs-string">"/path/to/flake-with-functions"</span>;

  <span class="hljs-attr">outputs</span> = inputs@{ self, nixpkgs, flake-<span class="hljs-keyword">with</span>-functions, ... }:
    flake-<span class="hljs-keyword">with</span>-functions.overlayFlake {
      <span class="hljs-comment"># An overlay that adds a suffix to the hello package</span>
      <span class="hljs-attr">overlay</span> = final: prev: {
        <span class="hljs-attr">hello</span> = prev.hello.overrideAttrs (old: {
          <span class="hljs-attr">name</span> = <span class="hljs-string">"<span class="hljs-subst">${old.name}</span>-customized"</span>;
        });
      };

      <span class="hljs-comment"># Other arguments passed to simpleFlake</span>
      <span class="hljs-keyword">inherit</span> inputs;
      <span class="hljs-attr">name</span> = <span class="hljs-string">"customized-hello-flake"</span>;
    };
}
</code></pre>
<p>Here we have created a new flake that depends on the <code>nixpkgs</code> flake and the <code>flake-with-functions</code> flake. We use the <code>overlayFlake</code> function from the latter to create a flake that provides a customized version of the hello package. We pass an overlay that adds a suffix to the package name, as well as other arguments required by the <code>simpleFlake</code> function.</p>
<p>We can build and run the customized hello package by using:</p>
<pre><code class="lang-bash">nix run .<span class="hljs-comment">#hello</span>
</code></pre>
<p>This will show:</p>
<pre><code class="lang-bash">Hello, world!-customized
</code></pre>
<p>We can also use the <code>niv</code> tool to manage our flake dependencies in a more convenient way. For example, we can run:</p>
<pre><code class="lang-bash">niv init -f
</code></pre>
<p>This will create a <code>sources.nix</code> file that contains the URLs and revisions of our flake inputs. We can then use this file in our <code>flake.nix</code> file by importing it:</p>
<pre><code class="lang-nix">{
  <span class="hljs-attr">description</span> = <span class="hljs-string">"A flake that uses an overlay to customize some packages"</span>;

  <span class="hljs-attr">inputs</span> = <span class="hljs-built_in">import</span> ./sources.nix;

  <span class="hljs-attr">outputs</span> = inputs@{ self, nixpkgs, flake-<span class="hljs-keyword">with</span>-functions, ... }:
    flake-<span class="hljs-keyword">with</span>-functions.overlayFlake {
      <span class="hljs-comment"># An overlay that adds a suffix to the hello package</span>
      <span class="hljs-attr">overlay</span> = final: prev: {
        <span class="hljs-attr">hello</span> = prev.hello.overrideAttrs (old: {
          <span class="hljs-attr">name</span> = <span class="hljs-string">"<span class="hljs-subst">${old.name}</span>-customized"</span>;
        });
      };

      <span class="hljs-comment"># Other arguments passed to simpleFlake</span>
      <span class="hljs-keyword">inherit</span> inputs;
      <span class="hljs-attr">name</span> = <span class="hljs-string">"customized-hello-flake"</span>;
    };
}
</code></pre>
<p>We can also use <code>niv</code> to update our dependencies by running:</p>
<pre><code class="lang-bash">niv update
</code></pre>
<p>This will fetch the latest revisions of our inputs and update the <code>sources.nix</code> file accordingly.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Nix flakes are a new experimental feature that improve the reproducibility, composability, and usability of Nix projects. They provide a standardized interface to Nix artifacts, a way to specify and pin dependencies, and a hermetic evaluation model. They also enable new ways to deliver software to users, such as using <code>nix profile</code> or <code>nix bundle</code>. Flakes are still under development and may change in the future, but they are already usable and provide many benefits over the traditional Nix approach.</p>
<p>If you want to learn more about nix flakes, you can check out the following resources:</p>
<ul>
<li><a target="_blank" href="https://github.com/NixOS/rfcs/">The NixOS RFC for flakes</a></li>
<li><a target="_blank" href="https://nixos.org/manual/nix/unstable/command-ref/new-cli/nix3-flake.html">The Nix manual for flakes</a></li>
<li><a target="_blank" href="https://nixos.wiki/wiki/Flakes">The NixOS wiki for flakes</a></li>
</ul>
<h2 id="heading-references">References</h2>
<ul>
<li>Flakes - NixOS Wiki. https://nixos.wiki/wiki/Flakes.</li>
<li>Nix Flakes, Part 1: An introduction and tutorial - Tweag. https://www.tweag.io/blog/2020-05-25-flakes/.</li>
<li>Practical Nix Flakes - Serokell Software Development Company. https://serokell.io/blog/practical-nix-flakes.</li>
<li>A Tour of Nix Flakes | Mattia Gheda. https://ghedam.at/a-tour-of-nix-flakes.</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[nix-shell Explained]]></title><description><![CDATA[Nix-shell is a powerful tool that allows you to create reproducible and isolated development environments for any project. In this blog post, I will show you how to use nix-shell to set up a development environment for a Node.js project.

What is nix...]]></description><link>https://hashnode.adityakumar.xyz/nix-shell-explained</link><guid isPermaLink="true">https://hashnode.adityakumar.xyz/nix-shell-explained</guid><category><![CDATA[Nix]]></category><dc:creator><![CDATA[Aditya Kumar]]></dc:creator><pubDate>Sun, 18 Jun 2023 04:22:01 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1688710606784/dbf6d3ca-c532-4298-8af6-ee51987a4e22.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Nix-shell is a powerful tool that allows you to create reproducible and isolated development environments for any project. In this blog post, I will show you how to use nix-shell to set up a development environment for a Node.js project.
</p>
<h2 id="heading-what-is-nix-shell">What is nix-shell?</h2>
<p>Nix-shell is a command that comes with Nix, a package manager and system configuration tool that takes a unique approach to managing software. Nix allows you to declare your dependencies in a file called <code>default.nix</code> or <code>shell.nix</code>, and then builds them in a sandboxed environment, ensuring that they are isolated from each other and from the rest of your system.</p>
<p>Nix-shell will build the dependencies of the specified derivation (a term used in Nix to refer to a package or a build process), but not the derivation itself. It will then start an interactive shell in which all environment variables defined by the derivation have been set to their corresponding values, and the script <code>$stdenv/setup</code> has been sourced. This means that you get an environment that closely resembles the one that Nix would use to build your project, but without actually building it.</p>
<p>This is useful for reproducing the environment of a derivation for development. For example, if you have a Node.js project that depends on some npm packages, you can use <code>nix-shell</code> to install those packages and run your project without affecting your global npm installation or other projects.</p>
<h2 id="heading-how-to-use-nix-shell">How to use nix-shell?</h2>
<p>To use nix-shell, you need to have Nix installed on your system. You can follow the instructions on <a target="_blank" href="https://nixos.org/download.html">NixOS website</a> to install Nix on Linux, MacOS, or Windows.</p>
<p>Once you have Nix installed, you need to create a file called <code>default.nix</code> or <code>shell.nix</code> in your project directory. This file will contain the declaration of your dependencies and any other configuration options for your development environment. For example, here is a simple <code>shell.nix</code> file for a Node.js project:</p>
<pre><code class="lang-nix">{ pkgs ? <span class="hljs-built_in">import</span> &lt;nixpkgs&gt; {} }:

pkgs.mkShell {
<span class="hljs-attr">name</span> = <span class="hljs-string">"node-project"</span>;
<span class="hljs-attr">buildInputs</span> = [ pkgs.nodejs ];
<span class="hljs-attr">shellHook</span> = <span class="hljs-string">''
echo "Welcome to node-project"
export NODE_ENV=development
''</span>;
}
</code></pre>
<p>This file uses some Nix syntax and functions that may look unfamiliar at first, but don't worry, I will explain them briefly.</p>
<ul>
<li>The first line is a function argument that allows us to import the <code>nixpkgs</code> package set, which contains thousands of pre-built packages for various languages and tools. We can access these packages through the <code>pkgs</code> variable.</li>
<li>The second line uses the <code>mkShell</code> function from <code>nixpkgs</code>, which is a helper function that creates a derivation suitable for nix-shell. It takes some arguments, such as:</li>
<li><code>name</code>: The name of the derivation.</li>
<li><code>buildInputs</code>: A list of packages that will be available in the nix-shell environment. In this case, we only need <code>nodejs</code>, which is provided by <code>nixpkgs</code>.</li>
<li><code>shellHook</code>: A bash script that will be run after <code>$stdenv/setup</code> has been sourced. This allows us to perform some initialisation specific to nix-shell, such as printing a welcome message or setting some environment variables.</li>
</ul>
<p>After creating this file, we can run <code>nix-shell</code> in our project directory, and we will be dropped into a shell where we have access to <code>nodejs</code> and our custom environment variables. We can then run our project as usual, for example:</p>
<pre><code class="lang-bash">$ nix-shell
Welcome to node-project

[nix-shell:~/node-project]$ node -v
v18.16.0

[nix-shell:~/node-project]$ node index.js 
Hello from nix-shell

[nix-shell:~/node-project]$ <span class="hljs-built_in">exit</span>
<span class="hljs-built_in">exit</span>
</code></pre>
<p>As you can see, nix-shell allows us to easily create and enter a development environment for our project without affecting our system or other projects. We can also share our <code>shell.nix</code> file with other developers and ensure that they have the same environment as us.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p><code>nix-shell</code> is a powerful tool that allows you to create reproducible and isolated development environments for any project. In this blog post, I showed you how to use <code>nix-shell</code> to set up a development environment for a Node.js project. You can learn more about <code>nix-shell</code> and Nix in general by reading the Nix manual, the Nix pills, or the NixOS website. I hope you enjoyed this blog post and found it useful. Happy hacking!</p>
]]></content:encoded></item><item><title><![CDATA[Reduce Size of Initramfs]]></title><description><![CDATA[When I was developing a Linux distribution, I had trouble getting it boot on my machine.

I thought I was building the kernel wrong and was generating initramfs wrong. So I took Debian's initrd from my machine and used it to boot. It took some time b...]]></description><link>https://hashnode.adityakumar.xyz/reduce-size-of-initramfs</link><guid isPermaLink="true">https://hashnode.adityakumar.xyz/reduce-size-of-initramfs</guid><category><![CDATA[linux kernel]]></category><category><![CDATA[initramfs]]></category><dc:creator><![CDATA[Aditya Kumar]]></dc:creator><pubDate>Sat, 29 Apr 2023 06:45:25 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/vZJdYl5JVXY/upload/4b57e28a358e84c00bca835627fb507f.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>When I was developing a Linux distribution, I had trouble getting it boot on my machine.

I thought I was building the kernel wrong and was generating initramfs wrong. So I took Debian's initrd from my machine and used it to boot. It took some time but it booted. So certainly I was generating initramfs wrong.</p>
<p>After digging around on the Internet, I found the problem lies in the large size of the initramfs. My version was several hundred megabytes. For whatever reason, the large size renders it unable to serve its purpose. The kernel modules are not stripped. Stripping the image solves the issue.</p>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> /path/to/new-kernel
find . -name *.ko -<span class="hljs-built_in">exec</span> strip --strip-unneeded {} +
</code></pre>
<p>Reference: <a target="_blank" href="https://unix.stackexchange.com/questions/270390/how-to-reduce-the-size-of-the-initrd-when-compiling-your-kernel">How to reduce the size of the initrd when compiling your kernel?</a></p>
]]></content:encoded></item><item><title><![CDATA[Install and Use Gitea]]></title><description><![CDATA[Here I document my steps to get Gitea up and running on a Debian server.
Gitea is a self-hosted service to host and accept contributions to your git repositories on the web.
Prerequisites

git

curl/wget to obtain the binary

MySQL/PostgreSQL/MSSQL/S...]]></description><link>https://hashnode.adityakumar.xyz/install-and-use-gitea</link><guid isPermaLink="true">https://hashnode.adityakumar.xyz/install-and-use-gitea</guid><category><![CDATA[gitea]]></category><dc:creator><![CDATA[Aditya Kumar]]></dc:creator><pubDate>Sun, 12 Feb 2023 05:41:29 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1688715422300/99d0759e-4776-4349-bbd6-0488c19ca2c4.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Here I document my steps to get Gitea up and running on a Debian server.</p>
<p>Gitea is a self-hosted service to host and accept contributions to your git repositories on the web.</p>
<h2 id="heading-prerequisites">Prerequisites</h2>
<ul>
<li><p>git</p>
</li>
<li><p>curl/wget to obtain the binary</p>
</li>
<li><p>MySQL/PostgreSQL/MSSQL/SQLite3/TiDB</p>
</li>
</ul>
<h2 id="heading-getting-gitea">Getting Gitea</h2>
<p>Go to Gitea's official website for <a target="_blank" href="https://docs.gitea.io/en-us/install-from-binary/">installation instructions</a>.</p>
<p>It usually boils down to</p>
<ol>
<li><p>Obtaining and verifying the binary</p>
</li>
<li><p>Creating a user</p>
</li>
<li><p>Creating directory structure</p>
</li>
<li><p>Creating a service file</p>
</li>
<li><p>Setting up a databse</p>
</li>
<li><p>Configuring Gitea</p>
</li>
</ol>
<h2 id="heading-create-user">Create user</h2>
<p>Create a user to run Gitea. Here we name it 'gitea' for the sake of our convenience.</p>
<pre><code class="lang-bash">adduer \
--system \
--shell /bin/bash \
--gecos <span class="hljs-string">'Gitea'</span> \
--group \
--disabled-password \
--home /home/gitea \
gitea
</code></pre>
<h2 id="heading-create-directory-structure">Create directory structure</h2>
<pre><code class="lang-bash">mkdir -p /var/lib/gitea/{custom,data.log}
chown -R gitea:gitea /var/lib/gitea
chmod -R 750 /var/lib/gitea
mkdir /etc/gitea
chown root:gitea /etc/gitea
chmod 770 /etc/gitea
</code></pre>
<h2 id="heading-copy-gitea-binary-to-global-location">Copy Gitea binary to global location</h2>
<pre><code class="lang-bash">cp gitea /usr/<span class="hljs-built_in">local</span>/bin/gitea
</code></pre>
<h2 id="heading-create-a-service-file">Create a service file</h2>
<p>Copy the sample <a target="_blank" href="https://github.com/go-gitea/gitea/blob/main/contrib/systemd/gitea.service">gitea.service</a> to <code>/etc/systemd/system/gitea.service</code>, then edit the file with a text editor.</p>
<p>Replace the lines starting with <code>---</code> to <code>+++</code>.</p>
<pre><code class="lang-plaintext">--- #Wants=postgresql.service
--- #After=postgresql.service
+++ Wants=postgresql.service
+++ After=postgresql.service

--- User=git
--- Group=git
+++ User=gitea
+++ Group=gitea
</code></pre>
<h2 id="heading-set-up-a-database">Set up a database</h2>
<p>As user <code>postgres</code>, run the following</p>
<pre><code class="lang-pgsql">createuser gitea
<span class="hljs-keyword">createdb</span> gitea
psql
<span class="hljs-keyword">alter</span> <span class="hljs-keyword">user</span> gites <span class="hljs-keyword">with</span> <span class="hljs-keyword">encrypted</span> <span class="hljs-keyword">password</span> <span class="hljs-string">'super-secure-password'</span>;
<span class="hljs-keyword">grant</span> <span class="hljs-keyword">all</span> <span class="hljs-keyword">privileges</span> <span class="hljs-keyword">on</span> <span class="hljs-keyword">database</span> gitea <span class="hljs-keyword">to</span> gitea;
\q
</code></pre>
<h2 id="heading-set-up-a-web-server">Set up a web server</h2>
<p>Put the following configuration in <code>/etc/caddy/Caddyfile</code></p>
<pre><code class="lang-plaintext">gitea.adityakumar.com {
  reverse_proxy localhost:3000

}
</code></pre>
<p>Now reload caddy</p>
<pre><code class="lang-bash">systemctl reload caddy
</code></pre>
<h2 id="heading-configure-gitea">Configure Gitea</h2>
<p>Enable and start Gitea</p>
<pre><code class="lang-bash">systemctl <span class="hljs-built_in">enable</span> --now gitea.service
</code></pre>
<p>Head to the website, or go to <code>localhost:3000</code> if you have physical access to the server. Alternatively you can use port forwarding to configure Gitea using your local machine.</p>
<p>On the page,</p>
<ul>
<li><p>enter database username, password and database name.</p>
</li>
<li><p>change Site Title to whatever you prefer.</p>
</li>
<li><p>enter <code>gitea</code> in Run As Username field.</p>
</li>
<li><p>change Gitea Base URL to the site's URL</p>
</li>
</ul>
<p>Rest of the options should be left as is unless you have other requirements.</p>
<p>Click on Install Gitea. It should write the configuration to <code>/etc/gitea/app.ini</code> and be ready for use.</p>
<p>Now change permissions on <code>/etc/gitea</code> to make it read-only.</p>
<pre><code class="lang-bash">chmod 750 /etc/gitea
chmod 640 /etc/gitea/app.ini
</code></pre>
]]></content:encoded></item><item><title><![CDATA[Format Code in Vim]]></title><description><![CDATA[Spend less time formatting your code with this easy trick!
gg=G

That's it. gg Goes to the top of the file. = tells vim to fix the indentation. G goes to the end of the file.]]></description><link>https://hashnode.adityakumar.xyz/format-code-in-vim</link><guid isPermaLink="true">https://hashnode.adityakumar.xyz/format-code-in-vim</guid><category><![CDATA[vim]]></category><dc:creator><![CDATA[Aditya Kumar]]></dc:creator><pubDate>Thu, 05 Jan 2023 05:23:20 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1688715769793/836eb709-4cc8-4a35-89d2-3cf069f12065.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Spend less time formatting your code with this easy trick!</p>
<pre><code class="lang-plaintext">gg=G
</code></pre>
<p>That's it. <code>gg</code> Goes to the top of the file. <code>=</code> tells vim to fix the indentation. <code>G</code> goes to the end of the file.</p>
]]></content:encoded></item><item><title><![CDATA[psql: FATAL: Peer authentication failed for user]]></title><description><![CDATA[The order of rules in pg_hba.conf matters.
Trying to connect to postgresql database with a standard user fails with psql: FATAL: Peer authentication failed fr user "user1".
The second line of pg_hba.conf makes your connection attempt fail:
local   al...]]></description><link>https://hashnode.adityakumar.xyz/psql-fatal-peer-authentication-failed-for-user</link><guid isPermaLink="true">https://hashnode.adityakumar.xyz/psql-fatal-peer-authentication-failed-for-user</guid><category><![CDATA[PostgreSQL]]></category><dc:creator><![CDATA[Aditya Kumar]]></dc:creator><pubDate>Wed, 04 Jan 2023 03:17:34 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1688715984450/337eecf6-2452-41ab-b8ea-aa64d31f917a.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The order of rules in <code>pg_hba.conf</code> matters.</p>
<p>Trying to connect to postgresql database with a standard user fails with <code>psql: FATAL: Peer authentication failed fr user "user1"</code>.</p>
<p>The second line of <code>pg_hba.conf</code> makes your connection attempt fail:</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">local</span>   <span class="hljs-keyword">all</span>     <span class="hljs-keyword">all</span>     peer
</code></pre>
<p>The order of rules matter. If the first one that matches the access method, username, database name and source IP range fails, there will be no second attempt. So either remove this line, your place your rule above this one.</p>
]]></content:encoded></item><item><title><![CDATA[Use home-manager Instead of nix-env]]></title><description><![CDATA[home-manager allows reprodicuble builds compared to nix-env. You can port your configuration to any machine and expect it to work the same.
This post assumes you are on a non-NixOS Linux system.
Getting nix
Nix can be installed via a simple shell scr...]]></description><link>https://hashnode.adityakumar.xyz/use-home-manager-instead-of-nix-env</link><guid isPermaLink="true">https://hashnode.adityakumar.xyz/use-home-manager-instead-of-nix-env</guid><category><![CDATA[Nix]]></category><dc:creator><![CDATA[Aditya Kumar]]></dc:creator><pubDate>Thu, 01 Sep 2022 07:17:47 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1688716070431/07e77c19-1217-4ab8-aa2d-3be23e555f5a.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><code>home-manager</code> allows reprodicuble builds compared to <code>nix-env</code>. You can port your configuration to any machine and expect it to work the same.</p>
<p>This post assumes you are on a non-NixOS Linux system.</p>
<h1 id="heading-getting-nix">Getting nix</h1>
<p>Nix can be installed via a simple shell script provided on <a target="_blank" href="https://nixos.org/download.html">their website</a>. Just use your judgement and follow the prompts.</p>
<h1 id="heading-installing-home-manager">Installing <code>home-manager</code></h1>
<p>The configuration is stored in <code>~/.config/nixpkgs/home.nix</code>. Run <code>home-manager switch</code> to have changes take effect.</p>
<p>Export <code>NIX_PATH</code> to your shell</p>
<pre><code class="lang-bash"><span class="hljs-built_in">export</span> NIX_PATH=<span class="hljs-variable">$HOME</span>/.nix-defexpr/channels:/nix/var/nix/profiles/per-user/root/channels<span class="hljs-variable">${NIX_PATH:+:$NIX_PATH}</span>
</code></pre>
<p>See <a target="_blank" href="https://github.com/NixOS/nix/issues/2033">issue#2033</a> and <a target="_blank" href="https://discourse.nixos.org/t/where-is-nix-path-supposed-to-be-set/16434/8">Nix discourse</a>.</p>
<p>Now add unstable nix channel</p>
<pre><code class="lang-bash"> nix-channel --add https://github.com/nix-community/home-manager/archive/master.tar.gz home-manager
</code></pre>
<p>Or latest stable (as of writing this post) 22.05, if you prefer it</p>
<pre><code class="lang-bash"> nix-channel --add https://github.com/nix-community/home-manager/archive/release-22.05.tar.gz home-manager
</code></pre>
<p>And update</p>
<pre><code class="lang-bash">nix-channel --update
</code></pre>
<p>Install Home Manager</p>
<pre><code class="lang-bash">nix-shell <span class="hljs-string">'&lt;home-manager&gt;'</span> -A install
</code></pre>
<p>Home Manager requires your shell to source <code>~/.nix-profile/etc/profile.d/hm-session-vars.sh</code>. It can be easily done by setting <code>programs.bash.enable = true;</code> (of course, here bash is just an example). This way, Home Manager will manage your shell configuration. However, you will need to migrate your bashrc configurations over to Home Manager, which might take some time. An easier way out would be to move your existing bashrc and have Home Manager use that.</p>
<pre><code class="lang-nix">{ pkgs, ...}: {
  programs.<span class="hljs-attr">bash</span> = {
    <span class="hljs-attr">enable</span> = <span class="hljs-literal">true</span>;
    <span class="hljs-attr">bashrcExtra</span> = <span class="hljs-string">''
      . ~/oldbashrc
    ''</span>;
  };
}
</code></pre>
<p>Since we are on a non-NixOS Linux system, Home Manager can automatically set some environment variables that will ease the usage of software installed with nix.</p>
<pre><code class="lang-nix">{pkgs, ...}: {
  targets.genericLinux.<span class="hljs-attr">enable</span> = <span class="hljs-literal">true</span>;
}
</code></pre>
<p>Now Home Manager is ready to use. There are many ways to install and configure packages using nix. Putting them here will make this post quite exhaustive. Check the links in the references as they go deeper and have up-to-date docs and examples.</p>
<h1 id="heading-references">References</h1>
<p><a target="_blank" href="https://nixos.wiki/wiki/Home_Manager">NixOS Wiki - Home Manager</a></p>
<p><a target="_blank" href="https://rycee.gitlab.io/home-manager/">Home Manager Manual</a></p>
]]></content:encoded></item><item><title><![CDATA[Program crashes when built with Clang but runs when built with GCC]]></title><description><![CDATA[Just how wild can a simple GCD program get?
I wrote a stupid gcd program that returns, well, GCD of two numbers. Funny enough, the program runs fine when compiled with gcc but crashes with illegal hardware instruction when compiled with clang.
My too...]]></description><link>https://hashnode.adityakumar.xyz/program-crashes-when-built-with-clang-but-runs-when-built-with-gcc</link><guid isPermaLink="true">https://hashnode.adityakumar.xyz/program-crashes-when-built-with-clang-but-runs-when-built-with-gcc</guid><category><![CDATA[debugging]]></category><dc:creator><![CDATA[Aditya Kumar]]></dc:creator><pubDate>Thu, 25 Aug 2022 18:21:48 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/cckf4TsHAuw/upload/f26c4630c969dca3986832bfd01ee158.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Just how wild can a simple GCD program get?</p>
<p>I wrote a stupid gcd program that returns, well, GCD of two numbers. Funny enough, the program runs fine when compiled with gcc but crashes with <code>illegal hardware instruction</code> when compiled with clang.</p>
<h2 id="heading-my-tools">My tools</h2>
<p>Here is the program:</p>
<pre><code class="lang-C++"><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;iostream&gt;</span></span>

<span class="hljs-function"><span class="hljs-keyword">size_t</span> <span class="hljs-title">gcd</span><span class="hljs-params">(<span class="hljs-keyword">size_t</span> dividend, <span class="hljs-keyword">size_t</span> divisor)</span> </span>{
  <span class="hljs-keyword">if</span> (divisor &gt; dividend) <span class="hljs-built_in">std</span>::swap(divisor, dividend);
  <span class="hljs-keyword">auto</span> remainder = dividend % divisor;
  <span class="hljs-keyword">if</span> (remainder == <span class="hljs-number">0</span>) <span class="hljs-keyword">return</span> divisor;
  <span class="hljs-keyword">else</span> gcd(divisor,remainder);
}

<span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">main</span><span class="hljs-params">(<span class="hljs-keyword">int</span> argc, <span class="hljs-keyword">char</span>** argv)</span> </span>{
  <span class="hljs-keyword">auto</span> dividend {<span class="hljs-built_in">std</span>::stoul(argv[<span class="hljs-number">1</span>])};
  <span class="hljs-keyword">auto</span> divisor {<span class="hljs-built_in">std</span>::stoul(argv[<span class="hljs-number">2</span>])};
  <span class="hljs-built_in">std</span>::<span class="hljs-built_in">cout</span> &lt;&lt; gcd(dividend, divisor) &lt;&lt; <span class="hljs-built_in">std</span>::<span class="hljs-built_in">endl</span>;
  <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
}
</code></pre>
<p>Some more relevant info:</p>
<pre><code class="lang-Bash">gcc --version                                                  
gcc (GCC) 12.2.0
[...]
</code></pre>
<pre><code class="lang-Bash">clang --version                                                        
clang version 14.0.6
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
</code></pre>
<pre><code class="lang-Bash">yay -Qi glibc          
Name            : glibc
Version         : 2.36-3
</code></pre>
<h2 id="heading-getting-started">Getting started</h2>
<p>Compile it with gcc:</p>
<pre><code class="lang-bash">g++ -W -Wall -Wextra -pedantic -std=c++20 -g -o gcd gcd-gcc.cpp 
gcd-gcc.cpp: In <span class="hljs-keyword">function</span> ‘int main(int, char**)’:
gcd-gcc.cpp:10:14: warning: unused parameter ‘argc’ [-Wunused-parameter]
   10 | int main(int argc, char** argv) {
      |          ~~~~^~~~
gcd-gcc.cpp: In <span class="hljs-keyword">function</span> ‘size_t gcd(size_t, size_t)’:
gcd-gcc.cpp:8:1: warning: control reaches end of non-void <span class="hljs-keyword">function</span> [-Wreturn-type]
    8 | }
      | ^
</code></pre>
<p>Compile it with clang:</p>
<pre><code class="lang-bash">clang++ -Weverything -Wno-c++98-compat -std=c++20 -g -o gcd gcd-new.cpp 
gcd-new.cpp:3:8: warning: no previous prototype <span class="hljs-keyword">for</span> <span class="hljs-keyword">function</span> <span class="hljs-string">'gcd'</span> [-Wmissing-prototypes]
size_t gcd(size_t dividend, size_t divisor) {
       ^
gcd-new.cpp:3:1: note: <span class="hljs-built_in">declare</span> <span class="hljs-string">'static'</span> <span class="hljs-keyword">if</span> the <span class="hljs-keyword">function</span> is not intended to be used outside of this translation unit
size_t gcd(size_t dividend, size_t divisor) {
^
static 
gcd-new.cpp:8:1: warning: non-void <span class="hljs-keyword">function</span> does not <span class="hljs-built_in">return</span> a value <span class="hljs-keyword">in</span> all control paths [-Wreturn-type]
}
^
gcd-new.cpp:10:14: warning: unused parameter <span class="hljs-string">'argc'</span> [-Wunused-parameter]
int main(int argc, char** argv) {
             ^
3 warnings generated.
</code></pre>
<p>So far everything seems good. Now running gcc's version gives</p>
<pre><code class="lang-bash">./gcd 70 60
10
</code></pre>
<p>...which is expected.</p>
<p>And clang's version:</p>
<pre><code class="lang-bash">./gcd 70 60
[1]    12974 illegal hardware instruction  ./gcd 70 60
</code></pre>
<p>There it is! Let's dig in.</p>
<pre><code class="lang-bash">lldb ./gcd
(lldb) target create <span class="hljs-string">"./gcd"</span>
Current executable <span class="hljs-built_in">set</span> to <span class="hljs-string">'/tmp/gcd'</span> (x86_64).
(lldb) r 70 60
Process 13207 launched: <span class="hljs-string">'/tmp/gcd'</span> (x86_64)
Process 13207 stopped
* thread <span class="hljs-comment">#1, name = 'gcd', stop reason = signal SIGILL: illegal instruction operand</span>
    frame <span class="hljs-comment">#0: 0x0000555555556368 gcd`gcd(dividend=70, divisor=60) at gcd-new.cpp:6:20</span>
   3    size_t gcd(size_t dividend, size_t divisor) {
   4      <span class="hljs-keyword">if</span> (divisor &gt; dividend) std::swap(divisor, dividend);
   5      auto remainder = dividend % divisor;
-&gt; 6      <span class="hljs-keyword">if</span> (remainder == 0) <span class="hljs-built_in">return</span> divisor;
   7      <span class="hljs-keyword">else</span> gcd(divisor,remainder);
   8    }
   9   
(lldb)
</code></pre>
<p>Stop reason says <code>signal SIGILL: illegal instruction operand</code>.</p>
<p>Illegal instruction operand? <code>dividend</code> is of type <code>size_t</code>, <code>divisor</code> is of type <code>size_t</code>. The modulus operator, in this case, will always return an integer greater than 0. Considering the above cases, the compiler should assign type <code>size_t</code> to <code>remainder</code>. Let's verify this.</p>
<pre><code class="lang-plaintext">(lldb) frame variable remainder
(unsigned long) remainder = 10
(lldb)
</code></pre>
<p>Turns out <code>remainder</code> is of type <code>unsigned long</code>, which should be fine in this case since comparison between unsigned long and a literal 0 is perfectly legal. If my memory serves right a literal 0 will be treated as a decimal of type <code>int</code>. Comparing it with type <code>unsigned long</code> would promote it to <code>unsigned long</code> and result in potential data loss of the signed bit. I think I am able to see the problem. The compiler would definitely deny such implicit type conversions.</p>
<p>Okay let's try changing it's data type to <code>long</code>.</p>
<pre><code class="lang-bash">diff gcd-gcc.cpp gcd-new.cpp 
5c5
&lt;   auto remainder = dividend % divisor;
---
&gt;   long remainder = dividend % divisor;
</code></pre>
<p>Now we get a message from the compiler:</p>
<pre><code class="lang-bash">gcd-new.cpp:5:29: warning: implicit conversion changes signedness: <span class="hljs-string">'unsigned long'</span> to <span class="hljs-string">'long'</span> [-Wsign-conversion]
  long remainder = dividend % divisor;
       ~~~~~~~~~   ~~~~~~~~~^~~~~~~~~
</code></pre>
<p>Now we can be sure <code>dividend</code> and <code>divisor</code> will be of type <code>long</code> in this line of code.</p>
<p>Let's try running.</p>
<pre><code class="lang-bash">./gcd 70 60
[1]    13887 illegal hardware instruction  ./gcd 70 60
</code></pre>
<p>It crashes again.</p>
<pre><code class="lang-bash">lldb ./gcd
(lldb) target create <span class="hljs-string">"./gcd"</span>
Current executable <span class="hljs-built_in">set</span> to <span class="hljs-string">'/tmp/gcd'</span> (x86_64).
(lldb) r 70 60
Process 13927 launched: <span class="hljs-string">'/tmp/gcd'</span> (x86_64)
Process 13927 stopped
* thread <span class="hljs-comment">#1, name = 'gcd', stop reason = signal SIGILL: illegal instruction operand</span>
    frame <span class="hljs-comment">#0: 0x0000555555556368 gcd`gcd(dividend=70, divisor=60) at gcd-new.cpp:6:20</span>
   3    size_t gcd(size_t dividend, size_t divisor) {
   4      <span class="hljs-keyword">if</span> (divisor &gt; dividend) std::swap(divisor, dividend);
   5      long remainder = dividend % divisor;
-&gt; 6      <span class="hljs-keyword">if</span> (remainder == 0) <span class="hljs-built_in">return</span> divisor;
   7      <span class="hljs-keyword">else</span> gcd(divisor,remainder);
   8    }
   9   
(lldb)
</code></pre>
<p>And the reason remains the same. Let's revert the changes and debug again.</p>
<p>Checking all variables reveal</p>
<pre><code class="lang-plaintext">(lldb) frame variable
(size_t) dividend = 70
(size_t) divisor = 60
(unsigned long) remainder = 10
(lldb)
</code></pre>
<p>Everything is normal here. So what causes the comparison of <code>remainder</code> with 0 raise <code>SIGILL</code>?</p>
<h2 id="heading-going-deeper">Going deeper</h2>
<p>Let's examine the assembly file.</p>
<pre><code class="lang-nix">  <span class="hljs-number">118</span> .Ltmp6:
  <span class="hljs-number">119</span>     .loc    <span class="hljs-number">0</span> <span class="hljs-number">6</span> <span class="hljs-number">17</span> is_stmt <span class="hljs-number">1</span>                <span class="hljs-comment"># gcd-new.cpp:6:17</span>
  <span class="hljs-number">120</span>     cmpq    $<span class="hljs-number">0</span>, -<span class="hljs-number">32</span>(%rbp)
  <span class="hljs-number">121</span> .Ltmp7:
  <span class="hljs-number">122</span>     .loc    <span class="hljs-number">0</span> <span class="hljs-number">6</span> <span class="hljs-number">7</span> is_stmt <span class="hljs-number">0</span>                 <span class="hljs-comment"># gcd-new.cpp:6:7</span>
  <span class="hljs-number">123</span>     jne .LBB1_5
  <span class="hljs-number">124</span> <span class="hljs-comment"># %bb.3:</span>
  <span class="hljs-number">125</span> .Ltmp8:
  <span class="hljs-number">126</span>     .loc    <span class="hljs-number">0</span> <span class="hljs-number">6</span> <span class="hljs-number">30</span>                          <span class="hljs-comment"># gcd-new.cpp:6:30</span>
  <span class="hljs-number">127</span>     movq    -<span class="hljs-number">24</span>(%rbp), %rax
  <span class="hljs-number">128</span>     movq    %rax, -<span class="hljs-number">40</span>(%rbp)                 <span class="hljs-comment"># 8-byte Spill</span>
  <span class="hljs-number">129</span>     movq    %fs:<span class="hljs-number">40</span>, %rax
  <span class="hljs-number">130</span>     movq    -<span class="hljs-number">8</span>(%rbp), %rcx
  <span class="hljs-number">131</span>     cmpq    %rcx, %rax
  <span class="hljs-number">132</span>     jne .LBB1_7
  <span class="hljs-number">133</span> <span class="hljs-comment"># %bb.4:</span>
  <span class="hljs-number">134</span>     .loc    <span class="hljs-number">0</span> <span class="hljs-number">0</span> <span class="hljs-number">30</span>                          <span class="hljs-comment"># gcd-new.cpp:0:30</span>
  <span class="hljs-number">135</span>     movq    -<span class="hljs-number">40</span>(%rbp), %rax                 <span class="hljs-comment"># 8-byte Reload</span>
  <span class="hljs-number">136</span>     .loc    <span class="hljs-number">0</span> <span class="hljs-number">6</span> <span class="hljs-number">23</span>                          <span class="hljs-comment"># gcd-new.cpp:6:23</span>
  <span class="hljs-number">137</span>     addq    $<span class="hljs-number">48</span>, %rsp
  <span class="hljs-number">138</span>     popq    %rbp
  <span class="hljs-number">139</span>     .cfi_def_cfa %rsp, <span class="hljs-number">8</span>
  <span class="hljs-number">140</span>     retq
</code></pre>
<p>This is the entire code for line 6 in the C++ source file.</p>
<p>Here in line 120 is the code for the equality check. Line 123 tells the compiler to jump to <code>else</code> part if the comparison is not equal (section <code>LBB1_5</code> contains code for <code>else</code> part). And a lot of stuff happening there like code to prevent buffer overflow (lines 129 - 132).</p>
<p>In short, I know what is happening but not enough to tell what is breaking. Maybe I'll just have lldb dump the assembly code of the function. It will probably be the same as what we already saw.</p>
<pre><code class="lang-nix">(lldb) disas -n gcd
gcd`gcd:
    <span class="hljs-number">0</span>x5555555562e0 &lt;+<span class="hljs-number">0</span>&gt;:   pushq  %rbp
    <span class="hljs-number">0</span>x5555555562e1 &lt;+<span class="hljs-number">1</span>&gt;:   movq   %rsp, %rbp
    <span class="hljs-number">0</span>x5555555562e4 &lt;+<span class="hljs-number">4</span>&gt;:   subq   $<span class="hljs-number">0</span>x30, %rsp
    <span class="hljs-number">0</span>x5555555562e8 &lt;+<span class="hljs-number">8</span>&gt;:   movq   %fs:<span class="hljs-number">0</span>x28, %rax
    <span class="hljs-number">0</span>x5555555562f1 &lt;+<span class="hljs-number">17</span>&gt;:  movq   %rax, -<span class="hljs-number">0</span>x8(%rbp)
    <span class="hljs-number">0</span>x5555555562f5 &lt;+<span class="hljs-number">21</span>&gt;:  movq   %rdi, -<span class="hljs-number">0</span>x10(%rbp)
    <span class="hljs-number">0</span>x5555555562f9 &lt;+<span class="hljs-number">25</span>&gt;:  movq   %rsi, -<span class="hljs-number">0</span>x18(%rbp)
    <span class="hljs-number">0</span>x5555555562fd &lt;+<span class="hljs-number">29</span>&gt;:  movq   -<span class="hljs-number">0</span>x18(%rbp), %rax
    <span class="hljs-number">0</span>x555555556301 &lt;+<span class="hljs-number">33</span>&gt;:  cmpq   -<span class="hljs-number">0</span>x10(%rbp), %rax
    <span class="hljs-number">0</span>x555555556305 &lt;+<span class="hljs-number">37</span>&gt;:  jbe    <span class="hljs-number">0</span>x555555556318            ; &lt;+<span class="hljs-number">56</span>&gt; at gcd-new.cpp:<span class="hljs-number">5</span>:<span class="hljs-number">20</span>
    <span class="hljs-number">0</span>x55555555630b &lt;+<span class="hljs-number">43</span>&gt;:  leaq   -<span class="hljs-number">0</span>x18(%rbp), %rdi
    <span class="hljs-number">0</span>x55555555630f &lt;+<span class="hljs-number">47</span>&gt;:  leaq   -<span class="hljs-number">0</span>x10(%rbp), %rsi
    <span class="hljs-number">0</span>x555555556313 &lt;+<span class="hljs-number">51</span>&gt;:  callq  <span class="hljs-number">0</span>x555555556550            ; std::swap&lt;unsigned long&gt; at move.h:<span class="hljs-number">199</span>
    <span class="hljs-number">0</span>x555555556318 &lt;+<span class="hljs-number">56</span>&gt;:  movq   -<span class="hljs-number">0</span>x10(%rbp), %rax
    <span class="hljs-number">0</span>x55555555631c &lt;+<span class="hljs-number">60</span>&gt;:  xorl   %ecx, %ecx
    <span class="hljs-number">0</span>x55555555631e &lt;+<span class="hljs-number">62</span>&gt;:  movl   %ecx, %edx
    <span class="hljs-number">0</span>x555555556320 &lt;+<span class="hljs-number">64</span>&gt;:  divq   -<span class="hljs-number">0</span>x18(%rbp)
    <span class="hljs-number">0</span>x555555556324 &lt;+<span class="hljs-number">68</span>&gt;:  movq   %rdx, -<span class="hljs-number">0</span>x20(%rbp)
    <span class="hljs-number">0</span>x555555556328 &lt;+<span class="hljs-number">72</span>&gt;:  cmpq   $<span class="hljs-number">0</span>x0, -<span class="hljs-number">0</span>x20(%rbp)
    <span class="hljs-number">0</span>x55555555632d &lt;+<span class="hljs-number">77</span>&gt;:  jne    <span class="hljs-number">0</span>x55555555635b            ; &lt;+<span class="hljs-number">123</span>&gt; at gcd-new.cpp:<span class="hljs-number">7</span>:<span class="hljs-number">12</span>
    <span class="hljs-number">0</span>x555555556333 &lt;+<span class="hljs-number">83</span>&gt;:  movq   -<span class="hljs-number">0</span>x18(%rbp), %rax
    <span class="hljs-number">0</span>x555555556337 &lt;+<span class="hljs-number">87</span>&gt;:  movq   %rax, -<span class="hljs-number">0</span>x28(%rbp)
    <span class="hljs-number">0</span>x55555555633b &lt;+<span class="hljs-number">91</span>&gt;:  movq   %fs:<span class="hljs-number">0</span>x28, %rax
    <span class="hljs-number">0</span>x555555556344 &lt;+<span class="hljs-number">100</span>&gt;: movq   -<span class="hljs-number">0</span>x8(%rbp), %rcx
    <span class="hljs-number">0</span>x555555556348 &lt;+<span class="hljs-number">104</span>&gt;: cmpq   %rcx, %rax
    <span class="hljs-number">0</span>x55555555634b &lt;+<span class="hljs-number">107</span>&gt;: jne    <span class="hljs-number">0</span>x55555555636a            ; &lt;+<span class="hljs-number">138</span>&gt; at gcd-new.cpp
    <span class="hljs-number">0</span>x555555556351 &lt;+<span class="hljs-number">113</span>&gt;: movq   -<span class="hljs-number">0</span>x28(%rbp), %rax
    <span class="hljs-number">0</span>x555555556355 &lt;+<span class="hljs-number">117</span>&gt;: addq   $<span class="hljs-number">0</span>x30, %rsp
    <span class="hljs-number">0</span>x555555556359 &lt;+<span class="hljs-number">121</span>&gt;: popq   %rbp
    <span class="hljs-number">0</span>x55555555635a &lt;+<span class="hljs-number">122</span>&gt;: retq   
    <span class="hljs-number">0</span>x55555555635b &lt;+<span class="hljs-number">123</span>&gt;: movq   -<span class="hljs-number">0</span>x18(%rbp), %rdi
    <span class="hljs-number">0</span>x55555555635f &lt;+<span class="hljs-number">127</span>&gt;: movq   -<span class="hljs-number">0</span>x20(%rbp), %rsi
    <span class="hljs-number">0</span>x555555556363 &lt;+<span class="hljs-number">131</span>&gt;: callq  <span class="hljs-number">0</span>x5555555562e0            ; &lt;+<span class="hljs-number">0</span>&gt; at gcd-new.cpp:<span class="hljs-number">3</span>
-&gt;  <span class="hljs-number">0</span>x555555556368 &lt;+<span class="hljs-number">136</span>&gt;: ud2    
    <span class="hljs-number">0</span>x55555555636a &lt;+<span class="hljs-number">138</span>&gt;: callq  <span class="hljs-number">0</span>x555555556140            ; symbol stub for: __stack_chk_fail
(lldb)
</code></pre>
<p>...and there we go. It seems more or less the same except the second last line. The arrow tells that is where things fell apart. Seems like things got a little bit wilder.</p>
<p>Apparently, line 6 in the C++ source is undefined behaviour and LLVM decided to put <code>ub2</code> to crash the program instead of doing anything it could have (because it is undefined behaviour).</p>
<p>Now this brings me to my next question: why does it work on gcc's version? Let's check out.</p>
<pre><code class="lang-nix">(lldb) disas -n gcd
gcd`gcd:
<span class="hljs-number">0</span>x555555556289 &lt;+<span class="hljs-number">0</span>&gt;:   pushq  %rbp
<span class="hljs-number">0</span>x55555555628a &lt;+<span class="hljs-number">1</span>&gt;:   movq   %rsp, %rbp
<span class="hljs-number">0</span>x55555555628d &lt;+<span class="hljs-number">4</span>&gt;:   subq   $<span class="hljs-number">0</span>x20, %rsp
<span class="hljs-number">0</span>x555555556291 &lt;+<span class="hljs-number">8</span>&gt;:   movq   %rdi, -<span class="hljs-number">0</span>x18(%rbp)
<span class="hljs-number">0</span>x555555556295 &lt;+<span class="hljs-number">12</span>&gt;:  movq   %rsi, -<span class="hljs-number">0</span>x20(%rbp)
<span class="hljs-number">0</span>x555555556299 &lt;+<span class="hljs-number">16</span>&gt;:  movq   -<span class="hljs-number">0</span>x20(%rbp), %rax
<span class="hljs-number">0</span>x55555555629d &lt;+<span class="hljs-number">20</span>&gt;:  movq   -<span class="hljs-number">0</span>x18(%rbp), %rdx
<span class="hljs-number">0</span>x5555555562a1 &lt;+<span class="hljs-number">24</span>&gt;:  cmpq   %rax, %rdx
<span class="hljs-number">0</span>x5555555562a4 &lt;+<span class="hljs-number">27</span>&gt;:  jae    <span class="hljs-number">0</span>x22b9                    ; &lt;+<span class="hljs-number">48</span>&gt; at gcd-gcc.cpp:<span class="hljs-number">5</span>:<span class="hljs-number">29</span>
<span class="hljs-number">0</span>x5555555562a6 &lt;+<span class="hljs-number">29</span>&gt;:  leaq   -<span class="hljs-number">0</span>x18(%rbp), %rdx
<span class="hljs-number">0</span>x5555555562aa &lt;+<span class="hljs-number">33</span>&gt;:  leaq   -<span class="hljs-number">0</span>x20(%rbp), %rax
<span class="hljs-number">0</span>x5555555562ae &lt;+<span class="hljs-number">37</span>&gt;:  movq   %rdx, %rsi
<span class="hljs-number">0</span>x5555555562b1 &lt;+<span class="hljs-number">40</span>&gt;:  movq   %rax, %rdi
<span class="hljs-number">0</span>x5555555562b4 &lt;+<span class="hljs-number">43</span>&gt;:  callq  <span class="hljs-number">0</span>x2911                    ; _ZSt4swapImENSt9enable_ifIXsrSt6__and_IJSt6__not_ISt15__is_tuple_likeIT_EESt21is_move_constructibleIS4_ESt18is_move_assignableIS4_EEE5valueEvE4typeERS4_SE_ at move.h:<span class="hljs-number">196</span>:<span class="hljs-number">5</span>
<span class="hljs-number">0</span>x5555555562b9 &lt;+<span class="hljs-number">48</span>&gt;:  movq   -<span class="hljs-number">0</span>x18(%rbp), %rax
<span class="hljs-number">0</span>x5555555562bd &lt;+<span class="hljs-number">52</span>&gt;:  movq   -<span class="hljs-number">0</span>x20(%rbp), %rcx
<span class="hljs-number">0</span>x5555555562c1 &lt;+<span class="hljs-number">56</span>&gt;:  movl   $<span class="hljs-number">0</span>x0, %edx
<span class="hljs-number">0</span>x5555555562c6 &lt;+<span class="hljs-number">61</span>&gt;:  divq   %rcx
<span class="hljs-number">0</span>x5555555562c9 &lt;+<span class="hljs-number">64</span>&gt;:  movq   %rdx, -<span class="hljs-number">0</span>x8(%rbp)
<span class="hljs-number">0</span>x5555555562cd &lt;+<span class="hljs-number">68</span>&gt;:  cmpq   $<span class="hljs-number">0</span>x0, -<span class="hljs-number">0</span>x8(%rbp)
<span class="hljs-number">0</span>x5555555562d2 &lt;+<span class="hljs-number">73</span>&gt;:  jne    <span class="hljs-number">0</span>x22da                    ; &lt;+<span class="hljs-number">81</span>&gt; at gcd-gcc.cpp:<span class="hljs-number">7</span>:<span class="hljs-number">11</span>
<span class="hljs-number">0</span>x5555555562d4 &lt;+<span class="hljs-number">75</span>&gt;:  movq   -<span class="hljs-number">0</span>x20(%rbp), %rax
<span class="hljs-number">0</span>x5555555562d8 &lt;+<span class="hljs-number">79</span>&gt;:  jmp    <span class="hljs-number">0</span>x22ed                    ; &lt;+<span class="hljs-number">100</span>&gt; at gcd-gcc.cpp:<span class="hljs-number">8</span>:<span class="hljs-number">1</span>
<span class="hljs-number">0</span>x5555555562da &lt;+<span class="hljs-number">81</span>&gt;:  movq   -<span class="hljs-number">0</span>x20(%rbp), %rax
<span class="hljs-number">0</span>x5555555562de &lt;+<span class="hljs-number">85</span>&gt;:  movq   -<span class="hljs-number">0</span>x8(%rbp), %rdx
<span class="hljs-number">0</span>x5555555562e2 &lt;+<span class="hljs-number">89</span>&gt;:  movq   %rdx, %rsi
<span class="hljs-number">0</span>x5555555562e5 &lt;+<span class="hljs-number">92</span>&gt;:  movq   %rax, %rdi
<span class="hljs-number">0</span>x5555555562e8 &lt;+<span class="hljs-number">95</span>&gt;:  callq  <span class="hljs-number">0</span>x2289                    ; &lt;+<span class="hljs-number">0</span>&gt; at gcd-gcc.cpp:<span class="hljs-number">3</span>:<span class="hljs-number">45</span>
<span class="hljs-number">0</span>x5555555562ed &lt;+<span class="hljs-number">100</span>&gt;: leave  
<span class="hljs-number">0</span>x5555555562ee &lt;+<span class="hljs-number">101</span>&gt;: retq   
(lldb)
</code></pre>
<p>The instructions look a little bit smaller and it looks like there is no stack canary? I am not sure. A few more things are different. Apart from that everything else seems similar.</p>
<h2 id="heading-lessons-learnt">Lessons learnt</h2>
<p>In the end I couldn't figure out what broke. I'll probably ask someone smarter.</p>
<h2 id="heading-wrapping-up">Wrapping up</h2>
<p>While I definitely was unable to tell what broke, I enjoyed every bit of it. I learned a lot about compiler's behaviour and what looks like seemingly harmless code may just be very unsafe waiting for a disaster to unfold.</p>
]]></content:encoded></item></channel></rss>