No description
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
cpetrault adf1f9106c
✨ feat: add interactive Proxmox Backup Server 3 to 4 upgrade script
Port of the pve8to9-upgrade.sh approach to PBS, following the official
wiki: preflight checks (root, PBS 3.x, detachable session, interrupted
upgrade resume, running tasks, free space), backup of /etc/proxmox-backup,
update to the latest 3.4, pbs3to4 checklist, optional read-only maintenance
mode on the datastores, apt repository switch to trixie in deb822 format,
dist-upgrade, post-upgrade checks and DKMS check for the kernel that will
boot. Hosts with Proxmox VE co-installed are refused.

Unit tests cover the pure helpers (version comparison, apt sources
handling, JSON parsing of tasks and datastores).
2026-09-16 11:53:39 +02:00
tests ✨ feat: add interactive Proxmox Backup Server 3 to 4 upgrade script 2026-09-16 11:53:39 +02:00
.env.example ♻️ refactor: drop remote prefix from CLOUD_LOG_PATH 2026-05-25 19:27:26 +00:00
.gitignore 📝 docs: add README, fill in LICENSE, untrack superpowers docs 2026-09-14 13:55:18 +02:00
disable_swap.sh 🐛 fix: address bugs found in code review 2026-05-21 22:25:53 +00:00
exec-all 🐛 fix: address bugs found in code review 2026-05-21 22:25:53 +00:00
fix_chrony_notify.sh ✨ feat: ajoute un script de réparation de chrony après migration majeure 2026-07-28 20:02:00 +02:00
install_proxsave_rclone.sh ✨ feat: let proxsave setup reuse an existing rclone remote 2026-09-14 13:53:32 +02:00
LICENSE 📝 docs: add README, fill in LICENSE, untrack superpowers docs 2026-09-14 13:55:18 +02:00
lxc-exec 🐛 fix: address bugs found in code review 2026-05-21 22:25:53 +00:00
mise.toml ✨ feat: automatise la migration Ceph Quincy→Squid avant l'upgrade PVE 9 2026-07-28 16:10:11 +02:00
pbs3to4-upgrade.sh ✨ feat: add interactive Proxmox Backup Server 3 to 4 upgrade script 2026-09-16 11:53:39 +02:00
pve8to9-upgrade.sh 🛡️ fix: refuse le hors-tmux, reprend une migration interrompue, contrôle DKMS 2026-07-28 20:04:22 +02:00
pve_clean.sh ✨ Add script to clean proxmox 2026-07-29 09:57:35 +02:00
README.md ✨ feat: add interactive Proxmox Backup Server 3 to 4 upgrade script 2026-09-16 11:53:39 +02:00
remove_openssh.sh ✨ Add script to remove all openssh-servers 2026-04-15 16:53:48 +02:00
updater.sh 🔥 Remove ozh update 2026-09-02 20:18:39 +02:00

proxmox_scripts

Maintenance scripts for self-hosted Proxmox VE and Proxmox Backup Server nodes: LXC mass update, PVE 8 → 9 and PBS 3 → 4 migrations, kernel cleanup, backup setup and a few one-shot fixes.

Everything is plain bash, meant to be run as root, directly on the PVE node. No daemon, no agent, no dependency beyond what a standard PVE install already ships (pct, qm, vzdump, whiptail).

Install

git clone ssh://git@git.deditoolbox.fr:22226/freesker/proxmox_scripts.git
cd proxmox_scripts
cp .env.example .env      # only needed for updater.sh and install_proxsave_rclone.sh
chmod +x *.sh lxc-exec exec-all

Scripts

Script What it does
updater.sh Snapshots, updates and cleans every LXC container of the node
pve8to9-upgrade.sh Interactive, step-by-step migration from Proxmox VE 8 to 9
pbs3to4-upgrade.sh Interactive, step-by-step migration from Proxmox Backup Server 3 to 4
pve_clean.sh Purges old PVE kernels to free /boot
fix_chrony_notify.sh Repairs chronyd failing to start after a PVE 9 migration
install_proxsave_rclone.sh Installs proxsave + rclone and configures an SFTP backup remote
remove_openssh.sh Uninstalls openssh-server from every LXC container
disable_swap.sh Sets swap: 0 in every LXC configuration file
lxc-exec / exec-all Runs a command in one / in every running container

updater.sh

Loops over the LXC containers of the node and, for each of them:

  1. prunes before-update* snapshots older than 7 days, but only when more than two of them exist;
  2. takes a new before-updateN snapshot — or falls back to vzdump on the storage defined by STORAGE when the container's storage has no snapshot support;
  3. starts the container if it was stopped;
  4. runs the distribution upgrade (apt, apk, dnf, pacman depending on ostype);
  5. updates the Docker stacks that were running when the script started — a /root/**/update_docker.sh script takes precedence over the default docker compose pull && down && up -d && system prune;
  6. purges caches, logs and apt lists, then runs pct fstrim;
  7. reboots the container if /var/run/reboot-required exists, or shuts it down again if it was stopped initially.

Only debian and ubuntu containers are processed; the others are skipped. At startup the script checks its own git remote and re-execs itself if a newer version is available. The full session is logged to /tmp/lxd-updater-<date>.

./updater.sh              # interactive: whiptail menu to pick containers to skip
./updater.sh -i           # non-interactive, process every container
./updater.sh -i 101 105   # non-interactive, skip containers 101 and 105

pve8to9-upgrade.sh

Guided migration of a single node from Proxmox VE 8 to 9, following the official procedure. The script pauses before every critical step and never reboots on its own.

