Wrap each install-method file download in its own try/catch so a missing or failing variant no longer aborts the entire script load. The service now records method-level errors, continues downloading remaining methods, and includes a combined error message in the result when no files were downloaded.
When cleaning up active executions tied to a disconnected websocket, the handler now safely checks for a process before sending SIGTERM and proactively updates any related installation record to `failed` with buffered output. This prevents records from being left stuck in `in_progress` after cleanup removes the execution before exit handling runs.
Improve install/update flow and server editing behavior. Script execution now records a known container ID when creating installation records, so entries are linked from the start. Server edit validation was updated in both the form and PUT API route to allow blank password/SSH key fields when an existing stored secret can be reused, while still enforcing required auth data for new servers or missing stored credentials. The batch update confirmation modal now requires explicit text confirmation ("UPDATE ALL") before running.
Adds broad ARM64-aware behavior across build/install flows, including architecture validation, ARM64 template sourcing, architecture-specific package handling, and ARM64 notices. Introduces end-to-end HTTP proxy support (vars, validation, interactive prompts, container bootstrap propagation, and update-path sourcing), plus SDN vnet selection/validation and storage health safeguards.
It also hardens runtime/update behavior with script status guarding, improves GPU device mapping (including /dev/kfd), and significantly refactors tools helpers for safer curl usage, shared archive deploy logic, better temp-file cleanup, prefix-aware GitHub/GitLab release selection, and stricter package/repo error handling. The error handler module is renamed to use an underscore path and all references are updated.
* feat: add JWT expiry validation and refactor magic numbers
- Decode JWT in WebSocket auth to reject expired tokens and log auth failures.
- Introduce constants `OUTPUT_BUFFER_MAX_LENGTH`, `BACKUP_UPDATE_DELAY_MS`, and `JWT_EXP_MS_FACTOR`.
- Replace hardcoded buffer length and delay values with the new constants.
- Coerce `AUTH_ENABLED` and `AUTH_SETUP_COMPLETED` to boolean and add `AUTH_SESSION_DURATION_DAYS` env.
* feat(auth): sync process.env and mark setup completed after credentials update
Add a `syncProcessEnvFromFile()` function that reads the .env file and updates
process.env and the cached JWT secret, ensuring that in-memory state matches
the persisted environment without requiring a server restart.
Call this function after writing credentials or toggling authentication
settings to keep the running server in sync. Also set the setup completed flag
when credentials are updated, and clear it when disabling auth to force the
fresh setup flow on re-enable.
---------
Co-authored-by: Vivelis <¨maceo.jalbert@gmail.com¨>
* fix(security): protect servers api and redact secrets
* feat: add authentication checks to various API routes
- Implemented `requireApiAuth` in multiple settings routes to enforce authentication.
- Added checks for setup completion in the authentication setup route.
- Enhanced error handling and response messages for better clarity.
- Ensured that sensitive information is only exposed to authenticated users.
* fix: update auth module import from .ts to .js
* fix: enhance error handling in auto-sync and normalize alpine CT slug
* fix: remove unnecessary whitespace in script handling functions
---------
Co-authored-by: ProxmoxVE Developer <dev@localhost>
Whiptail dialog positioning depends on COLUMNS/LINES matching the actual
rendered terminal size. When the window opens at a fixed 1000x640px and
the user resizes, the PTY needs a resize signal (currently broken on
old deployments). Opening maximized avoids the need to resize entirely:
the PTY spawns at full-screen dimensions, whiptail is correctly centered,
and resize is not needed for normal use.
User can still restore/drag to a smaller window after the script finishes.
The ref was only updated via a useEffect, which runs asynchronously after
the state update. If ResizeObserver fires in the gap between setExecutionId()
and the effect, the resize message carries the stale initial executionId
instead of the one registered with the server -> resizeExecution silently
fails and PTY never gets the SIGWINCH.
Setting executionIdRef.current directly in ws.onopen ensures the ref is
correct before any resize messages can be sent.
install.func: use _CORE_FUNC_LOADED guard instead of BASH_SOURCE[0]
check. When sourced via herestring (pct exec), BASH_SOURCE[0] is empty
string which slipped past the /dev/stdin check, causing /dev/core.func
not found errors. _CORE_FUNC_LOADED is always set when core.func is
already loaded as part of the combined FUNCTIONS_FILE_PATH.
handler.ts + Terminal.tsx: move the xterm clear (ESC[2J ESC[H) from
server-side to client-side, sent immediately before the resize WS
message. Server-side clear had a race: whiptail SIGWINCH redraw
(PTY -> SSH -> WS) could arrive before or after our server clear,
causing it to wipe the correctly redrawn dialog. Client-side clear
is synchronous and always precedes the server's SIGWINCH redraw.
install.func: move load_functions/catch_errors outside the stdin guard.
The guard only prevents sourcing files from /dev path when running via
stdin, but load_functions (which calls icons() setting CM) and
catch_errors must always run. Previously they were inside the guard,
so CM was never set when running via pct exec -> unbound variable crash.
Terminal.tsx: add executionIdRef and include executionId in resize WS
messages. Without it the handler can't find the active PTY execution,
so pty.resize() and the screen-clear after resize were both silent no-ops.
After pty.resize() sends SIGWINCH to the remote process, ncurses redraws
the dialog at the new position but does NOT erase the old character cells.
By sending ESC[2J ESC[H to the client immediately after resize, xterm is
cleared before whiptail's SIGWINCH redraw arrives (~10-50ms SSH roundtrip),
so the new dialog renders on a clean screen with no ghost artifacts.
- ResizeObserver now debounces 150ms before sending 'resize' to server,
preventing Unknown action spam during window drag
- Start message delayed 300ms after WS open so fitAddon.fit() has run
and actual cols/rows are read, fixing whiptail dialog misalignment
Fixes syntax error 'unexpected token fi' caused by empty if...fi block.
Source calls for core.func/error-handler.func were outside the guard,
causing them to run unconditionally (including via /dev/stdin).
Bug Fixes
---------
- fix: use exact match for config file existence check in isVM (#584)
Destroy container was calling qm destroy on LXC containers because
'not_exists'.includes('exists') is true. Fixed sentinel to 'not_found'.
- fix: allow nested repository paths in URL validator (#585)
Regex required exactly two path segments, rejecting GitLab nested
groups like https://git.example.com/group/sub-group/repo.
- fix: terminal window fills floating shell properly (#586)
Fixed-height xterm classes overflowed the FloatingShell window,
cutting off content and overlapping the button bar. Added fillParent
prop so the terminal fills available space via flexbox.
- fix: cleanupOrphanedScripts wrongly deletes VMs (#589)
Two bugs: ID regex \d{3,4} dropped IDs >=10000; config path used
server.name (display label) instead of the real Proxmox hostname,
causing config lookups to always return not_found and VMs to be
incorrectly removed from the database on every startup.
- fix: generate key pair hangs when key files already exist (#590)
ssh-keygen prompts 'Overwrite (y/n)?' when target file exists;
stdin never receives input so the process hangs indefinitely.
Now deletes existing key files before spawning ssh-keygen.
Script Engine Updates
---------------------
- add tools.func from upstream
- update build.func
- add vm-core
- add install.func from upstream
- add node heap space in error-handler
- minor fixes and upgrade pve version for core
- prefer jq in json_escape with robust awk fallback
- improve LXC motd profile and OS detection
Misc
----
- bump nodejs
- fix duplicate permissions in release-drafter.yml
- Just removing a doubled word in filebrowser-quantum description (#583)
Prevent non-interactive shells from printing the motd by adding a terminal check ([ -t 1 ] || return 0). Replace fragile /etc/os-release parsing with a sourced fallback that uses PRETTY_NAME/NAME (defaulting to "Unknown OS") for more robust OS display. Overall cleans up how the container profile prints OS information while preserving hostname and IP output.
Prefer jq for JSON string encoding when available (uses jq -Rs) to guarantee correct escaping; otherwise use a safer awk-based fallback. Inputs are pre-sanitized to strip ANSI sequences and control characters, and the new awk routine processes characters one-by-one to correctly escape backslashes, quotes and tabs and to join lines as \n, avoiding gsub replacement pitfalls from the previous implementation.