Stage 1 base config/hardening toolset, applied and verified on pve1

Splits the repo into Stage 1 (base host config/hardening, applies to any
node) and Stage 2 (future HA/Ceph cluster, deferred - pve1's mini-PC
hardware can't support the assumed split-disk/multi-NIC layout).

Adds the Stage 1 toolset: firewall deploy, named admin user creation,
unattended security upgrades, subscription-nag removal (with an apt hook
so the patch survives package updates), and a read-only audit script.
Fixes switch-to-no-subscription-repo.sh, which only handled the legacy
.list format and silently no-op'd against PVE 9's deb822 .sources files;
it now removes enterprise sources outright rather than commenting them
out. Shared logic (root check, idempotent file writes, backups) factored
into scripts/lib/common.sh.

Ran the full sequence against pve1 via scripts/bootstrap.sh +
create-admin-user.sh; scripts/audit.sh confirms all checks pass.
This commit is contained in:
beatzaplenty committed 2026-07-21 05:44:50 +00:00
1 parent 24a0047fa8
commit 2cca6a7dc0
17 files changed
+625 -97

No files matched your search

+34 -25
View File
@@ -1,33 +1,42 @@
#!/bin/bash
# Switch a fresh Proxmox VE install from the enterprise repo (which fails
# on apt update without a paid subscription) to the no-subscription repo.
# Remove the Proxmox/Ceph enterprise apt sources (which fail on apt update
# without a paid subscription) and switch to the no-subscription repo.
# Handles both the legacy one-line .list format and the deb822 .sources
# format current PVE installers write.
# Idempotent - safe to re-run. Run as root on the PVE host.
set -euo pipefail
if [ "$(id -u)" -ne 0 ]; then
echo "Must run as root." >&2
exit 1
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck source=lib/common.sh
source "${SCRIPT_DIR}/lib/common.sh"
require_root
SOURCES_DIR="/etc/apt/sources.list.d"
# Any sources file pointing at the enterprise host gets moved out of apt's
# way entirely (renamed .disabled) rather than commented out in place -
# apt only reads *.sources/*.list, so this fully removes it from
# consideration while keeping a copy on disk for reference.
for f in "${SOURCES_DIR}"/*.sources "${SOURCES_DIR}"/*.list; do
[ -f "$f" ] || continue
grep -qi 'enterprise.proxmox.com' "$f" 2>/dev/null || continue
mv "$f" "${f}.disabled"
echo "Removed enterprise source (renamed to .disabled): $f"
done
write_if_changed "${SOURCES_DIR}/pve-no-subscription.sources" "Types: deb
URIs: http://download.proxmox.com/debian/pve
Suites: $(pve_codename)
Components: pve-no-subscription
Signed-By: /usr/share/keyrings/proxmox-archive-keyring.gpg"
# Clean up a legacy-format no-subscription file from a previous run of an
# older version of this script, to avoid two sources for the same repo.
LEGACY_NOSUB="${SOURCES_DIR}/pve-no-subscription.list"
if [ -f "$LEGACY_NOSUB" ]; then
rm -f "$LEGACY_NOSUB"
echo "Removed superseded $LEGACY_NOSUB"
fi
CODENAME="$(. /etc/os-release && echo "$VERSION_CODENAME")"
ENTERPRISE_LIST="/etc/apt/sources.list.d/pve-enterprise.list"
if [ -f "$ENTERPRISE_LIST" ]; then
sed -i 's/^deb/#deb/' "$ENTERPRISE_LIST"
echo "Disabled $ENTERPRISE_LIST"
fi
CEPH_ENTERPRISE_LIST="/etc/apt/sources.list.d/ceph.list"
if [ -f "$CEPH_ENTERPRISE_LIST" ] && grep -q enterprise "$CEPH_ENTERPRISE_LIST" 2>/dev/null; then
sed -i 's/^deb/#deb/' "$CEPH_ENTERPRISE_LIST"
echo "Disabled $CEPH_ENTERPRISE_LIST"
fi
NOSUB_LIST="/etc/apt/sources.list.d/pve-no-subscription.list"
cat > "$NOSUB_LIST" <<EOF
deb http://download.proxmox.com/debian/pve ${CODENAME} pve-no-subscription
EOF
echo "Wrote $NOSUB_LIST for codename '${CODENAME}'."
apt-get update
echo "Repo switched. Review 'apt list --upgradable' before upgrading."