Skip to content

Instantly share code, notes, and snippets.

@shanesveller
Last active January 29, 2019 16:02
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save shanesveller/071cd919ea3fd8a6cd150ef815a1a5ae to your computer and use it in GitHub Desktop.
Save shanesveller/071cd919ea3fd8a6cd150ef815a1a5ae to your computer and use it in GitHub Desktop.
NixOS talk outline
{ config, pkgs, ... }:
{
imports =
[ # Include the results of the hardware scan.
./hardware-configuration.nix
./vagrant.nix
];
# Use the GRUB 2 boot loader.
boot.loader.grub.enable = true;
boot.loader.grub.version = 2;
boot.loader.grub.device = "/dev/sda";
# remove the fsck that runs at startup. It will always fail to run, stopping
# your boot until you press *.
boot.initrd.checkJournalingFS = false;
# Services to enable:
# Enable the OpenSSH daemon.
services.openssh.enable = true;
# Enable DBus
services.dbus.enable = true;
# Replace nptd by timesyncd
services.timesyncd.enable = true;
# Enable guest additions.
virtualisation.virtualbox.guest.enable = true;
# Packages for Vagrant
environment.systemPackages = with pkgs; [
findutils
gnumake
iputils
jq
nettools
netcat
nfs-utils
rsync
# Extra packages
vim
];
# Creates a "vagrant" users with password-less sudo access
users = {
extraGroups = [ { name = "vagrant"; } { name = "vboxsf"; } ];
extraUsers = [
# Try to avoid ask password
{ name = "root"; password = "vagrant"; }
{
description = "Vagrant User";
name = "vagrant";
group = "vagrant";
extraGroups = [ "users" "vboxsf" "wheel" ];
password = "vagrant";
home = "/home/vagrant";
createHome = true;
useDefaultShell = true;
openssh.authorizedKeys.keys = [
"ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA6NF8iallvQVp22WDkTkyrtvp9eWW6A8YVr+kz4TjGYe7gHzIw+niNltGEFHzD8+v1I2YJ6oXevct1YeS0o9HZyN1Q9qgCgzUFtdOKLv6IedplqoPkcmF0aYet2PkEDo3MlTBckFXPITAMzF8dJSIFo9D8HfdOV0IAdx4O7PtixWKn5y2hMNG0zQPyUecp4pzC6kivAIhyfHilFR61RGL+GPXQ2MWZWFYbAGjyiYJnAmCP3NOTd0jMZEnDkbUvxhMmBYSdETk1rRgm+R4LOzFUGaHqHDLKLX+FIPKcF96hrucXzcWyLbIbEgE98OHlnVYCzRdK8jlqm8tehUc9c9WhQ== vagrant insecure public key"
];
}
];
};
security.sudo.configFile =
''
Defaults:root,%wheel env_keep+=LOCALE_ARCHIVE
Defaults:root,%wheel env_keep+=NIX_PATH
Defaults:root,%wheel env_keep+=TERMINFO_DIRS
Defaults env_keep+=SSH_AUTH_SOCK
Defaults lecture = never
root ALL=(ALL) SETENV: ALL
%wheel ALL=(ALL) NOPASSWD: ALL, SETENV: ALL
'';
}

Table of Contents

NixOS

The Purely Functional Linux Distribution

Why NixOS?

  • Everything we love about Linux in general
  • Declarative configuration of nearly everything
  • Installation and updates are atomic, easily rolled back
    • Boot an older generation if you've completely broken your environment
    • Nearly all commands support dry-run modes as well
  • Isolated, repeatable development environments

Why NixOS? (Cont)

  • Easy X11/GPU driver support
  • Easy UEFI support
  • Easy ZFS support
  • Philosophical and technical alignment for Haskell folks
  • nix-shell encourages experimentation without "polluting" the system environment
  • Basically never mutates something in-place

Why NOT NixOS?

  • Inevitable package compatibility problems
    • Not with each other, but if no one maintains a Nix package for what you need
    • Filesystem layout/mutability assumptions during operation
    • Can't just make install
  • Comparatively tiny community
  • Nix package manager got a major breaking release earlier this year
  • Offline installation is iffy
  • You hate symlinks

Why NOT NixOS? (Cont)

  • Might require learning a brand new programming language (c.f. Emacs / Emacs Lisp)
  • Updating a package before a maintainer tackles it is not as straightforward as i.e. Homebrew
  • Some subsets of the nixpkgs ecosystem have used a lot of indirection/abstraction (BEAM languages)
  • Increased network bandwidth and disk space consumed due to isolation/provenance
  • Some packages will be compiled from source

