Skip to content

Playbook Format

YAML schema reference for Nefia playbook files.

Playbooks define multi-step operations as declarative YAML files. Each playbook contains a sequence of steps that run against target hosts in order, with support for conditionals, retries, and output chaining.

File Structure

A playbook is a single YAML file with three top-level fields:

yaml
name: deploy-app
description: Build and deploy the web application
steps:
  - name: stop-service
    exec: "systemctl stop app"
  - name: deploy-files
    fs_write:
      path: /var/www/app/index.html
      content: "<h1>Deployed</h1>"
  - name: start-service
    exec: "systemctl start app"

Top-Level Fields

FieldTypeRequiredDescription
namestringyesUnique identifier for the playbook. Used in CLI commands and logs.
descriptionstringnoHuman-readable description of what the playbook does.
versionintnoSchema version of the playbook format. Used for forward-compatible parsing.
varsmap[string]stringnoTop-level variables available for template substitution in step commands and content.
stepsstep[]yesOrdered list of steps to execute.

Step Schema

Each step in the steps array supports the following fields:

FieldTypeDefaultDescription
name *stringUnique name for this step. Used in logs and as a reference key for output chaining.
execstringShell command to execute. Exactly one of exec, sudo, fs_write, fs_read, fs_mkdir, fs_remove, fs_chmod, or service must be present.
sudostringCommand to run with sudo privileges.
fs_writeobjectFile write operation with path and content fields.
fs_readobjectFile read operation with path field.
fs_mkdirstringPath of a directory to create (parents are created automatically).
fs_removestringPath to remove (file or directory).
fs_chmodobjectChange file permissions with path and mode fields.
serviceobjectControl a system service with name and action fields.
osstringTarget OS filter: macos, linux, or windows. Step is skipped on non-matching hosts.
whenstringConditional expression. Supports Go templates and simple comparisons (e.g., {{ .Steps.<name>.OK }} == true). Step runs only when the expression evaluates to a non-empty/truthy string.
registerstringStore the step output as a named variable for use in subsequent steps. Name must use [a-zA-Z0-9_] only (no hyphens).
continue_on_errorbooleanfalseIf true, playbook execution continues even if this step fails.
timeout_msint0Per-step timeout in milliseconds. 0 means no timeout (falls back to --step-timeout if set on the CLI).
retryobjectRetry configuration with max_attempts and interval_ms.

Step Types

Executes a shell command on the target host. The exec field contains the command string.

yaml
- name: check-disk
  exec: "df -h /"
  timeout_ms: 10000

Retry Configuration

The retry object controls automatic retry behavior for flaky operations:

FieldTypeDefaultDescription
max_attemptsint1Maximum number of attempts (including the initial try).
interval_msint1000Delay in milliseconds between retry attempts.
yaml
- name: health-check
  exec: "curl -sf http://localhost:8080/health"
  retry:
    max_attempts: 5
    interval_ms: 3000

Template Variables

Playbook fields that accept strings (exec, fs_write.content, when) support Go template syntax. The following variables are available:

Host Variables

VariableDescriptionExample Value
{{.Host.ID}}Host identifier (name)prod-web-1
{{.Host.OS}}Target operating systemlinux
{{.Host.Address}}Host VPN address10.99.0.2

User Variables

Pass variables at runtime with the --var flag:

bash
nefia playbook run deploy.yaml --target group:webservers --var version=2.1.0 --var env=production

Reference them with {{.Vars.<name>}}:

yaml
- name: deploy-artifact
  exec: "wget https://releases.example.com/app-{{.Vars.version}}.tar.gz -O /tmp/app.tar.gz"

Step Output Variables

When a step uses register, its output and exit code become available to subsequent steps:

VariableDescription
{{.Steps.<register_name>.Output}}Standard output captured from the step.
{{.Steps.<register_name>.ExitCode}}Exit code (0 = success).
{{.Steps.<register_name>.OK}}Boolean indicating whether the step succeeded.
{{.Steps.<register_name>.Skipped}}Boolean indicating whether the step was skipped (e.g., by when or os filter).

Only steps that specify a register field are stored in .Steps. The map key is the value of register, not the step name.

yaml
- name: get-version
  exec: "cat /var/www/app/VERSION"
  register: current_version
 
- name: log-version
  exec: 'echo "Current version is {{.Steps.current_version.Output}}"'

Conditional Execution

The when field accepts Go template expressions. A step runs only when the expression produces a non-empty string.

