Commit Graph

69 Commits

Author SHA1 Message Date
markmorado
bef0bcc542 feat: add Workspace feature — scoped server groups with user access and sidebar selector 2026-03-15 01:00:24 +01:00
markmorado
85cc0ce76d fix: correct PermissionChecker import in dashboard.py 2026-03-10 20:05:11 +01:00
markmorado
3947dae7b9 feat: v1.1.3 — dashboard alerts panel, sparkline charts, log sanitisation, CSS vars 2026-03-10 14:10:00 +01:00
markmorado
a0a502f82a ui: replace native browser dialogs with custom panel modals
- settings.html: confirm() → showConfirm(), prompt() → showPrompt() for update, SMTP test, Telegram test
- backups.html: confirm() → showDeleteConfirm() for backup/storage/job deletion
2026-03-08 20:42:08 +01:00
markmorado
d788ac78c3 feat: v1.1.2 — dashboard redesign, pve CLI tool, sidebar cluster selector 2026-03-08 20:35:43 +01:00
markmorado
b8c6e52c9a fix(update): host-side watchdog replaces in-container rebuild
Root cause: docker compose down killed the nohup script inside the
container before rebuild could complete — only git pull was visible
(updated VERSION file).

Changes:
- update_host.sh: new host-side watchdog (poll .update_trigger every 3s)
  runs: git pull → docker compose down → build --no-cache app → up -d
  PROJECT_DIR and User are dynamic (set at install time, not hardcoded)
- update_service.py: perform_update() now writes .update_trigger instead
  of running git/docker commands inside the container
- deploy.sh: added install_update_watchdog() + --watchdog CLI option;
  generates /etc/systemd/system/pvemanager-update.service dynamically
  with correct User= and WorkingDirectory= for any install path/user
- .gitignore: ignore .update_trigger and generated systemd/ files
- CHANGELOG, VERSION, WIKI: bump to v1.1.1, document new update flow
2026-03-08 19:02:40 +01:00
markmorado
b3db346cfb feat: v1.1.0 — backup module, IPAM node binding, HA, task queue, theme CSS
- Backup module: full CRUD for storages, backup files, scheduled jobs (APScheduler)
- Proxmox client: storage/backup/restore/HA methods
- IPAM: proxmox_node field, server+node binding for networks and allocations
- Task queue service: improvements and new task types
- Monitoring worker: extended metrics and alerts
- HA support: add/remove VMs from Proxmox HA groups
- tasks.html: new task tracking page
- proxmox_vms.html: major UI update (bulk ops, HA, snapshots)
- backups.html: full backup management UI (3 tabs)
- base.html: sidebar backup link, websocket manager
- theme.css: full CSS variables theme, 395 lines added
- migrations: migration #15 (BackupJob), #16 (proxmox_node)
- RBAC: backup resource permissions
- websocket_manager.py: new module for WS connections
2026-03-08 18:29:29 +01:00
markmorado
2c8becc6d4 chore: bump version to 1.1.0
- Backup module with PBS support, APScheduler, storage management
- IPAM: server/node subnet binding, link-allocations modal
- Fix: update system rebuilds Docker image after git pull
- Theme: replace hardcoded colors with CSS variables
- i18n: Uzbek keys for IPAM node selector
2026-03-08 18:27:47 +01:00
markmorado
f1d82ff7ea docs: update WIKI.md to v1.0.5 — IPAM server/node binding, Uzbek locale note 2026-03-08 18:24:56 +01:00
markmorado
91dbf0b81c feat: IPAM improvements - server/node subnet binding, theme color fixes
- IPAM link-allocations: filter networks by proxmox_server_id and proxmox_node
  to prevent cross-server/cross-node IP assignment
- IPAM link-allocations: add manual server+network selection modal before linking
- IPAM add-network forms: add Proxmox server and node selectors with dynamic
  cluster-info loading (ipam_dashboard.html, ipam_networks.html)
