Flags the removal of GET /api/{server_id}/container/{vmid}/terminal as a
breaking change and documents the termproxy task failures and the black
console screen it came with.
59 KiB
59 KiB
Changelog
All notable changes to PVEmanager will be documented in this file.
[Unreleased]
🖥️ LXC console — failed termproxy tasks and the black screen
- ⚠️ Breaking change:
GET /api/{server_id}/container/{vmid}/terminalhas been removed. The WebSocket endpoint/proxmox/ws/terminal/{server_id}/{node}/{vmid}creates the termproxy session itself, so the REST call was unused by the panel and left an orphaned session on the node on every invocation. External clients should open the WebSocket directly - Opening an LXC console no longer leaves a failed task on the node —
failed waiting for client: timed out/TASK ERROR: command '/usr/bin/termproxy 5900 ... vzctlconsole<id>' failed. The console page created a termproxy session over REST (using only thenodefield of the response and discarding port and ticket), then a second one over the WebSocket endpoint and attached to that one. Nobody ever attached to the first, so Proxmox waited ~10 s for a client and failed the task - Console no longer shows a black screen with a "connected" badge in dev — React StrictMode mounts the effect twice and the connect helpers are async, so effect cleanup ran before they had assigned
wsRef/termRefand cleaned up nothing. Two xterm instances ended up in the same container: the one filling the viewport was orphaned while the live one was pushed out of the overflow-hidden area. Sessions now carry a cancellation guard, and both mount and the reconnect button go through a single entry point that tears the previous session down first. The same guard was applied to the node shell page
🔍 NFS storage dialog — scan for available exports
- Added a "scan exports" button next to the server field when adding an NFS storage — calls Proxmox's
GET /nodes/{node}/scan/nfsand turns the export path field from a free-text input into a select populated with the exports actually found on the target server, instead of requiring the path to be typed by hand and guessed - New endpoint
GET /api/backups/scan-nfs/{server_id}?server=<ip>on the backend, running the scan through the server's first available node
[v1.17.0] - 2026-08-20
💾 Move LXC container disks to another storage
- Disk move now works for LXC, not just QEMU VMs — the Move disk action was previously hardcoded to the VM
move_diskAPI and unreachable for containers (no Hardware tab, and the disk-row detector only matched VM device names).rootfs/mp\d+are now recognized as LXC disk devices, and a Move disk card was added to the Settings tab for LXC instances - New endpoint
POST /api/{server_id}/container/{vmid}/disk/movecalls Proxmox'slxc/{vmid}/move_volume; the target storage list is filtered by supported content type (rootdirfor LXC,imagesfor VM) instead of showing every storage - Blocked on running containers with a guided flow — Proxmox rejects
move_volumeon a running LXC (move_diskworks live for QEMU,move_volumedoes not for LXC). Attempting it now opens a confirmation dialog that stops the container, moves the disk, and restarts it, showing progress at each step; the container is always restarted even if the move itself fails. VMs and already-stopped containers still get a plain confirm dialog
📊 Instance list — collapsible metrics panel
- CPU/RAM/Disk/Net/Disk I/O/Uptime moved out of the always-visible table columns into a per-row panel that expands when you click the instance name, matching the disclosure pattern from VMmanager. The panel adds a Parameters link straight into the instance's Settings tab and clearer stat cards for network/disk throughput
- vCPU/RAM bars widened and enlarged (bar width and label/detail font size) for easier at-a-glance reading in the collapsed panel
✨ Network topology page
- New
/topologypage — an interactive map of the infrastructure: panel → cluster → Proxmox node → VM/LXC, rendered with React Flow. Node cards carry live CPU/RAM meters, guests show status, IP, bridge/VLAN and tags - Filters — narrow the graph to one connection, filter guests by status (all / running / stopped), and collapse a node's guests into a single badge above a configurable threshold (remembered per browser); expand a collapsed node individually
- Canvas tools — zoom, pan, fit-to-screen, fullscreen, minimap, legend and PNG/SVG export of the whole graph
- New API
GET /proxmox/api/network/topology— one aggregated request instead of fanning out over servers/nodes/SDN/VMs; gated onnetwork:view, honours workspace scoping and per-owner VM isolation. Unreachable connections degrade to cached data plus a warning instead of failing the page netNparser — guest NIC strings are now parsed (bridge, VLAN tag, MAC, model, firewall, rate, MTU) for both the QEMU and LXC dialects, available viainclude_nics=true
[v1.16.1] - 2026-08-17
🎨 UI
- Inter Variable font — the frontend now uses the variable-weight Inter font with a bumped type scale for sharper, more consistent typography across the panel
🔧 Deployment Fixes
pveCLI installs without root —deploy.shnow triessudoto install the CLI to/usr/local/bin, and falls back to~/.local/bin(with automatic PATH configuration) when root access is unavailable; previously the auto-install was silently skipped, leaving thepvecommand unavailable after deploypveCLI file permissions — the installed script is now set to755instead of relying on umask; previouslysudo cpcould leave the file without read permission for non-root users, causing "Permission denied" on every invocation- SSL no longer rolls back on deploy —
verify_nginx_runningnow usesdocker compose ps --format '{{.State}}'(returns"running"immediately) instead of grepping the human-readable STATUS column (which shows"Up Xs (health: starting)"for 30 s before the first healthcheck); with the old 20 s timeout the function always timed out, rolling back to HTTP even though the SSL certificate was successfully obtained
[v1.16.0] - 2026-08-14
🌍 i18n — Full Translation Pass
A comprehensive sweep that eliminated the remaining hardcoded and untranslated strings from the UI:
- Dashboard & Instances — action dialogs, resource cards, status labels, and bulk-operation descriptions are now fully translated (EN + RU)
- Images page — image browser, download/import dialogs, mirrors manager fully translated
- App Store — missing keys added for install wizard, operation states, and app detail labels
- Nodes — power action labels (
Start,Reboot,Shutdown) and common node-admin strings translated - Scripts & Certs — Scripts catalog and TLS/certificates sections added to both locales
- Roles — permission labels for all RBAC entries, including
remote_migrate, translated to Russian - Graphs, Wizard, Storages — previously hardcoded Russian strings moved to locale files and dual-translated
- Bulk migrate & Access realm — new locale keys for bulk migration actions and Proxmox realm labels
- Critical fixes — several strings that were silently falling back to English in the Russian UI are now correctly translated
🔑 SSH Keys
- Swap SSH keys on owner change — when an admin reassigns a VM/LXC to a different user, the instance now automatically receives the new owner's SSH public key (and the previous owner's key is removed), keeping access credentials in sync with the current owner
📦 Cloud Images
patch-cloud-images.sh— new helper script that patches official cloud images to includeqemu-guest-agent, then publishes them to a GitHub release mirror; enables live metrics and guest-agent features without requiring a post-deploy agent install- amd64 image catalog — default amd64 image entries now point to the GitHub mirror (qemu-guest-agent pre-installed) and include
sha256checksums for integrity verification
🐛 Bug Fixes
- VM storage overview — loop devices (
/dev/loop*) and system partitions (/dev/sr*,/boot,/snap) were included in per-disk usage cards; they are now filtered out so only data disks are shown - Cloud image re-download — cached import images were served from disk even when a checksum was provided and the remote file had changed; the cache is now invalidated when a checksum mismatch is detected
- Password visibility icon — the eye icon across all password fields (login, change-password, SSH key passphrase, and API-key dialogs) was inverted: open eye was shown when the field was hidden and vice-versa; icon state now correctly reflects whether the value is visible
[v1.15.0] - 2026-08-13
🚀 One-Command Bootstrap
bootstrap.sh— installs the panel with a single command on either a plain Debian/Ubuntu host or directly on a Proxmox VE host. On a PVE host it provisions a Debian 12 LXC, installs the panel inside it via the existingdeploy.sh, creates a localroot@pamAPI token and registers that host as the panel's first node — no Proxmox password is ever transmitted- Tolerates
apt-get updatefailures from an unsubscribed PVE host's enterprise repo instead of aborting the whole bootstrap beforegit/curlare installed - Registers the host at the correct
/proxmox/api/serverspath (the previous/api/servers404'd, since the Proxmox router is mounted under/proxmox) - Removed the insecure
pvemanager_secure_passwordfallback forPOSTGRES_PASSWORDincompose.yml— every deploy path already generates a real.envbefore the stack starts
💿 Images & Instances
- ISO eject/mount rework — the Images page now shows real ISO files already present on node storage (including ones that predate the node joining the panel); "Detach" is renamed Eject, the current image is shown inside the select, and a new "boot from disk" / "boot from this ISO" checkbox controls boot order on eject/mount
- Applying a new boot order reboots the guest via a hybrid restart — graceful ACPI shutdown with a forceStop fallback, then start — avoiding the guest-ping timeout seen on a freshly installed OS with no QEMU Guest Agent yet
🔒 RBAC & Access
/profilesplit from/settings— account settings (profile, password, 2FA, SSH keys) moved to their own permission-free/profilepage reached from the user menu and Ctrl+K, so revokingsetting:viewto keep a user out of panel settings no longer locks them out of their own account./settingskeeps the panel-wide tabs behindsetting:view, with saving behindsetting:update, security behindsetting:manage, and SMTP/Telegram behind admin-only- Routes are now guarded by permission, not just hidden from the sidebar —
/users,/logsand/settings(and their tabs) previously rendered for anyone who typed the URL and let the backend answer with 403s; denied users are now redirected to the first page they can open - Migration 42 drops
setting:viewfrom roles that don't also holdsetting:update/setting:manage, since those grants only existed to reach the old combined settings page
👤 Ownership & Quotas
- Owner assignment fixed at creation time — newly created VMs/LXCs were silently ending up with
owner_id = NULLbecause the sync job that registers a still-cloning VM beats the deploy flow to the database row; owner is now set on that update path too. A VM created by an admin on behalf of a user now also injects the user's SSH key instead of the admin's - Backfill migration for instances created before the fix above, recovered from
deploy_tasksandaudit_logsand applied only when every piece of evidence agrees on the same existing user; ambiguous instances are left ownerless forassign_instances_owner.pyto resolve by hand - Create Instance is disabled once a quota has no headroom left, instead of only refusing inside the wizard — the button shows a tooltip naming which limits are full (skipped for admins, whose own quota doesn't apply to instances they create for someone else)
- The pre-wizard quota block is now distinct from the in-wizard one: no headroom at all keeps the wizard from opening; headroom that a chosen configuration would exceed opens the wizard but disables Next/Deploy with the offending metric named
🐛 Bug Fixes
- Production deployments were bypassing TLS —
compose.prod.yml'sports: []didn't actually drop the published8000/3001ports (Compose concatenates list-valued fields across-ffiles instead of overriding), so an SSL deployment kept answering unencrypted on both ports alongside HTTPS. Fixed with the!resettag - SSL deployments reported "Failed to obtain SSL certificate" after successfully issuing one — the success check couldn't read certbot's root-owned, mode-0700 output directory as a non-root user; the check now verifies the certificate from inside the container and falls back to HTTP only if nginx actually fails to come up with the new config
- The frontend bundle's cold load could render a blank page — the general request-rate limit (
10r/s) applied to static assets too and started rejecting the SPA's ~86 preloaded chunks with 503s; and once that was fixed,limit_conn addr 10capped the whole page to 10 concurrent HTTP/2 streams (a browser multiplexes a page's entire load over one connection), producing the same blank page from a different limiter. Static assets now have their own rate-limit zone, and bothlimit_conncaps are raised - nginx workers were unable to open enough file descriptors to match
worker_connections 2048(Docker's defaultRLIMIT_NOFILEof 1024 quietly halved the real ceiling); raised to 8192 - Dropped
listen 443 ssl http2(deprecated since nginx 1.25.1) andssl_stapling(no OCSP responder in current Let's Encrypt certs) — both warned on nginx's periodic reload - Node uptime showed the wrong value on multi-node clusters — the server card took
Math.maxover every cluster node's uptime instead of the current node's own, so rebooting one node could still show another node's higher uptime - The terminated-sessions toast never translated — the message was assembled server-side in Python and returned verbatim, so the Russian UI showed "Terminated 0 sessions"; the count is now returned separately and the phrase is composed client-side (Russian needs four plural forms against English's two)
[v1.14.0] - 2026-07-24
🐛 Bug Fixes
- Workspace switch left stale instance filters behind — the server, node and per-column filters on the Instances page kept whatever values were picked in the previously active workspace, which could filter the newly-scoped VM list down to nothing. Switching the active workspace now resets all of them
- "Node" column filter never updated after the first render — its checklist of available nodes was memoized against the TanStack
Columnobject, which keeps the same identity across data updates, so the list stayed frozen at whatever nodes were visible when the popover first mounted — including nodes from workspaces you'd since switched away from. It now reads live from the table's faceted values on every render
[v1.13.0] - 2026-07-24
🛒 App Store
- Storage selection for the golden template — the "Golden LXC template" dialog now offers dropdowns for template storage (
vztmplcontent) and rootfs storage (rootdircontent) populated from the selected server/node, instead of free-text fields. Selection auto-pickslocal/local-lvmwhen present, falling back to the first available storage
📜 Scripts
- Name search in the scripts catalog — filter manual, Git and Community-Scripts entries by name directly from the Scripts page
[v1.12.0] - 2026-07-24
🔗 Cluster
- Import an existing cluster — nodes already joined into a Proxmox cluster outside the panel (via
pvecm/the Proxmox UI) can now be linked in the Cluster page instead of only via the panel's own Create/Join flow. Detection readscluster/config/joinon the selected node, matches its nodelist against known panel servers by IP/hostname, and links the matching panel records to that cluster group — nopvecmoperation is run, only the panel's own bookkeeping is updated
[v1.11.0] - 2026-07-24
🔌 Servers & Connectivity
- Auto-provisioned API tokens — connect a server with a login and password once; the panel authenticates, creates its own API token on the node (
privsep=0) and uses it from then on. The token can be revoked from the Proxmox UI, cannot be used for SSH or web login, and appears in the PVE audit log under its own name. Existing password-auth servers can be migrated in place via Provision token - Rejected credentials vs. unreachable node — an offline server used to report a single "Failed to connect"; now a stale/rejected token (401, typically left behind after a cluster join replaces
user.cfg/token.cfg) shows its ownauth_errorstate with a hint explaining the cause - Per-node storage availability — a storage can be declared cluster-wide but missing on a given node (e.g. an absent volume group or pool); this is now surfaced instead of staying invisible
- Unified status badges — every server list (including cluster topology and user-assignment views) renders the same
ServerStatusBadgeinstead of a repeated online/offline ternary - Workspace-scoped listings —
/api/cluster/topologyand/api/resources/allnow respect the active workspace instead of returning every server on the panel; live metrics are fetched in parallel instead of serially, so one unreachable cluster no longer stalls the whole request
📊 Monitoring
- Node Graphs tab — CPU, IO delay, memory, load average, network, swap and root filesystem charts on the node detail page, with
1h/24h/7d/30d/1ypresets
💿 Images & Instance Creation
- Local file upload — upload an ISO or
vztmpldirectly from your machine to node storage, alongside the existing URL-download flow - Blank VM for ISO installs — a new instance kind in the create wizard: an empty-disk VM with the ISO mounted and booted first, so the guest starts straight into the installer over noVNC; picking Windows presets OVMF, a SATA disk and an e1000 NIC
- ISO downloads — fetch an ISO onto a node by URL from the Images page or from a saved mirror (mirrors now accept
kind=iso)
🔄 Realtime & UX
- Instance and workspace lists now update immediately after assigning servers/users, deploying, or deleting a VM/container — no manual refresh needed
- The node overview no longer flashes "no data" while the instance list is still loading
🛠 Reliability
- Panel self-update recovers from a stalled rebuild instead of hanging at "restarting — 80%" forever; after a timeout it surfaces a clear "failed" state pointing at the host update logs
🎨 Theme
- Dark theme surfaces (background, card, popover, sidebar, borders) shifted from neutral to a blue-graphite hue
📖 Documentation
- Expanded the RBAC/Security guide (permission format, evaluation order, full permission catalogue, per-page map) and added a complete Russian translation, WIKI.ru.md
[v1.10.2] - 2026-07-23
🐛 Fixes
- Templates — after an auto-import, a clear message is shown instead of
undefined
[v1.10.0] - 2026-07-22
🧭 Navigation & Instances
- Command palette (Ctrl+K) — searchable palette over a shared registry of navigation items (its own store), for jumping to any page from the keyboard
- Unified navigation — the sidebar and command palette are driven by one shared nav-item registry
- Expanded instance menu — the per-instance row menu gains Options, Migrate, Change resources, Create backup (new
BackupDialog) and Delete; the menu no longer closes on every live list refresh (stablecolumns+getRowId) - Instance tab reorganization — for VMs, Compute resources, CPU options, Disk management and Disk resize moved from Settings to Hardware; LXC (which has no Hardware tab) keeps them in Settings. Shared cards extracted into
ResourceCards.tsx - New shared UI primitives —
alert,breadcrumb,checkbox,progress,switch,textarea; RU/EN locale keys for the new menu items and backup
🛒 App Store
- Global minimized-operations tray — minimized long-running operations (app install, golden-template build) now live in a global zustand store (persisted to
localStorage) and are rendered by aMinimizedOpsTrayin the app layout instead of by the dialog itself:- the chip survives page navigation and a tab reload; the tray polls progress on its own (REST, every 3 s) independently of the dialog
- clicking a chip returns to the operation's page and reopens the dialog — install resumes in
InstallWizard(resume mode via navigation state), template reopens the golden dialog with the server preselected - Minimize adds the operation to the tray and closes the dialog; the chip's ✕ only removes the chip (the operation keeps running on the server); chips for operations that no longer exist (404 after reload) are cleared automatically
- App data files — files bundled with a catalog app (
data_files) are delivered beforecompose up; UmbrelAPP_PASSWORD/default_credentialsare honored - Minimizable install/build dialogs — long operations can be collapsed via
MinimizableDialog - Install/uninstall reliability:
- teardown — a CT that no longer exists in Proxmox is treated as removed, so an
orphanedapp can finally be deleted from the DB - install — the VMID search skips already-occupied records (
nextiddoes not reserve the number, so a retry could grab another container) - retry — install parameters (
cores/memory/disk/storage/bridge/ip_config/port) are saved toinstalled_apps.install_params(JSONB, new migration) and reused on retry instead of falling back to hard-coded defaults - reconcile — an unreachable server no longer flags all of its apps as
orphaned - update — the actually-published port is recorded in the DB (
url/health) - .env — values containing
#are quoted (the dotenv parser was trimming them as an inline comment) - port
80, when chosen explicitly in the wizard, is published as-is useCatalog—available_onlyis part of the query key (fixes a cache collision)
- teardown — a CT that no longer exists in Proxmox is treated as removed, so an
🔒 Owner Isolation
- Live Proxmox resources are now owner-scoped — the instance list (
/api/virtual-machines) was already filtered byowner_id, but the live-resource endpoints/api/resources/all(dashboard) and/api/{server_id}/resources(node/server page) returned all VMs/LXC. A regular user (proxmox.view) could see other owners' instances through the node page. Both endpoints now filter VM/LXC by owner for non-privileged users (matchingvmidagainst thevm_instancescache); admins and roles withvm:managestill see everything assign_instances_owner.py— script to bulk-assign an owner to existing instances whoseowner_idisNULL(instances synced from Proxmox before ownership existed)
🐛 Fixes
- React Query cache cleared on login/logout — logging in as a different user in the same tab no longer serves the previous user's cached data (instance list, etc.) until a hard reload.
queryClientwas moved out ofApp.tsxintolib/query-client.tsso it is reachable outside React, andauth-storecallsqueryClient.clear()on successful login and on logout
[v1.9.1] - 2026-07-17
🛒 App Store
- Per-server golden template — the golden vztmpl is now stored and resolved per Proxmox
server_idinstead of one global pointer; building it on one server no longer overwrites/breaks the template configured for another.APPSTORE_GOLDEN_TEMPLATEis now only the last-resort fallback for servers without their own build. Migration 37 addsapp_operations.server_id - Golden template build fix — the automated build (
App Store → золотой шаблон) no longer fails at the finalvzdumpexport step (unable to parse directory volume name 'vztmpl/probe') - DNS reliability — App Store LXCs (and the golden-template build CT) now get an explicit
nameserver(APPSTORE_NAMESERVER, default1.1.1.1 8.8.8.8) instead of inheriting the node's resolver, which fixed image-pull timeouts on nodes whose DNS is only reachable from the host (e.g. over Tailscale) - Bind-mount permissions — data directories referenced in an app's
volumes:(${APP_DATA_DIR}/...or relative paths) are pre-created beforeup, fixingPermission deniedfor containers that write as a non-root user (e.g. MariaDB) - Delete/reinstall race fixed — deleting an app now waits for Proxmox to actually confirm the container is gone (up to 30 min, covers slow disk wipes) before freeing the VMID, instead of assuming success after a short timeout
pct createlock retry — transient "can't lock file ... got lock" errors right after a delete are retried a few times instead of failing the install immediately- Full error output — failed pipeline steps now surface the last 4000 characters of command output (previously the first 2000), so the actual failure reason isn't buried under
docker compose pullprogress noise - Install error UI — the error box in the install dialog now wraps long unbroken text (image digests, paths) and scrolls within its own bounded height instead of stretching the dialog
[v1.9.0] - 2026-07-09
🌐 IPAM
- Networks bound to server/node and workspace — an IPAM network can now be tied to a specific Proxmox server/node and to a workspace; each workspace uses one subnet, and the network is auto-selected by the active workspace in the Create Instance and App Store install wizards, so users no longer pick a network manually in the common case
- Auto-selection in wizards — the deploy wizards resolve the target network/pool from the current scope and pre-fill it; a missing binding falls back to manual selection
- Migration: IPAM network workspace-binding columns + default flag added via
backend/migrations/migrations.py
🔧 Nodes
- FQDN/domain accepted in the Proxmox host field — the Add/Edit Proxmox server form now accepts a domain name or FQDN (not only an IP), resolved when connecting
[v1.8.1] - 2026-07-09
🛒 App Store
- Umbrel as a second catalog source — the catalog is now multi-source: alongside
runtipi/runtipi-appstoreyou can enablegetumbrel/umbrel-apps(~380 apps). Sources are configured viaAPPSTORE_SOURCES(comma-separated, defaultruntipi); Umbrel app ids are namespaced (umbrel-<id>) so catalogs never collide - Umbrel compose adapter — install understands Umbrel manifests: the container port is taken from the
app_proxyservice (APP_PORT), the Umbrel runtime services (app_proxy,tor) are stripped, danglingdepends_onare cleaned, and the main service port is published on the LXC host so the health-check passes; Runtipi behaviour is unchanged - Umbrel icons — icons are fetched from the separate
getumbrel/umbrel-apps-galleryrepository (<app-id>/icon.svg) during sync and cached like Runtipi logos; a gallery fetch failure never fails the catalog sync - Multi-source sync — each source syncs independently (a network failure of one doesn't cancel the others), and the disappeared → unavailable pass is scoped per source so a Runtipi sync never touches Umbrel rows
- Source filter & badge (UI) — the App Store adds a source filter and a per-card source badge, shown only when more than one source is enabled; catalog metadata now exposes the available
sources - Custom install port — the install wizard accepts a custom host port (validated 1..65535), overriding the catalog default
- Instant instance cleanup — deleting an app soft-deletes the linked VM instance immediately for a snappier UI
- Data model & settings —
catalog_apps.sourcecolumn (migration 34); new env settingsAPPSTORE_SOURCES,UMBREL_APPSTORE_REPO,UMBREL_APPSTORE_REF,UMBREL_APPSTORE_GALLERY_REPO
[v1.8.0] - 2026-07-07
🛒 App Store
- Self-hosted app catalog with one-click install — new App Store module: each application is deployed into its own unprivileged LXC container running Docker Compose (1 app = 1 LXC). The catalog is imported from the
runtipi/runtipi-appstorerepository (~265 apps pass the filter) - Catalog Service — imports app metadata, logos, descriptions and compose files into the new
catalog_appstable; idempotent sync (manual Refresh catalog button + automatic every 24 h via APScheduler); a brokenconfig.jsonis skipped without failing the whole sync; theupdate_availableflag is computed fromtipi_version - Install pipeline — clone golden LXC template →
pct pushcompose/.env→docker compose up -d→ HTTP health-check, with a live step journal over WebSocket, dynamicform_fieldsrendering (text/password/email/number/boolean/fqdn), auto-generatedrandomsecrets, and Fernet-encrypted env storage; generated credentials are shown once - Lifecycle management — start / stop / restart / logs (
docker compose logs) / delete, plus background state reconciliation every 60 s (containers removed outside PVEmanager are flaggedorphaned) - Update & Rollback — update takes a pre-update Proxmox snapshot, then
docker compose pull && up -dwith health-check; rollback restores the snapshot (data included); only the latest pre-update snapshot is kept - UI — App Store grid (search, categories), app detail page with a source disclaimer and compose preview, install wizard with advanced LXC options and live progress, and a My Apps management screen; RU/EN locales; Powered by Runtipi appstore attribution
- Security — unprivileged LXC only;
pct exec/pct pushvia SSH with base64 file delivery and escaped.envvalues (no shell injection); new RBAC permissionsapp:view/app:install/app:manage - Data model & settings —
catalog_apps,installed_apps,app_operationstables (migrations 31–32); new env settingsAPPSTORE_GOLDEN_TEMPLATE,RUNTIPI_APPSTORE_REF,APPSTORE_DATA_DIR,CATALOG_SYNC_INTERVAL_HOURS,APPSTORE_HOST_ARCH - Docs —
docs/golden-template.md(golden LXC template preparation) anddocs/appstore-poc.md/appstore-catalog.md/appstore-engine.md
[v1.7.0] - 2026-06-26
🎯 Quotas
- Per-user resource quotas — limit each user's number of instances and the summed vCPU, RAM and disk across their VMs/LXC. A missing quota row or a
NULLcolumn means unlimited for that metric, so admins and unrestricted users are never blocked- Backend: new
UserQuotamodel (user_quotastable) andquota_service(get_user_usage/check_quota); usage is computed from thevm_instancescache (owner_id) — non-deleted, non-template instances only; enforcement raises HTTP 429 on VM/LXC deploy when a limit would be exceeded - Permissions: new
quota:viewandquota:manageRBAC permissions (category User Management, both requireuser:view) - API:
GET/PUT /api/users/{id}/quota(admin) returns limits plus current usage;GET /api/quota(self-service) returns the current user's own limits and usage - Frontend: admin quota dialog with usage bars on the Users page; own-limits card on the Settings page; remaining-quota hint in the Create Instance wizard config step;
useUserQuota/useSetUserQuota/useMyQuotahooks; RU/EN locales - Migration:
user_quotastable added viabackend/migrations/migrations.py
- Backend: new
[v1.6.0] - 2026-06-23
✨ Images
- Cloud image catalog — browse and download OS images from multiple sources (default Proxmox mirror and custom mirrors); images are downloaded to Proxmox storage
- Auto-convert to VM template — option to automatically convert downloaded
.qcow2images to Proxmox VM templates on completion - Custom mirrors for admins — admin-only UI to add, edit, list and delete custom mirror sources for image discovery
- Architecture-aware filtering — images filtered by node platform architecture (x86-64, aarch64); default architecture matches the selected node's platform
- Image download with progress — download dialog with real-time progress tracking and optional template conversion toggle
🐛 Bug Fixes
- Image import filename normalization —
.imgextension automatically normalized to.qcow2during import - VM sanitization on image import — VM names are sanitized during image import to prevent creation errors; improved error messages for transparent user feedback
[v1.5.2-1] - 2026-06-20
🖥️ UI
- Styled confirmation dialogs — all native browser
confirm()popups replaced with a consistent themed modal (ConfirmDialog). Added globalConfirmDialogProvider+useConfirmhook (Promise-based API). Affected: update panel, delete template/server/storage/SSH key/HA resource/SDN zone/VNet/subnet/IPAM pool/allocation, apply/revert network changes, IPAM orphan cleanup (16 call-sites across 11 files).
[v1.5.2] - 2026-06-20
📊 Metrics
- Real-time VM disk fill, IOPS and network I/O — live per-disk usage, disk read/write and network in/out rates added to the instance Overview tab, instances list and dashboard top-loaded list
- Backend:
get_vm_fsinfo()pulls per-filesystem usage via QEMU guest agent;metrics_broadcastercomputes I/O rates (bytes/sec) from cumulative counters; instances-list loop now refreshes each running VM viastatus/current(1 s granularity) instead ofcluster/resources(10 s pvestatd), with bounded concurrency and 1 s cadence - Frontend: per-disk cards, Network I/O and I/O-rate cards on OverviewTab via WebSocket; Net and Disk I/O columns in InstancesPage; Disk% shown for LXC; realtime metrics overlay in DashboardPage top-loaded list
- Backend:
⚙️ Settings
- Per-user language preference — each user account now has its own
languagecolumn (migration 26); the language selector moved from the Panel tab to the Profile tab; language is saved to DB and applied viai18n.changeLanguage()immediately on save - Panel tab improvements —
panel_namefield is read-only in UI (falls back to envPANEL_NAME);log_retention_daysfield exposed; Panel API acceptspanel_nameinPUTto allow DB override without touching the env var
🐛 Bug Fixes
- SMTP/security settings fields — renamed SMTP request/response fields (
host,port,username,password,from_email,tls) and pointed security settings hooks at/admin/api/security/settingswith a typedSecuritySettingsshape; addedminutes/security_savedi18n keys - Notifications form UX — added success/error toasts to SMTP and Telegram save buttons; Profile tab language selector wired up; password-change fields cleared only on success
- Telegram admin section — removed the Chat ID field from the global Telegram section (it was never persisted to DB); testing is now done via the personal "My notifications → Send test" flow
- Webhook URL field — removed the unimplemented Webhook URL field from the notifications settings to avoid misleading users
[v1.5.1] - 2026-06-04
🐛 Bug Fixes
- Frontend build: missing LogsPage component —
src/router.tsxreferenced./features/logs/LogsPage.tsx, but the file was missing, so Vite 8.0.5 / rolldown failed to resolve the dynamic import. Addedfrontend/src/features/logs/LogsPage.tsxwith stats cards (24h total, errors, failed logins, page count), level filter, search, pagination and i18n strings. Wires up to existinguseLogs/useLogStats/useLogLevelshooks. - Frontend build:
.gitignorecollision —frontend/.gitignorehad a barelogsentry that matched both the rootlogs/directory andsrc/features/logs/, hiding the new page from VCS. Scoped the rule to/logsso the features tree is no longer ignored.
📚 Documentation
- WIKI: bumped to v1.5.1 and added a new Logs & Audit section with page layout, log-level colour mapping, API reference (
/logs/api/logs,/logs/api/stats,/logs/api/levels,/logs/api/categories), query parameters, response shape and access-control notes - README: updated version badge to 1.5.1
[v1.5.0] - 2026-05-07
🐧 LXC — CT Template Deployment
- Create LXC from CT templates — full deployment workflow for creating LXC containers directly from Proxmox CT template files (
.tar.zst,.tar.gz); node/storage selection, IPAM integration, SSH keys support - Unified Create Instance Wizard — redesigned wizard (
CreateInstanceWizard) supports both VM templates (QEMU) and CT templates (LXC) in a single multi-step flow with type selector, template browser, config step, and confirmation - Reinstall LXC from CT template — reinstall support for containers created from CT templates; hostname, password, SSH keys, and IP address are preserved across reinstall
- Preserve credentials/IP across LXC reinstall — root password, SSH keys, IP configuration, and gateway are carried over automatically when reinstalling an LXC container
- nesting=1 by default — all newly created LXC containers get
nesting=1enabled to ensure compatibility with systemd 255+ (cgroup v2) - Fix: double URL-encoding of SSH public keys — SSH keys passed to Proxmox API during LXC creation no longer get double-encoded
🔑 SSH Keys Management
- SSH Keys API — full CRUD for user SSH key library:
GET /api/ssh-keys,POST /api/ssh-keys,PUT /api/ssh-keys/{id},DELETE /api/ssh-keys/{id} - Admin key management —
GET /api/ssh-keys/user/{user_id}— admins can view and manage SSH keys of any user - Key fingerprint — SHA-256 fingerprint is computed and stored automatically on key creation/update
- Private key storage — optional encrypted private key storage alongside the public key
- SSH Keys Manager UI — new tab in Settings page for adding, editing, and deleting SSH keys; shows key name, fingerprint, comment, and creation date
- Key selector in wizard — when deploying a VM or LXC, SSH keys can be selected from the personal library; admins deploying on behalf of another user can pick from that user's keys
- Per-user isolation — regular users manage only their own keys; users with
users.managepermission can manage keys for any account
🗑️ VM/LXC Operations
- Auto-stop before destroy — if a VM or LXC container is running when a delete request is issued, it is automatically stopped first; prevents Proxmox
can't lock fileerrors on destruction
🖥️ Frontend Improvements
- InstancesPage — refreshed layout, improved status badges and action menus
- NodesPage — updated node cards with cleaner metrics display
- TemplatesPage — improved template list with better filtering and group management
- BackupsPage — fixed several edge-cases in backup listing, restore dialog, and job scheduling UI
- UsersPage — improved user table with better role display and server assignment indicators
- SettingsPage — added SSH Keys Manager section; general UX polish
api-client.ts— added SSH keys API methods and LXC template endpointswebsocket.ts— connection stability improvementstypes/index.ts— addedSSHKey,LXCTemplate,LXCDeployRequesttypes
🛠️ Developer Experience
- Dev mode — new
compose.dev.ymloverride for Vite HMR (hot module replacement); usepve devordocker compose -f compose.yml -f compose.dev.yml up -d frontend; source files are mounted as volumes so changes apply instantly without rebuilding .dev-modemarker — signals to thepveCLI that the frontend is running in dev mode
[v1.4.0] - 2026-04-06
🌐 Networks — SDN Management & Node Interfaces
- Networks page — new unified page (
/proxmox/networks) for managing SDN zones, VNets, subnets, and node-level network interfaces; added to sidebar navigation with dedicated icon - Edit SDN Zone —
PUT /api/servers/{server_id}/sdn/zones/{zone}— update zone properties (mtu, dns, reversedns, ipam, etc.) - Edit SDN VNet —
PUT /api/servers/{server_id}/sdn/vnets/{vnet}— update VNet alias, VLAN tag, vlanaware, etc. - Delete SDN Subnet —
DELETE /api/servers/{server_id}/sdn/vnets/{vnet}/subnets/{subnet_cidr}— delete a subnet; optionally delete linked IPAM network (?delete_ipam_network=true) - Auto-create IPAM network on subnet creation —
POST .../subnetsnow acceptscreate_ipam_network: true; creates a matchingIPAMNetworklinked to the server and VNet, or returns the existing one - Node network interfaces — full CRUD for node-level interfaces (bridges, bonds, VLANs, ethernet): list, get, create, update, delete via
proxmox_client.py - Apply / Revert node network config —
PUTandDELETEon/nodes/{node}/networkto activate or roll back pending changes - Node list endpoint —
GET /api/servers/{server_id}/nodes— returns nodes for a Proxmox server (used by Networks page selectors)
🧹 Code cleanup
- SDN module imports cleaned up — removed unused imports (
ssl,asyncio,httpx,websockets,func,List, etc.) fromsdn.py - Networks router — new
networks.pymodule underapi/proxmox/with HTML page route and node API endpoints; registered inproxmox/__init__.py
🌍 i18n
- 49 new translation keys (EN + RU) for Networks page: interface types, bridge/bond/VLAN fields, apply/revert config, IPAM integration labels, edit zone/vnet, subnet deletion, and more
[v1.3.1] - 2026-04-05
🔍 VM List — Node Filtering & Responsive Toolbar
- Server filter — new dropdown to filter the VM list by Proxmox server/cluster; populated dynamically from loaded VMs
- Node filter — new dropdown to filter by Proxmox node; automatically narrows to nodes belonging to the selected server
- Both filters are saved in URL params (
?server=...&node=...) and restored on page reload - Toolbar redesigned into 2 rows — row 1: all filters (type / status / server / node / search with icon + stats); row 2: select-all checkbox, pagination, action buttons
- Responsive breakpoints — at ≤900px button labels hide; at ≤768px filters wrap 2-per-row; at ≤480px each filter is full-width; stats counter hidden on mobile
populateServerFilter()andpopulateNodeFilter()helper functions populate dropdowns from loaded VM data- Snapshots toolbar migrated from legacy
.vm-toolbar-left/.vm-toolbar-rightclasses to inline flex, unaffected by toolbar refactor
[v1.3.0] - 2026-03-27
🖥️ Console — VNC & Terminal Fixes
- VNC «Connection closed» fixed —
RFBClass(noVNC) now receives the WebSocket URL string directly instead of a pre-openedWebSocketobject; theonFirstMessagehack that broke the RFB handshake before the first frame is fully removed from bothvirtual_machines.htmlandinstance_detail.html - VNCAuth fixed for QEMU —
vncproxyis now called with"generate-password": 1; the returned 8-character DES key is passed to noVNC as the VNC password; falls back toticketwhenpasswordis absent (Proxmox 9.x NoAuth mode) - LXC
vncproxy500 fixed — LXCvncproxyAPI does not acceptgenerate-password; the parameter is omitted for LXC, which usesticketas the VNC password - LXC context menu opens xterm.js terminal — the right-click context menu in the VM list now shows Terminal for
lxctype (callsopenTerminalConsole()) and VNC Console forqemutype; previously all types usedopenVNCConsole() - Terminal modal added to VM list page —
#terminalModalwith full xterm.js (FitAddon, WebLinksAddon, Dracula theme) added tovirtual_machines.html; reuses existing backend endpointsGET /api/{server_id}/container/{vmid}/terminalandWebSocket /proxmox/ws/terminal/{server_id}/{node}/{vmid}
[v1.2.0] - 2026-03-16
🐛 Bug Fix — Disk Resize Lock Conflict
- Root cause fixed —
resize.put()in the Proxmox API is asynchronous and returns a UPID task; the old code did not wait for this task to finish before starting the VM, causing Proxmox to reportcan't lock file '/var/lock/qemu-server/lock-xxx.conf' — got timeoutandcommand '/usr/bin/qemu-img resize' failed: got timeout configure_vm(VM creation from template) — now captures the resize UPID and callswait_for_task(120 s)before returning; the VM can only be started after the disk has been fully resizedresize_vm_disk— same fix applied; the resize task completes before the function returnsresize_container_disk(both LXC methods) — same fix; the restart of the container is now issued only after the resize task is confirmed complete- Removed unnecessary post-resize VM restart — QEMU disk resize operates at the storage layer and does not require a VM reboot; the automatic
restart_vm()call after manual disk resize has been removed to prevent a second lock conflict
[v1.1.8] - 2026-03-16
👤 User → Server Assignment
user_serverstable (Migration 20) — новая таблица-связкаUser ↔ ProxmoxServer; позволяет напрямую закреплять конкретные серверы за пользователями- API
GET /api/users/{id}/servers— список серверов, назначенных пользователю - API
GET /api/users/{id}/server-assignments— расширенный список всех серверов с флагамиassignedиcompatible(совместимость по воркспейсам) - API
PUT /api/users/{id}/servers— установка набора серверов для пользователя; проверяет пересечение воркспейсов — если сервер и пользователь не состоят ни в одном общем воркспейсе, возвращает409 workspace_conflict - Фильтрация серверов для non-admin — обычный пользователь видит только серверы, которые ему назначены и входят в его воркспейс
🖥️ VM / LXC Owner
- API
GET /api/{server_id}/vm/{vmid}/owner— получить текущего владельца VM/LXC и список доступных пользователей - API
PUT /api/{server_id}/vm/{vmid}/owner— назначить или снять владельца (admin-only); действие логируется в audit
🔐 RBAC & Роли
- Migration 21 —
dashboard:viewпринудительно выставлен вfalseдля ролиuser(новый формат ключей) - Migration 22 — ключ
proxmox.cluster.manage→cluster:manageв ролиadmin; старый dot-формат удаляется, чтобы не сбрасывать весь permission-map user_countв ответеGET /api/roles— для каждой роли возвращается количество активных пользователей
🚀 Умный редирект после логина
- После успешного входа производится запрос
GET /api/auth/me— пользователь автоматически перенаправляется на первую страницу, к которой у него есть доступ (/dashboard→/virtual-machines→/vms→/backups→/ipam→/logs→/settings) - Поддержка параметра
?returnUrl=— возврат на запрошенную страницу после логина
🔧 Прочие улучшения
GET /api/serversдля не-привилегированного пользователя объединяет фильтрыassigned_serversиWorkspaceServer— пользователь видит только серверы из своего воркспейса, которые ему назначеныnode_uptimeдобавлен в ответ детального API сервера- Удалена лишняя проверка
PermissionCheckerна GET-роуте страницы/users(HTML)
[v1.1.7] - 2026-03-16
🌍 i18n — Translation Files Refactored
- Translations moved to JSON locale files — all 1 149 translation keys extracted from the Python source into
backend/app/locales/ru.jsonandbackend/app/locales/en.json i18n.pyreduced from 5 287 → 128 lines — now a lightweight JSON loader with lazy initialisation; zero changes to the public API (t(),I18nService.get(),.get_all(),.add_translation())- Adding a new language requires no code changes — drop a
xx.jsonfile intobackend/app/locales/and it is picked up automatically on next startup I18nService.reload()— new method that reloads all locale files at runtime without a container restart; useful for live translation editingI18nService.available_languages()— returns the list of language codes currently loaded from disk
[v1.1.6] - 2026-03-16
🖥️ LXC Terminal — xterm.js Console Fixed
- Root cause identified and fixed — Proxmox
termproxyprotocol requires a mandatory auth handshake: the client must send"USERNAME:VNCTICKET\n"as the very first WebSocket message; Proxmox responds with"OK"before starting the PTY. The backend handler was missing this step entirely, causing Proxmox to wait indefinitely and the browser to show "Disconnected". - Auth handshake added — after connecting to the Proxmox
vncwebsocketendpoint the backend now sends the auth message, validates the"OK"response, and only then starts the bidirectional proxy. - Initial terminal data forwarded — any terminal data arriving in the same
"OK"frame is immediately forwarded to the browser. - Graceful error handling — auth timeout (>10 s) and explicit rejection close the WebSocket with a descriptive reason code instead of silently hanging.
🔧 Fixes
- Fixed
'ProxmoxServer' object has no attribute 'username'— replacedserver.usernamewith correctserver.api_user(with token suffix stripping) - Fixed
CSRFPreventionTokenbeing sent in the request body — now sent only as an HTTP header - Fixed
additional_headers→extra_headers(websockets v12 API rename) - Added URL-encoding for
vncticketin the WebSocket URL (urllib.parse.quote) - Added
PVEAuthCookieheader in the WebSocket upgrade request - Added
subprotocols=["binary"]required by Proxmox vncwebsocket
[v1.1.5] - 2026-03-15
🗂️ Task Drawer — UPID Tracking & Clear Completed
- UPID-based task tracking — VM/LXC control methods (
start,stop,restart) inproxmox_client.pynow return the Proxmox task UPID instead of a boolean; each action automatically registers aProxmoxTaskentry for real-time Proxmox-side progress polling DELETE /proxmox/api/all-tasks/completed— new API endpoint: removes allcompleted/failed/cancelledtasks (bothProxmoxTaskandTaskQueue) for the current user in one request- Clear button in Task Drawer — trash icon appears in the drawer header whenever there are finished tasks; clicking it calls the new endpoint and updates the drawer instantly
- Auto-expire old tasks in Drawer — tasks older than 24 h are hidden from the Task Drawer on load and every 5 minutes; they remain accessible on the
/taskspage openTaskDrawer()global helper — bulk VM operations now open the Task Drawer instead of showing a bottom progress toast, providing a unified task-tracking experience- Human-readable bulk task descriptions —
TaskQueue.to_dict()now maps internaltask_typekeys (bulk_start,bulk_stop, etc.) to localised Russian descriptions
🔧 Fixes
pveCLI nginx detection — mode resolution now checks for the nginx config file (nginx/conf.d/serverpanel.conf) in addition to the runningserverpanel-nginxcontainer, fixing prod-mode detection on already-deployed hosts after container restarts
[v1.1.4] - 2026-03-15
🗂️ Workspaces — Scoped Server Groups
- New Workspace entity: named group of Proxmox servers with scoped user access
- DB models:
Workspace,WorkspaceServer,WorkspaceUserwith automatic DB migration - Full CRUD REST API (
/api/workspaces,/api/workspaces/{id}) — admin-only create/update/delete, filtered list for regular users X-Active-Workspacerequest header propagated from frontend — filters server/VM/backup API responses to the active workspace- Default workspace created on first run; all existing servers assigned to it
- Admin workspace management page (
/workspaces) — create/edit/delete workspaces, assign servers and users - Sidebar workspace selector — active workspace label shown in sidebar, switch without page reload
proxmox_server_detail.html— dedicated server detail page (new template)- i18n keys added for all workspace UI strings (EN + RU)
🔧 Fixes
- Fixed
PermissionCheckerimport error indashboard.py
[v1.1.3] - 2026-03-10
🚨 Dashboard — Alerts Panel & Real-time Node Stats
- New API endpoint
GET /api/dashboard/alerts— returns error/criticalAuditLogentries for the last 24 h (up to 50), protected bylogs.viewpermission - Alerts modal (
openAlertsModal()) on the dashboard status chip — click to view recent errors - Mini sparkline charts (Chart.js) for CPU, RAM, Storage per node — updates in-place without re-rendering
- Node stats fetched in parallel via
Promise.allfor all online servers - Full i18n coverage for new dashboard elements:
nodes_label,clusters_label,alerts_label,all_online,all_healthy,no_alerts,all_systems_operational,view_all,recent_audit_events,no_audit_events,last_24h,ram,ram_usage,storage,paused, and more
🔒 Security — Log sanitisation
- Removed IP addresses from structured log messages in
servers.pyto prevent credential leakage via logs logging_middleware.pynow suppresses noisy GET polling traffic — requests to/proxmox/api/,/api/notifications/unread-count,/settings/api/paneletc. are only logged on HTTP errors (≥ 400) or slow responses (> 5 s)
🎨 UI — CSS variables & GitHub stars
base.html: GitHub stars counter switched from Gitea API to GitHub API (api.github.com,stargazers_count)- Hard-coded
rgba()colours inbackups.htmlandproxmox_vms.htmlreplaced with CSS theme variables (var(--info-light),var(--warning-light)) - Backups server selector redesigned — added icon and label for better clarity
📖 WIKI — Fixes & new content
- Fixed broken anchor links in Table of Contents (
#deployment-guide→#installation-and-deployment) - Added Snapshots section with creation guide, management table, and full API reference
- Added Main Features / Dashboard section
- Fixed broken emoji characters in section headings (
🛠️ pve CLI Tool,🔌 API Reference)
[v1.1.2] - 2026-03-08
🎨 Dashboard Redesign
- New 5-column stat grid: Nodes, VMs, Containers, Clusters, Alerts
- Real-time VM/CT count loaded via API on page open
- Resource cards row with mini sparkline charts: CPU, RAM, Storage
- Status chip in header:
All systems operational/ warnings / critical - Header datetime display (live clock)
- Cluster count computed from DB (named clusters + standalone nodes)
- Alerts count sourced from
AuditLog— errors + criticals in last 24 h - Recent audit events (last 5) now passed to dashboard context
🖥️ Sidebar & Layout (base.html)
- Cluster Selector widget in sidebar — shows active cluster/standalone name
- Version badge in header (
v{{ version }}) page_subtitleandheader_statusJinja2 blocks for per-page overridesloadSidebarCluster()JS helper — fetches known servers, picks named cluster
🛠️ pve CLI Tool
- New
pveshell script at project root — management shortcuts (logs, restart, update, exec, etc.) deploy.sh --install-cli— installspveto/usr/local/bin/pve, patchesPVE_DIRto project path- Help visible after installation:
pve help
🎨 Theme CSS
- New CSS classes for redesigned dashboard:
.stats-grid-5,.stat-card-v2,.resource-cards-row,.resource-card,.version-badge,.status-chip,.header-datetime,.sidebar-cluster-section - Minor CSS fixes across login, logs, tasks, os_templates, users, proxmox_vms, virtual_machines, ipam_dashboard
[v1.1.1] - 2026-03-08
🔧 Fix: Update System — Host-side Rebuild
- Root cause fixed:
docker compose downубивал cgroup контейнера вместе сnohup-скриптом внутри него — rebuild никогда не завершался, был виден только результатgit pull(обновлённыйVERSION) - Новый подход: нажатие «Обновить панель» теперь записывает файл-триггер
.update_triggerв корень проекта - Host-side watchdog (
pvemanager-update.service/update_host.sh) обнаруживает триггер и выполняет на хосте:git pull → docker compose down → docker compose build --no-cache app → docker compose up -d - Watchdog работает как systemd-сервис на хосте — не зависит от жизни контейнера
PROJECT_DIRопределяется динамически в момент установки (не хардкодится)User=в systemd-юните совпадает с пользователем, запустившимdeploy.sh --watchdog- Установка / переустановка watchdog:
sudo ./deploy.sh --watchdog - Лог обновления:
./logs/update_host.log
[v1.1.0] - 2026-03-08
🚀 New Features
Backup Module
- New Backups page with 3 tabs: backup files, storages, scheduled jobs
- Proxmox Backup Server (PBS) support
- APScheduler-based backup job scheduler with cron expressions
- Backup retention policies (keep_last, keep_daily, keep_weekly, keep_monthly)
- Storage pool management (add, edit, delete)
- Task progress tracking via Proxmox UPID
- RBAC permissions for backup resources
IPAM Improvements
- Networks now bound to a specific Proxmox server and node — prevents cross-server IP assignment
- Manual server + network selection modal when linking IP to a VM/LXC
- Dynamic server and node dropdowns in network creation forms
- New
proxmox_nodefield in IPAMNetwork model and schema - Database migration #16
🔧 Fixes
- Update system: now correctly rebuilds Docker image after
git pull - Auto-detect current git branch (no more hardcoded
main) - Update logs saved to persistent
/app/logs/update.logvolume docker-composepackage added to Dockerfile (was missing)
🎨 Theme
- All hardcoded colors (
#fff,rgba(...),color: white) replaced with CSS variables across all major templates
🌍 Localization
- Added Uzbek language keys for:
proxmox_node, node selector, link-allocations modal
[v1.0] - 2025-12-15
🎉 Initial Production Release
Production-ready version with complete feature set for Proxmox management.