Back to blogNew in 0.3 · Open Source

    Unattended Windows backup deployment with Ansible

    New in Nimbus Backup 0.3: install and configure Windows-to-PBS backup entirely from files, no clicks. Two paths (CLI + service/GUI), reliable exit codes, ready-to-use Ansible playbooks.

    9 min read

    This is the headline feature of Nimbus Backup 0.3: the Windows backup client for Proxmox Backup Server can now be installed and fully configured from files, with no interactive step at all.

    It's built for Ansible — but works the same with any config-management tool (Salt, DSC, GPO, a login script). It's the argument that was missing to roll out backup across a fleet of workstations and servers. Two paths exist: pick the one that matches your orchestration.

    Nothing changes in the usual interactive workflow: this guide is for teams that want to deploy at scale, without opening the GUI on every machine. Everything below relies on the examples shipped in the repository, under examples/automation/.

    Path A — Command line (recommended for IaC)

    A single JSON file carries everything a backup needs (server address, token, SSL fingerprint, datastore, namespace…); scheduling is delegated to the Windows Task Scheduler. This is the most deterministic approach for pure infrastructure-as-code.

    {
      "baseurl": "https://pbs.example.net:8007",
      "certfingerprint": "AA:BB:CC:...",
      "authid": "ansible@pbs!deploy",
      "secret": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
      "datastore": "myDatastore",
      "namespace": "clients/acme",
      "backup-id": "srv-files",
      "backupdir": "C:",
      "usevss": true
    }

    Run:

    directorybackup.exe --config "C:\ProgramData\NimbusBackup\backup.json"
    • One config file holds every field (PBS connection, folders, VSS, exclusions…).
    • Every field can be overridden by a CLI flag (flags win over the file) — handy for a shared template with per-host overrides.
    • Exit codes are reliable, so your orchestrator detects failures unambiguously.

    Exit codes — the backbone of automation

    CodeMeaning
    0Success
    1Fatal failure (connection, authentication, mail…)
    2Another backup is already running (lock)
    3Completed partially — some files were unreadable, the snapshot is incomplete

    The example playbook ansible/deploy-cli.yml (with the template cli-single-config.json.j2) copies the binary, renders the config, and registers a daily scheduled task (win_scheduled_task) running as SYSTEM at highest run level — required for VSS to work.

    - name: Daily backup (Task Scheduler)
      community.windows.win_scheduled_task:
        name: NimbusBackup-Daily
        actions:
          - path: 'C:\Program Files\NimbusBackup\directorybackup.exe'
            arguments: '--config "C:\ProgramData\NimbusBackup\backup.json"'
        triggers:
          - type: daily
            start_boundary: '2026-01-01T02:30:00'
        username: SYSTEM
        run_level: highest   # required for VSS
        state: present
        enabled: true

    Path B — Service/GUI (MSI): one file for connection and schedule

    The MSI installs a Windows service. Since 0.3, a single config.json can carry the PBS connection, the backup settings and the schedule, via a scheduled_jobs array. On (re)start the service reconciles those jobs into its store and auto-computes each nextRun: you never compute timestamps in your template.

    {
      "pbs_servers": {
        "default": {
          "id": "default",
          "baseurl": "https://pbs.example.net:8007",
          "certfingerprint": "AA:BB:CC:...",
          "authid": "ansible@pbs!deploy",
          "secret": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
          "datastore": "myDatastore",
          "namespace": "clients/acme"
        }
      },
      "default_pbs_id": "default",
      "usevss": true,
      "scheduled_jobs": [
        {
          "id": "nightly-c",
          "name": "Nightly C:",
          "scheduleTime": "02:30",
          "enabled": true,
          "backupType": "host",
          "backupDirs": ["C:"],
          "backupId": "srv-files",
          "useVSS": true,
          "compression": "fastest"
        }
      ]
    }

    In three moves:

    1. Drop the file at C:\ProgramData\NimbusBackup\config.json.
    2. Restart the NimbusBackup service.
    3. Done — jobs are picked up, nextRun values computed.

    Example playbook: ansible/deploy-gui-service.yml (with the template ansible/gui-service-config.json.j2). Drop the file, notify a service restart, done:

    - name: Unified config (connection + schedule)
      ansible.windows.win_template:
        src: config.json.j2
        dest: 'C:\ProgramData\NimbusBackup\config.json'
      notify: Restart NimbusBackup
    
    # handlers
    - name: Restart NimbusBackup
      ansible.windows.win_service:
        name: NimbusBackup
        state: restarted

    Idempotency: re-running the playbook breaks nothing

    Jobs are matched by id. Re-pushing the same config upserts — no duplicates.

    An unchanged schedule is not re-fired: a still-valid nextRun is kept.

    Jobs created by hand in the GUI (whose id you don't list) are left untouched.

    If id is omitted, it is derived deterministically from the job name.

    Field reference

    Connection (pbs_servers[*])

    KeyNotes
    baseurlhttps://host:8007
    certfingerprintSHA-256 fingerprint (AA:BB:…); required for self-signed certs
    authidPBS API token, e.g. user@pbs!token
    secretToken secret (keep in Ansible Vault)
    datastoreTarget datastore
    namespaceOptional namespace

    Need to create the token first? See Managing PBS datastore API tokens.

    Scheduled job (scheduled_jobs[*], service/GUI path)

    KeyNotes
    idStable id; derived from name if omitted
    nameDisplay name
    scheduleTimeHH:MM, 24h, local time
    enabledMust be true to run
    backupTypehost (folders) or vm (whole machine)
    backupDirsList of paths, e.g. ["C:"]
    useVSSVSS-consistent snapshot
    compressionfastest | default | better | best
    excludeListOptional exclusion patterns
    runAtStartupAlso run once at service start
    nextRunOptional — auto-computed if empty

    Secrets: never commit a real token

    • Use Ansible Vault ({{ vault_pbs_secret }} in the examples).
    • On disk, config.json is written 0600.
    • The token is stripped before it ever reaches the GUI frontend.

    Which path should you pick?

    Path A — CLI

    Pure IaC, an orchestrator that already handles scheduling (Task Scheduler, remote cron, pipeline). Reliable exit codes, per-flag overrides. The most deterministic.

    Path B — Service/GUI

    You want a resilient Windows service (survives reboot and sleep), internal scheduling and a single file to push. Idempotent reconciliation, coexists with jobs created by hand.

    Get the client and the examples

    Open Source (GPL-3.0) · Ansible playbooks and Jinja2 templates included

    New to the Windows client? Start with the open-source GUI client guide (install, VSS, first backup), then come back here to industrialize it. For a real, measured case, see the first 1 TB production backup case study.

    A managed PBS to receive these backups

    Automated deployment pushes the backups; you still need a reliable destination. NimbusBackup provides a hosted, updated and backed-up Proxmox Backup Server, ready to receive your Windows workstations and servers.