Chicago GNU/Linux talk on Guix retrospective

By Christopher Allan Webber on Thu 01 October 2015

GuixSD logo

Friends... friends! I gave a talk on Guix last night in Chicago, and it went amazingly well. That feels like an undersell actually; it went remarkably well. There were 25 people, and apparently there was quite the waitlist, but I was really happy with the set of people who were in the room. I haven't talked about Guix in front of an audience before and I was afraid it would be a dud, but it's hard to explain the reaction I got. It felt like there was a general consensus in the room: Guix is taking the right approach to things.

I didn't expect this! I know some extremely solid people who were in the audience, and some of them are working with other deployment technologies, so I expected at some point to be told "you are wrong", but that moment didn't come. Instead, I met a large amount of enthusiasm for the subject, a lot of curious questions, and well... there was some criticism of the talk, though it mostly came to presentation style and approach. Also, I had promised to give two talks, both about federation and about Guix, but instead I just gave the latter and splatted over the latter's time. Though people seemed to enjoy themselves enough that I was asked to come back again and give the federation talk as well.

Before coming to this talk, I had wondered whether I had gone totally off the yaks in heading in this direction, but giving this talk was worth it in at least that the community reaction has been a huge confidence booster. It's worth persuing!

So, here are some things that came out of the talk for me:

  • The talk was clear, and generally people said that though I went into the subject to quite some depth, things were well understood and unambiguous to them.
  • This is important, because it means that once people understood the details of what I was saying, it gave them a better opportunity to evaluate for whether it was true or not... and so the general sense of the room that this is the right approach was reassuring.
  • A two tier strategy for pushing early adoption with "practical developers" probably makes sense:
    • Developers seem really excited about the "universal virtualenv" aspect of Guix (using "guix environment") and this is probably a good feature to start gaining adoption.
    • Getting GuixOps working and solidly demonstrable
  • The talk was too long. I think everything I said was useful, but I literally filled two talk slots. There are some obvious things that can be cut or reduced from the talk.
  • In a certain sense, this is also because the talk was not one, but multiple talks. Each of these items could be cut to a brief slide or two and then expanded into its own talk:
    • An intro to functional programming. I'm glad to see this this intro was very clear, and though concise, could be reduced within the scope of this talk to two quick slides rather than four with code examples.
    • An "Intro to Guile"
    • Lisp history, community, and its need for outreach and diversity
    • "Getting over your parenthesis phobia"
  • I simply unfolded an orgmode tree while presenting the talk, and while this made things easy on me, it's not very interesting for most audience members (though my friend Aeva clearly enjoyed it)

Additionally, upon hearing my talk, my friend Karl Fogel seemed quite convinced about Guix's direction (and there's few people whose analysis I'd rate higher). He observed that Guix's fundamentals seem solid, but that what it probably needs is institutional adoption at this point to bring it to the next level, and he's probably right. He also pointed out that it's not too much for an organization to invest themselves in Guix at this point, considering that developers are using way less stable software than Guix to do deployments. He suggested I try to give this talk at various companies, which could be interesting... well, maybe you'll hear more about this in the future. Maybe as a trial run I should submit some podcast episodes to Hacker Public Radio or something!

Anyway, starting next week I'm putting my words to action and working on doing actual deployments using Guix. Now that'll be interesting to write about! So stay tuned, I guess!

PS: You can download the orgmode file of the talk or peruse the html rendered version or even better check out my talks repo!

Userops Acid Test v0.1

By Christopher Allan Webber on Sun 27 September 2015

Hello all!

