Storage optimization: Difference between revisions

From NixOS Wiki
imported>Makefu
initial batch of nixos-users
 
imported>Fadenb
m Syntax highlighting
Line 7: Line 7:
If your root device is fixed and small-sized, you should move <code>/nix</code> to separate device. I have it running on LVM. Best to design that out of starts, otherwise you have to: - first you should know, that commands <code>mount</code> and <code>bash</code> belong to <code>/nix/store</code> so never mount empty disk over <code>/nix</code> or <code>/nix/store</code>, you will be locked out until reboot - create new ext4 FS and mount it over <code>/mnt</code> - <code>rsync -a</code> everything from <code>/nix</code> to <code>/mnt</code> - bind mount <code>/mnt</code> over <code>/nix</code> and rerun <code>nixos-rebuild switch</code> with something like
If your root device is fixed and small-sized, you should move <code>/nix</code> to separate device. I have it running on LVM. Best to design that out of starts, otherwise you have to: - first you should know, that commands <code>mount</code> and <code>bash</code> belong to <code>/nix/store</code> so never mount empty disk over <code>/nix</code> or <code>/nix/store</code>, you will be locked out until reboot - create new ext4 FS and mount it over <code>/mnt</code> - <code>rsync -a</code> everything from <code>/nix</code> to <code>/mnt</code> - bind mount <code>/mnt</code> over <code>/nix</code> and rerun <code>nixos-rebuild switch</code> with something like


<pre>fileSystems.&quot;/nix&quot; = { device = &quot;/dev/disk/by-label/nix&quot;; options = [ &quot;noatime&quot; ]; };</pre>
<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
* 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>
* bind mount <code>/</code> to <code>/old_root</code>, and remove <code>/old_root/nix</code>
Line 17: Line 17:
Next you may enable periodic auto GC, like this:
Next you may enable periodic auto GC, like this:


<pre> nix.gc.automatic = true;
<syntaxhighlight lang="bash">
  nix.gc.dates = &quot;weekly&quot;;
nix.gc.automatic = true;
  nix.gc.options = &quot;--delete-older-than 30d&quot;;</pre>
nix.gc.dates = "weekly";
nix.gc.options = "--delete-older-than 30d";</syntaxhighlight>
In my case this results 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.
In my case this results 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.


Line 26: Line 27:
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 command:
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 command:


