Added local user support.
Current sample config file.
# Example xo-apply configuration.
# Copy this into your own PRIVATE repo, edit, then:
# export XO_URL=https://xo.example.lan XO_TOKEN=...
# xo-apply diff config.yaml
# xo-apply apply config.yaml
#
# Secrets never go in this file: use ${env:VAR_NAME} placeholders,
# resolved from environment variables when the tool runs.
#
# A section that is ABSENT is unmanaged (xo-apply won't touch or report that
# resource type). A present-but-empty section means "manage this type, none
# should exist" (only deleted when you pass --prune).
remotes:
# NFS share on a NAS
- name: nas-backups
type: nfs
host: 192.168.1.50
path: /export/xo-backups
# port: 2049 # optional
# mountOptions: vers=4 # optional mount(8) options
# SMB / Windows share β host is "HOST\share" (single backslash in YAML
# double-quoted strings must be written as \\)
- name: windows-share
type: smb
host: "192.168.1.60\\backups"
domain: WORKGROUP
username: backup
password: ${env:SMB_BACKUP_PASSWORD}
# path: xo # optional subfolder inside the share
# S3-compatible object storage (AWS, MinIO, Backblaze B2, ...)
- name: offsite-s3
type: s3
host: s3.us-east-1.amazonaws.com
path: my-bucket/xo-backups # bucket/directory
accessKey: AKIAEXAMPLE
secretKey: ${env:S3_SECRET_KEY}
region: us-east-1
# protocol: http # for http-only endpoints (e.g. local MinIO)
# Directory local to the XO VM (e.g. a mounted USB disk)
- name: local-disk
type: local
path: /mnt/backup-disk
backupJobs:
# Delta (incremental) backup of every VM tagged "critical", every night
- name: nightly-critical
mode: delta
vms:
tag: critical
remotes: [nas-backups, offsite-s3]
settings: # optional global job settings, passed through to XO
concurrency: 2
# timezone: America/New_York
# maxExportRate: 104857600 # bytes/s
# nRetriesVmBackupFailures: 2
# reportWhen: failure
schedules:
- name: nightly
cron: "0 2 * * *"
retention: 14 # backups kept on the remotes
# snapshotRetention: 3 # snapshots kept on the pool
# timezone: America/New_York
# enabled: false # schedules are enabled by default
# Weekly full backup of specific VMs, selected by name
- name: weekly-full
mode: full
compression: zstd
vms:
names: [dc-01, mail-01]
# ...or select by uuid: uuids: [770aa52a-fd42-8faf-f167-8c5c4a237cac]
# ...or pass a raw XO smart-mode pattern for anything more complex:
# raw:
# type: VM
# tags:
# __or: [[prod]]
remotes: [nas-backups]
schedules:
- name: weekly
cron: "0 3 * * 0"
retention: 8
# Disaster Recovery / Continuous Replication: instead of (or in addition to)
# remotes, target one or more SRs. mode:full => DR, mode:delta => CR.
- name: dr-critical
mode: full # delta = Continuous Replication
vms:
tag: critical
srs: [4991d4aa-ed84-599b-7d19-97f2f943a366] # target SR UUID(s)
# remotes: [] # SR-only is fine; may be combined with remotes
schedules:
- name: hourly-dr
cron: "0 * * * *"
retention: 3 # replicas kept on the SR
# Metadata backups: pool metadata and/or XO's own configuration.
metadataBackups:
- name: xo-config
xoMetadata: true # back up XO's own config
pools: [939ed551-fbd6-9868-52d8-d3997b7bf7da] # pool UUID(s) for pool metadata
remotes: [nas-backups]
schedules:
- name: daily
cron: "0 21 * * *"
xoRetention: 7 # XO metadata backups kept
poolRetention: 7 # pool metadata backups kept
# Mirror backups: copy an existing remote's backups onto other remote(s),
# e.g. push local backups offsite to S3.
mirrorBackups:
- name: offsite-mirror
mode: full # full or delta, to match the source backups
sourceRemote: nas-backups
remotes: [offsite-s3]
schedules:
- name: nightly-mirror
cron: "0 5 * * *"
retention: 14
# Sequences: run backup schedules one after another. Each step names a job and
# one of its schedules (from any job kind above, or already in XO). The sequence
# has its own cron for when the whole chain runs.
sequences:
- name: nightly-then-metadata
steps:
- { job: nightly-critical, schedule: nightly }
- { job: xo-config, schedule: daily }
cron: "0 22 * * *"
# enabled: false # sequences are enabled by default
# timezone: America/New_York
# Local users (XO's internal auth provider). Users created by an external auth
# plugin (LDAP/SAML/GitHub) are NOT managed here and are never pruned.
#
# Passwords are write-only: XO never returns them, so a real password can't be
# exported or diffed β but XO REQUIRES a password to create a user. So `export`
# writes the placeholder `password: ChangeMe` for every user.
# β οΈ CHANGE these before importing into a real XO (or use a ${env:...} ref),
# otherwise every new user is created with the password "ChangeMe".
# The password is only used when a user is CREATED; for an existing user it is
# ignored (change it in the XO UI). Only `permission` is compared for drift.
users:
- email: ops@example.com
password: ChangeMe # required by XO; change before import
permission: admin # none | read | write | admin (default: none)
# Local groups. Members are referenced by email and resolved to ids at apply
# time; each member must be a user defined above or already present in XO.
groups:
- name: operators
users: [ops@example.com]