- Omri Bornstein/
- Posts/
- Nix Configurations/
- An Overly-configured NAS with NixOS, Syncthing, SMB & Tailscale/
An Overly-configured NAS with NixOS, Syncthing, SMB & Tailscale
Table of Contents
Since discovering Tailscale, I’ve consolidate my storage of important files in an over-engineered and overly-configured manner using Tailscale, NixOS (by the way), Syncthing, and SMB. Here is how I configured everything with Nix.
Tailscale #
This is the networking backbone of my homelab. I use it for enabling private communications between the storage server and clients from outside the server’s local network.
This is the Nix configuration I apply on each NixOS node in order to enable Tailscale and allow it internet access through the local firewall.
services.tailscale = {
enable = true;
useRoutingFeatures = "both";
};
# required per https://wiki.nixos.org/wiki/Tailscale#DNS
services.resolved = {
enable = true;
dnssec = "allow-downgrade";
dnsovertls = "opportunistic";
domains = [ "~." ];
fallbackDns = config.networking.nameservers;
};
networking = {
# ...
firewall = {
enable = true;
allowPing = true;
trustedInterfaces = [ "tailscale0" ];
allowedUDPPorts = [ config.services.tailscale.port ];
};
};
3rd-Party Clients #
- Fabian Koehler’s KTailctl is excellent Tailscale GUI for KDE Plasma.
Syncthing #
Syncthing is perfect for maintaining the same folder contents across multiple peer machines as soon as they change on one of the peers.
Syncthing doesn’t really have the notion of servers and clients, but I find it useful to configure the SMB server as a Syncthing peer with an accessible dashboard and ready to sync critical folders. The following Nix configuration is useful for such a “server” peer:
services.syncthing = {
enable = true;
user = "applegamer22";
dataDir = "/mnt/hdd2/";
configDir = "/home/applegamer22/.config/syncthing";
overrideDevices = false;
overrideFolders = false;
guiAddress = "0.0.0.0:8384";
settings.folders = {
"Music" = {
path = "/mnt/hdd2/Music";
ignorePerms = true;
};
};
};
systemd.services.syncthing.environment.STNODEFAULTFOLDER = "true";
Syncthing “client” peers running on NixOS can be set-up using this configuration:
services.syncthing = {
enable = true;
user = "applegamer22";
dataDir = "/home/applegamer22";
overrideDevices = false;
overrideFolders = false;
};
Once in a while I still need to approve peers after running system updates. I plan to look into fully declarative node IDs within my Nix Flake, which will require me to manage the cryptographic keys through Nix.
3rd-Party Clients #
Martchus
’s Syncthing Tray is excellent Syncthing GUI for KDE Plasma.Catfriend1
’s Syncthing Android client is an excellent fork of the discontinued official client.
SMB #
A remote SMB filesystem can be configured to only accept connections through Tailscale’s tailscale0
network interface.
services.samba-wsdd = {
enable = true;
openFirewall = true;
};
services.samba = {
enable = true;
openFirewall = true;
settings = {
global = {
"security" = "user";
"interfaces" = "lo tailscale0";
"bind interfaces only" = "yes";
"guest account" = "nobody";
"map to guest" = "bad user";
};
hdd = {
"path" = "/mnt";
"browseable" = "yes";
"read only" = "no";
"guest ok" = "no";
"create mask" = "0644";
"directory mask" = "0755";
"force user" = "applegamer22";
};
};
};
If there are no tailnet IP addresses defined in the global hosts allow
Samba setting, Tailscale won’t expose port 445 to devices with such addresses on your tailnet. The following command1 can be run to serve this port to the tailnet. Regardless of how this port is exposed to the tailnet, only devices that satisfy your tailnet’s access control settings will be able to access this port and Syncthing’s port 22000.
tailscale serve --bg --tcp 445 tcp://localhost:445
Services exposed to the tailnet can be disabled with a similar command.
tailscale serve --tcp 445 off
NixOS clients can mount a CIFS filesystem that points to the SMB server. The x-systemd.requires=tailscaled.service
2 makes sure the filesystem is unmounted before Tailscale’s daemon is stopped, which very useful for speeding up your client’s shutdowns.
environment.systemPackages = with pkgs; [ cifs-utils ];
fileSystems."/run/media/applegamer22/RPI4HDD" = {
# replace with your SMB server's tailnet IP address
device = "//100.121.142.2/hdd";
fsType = "cifs";
options = [
"x-systemd.automount"
"x-systemd.requires=tailscaled.service"
"x-systemd.idle-timeout=60"
"x-systemd.mount-timeout=0"
"username=applegamer22"
"uid=1000"
# u=rwx,g=rx
"file_mode=0750"
"dir_mode=0750"
"users"
"exec"
"rw"
"suid"
"dev"
"noatime"
];
};
3rd-Party Clients #
- The VLC Android app has an SMB capability that is enough for reading files.