<pre>$ nix-store --gc --print-roots
<syntaxhighlight lang="bash">$ nix-store --gc --print-roots
/home/danbst/dev/test-shell/.shell.drv -&gt; /nix/store/4diqwczyjipdqyi7aj34wfagblbhfjr9-nixops-1.4
/home/danbst/dev/test-shell/.shell.drv -> /nix/store/4diqwczyjipdqyi7aj34wfagblbhfjr9-nixops-1.4
/home/danbst/dev/test-shell/.shell.drv-2 -&gt; /nix/store/62h3c4d6rdnlxichixqg8h9jxi8nhxk0-stdenv
/home/danbst/dev/test-shell/.shell.drv-2 -> /nix/store/62h3c4d6rdnlxichixqg8h9jxi8nhxk0-stdenv
/home/danbst/dev/test-shell/.shell.drv-2-doc -&gt; /nix/store/14gnv1q1w0n9qwa3q23idsqvn51354y8-bash-4.3-p42-doc
/home/danbst/dev/test-shell/.shell.drv-2-doc -> /nix/store/14gnv1q1w0n9qwa3q23idsqvn51354y8-bash-4.3-p42-doc
/home/danbst/stack/new/website/server/result -&gt; /nix/store/1jhmp6vl364p32r8bjigk65qh1xa562f-server-0.1.0.0
/home/danbst/stack/new/website/server/result -> /nix/store/1jhmp6vl364p32r8bjigk65qh1xa562f-server-0.1.0.0
/home/danbst/testing/.nix-gc-roots/shell.drv -&gt; /nix/store/v3vqf48awjjzjivrx15kfqdh1d7cg4mq-sshpass-1.05
/home/danbst/testing/.nix-gc-roots/shell.drv -> /nix/store/v3vqf48awjjzjivrx15kfqdh1d7cg4mq-sshpass-1.05
...
...
/home/danbst/testing/.nix-gc-roots/shell.drv-12 -&gt; /nix/store/a2li4sl9pxh9aflqia2gp7w88ayvjwci-bash-4.3-p42
/home/danbst/testing/.nix-gc-roots/shell.drv-12 -> /nix/store/a2li4sl9pxh9aflqia2gp7w88ayvjwci-bash-4.3-p42
/home/danbst/testing/.nix-gc-roots/shell.drv-12-doc -&gt; /nix/store/kcswyb1d8zimkym0pjfi2fj1dly1w34w-bash-4.3-p42-doc
/home/danbst/testing/.nix-gc-roots/shell.drv-12-doc -> /nix/store/kcswyb1d8zimkym0pjfi2fj1dly1w34w-bash-4.3-p42-doc
/home/danbst/testing/.nix-gc-roots/shell.drv-12-info -&gt; /nix/store/njb817fwiafswzwvj9skw7w7k6b3fnbi-bash-4.3-p42-info
/home/danbst/testing/.nix-gc-roots/shell.drv-12-info -> /nix/store/njb817fwiafswzwvj9skw7w7k6b3fnbi-bash-4.3-p42-info
/home/ec2-user/result -&gt; /nix/store/q35aq2sh5dbyka6g6f6qb7b8msxwds5m-nixos-system-iron-16.03.1299.a8e0739
/home/ec2-user/result -> /nix/store/q35aq2sh5dbyka6g6f6qb7b8msxwds5m-nixos-system-iron-16.03.1299.a8e0739
/nix/var/nix/profiles/per-container/analyt/system-3-link -&gt; /nix/store/snrj72189wh9va23fawl3v80v92xnxlm-nixos-system-iron-16.03.1291.efe2d64
/nix/var/nix/profiles/per-container/analyt/system-3-link -> /nix/store/snrj72189wh9va23fawl3v80v92xnxlm-nixos-system-iron-16.03.1291.efe2d64
/nix/var/nix/profiles/per-container/d-live/system-6-link -&gt; /nix/store/cp2c58hnczsjk5h69ksajq5xfhsyhl6v-nixos-system-iron-16.03.1299.a8e0739
/nix/var/nix/profiles/per-container/d-live/system-6-link -> /nix/store/cp2c58hnczsjk5h69ksajq5xfhsyhl6v-nixos-system-iron-16.03.1299.a8e0739
/nix/var/nix/profiles/per-container/d-test/system-4-link -&gt; /nix/store/n1w7ywjg65x8iimchznxcyygbgmyfh55-nixos-system-iron-16.03.1287.6ac7ffd
/nix/var/nix/profiles/per-container/d-test/system-4-link -> /nix/store/n1w7ywjg65x8iimchznxcyygbgmyfh55-nixos-system-iron-16.03.1287.6ac7ffd
/nix/var/nix/profiles/per-container/dashboard/system-41-link -&gt; /nix/store/7qk19pkwgq0h3a1q9dcql3nks40rr75s-nixos-system-iron-16.03.1340.5a090dd
/nix/var/nix/profiles/per-container/dashboard/system-41-link -> /nix/store/7qk19pkwgq0h3a1q9dcql3nks40rr75s-nixos-system-iron-16.03.1340.5a090dd
...
...
/nix/var/nix/profiles/per-container/ttt/system-1-link -&gt; /nix/store/1kj9qs5gl3421jlkl3jfc2kqdsl8akwr-nixos-system-ttt-16.03.977.1da05df
/nix/var/nix/profiles/per-container/ttt/system-1-link -> /nix/store/1kj9qs5gl3421jlkl3jfc2kqdsl8akwr-nixos-system-ttt-16.03.977.1da05df
/nix/var/nix/profiles/per-user/danbst/channels-1-link -&gt; /nix/store/s0qay9qyqrn92zayldbvvj3zrfcl7a72-user-environment
/nix/var/nix/profiles/per-user/danbst/channels-1-link -> /nix/store/s0qay9qyqrn92zayldbvvj3zrfcl7a72-user-environment
/nix/var/nix/profiles/per-user/danbst/profile-28-link -&gt; /nix/store/69ds606146dqml04sm0fbpqwnv2w8i3q-user-environment
/nix/var/nix/profiles/per-user/danbst/profile-28-link -> /nix/store/69ds606146dqml04sm0fbpqwnv2w8i3q-user-environment
/nix/var/nix/profiles/per-user/ec2-user/profile-7-link -&gt; /nix/store/y2hc7zsnkzys9ba6xaijvjhff03rcgpy-user-environment
/nix/var/nix/profiles/per-user/ec2-user/profile-7-link -> /nix/store/y2hc7zsnkzys9ba6xaijvjhff03rcgpy-user-environment
/nix/var/nix/profiles/per-user/root/channels-4-link -&gt; /nix/store/254b6pkhhnjywvj5c0lp2vdai8nz4p0g-user-environment
/nix/var/nix/profiles/per-user/root/channels-4-link -> /nix/store/254b6pkhhnjywvj5c0lp2vdai8nz4p0g-user-environment
/nix/var/nix/profiles/system-398-link -&gt; /nix/store/wmndyzzrbc9fyjw844jmvzwgwgcinq7s-nixos-system-iron-16.0916.09pre.custom
/nix/var/nix/profiles/system-398-link -> /nix/store/wmndyzzrbc9fyjw844jmvzwgwgcinq7s-nixos-system-iron-16.0916.09pre.custom
/root/forkstat/result -&gt; /nix/store/i5glmg3wk2a48x52rhd92zip1cmc0kq9-forkstat-git
/root/forkstat/result -> /nix/store/i5glmg3wk2a48x52rhd92zip1cmc0kq9-forkstat-git
/run/booted-system -&gt; /nix/store/8jkrl9jyq7hqxb6xpwcaghpdm26gq98j-nixos-system-iron-16.0916.09pre.custom
/run/booted-system -> /nix/store/8jkrl9jyq7hqxb6xpwcaghpdm26gq98j-nixos-system-iron-16.0916.09pre.custom
/run/current-system -&gt; /nix/store/wmndyzzrbc9fyjw844jmvzwgwgcinq7s-nixos-system-iron-16.0916.09pre.custom</pre>
/run/current-system -> /nix/store/wmndyzzrbc9fyjw844jmvzwgwgcinq7s-nixos-system-iron-16.0916.09pre.custom</syntaxhighlight>
=== Don't forget to run <code>nix-collect-garbage -d</code> with <code>sudo</code> ===
=== Don't forget to run <code>nix-collect-garbage -d</code> with <code>sudo</code> ===


