💾 Archived View for perso.pw › blog › articles › nixos-nas.gmi captured on 2023-07-22 at 16:39:38. Gemini links have been rewritten to link to archived content

View Raw

More Information

⬅️ Previous capture (2023-05-24)

-=-=-=-=-=-=-

Making a home NAS using NixOS

Comment on Mastodon

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 a 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;

};

}