Declarative Configuration

  • Lives in 1-2 files in /etc/nixos (by default)
    • hardware-configuration.nix (filesystem mounts, swap, kernel modules, initrd payloads)
    • configuration.nix (basically everything else)
  • Test changes locally/immediately, or in a VM for more intrusive/lower-level changes
  • Can be versioned, shared, modularized, refactored

What can be configured?

System-level configuration:

  • Bootloader
  • Sound/video/input drivers
  • Users, groups, passwords, authorized SSH key, shell, sudo rules
  • Networking, firewall
  • System packages
  • Arbitrary /etc files
  • Arbitrary Systemd units
  • Virtualization and containerization

What can be configured? (Cont)

User environment:

  • Per-user packages
  • Common programs like shells, browsers, GPG, tmux
  • Many services plus their configuration (Apache, BIND, Nginx)
  • LXC/Docker Containers
    • From Docker Hub
    • Built locally from Nix derivations

What Could It Replace? (Hypothetically)

  • Configuration Management
  • Packer
  • Dockerfiles
  • FPM
  • Homebrew/Brewfile
  • RVM/rbenv/nodenv/pyenv/asdf

Nix

The Purely Functional Package Manager

Why Nix?

  • Uses binary caches (similar to Homebrew bottles or traditional Linux packages) when possible
  • Build packages from source when desired/required
    • Not compiled for your platform
    • Customized configuration/dependencies
  • Checksums used everywhere as part of the packaging syntax
  • Cross-platform* packaging
    • *if you run Linux/OSX

Why Nix? (Cont)

  • Understand the provenance of all of a package's dependencies
  • Customize package installation with overrides/overlays
  • Packages are naturally isolated from each other
    • Multiple concurrent versions installed, without conflict*
  • Point-in-time reproducible, if you provide a SHA/timestamp in your import

Stupid Nix Tricks

  • Reformat a machine, replace your old configuration.nix and be back in action in however long it takes you to download the packages (sans your stateful homedir data)
  • Use nix-copy-closure to copy the entire-system derivation to another NixOS machine, then update its configuration.nix to match and rebuild for a bit-for-bit identical environment (if you have identical CPU arch)

Stupid Nix Tricks (Cont)

  • Pin an exact release of a given Nix channel and then reproduce (not bit-for-bit) identical environments on OSX and Linux or across multiple developers' machines via nix-shell
  • Use an existing Nix/NixOS machine as a hyperlocal cache during installation using nix-serve
  • Use nix-shell --pure to be absolutely certain you've captured/documented all dependencies

Stupid Nix Tricks I Haven't Tried

  • Replace asdf with nix-shell
  • Use nix-shell in a script shebang
  • Manage your home directory/dotfiles with Nix
  • Manage an entire Emacs/Vim environment (including plugins/packages) via Nix

Miscellaneous Kudos

  • I found it notably easier/faster to install than ArchLinux
  • Installation docs available locally/automatically on TTY 8(?)
  • Pre-existing, accurate docs for installing on ZFS root
  • First distribution to support my 2017 GPU without tomfoolery

Further Reading

  • NixOps (Deploy NixOS instances to AWS, GCP, Azure, Libvirtd)
  • Hydra (Nix-based CI tool/build farm)
  • Disnix (Distributed systems using Nix)

NixOS

NixOS

The Purely Functional Linux Distribution

Why NixOS?

  • Everything we love about Linux in general
  • Declarative configuration of nearly everything
  • Installation and updates are atomic, easily rolled back
    • Boot an older **generation** if you’ve completely broken your environment
    • Nearly all commands support dry-run modes as well
  • Isolated, repeatable development environments

Why NixOS? (Cont)

  • Easy X11/GPU driver support
  • Easy UEFI support
  • Easy ZFS support
  • Philosophical and technical alignment for Haskell folks
  • nix-shell encourages experimentation without “polluting” the system environment
  • Basically **never** mutates something in-place

Why NOT NixOS?

  • Inevitable package compatibility problems
    • Not with each other, but if no one maintains a Nix package for what you need
    • Filesystem layout/mutability assumptions during operation
    • Can’t just make install
  • Comparatively tiny community
  • Nix package manager got a major breaking release earlier this year
  • Offline installation is iffy
  • You hate symlinks

Why NOT NixOS? (Cont)

  • Might require learning a brand new programming language (c.f. Emacs / Emacs Lisp)
  • Updating a package before a maintainer tackles it is not as straightforward as i.e. Homebrew
  • Some subsets of the nixpkgs ecosystem have used a lot of indirection/abstraction (BEAM languages)
  • Increased network bandwidth and disk space consumed due to isolation/provenance
  • Some packages will be compiled from source