Steps: preflight checks → backup of /etc → upgrade to the latest PVE 8.4 → Ceph migration (Quincy → Reef → Squid) → pve8to9 checklist → apt repository switch (bookworm → trixie) → dist-upgrade → post-upgrade checklist.

It refuses to start outside a detachable session (tmux or screen): an SSH drop during the dist-upgrade leaves apt stuck on a debconf question asked to a dead terminal, and the node half-migrated. An interrupted migration is detected on the next run and can be resumed instead of restarted.

On a cluster, run the Ceph migration manually on each node beforehand — the script only handles the single-node case.

tmux new -s pve8to9
./pve8to9-upgrade.sh

Logs land in /var/log/pve8to9-upgrade/, configuration backups in /root/pve8to9-backup-<timestamp>/.

pbs3to4-upgrade.sh

Guided in-place upgrade of a Proxmox Backup Server host from 3 to 4, following the official procedure. Same philosophy as pve8to9-upgrade.sh: the script pauses before every critical step, never reboots on its own, refuses to start outside tmux / screen, and resumes an interrupted upgrade on the next run.

Steps: preflight checks (root, PBS 3.x, running tasks, free space) → backup of /etc/proxmox-backup and /etc → upgrade to the latest PBS 3.4 → pbs3to4 checklist → optional read-only maintenance mode on every datastore → apt repository switch (bookworm → trixie, deb822 files) → dist-upgrade → post-upgrade checklist and service status → DKMS check for the kernel that will boot.

Datastores put in read-only mode by the script are listed again at the end, with the exact commands to lift the mode after the reboot. Hosts where Proxmox VE is co-installed are refused: both products must then be upgraded together, by hand.

tmux new -s pbs3to4
./pbs3to4-upgrade.sh

Logs land in /var/log/pbs3to4-upgrade/, configuration backups in /root/pbs3to4-backup-<timestamp>/.

pve_clean.sh

Derived from pvekclean v2.0.2 by Jordan Hillis (MIT). Lists the installed PVE kernels, keeps the running one and purges the others (image + headers), then runs update-grub. Useful before a major upgrade: a full /boot makes apt fail in the middle of a dist-upgrade.

./pve_clean.sh                # interactive
./pve_clean.sh --dry-run      # simulate, remove nothing (do this first)
./pve_clean.sh --keep 2       # keep the 2 most recent kernels
./pve_clean.sh --force        # no confirmation (cron)
./pve_clean.sh --remove-newer # also allow purging kernels newer than the running one
./pve_clean.sh --scheduler    # schedule the purge through cron

Two inherited behaviours worth knowing: the script offers to overwrite itself with the upstream version from GitHub (set check_for_updates=false to disable), and to install itself into /usr/local/sbin/pvekclean.

fix_chrony_notify.sh

After a migration to PVE 9 (Debian 13, systemd 257), chronyd can fail with Fatal error : Could not send notification to $NOTIFY_SOCKET, leaving the node without time synchronisation. The script installs a systemd drop-in switching the unit to Type=simple, and only does so when the failure signature matches.

./fix_chrony_notify.sh           # diagnose, fix if needed, verify sync
./fix_chrony_notify.sh --check   # diagnose only, change nothing
./fix_chrony_notify.sh --revert  # remove the drop-in and retest

install_proxsave_rclone.sh

Installs rclone and proxsave, then configures an SFTP remote end to end:

  1. prompts for remote name, host, port and user;
  2. generates a dedicated ed25519 key pair and prints the public key, so it can be added to the server's authorized_keys before continuing;
  3. tests the remote in read and write mode — a real upload in both the backup and the log directory, re-downloaded and compared byte for byte;
  4. writes CLOUD_REMOTE, CLOUD_REMOTE_PATH, CLOUD_LOG_PATH and WEBHOOK_HEALTHCHECK_URL into /opt/proxsave/configs/backup.env.

Any PROXSAVE_* variable missing from .env is prompted at runtime.

./install_proxsave_rclone.sh

remove_openssh.sh

Purges openssh-server from every LXC container (apt, apk or dnf depending on the OS). Stopped containers are started, cleaned, then shut down again; templates are skipped. A whiptail menu allows excluding containers, and the session is logged to /tmp/remove-openssh-<date>.

disable_swap.sh

Rewrites swap: 0 in every /etc/pve/nodes/*/lxc/*.conf. Containers must be restarted for the change to apply.

lxc-exec / exec-all

source lxc-exec && lxc-exec 101 "apt update"   # one container, by ID
./exec-all "apt update"                        # every running container

Configuration

Copy .env.example to .env and adjust it. .env is git-ignored; it is sourced by updater.sh and install_proxsave_rclone.sh from the script directory.

Variable Used by Purpose
STORAGE updater.sh vzdump target storage when snapshots are unavailable
PROXSAVE_REMOTE_PATH install_proxsave_rclone.sh Backup path on the SFTP remote (after <remote>:)
PROXSAVE_LOG_BASE install_proxsave_rclone.sh Base path holding the per-host log directories
PROXSAVE_HEALTHCHECK_URL install_proxsave_rclone.sh Healthcheck ping URL (e.g. healthchecks.io)

Development

Tooling is pinned with mise:

mise install                      # installs shellcheck
shellcheck *.sh lxc-exec exec-all

Unit tests cover the pure helpers of the upgrade scripts — parsing and decision functions only, no system call:

bash tests/test_ceph_helpers.sh   # pve8to9-upgrade.sh
bash tests/test_pbs_helpers.sh    # pbs3to4-upgrade.sh

License

MIT — see LICENSE. pve_clean.sh derives from pvekclean, also MIT.