yaml
- name: install-nginx
  exec: "apt-get install -y nginx"
  os: linux
  when: "{{if eq .Host.OS \"linux\"}}true{{end}}"
 
- name: restart-if-changed
  exec: "systemctl restart app"
  when: "{{if ne .Steps.deploy_config.ExitCode 0}}{{else}}true{{end}}"

The os field is a shorthand for OS-based filtering. It is simpler than writing a when expression for the same purpose:

yaml
# These two are equivalent:
- name: restart-launchd
  exec: "launchctl kickstart -k system/com.example.app"
  os: macos
 
- name: restart-systemd
  exec: "systemctl restart app"
  os: linux
 
- name: restart-service-windows
  exec: "Restart-Service -Name app -Force"
  os: windows

Example Playbooks

System Update

yaml
name: system-update
description: Update packages and reboot if required
steps:
  - name: update-packages
    exec: "apt-get update && apt-get upgrade -y"
    os: linux
    timeout_ms: 300000
 
  - name: update-packages-windows
    exec: "choco upgrade all -y"
    os: windows
    timeout_ms: 300000
 
  - name: check-reboot
    exec: '[ -f /var/run/reboot-required ] && echo yes || echo no'
    os: linux
    register: needs_reboot
 
  - name: reboot
    exec: 'shutdown -r +1 "Rebooting for kernel update"'
    os: linux
    when: "{{if eq .Steps.needs_reboot.Output \"yes\"}}true{{end}}"

Application Deployment

yaml
name: deploy-webapp
description: Deploy a new version of the web application
steps:
  - name: download-artifact
    exec: >
      wget -q https://releases.example.com/app-{{.Vars.version}}.tar.gz
      -O /tmp/app-{{.Vars.version}}.tar.gz
 
  - name: stop-service
    exec: "systemctl stop webapp"
 
  - name: extract
    exec: "tar xzf /tmp/app-{{.Vars.version}}.tar.gz -C /var/www/app/"
 
  - name: write-version
    fs_write:
      path: /var/www/app/VERSION
      content: "{{.Vars.version}}"
 
  - name: start-service
    exec: "systemctl start webapp"
 
  - name: health-check
    exec: "curl -sf http://localhost:8080/health"
    retry:
      max_attempts: 5
      interval_ms: 3000

Config Sync with Rollback

yaml
name: config-sync
description: Push configuration with automatic rollback on failure
steps:
  - name: backup-config
    exec: "cp /etc/app/config.yaml /etc/app/config.yaml.bak"
 
  - name: write-config
    fs_write:
      path: /etc/app/config.yaml
      content: |
        server:
          port: {{.Vars.port}}
          workers: 4
        database:
          host: {{.Vars.db_host}}
          name: {{.Vars.db_name}}
 
  - name: validate-config
    exec: "app --validate-config /etc/app/config.yaml"
    continue_on_error: true
    register: validation
 
  - name: rollback-on-failure
    exec: "mv /etc/app/config.yaml.bak /etc/app/config.yaml"
    when: "{{if ne .Steps.validation.ExitCode 0}}true{{end}}"
 
  - name: reload-service
    exec: "systemctl reload app"
    when: "{{if eq .Steps.validation.ExitCode 0}}true{{end}}"

Validating Playbooks

Check a playbook for syntax errors and schema violations before running it:

bash
nefia playbook validate deploy.yaml
nefia playbook validate deploy.yaml

Playbook: deploy-webapp Steps: 6 Template variables required: version

Validation: OK

Running Playbooks

Execute a playbook against a target selector:

bash
nefia playbook run deploy.yaml --target group:webservers --var version=2.1.0
nefia playbook run deploy.yaml

Running: deploy-webapp (6 steps) Target: 3 hosts (group:webservers)

[1/6] download-artifact ... OK (3 hosts, 4.2s) [2/6] stop-service ... OK (3 hosts, 1.1s) [3/6] extract ... OK (3 hosts, 2.3s) [4/6] write-version ... OK (3 hosts, 0.2s) [5/6] start-service ... OK (3 hosts, 1.4s) [6/6] health-check ... OK (3 hosts, 6.8s)

All steps completed successfully on 3/3 hosts.

CLI Reference

Complete reference for playbook-related CLI commands.

Configuration

Configure scheduling, timeouts, and concurrency in nefia.yaml.

Remote Execution

Execute ad-hoc commands with target selectors and concurrency control.