Line 59: Line 60:
If you use <code>nix-build</code>, but don't use <code>--no-build-output</code>, your FS will be filled with <code>result</code> symlinks to various derivations. In example above there are
If you use <code>nix-build</code>, but don't use <code>--no-build-output</code>, your FS will be filled with <code>result</code> symlinks to various derivations. In example above there are


<pre>/home/danbst/stack/new/website/server/result -&gt; /nix/store/1jhmp6vl364p32r8bjigk65qh1xa562f-server-0.1.0.0
<syntaxhighlight lang="bash">/home/danbst/stack/new/website/server/result -> /nix/store/1jhmp6vl364p32r8bjigk65qh1xa562f-server-0.1.0.0
/home/ec2-user/result -&gt; /nix/store/q35aq2sh5dbyka6g6f6qb7b8msxwds5m-nixos-system-iron-16.03.1299.a8e0739
/home/ec2-user/result -> /nix/store/q35aq2sh5dbyka6g6f6qb7b8msxwds5m-nixos-system-iron-16.03.1299.a8e0739
/root/forkstat/result -&gt; /nix/store/i5glmg3wk2a48x52rhd92zip1cmc0kq9-forkstat-git</pre>
/root/forkstat/result -> /nix/store/i5glmg3wk2a48x52rhd92zip1cmc0kq9-forkstat-git</syntaxhighlight>
How much do these (apparently) abandoned derivations take space?
How much do these (apparently) abandoned derivations take space?


<pre>$ du -sch $(nix-store -qR /root/forkstat/result /home/ec2-user/result /home/danbst/stack/new/website/server/result)
<syntaxhighlight lang="bash">$ du -sch $(nix-store -qR /root/forkstat/result /home/ec2-user/result /home/danbst/stack/new/website/server/result)
...
...
3.4G    total</pre>
3.4G    total</syntaxhighlight>
Wow, garbage? Not so much, but:
Wow, garbage? Not so much, but:


<pre># rm /root/forkstat/result /home/ec2-user/result /home/danbst/stack/new/website/server/result
<syntaxhighlight lang="bash"># rm /root/forkstat/result /home/ec2-user/result /home/danbst/stack/new/website/server/result
# nix-collect-garbage -d
# nix-collect-garbage -d
...
...
690 store paths deleted, 1817.99 MiB freed</pre>
690 store paths deleted, 1817.99 MiB freed</syntaxhighlight>
Especially look for system derivations. Those are created in many cases, for example, when running <code>nixos-rebuild  build-vm</code>
Especially look for system derivations. Those are created in many cases, for example, when running <code>nixos-rebuild  build-vm</code>


