vzdump and pct restore ran with their output thrown away, so a failed
backup only said "Backup failed for container N" (exit 235). That is the
second most common update-apps failure and none of them can be told
apart. Keep the output in the run log and put its error line in the
message, e.g. "CT is locked (backup)".
var_backup_storage was matched with grep -w, so "truenas" passed when
only "truenas-backup" exists and vzdump then failed on a storage that
does not exist. Match the whole name, and list the valid ones in the
error instead of a spinner line after it.
Name the app in "Update failed for container N", so a failed update
says which app's update failed. Declining the start dialog now exits 0
like the other tools instead of failing with whiptail's 1.
clear exits 1 for a TERM the host has no terminfo entry for, such as
xterm-ghostty or xterm-kitty over SSH, and when TERM is unset under cron.
The tools that run under errexit died on it in header_info within a
second, before showing anything, which telemetry counts as
"exit_code=1 | General error" with no step for update-lxcs, update-repo,
fstrim, clean-lxcs, execute and storage-share-helper.
Fall back to the escape sequence the engine's _cs_clear uses.
Nothing checked that the host is a Backup Server. On a PVE host the
first step stopped only because tar found no /etc/proxmox-backup (exit
2); answering "no" to that backup would have gone on to delete
/etc/apt/sources.list.d/*.list, add the PBS repositories and
dist-upgrade. Stop with the same message post-pbs-install uses.
pct fstrim exits 255 when the container is locked, for example while a
backup runs ("CT is locked (backup)"). Under errexit the command
substitution ended the whole run there, before the output check below it
and before the remaining containers, and telemetry filed it as
"DPKG: Fatal internal error". Print the result and go on instead.
The skip message printed $name, which is only set once a container has
run the command. When a non-Debian container (Alpine, for example) came
before any Debian one, set -u ended the run there with "name: unbound
variable" and exit 1; later it printed the previous container's name.
The target list came from storages with "images" content, but pct
restore puts the container's rootfs there and refuses a storage without
"rootdir" ("storage 'X' does not support container directories"). A
storage that holds VM disks only was offered, and picking it ended the
run after the backup with "Conversion failed" (exit 235).
On a PVE 9 host without deb822 .sources files the script asks whether to
disable the legacy .list sources, then read the answer from $? on the
next line. Under set -e a "No" ended the whole run with exit 1 right
there, so the "Kept legacy sources as-is" branch never ran and nothing
after it was offered. Test whiptail in the if instead.
* Drop the legacy engine copies from misc/
Nothing has loaded misc/*.func since ct/, install/, vm/ and tools/ moved to
community-scripts/core. misc/api.func stays until vm/owncloud-vm.sh gets its
DevScripts rewrite.
misc/images/ moves to .github/assets/. The tombstone stub for removed scripts
sourced misc/build.func and called variables(), which core's PVE engine does
not define; it now sources core.func.
* Drop misc/api.func
vm/owncloud-vm.sh was its last caller; DevScripts holds that script's rewrite
onto core/pve/vm-core.func. Merge this after the promotion.
* post-pmg-install: hide the subscription nag in the PMG 9 mobile quarantine
PMG 9 replaced pmgmanagerlib-mobile.js with the Yew/WASM app in
pmg-mobile-quarantine-ui, so the mobile hook no longer found its file.
The status check is compiled into the WASM, so the helper now injects a
fetch wrapper into the mobile index template that reports the
subscription as active to the app. The API response itself is unchanged.
All patches move into /usr/local/bin/pmg-remove-nag.sh behind a single
apt hook. "no" now also removes the mobile hook and the helper, and the
reinstall covers pmg-mobile-quarantine-ui so its template is restored.
Fixes#16217
* post-pmg-install: reinstall the mobile quarantine UI only where it exists
pmg-mobile-quarantine-ui is not in the PMG 8 (bookworm) repository, so
naming it in the reinstall made apt abort there and skip the widget
toolkit reinstall as well.
The mobile UI patch removed the dialog and card only when their text
contained "subscription", so translated UIs (de: "Subskription", fr:
"Abonnement", ...) kept the nag. It also deleted DOM nodes Yew still
owns and polled every 300 ms for good.
The helper now injects a fetch wrapper into the mobile index template
that fills the empty subscription level of each node in the /nodes
response, so the app never shows the alert or card. The API response
itself is unchanged; the node list shows "-" instead of "No
subscription". The mobile UI package is reinstalled alongside the widget
toolkit so old blocks are dropped, and "no" also removes the helper.
The CT check resolved the IP by running ip inside the guest via pct
exec, which depends on the guest having it installed. If not, this
always comes back empty, so the container is restarted every cycle
despite answering ping. lxc-info reports the addresses from the
host without running anything inside the guest.
Fixes#17685
* Scripts: close every msg_info block with msg_ok
Past-tense msg_info calls that should have been msg_ok, notices that opened a block before a prompt, and blocks without a closing msg_ok. These already left a stale spinner; with core's block stack they would resume it after every later msg_ok.
* Generate passwords with random_password
openssl rand -base64 | tr -dc | head -c returned fewer characters than asked for, and the unfiltered | cut variants put / and + into passwords that end up in DSNs and sed expressions. Secrets an app decodes as base64 are unchanged. Requires community-scripts/core#61.
* Keep data directories through CLEAN_INSTALL instead of copying them
create_backup copied uploads, storage and similar directories twice per update and needed their size again in free space. CLEAN_INSTALL_KEEP moves them aside instead. Only directories the upstream release does not ship, in scripts that restored right after the fetch. Requires community-scripts/core#61.
* Drop the 300s uv timeout overrides
setup_uv exports UV_HTTP_TIMEOUT=600 now; the scripts' 300 only lowered it. Requires community-scripts/core#61.
One checklist now lists containers and VMs side by side, each tagged with its
type, with separate ALL CT / ALL VM entries. VMs stop via qm stop and are
removed with qm destroy --purge --destroy-unreferenced-disks.
Two fixes fall out of the rework: the destroy exit status is read from the
background job rather than from the spinner, so failures actually surface, and
a guest is only stopped once its deletion is confirmed.
A container keeps the slug it was built with, so a renamed ct/ script leaves
the updater looking for a name that no longer exists.
Reported for pbs, renamed to proxmox-backup-server in 0e5f663df. The Alpine
merge on 2026-08-18 retired 29 more names the same way, so every container
installed from an alpine-* script before that date hits this too.
Candidates are only accepted when the target script really exists, so an
unknown slug still errors rather than running some other app's updater.
Fixes#16989
* docker-vm, pve-privilege-converter: source from GitHub raw instead of gitea mirror
* docker-vm, pve-privilege-converter, vm-core.func: source from GitHub raw instead of gitea mirror
* Fix: Incorporate the new update functions to prevent a empty grep on the legacy link in /usr/bin/update
* Remove outdated comments from update-apps.sh
Removed comments regarding the new-style entrypoint and fallback logic for service extraction.
---------
Co-authored-by: CanbiZ (MickLesk) <47820557+MickLesk@users.noreply.github.com>
* Move the top 25 scripts onto the core engine
The engine work of the last few days reaches 30 of 561 ct scripts, about 5% of
ProxmoxVE traffic: retry on engine downloads, exit 227 instead of a misfiled
dpkg error, the umask fix that stops a hardened host producing containers apt
cannot resolve in, the TMPDIR guard, the toolchain restore. All of it has been
sitting where almost nobody runs it.
All eighteen at once rather than in waves. A slow rollout does not exercise the
paths only some scripts take, and broad exposure is what surfaces bugs -- a
deliberate call about release risk.
Checked before touching anything, because "migrate" meant far more than a line
swap last time:
- None of the eighteen has an alpine-* variant, so there is no merge to do.
- No script references misc/ outside its bootstrap line.
- Of the 61 functions that exist only in misc/, none is called by any of them.
So it is one line per script, and every head is now byte-identical to the ones
migrated earlier. With these, ProxmoxVE goes from 30 scripts on the core engine
to 48 -- and from roughly 5% of traffic to the majority, since these are the
ones people actually install.
Two to watch: immich sits at 44.7% success and vaultwarden at 42.1% before
this. If their numbers move, the engine is one of two changed variables rather
than the only one.
* Move update-apps onto the core engine
Entry 11 of the list and the only one that is not a ct script, so it was left
out of the previous commit. It is a host tool: it never used build.func at all,
it sources misc/core.func and misc/api.func directly.
The swap is therefore two lines rather than one, and worth checking rather than
assuming. It uses exactly five engine functions -- header_info,
init_tool_telemetry, msg_info, msg_ok, msg_error -- all present in the core, and
both files load standalone, which they had not had to do before: everywhere else
they arrive through build.func.
That completes the list. All 25 now run on the core engine.
Fixing this one matters beyond the migration: update-apps is what drives
unattended updates across every container on a host, and it is the path where
PHS_SILENT was being ignored (#16593). It now gets the engine that honours it.
The "disable" option description stated "Comment out (disable) this repo" but the implementation uses `Enabled: false` (deb822 format) instead of commenting. Update description to better reflect the action.
* pve-tool: storage share helper script for Proxmox
This script provides a menu-driven interface for managing various storage types in Proxmox, including SMB, NFS, and iSCSI. It includes functions for testing mounts, adding storage, and managing LXC mountpoints.
* bump function call
* add dynamic whiptail (feedback from #15882)
* broken whiptail in menu 4
* fix ui bug, more space for container names
* fix whiptail pick mountpoint
* Allow removing multiple LXC mountpoints
Update `remove_lxc_mountpoint` in `storage-share-helper.sh` to support multi-select mountpoint removal for a container. Each selected mountpoint is now confirmed individually (default No), processed independently, and reported in a final result summary with `removed`, `FAILED`, or `skipped` status.
* stupid whiptail.. now done
* Update storage-share-helper.sh
* feat: add task monitoring option via e.g. healthchecks.io. To be configured via PING variable in config file.
* attach logfile on failure to healthcheck.io message
* fixed error status when updating lxc even if finished successful
---------
Co-authored-by: Sir106 <sir106@id-e.de>
- Trim whitespace, skip empty tokens and reject non-numeric input so a
malformed selection no longer feeds garbage into `sed -n "<index>p"`.
- Reject reversed ranges (start greater than end) with a clear message.
- Replace `grep | wc -l` with `grep -c` (ShellCheck SC2126).
- Replace the array-style exclude check (`${excluded_containers[@]}` on a
plain string) with an explicit per-VMID loop, resolving the ShellCheck
SC2199/SC2076 errors and avoiding accidental substring matches.
- Abort cleanly when the checklist dialog is cancelled instead of relying
on an unreachable `$?` test under `set -eEuo pipefail`.
- Exit gracefully on a declined confirmation prompt.
- Use `pct exec ... -- hostname` for consistent argument handling.
- AMD: download directly to "$microcode" instead of a convoluted, unquoted
basename of the full URL (fixes ShellCheck SC2046) and pin to https.
- Quote dpkg install and cleanup paths (SC2086) and use rm -f.
- Normalize the Debian pool URLs (drop the stray double/triple slashes).
- Define color variables directly instead of via $(echo ...) (SC2116/SC2028).
* Reduce IP-Tag resource usage and clean up ShellCheck findings
Performance / resource fixes in the generated service:
- VM IP detection only queries the QEMU guest agent when it is actually
enabled in the VM config. Previously every VM without an agent stalled
the loop for the full `qm guest cmd` timeout on each cycle; the timeout
is also lowered from 8s to 5s.
- Skip the ARP/ping fallback for VMs entirely when the guest agent already
returned addresses, avoiding needless ping probes every run.
- Snapshot `ip neighbor show` once per host instead of invoking it per MAC
in the VM and LXC lookups.
- Lower ping verification to a 1s timeout (`-W 1`).
ShellCheck cleanup in the installer:
- Define color variables directly instead of via $(echo ...) (SC2116/SC2028).
- Use `read -rp` everywhere (SC2162).
- Replace Unicode quotes with ASCII in a status message (SC1111).
* Cut IP-Tag CPU usage by avoiding per-guest pct/qm status calls
The periodic check spawned one `pct status` per container and one
`qm status` per VM each cycle. Both are heavy Perl tools (~hundreds of ms
CPU per invocation), so on hosts with many guests the 5-minute run caused
a noticeable CPU spike.
- Derive LXC status from the single `pct list` call that is already made
for enumeration.
- Add one `qm list` call to collect all VM statuses at once.
- Store both in a per-cycle STATUS_CACHE and read from it instead of
calling `pct status` / `qm status` per guest (with a fallback for direct
calls outside the cycle).
* feat(update-apps): add var_continue_on_error and TERM=dumb fix
- Add var_continue_on_error=yes to skip failed containers instead
of aborting all remaining updates. Useful for cron/unattended runs
where one disabled or broken script should not stop others.
Containers with backup still attempt restore on failure regardless.
- Set TERM=dumb when running pct exec to prevent whiptail from
hanging when no TTY is available (e.g. cron jobs redirecting
stdout/stderr). This causes whiptail to fail-fast instead of
blocking indefinitely.
- Add var_continue_on_error to export_config_json, --help output,
and usage examples (cron-style invocation example added).
* feat(update-apps): add var_dry_run to check updates without applying
Adds dry-run mode (var_dry_run=yes) that reports available updates for
all selected containers without modifying anything:
- Extracts GitHub source repo from the ct script header (# Source:)
- Resolves the version file name from check_for_gh_release app arg
- Reads current installed version from ~/.appname inside the container
- Queries GitHub API /releases/latest for comparison
- Outputs color-coded status: up-to-date (green), update available (yellow),
or unknown (blue/yellow with reason)
Non-GitHub sources (Codeberg, custom URLs) are skipped with a notice.
Resource scaling is suppressed entirely during dry-run.
Example usage:
var_container=all_running var_skip_confirm=yes var_dry_run=yes \
bash -c "$(curl -fsSL .../update-apps.sh)"
* fix(update-apps): dry-run uses check_for_gh_release args, not Source header
The # Source: header can point to a different repo than what
check_for_gh_release actually queries (e.g. RustDesk uses
lejianwen fork, not official rustdesk repo).
Now parse both app name and source repo directly from the
check_for_gh_release call in the ct script:
check_for_gh_release "appname" "owner/repo"
Also fix $HOME/.appname path expansion in pct exec context.
* fix issue on clear()
* feat(update-apps): add no-op clear wrapper to PATH for update scripts
Co-authored-by: Copilot <copilot@github.com>
* feat(update-apps): enhance error handling for unattended mode in resource checks
Co-authored-by: Copilot <copilot@github.com>
* feat(update-apps): implement structured logging and summary report for updates
Co-authored-by: Copilot <copilot@github.com>
* fix log issue
Co-authored-by: Copilot <copilot@github.com>
* feat(update-apps): enhance dry-run functionality and logging for container updates
Co-authored-by: Copilot <copilot@github.com>
* feat(update-apps): add dry-run completion message for better user feedback
Co-authored-by: Copilot <copilot@github.com>
---------
Co-authored-by: Copilot <copilot@github.com>