# netbox-proxbox developer guide

Developer guide — architecture, integrations, contribution workflow and end-to-end testing.

| Field |Value |
| --- | --- |
| Canonical URL | https://emersonfelipesp.com/netbox-proxbox/developer |
| Showcase | https://emersonfelipesp.com/netbox-proxbox |
| GitHub | https://github.com/emersonfelipesp/netbox-proxbox |
| Releases | https://emersonfelipesp.com/netbox-proxbox/releases |
| Release snapshot synced | 2026-06-21T12:43:39.386Z |

## Intro

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

- 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

| Target |Protocol |Library |Notes |
| --- | --- | --- | --- |
| proxbox-api | HTTP REST + Server-Sent Events + WebSocket | requests + websockets + a small SSE reader in services/backend_proxy.py | Resolved at runtime via FastAPIEndpoint.objects.first() — never imported as a Python dependency. |
| NetBox core (Django ORM + DRF) | in-process | NetBox plugin framework | Plugin lives inside NetBox; persists its own models in NetBox's database and renders inside NetBox's templates. |
| Proxmox VE | indirect | — | The plugin never talks to Proxmox directly; everything goes through proxbox-api. |

## Contributing

Development install:

```shell
pip install -e '.[dev,test,cli]'
```

Pre-PR checks:

- syntax compile: `python -m compileall netbox_proxbox tests`
- lint: `rtk ruff check .`
- type check (cli): `rtk ty check proxbox_cli`
- unit + integration: `rtk 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.

Issues: https://github.com/emersonfelipesp/netbox-proxbox/issues

## CI

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.

| 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. |

- 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, netbox_image, and proxmox_service for focused validation.
- Each matrix cell pulls a dedicated proxmox-sdk image tag — emersonfelipesp/proxmox-sdk:latest-pve, :latest-pbs, :latest-pdm — so the three Proxmox surfaces run in parallel with fail-fast disabled.
- The public MkDocs source of truth is docs/developer/ci-e2e-workflows.md (parallel mock matrix detailed in docs/features/e2e-docker-testing.md).

## End-to-end tests

Framework: Plain Python requests + Docker Compose stack (NetBox + PostgreSQL + Redis + proxbox-api + a per-cell proxmox-sdk mock chosen from latest-pve / latest-pbs / latest-pdm).

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 Docker matrix fans out across NetBox versions × proxmox_service so PVE, Proxmox Backup Server, and Proxmox Datacenter Manager surfaces are exercised in parallel. PVE-only assertions are gated by a stack helper and auto-skip on pbs/pdm cells; the proxbox-api /health smoke runs on every cell.

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 (default pve): `python tests/e2e/e2e_stack_check.py`
- run E2E against PBS mock: `PROXMOX_SERVICE=pbs python tests/e2e/e2e_stack_check.py`
- run E2E against PDM mock: `PROXMOX_SERVICE=pdm python 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:latest-{pve,pbs,pdm} chosen per matrix cell.
- Mock data: tests/e2e/proxmox_openapi_mock_data.json mounted into the proxmox-sdk mock container; the requested service tag drives which OpenAPI surface (PVE / PBS / PDM) is served.
- Matrix axes: netbox_image (3) × install_source ∈ {local, pypi, container, testpypi} × dependency_mode ∈ {dev, published, testpypi-package, pypi-package} × proxmox_service ∈ {pve, pbs, pdm}, with fail-fast disabled.
- 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 (https://github.com/emersonfelipesp/netbox-proxbox/blob/main/.github/workflows/e2e-docker.yml)

## Links

| Label |URL |
| --- | --- |
| repo | https://github.com/emersonfelipesp/netbox-proxbox |
| docs | https://emersonfelipesp.com/netbox-proxbox/docs/ |
| backendRepo | https://github.com/emersonfelipesp/proxbox-api |
| issues | https://github.com/emersonfelipesp/netbox-proxbox/issues |
| contributing | https://github.com/emersonfelipesp/netbox-proxbox/blob/main/CONTRIBUTING.md |