Line 83: Line 84:
When you invoke <code>nix-shell</code> with
When you invoke <code>nix-shell</code> with


<pre> nix-shell --indirect --add-root $DIR/.nix-gc-roots/shell.drv ...</pre>
<syntaxhighlight lang="bash">nix-shell --indirect --add-root $DIR/.nix-gc-roots/shell.drv ...</syntaxhighlight>
then you'll have a persistent environment which won't be garbage collected. It is useful when you don't want to spend time waiting for redownloads every time you enter the shell.
then you'll have a persistent environment which won't be garbage collected. It is useful when you don't want to spend time waiting for redownloads every time you enter the shell.


Line 94: Line 95:
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.


<pre># nix-store --optimise
<syntaxhighlight lang="bash"># nix-store --optimise
985.41 MiB freed by hard-linking 251942 files</pre>
985.41 MiB freed by hard-linking 251942 files</syntaxhighlight>

Revision as of 20:04, 26 August 2017

A problem with NixOS, I've run into multiple time, is lack of space on / device. Even if you are using Nix only occasionally, it is easy for /nix/store to go beyond 50G.

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

Split /nix to separate LVM volume

If your root device is fixed and small-sized, you should move /nix to separate device. I have it running on LVM. Best to design that out of starts, otherwise you have to: - first you should know, that commands mount and bash belong to /nix/store so never mount empty disk over /nix or /nix/store, you will be locked out until reboot - create new ext4 FS and mount it over /mnt - rsync -a everything from /nix to /mnt - bind mount /mnt over /nix and rerun nixos-rebuild switch with something like

fileSystems."/nix" = { device = "/dev/disk/by-label/nix"; options = [ "noatime" ]; };
  • reboot to be sure /nix/store is properly mounted
  • bind mount / to /old_root, and remove /old_root/nix

That's it! You moved /nix/store!

Enable periodic GC

Next you may enable periodic auto GC, like this:

nix.gc.automatic = true;
nix.gc.dates = "weekly";
nix.gc.options = "--delete-older-than 30d";

