Book status: released!


I am ecstatic to announce that the book is now officially released! You can get it here: If you purchased the Early Release version, you should automatically be able to download the final version from your "Your products" page at

It's been an incredible ride, and it's an incredible feeling to see it come to this big milestone (I won't say "the end", because I know this book will keep evolving).

There have been so many people who helped me through this process, including my editor (Andy Oram), all the staff at O'Reilly, who have been so professional and helpful, my very competent tech reviewers (Mark Burgess and Jesse Becker), all my colleagues at CFEngine AS, all the readers of intermediate and partial versions of the book, all the people who purchased the Early Release, and of course, my lovely wife and my two beautiful daughters, who were so patient while I worked on "the book". Everyone gave me encouragement, incredible feedback, and tons of guidance and support. Thank you everyone!

Book status: print-ready

I am very happy! I got the notification today that the final book draft has been produced and sent to the printer. This means that over the next few days the final version will be available for purchase, both as e-book and in print form. I will of course let you know when this happens.

For now, time to enjoy a relaxing weekend, the first with no book-related work in a long time :)

Syntax highlighting in "Learning CFEngine 3"

The electronic versions of the book contain full syntax highlighting and other useful features. I'm biased of course, but I think it is both functional and beautiful. Here's a sample from Chapter 4:


The syntax highlighting in my opinion greatly helps in reading the code. Additionally, each one of those numbered callouts in the code are in-document links that take you to the paragraph where that part of the code is described. Conversely, the callouts in the text take you back to the corresponding line in the code. And finally, most CFEngine keywords and concepts are links to the corresponding description in the CFEngine Reference Manual. In the PDF, clicking on that blue "files:" in the last paragraph will take you to

CFEngine community event: March 8th, 2012

I am visiting the Bay Area this week, and we took the opportunity to organize a CFEngine community event on Thursday, March 8th, at 6:30 PM. Come by, meet the CFEngine team, hear about some of the exciting things we are working on, and give us your feedback for the future.

Hope to see you there! If you plan to attend please don't forget to register.

Book status: production

Some people have asked me what the status of the book is, so I thought I would post it here. The book is currently in the "production stage", which means that the draft has been finalized content-wise, and is now being prepared for publication by O'Reilly. They have a specialized group of people for this, who work on preparing nice final versions of the figures, making sure the layout of the book is correct, and doing a few thorough proofreading and editing passes.

This means that it's now really close to publication. I cannot make any promises about the specific date, but it should be before the end of March.

Thank you for your interest!

Searching CFEngine documentation

The CFEngine Reference Manual is extremely useful, and is the ultimate guide to everything about CFEngine. However, it is not always the easiest to find what you are looking for.

To help in this respect, I have created a cross-referenced index of all the section headings in the manual. You can search it using the second search box on the right of any page of this site. For example, try searching for "ifvarclass", and you will be redirected to the section of the manual that described that attribute. If your search term matches more than one section (for example, try searching for "root"), you will be shown a disambiguation page where you can select which one you want.