So a while ago we started talking about this userops thing. Basically, the idea is "deployment for the people", focusing on user computing / networking freedom (in contrast to "devops", benefits to large institutions are sure to come as a side effect, but are not the primary focus. There's kind of a loose community surrounding the term now, and a number of us are working towards solutions. But I think something that has been missing for me at least is something to test against. Everyone in the group wants to make deployment easiser. But what does that mean?

This is an attempt to sketch out requirements. Keep in mind that I'm writing out this draft on my own, so it might be that I'm missing some things. And of course, some of this can be interpreted in multiple ways. But it seems to me that if we want to make running servers something for mere mortals to do for themselves, their friends, and their families, these are some of the things that are needed:

  1. Free as in Freedom:

    I think this one's a given. If your solution isn't free and open source software, there's no way it can deliver proper network freedoms. I feel like this goes without saying, but it's not considered a requirement in the "devops" world... but the focus is different there. We're aiming to liberate users, so your software solution should of course itself start with a foundation of freedom.

  2. Reproducible:

    It's important to users that they be able to have the same system produced over and over again. This is important for experimenting with a setup before deployment, for ensuring that issues are reproducible and friends and communities helping each other debug problems when they run into them. It's also important for security; you should be able to be sure that the system you have described is the system you are really running, and that if someone has compromised your system, that you are able to rebuild it. And you shouldn't be relying on someone to build a binary version of your system for you, unless there's a way to rebuild that binary version yourself and you have a way to be sure that this binary version corresponds to the system's description and source. (Use the source, Luke!)

    Nonetheless, I've noticed that when people talk about reproducibility, they sometimes are talking about two distinct but highly related things.

    1. Reproducible packages:

      The ability to compile from source any given package in a distribution, and to have clear methods and procedures to do so. While has been a given in the free software world for a long time, there's been a trend in the devops-type world towards a determination that packaging and deployment in modern languages has gotten too complex, so simply rely on some binary deployment. For reasons described above and more, you should be able to rebuild your packages... *and* all of your packages' dependencies... and their dependencies too. If you can't do this, it's not really reproducible.

      An even better goal is to guarantee not only that packages can be built, but that they are byte-for-byte identical to each other when built upon all their previous dependencies on the same architecture. The Debian Reproducibility Project is a clear example of this principle in action.

    2. Reproducible systems:

      Take the package reproducibility description above, and apply it to a whole system. It should be possible to, one way or another, either describe or keep record of (or even better, both) the system that is to be built, and rebuild it again. Given selected packages, configuration files, and anything else that is not "user data" (which is addressed in the next section), it should be possible to have the very same system that existed previously.

      As with many things on this list, this is somewhat of a gradient. But one extrapoliation, if taken far enough, I believe is a useful one (and ties in with the "recoverable sytem" part): systems should not be necessarily dependent upon the date and time they are deployed. That is to say, if I deployed a system yesterday, I should be able to redeploy that same system today on an entirely new system using all the packages that were installed yesterday, even if my distribution now has newer, updated packages. It should be possible for a system to be reproducible towards any state, no matter what fixed point in time we were originally referring to.

  3. Recoverable:

    Few things are more stressful than having a computer that works, is doing something important for you, and then something happens... and suddenly it doesn't, and you can't get back to the point where your computer was working anymore. Maybe you even lost important data!

    If something goes wrong, it should be possible to set things right again. A good userops system should do this. There are two domains to which this applies:

    1. Recoverable data:

      In other words, backups. Anything that's special, mutable data that the user wants to keep fits in this territory. As much as possible, a userops system should seek to make running backups easy. Identifying based on system configuration which files to copy and helping to provide this information to a backup system, or simply only leaving all mutable user data in an easy-to-back-up location would help users from having to determine what to back up on their own, which can be easily overwhelming and error-prone for an individual.

      Some data (such as data in many SQL databases) is a bit more complex than just copying over files. For something like this, it would be best if a system could help with setting up this data to be moved to a more appropriate backup serialization.

    2. Recoverable system:

      Linking somewhat to the "reproducible system" concept, a user should be able to upgrade without fear of becoming stuck. Upgrade paralysis is something I know I and many others have experienced. Sometimes it even appears that an upgrade will go totally fine, and you may have tested carefully to make sure it will, but you do an upgrade, and suddenly things are broken. The state of the system has moved to a point where you can't get back! This is a problem.

      If a user experiences a problem in upgrading their system software and configuration, they should have a good means of rolling back. I believe this will remove much of the anxiety out of server administration especially for smaller scale deployments... I know it would for me.

  4. Friendly GUI

    It should be possible to install the system via a friendly GUI. This probably should be optional; there may be lower level interfaces to the deployment system that some users would prefer to use. But many things probably can be done from a GUI, and thus should be able to be.

    Many aspects of configuring a system require filling in shared data between components; a system should generally follow a Don't Repeat Yourself type philosophy. A web application may require the configuration details of a mail transfer agent, and the web application may also need to provide its own details to a web server such as Nginx or Apache. Users should have to fill in these details in one place each, and they should propagate configuration to the other components of the system.

  5. Scriptable

    Not everyone should have to work with this layer directly, but everyone benefits from scriptability. Having your system be scriptable means that users can properly build interfaces on top of your system and additional components that extend it beyond directions you may be able to do directly. For example, you might not have to build a web interface yourself; if your system exposes its internals in a language capable enough of building web applications, someone else can do that for you. Similarly with provisioning, etc.

    Working with the previous section, bonus points if the GUI can "guide users" into learning how to work with more lower level components; the Blender UI is a good example of this, with most users being artists who are not programmers, but hovering over user interface elements exposes their Python equivalents, and so many artists do not start out as developers, but become so in working to extend the program for their needs bit by bit. (Emacs has similar behavior, but is already built for developers, so is not as good of an example.) "Self Extensibility" is another way to look at this.

  6. Collaboration friendly:

    Though many individuals will be deploying on their own, many server deployments are set up to serve a community. It should be possible for users to help each other collaborate on deployment. This may mean a variety of things, from being able to collaborate on configuration, to having an easy means to reproduce a system locally.

    Additionally, many deployments share steps. Users should be able to help each other out and share "recipes" of deployment steps. The most minimalist (and least useful) version of this is something akin to snippet sharing on a wiki. Most likely, wikis already exist, so more interestingly, it should be possible to share deployment strategies via code that is proceduralized in some form. As such, in an ideal form, deployment recipes should be made available similar to how packages are in present distributions, with the appropriate slots left open for customization for a particular deployment.

  7. Fleet manageable:

    Many users have not one but many computers to take care of these days. Keeping so many systems up to date can be very hard; being able to do so for many systems at once (especially if your system allows them to share configuration components) can help a user actually keep on track of things and lead to less neglected systems.

    There may be different sets, or "fleets", of computers to take care of... you may find that a user discovers that she needs to both take care of a set of computers for her (and maybe her loved ones') personal use, but she also has servers to take care of for a hobby project, and another set of servers for work.

    Not all users require this, and perhaps this can be provided on another layer via some other scripting. But enough users are in "maintainance overload" of keeping track of too many computers that this should probably be provided.

  8. Secure

    One of the most important and yet open ended requirements, proper security is critical. Security decisions usually involve tradeoffs, so what security decisions are made is left somewhat open ended, but there should be a focus of security within your system. Most importantly, good security hygeine should be made easy for your users, ideally as easy or easier than not following good hygeiene.

    Particular areas of interest include: encrypted communication, preferring or enforcing key based authentication over passwords, isolating and sandboxing applications.

To my knowledge, at this time no system provides all the features above in a way that is usable for many everyday users. (I've also left some ambiguity in how to achieve these properties above, so in a sense, this is not a pass/fail type test, but rather a set of properties to measure a system against.) In an ideal future, more Userops type systems will provide the above properties, and ideally not all users will have to think too much about their benefits. (Though it's always great to give the opportunity to users who are interested in thinking about these things!) In the meanwhile, I hope this document will provide a useful basis for implementing and thinking about mapping one's implementation against!

Wisp: Lisp, minus the parentheses

By Christopher Allan Webber on Wed 23 September 2015

Arne Babenhauserheide has built a really cool syntax alternative for Scheme, Wisp (not to be confused with a different lisp-related-wisp), or in standards version, SRFI 119. It looks pretty nice:

;; hello world example
display                             ;    (display
  string-append "Hello " "World!"   ;      (string-append "Hello " "World!"))
display "Hello Again!"              ;    (display "Hello Again!")

;; hello world function
define : hello who                  ;    (define (hello who)
  display                           ;      (display 
    string-append "Hello " who "!"  ;        (string-append "Hello " who "!")))

Actually, let's see that in emacs, just to be sure.

Wisp and hello world

How about something slightly more substantial? How about a real life Guix package for GNU Grep:

Wisp, Emacs, Guix and Grep

Wow, not bad... not bad at all! I'd say that's quite readable! (Too bad the lines don't line up exactly in that screenshot; that's not the code but rather my emacs theme bolding the wisp code.)

What's nice is that unlike most s-expression alternatives, it doesn't lack any of the power of Lisp; it's "just lisp" with the parentheses hidden by vaguely pythonesque indentation, which means even macros work.

Now me personally? I've learned to love the parens, and there's nothing that beats an editor that knows how to do cool structural s-expression editing and navigation. But I admit that learning to read through all the parentheses was a tough thing for me initally, and certainly for many others. Maybe this can help boil the lisp frog for some.

Now what would really be hylarious would be to port this to Hy...

More careful exceptions in Guile

By Christopher Allan Webber on Sat 05 September 2015

So as I've probably said before, I've been spending a lot more time hacking in Guile lately. I like it a lot!

However, there is one thing that really irks me: error handling. Though a programmer in Guile has a lot of flexibility to define their own error handling mechanisms, really I think a language should be providing good builtin ways of doing so. Guile does provide some builtin methods, but I have problems with both of them.

The first is the more egregious of the two, and is a procedure known simply as error, which takes one argument: a string describing what went wrong. Usage looks like so:

(if (something-bad? thing)
  (error "You shouldn't have done that!"))

This is fast to toss through your code without thinking, but at serious cost. The problem is that this follows the "diaper pattern" (or "diaper antipattern?"). Guile provides a catch procedure, but if you try catching these errors, they are all thrown with the "misc-error" symbol, and there is no way to catch the right errors.

(catch 'misc-error
  ;; the code we're running
  (lambda ()
    (let ((http-response (get-some-url)))
      (if http-response
          ;; all went well, continue with our webby things
          (do-web-things http-response)
          ;; Uhoh!
          (error "the internet's tubes are filled"))))
  ;; The code to catch things
  (lambda _ (display "sorry, someone broke the internet\n")))

But wait... what if the user gave a keyboard interrupt and instead your database execution code caught it instead? I you can't catch errors precisely, things might bubble to the wrong place.

This is not an abstract problem; this happened to me in an extremely well written Guile program, Guix: I was working on adding a new package and had screwed up the definition, so somewhere up the chain Guix threw an error about my malformed package, but I didn't know... instead, when I was attempting to run the "guix package" command to test out my command, suddenly the "guix package" command disappeared entirely. Whaaaaat? I did some debugging and found a (catch 'misc-error) in the command line arguments handling code. Whew! Well, that usage of "(error)" got replaced with some more careful code, but what if I couldn't find it, or was a more green developer?

So, luckily, Guile does provide a better exception handling system, mostly. There's throw, which looks a bit like this in your code:

(catch 'http-tubes-error
  ;; the code we're running
  (lambda ()
    (let ((http-response (get-some-url)))
      (if http-response
          ;; all went well, continue with our webby things
          (do-web-things http-response)
          ;; Uhoh!
          (throw 'http-tubes-error "the internet's tubes are filled"))))
  ;; The code to catch things
  (lambda _ (display "sorry, someone broke the internet\n")))

Okay, great! This is much more specific, yay!

Except... it still kind of bothers me. Maybe I'm being overly pedantic here, but what if you and I both had 'json-error exceptions in our own separate libraries? The problem is (unlike in common lisp) there aren't module-specific symbols in Guile! This means we could catch someone else's 'json-error when we really wanted to catch our own.

Okay, maybe this is rare, but I really don't like running into these kinds of problems. I want my exception symbols to be unique per package, damnit!

So in the interest of doing so, let me present you with a terrible hack of scheme code (which like all other code content in this blogpost, I both waive under CC0 1.0 Universal (and also do waive any potential patent "rights") and also release under LGPLv3 or later, your choice):

(define-syntax-rule (define-error-symbol error-symbol)
  (define error-symbol
     ;; gensym can take a prefix
     (symbol->string (quote error-symbol)))))

Okay, it's kind of hacky, but what this does is give you a nice convenient way to define unique symbols. (Edit: turns out gensym can take a prefix, so the above code is even easier and less hacky now! Thanks for the tip, taylanub!) You can use it like so:

(define-error-symbol http-tubes-error)

(catch http-tubes-error
  ;; the code we're running
  (lambda ()
    (let ((http-response (get-some-url)))
      (if http-response
          ;; all went well, continue with our webby things
          (do-web-things http-response)
          ;; Uhoh!
          (throw http-tubes-error "the internet's tubes are filled"))))
  ;; The code to catch things
  (lambda _ (display "sorry, someone broke the internet\n")))

See? All you have to do is do a simple definition above and you have a unique-per-your-program error symbol (thanks to the gensym). Now if users want to catch your errors, but only your errors, they can import the error symbol directly from your package.

So the lesson from this post is: if you're going to use exceptions in your code, please be careful... and specific!

Update: Apparently I can't be the only one who finds the need for this; turns out that prompts (which have a similar "unwinding" property to exceptions) also take symbols, but usefully there's (make-prompt-tag) which does pretty much exactly the same thing as define-error-symbol above. So I must not be totally crazy!

In which I receive the O'Reilly Open Source Award

By Christopher Allan Webber on Tue 01 September 2015

Well, I'm late in putting this one out there, but it's still worth putting on the record! About a month ago, I was fortunate enough to receive the O'Reilly Open Source Award. In fact, here's a picture of me receiving it!

receiving the award
Photo taken by Brandin Grams, CC BY 4.0, originally microblogged by Karen Sandler

(... there's a video too!)

So, getting the award was exciting and unexpected. Exciting, because just look at the list of people who have received this award previously!

Even to just share the stage with friends Marina Zhurakhinskaya of Outreachy, Stefano Zacchiroli of Debian, and Sarah Mei was a huge honor (okay, Sarah Mei is not someone I know, but I know very well of Railsbridge and the many ways it has paved forward diversity initiatives in free software). Plus, even though I don't know much about Hadoop, I know others who do, and the looming head of Doug Cutting behind us in videorecording excited them! And looking at former recipients, nearly everyone on this list is a person who has made humongous strides in shaping the world of free and open source software, and let's face it, almost everyone on this list has done more in that capacity than I have.

Which leads me to the surprise part... I was really not expecting this award, so when I saw the email informing me I was being awarded it I began to flag it as spam, assuming it was something that snuck past spamassassin. But wait, I actually know this award! I then preceded to try to get Morgan's attention (she was on the phone) by exuberantly waving my arms, which lead our dog to jump up and also wave her forelegs in a very similar fashion.

So that is all to say I'm very honored to have received the thing!

So, then I knew I received the award, but didn't know for what text I was nominated until the ceremony, but I was really happy with it when I heard it said: for my free software advocacy (and with those words) and my work on GNU MediaGoblin (GNU was pronounced with each letter as if a university chant... G! N! U!). I suspected as much and I'm glad I received the award under that description.

And that is also to say I am really glad for the recognition!

The recognition does help, in some way, as a counterbalance to other feelings. In another sense, I also look at the list of other people who have received the award and I feel a bit embarrassed because I think maybe I don't deserve it. I had confided in this to some friends (I guess it's no longer confiding now that I'm writing in a blogpost), and the response has mostly been something along the lines of "of course you do, just feel good about the thing", and of course that's also the kind of thing you want to hear from your friends, and it would be pretty embarrassing if they didn't say those kinds of things in response, and you begin to wonder that given that if you're playing some sort of scripted roles, and typing this I even wonder if this "I don't deserve it" text is doing that too, and maybe it is, maybe everything is... but I still think sometimes I am fooling everyone and when I am given recognition that I am some kind of tricky person, tricky enough to trick people into giving me an award for a pile of incomplete things.

I think there are a variety of reasons for this, one of the more obvious being that MediaGoblin is moving along but it isn't there yet, something I think nobody is more deeply aware of than myself. And people are still locked down by proprietary network services, we still don't have a generally agreed upon federation standard, and it is still really hard to run your own server. These aren't my battles alone and a good number of us are working on them, (and I even have interesting things to report in these areas that I have not yet blogged about) but when I think about things not being done I feel personally responsible for it. Part of the challenge also is that I do not generally look at my life as in terms of things I have accomplished, but in terms of the things I haven't, and obviously that is not a great strategy for feeling good about the things you've done.

But let me turn this blogpost back around again, before I look like some kind of jerk who gets an award and then mopes about it!

In this same sense the recognition has helped a lot. Not everything that I want to see done is done yet, but the O'Reilly Open Source Award selection process happens through previous winners, so clearly people who know better than I do have recognized that the things we've done and the direction we're heading are the right ones.

You may notice that I'm switching between "I" and "we", so a bit more on that... it's worth noting that any accomplishments I have are connected to some significant free software community, so they're hardly just "my" accomplishments... that statement of indicating that the roads we're heading down are the right ones applies to all the people in the communities of which I've become some apparent type of minor figurehead. (Be wary of pedestals, with coordination like mine, a great way to dash oneself against the floor...)

So! That's a lot of words there, but the crux it is that I'm still excited to have gotten the award, and as much of a worrier as I am, the recognition is especially nice as a kind of reassurance. In the meanwhile, I have a fancy new bookshelf and a nice little display for this hunk of glass:

On the bookshelf

On the bookshelf, zoomed in a bit

O'Reilly award, on display

Pretty cool hunk of glass, right? I think so!

PS: John Sullivan snapped this image of Stefano Zacchiroli and I right after the ceremony, on a trip to Powell's books.

Award Winners at Pow-ells
"Award Winners" photo taken by John Sullivan CC BY-SA 4.0