Painless Software
3. Repo Design.
Beautiful is better than ugly. System and User configuration.
2. Getting Started.
Learning resources, downloads and basic commands.
1. Why use NixOS.
Config management for Dev machines.
4. The Nix language.
Modules and Lambda functions.
5. Develop your NixOS Config.
Working with a tool you don't know yet.
6. Python on NixOS.
Make development a breeze on a non-compliant system.
✅ Fix-Price Projects & Agile
✅ Continuous Delivery
✅ Modern Continuous Delivery
✅ NixOS
✅ NixOS
✅ Juju & Charmed Operators
feature
branch
production
system
approve
review
system
open PR/MR
build
server
push code
Release early, release often!
CD Pattern | Anti-Pattern |
---|---|
Automate environment config | Manual setup, "work of art" |
Scripted setup | Notes, documentation of setup |
Single command builds | Comprehensive instructions |
Fix broken environments first | Ignore errors, postpone fixes |
TDD, automate tests | Manual verification + fixes |
Fully version controlled | Parts not version controlled |
Visibility, dashboards, sharing | Geeky "secret configurations" |
Easy Replacement
Portable, declarative configuration. Effortless upgrades of hardware and software.
Resilience Built-In
Work on any office owned computer. Continue where you left off when device gets dropped or stolen.
➜ Make installation and backup fully automatic, restore data upon login.
Fun Team Investment
Learn by improving a shared setup. Solve problems together.
➜ Treat every machine like a container with a data volume. Resist manual config changes. Get into the IaC mindset, naturally.
3. Repo Design.
Beautiful is better than ugly. System and User configuration.
2. Getting Started.
Learning resources, downloads and basic commands.
1. Why use NixOS.
Config management for Dev machines.
4. The Nix language.
Modules and Lambda functions.
5. Develop your NixOS Config.
Working with a tool you don't know yet.
6. Python on NixOS.
Make development a breeze on a non-compliant system.
Nix = purely functional package manager
Nix store = /nix/store
(contains packages aka derivations)
Nix expressions = functional language to describe/build a package
NixOS = Linux distribution based on & built entirely from Nix
NixOS config = /etc/nixos/configuration.nix
(default, example)
FHS ?!?
Fear not, Pythonistas! —
You write pythonic code, you do functional.
foo = [99, 3, 4, 0]
id(foo) # 140428019716160
bar = sorted(foo)
id(bar) # 140428019721728
inverse = list(reversed(bar))
print(inverse) # [99, 4, 3, 0]
# not pure functional
result = foo.sort()
id(foo) # 140428019716160
print(foo) # [0, 3, 4, 99]
print(result) # None
words = ["Ciao", "Python", "Italia"]
upper_words = list(map(str.upper, words))
upper_list = [str.upper(s) for s in words]
print(upper_words) # ['CIAO', PYTHON', 'ITALIA']
print(upper_list) # ['CIAO', PYTHON', 'ITALIA']
salutation = "Ciao" if friend else "Buongiorno"
(lambda :-1)() # -1
sorted(words, key=lambda s: -len(s)) # ..., Ciao
list comprehensions
set comprehensions
dictionary comprehensions
generator comprehensions
lambda expressions
built-in functions
nix-channel | nix flake [init|check|show|update|...] |
nix-shell -p <pkg> ... | nix shell <repo>#<pkg> ... |
nix-shell -p <pkg> --run "<cmd> ..." | nix run <repo>#<pkg> ... |
nix-shell [default.nix|shell.nix] | nix develop |
nix-instantiate --eval [--expr] ... | nix eval [<repo>#<pkg>|--expr ...|--file ...] |
search.nixos.org | nix search nixpkgs <regex> |
New (think "Python 3")
Old (think "Python 2")
Excutables | /run/current-system/sw/bin/ |
User executables | /etc/profiles/per-user/<username>/bin/ |
Application data | /run/current-system/sw/share/ |
User app data | /etc/profiles/per-user/<username>/share/ |
Application icons | /run/current-system/sw/share/icons/hicolor/scalable/apps/org.gnome.Epiphany.svg |
User app icons | /etc/profiles/per-user/<username>/share/icons/ |
Autostart items | /run/current-system/sw/etc/xdg/autostart |
Interesting Places
$ tree /etc/nixos
/etc/nixos
|-- configuration.nix
`-- hardware-configuration.nix
# Edit this configuration file to define what s
{ config, pkgs, ... }:
{
imports = [
./hardware-configuration.nix
];
boot.loader.systemd-boot.enable = true;
networking.hostName = "nixos";
networking.networkmanager.enable = true;
time.timeZone = "Europe/Rome";
i18n.defaultLocale = "en_US.UTF-8";
programs.firefox.enable = true;
environment.systemPackages = with pkgs; [
vim
];
}
# Do not modify this file! It was generated by
{ config, lib, pkgs, modulesPath, ... }:
{
boot.kernelModules = [ "kvm-intel" ];
fileSystems."/" = {
device = "/dev/disk/by-uuid/5a42e090-37b7";
fsType = "ext4";
};
networking.useDHCP = lib.mkDefault true;
}
$ sudo nixos-rebuild [switch|boot|test]
...
Done. The new configuration is /nix/store/j6a42...
$ nixos-rebuild --use-remote-sudo [switch|boot|test]
...
Done. The new configuration is /nix/store/j6a42...
a
b
Recommended
$ sudo su -
# cd /etc/nixos
# git init && git add -v .
# git commit -m "Profit!"
$ cp -r /etc/nixos ~/.nixos-config
$ cd ~/.nixos-config
$ git init && git add -v .
$ git commit -m "Profit!"
$ git push origin main
$ sudo rm /etc/nixos/*
$ nixos-rebuild --use-remote-sudo --file configuration.nix
Recommended
🫣
🙂
1.a
1.b
2
🤑
3. Repo Design.
Beautiful is better than ugly. System and User configuration.
2. Getting Started.
Learning resources, downloads and basic commands.
1. Why use NixOS.
Config management for Dev machines.
4. The Nix language.
Modules and Lambda functions.
5. Develop your NixOS Config.
Working with a tool you don't know yet.
6. Python on NixOS.
Make development a breeze on a non-compliant system.
imports
Copier template
hosts/
– managed machinesroles/
– classes of machines (abstraction layer)system/
– system-global configurationManage user-specific software and settings ("dotfiles")
💡 Some people use GNU Stow instead to manage dotfiles
Declarative disk partitioning
disko-config.nix
$ sudo nix run github:nix-community/disko/latest -- \
--mode destroy,format,mount \
--flake gitlab:painless-software/nixos-config#example
3. Repo Design.
Beautiful is better than ugly. System and User configuration.
2. Getting Started.
Learning resources, downloads and basic commands.
1. Why use NixOS.
Config management for Dev machines.
4. The Nix language.
Modules and Lambda functions.
5. Develop your NixOS Config.
Working with a tool you don't know yet.
6. Python on NixOS.
Make development a breeze on a non-compliant system.
{
# numbers
a = 1; f = 3.14;
# strings
text = "Hello Pi! ${f}";
multi_line = ''
Very long text ... with ${a}
'';
# boolean
truth = false; lie = true;
# attribute sets
b = { foo = 1; bar = "something"; };
# lists
c = [ 1 2 3 ];
d = [ "hello" "world" ];
# paths
x = /absolute/path/to
y = ./relative/path
z = ~/.config # path in home dir
}
data types
{
# negation
truth = !false;
# string and paths
a_str = "Dirs" + ~/.config/user-dirs.dirs;
a_path = /etc + "/nixos";
# list concatenation
l = [ 1 2 3 ] ++ [ "four" "five"];
# logical and, logical or
m = true && false; n = true || false;
# update attribute set
s = { x = 1; } // { y = 1; x = 2; };
# has attribute (attribute set member)
h = { x = 42; } ? x;
}
operators
d = builtins.readDir;
f = builtins.readFile;
e = builtins.getEnv "HOME"; ...
built-ins
42
a.nix
"foo"
b.nix
true
c.nix
~/.local/bin
d.nix
[ ]
e.nix
{ }
f.nix
x: x + 1
g.nix
{
x = import ./a.nix;
}
imported.nix
{ lib, ... }:
{
imports = [ ];
options = {
my.option = lib.mkOption { };
};
config = { };
}
explicit.nix
↷
Module
{ lib, ... }:
{
options = {
desktop.style = lib.mkOption {
type = lib.types.enum [ "Windows" "macOS" "GNOME" ];
default = "GNOME";
};
};
}
options-only.nix
{
console.keyMap = "it";
services.xserver.xkb = {
layout = "it";
variant = "";
};
}
implicit-config.nix
{ lib, ... }:
{
imports = [
./file.nix
];
options = {
magicNumber = lib.mkOption {
type = lib.types.number;
default = 3.14;
};
};
config = {
boot.loader.grub.enable = true;
};
}
module.nix
{ lib, ... }:
let
foo = "Hello";
in
{
imports = [
./file.nix
];
options = {
greeting = lib.mkOption {
type = lib.types.str;
default = foo;
};
};
config = {
boot.loader.grub.enable = true;
};
}
variables.nix
{
description = "Python Italia flake";
inputs = {
nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable";
nixos-hardware.url = "github:NixOS/nixos-hardware?ref=master";
};
outputs = { self, nixpkgs }: {
nixosConfigurations = nixpkgs.lib.mapAttrs mkSystem systems;
};
}
flake.nix
$ nix flake update
Recommendation
✨
Nix | Python |
---|---|
Flake, flake.nix, flake.lock | pyproject.toml, uv.lock |
Module, <filename>.nix | Module, <filename>.py |
Lambda expression, function | Python code (module) |
3. Repo Design.
Beautiful is better than ugly. System and User configuration.
2. Getting Started.
Learning resources, downloads and basic commands.
1. Why use NixOS.
Config management for Dev machines.
4. The Nix language.
Modules and Lambda functions.
5. Develop your NixOS Config.
Working with a tool you don't know yet.
6. Python on NixOS.
Make development a breeze on a non-compliant system.
$ copier copy gl:painless-software/cicd/config/nixos nixos-config
...
$ pre-commit install
...
$ git init
$ git add -v .
...
$ pre-commit
$ nix flake check
...
---
deadnix:
extends: .nix
script: nix-shell -p deadnix --run "deadnix --fail"
statix:
extends: .nix
script: nix-shell -p statix --run "statix check"
flake:
extends: .nix
script:
- nix flake check
- nix flake show
disko:
extends: .nix
script: nix run github:nix-community/disko/latest --
--mode destroy,format,mount --dry-run --flake .#generic
tooling:
extends: .megalinter
variables:
FLAVOR: documentation
.gitlab-ci.yml
Copier template
Flake
Establish execution entrypoint (e.g. integrate hosts/
).
Consider integrating QA tools, pre-commit and CI/CD early.
Disko
Integrate Disko configuration. Verify installation process end-to-end.
Consider setting up functional tests with VMs.
Refine
Delegate host setup to system/
configuration. Consider introducing roles/
.
Consolitate home/
features in common user/
modules.
Home Manager
Allow configuring settings and installing software for individual users.
Consider using LDAP for a flexible, host-independent setup.
3. Repo Design.
Beautiful is better than ugly. System and User configuration.
2. Getting Started.
Learning resources, downloads and basic commands.
1. Why use NixOS.
Config management for Dev machines.
4. The Nix language.
Modules and Lambda functions.
5. Develop your NixOS Config.
Working with a tool you don't know yet.
6. Python on NixOS.
Make development a breeze on a non-compliant system.
# system/software/developer.nix
{ pkgs, ... }:
{
environment.systemPackages = with pkgs; [
python313 # first in list will be default Python
python312
python311
python310
uv
];
}
# system/software/developer.nix
{ pkgs, ... }:
{
environment.systemPackages = with pkgs; [
uv
];
}
a
b
system-managed
user-managed
$ uv python install --preview --default
$ which python
/home/nixos/.local/bin/python
➜
You cannot mix system Pythons with Python packages that ship precompiled binary code.
$ uv venv
Using CPython 3.13.3 interpreter at: /run/current-system/sw/bin/python
Creating virtual environment at: .venv
$ source .venv/bin/activate
$ uv pip install numpy
+ numpy==2.2.6
$ python
>>> import numpy
Traceback (most recent call last):
...
ImportError: libstdc++.so.6: cannot open shared object file: No such file or directory
$ uv tool install copier
$ uv tool install httpie
$ uv tool install pre-commit
$ uv tool install pyclean
$ uv tool install tox
# system/terminal/default.nix
{
environment.localBinInPath = true;
}
$ ls ~/.local/bin
copier http httpie https pre-commit pyclean python tox
$ uv tool list
$ uv tool upgrade --all
What did he
forget to explain?
I think it was
nix develop
And how to configure backup and restore
And automatic system upgrades
Less pain, more fun.
Most backgrounds from Unsplash (CC BY-SA)
Comic from Work Chronicles (CC BY-SA)
Decorative icons are unicode (CC-0)