Title : Making a home NAS using NixOS
Author: Solène
Date  : 18 October 2020
Tags  : nixos linux nas

Still playing with [NixOS](https://nixos.org/), I wanted to experience
how difficult it would be to write a NixOS configuration file to
turn a computer into a simple NAS with basics features: samba
storage, dlna server and auto suspend/resume.

What is [NixOS](https://nixos.org/features.html)? As a reminder for
some and introduction to the others, NixOS is a Linux distribution
built by the Nix package manager, which make it very different than
any other operating system out there, except [Guix](https://guix.gnu.org/)
which has a similar approach with their own package manager written
in Scheme.

NixOS uses a declarative configuration approach along with lot of
others features derived from Nix. What's big here is you no longer
tweak anything in `/etc` or install packages, you can define the
working state of the system in one configuration file. This system
is a totally different beast than the others OS and require some
time to understand how it work. Good news though, **everything**
is documented in the man page `configuration.nix`, from fstab
configuration to users managements or how to enable samba!

Here is the `/etc/nixos/configuration.nix` file on my NAS.

It enables ssh server, samba, minidlna and vnstat. Set up an user
with my ssh public key. Ready to work.

Using `rtcwake` command (Linux specific), it's possible to put
the system into standby mode and schedule an auto resume after
some time. This is triggered by a cron job at 01h00.

    { config, pkgs, ... }:
    {
      # include stuff related to hardware, auto generated at install
      imports = ./hardware-configuration.nix ];
      boot.loader.grub.device = "/dev/sda";
      
      # network configuration
      networking.interfaces.enp3s0.ipv4.addresses = [ {
        address = "192.168.42.150";
        prefixLength = 24;
      } ];
      networking.defaultGateway = "192.168.42.1";
      networking.nameservers = [ "192.168.42.231" ];
      
      # FR locales and layout
      i18n.defaultLocale = "fr_FR.UTF-8";
      console = { font = "Lat2-Terminus16"; keyMap = "fr"; };
      time.timeZone = "Europe/Paris";
      
      # Packages management
      environment.systemPackages = with pkgs; [
        kakoune vnstat borgbackup utillinux
      ];
      
      # network disabled (I need to check the ports used first)
      networking.firewall.enable = false;
      
      # services to enable
      services.openssh.enable = true;
      services.vnstat.enable = true;
      
      # auto standby
      services.cron.systemCronJobs = [
          "0 1 * * * root rtcwake -m mem --date +6h"
      ]; 
      
      # samba service
      services.samba.enable = true;
      services.samba.enableNmbd = true;
      services.samba.extraConfig = ''
            workgroup = WORKGROUP
            server string = Samba Server
            server role = standalone server
            log file = /var/log/samba/smbd.%m
            max log size = 50
            dns proxy = no
            map to guest = Bad User
        '';
      services.samba.shares = {
          public = {
              path = "/home/public";
              browseable = "yes";
              "writable" = "yes";
              "guest ok" = "yes";
              "public" = "yes";
              "force user" = "share";
            };
         };
      
      # minidlna service
      services.minidlna.enable = true;
      services.minidlna.announceInterval = 60;
      services.minidlna.friendlyName = "Rorqual";
      services.minidlna.mediaDirs = ["A,/home/public/Musique/" "V,/home/public/Videos/"];
      
      # trick to create a directory with proper ownership
      # note that tmpfiles are not necesserarly temporary if you don't
      # set an expire time. Trick given on irc by someone I forgot the name..
      systemd.tmpfiles.rules = [ "d /home/public 0755 share users" ];
      
      # create my user, with sudo right and my public ssh key
      users.users.solene = {
        isNormalUser = true;
        extraGroups = [ "wheel" "sudo" ];
        openssh.authorizedKeys.keys = [
              "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOIZKLFQXVM15viQXHYRjGqE4LLfvETMkjjgSz0mzMzS personal"
              "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOIZKLFQXVM15vAQXBYRjGqE6L1fvETMkjjgSz0mxMzS pro"
        ];
      };
      
      # create a dedicated user for the shares
      # I prefer a dedicated one than "nobody"
      # can't log into it
      users.users.share= {
        isNormalUser = false;
      };
    }