Declarative Configuration

  • Lives in 1-2 files in /etc/nixos (by default)
    • hardware-configuration.nix (filesystem mounts, swap, kernel modules, initrd payloads)
    • configuration.nix (basically everything else)
  • Test changes locally/immediately, or in a VM for more intrusive/lower-level changes
  • Can be versioned, shared, modularized, refactored

What can be configured?

System-level configuration:

  • Bootloader
  • Sound/video/input drivers
  • Users, groups, passwords, authorized SSH key, shell, sudo rules
  • Networking, firewall
  • System packages
  • Arbitrary /etc files
  • Arbitrary Systemd units
  • Virtualization and containerization

What can be configured? (Cont)

User environment:

  • Per-user packages
  • Common programs like shells, browsers, GPG, tmux
  • Many services plus their configuration (Apache, BIND, Nginx)
  • LXC/Docker Containers
    • From Docker Hub
    • Built locally from Nix derivations

What Could It Replace? (Hypothetically)

  • Configuration Management
  • Packer
  • Dockerfiles
  • FPM
  • Homebrew/Brewfile
  • RVM/rbenv/nodenv/pyenv/asdf

Nix

The Purely Functional Package Manager

Why Nix?

  • Uses binary caches (similar to Homebrew bottles or traditional Linux packages) when possible
  • Build packages from source when desired/required
    • Not compiled for your platform
    • Customized configuration/dependencies
  • Checksums used everywhere as part of the packaging syntax
  • Cross-platform* packaging
    • *if you run Linux/OSX

Why Nix? (Cont)

  • Understand the provenance of all of a package’s dependencies
  • Customize package installation with overrides/overlays
  • Packages are naturally isolated from each other
    • Multiple concurrent versions installed, without conflict*
  • Point-in-time reproducible, if you provide a SHA/timestamp in your import

Stupid Nix Tricks

  • Reformat a machine, replace your old configuration.nix and be back in action in however long it takes you to download the packages (sans your stateful homedir data)
  • Use nix-copy-closure to copy the entire-system derivation to another NixOS machine, then update its configuration.nix to match and rebuild for a bit-for-bit identical environment (if you have identical CPU arch)

Stupid Nix Tricks (Cont)

  • Pin an exact release of a given Nix **channel** and then reproduce (not bit-for-bit) identical environments on OSX and Linux or across multiple developers’ machines via nix-shell
  • Use an existing Nix/NixOS machine as a hyperlocal cache during installation using nix-serve
  • Use nix-shell --pure to be absolutely certain you’ve captured/documented all dependencies

Stupid Nix Tricks I Haven’t Tried

  • Replace asdf with nix-shell
  • Use nix-shell in a script shebang
  • Manage your home directory/dotfiles with Nix
  • Manage an entire Emacs/Vim environment (including plugins/packages) via Nix

Miscellaneous Kudos

  • I found it notably easier/faster to install than ArchLinux
  • Installation docs available locally/automatically on TTY 8(?)
  • Pre-existing, accurate docs for installing on ZFS root
  • First distribution to support my 2017 GPU without tomfoolery

Further Reading

  • NixOps (Deploy NixOS instances to AWS, GCP, Azure, Libvirtd)
  • Hydra (Nix-based CI tool/build farm)
  • Disnix (Distributed systems using Nix)
{ pkgs ? import <nixpkgs> { } }: let
myPkgs = import (pkgs.fetchFromGitHub {
owner = "nixos";
repo = "nixpkgs";
rev = "dfee3e63d3b9bec2ea154ca880c82060c241e123";
sha256 = "01rv25rr0394xkf1bf1d3f3538cb6kdwwdnmssj0sf7vxjn13z4b";
}) {};
nodejs = myPkgs.nodejs-9_x;
yarn = myPkgs.lib.overrideDerivation myPkgs.yarn (attrs: rec {
buildInputs = [pkgs.makeWrapper nodejs];
});
in myPkgs.stdenv.mkDerivation {
name = "my_node_project";
version = "0.1.0";
buildInputs = [
nodejs
myPkgs.openssl
yarn
];
}
with import <nixpkgs>{};
let
nodejs = pkgs.nodejs-8_x;
yarn = pkgs.lib.overrideDerivation pkgs.yarn (attrs: rec {
buildInputs = [pkgs.makeWrapper nodejs];
});
in pkgs.stdenv.mkDerivation {
name = "my_node_project";
version = "0.1.0";
buildInputs = [
nodejs
pkgs.openssl
yarn
];
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment