Using Razor on Docker

Table of Contents

Puppetlabs Razor installs machines from bare metal and hands off to 'brokers' to provision.

There are a few containers out there for it but I had problems with some I tried so built one based off a semi-working centos6.6 image from sedlund (iirc it installed razor with the puppetlabs-razor module which is broken and installs with the wrong version of jruby)

Here's a very brief run through of getting it going, see the razor-server wiki for more detail.

1 Build the container

  • Dockerfile
    # docker-razor
    FROM centos:centos6.6
    COPY install.pp /root/install.pp
    COPY /root/
    RUN yum -y update && \
        rpm -ivh && \
        yum install -y puppet tar razor-server && \
        puppet module install puppetlabs/postgresql && \
        chmod 750 /root/
    ENV  HOSTNAME       razor-server
    ENV  TORQUEBOX_HOME /opt/razor-torquebox
    ENV  PATH           $JRUBY_HOME/bin:$PATH
    EXPOSE 8080
    CMD ["/root/"]
  • install.pp
    # install.pp
    class { '::postgresql::globals':
      manage_package_repo => true,
      version             => '9.2',
    class { '::postgresql::server': }
    postgresql::server::db { 'razor':
      user     => 'razor',
      password => postgresql_password('razor', 'PASS'),
    mkerneltar=`basename $mkernelurl`
    # Setup the postgres DB if it hasnt been.
    if [\[ ! -x /etc/init.d/postgresql-9.2 ]]; then
      mkdir -p /var/lib/pgsql/9.2 2>/dev/null
      puppet apply /root/install.pp
      sed -i -e 's/razor_prd/razor/' -e 's/mypass/PASS/g' /etc/razor/config.yaml
      cd /opt/razor
      jruby bin/razor-admin -e production migrate-database
      torquebox deploy --env production
    # Install the Razor Microkernel, if it hasnt yet.
    if [\[! -e $repodir/microkernel/vmlinuz0]]; then
      cd $repodir
      curl -LO $mkernelurl
      tar xfva $mkerneltar
    /etc/init.d/postgresql-9.2 start && \
      torquebox run --bind-address=

files can be cloned from my github repo.

build the container with docker build -t docker-razor .

We want to run it using a storage container so lets create one:

docker run --name razor-store -v /var/lib/razor/repo-store -v /var/lib/pgsql -v /var/logs busybox true

We want the tasks mounted on the filesystem so we can read/edit them so we run the container with:

docker run --name razor-server --hostname razor-server -d -p 8080:8080 \
 -v /volume1/docker/razor/tasks:/opt/razor/tasks --volumes-from razor-store \

It'll take some time to install postgres, configure and start.

2 Set up pxe/tftp

We'll also need a functional pxe/tftp setup, we need ipxe to load the razor microkernel, for isc-dhcp we can do

host node1 {
  hardware ethernet aa:bb:cc:dd:ee:ff;
  option routers;
  option subnet-mask;
  option broadcast-address;
  if exists user-class and option user-class = "iPXE" {
    filename "";
  } else {
    filename "undionly-20140116.kpxe";
  filename "pxelinux.0";

or you can set grub to boot ipxe (assuming you have ipxe.krn in tftp)

LABEL boot_razor
  MENU LABEL Razor Node Boot
  KERNEL ipxe.krn
  APPEND initrd=bootstrap.ipxe

3 Configure razor

Once razor is running we can use the razor-client to set it all up. We'll need the following:

  • The iPXE bootstrap
    wget -O- >bootstrap.ipxe

    This should live in the tftp root.

  • A repo
    razor create-repo --name ubuntu1404-3 --iso-url --task ubuntu1404-3
  • A broker
    razor create-broker --name puppet --configuration server=puppet.local.lan --configuration environment=production --broker-type puppet
  • A tag
    razor create-tag --name microserver --rule '["=", ["fact", "productname"], "ProLiant MicroServer"]'
  • A policy

    create microserver-policy.json

      "name": "microserver-ubuntu",
      "repo": "ubuntu1404-3",
      "task": "ubuntu/trusty",
      "enabled": true,
      "broker": "puppet",
      "hostname": "host${id}.local.lan",
      "root_password": "password",
      "max_count": 3,
      "tags": ["microserver"]

    add the policy with

    razor create-policy --json microserver.json

4 And install

Once we've booted the new host and the microkernel has loaded we can see it in razor with razor nodes, more info is available with razor nodes node1

We can also add some metadata to the node once discovered so we know what it is since razor will call it host1.local.lan in this example.

razor modify-node-metadata --node node1 --update name=fancy_name

If we want razor to be able to control power state we can give it IPMI access

razor set-node-ipmi-credentials --name node1 --ipmi-hostname bartledan-sc.local.lan --ipmi-username <user> --ipmi-password <pass>

At this point the host should be being installed using the preseeding info found in /volume1/docker/razor/tasks/ubuntu.task. Once installed it should have already sent a cert request for puppet waiting for you to sign (or autosign) to configure the host as you want.

Next steps - create your own preseed.erb task to configure the host the way you want.

Date: 2015-09-15 Tue

Emacs 24.5.1 (Org mode 8.2.10)