Guix(SD)

1 Introduction

1.1 What's Guix?

Not just "Yet Another Package Manager / Distro!"

https://www.gnu.org/software/guix/

1.1.1 A functional package manager

"wtf does that mean?" you say!

In brief: packages are based "purely" on their dependencies. And same with the dependencies of dependencies!

We'll come back to this!

1.1.2 Based on Nix

  • Nix pioneered most of the ideas of functional package management!
  • Most of Guix's design follows Nix
  • But not the same codebase
    • Only Guix's daemon comes from Nix
    • They both use "Hydra", a continuous integration system, to build binary packages though
  • And not the same language:
    • Nix uses a mishmash of languages, including a special DSL for packaging
    • Guix uses Guile… for nearly everything

1.1.3 Free as in Freedom

  • Default packages are 100% libre.
  • This is another difference from Nix…
  • You could taint things with nonfree software, but the base will always be pure. Better foundations: easier to taint something than to remove impurities later.

1.1.4 (Other) features

  • Atomic: Either everything succeeds, or nothing does Never have a system broken mid-install again.
  • Time travel: roll back and forward without pain.
  • Multiple profiles:
    • Your company's application 1 is on Django 2.X whereas the old version is stuck on Django 1.9? No problem.
    • Each user can have their own profiles, separate from the system! You need GCC 5, but your sysadmin only installed GCC 4? No problem.
  • Can serve as a universal package manager
  • Can provide an isolated "environment" for hacking… Like a universal "virtualenv", for any language

1.1.5 "The git of package management"????

This is kind of a stretch! But git might feel familiar, so..

cwebber@earlgrey:~/devel/sly$ git cat-file -p 6573261753243257c7b168e174d45c9cd40061ee
                                       
tree 3bcdcbeac414887a356b375a4b230f80159efe2f
parent c23f81b59db98d7af4fd91a41c9b366823662083
author Christopher Allan Webber <cwebber@dustycloud.org> 1434053151 -0500
committer David Thompson <davet@gnu.org> 1434416170 -0400

examples: Add Conway's Game of Life.

* examples/life.scm: New file.
* examples/Makefile.am (nobase_dist_examples_DATA): Add it.
  • All these "hash" references are (kind of) "content addressed storage"
  • A commit's parents get hashed in as a kind of depenency … See how git's history is immutably tied to its parents?
  • But feature-wise, making a new commit doesn't "destroy" the old version.

(This metaphor only goes so far, for example, you can easily drop old history and reclaim that space in Guix…)

1.2 What's GuixSD?

  • Now take Guix, and make it a distro!

1.3 Motivations

1.3.1 Has this ever happened to you?

  • My system failed mid-upgrade and now it's BORKED
  • Oh no I thought this upgrade was okay but now it isn't
  • One Package Manager Per Child Language
  • My server is a special snowflake and I have no idea how to reproduce or replace it
  • This deployment system has a turing tarpit of custom config languages (I've fallen and I can't get out!)

1.3.2 Personal motivations

But maybe most critically for me:

  • Network freedom is near-impossible current state of deployability
  • Tired of

2 Prereq: Understanding "functional"

Or: "I'm not trying to trick you into learning monads, I promise!"

2.1 Understanding pure functions

2.1.1 A definition of pure functions

===================================================================
  A pure function:
  
  1. Given the same arguments, must always produce the same output.
     (Can't rely on any data that might change!)
  2. Doesn't cause any observable "side effects".
     (Can't change anything that isn't its output!)
===================================================================

Simplified from: https://en.wikipedia.org/wiki/Pure_function

(Yes, that's all functional programming means! But what is extrapolated from those requirements is what makes things interesting…)

2.1.2 Your prescription: no side effects!

"Side effects" are not allowed:

  • It can't do any IO
    • It can't read or write from the filesystem
    • No network access
  • No changing global variables or relying on changing variables
  • No GUIs, no widgets
  • Definitely no "random" procedure
  • No beeps and boops
  • No mutating data that is accessed elsewhere

2.1.3 Functions vs procedures

# A function
def greet(name):
    return "Hello, " + name

# A procedure (NOT a function)
def greet_printer(name):
    print("Hello, " + name)

Printing to the screen is a "side effect"

2.1.4 This is as far from a pure function as you can get

def write_site_status_to_file(our_file, config):
    # mutation!
    urls = config.pop("urls")
    # iteration!
    for url in urls:
        # time-dependent variables!
        current_time = datetime.datetime.now().isoformat()
        # File IO!
        our_file.write("\n--Site status at %s--\n" % current_time)
        # Network IO!
        site_status = urlopen(url).read()
        # More file IO!
        our_file.write(site_status)

2.2 A purely functional program can't do anything

… Functional programs can't really do anything, since they can't have side effects. As Simon Peyton Jones, a well-known functional programmer, likes to say, "All you can do without side effects is push a button and watch the box get hot for a while." (Which isn't technically true, since even the box getting hot is a side effect.) – Land of Lisp, p. 300

2.3 So… what does it give you?

That sounds like a lot of "can't", but functional programming gives you some amazing properties:

  • GUARANTEED reproducibility. By definition!
  • Concurrent programming is easy. No mutation means no locking!
  • Most of the hard bugs vanish (Ever heard of a heisenbug?)
  • Game engines which can "scrub" back and forth in time! Debug by setting that game to 20 seconds ago! (Elm and Sly)
  • Memoization means caching with no cache invalidation challenges
  • Optimized "immutable" datastructures are cooooooooool
  • And much, much more

Unfortunately, this isn't a functional programming talk!

(I recommend reading Land of Lisp for a great explaination of where functional programming is awesome, applied to game AI!)

2.4 Functional programming strategy

Break your program into two parts:

  • The clean part: purely functional! Make as much of your program into this clean part as possible.
  • The dirty part: do side effects here. Make this as small and "quarantined" as possible.

3 Guix: a functional package manager

3.1 Understanding pure functional packaging

3.1.1 The general picture

3.1.2 What will we get?

3.1.3 What

3.2 Exploring a little install

3.2.1 Run an install command!

guix package -i extremetuxracer

Now let's run it!

etr

3.2.2 Where'd that package go?

Let's look in the "store":

ls /gnu/

3.3 So what does a Guix package look like?

How about a nice game of chess?

3.4 How deep does it go?

3.5 Multiple profiles!

3.6 What does writing a package look like?

3.7 Guix is a lot like Git

3.8 GUI alternatives?

3.8.1 You meant emacs right?

3.8.2 guix-web

3.8.3 .~~@YOUR GUI HERE!@~~.

4 GuixSD: a functional system distribution

4.1 Describe your system and go

4.2 Run it in a VM! On a container!

5 Cool demonstrations

6 Guile as a killer feature

This is where Guix diverges from Nix

6.1 What's Guile?

6.2 How much of Guix is written in Guile?

6.3 What can we do here?

6.4 How does this compare against Nix?

6.5 A word against "turing tarpits"

7 Wrapping up

7.1 Guix is "The Right Thing", but "right thing" != success

Avoiding a "Worse is Better" type fate, and other analyses here

7.2 Other conclusions

7.3 Blah blah thanks for coming

Date: 2015-09-30 Wed

Author: Christopher Allan Webber

Created: 2015-09-29 Tue 15:15

Emacs 24.4.1 (Org mode 8.2.10)

Validate