The default target audits the XCP-ng and XOA groups from
//infra/xcp_ng/ansible:inventory. It reuses the owner’s xcpng_host and
xcp_ng_ansible credential selectors. SSH uses the controller’s existing
~/.ssh/known_hosts, requires an ED25519 match, and never adds keys. The
Host Bot configuration owns approved key provisioning and provenance.
XOA’s existing firewall limits new SSH connections, so its transport reuses
one authenticated connection. The controller control socket uses a per-run
mode 0700 /tmp/appliance-ssh.* directory: the workspace’s absolute path
exceeds Linux’s 108-byte Unix-socket limit. The playbook closes the connection
and removes this temporary directory. An unreachable host can prevent Ansible’s
cleanup; ssh-control-directory.txt records the exact controller path for
operator cleanup. Audit evidence remains in the requested workspace directory.
Both appliances use alwaldend.main.lynis_audit with an already installed
Ansible-compatible interpreter. XCP-ng’s host-level interpreter declaration
and earlier manual bootstrap exception belong to the
owner inventory. Ansible reports runtime
failures directly; the audit installs no interpreter or scanner package.
Audit
Create an existing controller-owned mode 0700 report directory. The default audit uses the pinned Lynis archive:
umask 077
mkdir -p out/security/appliances/tmp
TMPDIR="$PWD/out/security/appliances/tmp" \
ANSIBLE_LOCAL_TEMP="$PWD/out/security/appliances/tmp" \
bazel run //infra/security/appliances:ansible -- \
--extra-vars "appliance_report_directory=$PWD/out/security/appliances"
Use --limit xcpng or --limit xoa for one appliance group. Use separate report
directories to compare runs. Each host gets a unique private Lynis result
directory containing scanner reports and the caller’s boot identities.
Files are mode 0600. Scanner exit codes
0 and 78 mean the scan completed; 78 includes warnings. They are not a
finding that a host is uncompromised.
:ansible.status performs only a boot-ID and uptime
probe with one SSH connection per appliance and retains connection failures.
The shared Lynis role
owns archive extraction, the audit profile, private evidence collection, failure
handling, and remote scratch cleanup for both appliances. Its unique result
directory is directly under appliance_report_directory; there is no second
appliance audit lifecycle. Set lynis_audit_timeout_seconds to change the
shared role’s default bound. The caller records before/after boot identities
and the XOA connection recovery path there after the role returns, including
scanner failures. An interruption can prevent these final observations; it
does not establish an unchanged boot or a completed audit. Raw status and boot
checks remain available without the audit’s Python runtime.
The local-only :syntax target checks the playbooks without AL
authentication or a host connection. Building :ansible_bin checks packaging;
neither is a substitute for inspecting a successful live audit’s evidence.
Package updates
Auditing never selects an update playbook. The separate
:ansible.update_xcpng and :ansible.update_xoa targets require
appliance_report_directory and explicit operator authorization for the
selected mutation. Both preserve and compare boot IDs.
The XCP-ng path permits only a single-host XCP-ng 8.3 pool coordinator with
HA off, no active XAPI tasks, no XOSTOR, no attached CD media, and no
unreviewed yum-cron. It records the host’s enabled state, temporarily disables
new VM placement, and runs yum update using only the stable
xcp-ng-base and xcp-ng-updates repositories with signature/TLS verification
intact. After successful package installation it invokes the vendor
xe-toolstack-restart, waits for XAPI readiness, and restores the original
enabled state. Existing guests are not evacuated, stopped, or rebooted.
Restoration is also attempted after failure when XAPI responds; failure to
recover XAPI is reported rather than claiming restoration. Kernel and
hypervisor fixes can remain inactive until a separately authorized host reboot.
This vendor yum workflow remains on raw transport. A newer Ansible interpreter does not provide the vendor Python’s yum module bindings or replace its maintenance procedure.
If the selected download mirror fails, set
appliance_xcpng_use_origin_mirror=true to select the vendor’s documented
https://updates.xcp-ng.org origin for this transaction. The override applies
only to the same stable 8.3 repositories and preserves signature and TLS
verification; it does not change installed repository configuration. See the
vendor mirror documentation.
The XCP-ng vendor procedure
documents the disable, yum update, control-plane restart, and enable sequence
without a host reboot. It requires pool coordinator ordering and HA precautions.
Its Rolling Pool
Update procedure reboots hosts and therefore cannot satisfy a no-reboot run.
The CLI reference
directs package maintenance to yum instead of xe update-*. Multi-host and
XOSTOR maintenance require a separately reviewed coordinated workflow.
The XOA path verifies Debian and invokes the shared package-update role using
the existing interpreter and APT bindings. Missing bindings fail rather than
being installed implicitly. The role installs the
authorized standard unattended-upgrades component if needed and configures
native OS automatic updates with immediate and automatic reboots disabled.
The XOA application updater is
separate from Debian OS maintenance. Its installed version and unattended
reboot semantics must be verified before application automation is changed.
This workflow does not claim or enable application automatic updates. Native
unattended XCP-ng updates meeting the pool and no-reboot constraints have not
been established; appliance_automatic_updates=true fails before mutation.
ClamAV scans
The independent :clamav target reuses the appliance inventory and authentication
but defaults to XOA only. XCP-ng remains unscanned because the official native
ClamAV payload requires a newer glibc. This does not change either appliance’s
Lynis or package-update workflow.
Follow the ClamAV invocation instructions, selecting
//infra/security/appliances:clamav and including localhost in any limit, such
as --limit 'localhost,xoa'. The shared native role streams endpoint data to
the private controller; its signature cache and bounded transient unit are
owned by the controller package. :clamav_syntax checks
this playbook locally without authentication or live scanning.