In my case this results into some redownloads (if you ever use import (builtins.fetchFromTarball ...) 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 nix-collect-garbage -d is it doesn't collect all the garbage! The key to understand how's that, is to run command:

$ nix-store --gc --print-roots
/home/danbst/dev/test-shell/.shell.drv -> /nix/store/4diqwczyjipdqyi7aj34wfagblbhfjr9-nixops-1.4
/home/danbst/dev/test-shell/.shell.drv-2 -> /nix/store/62h3c4d6rdnlxichixqg8h9jxi8nhxk0-stdenv
/home/danbst/dev/test-shell/.shell.drv-2-doc -> /nix/store/14gnv1q1w0n9qwa3q23idsqvn51354y8-bash-4.3-p42-doc
/home/danbst/stack/new/website/server/result -> /nix/store/1jhmp6vl364p32r8bjigk65qh1xa562f-server-0.1.0.0
/home/danbst/testing/.nix-gc-roots/shell.drv -> /nix/store/v3vqf48awjjzjivrx15kfqdh1d7cg4mq-sshpass-1.05
...
/home/danbst/testing/.nix-gc-roots/shell.drv-12 -> /nix/store/a2li4sl9pxh9aflqia2gp7w88ayvjwci-bash-4.3-p42
/home/danbst/testing/.nix-gc-roots/shell.drv-12-doc -> /nix/store/kcswyb1d8zimkym0pjfi2fj1dly1w34w-bash-4.3-p42-doc
/home/danbst/testing/.nix-gc-roots/shell.drv-12-info -> /nix/store/njb817fwiafswzwvj9skw7w7k6b3fnbi-bash-4.3-p42-info
/home/ec2-user/result -> /nix/store/q35aq2sh5dbyka6g6f6qb7b8msxwds5m-nixos-system-iron-16.03.1299.a8e0739
/nix/var/nix/profiles/per-container/analyt/system-3-link -> /nix/store/snrj72189wh9va23fawl3v80v92xnxlm-nixos-system-iron-16.03.1291.efe2d64
/nix/var/nix/profiles/per-container/d-live/system-6-link -> /nix/store/cp2c58hnczsjk5h69ksajq5xfhsyhl6v-nixos-system-iron-16.03.1299.a8e0739
/nix/var/nix/profiles/per-container/d-test/system-4-link -> /nix/store/n1w7ywjg65x8iimchznxcyygbgmyfh55-nixos-system-iron-16.03.1287.6ac7ffd
/nix/var/nix/profiles/per-container/dashboard/system-41-link -> /nix/store/7qk19pkwgq0h3a1q9dcql3nks40rr75s-nixos-system-iron-16.03.1340.5a090dd
...
/nix/var/nix/profiles/per-container/ttt/system-1-link -> /nix/store/1kj9qs5gl3421jlkl3jfc2kqdsl8akwr-nixos-system-ttt-16.03.977.1da05df
/nix/var/nix/profiles/per-user/danbst/channels-1-link -> /nix/store/s0qay9qyqrn92zayldbvvj3zrfcl7a72-user-environment
/nix/var/nix/profiles/per-user/danbst/profile-28-link -> /nix/store/69ds606146dqml04sm0fbpqwnv2w8i3q-user-environment
/nix/var/nix/profiles/per-user/ec2-user/profile-7-link -> /nix/store/y2hc7zsnkzys9ba6xaijvjhff03rcgpy-user-environment
/nix/var/nix/profiles/per-user/root/channels-4-link -> /nix/store/254b6pkhhnjywvj5c0lp2vdai8nz4p0g-user-environment
/nix/var/nix/profiles/system-398-link -> /nix/store/wmndyzzrbc9fyjw844jmvzwgwgcinq7s-nixos-system-iron-16.0916.09pre.custom
/root/forkstat/result -> /nix/store/i5glmg3wk2a48x52rhd92zip1cmc0kq9-forkstat-git
/run/booted-system -> /nix/store/8jkrl9jyq7hqxb6xpwcaghpdm26gq98j-nixos-system-iron-16.0916.09pre.custom
/run/current-system -> /nix/store/wmndyzzrbc9fyjw844jmvzwgwgcinq7s-nixos-system-iron-16.0916.09pre.custom

Don't forget to run nix-collect-garbage -d with sudo

Otherwise you are clearing only current user profile, not system-wide.

Look for result symlinks

If you use nix-build, but don't use --no-build-output, your FS will be filled with result symlinks to various derivations. In example above there are

/home/danbst/stack/new/website/server/result -> /nix/store/1jhmp6vl364p32r8bjigk65qh1xa562f-server-0.1.0.0
/home/ec2-user/result -> /nix/store/q35aq2sh5dbyka6g6f6qb7b8msxwds5m-nixos-system-iron-16.03.1299.a8e0739
/root/forkstat/result -> /nix/store/i5glmg3wk2a48x52rhd92zip1cmc0kq9-forkstat-git

How much do these (apparently) abandoned derivations take space?

$ du -sch $(nix-store -qR /root/forkstat/result /home/ec2-user/result /home/danbst/stack/new/website/server/result)
...
3.4G    total

Wow, garbage? Not so much, but:

# rm /root/forkstat/result /home/ec2-user/result /home/danbst/stack/new/website/server/result
# nix-collect-garbage -d
...
690 store paths deleted, 1817.99 MiB freed

Especially look for system derivations. Those are created in many cases, for example, when running nixos-rebuild build-vm

Don't forget to reboot

As you see, the reference in /run/booted-system is a GC root, so it won't be cleared until reboot. If you don't want to reboot, just rm /run/booted-system that link and rerun sudo nix-collect-garbage.

Proper nix-shell GC pinning

When you invoke nix-shell with

nix-shell --indirect --add-root $DIR/.nix-gc-roots/shell.drv ...

then you'll have a persistent environment which won't be garbage collected. It is useful when you don't want to spend time waiting for redownloads every time you enter the shell.

A little problem exists though. GC roots are numbered sequentially, so if you change shell.nix to contain less derivations, and name of last GC root will start with shell.drv-7, then shell.drv-{8,9,10,11,12}* will be dangling and unused. To overcome this problem you should remove GC roots dir periodically (or just before nix-shell)

Obviously, you should remove the GC roots directory for projects you don't plan to work on.

Last resort - --optimise

Run nix-store --optimise 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.

# nix-store --optimise
985.41 MiB freed by hard-linking 251942 files