___ _ | _ \_ _ _____ __| |__ _____ __ | _/ '_/ _ \ \ / '_ \/ _ \ \ / |_| |_| \___/_\_\_.__/\___/_\_\ n e t b o x ⇄ p r o x m o x
emerson@netdevops:~/netbox-proxbox$ ./describe.sh netbox-proxbox
Developer guide — architecture, integrations, contribution workflow and end-to-end testing.
netbox-proxbox is a Django plugin shipped on top of NetBox 4.5.x / 4.6.x. It runs inside the NetBox process and orchestrates all real Proxmox traffic through a sibling FastAPI service called proxbox-api.
This page documents the moving parts a contributor has to understand: how a Full Update click in the NetBox UI ends up streaming clusters, nodes, VMs, snapshots and backups into the source-of-truth, where the code that does it lives, and how the test suite proves the wiring works.
›intro
emerson@netdevops:~/netbox-proxbox/developer$ cat README.md | head
netbox-proxbox is a Django plugin shipped on top of NetBox 4.5.x / 4.6.x. It runs inside the NetBox process and orchestrates all real Proxmox traffic through a sibling FastAPI service called proxbox-api.
This page documents the moving parts a contributor has to understand: how a Full Update click in the NetBox UI ends up streaming clusters, nodes, VMs, snapshots and backups into the source-of-truth, where the code that does it lives, and how the test suite proves the wiring works.
›architecture
emerson@netdevops:~/netbox-proxbox/developer$ tree -L 2 src/
- ├─Plugin entry: netbox_proxbox/__init__.py registers the NetBoxPluginConfig (currently certified against NetBox v4.5.8 → v4.6.x).
- ├─Persisted models: ProxmoxEndpoint, NetBoxEndpoint (singleton), FastAPIEndpoint (singleton), ProxmoxCluster, ProxmoxNode, ProxmoxStorage, BackupRoutine, Replication, VMBackup, VMSnapshot, VMTaskHistory, ProxboxPluginSettings.
- ├─URL routing: netbox_proxbox/urls.py wires every CRUD and operational view; views in netbox_proxbox/views/ extend NetBoxModelViewSet and use register_model_view for related-object panels.
- ├─REST API: netbox_proxbox/api/ exposes DRF NetBoxModelViewSet routes for every persisted model.
- ├─Sync workflow: a Full Update enqueues ProxboxSyncJob on NetBox's RQ default queue (7200s job timeout, 3600s HTTP read timeout). The job calls proxbox-api's full-update/stream endpoint and replays each SSE event back to the browser via netbox_proxbox/services/backend_proxy.py.
- ├─Live log viewer: a separate WebSocket bridge keeps proxbox-api's log buffer streaming inside the plugin UI. Browser-side parsing lives in netbox_proxbox/static/netbox_proxbox/js/.
- ├─Security model: CRUD views use ObjectPermissionRequiredMixin; custom views use ConditionalLoginRequiredMixin (respects NetBox's LOGIN_REQUIRED); operational endpoints use ContentTypePermissionRequiredMixin.
- ├─Companion CLI: proxbox_cli/ ships the pxb command (declared in pyproject.toml [project.scripts]) for headless sync triggers.
›integrations
emerson@netdevops:~/netbox-proxbox/developer$ ./describe-integrations
| › target | › protocol | › library |
|---|---|---|
| proxbox-api | HTTP REST + Server-Sent Events + WebSocket | requests + websockets + a small SSE reader in services/backend_proxy.py |
| NetBox core (Django ORM + DRF) | in-process | NetBox plugin framework |
| Proxmox VE | indirect | — |
- › proxbox-api: Resolved at runtime via FastAPIEndpoint.objects.first() — never imported as a Python dependency.
- › NetBox core (Django ORM + DRF): Plugin lives inside NetBox; persists its own models in NetBox's database and renders inside NetBox's templates.
- › Proxmox VE: The plugin never talks to Proxmox directly; everything goes through proxbox-api.
›contributing
emerson@netdevops:~/netbox-proxbox/developer$ ./contributing --help
# dev install
# pre-PR checks
› syntax compile
shellpython -m compileall netbox_proxbox tests
› lint
shellrtk ruff check .
› type check (cli)
shellrtk ty check proxbox_cli
› unit + integration
shellrtk pytest tests/
# code style
- ├─Linter: ruff (line length 88, select E/F/W).
- ├─Formatter: black.
- ├─Type checker: ty (>=0.0.1a19).
- ├─Pre-commit hooks: .pre-commit-config.yaml (run before opening a PR).
- ├─PRs reference the closing issue with `Closes #<id>`. Contribution guide: CONTRIBUTING.md.
# issue tracker https://github.com/N-Multifibra/netbox-proxbox/issues
›ci
emerson@netdevops:~/netbox-proxbox/developer$ gh workflow list
The CI surface is split between fast package checks, a reusable Docker E2E stack, documentation automation, nightly contract checks, and staged package publishing.
Release validation keeps the plugin and backend on matching package indexes: TestPyPI plugin validation uses TestPyPI proxbox-api, while PyPI candidate and final validation use PyPI proxbox-api.
# workflows
| › workflow | › trigger | › purpose |
|---|---|---|
| ci.yml | push + pull_request | Runs lint, ty, compile checks, pytest coverage, and package metadata contract tests. |
| e2e-docker.yml | workflow_call + manual + nightly | Runs NetBox, rqworker, proxbox-api, PostgreSQL, Redis, and a Proxmox mock in Docker. |
| publish-testpypi.yml | version tags + GitHub releases + manual | Publishes immutable TestPyPI/PyPI package versions and gates them with exact install and E2E validation. |
| docs.yml | docs changes | Builds and publishes the MkDocs site. |
| nightly-contracts.yml | schedule + manual | Checks cross-repo contracts that must stay aligned with proxbox-api. |
# notes
- ├─Never retry a consumed package version with --skip-existing; publish the next .postN or rcN instead.
- ├─The E2E workflow accepts install_source, dependency_mode, proxbox_api_version, and netbox_image for focused validation.
- ├─The public MkDocs source of truth is docs/developer/ci-e2e-workflows.md.
›e2e
emerson@netdevops:~/netbox-proxbox/developer$ ./run-e2e --report
› framework
Plain Python requests + Docker Compose stack (NetBox + PostgreSQL + Redis + proxbox-api + a proxmox-sdk:dev-nginx mock).
There is no pytest E2E target — the suite is a runnable Python script that brings the whole stack up, drives a Full Update, and asserts the resulting NetBox state.
The same suite is wired into GitHub Actions for nightly coverage and for staged package releases: TestPyPI runs install the plugin and proxbox-api from TestPyPI, while PyPI candidate and final runs install both from PyPI.
# commands
› run E2E locally
shellpython tests/e2e/e2e_stack_check.py
# coverage
- ├─Spec files: tests/e2e/e2e_stack_check.py, stack_setup.py, stack_sync.py, stack_common.py, mock_proxmox_api.py.
- ├─Stack: NetBox image netboxcommunity/netbox:v4.5.8 / v4.5.9 / v4.6.0 + Postgres + Redis + proxbox-api + proxmox-sdk:dev-nginx.
- ├─Mock data: tests/e2e/proxmox_openapi_mock_data.json mounted into the proxmox-sdk mock container.
- ├─Matrix axes include install_source ∈ {local, pypi, container, testpypi} and dependency_mode ∈ {dev, published, testpypi-package, pypi-package}.
- ├─Release gate: publish-testpypi.yml publishes to TestPyPI first, validates exact package installs, then promotes PyPI rc/final versions only after E2E passes with the matching proxbox-api package index.
- ├─Schedule: nightly cron 31 2 * * * exercises the full matrix unattended.
› ci workflow: .github/workflows/e2e-docker.yml
›links
emerson@netdevops:~/netbox-proxbox/developer$ links
- repo → https://github.com/N-Multifibra/netbox-proxbox
- docs → https://emersonfelipesp.github.io/netbox-proxbox/
- backendRepo → https://github.com/emersonfelipesp/proxbox-api
- issues → https://github.com/N-Multifibra/netbox-proxbox/issues
- contributing → https://github.com/N-Multifibra/netbox-proxbox/blob/main/CONTRIBUTING.md