- models.py / schemas.py: add proxmox_node field to IPAMNetwork
- migrations: migration #16 adds proxmox_node column to ipam_networks table
- Theme fixes: replace all hardcoded rgba/color:#fff/color:white with CSS vars
  across base.html, virtual_machines.html, instance_detail.html,
  os_templates.html, proxmox_vms.html, ipam_network_detail.html,
  ipam_allocations.html
- i18n: add proxmox_node, node selector, link-allocations modal keys (ru/en)
- Version bump: 1.0.4 -> 1.0.5
2026-03-08 14:17:54 +01:00
markmorado
4bbc02982a fix: update system now rebuilds docker image after git pull
- Add docker-compose package to Dockerfile (was missing, caused silent failure)
- Auto-detect current git branch instead of hardcoding 'main'
- Auto-select compose command (docker compose / docker-compose)
- Write update logs to persistent /app/logs/update.log volume
- Log git pull stdout/stderr for diagnostics
2026-03-08 13:04:02 +01:00
markmorado
835606a0f7 feat: add backup storage module with scheduler, PBS support and icon fixes
- Add BackupJob model and migration 15
- Add RBAC permissions for backup resources
- Add ProxmoxClient storage/backup methods (list, create, restore, delete)
- Add /proxmox/api/backups/* API endpoints
- Add APScheduler-based backup job scheduler service
- Add backups.html template with 3 tabs (backups, storages, jobs)
- Add sidebar navigation link for backups page
- Fix backup page icons (replace SVG with Font Awesome)
- Bump version to 1.0.4
2026-03-08 12:53:26 +01:00
markmorado
8395ccdfde fix: show server IP and admin credentials in deployment output 2026-03-08 12:43:49 +01:00
markmorado
a3abf58453 Update repository URL to git.tzim.uz/markmorado/pvemanager 2026-03-08 12:31:42 +01:00
markmorado
65a71a5742 fix: make backend/.env optional in compose.yml to fix first-run error on clean servers 2026-03-08 12:22:38 +01:00
markmorado
85aa59e7b6 Add favicon, backup scheduler, backup API and templates, RBAC and migration updates 2026-03-08 11:40:41 +01:00
markmorado
7a77ffbd2b fix: use semantic version comparison for update check
String comparison caused local 1.0.3 to show "update available"
when GitHub had 1.0.2, since "1.0.3" != "1.0.2".

Added _is_newer() with proper semver tuple comparison so update_available
is only set when the remote version is strictly greater than local.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-08 02:59:39 +01:00
markmorado
7833df3c39 chore: bump version to 1.0.3
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-08 02:56:08 +01:00
markmorado
3d9d1bb2e0 fix: correct repo URL fallback and HTTP error reporting in update service
- Replace hardcoded legacy Gitea URL in settings.py fallback
- Skip legacy Gitea URL even if saved in DB (treat as unset)
- Track last_response in branch loop so errors report the real HTTP
  status code instead of always showing "HTTP unknown"
- Unify 401/403/404 into one "private or not accessible" message

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-08 02:52:17 +01:00
markmorado
93d60b47e3 fix: correct default repository URL in update service
The fallback repo URL was pointing to the old Gitea instance
(git.tzim.uz/dilshod/pve_manager), causing "Failed to fetch VERSION
file: HTTP unknown" because both main/master branches returned non-200.

Updated to the current GitHub repository.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-08 02:47:17 +01:00
markmorado
eea3534e30 chore: bump version to 1.0.2
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-08 02:42:20 +01:00
markmorado
c07d9e8711 fix: deduplicate dashboard node charts by cluster, not just by node name
Previously seenNodes used only the node name as the dedup key, causing
independent servers that happen to share a default node name (e.g. "pve")
to hide each other's charts.

Fix: /api/{server_id}/nodes now also returns cluster_id — the actual
Proxmox cluster name for clustered servers, or "standalone-{server_id}"
for single-node servers. The dashboard deduplicates by
"cluster_id::node_name", so:
- nodes in the same cluster → deduped correctly (shown once)
- nodes on independent servers with the same name → both shown

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-08 02:37:18 +01:00
markmorado
84015ce0bd fix: make auto-import synchronous, return templates list
The /api/auto-import/{server_id} endpoint ran as a background task
and returned {status: "queued"} with no templates field, while the
frontend's executeAutoImport() immediately called data.templates.forEach()
— causing TypeError: can't access property "forEach", data.templates
is undefined.

Replaced the background task with a synchronous handler that imports
templates in-request and returns {templates: [...], imported_count: N},
matching what the frontend expects.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-08 02:25:35 +01:00
markmorado
a5059555e9 chore: bump version to 1.0.1, update README
- VERSION: 1.0.0 → 1.0.1 (patch — bug fixes only)
- README: full rewrite with modern formatting, accurate badges,
  real GitHub URLs, complete feature list and tech stack table

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-08 02:09:59 +01:00
markmorado
8c5a896683 fix: correct relative imports in proxmox subpackage and CSP headers
- Fix all `from ..` → `from ...` in app/api/proxmox/*.py after the
  proxmox.py split (PR #6) placed modules one level deeper, causing
  ModuleNotFoundError on startup
- Broaden Content-Security-Policy to allow CDN sources used in templates:
  cdnjs.cloudflare.com (Font Awesome), cdn.jsdelivr.net (Bootstrap,
  Chart.js, xterm), fonts.googleapis.com/gstatic.com (Google Fonts),
  esm.sh (noVNC) — the overly-strict CSP was blocking all icons and
  charts from loading in the browser

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-08 01:56:08 +01:00
Dilshod Rasulov
a2b53a1b84 Merge pull request #7 from markmorado/claude/code-review-audit-cxCWB
fix: repair two runtime bugs missed in Q2/Q3
2026-03-07 23:40:37 +05:00
Claude
7c42de11a3 fix: repair two runtime bugs missed in Q2/Q3
- proxmox/__init__.py: re-export get_next_vmid, save_vm_instance,
  get_vm_instance so templates.py import doesn't raise ImportError
  (regression introduced in Q3 split)
- ipam.py:791: remove erroneous await on non-async get_orphan_allocations()
  (missed in Q2 async cleanup)

https://claude.ai/code/session_019rK2wvaWg5zXFwmAPPEB7R
2026-03-07 18:29:33 +00:00
Dilshod Rasulov
02b607d424 Merge pull request #6 from markmorado/claude/code-review-audit-cxCWB
Claude/code review audit cx cwb
2026-03-07 22:39:45 +05:00
Claude
6fb7406d27 refactor: split proxmox.py (4676 lines) into package with 7 modules
- _helpers.py: shared helpers (check_vm_access, _get_proxmox_client, etc.)
- servers.py: HTML pages, server CRUD, resources, node status (16 routes)
- sdn.py: SDN zones/vnets/subnets (10 routes)
- snapshots.py: VM/container snapshots + archives (10 routes)
- vms.py: VM/LXC control, HA, monitoring, VNC, terminal, bulk ops (42 routes)
- tasks.py: Proxmox task management (6 routes)
- __init__.py: re-exports unified router (84 routes total, no public API change)

https://claude.ai/code/session_019rK2wvaWg5zXFwmAPPEB7R
2026-03-07 17:35:17 +00:00
Claude
7bd2dd5b8f refactor: remove spurious async defs in ipam.py, deduplicate ProxmoxClient instantiation
- api/ipam.py: convert 30 async def handlers that had no await to plain def,
  letting FastAPI run them in its thread pool (correct for sync SQLAlchemy I/O);
  cleanup_orphan_allocations kept async (it has await)
- api/proxmox.py: add _get_proxmox_client(server) helper that encapsulates the
  use_password/token branching, replace 58 duplicated 10-line blocks with a
  single call; get_proxmox_resources() call sites left unchanged (different sig)

https://claude.ai/code/session_019rK2wvaWg5zXFwmAPPEB7R
2026-03-07 11:57:44 +00:00
Dilshod Rasulov
1aa0819883 Merge pull request #5 from markmorado/claude/code-review-audit-cxCWB
perf: async Proxmox API, optimized IPAM queries, log cleanup scheduli…
2026-03-07 16:49:50 +05:00
Claude
e05650cc9b perf: async Proxmox API, optimized IPAM queries, log cleanup scheduling, background template import
- proxmox_client.py: add ThreadPoolExecutor(max_workers=20) + async wrapper
  methods (async_get_nodes, async_get_vms, async_get_containers,
  async_get_node_status, async_get_vm_status, async_get_container_status,
  async_get_storages, async_get_all_resources) to avoid blocking event loop
- ipam_service.py: replace full-network allocation scan + Python IP loop with
  per-pool targeted SQL query — only loads IPs for the specific pool being searched
- api/ipam.py: fix N+1 full-table scans on GET /api/allocations — use IN-filtered
  queries on only the network/pool IDs present in the result set
- monitoring_worker.py: wire LoggingService.cleanup_old_logs(days=30) into the
  existing run_cleanup_expired() job so audit logs don't grow unboundedly
- api/templates.py: convert auto_import_templates to async endpoint using
  BackgroundTasks — returns immediately, heavy Proxmox I/O runs in background

https://claude.ai/code/session_019rK2wvaWg5zXFwmAPPEB7R
2026-03-07 11:48:53 +00:00
Dilshod Rasulov
f4b6b36f3b Merge pull request #4 from markmorado/claude/encrypt-db-passwords-cxCWB
security: encrypt sensitive DB fields, clean up dynamic import
2026-03-06 21:19:03 +05:00
Claude
5f688abff3 security: encrypt sensitive DB fields, clean up dynamic import
Encrypt Proxmox server passwords and VM cloud-init passwords in the database:
- Add backend/app/crypto.py: Fernet-based encrypt/decrypt helpers + EncryptedString
  SQLAlchemy TypeDecorator (transparent to all existing code, no API changes)
- Add FERNET_KEY config field (env var); without it values stay plaintext for
  backward compatibility, with a logged warning
- Update models.py: ProxmoxServer.password and VMInstance.cloud_init_password
  now use EncryptedString(255) instead of String(255)
- Add migration 14 in migrations/migrations.py: idempotent re-encryption of
  existing plaintext rows (skipped when FERNET_KEY is not set)

CSRF analysis:
- /api/auth/change-password is protected by JWT Bearer token (Authorization header)
- Browsers cannot auto-include Authorization headers cross-site → CSRF is not
  applicable here; added explanatory comment

Improve migration loading:
- Add migrations/__init__.py to make it a proper Python package
- Replace fragile importlib dynamic loading in main.py with a standard import

https://claude.ai/code/session_019rK2wvaWg5zXFwmAPPEB7R
2026-03-06 16:17:45 +00:00
Dilshod Rasulov
0b898f5c43 Merge pull request #3 from markmorado/claude/code-review-audit-cxCWB
Security hardening: IP validation, CORS config, SSL defaults, and error handling
2026-03-06 20:59:06 +05:00
Claude
91ff467f2f security: fix critical vulnerabilities and code quality issues
Critical fixes:
- init_admin.py: replace hardcoded admin123 password with ADMIN_PASSWORD env var
- proxmox_client.py, models.py: change verify_ssl default from False to True
- api/proxmox.py: use server.verify_ssl instead of hardcoded verify=False in websocket handler
- ssh_client.py: replace AutoAddPolicy (MITM-vulnerable) with WarningPolicy + load_system_host_keys

Security hardening:
- main.py: add security headers middleware (CSP, X-Frame-Options, HSTS, X-XSS-Protection, Referrer-Policy)
- main.py: fix CORS — allow_credentials=True is incompatible with allow_origins=["*"]; read origins from CORS_ORIGINS env var
- auth.py, logging_middleware.py: validate X-Forwarded-For/X-Real-IP to prevent IP spoofing

Performance:
- monitoring_worker.py: wire up cleanup_expired_connections() as hourly scheduled job (was defined but never called)

Code quality:
- logging_service.py: move `import json` from inside function to module level
- ssh_client.py, proxmox_client.py, api/proxmox.py, rbac/migration.py, task_queue_service.py: replace all bare `except:` with `except Exception:`
- .env.example, config.py: document ADMIN_PASSWORD and CORS_ORIGINS settings

https://claude.ai/code/session_019rK2wvaWg5zXFwmAPPEB7R
2026-03-06 15:57:20 +00:00
Dilshod Rasulov
e6facf43f4 Merge pull request #2 from markmorado/qwen-code-ba4211ed-a3e5-4ad3-b1ea-7db4f0846ebd
Update from task ba4211ed-a3e5-4ad3-b1ea-7db4f0846ebd
2026-03-02 19:57:04 +05:00
qwen.ai[bot]
58d1c3f5be update branch 2026-03-02 14:54:42 +00:00
Dilshod Rasulov
384f9253e4 Merge pull request #1 from markmorado/qwen-code-ba4211ed-a3e5-4ad3-b1ea-7db4f0846ebd
Update from task ba4211ed-a3e5-4ad3-b1ea-7db4f0846ebd
2026-03-02 19:39:18 +05:00
qwen.ai[bot]
79dd95c6d4 Initialize default admin user on startup to resolve missing credentials issue
- Updated `backend/app/main.py`: Added automatic execution of `/app/init_admin.py` during application startup to create default admin account
- Modified `.gitignore`: Removed `.env` from ignored files to ensure environment configuration is available during deployment
- Enhanced `lifespan` context manager: Integrated admin initialization with proper error handling and logging
- Improved startup reliability: Ensures default credentials are provisioned regardless of deployment environment

The fix ensures that new deployments automatically set up the default admin user, resolving widespread issues with missing login credentials. The change is robust, idempotent, and logs all initialization steps for debugging.
2026-03-02 14:38:01 +00:00
Dilshod Rasulov
b65be53f28 Clean up CHANGELOG by removing old versions
Removed outdated version information and features for versions v2.1.4 to v1.0.0 from CHANGELOG.md.
2025-12-29 12:35:04 +05:00
Dilshod Rasulov
5731a09064 Change version file to 1.0 2025-12-29 11:29:10 +05:00
19c726aca2 Security: improve password generation in deploy script
- Modified create_default_env() to accept password as parameter
- Modified create_default_backend_env() to accept password and secret key as parameters
- Updated quick_deploy_standalone() to pass generated passwords directly
- Updated quick_deploy_nginx() to pass generated passwords directly
- Ensures no hardcoded passwords are ever written to .env files
- All passwords are now randomly generated with openssl (25 chars for DB, 64 chars for JWT)
2025-12-16 20:30:21 +05:00
4afffe9953 Fix server availability check - use is_admin instead of role relationship 2025-12-16 20:19:12 +05:00
f0e53e2939 Bump version to 1.1.0
New features:
- In-app notifications for new panel version availability
- Git repository selection for updates (configurable via UI)
- Password reset instructions in troubleshooting guide
2025-12-16 20:06:22 +05:00
8a29e3a087 Update WIKI with git repository selection instructions 2025-12-16 20:05:54 +05:00
8dced5479d Add git repository selection for panel updates
- Add repository URL setting to panel_settings table
- Support for multiple git hosting providers (GitHub, Gitea, GitLab, etc.)
- UI selector for predefined repositories (git.tzim.uz and github.com) or custom URL
- Update service now uses repository from database settings
- API endpoints: GET/PUT /api/updates/repository
- Migration for default repository setting
- Translations for repository selection UI
2025-12-16 20:04:57 +05:00
2541360f51 Fix password reset commands - remove emoji to avoid encoding issues 2025-12-16 19:51:25 +05:00
1fda6a595b Add password reset instructions to troubleshooting guide 2025-12-16 19:49:13 +05:00
aa8c06116d Add in-app notifications for new panel version availability
- Add notify_update_available() method to NotificationService
- Add translations for update notifications (ru/en)
- Add 'update' type to default notification types
- Add check_for_panel_updates() background task (runs every 6 hours)
- Notifications include link to settings page for easy update access
- Prevent duplicate notifications for same version
2025-12-16 19:38:04 +05:00