Gurp 1.0.0
30 July 2025

When I began Gurp, my primary criterion was “must do everything my current Ansible setup does”. With a successful, hands-free rebuild of all my zones, this goal is achieved, and I’m cutting release 1.0.0.

Let’s have a look at some charts. I love charts. Gurp has a --metrics-to option, which makes it push run summary metrics to my VictoriaMetrics instance, in InfluxDB format.

Here’s the apply time. In each of these zones Gurp is managing somewhere between thirty and eighty resources.

gurp apply times

The outliers have lots of packages and some Ruby Gems. If it doesn’t need to shell out to pkg or gem, Gurp can fire up, compile your machine definition and assert (and possibly correct) the state of dozens of resources in under a second. When I maintained these same configs with Puppet, it was taking at least a couple of minutes per zone. Ansible was worse. Gurp can do thirty zones in thirty seconds.

How about resource usage? Ansible runs maxed out the CPU on my box, and Chef used so much memory most of my zones wouldn’t let it run.

gurp CPU usage

That’s percentage CPU (I need to fix that axis), and none of the spikes correlate with Gurp runs. How about memory?

gurp memory usage

Flat. You can’t see Gurp at all.

What I Got Right

What I Got Wrong

What I’m Still Not Sure About

What Next

The whole codebase could probably use a refactor. So many changes of plan have left vestigial tails everywhere, and some of the Janet is proper spaghetti. I’ve got good test coverage for the front-end, so refactoring that ought not to be too risky, and I always feel very safe refactoring Rust.

There’s a branch with bhyve zone support, but I’m a bit ambivalent about it. It was one thing adding LX support, but bhyve, with cloud-init is a lot messier, and Gurp offers no way whatsoever to configure a “real” Linux or BSD instance. Gurping an Unbuntu bhyve zone means you need Puppet or something to configure it, and that feels like it makes this whole exercise a bit pointless.

As I mentioned when I wrote about bootstrapping zones, I have a rough idea about client-server Gurp. A central instance would have access to all your files and configs, and clients would request their data from it. The first step would be to make file’s :from accept URIs, which would be useful anyway. The question is, would the client or the server compile the Janet? If the former, you would only have to get the compiled JSON data, but you couldn’t have any host-specific logic in your front-end code, because you’d be inspecting the server. (I don’t do this at all, but I can easily see cases where it would make sense.) If the latter, you’ve likely got to pull a whole load of files down and assemble them somehow. Offering both probably puts you in some sort of awful, confusing compromise, like pull-mode Ansible. And once you start doing HTTP, you’ve got to do HTTPS, and then we’re in the world of certificates, and we’re back to secrets management, and I really don’t think I can be bothered with it.

I’ve covered most of illumos’s OS primitives, but in a very basic way. There are some fairly basic things Gurp simply can’t do, like selecting package mediators, or configuring network interfaces. Some things it covers, like managing packages, it does in the most limited way possible. So there’s plenty of room for improvement and plenty of scope for new features. But as of this moment, I’m not sure how much of this I want to take on. I wanted to see if I could replicate my Ansible usage with Rust and Janet, and I could. That might be enough for a little while.

tags