Has anyone ever used NixOS as daily-drive distro?
I'm impressed by reproducibility of NixOS, configuration mechanism and Nix package manager, but how it would be in daily-drive use? Is it worth it?
I'm impressed by reproducibility of NixOS, configuration mechanism and Nix package manager, but how it would be in daily-drive use? Is it worth it?
I want to finally try NixOS and build a desktop OS from the ground up with sway, iwd, waybar, foot terminal, cmus, etc.
I'm not a developer, but I'm a seasoned Linux user. Used Gentoo for years, Void Linux and now I'm on OpenSUSE TW.
I'm finding all sorts of guides and it seems confusing. In the past there wasn't any mention of home-manager and flakes, now it seems there are these things. Those are all things I need to care about? Is it all configured in one file?
Since I took so long to reply to Tips to use NixOS on a server? by @simao, I decided to create a new topic to share my configs. Hopefully this is informative for anyone looking to do similar things - I'll also gladly take critiques, since my setup is probably not perfect.
First, I will share the output of 'lsblk' on my VPS:
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
vda 253:0 0 180G 0 disk
├─vda1 253:1 0 512M 0 part /boot
└─vda2 253:2 0 179.5G 0 part
└─crypt 254:0 0 179.5G 0 crypt
That is, I use an unencrypted /boot
partition, vda1
, with GRUB 2 to prompt for a passphrase during boot, to unlock the LUKS encrypted vda2
. I prefer to use ZFS as my file system for the encrypted drive, and LUKS rather than ZFS encryption. This is an MBR drive, since that's what my VPS provider uses, though UEFI would look the same. The particular way I do this also requires access through the provider's tools, and not ssh or similar. The hardware-configuration.nix
file reflects this:
# Do not modify this file! It was generated by ‘nixos-generate-config’
# and may be overwritten by future invocations. Please make changes
# to /etc/nixos/configuration.nix instead.
{ config, lib, pkgs, modulesPath, ... }:
{
imports =
[ (modulesPath + "/profiles/qemu-guest.nix")
];
boot.initrd.availableKernelModules = [ "aes_x86_64" "ata_piix" "cryptd" "uhci_hcd" "virtio_pci" "sr_mod" "virtio_blk" ];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ ];
boot.extraModulePackages = [ ];
fileSystems."/" =
{ device = "rpool/root/nixos";
fsType = "zfs";
};
fileSystems."/home" =
{ device = "rpool/home";
fsType = "zfs";
};
fileSystems."/boot" =
{ device = "/dev/disk/by-uuid/294de4f1-72e2-4377-b565-b3d4eaaa37b6";
fsType = "ext4";
};
swapDevices = [ ];
}
# Edit this configuration file to define what should be installed on
# your system. Help is available in the configuration.nix(5) man page
# and in the NixOS manual (accessible by running ‘nixos-help’).
{ config, lib, pkgs, ... }:
{
imports =
[ # Include the results of the hardware scan.
./hardware-configuration.nix
];
# Hardware stuff
# add the following to hardware-configuration.nix - speeds up encryption
#boot.initrd.availableKernelModules ++ [ "aes_x86_64" "cryptd" ];
boot.initrd.luks.devices.crypt = {
# Change this if moving to another machine!
device = "/dev/disk/by-uuid/86090289-1c1f-4935-abce-a1aeee1b6125";
};
boot.kernelParams = [ "zfs.zfs_arc_max=536870912" ]; # sets zfs arc cache max target in bytes
boot.supportedFilesystems = [ "zfs" ];
nix.maxJobs = lib.mkDefault 6; # number of cpu cores
# Use the GRUB 2 boot loader.
boot.loader.grub.enable = true;
boot.loader.grub.version = 2;
# boot.loader.grub.efiSupport = true;
# boot.loader.grub.efiInstallAsRemovable = true;
# boot.loader.efi.efiSysMountPoint = "/boot/efi";
# Define on which hard drive you want to install Grub.
boot.loader.grub.device = "/dev/vda"; # or "nodev" for efi only
boot.loader.grub.enableCryptodisk = true;
boot.loader.grub.zfsSupport = true;
networking.hostName = "m"; # Define your hostname.
# networking.wireless.enable = true; # Enables wireless support via wpa_supplicant.
# The global useDHCP flag is deprecated, therefore explicitly set to false here.
# Per-interface useDHCP will be mandatory in the future, so this generated config
# replicates the default behaviour.
networking.useDHCP = false;
networking.interfaces.ens3.useDHCP = true;
networking.hostId = "aoeu"; # set this to the first eight characters of /etc/machine-id for zfs
networking.nat = {
enable = true;
externalInterface = "ens3"; # this may not be the interface name
internalInterfaces = [ "wg0" ];
};
networking.firewall = {
enable = true;
allowedTCPPorts = [ 53 25565 ]; # open 53 for DNS and 25565 for Minecraft
allowedUDPPorts = [ 53 51820 ]; # open 53 for DNS and 51820 for Wireguard - change the Wireguard port
};
networking.wg-quick.interfaces = {
wg0 = {
address = [ "10.0.0.1/24" "fdc9:281f:04d7:9ee9::1/64" ];
listenPort = 51820;
privateKeyFile = "/root/wireguard-keys/privatekey"; # fill this file with the server's private key and make it so only root has read/write access
postUp = ''
${pkgs.iptables}/bin/iptables -A FORWARD -i wg0 -j ACCEPT
${pkgs.iptables}/bin/iptables -t nat -A POSTROUTING -s 10.0.0.1/24 -o ens3 -j MASQUERADE
${pkgs.iptables}/bin/ip6tables -A FORWARD -i wg0 -j ACCEPT
${pkgs.iptables}/bin/ip6tables -t nat -A POSTROUTING -s fdc9:281f:04d7:9ee9::1/64 -o ens3 -j MASQUERADE
'';
preDown = ''
${pkgs.iptables}/bin/iptables -D FORWARD -i wg0 -j ACCEPT
${pkgs.iptables}/bin/iptables -t nat -D POSTROUTING -s 10.0.0.1/24 -o ens3 -j MASQUERADE
${pkgs.iptables}/bin/ip6tables -D FORWARD -i wg0 -j ACCEPT
${pkgs.iptables}/bin/ip6tables -t nat -D POSTROUTING -s fdc9:281f:04d7:9ee9::1/64 -o ens3 -j MASQUERADE
'';
peers = [
{ # peer0
publicKey = "{client public key}"; # replace this with the client's public key
presharedKeyFile = "/root/wireguard-keys/preshared_from_peer0_key"; # fill this file with the preshared key and make it so only root has read/write access
allowedIPs = [ "10.0.0.2/32" "fdc9:281f:04d7:9ee9::2/128" ];
}
];
};
};
# Configure network proxy if necessary
# networking.proxy.default = "http://user:password@proxy:port/";
# networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain";
nixpkgs.config = {
allowUnfree = true; # don't set this if you want to ensure only free software
};
# Select internationalisation properties.
i18n.defaultLocale = "en_US.UTF-8";
console = {
font = "Lat2-Terminus16";
keyMap = "us";
};
# Set your time zone.
time.timeZone = "America/New_York"; # set this to the same timezone your server is located in
# List packages installed in system profile. To search, run:
# $ nix search wget
environment = {
systemPackages = with pkgs; let
nvimcust = neovim.override { # lazy minimal neovim config
viAlias = true;
vimAlias = true;
withPython = true;
configure = {
packages.myPlugins = with pkgs.vimPlugins; {
start = [ deoplete-nvim ];
opt = [];
};
customRC = ''
if filereadable($HOME . "/.config/nvim/init.vim")
source ~/.config/nvim/init.vim
endif
set number
set expandtab
filetype plugin on
syntax on
let g:deoplete#enable_at_startup = 1
'';
};
};
in
[
jdk8
nvimcust
p7zip
wget
wireguard
];
};
# Some programs need SUID wrappers, can be configured further or are
# started in user sessions.
# programs.mtr.enable = true;
# programs.gnupg.agent = {
# enable = true;
# enableSSHSupport = true;
# pinentryFlavor = "gnome3";
# };
# List services that you want to enable:
# Enable the OpenSSH daemon.
services = {
dnsmasq = {
enable = true;
# this allows DNS requests from wg0 to be forwarded to the DNS server on this machine
extraConfig = ''
interface=wg0
'';
};
fail2ban = {
enable = true;
};
openssh = {
enable = true;
permitRootLogin = "no";
};
zfs = {
autoScrub = {
enable = true;
interval = "monthly";
};
};
};
# Set sudo to request root password for all users
# this should be changed for a multi-user server
security.sudo.extraConfig = ''
Defaults rootpw
'';
# Define a user account. Don't forget to set a password with ‘passwd’.
users.users = {
vpsadmin = { # admin account that has a password
isNormalUser = true;
home = "/home/vpsadmin";
extraGroups = [ "wheel" ]; # Enable ‘sudo’ for the user.
shell = pkgs.zsh;
};
mcserver = { # passwordless user to run a service - in this instance minecraft
isNormalUser = true;
home = "/home/mcserver";
extraGroups = [];
shell = pkgs.zsh;
};
};
systemd = {
services = {
mcserverrun = { # this service runs a systemd sandboxed modded minecraft server as user mcserver
enable = true;
description = "Start and keep minecraft server running";
wants = [ "network.target" ];
after = [ "network.target" ];
serviceConfig = {
User = "mcserver";
NoNewPrivileges = true;
PrivateTmp = true;
ProtectSystem = "strict";
PrivateDevices = true;
ReadWritePaths = "/home/mcserver/Eternal_current";
WorkingDirectory = "/home/mcserver/Eternal_current";
ExecStart = "${pkgs.jdk8}/bin/java -Xms11520M -Xmx11520M -server -XX:+AggressiveOpts -XX:ParallelGCThreads=3 -XX:+UseConcMarkSweepGC -XX:+UnlockExperimentalVMOptions -XX:+UseParNewGC -XX:+ExplicitGCInvokesConcurrent -XX:MaxGCPauseMillis=10 -XX:GCPauseIntervalMillis=50 -XX:+UseFastAccessorMethods -XX:+OptimizeStringConcat -XX:NewSize=84m -XX:+UseAdaptiveGCBoundary -XX:NewRatio=3 -jar forge-1.12.2-14.23.5.2847-universal.jar nogui";
Restart = "always";
RestartSec = 12;
};
wantedBy = [ "multi-user.target" ];
};
mcserverscheduledrestart = { # this service restarts the minecraft server on a schedule
enable = true;
description = "restart mcserverrun service";
serviceConfig = {
Type = "oneshot";
ExecStart = "${pkgs.systemd}/bin/systemctl try-restart mcserverrun.service";
};
};
};
timers = {
mcserverscheduledrestart = { # this timer triggers the service of the same name
enable = true;
description = "restart mcserverrun service daily";
timerConfig = {
OnCalendar = "*-*-* 6:00:00";
};
wantedBy = [ "timers.target" ];
};
};
};
# This value determines the NixOS release from which the default
# settings for stateful data, like file locations and database versions
# on your system were taken. It‘s perfectly fine and recommended to leave
# this value at the release version of the first install of this system.
# Before changing this value read the documentation for this option
# (e.g. man configuration.nix or on https://nixos.org/nixos/options.html).
system.stateVersion = "20.09"; # Did you read the comment?
}
Edit: Also, the provider I use is ExtraVM, who has been excellent.
I see some people using NixOs on their servers. I would like to try it out to self host some services and learn about NixOs.
I use hetzner and they have an NixOs iso available so I can just use that to install NixOs. But how do people manage remote instances of NixOs? They would just use ansible or something like it, to run nix on the host, or is there a better way?
Thanks
I'm trying to package Elmer for use with NixOS, and could use some help from any experienced Nix users. My current attempt is located here. There is some junk left around in that file from my experimenting, but it's at least a start. There are also a few lines of error included in the comment here.
Any help is appreciated!
Has anyone here used NixOS for any significant amount of time as their daily driver? I've been considering using it since I learned about it, I really like the idea of how it manages packages, but I'm a bit hesitant, particularly about the availability of packages, and how the whole folder structure changes from the usual Linux. I'm also worried since I haven't seen any guide about how to use python other than the usual advice to get a virtualenv for everything.
I consider myself a fairly advanced Linux user, I have used Arch as my daily driver for 4 years, and Linux for like 10 years, as a side note, so I'm not really that afraid of troubleshooting.