Add audit and reports page, and a change journal

ProxMenux modifies the host: it rewrites configuration files, installs packages, enables services. Until now nobody could say afterwards what had changed, and showing the script does not answer that question — a four-hundred-line function may alter two values, and the reader has no way to know which two. This adds the two halves of an answer.

The change journal records what ProxMenux does as it does it. Eleven bash primitives capture the previous state, apply the change and record it in the same step, writing to a spool that the Monitor reads back. One hundred and thirteen functions across twenty-five scripts are instrumented, covering post-install, shared storage, security tooling, container conversions, disk operations and the PVE 8 to 9 upgrade path. The page shows the difference — rotate 7 becoming rotate 14 — and never the script. Restore and backup scripts are deliberately left out: a restore puts the host back to a state some other script already recorded.

The Audit and reports page answers the other half: what state is this host in, regardless of who put it there. Forty-three checks across seven areas read the host and classify each result as critical, warning, observation, conformant, unverified or not applicable, with the evidence they read attached to each one. A declared policy lets the reader say what this particular host is expected to do — which guests must have a backup, which storages are essential — so the report judges the host against its own intent rather than a generic template. An inventory records the hardware, network and guest topology behind those readings, a comparison shows what moved between two runs, and six report profiles produce a printable document scoped to what the reader needs. Everything is available in the eight supported languages.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
MacRimi
2026-09-08 21:06:04 +02:00
co-authored by Claude Opus 5
parent ae75508eff
commit da8a480eff
102 changed files with 24118 additions and 1403 deletions
+24 -5
View File
@@ -41,7 +41,16 @@ PROXMENUX_UTILS=(
# Ensure APT repositories are configured for the current PVE version.
# Creates missing no-subscription repo entries for PVE8 (bookworm) or PVE9 (trixie).
# Shared journal helpers, so any script sourcing this file records what
# it installs without arranging for it.
if [[ -f "${LOCAL_SCRIPTS:-/usr/local/share/proxmenux/scripts}/global/pmx_journal.sh" ]]; then
source "${LOCAL_SCRIPTS:-/usr/local/share/proxmenux/scripts}/global/pmx_journal.sh"
fi
ensure_repositories() {
local FUNC_VERSION="1.0"
pmx_journal_context "ensure_repositories" "$FUNC_VERSION"
local pve_version need_update=false
pve_version=$(pveversion 2>/dev/null | grep -oP 'pve-manager/\K[0-9]+' | head -1)
@@ -57,7 +66,7 @@ ensure_repositories() {
# 0640, which the PVE 9 webgui's repository manager treats as
# unparseable and silently hides the source — issue #230.
if [[ ! -f /etc/apt/sources.list.d/proxmox.sources ]]; then
cat > /etc/apt/sources.list.d/proxmox.sources <<'EOF'
pmx_write_file /etc/apt/sources.list.d/proxmox.sources <<'EOF'
Enabled: true
Types: deb
URIs: http://download.proxmox.com/debian/pve
@@ -70,7 +79,7 @@ EOF
fi
if [[ ! -f /etc/apt/sources.list.d/debian.sources ]]; then
cat > /etc/apt/sources.list.d/debian.sources <<'EOF'
pmx_write_file /etc/apt/sources.list.d/debian.sources <<'EOF'
Types: deb
URIs: http://deb.debian.org/debian/
Suites: trixie trixie-updates
@@ -96,19 +105,20 @@ EOF
echo "deb http://deb.debian.org/debian bookworm main contrib non-free non-free-firmware"
echo "deb http://deb.debian.org/debian bookworm-updates main contrib non-free non-free-firmware"
echo "deb http://security.debian.org/debian-security bookworm-security main contrib non-free non-free-firmware"
} >> "$sources_file"
} | pmx_append_file "$sources_file"
need_update=true
fi
if [[ ! -f /etc/apt/sources.list.d/pve-no-subscription.list ]]; then
echo "deb http://download.proxmox.com/debian/pve bookworm pve-no-subscription" \
> /etc/apt/sources.list.d/pve-no-subscription.list
| pmx_write_file /etc/apt/sources.list.d/pve-no-subscription.list
need_update=true
fi
fi
if [[ "$need_update" == true ]] || [[ ! -d /var/lib/apt/lists || -z "$(ls -A /var/lib/apt/lists 2>/dev/null)" ]]; then
msg_info "$(translate "Updating APT package lists...")"
pmx_record_execution "Update APT package lists" "apt-get update"
apt-get update >/dev/null 2>&1 || apt-get update
# Spinner pair: msg_info must be closed before returning.
# Without this the next `msg_info` caller spawns a second
@@ -132,7 +142,16 @@ install_single_package() {
msg_info "$(translate "Installing") $package${description:+ ($description)}..."
local install_success=false
if DEBIAN_FRONTEND=noninteractive apt-get install -y "$package" >/dev/null 2>&1; then
# Every script that installs anything comes through here, so this is
# where an installation becomes visible in the audit. What gets
# recorded is the difference the operation made — the packages that
# were not on the host and now are, dependencies included — rather
# than the name that was asked for.
if declare -F pmx_install_pkg >/dev/null 2>&1; then
PMX_JOURNAL_FUNCTION="${PMX_JOURNAL_FUNCTION:-install_single_package}" \
PMX_JOURNAL_SOURCE="${PMX_JOURNAL_SOURCE:-${SCRIPT_SOURCE:-utils-install-functions.sh}}" \
pmx_install_pkg "$package" && install_success=true
elif DEBIAN_FRONTEND=noninteractive apt-get install -y "$package" >/dev/null 2>&1; then
install_success=true
fi
cleanup 2>/dev/null || true