Updates `build_container()` to source `error_handler.func` instead of the incorrectly named `error-handler.func`, ensuring the combined stdin-sourced script includes the intended error handling file.
An unconditional `export FUNCTIONS_FILE_PATH="$(curl -fsSL "$_func_url")"`
line ran after the if/else that decides how to populate
FUNCTIONS_FILE_PATH. $_func_url is only ever assigned inside the else
branch (remote-fetch path), so whenever the local install.func file
existed (the normal case), this stray line ran curl with an empty URL —
"curl: option : blank argument where content is expected" — aborting
every fresh container creation (e.g. Adguard LXC) with exit code 2.
Bump to 1.1.7.1 (VERSION + package.json) for this hotfix.
* Fix fallback path for scripts without install_methods
Generalize the fallback logic in `isScriptDownloaded` and `getDownloadedFiles` to use `deriveScriptPath` instead of hard-coding the `ct/` directory. This fixes detection for PocketBase-style 'pve'/'addon' tool scripts that have no `install_methods` but are still downloaded via `loadScript`'s own fallback path.
* Run batch container updates in background, auto-advance on completion
Batch "Update All" previously required the user to manually close each
per-container terminal before the next one would start, and each window
opened focused/visible. Now batch-update sessions open minimized and
auto-close (advancing the queue) once the script itself reports
completion via the WS "end" message, instead of waiting for a manual
close.
* Hint where to enable server color coding when disabled
Server Color Coding is a hidden-by-default setting (Settings > General),
so the color field silently disappeared from the server form with no
indication it existed. Show a short pointer to where it can be enabled.
* Fix strict-null-check build error in fallback path detection
* Harden WebSocket/SSH execution security
- Validate shell-interpolated params (containerId, storage, hostnames, containerType, cloneCount) on WebSocket 'start' messages
- Add path traversal guard: script paths must resolve inside the scripts directory
- Filter env-var keys to valid shell identifiers before interpolation in all execution paths
- Redact SSH credentials (password, ssh_key, ssh_key_passphrase) from all API responses in servers and installedScripts routers
- Suppress secret values from SSH execution logs; log only key names
- Update installation record to 'failed' on manual stop; guard optional chaining on process/ws access
* Persist update results for installed scripts
Propagate `installedScriptId` from the UI terminal session through WebSocket start messages so update runs can be tied to a specific InstalledScript record. Update execution paths (local and SSH) now buffer output and persist final status/output_log on completion.
The Installed Scripts tab now shows a batch-update completion summary with succeeded/failed containers after refetching fresh statuses, and shell session/types were extended accordingly. Also tightened `redactServer` typing to accept server-like objects with optional secret fields while still stripping sensitive values.
* Remove overbroad regex fallbacks for container ID / web UI IP detection
parseContainerId's generic 3-4 digit fallback and parseWebUIUrl's bare-IP
fallback could match any unrelated number/dotted-quad in script output
(ports, percentages, netmasks) and silently overwrite the correct
container_id/web_ui_ip with a wrong one. Removed both fallbacks — every
remaining pattern requires enough context (a label, protocol, or port)
to be a reasonably reliable match.
* Add toasts and dynamic terminal sizing
Introduce a new `ToastProvider`/`useToast` context and wire it into the app so server CRUD actions in `SettingsModal` show success/error toast feedback, including API error messages when available. Also pass terminal `cols`/`rows` through script and SSH execution paths with larger fallback defaults to improve ncurses/whiptail rendering versus the old fixed 80x24/120x30 sizes.
* Thread real terminal size through every execution path
cols/rows from the WebSocket start message were parsed but never passed
to any of the start*Execution methods — every PTY (local script, SSH
script, in-container exec, update, shell, backup, clone) was spawned
with a hardcoded small size (80x24 or 120x30) regardless of the
browser's actual terminal dimensions. Whiptail/dialog-based scripts
center their UI based on that (wrong) reported size, so the dialog box
ends up positioned arbitrarily instead of centered in the visibly much
larger terminal. Now the real cols/rows are threaded end-to-end.
* Improve modal stacking and dialog readability
Add a shared `NEWT_COLORS` export to server-side script/update execution so whiptail/dialog UIs use a higher-contrast theme, including interactive LXC shell sessions. Update Backups, Generator, DiffViewer, and Installed Scripts modals to register with `ModalStackProvider` and use dynamic z-index values (and portal usage in DiffViewer), fixing overlay ordering and close behavior consistency across stacked dialogs.
Declare `postcss` as a direct dependency in `package.json` (v8.5.20). This makes PostCSS availability explicit for the project and results in lockfile deduplication by removing Next.js’s nested PostCSS entry.
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).