Storage optimization: Difference between revisions

imported>Mth
not sure about these changes, review appreciated
imported>Mth
No edit summary
Line 1: Line 1:
A recurring problem with NixOS is lack of space on <code>/</code>. Even if you are using Nix only occasionally, it is easy for <code>/nix/store</code> to go beyond 50G.
A recurring problem with NixOS is lack of space on <code>/</code>. Even if you are using Nix only occasionally, it is easy for <code>/nix/store</code> to go beyond 50G. Here are generic notes on how to not run out of space too often.


Here are generic notes on how to not run out of space too often. I assume you already know about <code>nix-collect-garbage</code> and do care about used disk space.
== Garbage collection ==


== Move the store ==
The Nix store sometimes contains entries which are no longer useful.<ref group="cf.">[https://nixos.org/nix/manual/#sec-garbage-collection Nix Manual, 11. Garbage Collection]</ref> They can be deleted with {{ic|nix-collect-garbage -d}} <ref group="cf.">{{man|nix-collect-garbage|sec=1}}</ref> or {{ic|nix-store --gc}}.<ref group="cf.">{{man|nix-store|sec=1}}, under {{ic|OPERATION --GC}}</ref>


{{ic|/nix}} can reside on another device. This is useful if your root device is very small, and that you have another, larger drive at hand. It is easiest to set up when installing NixOS. To move <code>/nix</code> to another device on an existing NixOS installation:
Note that if a result file still exists in the file system, all the dependencies used to build it will be kept. To see which result files prevent garbage collection, run:
 
# Create a new ext4 partition and mount it over <code>/mnt</code>
# <code>rsync -a</code> everything from <code>/nix</code> to <code>/mnt</code>
# bind <code>/mnt</code> to <code>/nix</code> (e.g. using <code>mount</code>) and rerun <code>nixos-rebuild switch</code> with something like <syntaxhighlight lang="bash">fileSystems."/nix" = { device = "/dev/disk/by-label/nix"; options = [ "noatime" ]; };</syntaxhighlight>
# reboot to be sure <code>/nix/store</code> is properly mounted
# bind mount <code>/</code> to <code>/old_root</code>, and remove <code>/old_root/nix</code>
 
Keep in mind that all commands like <code>mount</code> and <code>bash</code> point to some executable in <code>/nix/store</code>, so never mount an empty disk over <code>/nix</code> or <code>/nix/store</code>, otherwise you will be locked out until reboot!
 
== Enable periodic Garbage Collection ==
 
Next you may enable periodic auto GC, for example like this:
 
<syntaxhighlight lang="bash">
nix.gc.automatic = true;
nix.gc.dates = "weekly";
nix.gc.options = "--delete-older-than 30d";</syntaxhighlight>
This can result into some redownloads (if you ever use <code>import (builtins.fetchFromTarball ...)</code> all these fetched tarballs are not referenced anywhere and removed on GC), but overall it frees you from runnning GC manually often.
 
== You will never be free of manual GC! ==
 
One of least mentioned problems with <code>nix-collect-garbage -d</code> is it doesn't collect all the garbage! The key to understand how's that, is to run this command:


<syntaxhighlight lang="bash">$ nix-store --gc --print-roots
<syntaxhighlight lang="bash">$ nix-store --gc --print-roots
Line 92: Line 70:
Obviously, you should remove the GC roots directory for projects you don't plan to work on.
Obviously, you should remove the GC roots directory for projects you don't plan to work on.


== Last resort - <code>--optimise</code> ==
=== Automatic garbage collection ===
 
Next you may enable periodic auto GC, for example like this:
 
<syntaxhighlight lang="bash">
nix.gc.automatic = true;
nix.gc.dates = "weekly";
nix.gc.options = "--delete-older-than 30d";</syntaxhighlight>
This can result into some redownloads (if you ever use <code>import (builtins.fetchFromTarball ...)</code> all these fetched tarballs are not referenced anywhere and removed on GC), but overall it frees you from runnning GC manually often.
 
== Moving the store ==
 
{{ic|/nix}} can reside on another device. This is useful if your root device is very small, and that you have another, larger drive at hand. It is easiest to set up when installing NixOS. To move <code>/nix</code> to another device on an existing NixOS installation:
 
# Create a new ext4 partition and mount it over <code>/mnt</code>
# <code>rsync -a</code> everything from <code>/nix</code> to <code>/mnt</code>
# bind <code>/mnt</code> to <code>/nix</code> (e.g. using <code>mount</code>) and rerun <code>nixos-rebuild switch</code> with something like <syntaxhighlight lang="bash">fileSystems."/nix" = { device = "/dev/disk/by-label/nix"; options = [ "noatime" ]; };</syntaxhighlight>
# reboot to be sure <code>/nix/store</code> is properly mounted
# bind mount <code>/</code> to <code>/old_root</code>, and remove <code>/old_root/nix</code>
 
Keep in mind that all commands like <code>mount</code> and <code>bash</code> point to some executable in <code>/nix/store</code>, so never mount an empty disk over <code>/nix</code> or <code>/nix/store</code>, otherwise you will be locked out until reboot!
 
== Optimizing the store ==


Run <code>nix-store --optimise</code> in case you really need some a bit of space. It is a lengthy operation, and after multiple-outputs PR landing, it became less useful.
Run <code>nix-store --optimise</code> in case you really need some a bit of space. It is a lengthy operation, and after multiple-outputs PR landing, it became less useful.


<syntaxhighlight lang="bash"># nix-store --optimise
<pre>
985.41 MiB freed by hard-linking 251942 files</syntaxhighlight>
# nix-store --optimise
985.41 MiB freed by hard-linking 251942 files
</pre>
 
== See also ==
 
<references group="cf."/>