You can also search the index directly by going to, replacing "keyword" with your search term. Without a search term (, it will redirect you to the top of the manual. Here are a few examples to get you started:

In the electronic versions of the book, all CFEngine keywords in the text will be linked to this index, to provide you easy access to the reference documentation about that concept.

But the real power, in my opinion, comes from using these links as browser "search keywords". Most modern browsers allow you to define search keywords or search engines. If you define a keyword whose search URL is as shown above (using whatever mechanism necessary to put the search term in the place of "keyword", then you will be able to easily search the CFEngine docs. For example, using Safari Omnibar, I have defined a new "search provider" as follows:


So now I can simply type "cf keyword" in my Safari URL bar and it will do a search for that keyword.



A couple of days ago I finished writing all the material that was planned for the book, so it is now content-complete! I am now going through all the comments that came back from the tech reviewers, and from many readers that sent me feedback while reading the early release. After that it goes to the production department at O'Reilly for putting it in its final form, and then it will be ready for publication!

Thank you to everyone who has given me feedback and encouragement so far!

Code examples for "Learning CFEngine 3" now available

I'm happy to announce that the code examples from Learning CFEngine 3 are now available for browsing and download at You can view or download individual files, and also the whole collection. You can also get them from the GitHub repository.

These examples are extracted automatically from the source files for the book, and as such reflect exactly the current state of what you will find in it. This also means, of course, that as the book evolves you will see changes in the files.

As usual, please feel free to play with them, and let me know if you find anything broken.

CFEngine 3 training on January 25-27th, 2012

Quick plug: if you are in the Bay Area and are interested in getting some hands-on introduction to CFEngine 3, please make sure to check out this training session:

Automating System Administration using CFEngine 3
Presented by Mark Burgess & Aleksey Tsalolikhin
Date: January 25-27
Location: Palo Alto, CA
Price: $1950 per person (group discount negotiable)
Registration & Agenda:
Mark is the original author of CFEngine and the ultimate CFEngine authority in the world. He will be joined by Aleksey, one of the most experienced CFEngine trainers around. Both are excellent teachers, so the course is guaranteed to be excellent.

cf-cmd: A command-line tool for running CFEngine snippets

While writing this book, I've had to run hundreds of little CFEngine snippets to run tests, develop examples, verify functionality, or get a solid idea of what some constructs did. After building the typical "test bundle" scaffolding in an editor for the hundredth time, I decided to do something about it. The result is the cf-cmd command. I will let it speak for itself:

$ cf-cmd help
cf-cmd v1.0 - Diego Zamboni>

cf-cmd is a tool that allows you to run small CFEngine snippets quickly,
by automatically wrapping them around a standard "test" bundle.

The CFEngine Standard Library is automatically included.

The following inputs are understood by this tool:

help     Print this message
list     Print current policy
clear    Clear current policy
go|run   Execute current policy using cf-agent
type:    Switch to the given promise type
         (classes:, commands:, databases:, environments:, files:, interfaces:,
         methods:, outputs:, packages:, processes:, reports:, services:,
         storage:, vars:)
           The current promise type is shown in the prompt.

All other lines are added literally to the current promise type.

Commands can be abbreviated to any part of their name (for example,
"r" or "ru" for "run").

You can add lines to any of the standard promise types inside the test
bundle by switching to the appropriate promise type first.

The default promise type is "reports:", to make it easier to quickly print
the value of expressions.

You can give the inputs also on the command line, they are interpreted
in exactly the same way (make sure to quote things correctly).

  cf-cmd '"Flavor: $(sys.flavor)";' list run
  cf-cmd '"var1 = $(var1)";' vars: '"var1" string => "test";' l r
  cf-cmd h

You should try out those examples at the end to see what they do. An example interactive session looks like this (I have bolded the inputs to make them easier to see):

$ cf-cmd 
reports: > "this is a test";
reports: > list
body common control {
   inputs => { "/var/cfengine/inputs/" };
   bundlesequence => { "test" };

bundle agent test
  "this is a test";
reports: > run
-> Running policy with 'cf-agent -KI -f ./'
R: this is a test
reports: > clear
reports: > l    (abbreviation of "list")
body common control {
   inputs => { "/var/cfengine/inputs/" };
   bundlesequence => { "test" };

bundle agent test
reports: > files: 
-> Switching to files: promise type.
files: > "/tmp/test"
files: >   create => "true",
files: >   classes => if_repaired("done");
files: > reports: 
-> Switching to reports: promise type.
reports: > done::
reports: > "Success";
reports: > l
body common control {
   inputs => { "/var/cfengine/inputs/" };
   bundlesequence => { "test" };

bundle agent test
    create => "true",
    classes => if_repaired("done");
reports: > run
-> Running policy with 'cf-agent -KI -f ./'
 -> Created file /tmp/test, mode = 600
R: Success
reports: > 

The interactive prompt supports editing and completion of all commands and promise types - press Tab to view available completions.

You can download the script {% gist 1525722 %}.

Just put it somewhere in your path. If needed, modify the location of the file on your system (by default it looks for it under /var/cfengine/inputs/). You need Ruby installed (I tested with version 1.9.3).

If you find it useful, or if you find any problems or have any suggestions, please let me know. I'd be happy to hear from you.