Skip to main content
RunBook Academy

LinuxXXXIV · Configuration ManagementDesired state

Desired state and idempotency - the foundations of CM

Intermediate⏱ ~10 minbash

What you'll learn

  • Define desired state vs imperative commands
  • Explain why idempotency matters
  • Recognise idempotent vs non-idempotent operations
  • Write idempotent CM code

Prerequisites

Verified against Ubuntu 24.04 LTS · Debian 12 (Bookworm) · RHEL 9.x · Rocky Linux 9.x · AlmaLinux 9.x · Linux kernel 6.1 LTS / 6.6 LTS · systemd 255+ · OpenSSH 8.7p1 (RHEL 9) / 9.6p1 (Ubuntu 24.04) · nftables 1.0.x · chrony 4.x · Pacemaker 2.1.x · Corosync 3.1.x · 2026-08-09

Not yet marked complete on this device.

Configuration management works by declaring desired state (“the file should contain X”) and letting the tool enforce it. Idempotency means applying the same configuration twice is safe.

Imperative vs declarative

Imperative (“do this”):

apt install nginx
systemctl start nginx
echo "worker_processes 4;" > /etc/nginx/nginx.conf
systemctl reload nginx

If you run this twice, the result depends on the starting state. If nginx is already installed, fine. If the config file was different, it is overwritten.

Declarative (“the state should be”):

# Ansible
- apt:
    name: nginx
    state: present
- service:
    name: nginx
    state: started
- copy:
    content: |
      worker_processes 4;
    dest: /etc/nginx/nginx.conf
- service:
    name: nginx
    state: reloaded

If you run this twice, the result is the same: nginx is installed, running, with the right config. Running the playbook is idempotent.

Why idempotency matters

  • Safe to re-run: if the playbook crashes halfway, you can re-run it without breaking anything.
  • Drift correction: a drifted host can be brought back to desired state by re-running the playbook.
  • Verification: idempotent operations can be checked after-the-fact; the state is known to be correct.

Non-idempotent operations (e.g. command: rm -rf /tmp/foo) can be destructive if run twice or in the wrong order.

Idempotency patterns

IdempotentNon-idempotent
apt: name=X state=presentcommand: apt install -y X
file: state=touchcommand: touch X
lineinfile: state=presentcommand: echo X >> file
service: state=started enabled=yescommand: systemctl start X
user: state=presentcommand: useradd X

Ansible modules are designed to be idempotent. Shell commands are not. Prefer modules.

Avoid common pitfalls

  • Always run a playbook twice to verify it is idempotent.
  • Never use command for things Ansible has a module for.
  • Never use shell that depends on the order of operations.
  • Always read the diff before applying in production.

Desired state examples

# Package state
- apt:
    name:
      - nginx
      - postgresql-15
    state: present

# Service state
- service:
    name: nginx
    state: started
    enabled: yes

# File state
- copy:
    src: files/nginx.conf
    dest: /etc/nginx/nginx.conf
    owner: root
    group: root
    mode: '0644'

# User state
- user:
    name: deploy
    state: present
    shell: /bin/bash

Each declares what should be true. Ansible figures out how to make it true.

Knowledge check

Knowledge check · 3 questions

  1. Q1. What is the difference between imperative and declarative CM?

  2. Q2. Running an idempotent playbook twice produces the same result.

  3. Q3. Which of the following are idempotent? Select all that apply.

Passing score: 75%. Answers are checked in this browser.