Introduce `ranges_to_string_list` for converting numeric ranges into a
list of readable strings. Update the `vid_ranges_list` property and
templates to use this method for better readability and maintainability.
Add related tests to ensure functionality.
Closes#20516
Commit d22246688 added form prefix support to the `GET` handler to fix
Markdown preview functionality in quick add modals. The form prefix
allows Django to properly namespace field names and IDs when rendering
forms within the quick add modal context.
However, the corresponding change was not made to the `POST` handler. This
created a mismatch where form fields were rendered with the `quickadd-`
prefix during `GET` requests, but the `POST` handler instantiated forms
without the prefix. When users submitted quick add forms, Django looked
for unprefixed field names like `address` and `status` in the `POST` data,
but the actual submitted data used prefixed names like `quickadd-address`
and `quickadd-status`. This caused validation to fail immediately with
"This field is required" errors for all required fields, making every
quick add form unusable.
The fix adds the same prefix detection logic to the `POST` handler that was
added to the `GET` handler, checking for the `_quickadd` parameter in the
query string and applying the `quickadd` prefix when present. This ensures
consistent form field naming between rendering and validation.
A regression test has been added to `MACAddressTestCase` to verify that MAC
addresses can be successfully created via the quick add modal, preventing
this issue from recurring. This test should be promoted to a template
test whenever it becomes possible to determine if a model should support
quick-add functionality.
Introduce a generic lookup for ArrayField(RangeField) that matches rows
where a scalar value is contained by any range in the array
(e.g. VLANGroup.vid_ranges).
Replace the raw-SQL helper in the VLANGroup FilterSet (`contains_vid`)
with the ORM lookup for better maintainability.
Add tests for the lookup and the FilterSet behavior.
Closes#20497
Adjusts the schema mapping for `IntegerRangeSerializer` by setting
`match_subclasses` to `True` and refining the array definition. Adds
an example field for clarity in generated OpenAPI documentation.
Fixes#20494
Add `get_internal_type()` to custom field classes for Django compatibility,
annotate path parameters and operation IDs for background endpoints, and
provide serializer context on the RQ base viewset to clear schema warnings.
Fixes#20365
Introduces a new "facility" field in the bulk edit forms for Site and
Location models. Updates fieldsets and nullable fields to incorporate
the "facility" field.
Closes#20438
* fix(users): Override create_superuser to drop is_staff
Override `UserManager.create_superuser()` to strip `is_staff` from
`extra_fields` and enforce `is_superuser=True`, fixing the `TypeError`
during `createsuperuser` with the custom `User` model.
Fixes#20342
* Set alters_data=True on manager methods
---------
Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>
Introduces cloning functionality for ObjectPermission objects using the
CloningMixin. Updates the constraints field handling, adds JSONField,
and introduces logic to process initial data for cloned objects.
Fixes#15492
Refactors `CableTypeChoices` by reorganizing cable types into more
specific subcategories. Enhances clarity with distinct groups such as
Copper (Twisted Pair, Twinax, Coaxial) and Fiber (Multi Mode, Single
Mode, Other).
Closes#19865
Remove `FHRPGroupAssignmentForm.__init__` logic that tied group choices
to the interface IP prefix. Add `group_id` to the `q` filter to enable
matching by group ID.
Fixes#19262
* Fixes#20327: Device queries are now faster when including ConfidContexts
Move .distinct() from main queryset to tag subquery to eliminate
performance bottleneck when querying devices with config contexts.
The .distinct() call on the main device queryset was causing PostgreSQL
to sort all devices before pagination, resulting in 15x slower API
responses for large installations (10k+ devices, 100+ config contexts).
Moving .distinct() to the tag subquery eliminates duplicates at their
source (GenericForeignKey tag relationships) while preserving the fix
for issues #5314 and #5387 without impacting overall query performance.
* Add performance regression test for config context annotation
The test verifies that:
- Main device queries do not use expensive DISTINCT operations
- Tag subqueries properly use DISTINCT to prevent duplicates from issue #5387
This ensures the optimization from issue #20327 (moving .distinct() from maintaining
query to tag subquery) cannot be accidentally reverted while maintaining the
correctness guarantees for issues #5314 and #5387.
* Address PR feedback, clean up new regression test
The new regression test now avoids casting the query to a string and
inspecting the string, which was brittle at best.
The new approach asserts directly against `queryset.distinct` for the
main query and then finds the subquery that we expect to have distinct
set and verifies that is in fact the case.
I also realized that the use of `connection.query_log` was problematic,
in that it didn't seem to return any queries as expected. This meant
that the test was actually not making any assertions since none of the
code inside of the for loop over `device_queries` ever ran.
* Closes#19944: Add multi-scenario CSV import testing support with cleanup
Enhanced BulkImportObjectsViewTestCase to support multiple CSV import scenarios via dictionary format,
where each scenario runs as a separate subtest with automatic cleanup. This enables testing different
import configurations (e.g., with/without optional fields) in a single test run with clear output
showing which scenario is being tested.
Introduces cleanupSubTest() context manager that uses database savepoints to automatically roll back
changes between subtests, providing test isolation similar to separate test methods. This allows
subtests to create/modify objects without affecting subsequent subtests in the same test method.
Added post_import_callback parameter to bulk import tests, allowing child classes to inject custom
assertions that run before database cleanup. This solves the inheritance problem where child classes
need to verify imported data but the parent's cleanup would roll back the data before assertions could
run.
The callback approach is cleaner than conditional cleanup parameters - it makes the execution timing
explicit and maintains test isolation while still allowing extensibility.
* Fixup ModuleTypeTestCase bulk import test to work with callback mechamisn
* Update CableTestCase to use expanded CSV scenario testing
* Remove unneeded permission cleanup
Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>
* Consolidate scenario name retrieval into method
---------
Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>
* Closes#16137: Remove is_staff boolean from User model
* Remove default is_staff value from UserManager.create_user()
* Restore staff_only on MenuItem
* Introduce IsSuperuser API permission to replace IsAdminUser
* Update and improve RQ task API view tests
* Remove is_staff attribute assignment from RemoteUserBackend
Replaces inline plugin title HTML with a reusable template in
`template_code.py`. Adds a default icon for plugins without custom icons
and updates the table logic to use this template.
Removes redundant logic from the `render_title_long` method to improve
maintainability.
Changes the `order_by` field in `plugins.py` from `name` to
`title_long`.
Fixes#20264
Introduces a sync button in the DataSource table for improved user
interaction. Enables users to trigger sync actions directly from the
table, with context-sensitive availability based on permissions and
record status.
Closes#19547
This fix actually fixes this for all valid JSON values that evaluate to
`False` in Python when loaded and cast to bool:
`bool(json.loads(<val>))`.
- `{}`
- `[]`
- `0`
- `False`
This does not change the behavior of `()` or `""` which are both
explicitly cited as "empty" values on `JSONField`.
Adds the `accessor` attribute with `tables.A('is_loaded')` to the
`is_installed` column in the plugin's table. This ensures proper data
access and improves the table's functionality.
Fixes#19744
Changes the value of `to_field_name` from `name` to `address` in the
VPN bulk import form. This ensures proper mapping and validation for
IP address selection during the bulk import process.
Closes#20238
Introduces `TunnelGroupIndex` for enabling search functionality on
Tunnel Groups. Includes searchable fields for `name` and `description`
with respective weights and display attributes.
Closes#20237
Resolves performance issue where prefix deletion with 2000+ children
took 5-10 minutes due to sequential scans in hierarchy depth/children
calculations. Adding PostgreSQL GiST index with inet_ops enables efficient
network containment operators (>>, <<, <<=) in annotate_hierarchy() queries.
Performance impact:
- 30-60x speedup: 5-10 minutes → 10 seconds for large prefix deletions
- Real-world validation: 4s migration time on 1.24M prefix dataset
- Storage cost: 47MB index (11% of table storage, 38 bytes per prefix)
Works in conjunction with existing B-tree indexes on vrf_id for optimal
query performance. Benefits all network containment operations including
hierarchy navigation, aggregate views, and available IP/prefix calculations.
* Closes#20003: Introduce mechanism to register callbacks for webhook context
* Swap ContentType with ObjectType
* Add plugin dev documentation for webhook callbacks
* Fix tests
* Add note about namespacing webhook data
* Fixes#19986: Fix plugin list view button URLs
Plugin list view action buttons (Add, Import, Export) were generating 404
errors because ObjectAction.get_url() was manually constructing viewnames
without the required "plugins:" namespace prefix for plugin models.
Replace manual viewname construction with NetBox's get_viewname() utility
function, which properly handles plugin detection and namespace prefixing
for both core and plugin models.
* Ensure expected URL patterns are registered, ensures tests pass
- Extract script list content into reusable partial template
- Add object-list CSS class for proper embedded table styling
- Hide module headers and management actions in widget context
- Use compact buttons with icon-only labels for widgets
- Add test coverage for embedded parameter handling
The embedded version now renders cleanly in dashboard widgets while
preserving full functionality in the main script list page.
* Fix MAC address pagination duplicates by adding 'pk' to model ordering
Add 'pk' to MACAddress model ordering to ensure deterministic results
when multiple MAC addresses have the same value. This prevents the same
MAC address from appearing on multiple pages during pagination.
The issue occurred because Django's default ordering by 'mac_address'
alone is non-deterministic when multiple records share the same MAC
address value, causing inconsistent pagination results when the same
MAC address is assigned to multiple interfaces on a device.
Added regression test that verifies MAC addresses with identical values
are properly ordered by their primary key, ensuring consistent pagination
behavior across the application.
Fixes netbox-community#19917
* Remove test
* Resolve migration conflict
---------
Co-authored-by: Jad Seifeddine <jseifeddine@macquarietelecom.com>
Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>
Replace direct string concatenation with URLSearchParams to properly
encode user input in export link URLs, preventing injection of malicious
parameters or scripts through the search functionality.
Resolves CodeQL Alert #63 (js/xss-through-dom)
* Closes#19977: Denormalize site, location, and rack for device components
* Set blank=True on denormalized ForeignKeys
* Populate denormalized field in test data
* Ignore private fields when constructing test GraphQL requests
* Closes#19968: Use multiple selection lists for the assignment of object types when editing a permission
* Remove errant logging statements
* Defer compilation of choices for object_types
* Fix test data
* Convert ObjectType to a concrete child model of ContentType
* Add public flag to ObjectType
* Catch post_migrate signal to update ObjectTypes
* Reference ObjectType records instead of registry for feature support
* Automatically create ObjectTypes
* Introduce has_feature() utility function
* ObjectTypeManager should not inherit from ContentTypeManager
* Misc cleanup
* Don't populate ObjectTypes during migration
* Don't automatically create ObjectTypes when a ContentType is created
* Fix test
* Extend has_feature() to accept a model or OT/CT
* Misc cleanup
* Deprecate get_for_id() on ObjectTypeManager
* Rename contenttypes.py to object_types.py
* Add index to features ArrayField
* Keep FK & M2M fields pointing to ContentType
* Add get_for_models() to ObjectTypeManager
* Add tests for manager methods & utility functions
* Fix migrations for M2M relations to ObjectType
* model_is_public() should return False for non-core & non-plugin models
* Order ObjectType by app_label & model name
* Resolve migrations conflict
* Fixes#18900: introduce/raise QuerySetNotOrdered exception
Defines a new exception, `QuerySetNotOrdered`, and raises it in
`OptionalLimitOffsetPagination.paginate_queryset` in the right
conditions:
- the iterable to be paginated is a QuerySet isinstance
- the `queryset.ordered` flag is not truthy
* Don't try to reapply ordering if ordering is already present
* Add ordering for failing tagged-objects list API endpoint
I chose to implement this here for TaggedItemViewSet, rather than on the
model, because any meaningful ordering is going to be done on the
related Tag instance and I didn't want to introduce potential, not well
understood side-effects by applying a model-wide ordering via a related
model field.
* Add default Token ordering behavior
* Adds basic tests for raising QuerySetNotOrdered
* Note why ordering is not applied in TaggedItem.Meta
* Add message field to ObjectChange model
* Set max length on changelog message
* Enable changelog messages for single object operations
* Fix tests
* Add changelog message support for bulk edit & bulk delete
* Cosmetic improvements to form fields
* Fix bulk operation templates
* Add message support for bulk import/update
* Add REST API support for changelog messages (WIP)
* Fix changelog_message assignment
* Enable changelog message support for bulk deletions
* Add documentation
* Fix changelog message support for VirtualChassis
* Add ChangeLoggingMixin to necesssary model forms
* Introduce get_random_string() utility function for tests
* Incorporate changelog messages for object view tests
* Incorporate changelog messages for object bulk view tests
* Add missing mixins for changelog message support
* Tweak test to generate expected number of change records
* Finish adding tests for changelog message functionality
* Misc cleanup
* Fixes#19956: Prevent duplicate deletion records from cascading deletions
* Tweak bulk deletion test to work around cascading deletions issue
* Correct API URL
* feat(dcim): Add site fields to Cable bulk import form
Introduces `side_a_site` and `side_b_site` fields for the Cable bulk
import form. Limits device choices on both sides to the selected site
for improved input validation and consistency.
* feat(dcim): Enhance test data setup with multiple sites
Refactors tests to create multiple sites and assign devices accordingly.
Updates CSV data to include `side_a_site` and `side_b_site` fields for
scenarios involving multiple sites. This improves test coverage and
alignment with real-world use cases.
* docs(dcim): Update comments explaining indent for CSV import
Improved the inline comments to clarify the rationale behind allowing
devices with duplicate names on different sites during CSV bulk import.
The select list of 'Images and Label', 'Images Only', and 'Label Only'
was broken during recent work while implementing #19823.
This fixes the issue by placing the `rack_elevation` class attribute on
the <div> element that contains the SVG after being loaded by HTMX. In
addition, we needed to slightly modify the selectors in the frontend
code that looked for the elements within the SVG to hide and/or show.
Previously, it was looking inside of a contentDocument embedded in an
<object> element. The simplified version just looks inside of the
SVG containing div.
* Show human-friendly values for file size
* Introduce optional dedicated columns for name & filename
* Add combined dimensions column
* Restore image preview on hover
* Remove object_type from default columns list
* Parent column is not orderable
* Filter/search image attachments by filename
* Correct table column name
* Closes: #18588: Relabel Service model to Application Service
Updates the `verbose_name` of the `Service` and `ServiceTemplate` models to "Application Service" and
"Application Service Template" respectively. This serves as the foundational change for relabeling
the model throughout the user interface to reduce ambiguity.
To preserve backward compatibility for the REST and GraphQL APIs, the test suites have been updated
to assert the stability of the original field and parameter names. This includes:
* Using `filter_name_map` in the filterset test case to ensure API query parameters remain
`service` and `service_id`.
* Employing the GraphQL test suite's aliasing mechanism to ensure the public schema remains
unchanged despite the underlying `verbose_name` modification.
Subsequent commits will address UI-specific labels in navigation, tables, forms, and templates.
* Rename to Application Services/Application Service Templates in nav menu
* Rename ~service to ~'Application Service' in templates
This was done for both the Service model and Service Template model
appearances in templates where the word was hardcoded.
* Change ~service to ~'application service' hardcoded strings in Python files
* Update ~service to ~'application service' in docs
* Add background_job toggle to BulkEditForm
* Account for bug fix in v4.3.4
* Enable background jobs for bulk edit & bulk delete
* Move background_job field to a mixin
* Cosmetic improvements
* Misc cleanup
* Fix BackgroundJobMixin
Replaced manual rendering of custom fields in the filter tab with the
`render_custom_fields` template tag. This change ensures that custom fields are
properly grouped, addressing the issue where they were previously displayed
without their associated groups.
* Fixes#19800: ModuleType import supports associating ModuleTypeProfile
* Fixes up ModuleTypeTestCase to include bulk import testing
Also includes an additional regression assertion.
* Address PR feedback
I ultimately left the extra asserts in for test_bulk_import_objects_with_permissionsince
since the parent test is currently only testing against number of
objects successfully imported. Will file a follow up FR to improve that
test.
* Support menu items that are callables
* Fix quote on add button
* Clarify docstring to differentiate link and url
* Back out support for callables but keep alternate prerendered url param
* Make url a property on MenuItem/PluginMenuItem etc, overridable via a setter
* Use reverse_lazy instead of reverse
* Use reverse_lazy instead of reverse
* Initial work on #19589
* Add tooling for handling background requests
* UI notification should link to enqueued job
* Use an informative name for the job
* Disable background jobs for file uploads
* Closes#19231: Add bulk renaming support for all models
* Introduce a template filter for getattr()
* Extend BulkRenameView to support arbitrary field names
* Address bulk renaming support for remaining models
* Bulk rename URL resolution should fail silently
* Update documentation
* Fix bulk button rendering for HTMX requests
* Initial work on #19735
* Work in progress
* Remove ClusterRemoveDevicesView (anti-pattern)
* Misc cleanup
* Fix has_bulk_actions
* Fix has_bulk_actions for ObjectChildrenView
* Restore clone button
* Misc cleanup
* Clean up custom bulk actions
* Rename individual object actions
* Collapse into a single template tag
* Fix support for legacy action dicts
* Rename bulk attr to multi
* clone_button tag should fail silently if view name is invalid
* Clean up action buttons
* Fix export button label
* Replace clone_button with an ObjectAction
* Create object actions for adding device/VM components
* Move core_sync.html to core app
* Remove extra_bulk_buttons from template doc
- Expands the logic in ServiceImportForm.clean() to handle properly
validation of FHRPGroup assignments and maintain the existing
[VM]Interface validation checks.
- Includes an extension to ServiceTestCase.csv_data to act as a
regression test for this behavior.
* 19644 set atomic transactions to appropriate database
* 19644 set atomic transactions for Job Script run
* 19644 set atomic transactions to appropriate database
* 19644 set atomic transactions to appropriate database
* 19644 fix review comments
* 19644 fix review comments
* Add condition to ScriptResultView.get function to generate a download
file of job output if job is completed
* Update template script_result.html adding a download button to trigger
output download in ScriptResultView.get
* Simplify conditional logic; tweak timestamp format
---------
Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>
The collector we use to notify users about dependent object that will be
deleted does handle GFKs. However, a GenericRelation must be set up on
the other end.
Ensures the `queryset.none()` method is called properly with
parentheses. This fixes a potential issue where the method would not
execute as intended, improving the stability and correctness of the
filter logic.
Fixes the reference from `interface_a` to `interface_b` in the
validation error message for WirelessLink. Ensures the correct field is
indicated during validation errors.
* Update values to ensure consistency when referencing values see\t
* Update required-parameters.md For Updated Django Link
* Update required-parameters.md to fix Django link
* Update error-reporting.md Remove Number Formatting
* Update docs/configuration/error-reporting.md
---------
Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>
* feat(project): Add project metadata to pyproject.toml
Introduces project metadata, including name, version, authors, and
description, to `pyproject.toml` for enhanced package definition.
Also includes URLs for source code, documentation, and issue tracking.
* docs(release): Add checklist item for Python versions in pyproject.toml
Include step to update minimum and supported Python versions
in the project metadata file as part of the release process.
* docs(release): Update checklist to include pyproject.toml versioning
Add a step to update the version in `pyproject.toml` alongside
`release.yaml`.
* feat(project): Update pyproject.toml for best practices
Refreshes metadata to resolve deprecations and follow packaging best
practices. Updates include description, license, Python versions,
classifiers, maintainers, and repository URLs for improved compliance.
* fix(project): Update repository URL key in pyproject.toml
Replaces the 'Repository' key with 'Source' in accordance with updated
metadata conventions. This ensures compliance with modern best
practices for project metadata.
* fix(project): Specify Python 3 :: Only in classifiers
Updates the Python version classifier in `pyproject.toml` to indicate
support exclusively for Python 3. This change ensures clarity in the
supported Python versions for the project metadata.
* Fixes#19487: make CircuitTermination.termination GFK not orderable
* Add test to ensure no more broken sorting for CircuitTerminationTable
* Fix CircuitTerminationTable.site_group accessor
* Make TunnelTerminationTable.termination GFK field non-orderable
Provides instructions for removing stale Content Types and related
Permissions after uninstalling a plugin. Includes steps for identifying
and safely deleting stale entries to prevent issues in the permissions
management UI.
The ability to render nested templates was accidentally removed with the
implementation of #17653, which normalized the behavior of various Jinja2
template rendering actions.
This fix restores that behavior while retaining the normalized behavior.
This fix also includes regression tests to ensure this behavior is not
removed accidentally again in the future.
* Fixes#19415: Increased Circuit/WirelessLink absolute distance upper limit
Also adds form validation that provides a useful message to the user
rather than a 500 error with potentially little information.
* Include forgotten migration files
* Remove unnecessary comments
* Remove more unnecessary comments
* Addresses PR feedback
* Gah, remove django migration header comment
* Clean up new has_field_errors mechanism, fix issue with ObjectAttribute
* Address PR feedback, revert changes to render_fieldset template tag
Extend `InterfaceSpeedChoices` to include 2.5 Gbps and 5 Gbps values.
This improves support for modern interface speeds and enhances API data
validation.
Introduces a search index for the Tag model to enable global search for
Tags. Includes fields for name, slug, and description with corresponding
weight values. Display attributes are limited to the description field.
Fixes#17073
Hat tip to @pheus. Thanks!
I did end up leaving the filter function arguments as the Sass
processor complains when you try calling a filter function without
an argument. :/
* On delete signal handling, manually save the related object in a ManyToOneRel to trigger a change record
* Only set remote field to None if null=True on the relation
Refactors the 'type' column to use ColoredLabelColumn for improved
visual distinction, aligning it with the rack roles display.
Removes the now redundant 'linkify' attribute from the column
definition.
* feat(dcim): Add VLAN Translation Policy to Filter Form
Introduces support for VLAN Translation Policies in the Interface
Filter Form.
* feat(virtualization): Add VLAN Translation Policy to Filter Form
Introduces support for VLAN Translation Policies in the Interface
Filter Form.
* feat(dcim): Add VLAN mode filter to CommonInterface
Introduces a new FilterSet for VLAN mode in CommonInterfaceFilterSet.
This allows filtering interfaces based on their VLAN mode using defined
choices.
* feat(dcim): Add VLAN mode filter to Interface FilterForm
Add a field to InterfaceFilterSet to filter interfaces by 802.1Q VLAN
mode.
* feat(virtualization): Add VLAN mode filter to VMInterface
Add a field to VMInterfaceFilterSet to filter interfaces by 802.1Q VLAN
mode.
* fix(dcim): Correct mode filter parameter type in tests
Updates the `mode` filter parameter to accept a list instead of a single
value in `test_filtersets.py`. Ensures proper count assertion for
accurate test behavior.
* feat(virtualization): Add tests for VLAN mode filtering
Introduces tests to validate filtering by `mode` for VMInterface.
Ensures correct filtering for 802.1Q VLAN mode.
* refactor(virtualization): Reorganize FieldSets in FilterSets
Splits the 'Attributes' FieldSet into two distinct FieldSets for better
clarity: 'Attributes' and 'Addressing'. This improves form organization
and makes it more intuitive for users.
* feat(dcim): Add filter by location slug for Device
Introduces a TreeNodeMultipleChoiceFilter for filtering locations by
slug. Enhances filtering flexibility in the Device model by supporting
both ID and slug lookups.
Fixes#19056
* feat(dcim): Add Device filtering by location slug in tests
Extend test cases to include filtering by location slug. Ensures the
FilterSet works correctly with slug-based queries for locations.
Fixes#19056
* feat(ipam): Add VLAN group filters to IPAM FilterSet
Introduces filters for VLAN groups using both ID and slug fields.
* feat(ipam): Add VLAN group filter in IPAM FilterForm
Introduces a `vlan_group_id` filter to IPAM forms for filtering based on
VLAN groups.
* feat(ipam): Add VLAN group filtering to tests
Introduces tests for VLAN group filtering in FilterSets. This ensures
correct validation and behavior when filtering by VLAN group.
* Add SavedTableConfig
* Update table configuration logic to support TableConfigs
* Update table config link when updating table
* Correct docstring
* Misc cleanup
* Use multi-select widgets for column selection
* Return null config params for tables with no model
* Fix auto-selection of selected columns
* Update migration
* Clean up template
* Enforce enabled/shared flags
* Search/filter by table name
* Misc cleanup
* Fix population of selected columns
* Ordering field should not be required
* Enable cloning for TableConfig
* Misc cleanup
* Add model documentation for TableConfig
* Drop slug field from TableConfig
* Improve TableConfig validation
* Remove add button from TableConfig list view
* Fix ordering validation to account for leading hyphens
* 19073 allow plugins to be marked as hidden or disabled in plugins table
* 19073 allow plugins to be marked as hidden or disabled in plugins table
* 19073 allow plugins to be marked as hidden or disabled in plugins table
* 19073 review changes
* Rename 'unlinked' to 'static' & update docs
---------
Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>
Add steps to update the dependency requirements matrix for each minor
release in the release checklist. Clarify how to document changes for
system requirements and linked installation guides.
Fixes#18733
* fix(forms): Call super().clean() in clean methods
Adds a call to super().clean() in the clean methods of object creation
forms. This ensures base class validation logic is executed properly
before custom logic is applied.
Fixes#19041
* test(forms): Add tests for front port form validation
Introduces unit tests for validating FrontPortCreateForm behavior.
Tests include scenarios for matching and mismatched name-label pairs
to ensure proper form validation logic.
Fixes#19041
* Omit errant print statement
---------
Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>
* Move Module & ModuleType models to a separate file
* Add ModuleTypeProfile & related fields
* Initial work on JSON schema validation
* Add attributes property on ModuleType
* Introduce MultipleOfValidator
* Introduce JSONSchemaProperty
* Enable dynamic form field rendering
* Misc cleanup
* Fix migration conflict
* Ensure deterministic ordering of attriubte fields
* Support choices & default values
* Include module type attributes on module view
* Enable modifying individual attributes via REST API
* Enable filtering by attribute values
* Add documentation & tests
* Schema should be optional
* Include attributes column for profiles
* Profile is nullable
* Include some initial profiles to be installed via migration
* Fix migrations conflict
* Fix filterset test
* Misc cleanup
* Fixes#19023: get_field_value() should respect null values in bound forms (#19024)
* Skip filters which do not specify a JSON-serializable value
* Fix handling of array item types
* Fix initial data in schema field during bulk edit
* Implement sanity checking for JSON schema definitions
* Fall back to filtering by string value
Adds a dependency matrix to the upgrade guide, detailing supported
Python, PostgreSQL, and Redis versions for each NetBox release. This
helps users verify compatibility before upgrading.
Fixes#18733
Made DeviceRoles hierarchical, had to also change the filtersets for Device, ConfigContext and VirtualMachine to use the TreeNodeMultipleChoiceFilter.
Note: The model was changed to use NestedGroupModel, a side-effect of this is it also adds comments field, but I thought that was better then doing a one-off just for DeviceRole and having to define the fields, validators, etc.. - keeps everything DRY / consistent.
* 18981 Make Device Roles Hierarchical
* 18981 forms, serializer
* 18981 fix tests
* 18981 fix tests
* 18981 fix tests
* 18981 fix tests
* 18981 fix tests
* 18981 fix migration merge
* 18981 fix tests
* 18981 fix filtersets
* 18981 fix tests
* 18981 comments
* 18981 review changes
* Employ native PostgreSQL functions for updating object JSON data when adding/removing custom fields
* Optimize rename_object_data()
* remove_stale_data() should validate model class
* Add fhrpgroup to IPAddressImportForm
* Change fhrpgroup accessor to name
* rename fhrpgroup to fhrp_group
* Add fhrp_group to IPAddressTestCase csv_data
* Fixes#17443: Adds ExportTemplate.file_name field
* Addresses PR feedback
- Adds `file_name` to `ExportTemplateBulkEditForm.nullable_fields`
- Shortens max length of `ExportTemplate.file_name` to 200 chars
- Adds tests for `ExportTemplateFilterSet.file_extension`
* Fixes migration conflict caused by fix for #17841
Closes: #15842
Branched from #18145 by @tobiasge
Provides a new LOGIN_FORM_HIDDEN setting which allows the administrator to hide the local login form, intended only to be used when SSO is used exclusively for authentication. Note that this means local login will be impossible in the event of SSO provider issues, and can be remedied only through a change to the application config and a restart of the service.
* #15842 - Hide login form
This doesn't implement the full solution proposed in #15842 but enables
administrators to hide the login form when users should only login with a SSO
provider. To prevent a complete lockout when the SSO provider is having
issues the GET parameter `skipsso` can be added to the login URL to show
the form regardless.
* Remove skipsso backdoor
* Add warning
---------
Co-authored-by: Tobias Genannt <tobias.genannt@qbeyond.de>
- [x] 1. Add the field to the model class
- [x] 2. Generate and run database migrations
- [NA] 3. Add validation logic to clean()
- [NA] 4. Update relevant querysets
- [x] 5. Update API serializer
- [x] 6. Add fields to forms
- [x] dcim.forms.model_forms.LocationForm, create/edit (e.g. model_forms.py)
- [x] dcim.forms.buld_edit.LocationBulkEditForm, bulk edit
- [x] dcim.dorms.bulk_import.LocationImportForm, CSV import
- [x] filter (UI and API)
- [NA] UI
- Note: could not find any comments related things in filtersets
- [x] API
- [x] 7. Extend object filter set
- [x] 8. Add column to object table
- [x] 9. Update the SearchIndex
- [x] 10. Update the UI templates
- [x] 11. Create/extend test cases
- [NA] models
- [x] views
- [NA] forms
- [x] filtersets
- [x] api
- [NA] 12. Update the model's documentation
* Fixes#18845: restores sort behavior for DeviceTable.name column
* Remove accessor/order_by and modify DEVICE_LINK template
Thanks to @alehaa for the suggestion.
This also includes an additional `.select_related()` operation on
`DeviceListView.queryset` to avoid extra queries. Thanks to
@renatoalmeidaoliveira and @jeremystretch for pointing out the need for
this.
* Fixes: #18568 Update mkdocstrings and adapt config
* Fixed some output formatting errors
When trying to compare the output from "mkdocstrings[python-legacy]==0.27.0" and
"mkdocstrings[python]==0.28.2" I encountered some HTML errors:
- <div> inside a <p>
- unescaped non-tags <pk>
* Skip incompatible plugins during startup and remove from PLUGINS
* Handle exceptions on request processors in incompatible plugins, and display status in Plugins page
* Revert "Handle exceptions on request processors in incompatible plugins, and display status in Plugins page"
This reverts commit d97bf2ab146114cc13d751878a17a383de0fd5f8.
* Resolve merge conflicts
* Skip incompatible plugins during startup and remove from PLUGINS
* Rename Installed column to Active, and add custom PluginActiveColumn with tooltip
* Fix is_installed
* Simplify plugin_config.validate syntax
Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>
* Merge feature
* Revert "Merge feature"
This reverts commit d1ea60f082.
* Undo simplification
* Add failed_to_load logic
* Use a TemplateColumn for is_installed
* Remove custom column class
* Remove merge vestige
* Simplify plugin attributes for is_installed column
* Use placeholders for false values to increase legibility of the plugins table
---------
Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>
* Add Contact filter to Services
* Add ContactModelFilterForm to ProviderAccountFilterForm
* Add Contact filter support for Aggregate
* Add Contact filter support for Prefix
* Add Contact filter to IPRange
* Add Contact filter to IPAddress
* Add Contact filter to L2VPN
* Add Contact filter to TunnelGroup
* Add Contact filter to Tunnel
* Add ContactModelFilterSet to ProviderAccountFilterSet
* Fixes classes inheritance order
Setup NetBoxModelFilterSetForm as the last inherited class
Co-authored-by: Jason Novinger <jnovinger@gmail.com>
---------
Co-authored-by: Jason Novinger <jnovinger@gmail.com>
* Add sync_interval to DataSource
* Enqueue a SyncDataSourceJob when needed after saving a DataSource
* Fix logic for clearing pending jobs on interval change
* Fix lingering background tasks after modifying DataSource
* Fixes: #15924 - Prevent API payload from allowing tagged_vlans while interface mode is set to taged-all
* Prevent cleanup of tagged_vlans when no tagged_vlans set on interface
* Fix test errors
* Remove accidental debug statements
* Update validation to model clean method instead of serializer
* Remove clearing of tagged vlans from `save()`
* Make changes to validation to account for M2M not being available under model in addition to not being able to check incoming vlans under same model.
* Optimize untagged vlan check
* Re-ordering statements in validators
* Forgot to call super().clean()
* Adjust logic for form and serializer. Add tests
* Fix test failure
* Fix ruff errors
* Fix test by removing now invalid test
* Update serializer, form and tests
* Optimize API test for vlan fields
* Optimize API serializer logic
---------
Co-authored-by: Daniel Sheppard <dans@dansheps.com>
Adds:
- dcim.choices.PowerOutletStatusChoices
- dcim.models.device_components.PowerOutlet.status field with `choices`
set to PowerOutletStatusChoices
- adds migration for PowerOutlet.status field
- updates breaking view tests
* Add SPB in L2VPN
* Change category as Other
Co-authored-by: Daniel Sheppard <dans@dansheps.com>
---------
Co-authored-by: Daniel Sheppard <dans@dansheps.com>
* 18296 add tenant to vlan groups
* 18296 add tenant to vlan groups
* 18296 add tenant to vlan groups
* 18296 add tenant to vlan groups
* 18296 review changes
During serialization, custom fields may be available to a model due to
multi-table inheritance, but might not be available in serialized data
because only direct fields of the model are covered. Now this attribute
is only used if available in serialized data. Models using multi-table
inheritance must modify their serialize_object() method to cover parent
serialization.
* Fixes#18585: filtering circuits by location
This also fixes a related issue where selected filter is not shown in
the filter form.
Changes:
- Adds `CircuitFilterSet.location_id` field to enable filtering with
incoming GET params
- Adds `CirciotFilterForm.location_id` field to enable filtering from
list form
- Adds `location_id` to the Location fieldset on `CircuitFilterForm`
* Adds test for new CircuitFilterset.location_id filter
* Fix model URL generator for plugins
* Fix reverse accessor warning
* Revert "Fix reverse accessor warning"
This reverts commit f07642bb99.
* Add URL test case for regular models
* Split dummy models
Instead of using a single model for testing, one is used for testing the
plugin API and a dedicated one is used for testing the NetBox plugin
model features.
* Fix filterset test case error
* Rename test module
---------
Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>
* Add racktype_count annotation to list view queryset, create the LinkedCountColumn in ManufacturerTable
* Add Manufacturer field to RackTypeFilterForm
* Setup ObjectChangeFilterForm __init__ to add query_param to filter_id
* code lint, move __init__ to end of class
* Move filter_id widget setup to SavedFiltersMixin, and add model attributes to Models FilterForms
* Add missing model declarations for filter forms
---------
Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>
* Changed LogLevelChoices order; Changed ScriptResultView to select LogLevelChoices to LOG_DEFAULT and setup the html template to put (All) in the last one
* Change LogLevelChoices in ScriptResultView get_table method
* Remove default option, add Default string to INFO
* Fix scripts.py and reports.py to reflect removing DEFAULT level
* fix linting
* Disable sorting by `mac_address` for legacy `mac_address` field for Device and VM Interfaces
* Ensure `primary_mac_address` field is included in field list for Device and VM Interfaces
* Remove the json filter for protection rules
* Configure PROTECTION_RULE config attribute to use ConfigJSONEncoder as serializer
* Tweak getattr()
---------
Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>
* Remove 'site' and 'provider_network' from CircuitTerminationIndex.display_attrs
* Use '_site' and '_provider_network' in display_attrs
* Replace private fields with 'termination'
* Iterate through a freshly queried set of CableTerminations to find endpoints in update_connected_endpoints
* Add defensive break if q_filter has not been populated
* Rename circuit to member on CircuitGroupAssignment
* Support group assignment for virtual circuits
* Update release notes
* Introduce separate nav menu heading for circuit groups
* Add generic relations for group assignments
* Remove obsolete code
* Clean up bulk import & extend tests
* Validate that a scope has been selected if a scope_type is specified, on CachedScopeMixin models
* Cleaner logic
* Call super().clean() after validating scope_type/scope
* Handle condition gracefully where an empty object list is passed in to draw_far_objects (e.g. orphaned cable where attached device has been deleted)
* Move continue statement to right after draw_far_objects
* Preferable falsy syntax
Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>
* Check far_ends rather than altering draw_far_objects
---------
Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>
* Use table_htmx.html for assigning ipaddresses
* Add disable_htmx property on ObjectChildrenView to allow IP assignment flow to avoid htmx fragmentary rendering on object save
* Revert "Add disable_htmx property on ObjectChildrenView to allow IP assignment flow to avoid htmx fragmentary rendering on object save"
This reverts commit fa8f2ac377.
* Suppress adding the RSS feed widget to the dashboard if ISOLATED_DEPLOYMENT is set
* Add config option on RSSFeedWidget to specify requires_internet and to display a more appropriate error if ISOLATED_DEPLOYMENT is set
* Remove skipping behavior from utils.py
* Add required=False
* Wait until job1 is scheduled before enqueueing job2
* Clamp limit=0 to default_limit
* Handle unspecified limit explicitly so as to return min(PAGINATE_COUNT, MAX_PAGE_SIZE)
* Revert original min()
* Coerce MAX_PAGE_SIZE to be at least PAGINATE_COUNT
* Raise ImproperlyConfigured error if MAX_PAGE_SIZE < PAGINATE_COUNT
* Revert test behavior
* Revert "Revert test behavior"
This reverts commit 5087a1111a.
* Revert "Raise ImproperlyConfigured error if MAX_PAGE_SIZE < PAGINATE_COUNT"
This reverts commit 5dd93c096d.
* fixes 17465 add racktype on bulkimport and bulkedit of racks
* Make width & u_height optional when setting rack_type on import
---------
Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>
* Hide traceback from rendered device config
When an exception occurs during device configuration rendering, it
usually doesn't contain information about the template being rendered,
but rather the trace of how the template was rendered. Since this could
confuse users and expose internal server information, it is now hidden.
* Improve error message display; replicate changes for VMs
---------
Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>
* Fixes: #14044 - Allow regex renaming of unnamed devices
* Allow regex renaming of unnamed devices (already allowed actually)
* Catch errors relating to unnamed devices or integrity errors as a result of the rename process
* Move validation to ensure all renames are eligible
* Update to treat null name an empty string
* Fixes#17490: Config Template unable to dynamically include templates
* Cast the generator returned by find_referenced_templates() to an iterable to avoid exhausting it on the check for None
Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>
* Apply the path__in filter to avoid duplicating code
Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>
* Remove extra if None not in referenced_templates
---------
Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>
* Add status to rack elevation device tooltip
* Use get method for status display
Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>
---------
Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>
* Move {module} substitution help text to main ComponentCreateForm.__init__ so it applies to all component types, and fix formatting
* Simplify help text replacement string for component forms with 'module' field
* Reuse help text string in both ComponentCreateForm and ModularComponentTemplateForm
* Remove help text override from regular (direct) object creation of device components
* Re-add space
* Tweak help text
---------
Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>
* Wait until job1 exists in Redis before enqueueing job2
* Job can exist but not have status
* Catch InvalidJobOperation and use as trigger for retry
* Catch InvalidJobOperation when deleting/canceling job
* Remove testing code
* Fix non-null constraint for script execution
With c34a0e2, validation of job object fields is enabled, so ScriptJob
must not set required fields to empty strings. This commit reverts
b18f193 and (hopefully) fixes this issue not only for UI views, but for
all interactions with scripts.
Fixes: #17923
* Fix name of recurring jobs
For recurring jobs, the name must be passed to the next job object when
the job is rescheduled.
* Fixes: #18037 - Bound VLANGroup VLAN ID max by `VLAN_VID_MAX`
* Correct exception string
* Validate min & max VID values
* Fix min/max VID validation
---------
Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>
* Extend register_model_view() to enable registering list views
* Register circuits list views with register_model_view()
* Register core list views with register_model_view()
* Fix bulk_edit & bulk_delete URL paths
* Register dcim list views with register_model_view() (WIP)
* Register dcim list views with register_model_view()
* Register extras list views with register_model_view()
* Register ipam list views with register_model_view()
* Register tenancy list views with register_model_view()
* Register users list views with register_model_view()
* Register virtualization list views with register_model_view()
* Register vpn list views with register_model_view()
* Register wireless list views with register_model_view()
* Add change note for register_model_view()
* Create MACAddress model and migrations to convert existing .mac_address fields to standalone objects
* Add migrations
* All views/filtering working and documentation done; no unit tests yet
* Redo migrations following VLAN Translation
* Remove mac_address filter fields and add table columns for device/vm
* Remove unnecessary "bulk rename"
* Fix filterset tests for Device
* Fix filterset tests for Interface
* Fix tests on single-object forms
* Fix serializer tests
* Fix filterset tests for VMInterface
* Fix filterset tests for Device and VirtualMachine
* Move new field check into lookup_map iteration
* Fix general MACAddress filter tests
* Add GraphQL types/filters/schema
* Fix bulk edit/create tests (bulk editing Interfaces will be unsupported because of inheritance from ComponentBulkEditForm)
* Make mac_address read_only on InterfaceSerializer/VMInterfaceSerializer
* Undo unrelated work
* Cleanup unused IPAddress derived stuff
* API endpoints
* Add serializer objects to interface serializers
* Clean up unnecessary bulk create forms/views/routes
* Add SearchIndex and adjust indexable fields for Interface and VMInterface
* Reorganize MACAddress classes out of association with DeviceComponents
* Move MACAddressSerializer
* Enforce saving only a single is_primary MACAddress per interface/vminterface
* Perform is_primary validation on MACAddress model and just check if one already exists for the interface
* Remove form-level validation
* Fix check for current is_primary setting when reassigning
* Model cleanup
* Documentation notes and cleanup
* Simplify serializer and add ip_addresses
* Add to VMInterfaceSerializer too
* Style cleanup
* Standardize "MAC Address" instead of "MAC"
* Remove unused views
* Add is_primary field for bulk edit
* HTML cleanup and add copy-to-clipboard button
* Remove mac_address from Interface and VMInterface bulk-edit forms
* Add device and VM filtering
* Use combined assigned_object_parent in table to match structure of IPAddressTable
* Add GFK fields to MACAddressSerializer
* Reorganize "Addressing" sections to remove from proximity to "Device Components" and related groupings
* Clean up migrations
* Misc cleanup
* Add filterset test
* Remove mac_address field from interface forms
* Designate primary MAC address via a ForeignKey on the interface models
* Add serializer fields for primary_mac_address
* Update docs
---------
Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>
* 12596 Add Allocated Resources to Cluster API
* 12596 Add Allocated Resources to Cluster API
* 12596 Add Allocated Resources to Cluster API
* 12596 Add Allocated Resources to Cluster API
* 12596 review changes
* 12596 review changes
* Allow adding/removing tagged VLANs in bulk editing of Interfaces
* Move vlan/interface-specific field operations to an overrideable method
* Ensure interfaces are MODE_TAGGED before adding/removing tagged vlans
* Add docstring for generic extra_object_field_operations
* Move tagging ops into post_save_operations and use a TabbedGroup in the form
* Fix check for existing jobs
If a job is to be enqueued once and no specific scheduled time is
specified, any scheduled time of existing jobs will be valid. Only if a
specific scheduled time is specified for 'enqueue_once()' can it be
evaluated.
* Allow system jobs to be registered
A new registry key allows background system jobs to be registered and
automatically scheduled when rqworker starts.
* Test scheduling of system jobs
* Fix plugins scheduled job documentation
The documentation reflected a non-production state of the JobRunner
framework left over from development. Now a more practical example
demonstrates the usage.
* Allow plugins to register system jobs
* Rename system job metadata
To clarify which meta-attributes belong to system jobs, each of them is
now prefixed with 'system_'.
* Add predefined job interval choices
* Remove 'system_enabled' JobRunner attribute
Previously, the 'system_enabled' attribute was used to control whether a
job should run or not. However, this can also be accomplished by
evaluating the job's interval.
* Fix test
* Use a decorator to register system jobs
* Specify interval when registering system job
* Update documentation
---------
Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>
* VLANTranslationPolicy and VLANTranslationRule models and all associated UI classes
* Change VLANTranslationPolicy to a PrimaryModel and make name unique
* Add serializer classes to InterfaceSerializer
* Remake migrations
* Add GraphQL typing
* Skip tagged models in test
* Missing migration
* Remove get_absolute_url methods
* Remove package-lock.json
* Rebuild migration and add constraints and field options
* Rebuild migrations
* Use DynamicModelChoiceField for policy field
* Make vlan_translation_policy fields on filtersets more consistent with existing __name convention
* Add vlan_translation_table to VMInterface detail page
* Add vlan_translation_policy to VMInterfaceSerializer
* Move vlan_translation_policy fields to model and filterset mixins
* Protect in-use policies against deletion
* Add vlan_translation_policy to fields in VMInterfaceSerializer
* Cleanup indentation
* Remove unnecessary ordering column
* Rebuild migrations
* Search methods and registration
* Ensure 'id' column is present by default
* Add graphql types/filters/schema for VLANTranslationRule
* Filterset tests
* View tests
* API and viewset tests (incomplete)
* Add tags to VLANTranslationRuleForm
* Complete viewset tests for VLANTranslationRule
* Make VLANTranslationRule.policy nullable (but still required)
* Revert "Make VLANTranslationRule.policy nullable (but still required)"
This reverts commit 4c1bb437ef.
* Revert nullability
* Explicitly prefetch policy in graphql
* Documentation of new and affected models
* Add note about select_related in graphql
* Rework policy/rule documentation
* Move vlan_translation_policy into 802.1Q Switching fieldset
* Remove redundant InterfaceVLANTranslationTable
* Conditionally include vlan_translation_table in interface.html and vminterface.html
* Add description field to VLANTranslationRule
* Define vlan_translation_table conditionally
* Add policy (name) filter to VLANTranslationRuleFilterSet
* Revert changes to adding-models.md (moved to another PR)
* Dynamic table for linked rules in vlantranslationpolicy.html
* Misc cleanup
---------
Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>
* Add new INET lookups for net_host_lt/gt/lte/gte comparisons irrespective of subnet inclusion
* Refactor Lookup subclasses to be more DRY
* Move comparison_sql to class attribute
* Add HostAsInet(Transform) to perform cast
* Remove unnecessary Lookup comparison classes
* Chain Host and Inet instead of making a new transform
* 17460 make ModuleType / DeviceType bulk buttons consistent
* 17460 refactor moduletype/devicetype to use standardized object_children
* 17460 refactor moduletype/devicetype to use standardized object_children
* 17460 refactor moduletype/devicetype to use standardized object_children
Previously, fields in the Job model were not validated when the job was
created. Now 'full_clean()' is called before saving the job to ensure
valid data.
* Replace site FK on Prefix with scope GFK
* Add denormalized relations
* Update prefix filters
* Add generic relations for Prefix
* Update GraphQL type for Prefix model
* Fix tests; misc cleanup
* Remove prefix_count from SiteSerializer
* Remove site field from PrefixBulkEditForm
* Restore scope filters for prefixes
* Fix scope population on PrefixForm init
* Show scope type
* Assign scope during bulk import of prefixes
* Correct handling of GenericForeignKey in PrefixForm
* Add prefix counts to all scoped objects
* Fix migration; linter fix
* Add limit_choices_to on scope_type
* Clean up cache_related_objects()
* Enable bulk editing prefix scope
* Add a background-color to img elements in docs to ensure readability in dark mode
* Limit style changes to those within CMS content blocks; update colors of main netbox_logo.svg
* Add a white stroke to the main logo
* Add light & dark mode versions of the NetBox logo
---------
Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>
Previously Azure AD was renamed to Entra ID. However, as django social
auth didn't change its API, just the display names must be changed but
not the API names.
* 17754 fix per-page on version history
* 17754 remove htmx table
* Use non-HTMX template for static tables
---------
Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>
* Align strawberry resolver with expected return type
* Align test data with expected representation of extra_choices in CustomFieldChoiceSet model
---------
Co-authored-by: Griffin Ellis <griffin.ellis@pico.net>
* Fixes: #17648 - Fix exception thrown in `Job.delete()` when no object_type specified
* Remove unrelated fix
* Change back elif to if
* Remove unused imports
---------
Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>
* Fixes: #17566 - Fix issue `Job.get_absolute_url()` to prevent exception being thrown if no object_type is set
* Add back whitespace after statements
* Remove whitespace. Change to if statement
* Only remove extraneous attributes from extra if changing to a BooleanField
* Add tests for MultipleChoiceField icontains and negation
* Use enum in test consistently
* Reorganize tests
* Add __empty test to base filter lookup tests
* Fix test name
* Change var name for clarity
Occurrences of the old term have been replaced by the new term. However,
the documentation still needs some work to reflect the new Entra ID
screenshots and terminology.
* 17195 Add color to PowerOutlet
* 17195 Add color to PowerOutlet
* Reorder serializer fields
* Misc cleanup
---------
Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>
* 17558 raise validation error if removing choice from choiceset that is currently used
* 17558 raise validation error if removing choice from choiceset that is currently used
* 17558 raise validation error if removing choice from choiceset that is currently used
* 17558 add tests
* 17558 add tests
* Tightened up choice evaluation logic a bit; cleaned up test
---------
Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>
* Ensure model is defined when rendering bulk_edit_button
* Move model check to inner conditional
* Set model in context
* Return child_model instead of model for use in bulk_edit_button
* Add handling for FieldError to CSVModelChoiceField.to_python to handle invalid accessor field
* manufacturer & default_platform should be CSVModelChoiceFields
* Fix string translation
---------
Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>
* Respect the weight unit of the DeviceType when displaying the Device details
* Reuse the same weight formatting construct as in rack.html, and add placeholder in rack if empty
* Add primary_ip4 and primary_ip6 to bulk import form for VDC
* Specify IPAddress querysets with address field accessor and labels
* Filter primary_ip4/ip6 querysets to only those IPs available on the device
* Fix comment
* Make ipv6 help text more correct
* Shorten IPv6 example
---------
Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>
* Closes#16926 Adds various USB cable types to front/rear ports and cable choices
* Closes#16926 Changes USB cable types to reflect versions-physical differences. Updated human readable labels on USB front/rear ports to match style of usb console ports
* Closes#16926 Removes USB cable type choices in favor of single, generic 'USB' cable
* New screenshots for 4.1
* Remove footer info
* Add bookmarks to dashboard to match previous
* Reverse ordering of bookmarks
* Fix colors of cables in cable-trace.png
* New screenshots for 4.1
* Recapture screenshots with better rendering gradient
* Better sidebar on cable-trace.png
* 17174 add version to plugin catalog
* Retain the created & updated columns for optional use
---------
Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>
* Fixes#17097: Record static object representation when calling NotificationGroup.notify()
* Redirect to notifications list when marking as read notifications for deleted objects
* Link to object in notifications dropdown only for non-destructive events
* 16649 general contrast issues (#16759)
* fixes#16647: navigation contrast issues updated
* fixes#16651: table contrast issues new
* fixed#16649: general contrast issues
* fixes#16649: feedback changes
---------
Co-authored-by: Andrew Gormley <Andrew@MacBook-Pro-3.local>
Co-authored-by: Andrew Gormley <Andrew@MacBook-Pro-3.broadband>
* 16648 dashboard contrast issues (#16824)
* fixed#16648: dashboard contrast issues
* reinstate amendment to 16649
* fixed#16648: created gridstack override and removed inline bug fix
---------
Co-authored-by: Andrew Gormley <Andrew@MacBook-Pro-3.local>
* fixed#16853: accessibility issues
* fixed#16847: updated font (#16848)
* fixed#16847: updated font
* fixed#16847: changed font to local and added current font as fallback
* fixed#16847: removed inter and added padding to page header
---------
Co-authored-by: Andrew Gormley <Andrew@MacBook-Pro-3.local>
Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>
* 16849 document hierarchy issues (#16875)
* fixed#16849: h elements not in sequential order
* fixed#16849: Lists do not contain only li elements
* fixed#16849: fixed h hierarchy on rack object pages
* Remove standalone h5 classes
* Remove unnecessary line breaks
---------
Co-authored-by: Andrew Gormley <Andrew@MacBook-Pro-3.local>
Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>
* 16650 button contrast issues (#16845)
* fixed#16650: button contrast issues
* fixed#16650: green bg text contrast issue
* Revert errant JS resource updates
* Revert custom button colors
* Fix indentation
---------
Co-authored-by: Andrew Gormley <Andrew@MacBook-Pro-3.local>
Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>
* 16907 web UI refresh (#16915)
* closes#16907: web ui refresh
* closes#16907: changed default widget color to primary color
* closes#16907: removed comma
* Revert dashboard widget color changes
* Rename logo images for consistency
* Restore original dashboard widget config
* Remove .navbar-brand-autodark from logo
* Restore logo file names
---------
Co-authored-by: Andrew Gormley <Andrew@MacBook-Pro-3.local>
Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>
* 16394 distinguish product edition (#16924)
* closes#16907: web ui refresh
* closes#16907: changed default widget color to primary color
* closes#16907: removed comma
* closes#16394: distinguish product edition
* Revert dashboard changes
* Clean up redundant styling (merge error)
* removed labs logo and added sub text for all editions
* fixed motif bug
* Fix "flashing" of side nav under dark mode
* Use title case for edition label
* altered edition text style
---------
Co-authored-by: Andrew Gormley <Andrew@MacBook-Pro-3.local>
Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>
* Query release features to toggle commercial theme
* fixes dark mode primary button contrast issue
* fixes#16913: hidden admin nav link (#16978)
Co-authored-by: Andrew Gormley <Andrew@MacBook-Pro-3.local>
Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>
* fixed 16852: misc accessbility problems (#16977)
* fixed 16852: misc accessbility problems
* Restore tooltip text
* Add translation support
* Add missing i18n
---------
Co-authored-by: Andrew Gormley <Andrew@MacBook-Pro-3.local>
Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>
* fixes issues in #16850 (#16986)
* fixes issues in #16850: issue 3 and 5
* Add link text for 'clear' button on table column
* Translate aria label
---------
Co-authored-by: Andrew Gormley <Andrew@MacBook-Pro-3.local>
Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>
* Use alternate footer links for commercial releases
* Remove Inter font
* Adjust base font weight to 500
* Retain default text color for hyperlinks inside tables
* Logo & edition cleanup
* Move dashboard styling
* Misc cleanup
* Remove unused styles
* Misc cleanup & refactoring
---------
Co-authored-by: Andrew Gormley <andrewgormley91@gmail.com>
Co-authored-by: Andrew Gormley <Andrew@MacBook-Pro-3.local>
Co-authored-by: Andrew Gormley <Andrew@MacBook-Pro-3.broadband>
* Introduce reusable BackgroundJob framework
A new abstract class can be used to implement job function classes. It
handles the necessary logic for starting and stopping jobs, including
exception handling and rescheduling of recurring jobs.
This commit also includes the migration of data source jobs to the new
framework.
* Restore using import_string for jobs
Using the 'import_string()' utility from Django allows the job script
class to be simplified, as module imports no longer need to avoid loops.
This should make it easier to queue and maintain jobs.
* Use SyncDataSourceJob for management command
Instead of maintaining two separate job execution logics, the same job
is now used for both background and interactive execution.
* Implement BackgroundJob for running scripts
The independent implementations of interactive and background script
execution have been merged into a single BackgroundJob implementation.
* Fix documentation of model features
* Ensure consitent code style
* Introduce reusable ScheduledJob
A new abstract class can be used to implement job function classes that
specialize in scheduling. These use the same logic as regular
BackgroundJobs, but ensure that they are only scheduled once at any given
time.
* Introduce reusable SystemJob
A new abstract class can be used to implement job function classes that
specialize in system background tasks (e.g. synchronization or
housekeeping). In addition to the features of the BackgroundJob and
ScheduledJob classes, these implement additional logic to not need to be
bound to an existing NetBox object and to setup job schedules on plugin
load instead of an interactive request.
* Add documentation for jobs framework
* Revert "Use SyncDataSourceJob for management"
This partially reverts commit db591d4. The 'run_now' parameter of
'enqueue()' remains, as its being used by following commits.
* Merge enqueued status into JobStatusChoices
* Fix logger for ScriptJob
* Remove job name for scripts
Because scripts are already linked through the Job Instance field, the
name is displayed twice. Removing this reduces redundancy and opens up
the possibility of simplifying the BackgroundJob framework in future
commits.
* Merge ScheduledJob into BackgroundJob
Instead of using separate classes, the logic of ScheduledJob is now
merged into the generic BackgroundJob class. This allows reusing the
same logic, but dynamically deciding whether to enqueue the same job
once or multiple times.
* Add name attribute for BackgroundJob
Instead of defining individual names on enqueue, BackgroundJob classes
can now set a job name in their meta class. This is equivalent to other
Django classes and NetBox scripts.
* Drop enqueue_sync_job() method from DataSource
* Import ScriptJob directly
* Relax requirement for Jobs to reference a specific object
* Rename 'run_now' arg on Job.enqueue() to 'immediate'
* Fix queue lookup in Job enqueue
* Collapse SystemJob into BackgroundJob
* Remove legacy JobResultStatusChoices
ChoiceSet was moved to core in 40572b5.
* Use queue 'low' for system jobs by default
System jobs usually perform low-priority background tasks and therefore
can use a different queue than 'default', which is used for regular jobs
related to specific objects.
* Add test cases for BackgroundJob handling
* Fix enqueue interval jobs
As the job's name is set by enqueue(), it must not be passed in handle()
to avoid duplicate kwargs with the same name.
* Honor schedule_at for job's enqueue_once
Not only can a job's interval change, but so can the time at which it is
scheduled to run. If a specific scheduled time is set, it will also be
checked against the current job schedule. If there are any changes, the
job is rescheduled with the new time.
* Switch BackgroundJob to regular methods
Instead of using a class method for run(), a regular method is used for
this purpose. This gives the possibility to add more convenience methods
in the future, e.g. for interacting with the job object or for logging,
as implemented for scripts.
* Fix background tasks documentation
* Test enqueue in combination with enqueue_once
* Rename background jobs to tasks (to differentiate from RQ)
* Touch up docs
* Revert "Use queue 'low' for system jobs by default"
This reverts commit b17b2050df.
* Remove system background job
This commit reverts commits 4880d81 and 0b15ecf. Using the database
'connection_created' signal for job registration feels a little wrong at
this point, as it would trigger registration very often. However, the
background job framework is prepared for this use case and can be used
by plugins once the auto-registration of jobs is solved.
* Fix runscript management command
Defining names for background jobs was disabled with fb75389. The
preceeding changes in 257976d did forget the management command.
* Use regular imports for ScriptJob
* Rename BackgroundJob to JobRunner
---------
Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>
* 12826 add RackType
* 12826 add forms, filters, tables
* 12826 add to menu
* 12826 remove role
* 12826 add api/serializers
* 12826 add tests and fixes
* 12826 fix tests
* 12826 fix tests
* 12826 fix tests
* 12826 fix tests
* 12826 add device_type to device and instantiation
* 12826 test device creation
* 12826 add slug
* 12826 fix tests
* 12826 fix slug field
* 12826 prevent modification of rack fields if rack_type set
* 12826 update rack fields on rack_type edit
* Misc cleanup
* Update model docs
* Add manufacturer field to RackType
* Add test for mounting_depth
* Rename 'type' to 'form_factor'
* Create base classes for Rack & RackType models, serializers
* Hide RackType-defined fields on RackForm when a rack type is set
* Establish a base filter form for Rack & RackType
* Clean up RackType attr inheritance
* Clean up templates
---------
Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>
* Initial work on #15621
* Signal receiver should ignore models which don't support notifications
* Flesh out NotificationGroup functionality
* Add NotificationGroup filters for users & groups
* Separate read & dimiss actions
* Enable one-click dismissals from notifications list
* Include total notification count in dropdown
* Drop 'kind' field from Notification model
* Register event types in the registry; add colors & icons
* Enable event rules to target notification groups
* Define dynamic choices for Notification.event_name
* Move event registration to core
* Add more job events
* Misc cleanup
* Misc cleanup
* Correct absolute URLs for notifications & subscriptions
* Optimize subscriber notifications
* Use core event types when queuing events
* Standardize queued event attribute to event_type; change content_type to object_type
* Rename Notification.event_name to event_type
* Restore NotificationGroupBulkEditView
* Add API tests
* Add view & filterset tests
* Add model documentation
* Fix tests
* Update notification bell when notifications have been cleared
* Ensure subscribe button appears only on relevant models
* Notifications/subscriptions cannot be ordered by object
* Misc cleanup
* Add event icon & type to notifications table
* Adjust icon sizing
* Mute color of read notifications
* Misc cleanup
* 7537 add serial number to virtual machines
* 7537 add migration
* 7537 add sn to search
* 7537 add to model documentation
* 8984 move serializer field
* 8984 add to detail view and search index
* 7537 serial_number -> serial
* 7537 fix migration
* Add missing serial field
* Give serial field higher precedence for search
---------
Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>
* It's very important that you not submit a pull request until a relevant issue has been opened **and** assigned to you. Otherwise, you risk wasting time on work that may ultimately not be needed.
* New pull requests should generally be based off of the `develop` branch, rather than `master`. The `develop` branch is used for ongoing development, while `master` is used for tracking stable releases. (If you're developing for an upcoming minor release, use `feature` instead.)
* New pull requests should generally be based off of the `main` branch. This branch, in keeping with the [trunk-based development](https://trunkbaseddevelopment.com/) approach, is used for ongoing development and bug fixes and always represents the newest stable code, from which releases are periodically branched. (If you're developing for an upcoming minor release, use `feature` instead.)
* In most cases, it is not necessary to add a changelog entry: A maintainer will take care of this when the PR is merged. (This helps avoid merge conflicts resulting from multiple PRs being submitted simultaneously.)
@@ -109,21 +109,9 @@ Do you have an idea for something you'd like to build in NetBox, but might not b
Check out our [plugin development tutorial](https://github.com/netbox-community/netbox-plugin-tutorial) to get started!
## :rescue_worker_helmet: Become a Maintainer
## :briefcase: Looking for a Job?
We're always looking for motivated individuals to join the maintainers team and help drive NetBox's long-term development. Some of our most sought-after skills include:
* Python development with a strong focus on the [Django](https://www.djangoproject.com/) framework
* Expertise working with PostgreSQL databases
* Javascript & TypeScript proficiency
* A knack for web application design (HTML & CSS)
* Familiarity with git and software development best practices
* Excellent attention to detail
* Working experience in the field of network operations & engineering
We generally ask that maintainers dedicate around four hours of work to the project each week on average, which includes both hands-on development and project management tasks such as issue triage. Maintainers are also encouraged (but not required) to attend our bi-weekly Zoom call to catch up on recent items.
Interested? You can contact our lead maintainer, Jeremy Stretch, at jeremy@netbox.dev or on the [NetDev Community Slack](https://netdev.chat/). We'd love to have you on the team!
At [NetBox Labs](https://netboxlabs.com/), we're always looking for highly skilled and motivated people to join our team. While NetBox is a core part of our product lineup, we have an ever-expanding suite of solutions serving the network automation space. Check out our [current openings](https://netboxlabs.com/careers/) to see if you might be a fit!
NetBox exists to empower network engineers. Since its release in 2016, it has become the go-to solution for modeling and documenting network infrastructure for thousands of organizations worldwide. As a successor to legacy IPAM and DCIM applications, NetBox provides a cohesive, extensive, and accessible data model for all things networked. By providing a single robust user interface and programmable APIs for everything from cable maps to device configurations, NetBox serves as the central source of truth for the modern network.
@@ -81,18 +85,12 @@ NetBox automatically logs the creation, modification, and deletion of all manage
* The [official documentation](https://docs.netbox.dev) offers a comprehensive introduction.
* Check out [our wiki](https://github.com/netbox-community/netbox/wiki/Community-Contributions) for even more projects to get the most out of NetBox!
Looking for a managed solution? Check out <strong><a href="https://netboxlabs.com/netbox-cloud/">NetBox Cloud</a></strong> or <strong><a href="https://netboxlabs.com/netbox-enterprise/">NetBox Enterprise</a></strong>!
</p>
## Get Involved
* Follow [@NetBoxOfficial](https://twitter.com/NetBoxOfficial) on Twitter!
* Join the conversation on [the discussion forum](https://github.com/netbox-community/netbox/discussions) and [Slack](https://netdev.chat/)!
* Already a power user? You can [suggest a feature](https://github.com/netbox-community/netbox/issues/new?assignees=&labels=type%3A+feature&template=feature_request.yaml) or [report a bug](https://github.com/netbox-community/netbox/issues/new?assignees=&labels=type%3A+bug&template=bug_report.yaml) on GitHub.
* Contributions from the community are encouraged and appreciated! Check out our [contributing guide](CONTRIBUTING.md) to get started.
* [Share your idea](https://plugin-ideas.netbox.dev/) for a new plugin, or [learn how to build one](https://github.com/netbox-community/netbox-plugin-tutorial) yourself!
@@ -14,6 +14,12 @@ Administrators are encouraged to adhere to industry best practices concerning th
* Prohibit access to your database from clients other than the NetBox application
* Keep your deployment updated to the most recent stable release
## Compliance Reporting
Please note that security compliance reports (e.g. SOC 2) are provided by NetBox Labs only to customers using NetBox Cloud or NetBox Enterprise. They are not available to users of self-hosted NetBox Community Edition.
If you would like to consider upgrading to NetBox Cloud or Enterprise, please contact `sales@netboxlabs.com`.
## Reporting a Suspected Vulnerability
If you believe you've uncovered a security vulnerability and wish to report it confidentially, you may do so by emailing `security@netboxlabs.com`. Please ensure that your report meets all the following conditions:
@@ -28,4 +34,4 @@ For any security concerns regarding the community-maintained Docker image for Ne
### Bug Bounties
As NetBox is provided as free open source software, we do not offer any monetary compensation for vulnerability or bug reports, however your contributions are greatly appreciated.
As NetBox is provided as free open source software, we do not offer any monetary compensation for vulnerability or bug reports; however, your contributions are greatly appreciated.
This guide explains how to configure single sign-on (SSO) support for NetBox using [Google OAuth2](https://developers.google.com/identity/protocols/oauth2/web-server) as an authentication backend.
## Google OAuth2 Configuration
1. Log into [console.cloud.google.com](https://console.cloud.google.com/).
2. Create new project for NetBox.
3. Under "APIs and Services" click "OAuth consent screen" and enter the required information.
4. Under "Credentials," click "Create Credentials" and select "OAuth 2.0 Client ID." Select type "Web application."
- "Authorized JavaScript origins" should follow the format `http[s]://<netbox>[:<port>]`
- "Authorized redirect URIs" should follow the format `http[s]://<netbox>[:<port>]/oauth/complete/google-oauth2/`
5. Copy the "Client ID" and "Client Secret" values somewhere convenient.
!!! note
Google requires the NetBox hostname to use a public top-level-domain (e.g. `.com`, `.net`). The use of IP addresses is not permitted (except `127.0.0.1`).
For more information, consult [Google's documentation](https://developers.google.com/identity/protocols/oauth2/web-server#prerequisites).
## NetBox Configuration
### 1. Enter configuration parameters
Enter the following configuration parameters in `configuration.py`, substituting your own values:
Restart the NetBox services so that the new configuration takes effect. This is typically done with the command below:
```no-highlight
sudo systemctl restart netbox
```
## Testing
Log out of NetBox if already authenticated, and click the "Log In" button at top right. You should see the normal login form as well as an option to authenticate using Google. Click that link.

You should be redirected to Google's authentication portal. Enter the username/email and password of your test account to continue. You may also be prompted to grant this application access to your account.

If successful, you will be redirected back to the NetBox UI, and will be logged in as the Google user. You can verify this by navigating to your profile (using the button at top right).
This user account has been replicated locally to NetBox, and can now be assigned groups and permissions.
This guide explains how to configure single sign-on (SSO) support for NetBox using [Microsoft Azure Active Directory (AD)](https://azure.microsoft.com/en-us/services/active-directory/) as an authentication backend.
This guide explains how to configure single sign-on (SSO) support for NetBox using [Microsoft Entra ID](https://www.microsoft.com/en-us/security/business/identity-access/microsoft-entra-id) as an authentication backend.
## Azure AD Configuration
## Entra ID Configuration
### 1. Create a test user (optional)
@@ -25,7 +25,7 @@ Once finished, make note of the application (client) ID; this will be used when
NetBox also supports multitenant authentication via Azure AD, however it requires a different backend and an additional configuration parameter. Please see the [`python-social-auth` documentation](https://python-social-auth.readthedocs.io/en/latest/backends/azuread.html#tenant-support) for details concerning multitenant authentication.
NetBox also supports multitenant authentication via Azure AD; however, it requires a different backend and an additional configuration parameter. Please see the [`python-social-auth` documentation](https://python-social-auth.readthedocs.io/en/latest/backends/azuread.html#tenant-support) for details concerning multitenant authentication.
Local user accounts and groups can be created in NetBox under the "Authentication" section in the "Admin" menu. This section is available only to users with the "staff" permission enabled.
Local user accounts and groups can be created in NetBox under the "Authentication" section in the "Admin" menu.
At a minimum, each user account must have a username and password set. User accounts may also denote a first name, last name, and email address. [Permissions](../permissions.md) may also be assigned to individual users and/or groups as needed.
@@ -54,6 +54,7 @@ Icons](https://github.com/google/material-design-icons) icon's name; or be
`None` for no icon.
For instance, the OIDC backend may be customized with
NetBox supports native integration with [Sentry](https://sentry.io/) for automatic error reporting. To enable this functionality, set `SENTRY_ENABLED` to True and define your unique [data source name (DSN)](https://docs.sentry.io/product/sentry-basics/concepts/dsn-explainer/) in `configuration.py`.
NetBox supports native integration with [Sentry](https://sentry.io/) for automatic error reporting. To enable this functionality, set `SENTRY_ENABLED` to `True` and define your unique [data source name (DSN)](https://docs.sentry.io/product/sentry-basics/concepts/dsn-explainer/) in `configuration.py`.
NetBox includes a `housekeeping` management command that should be run nightly. This command handles:
* Clearing expired authentication sessions from the database
* Deleting changelog records older than the configured [retention time](../configuration/miscellaneous.md#changelog_retention)
* Deleting job result records older than the configured [retention time](../configuration/miscellaneous.md#job_retention)
* Check for new NetBox releases (if [`RELEASE_CHECK_URL`](../configuration/miscellaneous.md#release_check_url) is set)
This command can be invoked directly, or by using the shell script provided at `/opt/netbox/contrib/netbox-housekeeping.sh`.
## Scheduling
### Using Cron
This script can be linked from your cron scheduler's daily jobs directory (e.g. `/etc/cron.daily`) or referenced directly within the cron configuration file.
On Debian-based systems, be sure to omit the `.sh` file extension when linking to the script from within a cron directory. Otherwise, the task may not run.
### Using Systemd
First, create symbolic links for the systemd service and timer files. Link the existing service and timer files from the `/opt/netbox/contrib/` directory to the `/etc/systemd/system/` directory:
@@ -106,7 +106,7 @@ This approach can span multiple levels of relations. For example, the following
```
!!! note
While the above query is functional, it's not very efficient. There are ways to optimize such requests, however they are out of scope for this document. For more information, see the [Django queryset method reference](https://docs.djangoproject.com/en/stable/ref/models/querysets/) documentation.
While the above query is functional, it's not very efficient. There are ways to optimize such requests; however, they are out of scope for this document. For more information, see the [Django queryset method reference](https://docs.djangoproject.com/en/stable/ref/models/querysets/) documentation.
Reverse relationships can be traversed as well. For example, the following will find all devices with an interface named "em0":
You may need to change the username, host, and/or database in the command above to match your installation.
When replicating a production database for development purposes, you may find it convenient to exclude changelog data, which can easily account for the bulk of a database's size. To do this, exclude the `extras_objectchange` table data from the export. The table will still be included in the output file, but will not be populated with any data.
When replicating a production database for development purposes, you may find it convenient to exclude changelog data, which can easily account for the bulk of a database's size. To do this, exclude the `core_objectchange` table data from the export. The table will still be included in the output file, but will not be populated with any data.
By default, NetBox stores uploaded files (such as image attachments) in its media directory. To fully replicate an instance of NetBox, you'll need to copy both the database and the media files.
!!! note
These operations are not necessary if your installation is utilizing a [remote storage backend](../configuration/system.md#storage_backend).
These operations are not necessary if your installation is utilizing a [remote storage backend](../configuration/system.md#storages).
Many network devices utilize field-swappable [small-form factor pluggable transceivers (SFPs)](https://en.wikipedia.org/wiki/Small_Form-factor_Pluggable) to enable changing the physical media type of a fixed interface. For example, a 10 Gigabit Ethernet interface might be connected using copper, multimode fiber, or single-mode fiber, each of which requires a different type of SFP+ transceiver.
It can be challenging to model SFPs given their dynamic nature. This guide intends to capture the recommended strategy for modeling SFPs on NetBox v4.4 and later.
## Modeling Strategy
Pluggable transceivers are most accurately represented in NetBox as discrete [modules](../models/dcim/module.md) which are installed within [module bays](../models/dcim/modulebay.md). A module can deliver one or more [interfaces](../models/dcim/interface.md) (or other components) to the device in which it is installed. This approach ensures that a new interface is automatically created on the device when the module is installed, and deleted when the module is removed.
If one has not already been defined, create a [module type profile](../models/dcim/moduletypeprofile.md) for SFPs. This profile will be assigned for all module types which represent a pluggable transceiver. Typically, you will need only one profile for all pluggable transceivers.
You might opt to define custom attributes for the profile by defining a custom [JSON schema](https://json-schema.org/). Profile attributes might be used to define characteristics unique to transceivers, such as optical wavelength and power ranges. Adding profile attributes is optional, and can be done at a later point.
!!! note
Creating a module type profile is optional, but recommended as it allows for defining custom module attributes.
### 2. Create a Module Type for Each SFP Model in Inventory
Next, create a [module type](../models/dcim/moduletype.md) to represent each unique SFP model present in your network. Each module type should define a manufacturer and a unique model name, and may also include a part number. For example, you might create a module type for each of the following transceivers:
| Manufacturer | Model | Media Type |
|--------------|------------------|------------|
| Cisco | SFP-10G-SR | 10GE MMF |
| Cisco | SFP-10G-LR | 10GE SMF |
| Juniper | QFX-QSFP-40G-SR4 | 40GE MMF |
| Juniper | JNP-QSFP-DAC-5M | 40GE DAC |
### 3. Add an Interface to the Module Type
After creating each module type, create an interface template on it to represent its physical interface. The definition of this interface template will depend on the transceiver's physical media type. (Reference the table above for examples.) When a new module is "installed" within a module bay on a device, its templated interface(s) will be automatically instantiated on that device as child interfaces of the module.
Determining which name to use for the transceiver's interface can be tricky, as the interface name might depend on the type of device in which the SFP is installed. To avoid having to rename interfaces, consider using the `{module}` token in place of a static interface name. The interface's name will inherit the position of the bay in which its parent module is installed. If creating multiple interfaces on a module, be sure to append a unique ID (e.g. `{module}:1`) to ensure each interface gets assigned a unique name.
### 4. Create Device Types
If you haven't already, create a [device type](../models/dcim/devicetype.md) to represent each unique device model in your network.
!!! note
Skip this step if you've already created the necessary device types.
### 5. Add Module Bays to the Device Type
Once you've created a device type, add the appropriate number of module bays on each device type to represent its SFP slots. For example, a Juniper QFX5110 would have module bays numbered `0/0/0` through `0/0/55`: 48 SFP+ bays and 8 QSFP28 bays (56 total).
Be sure to define both the name **and position** of each module bay with a unique value. The module bay's position will be used to automatically name SFP interfaces.
### 6. Create a Device
Create a new device using the device type added in the previous step. The module bays (and any other components) defined on the device type will be instantiated on the new device automatically.
!!! note
If you've already created the necessary devices in NetBox, you'll need to add their module bays manually. You can add multiple module bays at once by selecting the desired devices from the device list and selecting **Add Components > Module Bays** at the bottom of the page.
### 7. Add the SFP Modules
Finally, create each SFP in the new device by "installing" a new module of the appropriate type in each module bay. The interface(s) defined on the selected module type will be automatically populated on the new module. If present, the `{module}` token in the name of each interface template will be replaced with the position of the bay in which the module is being installed. For example, an interface template with the name `et-{module}` being created on a module installed in a bay with position `0/0/14` will create an interface named `et-0/0/14`.
When adding many modules at once, you may find it helpful to utilize NetBox's bulk import functionality. This allows you to create many modules at once from CSV, JSON, or YAML data.
The purpose of this handbook is to help users and administrators use NetBox efficiently. It contains assorted recommendations and best practices compiled over time, intending to serve a wide variety of use cases.
## Server Configuration
### WSGI Server Configuration
NetBox operates as a [Web Server Gateway Interface (WSGI)](https://en.wikipedia.org/wiki/Web_Server_Gateway_Interface) application, which sits behind a frontend HTTP server such as nginx or Apache. The HTTP server handles low-level HTTP request processing and serving static assets, and forwards application-level requests to NetBox via WSGI.
A backend WSGI server (typically [Gunicorn](https://gunicorn.org/) or [uWSGI](https://uwsgi-docs.readthedocs.io/en/latest/)) is responsible for running the NetBox application. This is accomplished by initializing a number of WSGI worker processes which accept WSGI requests relayed from the frontend HTTP server.
Tuning your WSGI server is crucial to realizing optimal performance from NetBox. Below are some recommended configuration parameters.
#### Provision Multiple Workers
General guidance is to set the number of worker processes to double the number of CPU cores available, plus one (`2 * CPUs + 1`).
#### Limit the Worker Lifetime
Set a maximum number of requests that a worker can service before being respawned. This helps protect against potential memory leaks.
#### Set a Request Timeout
Limit the time a worker may spend processing any request. This prevents a long-running request from tying up a worker beyond an acceptable threshold. We suggest a limit of 120 seconds as a reasonable safeguard.
#### Bind Using a Unix Socket
When running the HTTP frontend and WSGI server on the same machine, binding via a Unix socket (instead of a TCP socket) may yield slight performance gains.
### NetBox Configuration
NetBox ships with a reasonable default configuration for most environments, but administrators are encouraged to explore all the [available parameters](../configuration/index.md) to tune their installation. Some of the most notable parameters impacting performance are called out below.
#### Reduce the Maximum Page Size
NetBox paginates large result sets to reduce the overall response size. The [`MAX_PAGE_SIZE`](../configuration/miscellaneous.md#max_page_size) parameter specifies the maximum number of results per page that a client can request. This is set to 1,000 by default. Consider lowering this number if you find that API clients are frequently requesting very large result sets.
#### Limit GraphQL Aliases
By default, NetBox restricts a GraphQL query to 10 aliases. Consider reducing this number by setting [`GRAPHQL_MAX_ALIASES`](../configuration/graphql-api.md#graphql_max_aliases) to a lower value.
#### Designate Isolated Deployments
If your NetBox installation does not have Internet access, set [`ISOLATED_DEPLOYMENT`](../configuration/system.md#isolated_deployment) to True. This will prevent the application from attempting routine external requests.
#### Reduce Sentry Sampling
If [Sentry](https://sentry.io/) has been enabled for error reporting and analytics, consider lowering its sampling rate. This can be accomplished by modifying the values for `sample_rate` and `traces_sample_rate` under [`SENTRY_CONFIG`](../configuration/error-reporting.md#sentry_config).
#### Remove Unneeded Event Handlers
Check whether any custom event handlers have been added under [`EVENTS_PIPELINE`](../configuration/miscellaneous.md#events_pipeline). Remove any that are no longer needed.
### Background Task Workers
NetBox defers the execution of certain tasks to background workers via Redis queues serviced by one or more background workers. These workers operate asynchronously from the frontend WSGI workers, and process tasks in the order they are enqueued.
NetBox creates three default queues for background tasks: `high`, `default`, and `low`. Additional queues can be configured via the [`QUEUE_MAPPINGS`](../configuration/miscellaneous.md#queue_mappings) configuration parameter.
By default, a background worker (spawned via `manage.py rqworker`) will listen to all available queues. To improve responsiveness to high-priority background tasks, consider dedicating one or more workers to service the `high` queue only:
```
$ ./manage.py rqworker high
19:31:20 Worker 861be45b32214afc95c235beeb19c9fa: started with PID 2300029, version 2.6.0
19:31:20 Worker 861be45b32214afc95c235beeb19c9fa: subscribing to channel rq:pubsub:861be45b32214afc95c235beeb19c9fa
19:31:20 *** Listening on high...
19:31:20 Worker 861be45b32214afc95c235beeb19c9fa: cleaning registries for queue: high
19:31:20 Scheduler for high started with PID 2300096
```
## API Clients
### REST API
NetBox's [REST API](../integrations/rest-api.md) is the primary means of integration with external systems, allowing full create, read, update, and delete (CRUD) operations. There are a few performance considerations to keep in mind when dealing with very large data sets.
#### Use "Brief" Mode for Simple Lists
In cases where you need to retrieve only a minimal representation of objects, append `?brief=True` to the URL. This instructs NetBox to omit all fields except the following:
* ID
* URL
* Display text
* Name (or similar identifier)
* Slug (if present)
* Description
* Counts of notable related objects (where applicable)
For example, a site fetched using brief mode returns only the following:
```json
{
"id":2,
"url":"https://netbox/api/dcim/sites/2/",
"display":"DM-Akron",
"name":"DM-Akron",
"slug":"dm-akron",
"description":""
}
```
Omitting all other fields (especially those which fetch and return related objects) often results in much faster queries.
#### Declare Selected Fields
If you need more flexibility regarding the fields to be returned for an object type, you can specify a list of fields to include using the `fields` query parameter. For example, a request for `/api/dcim/sites/?fields=id,name,status,region` will return the following:
```json
{
"id":2,
"name":"DM-Akron",
"status":{
"value":"active",
"label":"Active"
},
"region":{
"id":51,
"url":"https://netbox/api/dcim/regions/51/",
"display":"Ohio",
"name":"Ohio",
"slug":"us-oh",
"description":"",
"site_count":0,
"_depth":2
}
}
```
Like brief mode, this approach can significantly reduce the response time of an API request by omitting unneeded data.
#### Employ Pagination
Like the user interface, the REST API employs pagination to limit the number of objects returned in a single response. If a page size is not specified by the request (i.e. by passing `?limit=10`), NetBox will use the default size defined by [`PAGINATE_COUNT`](../configuration/default-values.md#paginate_count). The default page size is 50.
For some requests, especially those using brief mode or a minimal selection of fields, it may be desirable to specify a higher page size, so that fewer requests are needed to retrieve all objects. Appending `?limit=0` to the request effectively seeks to disable pagination. (Note, however, that the requested page size cannot exceed the value of [`MAX_PAGE_SIZE`](../configuration/miscellaneous.md#max_page_size), which defaults to 1,000.)
Complex API requests, which pull in many related objects, generate a relatively high load on the application, and generally benefit from reduced page size. If you find that your API requests are taking an inordinate amount of time, try reducing the page size from the default value so that fewer objects need to be returned for each request.
### GraphQL API
NetBox's read-only [GraphQL API](../integrations/graphql-api.md) offers an alternative to its REST API, and provides a very flexible means of retrieving data. GraphQL enables the client to request any object from a single endpoint, specifying only the desired attributes and relations. Many users prefer this to the more rigid structure of the REST API, but it's important to understand the trade-offs of crafting complex queries.
#### Request Only the Necessary Fields
For optimal performance, craft your GraphQL queries to return only the fields needed by the client. This will reduce the overall query time, especially when omitting related objects.
#### Avoid Overly Complex Queries
The primary benefit of the GraphQL API is that it allows the client to offload to the server the work of stitching together various related objects, which would require the client to make multiple requests to different endpoints if using the REST API. However, this advantage does not come for free: The more information that is requested in a single query, the more work the server needs to do to fetch the raw data from the database and render it into a GraphQL response. Very complex queries can yield dozens or hundreds of SQL queries on the backend, which increase the time it takes to render a response.
While it can be tempting to pack as much data as possible into a single GraphQL query, realize that there is a balance to be struck between minimizing the number of queries needed and avoiding complexity in the interest of performance. For example, while it is possible to retrieve via a single GraphQL API request all the IP addresses and all attached cables for every device in a site, it is probably more efficient (often _much_ more efficient) to make two or three separate requests and correlate the data locally.
#### Use Filters
You can specify filters when making a GraphQL query to limit the set of objects returned. This works a bit differently from the REST API, as filters are declared inside the query statement rather than appended to the URL, but the concept is the same. For example, to return only active sites:
```graphql
query{
site_list(
filters:{
status:STATUS_ACTIVE
}
){
name
}
}
```
This returns only sites with a status of "active" and avoid needing to parse through all the others. For further information about filters, see the [GraphQL API documentation](../integrations/graphql-api.md).
#### Employ Pagination
Like the REST API, the GraphQL API supports pagination. Queries which return a large number of objects should employ pagination to limit the size of each response.
This parameter controls the content and layout of user's default dashboard. Once the dashboard has been created, the user is free to customize it as they please by adding, removing, and reconfiguring widgets.
This parameter must specify an iterable of dictionaries, each representing a discrete dashboard widget and its configuration. The follow widget attributes are supported:
This parameter must specify an iterable of dictionaries, each representing a discrete dashboard widget and its configuration. The following widget attributes are supported:
*`widget`: Dotted path to the Python class (required)
*`width`: Default widget width (between 1 and 12, inclusive)
@@ -63,13 +63,15 @@ DEFAULT_USER_PREFERENCES = {
For a complete list of available preferences, log into NetBox and navigate to `/user/preferences/`. A period in a preference name indicates a level of nesting in the JSON data. The example above maps to `pagination.per_page`.
See also: [Clearing table preferences](../features/user-preferences.md#clearing-table-preferences) for resolving errors caused by saved table columns or ordering.
---
## PAGINATE_COUNT
!!! tip "Dynamic Configuration Parameter"
Default: 50
Default: `50`
The default maximum number of objects to display per page within each list of objects.
@@ -79,7 +81,7 @@ The default maximum number of objects to display per page within each list of ob
!!! tip "Dynamic Configuration Parameter"
Default: 15
Default: `15`
The default value for the `amperage` field when creating new power feeds.
@@ -89,7 +91,7 @@ The default value for the `amperage` field when creating new power feeds.
!!! tip "Dynamic Configuration Parameter"
Default: 80
Default: `80`
The default value (percentage) for the `max_utilization` field when creating new power feeds.
@@ -99,7 +101,7 @@ The default value (percentage) for the `max_utilization` field when creating new
!!! tip "Dynamic Configuration Parameter"
Default: 120
Default: `120`
The default value for the `voltage` field when creating new power feeds.
@@ -109,7 +111,7 @@ The default value for the `voltage` field when creating new power feeds.
!!! tip "Dynamic Configuration Parameter"
Default: 22
Default: `22`
Default height (in pixels) of a unit within a rack elevation. For best results, this should be approximately one tenth of `RACK_ELEVATION_DEFAULT_UNIT_WIDTH`.
@@ -119,6 +121,6 @@ Default height (in pixels) of a unit within a rack elevation. For best results,
!!! tip "Dynamic Configuration Parameter"
Default: 220
Default: `220`
Default width (in pixels) of a unit within a rack elevation.
This setting enables debugging. Debugging should be enabled only during development or troubleshooting. Note that only
clients which access NetBox from a recognized [internal IP address](./system.md#internal_ips) will see debugging tools in the user
@@ -16,6 +16,6 @@ interface.
## DEVELOPER
Default: False
Default: `False`
This parameter serves as a safeguard to prevent some potentially dangerous behavior, such as generating new database schema migrations. Additionally, enabling this setting disables the debug warning banner in the UI. Set this to `True`**only** if you are actively developing the NetBox code base.
A dictionary mapping keyword arguments to values, to be passed to `sentry_sdk.init()`. See the [Sentry Python SDK documentation](https://docs.sentry.io/platforms/python/) for more information on supported parameters.
The default configuration is shown below:
```python
{
"sample_rate":1.0,
"send_default_pii":False,
"traces_sample_rate":0,
}
```
Additionally, `http_proxy` and `https_proxy` are set to the HTTP and HTTPS proxies, respectively, configured for NetBox (if any).
## SENTRY_DSN
Default: None
!!! warning "This parameter will be removed in NetBox v4.5."
Set this using `SENTRY_CONFIG` instead:
Defines a Sentry data source name (DSN) for automated error reporting. `SENTRY_ENABLED` must be True for this parameter to take effect. For example:
Set to True to enable automatic error reporting via [Sentry](https://sentry.io/).
Set to `True` to enable automatic error reporting via [Sentry](https://sentry.io/).
!!! note
The `sentry-sdk` Python package is required to enable Sentry integration.
@@ -25,7 +50,16 @@ Set to True to enable automatic error reporting via [Sentry](https://sentry.io/)
## SENTRY_SAMPLE_RATE
Default: 1.0 (all)
!!! warning "This parameter will be removed in NetBox v4.5."
Set this using `SENTRY_CONFIG` instead:
```
SENTRY_CONFIG = {
"sample_rate": 0.2,
}
```
Default: `1.0` (all)
The sampling rate for errors. Must be a value between 0 (disabled) and 1.0 (report on all errors).
@@ -33,7 +67,16 @@ The sampling rate for errors. Must be a value between 0 (disabled) and 1.0 (repo
## SENTRY_SEND_DEFAULT_PII
Default: False
!!! warning "This parameter will be removed in NetBox v4.5."
Set this using `SENTRY_CONFIG` instead:
```
SENTRY_CONFIG = {
"send_default_pii": True,
}
```
Default: `False`
Maps to the Sentry SDK's [`send_default_pii`](https://docs.sentry.io/platforms/python/configuration/options/#send-default-pii) parameter. If enabled, certain personally identifiable information (PII) is added.
@@ -60,7 +103,16 @@ SENTRY_TAGS = {
## SENTRY_TRACES_SAMPLE_RATE
Default: 0 (disabled)
!!! warning "This parameter will be removed in NetBox v4.5."
Set this using `SENTRY_CONFIG` instead:
```
SENTRY_CONFIG = {
"traces_sample_rate": 0.2,
}
```
Default: `0` (disabled)
The sampling rate for transactions. Must be a value between 0 (disabled) and 1.0 (report on all transactions).
@@ -55,9 +55,9 @@ Sets content for the top banner in the user interface.
## CENSUS_REPORTING_ENABLED
Default: True
Default: `True`
Enables anonymous census reporting. To opt out of census reporting, set this to False.
Enables anonymous census reporting. To opt out of census reporting, set this to `False`.
This data enables the project maintainers to estimate how many NetBox deployments exist and track the adoption of new versions over time. Census reporting effects a single HTTP request each time a worker starts. The only data reported by this function are the NetBox version, Python version, and a pseudorandom unique identifier.
@@ -67,7 +67,7 @@ This data enables the project maintainers to estimate how many NetBox deployment
!!! tip "Dynamic Configuration Parameter"
Default: 90
Default: `90`
The number of days to retain logged changes (object creations, updates, and deletions). Set this to `0` to retain
changes in the database indefinitely.
@@ -79,7 +79,7 @@ changes in the database indefinitely.
## CHANGELOG_SKIP_EMPTY_CHANGES
Default: True
Default: `True`
If enabled, a change log record will not be created when an object is updated without any changes to its existing field values.
@@ -96,21 +96,21 @@ The maximum size (in bytes) of an incoming HTTP request (i.e. `GET` or `POST` da
---
## DJANGO_ADMIN_ENABLED
Default: False
Setting this to True installs the `django.contrib.admin` app and enables the [Django admin UI](https://docs.djangoproject.com/en/5.0/ref/contrib/admin/). This may be necessary to support older plugins which do not integrate with the native NetBox interface.
---
## ENFORCE_GLOBAL_UNIQUE
!!! tip "Dynamic Configuration Parameter"
Default: True
Default: `True`
By default, NetBox will prevent the creation of duplicate prefixes and IP addresses in the global table (that is, those which are not assigned to any VRF). This validation can be disabled by setting `ENFORCE_GLOBAL_UNIQUE` to False.
By default, NetBox will prevent the creation of duplicate prefixes and IP addresses in the global table (that is, those which are not assigned to any VRF). This validation can be disabled by setting `ENFORCE_GLOBAL_UNIQUE` to `False`.
---
## EVENTS_PIPELINE
Default: `['extras.events.process_event_queue',]`
NetBox will call dotted paths to the functions listed here for events (create, update, delete) on models as well as when custom EventRules are fired.
---
@@ -122,21 +122,11 @@ The maximum amount (in bytes) of uploaded data that will be held in memory befor
---
## GRAPHQL_ENABLED
!!! tip "Dynamic Configuration Parameter"
Default: True
Setting this to False will disable the GraphQL API.
---
## JOB_RETENTION
!!! tip "Dynamic Configuration Parameter"
Default: 90
Default: `90`
The number of days to retain job results (scripts and reports). Set this to `0` to retain job results in the database indefinitely.
@@ -149,9 +139,9 @@ The number of days to retain job results (scripts and reports). Set this to `0`
!!! tip "Dynamic Configuration Parameter"
Default: False
Default: `False`
Setting this to True will display a "maintenance mode" banner at the top of every page. Additionally, NetBox will no longer update a user's "last active" time upon login. This is to allow new logins when the database is in a read-only state. Recording of login times will resume when maintenance mode is disabled.
Setting this to `True` will display a "maintenance mode" banner at the top of every page. Additionally, NetBox will no longer update a user's "last active" time upon login. This is to allow new logins when the database is in a read-only state. Recording of login times will resume when maintenance mode is disabled.
---
@@ -169,7 +159,7 @@ This specifies the URL to use when presenting a map of a physical location by st
!!! tip "Dynamic Configuration Parameter"
Default: 1000
Default: `1000`
A web user or API consumer can request an arbitrary number of objects by appending the "limit" parameter to the URL (e.g. `?limit=1000`). This parameter defines the maximum acceptable limit. Setting this to `0` or `None` will allow a client to retrieve _all_ matching objects at once with no limit by specifying `?limit=0`.
@@ -177,7 +167,7 @@ A web user or API consumer can request an arbitrary number of objects by appendi
## METRICS_ENABLED
Default: False
Default: `False`
Toggle the availability Prometheus-compatible metrics at `/metrics`. See the [Prometheus Metrics](../integrations/prometheus-metrics.md) documentation for more details.
@@ -187,9 +177,9 @@ Toggle the availability Prometheus-compatible metrics at `/metrics`. See the [Pr
!!! tip "Dynamic Configuration Parameter"
Default: False
Default: `False`
When determining the primary IP address for a device, IPv6 is preferred over IPv4 by default. Set this to True to prefer IPv4 instead.
When determining the primary IP address for a device, IPv6 is preferred over IPv4 by default. Set this to `True` to prefer IPv4 instead.
---
@@ -211,7 +201,7 @@ If no queue is defined the queue named `default` will be used.
## RELEASE_CHECK_URL
Default: None (disabled)
Default: `None` (disabled)
This parameter defines the URL of the repository that will be checked for new NetBox releases. When a new release is detected, a message will be displayed to administrative users on the home page. This can be set to the official repository (`'https://api.github.com/repos/netbox-community/netbox/releases'`) or a custom fork. Set this to `None` to disable automatic update checks.
@@ -241,3 +231,15 @@ This parameter controls how frequently a failed job is retried, up to the maximu
Default: `0` (retries disabled)
The maximum number of times a background task will be retried before being marked as failed.
## DISK_BASE_UNIT
Default: `1000`
The base unit for disk sizes. Set this to `1024` to use binary prefixes (MiB, GiB, etc.) instead of decimal prefixes (MB, GB, etc.).
## RAM_BASE_UNIT
Default: `1000`
The base unit for RAM sizes. Set this to `1024` to use binary prefixes (MiB, GiB, etc.) instead of decimal prefixes (MB, GB, etc.).
A list of installed [NetBox plugins](../plugins/index.md) to enable. Plugins will not take effect unless they are listed here.
@@ -13,7 +13,7 @@ A list of installed [NetBox plugins](../plugins/index.md) to enable. Plugins wil
## PLUGINS_CONFIG
Default: Empty
Default: `[]`
This parameter holds configuration settings for individual NetBox plugins. It is defined as a dictionary, with each key using the name of an installed plugin. The specific parameters supported are unique to each plugin: Reference the plugin's documentation to determine the supported parameters. An example configuration is shown below:
@@ -33,3 +33,21 @@ Note that a plugin must be listed in `PLUGINS` for its configuration to take eff
---
## PLUGINS_CATALOG_CONFIG
Default: `{}` (Empty)
This parameter controls how individual plugins are displayed in the plugins catalog under Admin > System > Plugins. Adding a plugin to the `hidden` list will omit that plugin from the catalog. Adding a plugin to the `static` list will display the plugin, but not link to the plugin details or upgrade instructions.
The configuration parameters listed here control remote authentication for NetBox. Note that `REMOTE_AUTH_ENABLED` must be true in order for these settings to take effect.
The configuration parameters listed here control remote authentication for NetBox. Note that `REMOTE_AUTH_ENABLED` must be `True` in order for these settings to take effect.
---
@@ -8,7 +8,7 @@ The configuration parameters listed here control remote authentication for NetBo
Default: `False`
If true, NetBox will automatically create groups specified in the `REMOTE_AUTH_GROUP_HEADER` header if they don't already exist. (Requires `REMOTE_AUTH_ENABLED`.)
If `True`, NetBox will automatically create groups specified in the `REMOTE_AUTH_GROUP_HEADER` header if they don't already exist. (Requires `REMOTE_AUTH_ENABLED`.)
---
@@ -16,7 +16,7 @@ If true, NetBox will automatically create groups specified in the `REMOTE_AUTH_G
Default: `False`
If true, NetBox will automatically create local accounts for users authenticated via a remote service. (Requires `REMOTE_AUTH_ENABLED`.)
If `True`, NetBox will automatically create local accounts for users authenticated via a remote service. (Requires `REMOTE_AUTH_ENABLED`.)
---
@@ -43,7 +43,7 @@ The list of groups to assign a new user account when created using remote authen
Default: `{}` (Empty dictionary)
A mapping of permissions to assign a new user account when created using remote authentication. Each key in the dictionary should be set to a dictionary of the attributes to be applied to the permission, or `None` to allow all objects. (Requires `REMOTE_AUTH_ENABLED` as True and `REMOTE_AUTH_GROUP_SYNC_ENABLED` as False.)
A mapping of permissions to assign a new user account when created using remote authentication. Each key in the dictionary should be set to a dictionary of the attributes to be applied to the permission, or `None` to allow all objects. (Requires `REMOTE_AUTH_ENABLED` as `True` and `REMOTE_AUTH_GROUP_SYNC_ENABLED` as `False`.)
---
@@ -127,19 +127,3 @@ The list of groups that promote an remote User to Superuser on Login. If group i
Default: `[]` (Empty list)
The list of users that get promoted to Superuser on Login. If user isn't present in list on next Login, the Role gets revoked. (Requires `REMOTE_AUTH_ENABLED` and `REMOTE_AUTH_GROUP_SYNC_ENABLED` )
---
## REMOTE_AUTH_STAFF_GROUPS
Default: `[]` (Empty list)
The list of groups that promote an remote User to Staff on Login. If group isn't present on next Login, the Role gets revoked. (Requires `REMOTE_AUTH_ENABLED` and `REMOTE_AUTH_GROUP_SYNC_ENABLED` )
---
## REMOTE_AUTH_STAFF_USERS
Default: `[]` (Empty list)
The list of users that get promoted to Staff on Login. If user isn't present in list on next Login, the Role gets revoked. (Requires `REMOTE_AUTH_ENABLED` and `REMOTE_AUTH_GROUP_SYNC_ENABLED` )
This is a list of valid fully-qualified domain names (FQDNs) and/or IP addresses that can be used to reach the NetBox service. Usually this is the same as the hostname for the NetBox server, but can also be different; for example, when using a reverse proxy serving the NetBox website under a different FQDN than the hostname of the NetBox server. To help guard against [HTTP Host header attackes](https://docs.djangoproject.com/en/3.0/topics/security/#host-headers-virtual-hosting), NetBox will not permit access to the server via any other hostnames (or IPs).
This is a list of valid fully-qualified domain names (FQDNs) and/or IP addresses that can be used to reach the NetBox service. Usually this is the same as the hostname for the NetBox server, but can also be different; for example, when using a reverse proxy serving the NetBox website under a different FQDN than the hostname of the NetBox server. To help guard against [HTTP Host header attacks](https://docs.djangoproject.com/en/stable/topics/security/#host-headers-virtual-hosting), NetBox will not permit access to the server via any other hostnames (or IPs).
!!! note
This parameter must always be defined as a list or tuple, even if only a single value is provided.
The value of this option is also used to set `CSRF_TRUSTED_ORIGINS`, which restricts POST requests to the same set of hosts (more about this [here](https://docs.djangoproject.com/en/stable/ref/settings/#std:setting-CSRF_TRUSTED_ORIGINS)). Keep in mind that NetBox, by default, sets `USE_X_FORWARDED_HOST` to true, which means that if you're using a reverse proxy, it's the FQDN used to reach that reverse proxy which needs to be in this list (more about this [here](https://docs.djangoproject.com/en/stable/ref/settings/#allowed-hosts)).
The value of this option is also used to set `CSRF_TRUSTED_ORIGINS`, which restricts POST requests to the same set of hosts (more about this [here](https://docs.djangoproject.com/en/stable/ref/settings/#std:setting-CSRF_TRUSTED_ORIGINS)). Keep in mind that NetBox, by default, sets `USE_X_FORWARDED_HOST` to `True`, which means that if you're using a reverse proxy, it's the FQDN used to reach that reverse proxy which needs to be in this list (more about this [here](https://docs.djangoproject.com/en/stable/ref/settings/#allowed-hosts)).
Example:
@@ -23,9 +23,55 @@ ALLOWED_HOSTS = ['*']
---
## API_TOKEN_PEPPERS
!!! info "This parameter was introduced in NetBox v4.5."
[Cryptographic peppers](https://en.wikipedia.org/wiki/Pepper_(cryptography)) are employed to generate hashes of sensitive values on the server. This parameter defines the peppers used to hash v2 API tokens in NetBox. You must define at least one pepper before creating a v2 API token. See the [API documentation](../integrations/rest-api.md#authentication) for further information about how peppers are used.
Treat pepper values as extremely sensitive. Consider populating peppers from environment variables at initialization time rather than defining them in the configuration file, if feasible.
Peppers must be at least 50 characters in length and should comprise a random string with a diverse character set. Consider using the Python script at `$INSTALL_ROOT/netbox/generate_secret_key.py` to generate a pepper value.
It is recommended to start with a pepper ID of `1`. Additional peppers can be introduced later as needed to begin rotating token hashes.
!!! tip
Although NetBox will run without `API_TOKEN_PEPPERS` defined, the use of v2 API tokens will be unavailable.
---
## DATABASE
NetBox requires access to a PostgreSQL 12 or later database service to store data. This service can run locally on the NetBox server or on a remote system. The following parameters must be defined within the `DATABASE` dictionary:
!!! warning "Legacy Configuration Parameter"
The `DATABASE` configuration parameter is deprecated and will be removed in a future release. Users are advised to adopt the new `DATABASES` (plural) parameter, which allows for the configuration of multiple databases.
See the [`DATABASES`](#databases) configuration below for usage.
---
## DATABASES
NetBox requires access to a PostgreSQL 14 or later database service to store data. This service can run locally on the NetBox server or on a remote system. Databases are defined as named dictionaries:
```python
DATABASES={
'default':{...},
'external1':{...},
'external2':{...},
}
```
NetBox itself requires only that a `default` database is defined. However, certain plugins may require the configuration of additional databases. (Consider also configuring the [`DATABASE_ROUTERS`](./system.md#database_routers) parameter when multiple databases are in use.)
The following parameters must be defined for each database:
*`NAME` - Database name
*`USER` - PostgreSQL username
@@ -38,14 +84,16 @@ NetBox requires access to a PostgreSQL 12 or later database service to store dat
'PORT':'',# Database port (leave blank for default)
'CONN_MAX_AGE':300,# Max database connection age
}
}
```
@@ -53,7 +101,7 @@ DATABASE = {
NetBox supports all PostgreSQL database options supported by the underlying Django framework. For a complete list of available parameters, please see [the Django documentation](https://docs.djangoproject.com/en/stable/ref/settings/#databases).
!!! warning
Make sure to use a PostgreSQL-compatible backend for the ENGINE setting. If you don't specify an ENGINE, the default will be django.db.backends.postgresql.
The `ENGINE` parameter must specify a PostgreSQL-compatible database backend. If not defined, the default engine `django.db.backends.postgresql` will be used.
If disabled, the values of API tokens will not be displayed after each token's initial creation. A user **must** record the value of a token prior to its creation, or it will be lost. Note that this affects _all_ users, regardless of assigned permissions.
---
## ALLOWED_URL_SCHEMES
!!! tip "Dynamic Configuration Parameter"
@@ -20,26 +12,36 @@ A list of permitted URL schemes referenced when rendering links within NetBox. N
## AUTH_PASSWORD_VALIDATORS
This parameter acts as a pass-through for configuring Django's built-in password validators for local user accounts. If configured, these will be applied whenever a user's password is updated to ensure that it meets minimum criteria such as length or complexity. An example is provided below. For more detail on the available options, please see [the Django documentation](https://docs.djangoproject.com/en/stable/topics/auth/passwords/#password-validation).
This parameter acts as a pass-through for configuring Django's built-in password validators for local user accounts. These rules are applied whenever a user's password is created or updated to ensure that it meets minimum criteria such as length or complexity. The default configuration is shown below.
The default configuration enforces the follow criteria:
* A password must be at least 12 characters in length.
* A password must have at least one uppercase letter, one lowercase letter, and one numeric digit.
Although it is not recommended, the default validation rules can be disabled by setting `AUTH_PASSWORD_VALIDATORS = []` in the configuration file. For more detail on customizing password validation, please see [the Django documentation](https://docs.djangoproject.com/en/stable/topics/auth/passwords/#password-validation).
---
## CORS_ORIGIN_ALLOW_ALL
Default: False
Default: `False`
If True, cross-origin resource sharing (CORS) requests will be accepted from all origins. If False, a whitelist will be used (see below).
If `True`, cross-origin resource sharing (CORS) requests will be accepted from all origins. If False, a whitelist will be used (see below).
---
@@ -49,7 +51,7 @@ If True, cross-origin resource sharing (CORS) requests will be accepted from all
These settings specify a list of origins that are authorized to make cross-site API requests. Use
`CORS_ORIGIN_WHITELIST` to define a list of exact hostnames, or `CORS_ORIGIN_REGEX_WHITELIST` to define a set of regular
expressions. (These settings have no effect if `CORS_ORIGIN_ALLOW_ALL` is True.) For example:
expressions. (These settings have no effect if `CORS_ORIGIN_ALLOW_ALL` is `True`.) For example:
```python
CORS_ORIGIN_WHITELIST=[
@@ -69,9 +71,9 @@ The name of the cookie to use for the cross-site request forgery (CSRF) authenti
## CSRF_COOKIE_SECURE
Default: False
Default: `False`
If true, the cookie employed for cross-site request forgery (CSRF) protection will be marked as secure, meaning that it can only be sent across an HTTPS connection.
If `True`, the cookie employed for cross-site request forgery (CSRF) protection will be marked as secure, meaning that it can only be sent across an HTTPS connection.
---
@@ -79,7 +81,7 @@ If true, the cookie employed for cross-site request forgery (CSRF) protection wi
Default: `[]`
Defines a list of trusted origins for unsafe (e.g. `POST`) requests. This is a pass-through to Django's [`CSRF_TRUSTED_ORIGINS`](https://docs.djangoproject.com/en/4.0/ref/settings/#std:setting-CSRF_TRUSTED_ORIGINS) setting. Note that each host listed must specify a scheme (e.g. `http://` or `https://).
Defines a list of trusted origins for unsafe (e.g. `POST`) requests. This is a pass-through to Django's [`CSRF_TRUSTED_ORIGINS`](https://docs.djangoproject.com/en/stable/ref/settings/#csrf-trusted-origins) setting. Note that each host listed must specify a scheme (e.g. `http://` or `https://).
```python
CSRF_TRUSTED_ORIGINS = (
@@ -122,7 +124,7 @@ DEFAULT_PERMISSIONS = {
## EXEMPT_VIEW_PERMISSIONS
Default: Empty list
Default: `[]` (Empty list)
A list of NetBox models to exempt from the enforcement of view permissions. Models listed here will be viewable by all users, both authenticated and anonymous.
If true, the lifetime of a user's authentication session will be automatically reset upon each valid request. For example, if [`LOGIN_TIMEOUT`](#login_timeout) is configured to 14 days (the default), and a user whose session is due to expire in five days makes a NetBox request (with a valid session cookie), the session's lifetime will be reset to 14 days.
If `True`, the lifetime of a user's authentication session will be automatically reset upon each valid request. For example, if [`LOGIN_TIMEOUT`](#login_timeout) is configured to 14 days (the default), and a user whose session is due to expire in five days makes a NetBox request (with a valid session cookie), the session's lifetime will be reset to 14 days.
Note that enabling this setting causes NetBox to update a user's session in the database (or file, as configured per [`SESSION_FILE_PATH`](#session_file_path)) with each request, which may introduce significant overhead in very active environments. It also permits an active user to remain authenticated to NetBox indefinitely.
@@ -159,7 +161,7 @@ Note that enabling this setting causes NetBox to update a user's session in the
## LOGIN_REQUIRED
Default: True
Default: `True`
When enabled, only authenticated users are permitted to access any part of NetBox. Disabling this will allow unauthenticated users to access most areas of NetBox (but not make any changes).
@@ -170,12 +172,23 @@ When enabled, only authenticated users are permitted to access any part of NetBo
## LOGIN_TIMEOUT
Default: 1209600 seconds (14 days)
Default: `1209600` seconds (14 days)
The lifetime (in seconds) of the authentication cookie issued to a NetBox user upon login.
---
## LOGIN_FORM_HIDDEN
Default: `False`
Option to hide the login form when only SSO authentication is in use.
!!! warning
If the SSO provider is unreachable, login to NetBox will be impossible if this option is enabled. The only recourse is to disable it in the local configuration and restart the NetBox service.
---
## LOGOUT_REDIRECT_URL
Default: `'home'`
@@ -186,23 +199,23 @@ The view name or URL to which a user is redirected after logging out.
## SECURE_HSTS_INCLUDE_SUBDOMAINS
Default: False
Default: `False`
If true, the `includeSubDomains` directive will be included in the HTTP Strict Transport Security (HSTS) header. This directive instructs the browser to apply the HSTS policy to all subdomains of the current domain.
If `True`, the `includeSubDomains` directive will be included in the HTTP Strict Transport Security (HSTS) header. This directive instructs the browser to apply the HSTS policy to all subdomains of the current domain.
---
## SECURE_HSTS_PRELOAD
Default: False
Default: `False`
If true, the `preload` directive will be included in the HTTP Strict Transport Security (HSTS) header. This directive instructs the browser to preload the site in HTTPS. Browsers that use the HSTS preload list will force the site to be accessed via HTTPS even if the user types HTTP in the address bar.
If `True`, the `preload` directive will be included in the HTTP Strict Transport Security (HSTS) header. This directive instructs the browser to preload the site in HTTPS. Browsers that use the HSTS preload list will force the site to be accessed via HTTPS even if the user types HTTP in the address bar.
---
## SECURE_HSTS_SECONDS
Default: 0
Default: `0`
If set to a non-zero integer value, the SecurityMiddleware sets the HTTP Strict Transport Security (HSTS) header on all responses that do not already have it. This will instruct the browser that the website must be accessed via HTTPS, blocking any HTTP request.
@@ -210,9 +223,9 @@ If set to a non-zero integer value, the SecurityMiddleware sets the HTTP Strict
## SECURE_SSL_REDIRECT
Default: False
Default: `False`
If true, all non-HTTPS requests will be automatically redirected to use HTTPS.
If `True`, all non-HTTPS requests will be automatically redirected to use HTTPS.
!!! warning
Ensure that your frontend HTTP daemon has been configured to forward the HTTP scheme correctly before enabling this option. An incorrectly configured frontend may result in a looping redirect.
@@ -229,14 +242,14 @@ The name used for the session cookie. See the [Django documentation](https://doc
## SESSION_COOKIE_SECURE
Default: False
Default: `False`
If true, the cookie employed for session authentication will be marked as secure, meaning that it can only be sent across an HTTPS connection.
If `True`, the cookie employed for session authentication will be marked as secure, meaning that it can only be sent across an HTTPS connection.
---
## SESSION_FILE_PATH
Default: None
Default: `None`
HTTP session data is used to track authenticated users when they access NetBox. By default, NetBox stores session data in its PostgreSQL database. However, this inhibits authentication to a standby instance of NetBox without write access to the database. Alternatively, a local file path may be specified here and NetBox will store session data as files instead of using the database. Note that the NetBox system user must have read and write permissions to this path.
The base URL path to use when accessing NetBox. Do not include the scheme or domain name. For example, if installed at https://example.com/netbox/, set:
@@ -12,6 +12,14 @@ BASE_PATH = 'netbox/'
---
## DATABASE_ROUTERS
Default: `[]` (empty list)
An iterable of [database routers](https://docs.djangoproject.com/en/stable/topics/db/multi-db/) to use for automatically selecting the appropriate database(s) for a query. This is useful only when [multiple databases](./required-parameters.md#databases) have been configured.
---
## DEFAULT_LANGUAGE
Default: `en-us` (US English)
@@ -62,9 +70,19 @@ Email is sent from NetBox only for critical events or if configured for [logging
---
## HOSTNAME
!!! info "This parameter was introduced in NetBox v4.4."
Default: System hostname
The hostname displayed in the user interface identifying the system on which NetBox is running. If not defined, this defaults to the system hostname as reported by Python's `platform.node()`.
---
## HTTP_PROXIES
Default: None
Default: `None`
A dictionary of HTTP proxies to use for outbound requests originating from NetBox (e.g. when sending webhook requests). Proxies should be specified by schema (HTTP and HTTPS) as per the [Python requests library documentation](https://requests.readthedocs.io/en/latest/user/advanced/#proxies). For example:
@@ -75,6 +93,8 @@ HTTP_PROXIES = {
}
```
If more flexibility is needed in determining which proxy to use for a given request, consider implementing one or more custom proxy routers via the [`PROXY_ROUTERS`](#proxy_routers) parameter.
A list of IP addresses recognized as internal to the system, used to control the display of debugging output. For
example, the debugging toolbar will be viewable only when a client is accessing NetBox from one of the listed IP
addresses (and [`DEBUG`](./development.md#debug) is true).
addresses (and [`DEBUG`](./development.md#debug) is `True`).
---
## ISOLATED_DEPLOYMENT
Default: `False`
Set this configuration parameter to `True` for NetBox deployments which do not have Internet access. This will disable miscellaneous functionality which depends on access to the Internet.
!!! note
If Internet access is available via a proxy, set [`HTTP_PROXIES`](#http_proxies) instead.
---
@@ -91,7 +122,7 @@ addresses (and [`DEBUG`](./development.md#debug) is true).
Default: `{}`
A dictionary of custom jinja2 filters with the key being the filter name and the value being a callable. For more information see the [Jinja2 documentation](https://jinja.palletsprojects.com/en/3.1.x/api/#custom-filters). For example:
A dictionary of custom Jinja2 filters with the key being the filter name and the value being a callable. For more information see the [Jinja2 documentation](https://jinja.palletsprojects.com/en/3.1.x/api/#custom-filters). For example:
```python
def uppercase(x):
@@ -135,6 +166,8 @@ LOGGING = {
* `netbox.<app>.<model>` - Generic form for model-specific log messages
* `netbox.auth.*` - Authentication events
* `netbox.api.views.*` - Views which handle business logic for the REST API
* `netbox.views.*` - Views which handle business logic for the web UI
@@ -143,12 +176,22 @@ LOGGING = {
## MEDIA_ROOT
Default: $INSTALL_ROOT/netbox/media/
Default: `$INSTALL_ROOT/netbox/media/`
The file path to the location where media files (such as image attachments) are stored. By default, this is the `netbox/media/` directory within the base NetBox installation path.
---
## PROXY_ROUTERS
Default: `["utilities.proxy.DefaultProxyRouter"]`
A list of Python classes responsible for determining which proxy server(s) to use for outbound HTTP requests. Each item in the list can be the class itself or the dotted path to the class.
The `route()` method on each class must return a dictionary of candidate proxies arranged by protocol (e.g. `http` and/or `https`), or None if no viable proxy can be determined. The default class, `DefaultProxyRouter`, simply returns the content of [`HTTP_PROXIES`](#http_proxies).
---
## REPORTS_ROOT
Default: `$INSTALL_ROOT/netbox/reports/`
@@ -173,29 +216,92 @@ The dotted path to the desired search backend class. `CachedValueSearchBackend`
---
## STORAGE_BACKEND
## STORAGES
Default: None (local storage)
The backend storage engine for handling uploaded files such as [image attachments](../models/extras/imageattachment.md) and [custom scripts](../customization/custom-scripts.md). NetBox integrates with the [`django-storages`](https://django-storages.readthedocs.io/en/stable/) and [`django-storage-swift`](https://github.com/dennisv/django-storage-swift) libraries, which provide backends for several popular file storage services. If not configured, local filesystem storage will be used.
The backend storage engine for handling uploaded files (e.g. image attachments). NetBox supports integration with the [`django-storages`](https://django-storages.readthedocs.io/en/stable/) and [`django-storage-swift`](https://github.com/dennisv/django-storage-swift) packages, which provide backends for several popular file storage services. If not configured, local filesystem storage will be used.
By default, the following configuration is used:
The configuration parameters for the specified storage backend are defined under the `STORAGE_CONFIG` setting.
A dictionary of configuration parameters for the storage backend configured as `STORAGE_BACKEND`. The specific parameters to be used here are specific to each backend; see the documentation for your selected backend ([`django-storages`](https://django-storages.readthedocs.io/en/stable/) or [`django-storage-swift`](https://github.com/dennisv/django-storage-swift)) for more detail.
The specific configuration settings for each storage backend can be found in the [django-storages documentation](https://django-storages.readthedocs.io/en/latest/index.html).
If `STORAGE_BACKEND` is not defined, this setting will be ignored.
!!! note
Any keys defined in the `STORAGES` configuration parameter replace those in the default configuration. It is only necessary to define keys within the `STORAGES` for the specific backend(s) you wish to configure.
### Environment Variables and Third-Party Libraries
NetBox uses an explicit Python configuration approach rather than automatic environment variable detection. While this provides clear configuration management and version control capabilities, it affects how some third-party libraries like `django-storages` function within NetBox's context.
Many Django libraries (including `django-storages`) expect to automatically detect environment variables like `AWS_STORAGE_BUCKET_NAME` or `AWS_S3_ACCESS_KEY_ID`. However, NetBox's configuration processing prevents this automatic detection from working as documented in some of these libraries.
When using third-party libraries that rely on environment variable detection, you may need to explicitly read environment variables in your NetBox `configuration.py`:
This approach works because the environment variables are resolved during NetBox's configuration processing, before the third-party library attempts its own environment variable detection.
!!! warning "Configuration Behavior"
Simply setting environment variables like `AWS_STORAGE_BUCKET_NAME` without explicitly reading them in your configuration will not work. The variables must be read using `os.environ.get()` within your `configuration.py` file.
---
## TIME_ZONE
Default: UTC
Default: `"UTC"`
The time zone NetBox will use when dealing with dates and times. It is recommended to use UTC time unless you have a specific need to use a local time zone. Please see the [list of available time zones](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones).
@@ -203,6 +309,6 @@ The time zone NetBox will use when dealing with dates and times. It is recommend
## TRANSLATION_ENABLED
Default: True
Default: `True`
Enables language translation for the user interface. (This parameter maps to Django's [USE_I18N](https://docs.djangoproject.com/en/stable/ref/settings/#std-setting-USE_I18N) setting.)
@@ -74,6 +74,8 @@ If a default value is specified for a selection field, it must exactly match one
An object or multi-object custom field can be used to refer to a particular NetBox object or objects as the "value" for a custom field. These custom fields must define an `object_type`, which determines the type of object to which custom field instances point.
By default, an object choice field will make all objects of that type available for selection in the drop-down. The list choices can be filtered to show only objects with certain values by providing a `query_params` dict in the Related Object Filter field, as a JSON value. More information about `query_params` can be found [here](./custom-scripts.md#objectvar).
## Custom Fields in Templates
Several features within NetBox, such as export templates and webhooks, utilize Jinja2 templating. For convenience, objects which support custom field assignment expose custom field data through the `cf` property. This is a bit cleaner than accessing custom field data through the actual field (`custom_field_data`).
Custom links allow users to display arbitrary hyperlinks to external content within NetBox object views. These are helpful for cross-referencing related records in systems outside NetBox. For example, you might create a custom link on the device view which links to the current device in a Network Monitoring System (NMS).
Custom links are created by navigating to Customization > Custom Links. Each link is associated with a particular NetBox object type (site, device, prefix, etc.) and will be displayed on relevant views. Each link has display text and a URL, and data from the NetBox item being viewed can be included in the link using [Jinja2 template code](https://jinja2docs.readthedocs.io/en/stable/) through the variable `object`, and custom fields through `object.cf`.
Custom links are created by navigating to Customization > Custom Links. Each link is associated with a particular NetBox object type (site, device, prefix, etc.) and will be displayed on relevant views. Each link has display text and a URL, and data from the NetBox item being viewed can be included in the link using [Jinja template code](https://jinja.palletsprojects.com/en/stable/) through the variable `object`, and custom fields through `object.cf`.
@@ -17,6 +17,9 @@ They can also be used as a mechanism for validating the integrity of data within
Custom scripts are Python code which exists outside the NetBox code base, so they can be updated and changed without interfering with the core NetBox installation. And because they're completely custom, there is no inherent limitation on what a script can accomplish.
!!! danger "Only install trusted scripts"
Custom scripts have unrestricted access to change anything in the databse and are inherently unsafe and should only be installed and run from trusted sources. You should also review and set permissions for who can run scripts if the script can modify any data.
## Writing Custom Scripts
All custom scripts must inherit from the `extras.scripts.Script` base class. This class provides the functionality necessary to generate forms and log activity.
Script attributes are defined under a class named `Meta` within the script. These are optional, but encouraged.
!!! warning
These are also defined and used as properties on the base custom script class, so don't use the same names as variables or override them in your custom script.
### `name`
This is the human-friendly names of your script. If omitted, the class name will be used.
@@ -125,15 +131,6 @@ self.log_info(f"Running as user {username} (IP: {ip_address})...")
For a complete list of available request parameters, please see the [Django documentation](https://docs.djangoproject.com/en/stable/ref/request-response/).
## Reading Data from Files
The Script class provides two convenience methods for reading data from files:
*`load_yaml`
*`load_json`
These two methods will load data in YAML or JSON format, respectively, from files within the local path (i.e. `SCRIPTS_ROOT`).
## Logging
The Script object provides a set of convenient functions for recording messages at different severity levels:
@@ -267,6 +264,15 @@ Stores a numeric integer. Options include:
*`min_value` - Minimum value
*`max_value` - Maximum value
### DecimalVar
Stores a numeric decimal. Options include:
*`min_value` - Minimum value
*`max_value` - Maximum value
*`max_digits` - Maximum number of digits, including decimal places
*`decimal_places` - Number of decimal places
### BooleanVar
A true/false flag. This field has no options beyond the defaults listed above.
@@ -302,6 +308,7 @@ A particular object within NetBox. Each ObjectVar must specify a particular mode
*`query_params` - A dictionary of query parameters to use when retrieving available options (optional)
*`context` - A custom dictionary mapping template context variables to fields, used when rendering `<option>` elements within the dropdown menu (optional; see below)
*`null_option` - A label representing a "null" or empty choice (optional)
*`selector` - A boolean that, when True, includes an advanced object selection widget to assist the user in identifying the desired object (optional; False by default)
To limit the selections available within the list, additional query parameters can be passed as the `query_params` dictionary. For example, to show only devices with an "active" status:
!!! info "This feature was introduced in NetBox v4.0."
The attributes of a related object can be referenced by specifying a dotted path. For example, to reference the name of a region to which a site is assigned, use `region.name`:
```python
@@ -104,8 +102,6 @@ CUSTOM_VALIDATORS = {
#### Validating Request Parameters
!!! info "This feature was introduced in NetBox v4.0."
In addition to validating object attributes, custom validators can also match against parameters of the current request (where available). For example, the following rule will permit only the user named "admin" to modify an object:
To access custom fields of an object within a template, use the `cf` attribute. For example, `{{ obj.cf.color }}` will return the value (if any) for a custom field named `color` on `obj`.
If you need to use the config context data in an export template, you'll should use the function `get_config_context` to get all the config context data. For example:
@@ -8,7 +8,7 @@ Each model should define, at a minimum:
* A `Meta` class specifying a deterministic ordering (if ordered by fields other than the primary ID)
* A `__str__()` method returning a user-friendly string representation of the instance
* A `get_absolute_url()` method returning an instance's direct URL (using `reverse()`)
* A `get_absolute_url()` method if necessary; a standard version of the method is defined in the `NetBoxFeatureSet` base class, but you will need to provide your own (returning an instance's direct URL using `reverse()`) if not subclassing that base class
## 2. Define field choices
@@ -71,15 +71,18 @@ Add the relevant navigation menu items in `netbox/netbox/navigation/menu.py`.
Create the following for each model:
* Detailed (full) model serializer in `api/serializers.py`
* Nested serializer in `api/nested_serializers.py`
* API view in `api/views.py`
* Endpoint route in `api/urls.py`
## 13. GraphQL API components
Create a GraphQL object type for the model in `graphql/types.py` by subclassing the appropriate class from `netbox.graphql.types`.
Create the following for each model:
Also extend the schema class defined in `graphql/schema.py` with the individual object and object list fields per the established convention.
* GraphQL object type for the model in `graphql/types.py` (subclass the appropriate class from `netbox.graphql.types`)
* Add a GraphQL filter for the model in `graphql/filters.py`
* Extend the query class for the app in `graphql/schema.py` with the individual object and object list fields
**Note:** GraphQL unit tests may fail citing null values on a non-nullable field if related objects are prefetched. You may need to fix this by setting the type annotation to be `= strawberry_django.field(select_related=["foo"])` or similar.
@@ -22,24 +22,9 @@ Stores registration made using `netbox.denormalized.register()`. For each model,
### `model_features`
A dictionary of particular features (e.g. custom fields) mapped to the NetBox models which support them, arranged by app. For example:
A dictionary of model features (e.g. custom fields, tags, etc.) mapped to the functions used to qualify a model as supporting each feature. Model features are registered using the `register_model_feature()` function in `netbox.utils`.
```python
{
'custom_fields':{
'circuits':['provider','circuit'],
'dcim':['site','rack','devicetype',...],
...
},
'event_rules':{
'extras':['configcontext','tag',...],
'dcim':['site','rack','devicetype',...],
},
...
}
```
Supported model features are listed in the [features matrix](./models.md#features-matrix).
Core model features are listed in the [features matrix](./models.md#features-matrix).
### `models`
@@ -49,6 +34,10 @@ This key lists all models which have been registered in NetBox which are not des
This store maintains all registered items for plugins, such as navigation menus, template extensions, etc.
### `request_processors`
A list of context managers to invoke when processing a request e.g. in middleware or when executing a background job. Request processors can be registered with the `@register_request_processor` decorator.
### `search`
A dictionary mapping each model (identified by its app and label) to its search index class, if one has been registered for it.
@@ -6,7 +6,7 @@ Below is a list of tasks to consider when adding a new field to a core model.
Add the field to the model, taking care to address any of the following conditions.
* When adding a GenericForeignKey field, also add an index under `Meta` for its two concrete fields. For example:
* When adding a GenericForeignKey field, you may need add an index under `Meta` for its two concrete fields. (This is required only for non-unique GFK relationships, as the unique constraint introduces its own index.) For example:
```python
class Meta:
@@ -50,7 +50,7 @@ If you're adding a relational field (e.g. `ForeignKey`) and intend to include th
## 5. Update API serializer
Extend the model's API serializer in `<app>.api.serializers` to include the new field. In most cases, it will not be necessary to also extend the nested serializer, which produces a minimal representation of the model.
Extend the model's API serializer in `<app>.api.serializers` to include the new field.
The NetBox project utilizes three persistent git branches to track work:
The NetBox project utilizes two persistent git branches to track work:
* `master` - Serves as a snapshot of the current stable release
* `develop` - All development on the upcoming stable (patch) release occurs here
* `feature` - Tracks work on an upcoming minor release
* `main` - All development on the upcoming stable (patch) release occurs here. Releases are published from this branch.
* `feature` - All work planned for the upcoming minor release is done here.
Typically, you'll base pull requests off of the `develop` branch, or off of `feature` if you're working on a new major release. For example, assume that the current NetBox release is v3.3.5. Work applied to the `develop` branch will appear in v3.3.6, and work done under the `feature` branch will be included in the next minor release (v3.4.0).
!!! warning
**Never** merge pull requests into the `master` branch: This branch only ever merges pull requests from the `develop` branch, to effect a new release.
Typically, you'll base pull requests off of the `main` branch, or off of `feature` if you're working on the upcoming minor or major release. For example, assume that the current NetBox release is v4.2.3. Work applied to the `main` branch will appear in v4.2.4, and work done under the `feature` branch will be included in the next minor release (v4.3.0).
To create a new branch, first ensure that you've checked out the desired base branch, then run:
@@ -62,22 +58,7 @@ $issue-$description
The description should be just two or three words to imply the focus of the work being performed. For example, bug #1234 to fix a TypeError exception when creating a device might be named `1234-device-typerror`. This ensures that branches are always follow some logical ordering (e.g. when running `git branch -a`) and helps other developers quickly identify the purpose of each.
### 3. Enable Pre-Commit Hooks
NetBox ships with a [git pre-commit hook](https://githooks.com/) script that automatically checks for style compliance and missing database migrations prior to committing changes. This helps avoid erroneous commits that result in CI test failures. You are encouraged to enable it by creating a link to `scripts/git-hooks/pre-commit`:
```no-highlight
cd .git/hooks/
ln -s ../../scripts/git-hooks/pre-commit
```
For the pre-commit hooks to work, you will also need to install the pycodestyle package:
```no-highlight
python -m pip install pycodestyle
```
...and set up the yarn packages as shown in the [Web UI Development Guide](web-ui.md)
### 4. Create a Python Virtual Environment
### 3. Create a Python Virtual Environment
A [virtual environment](https://docs.python.org/3/tutorial/venv.html) (or "venv" for short) is like a container for a set of Python packages. These allow you to build environments suited to specific projects without interfering with system packages or other projects. When installed per the documentation, NetBox uses a virtual environment in production.
Notice that the console prompt changes to indicate the active environment. This updates the necessary system environment variables to ensure that any Python scripts are run within the virtual environment.
### 5. Install Required Packages
### 4. Install Required Packages
With the virtual environment activated, install the project's required Python packages using the `pip` module. Required packages are defined in `requirements.txt`. Each line in this file specifies the name and specific version of a required package.
@@ -109,12 +90,32 @@ With the virtual environment activated, install the project's required Python pa
python -m pip install -r requirements.txt
```
### 5. Install Pre-Commit
NetBox uses [`pre-commit`](https://pre-commit.com/) to automatically validate code when commiting new changes. This includes the following operations:
* Run the `ruff` Python linter
* Run Django's internal system check
* Check for missing database migrations
* Validate any changes to the documentation with `mkdocs`
* Validate Typescript & Sass styling with `yarn`
* Ensure that any modified static front end assets have been recompiled
Enable `pre-commit` with the following commands _prior_ to commiting any changes:
```no-highlight
python -m pip install ruff pre-commit
pre-commit install
```
You may also need to set up the yarn packages as shown in the [Web UI Development Guide](web-ui.md).
### 6. Configure NetBox
Within the `netbox/netbox/` directory, copy `configuration_example.py` to `configuration.py` and update the following parameters:
* `ALLOWED_HOSTS`: This can be set to `['*']` for development purposes
* `REDIS`: Redis configuration (if different from the defaults)
* `SECRET_KEY`: Set to a random string (use `generate_secret_key.py` in the parent directory to generate a suitable key)
* `DEBUG`: Set to `True`
@@ -146,7 +147,7 @@ For UI development you will need to review the [Web UI Development Guide](web-ui
## Populating Demo Data
Once you have your development environment up and running, it might be helpful to populate some "dummy" data to make interacting with the UI and APIs more convenient. Check out the [netbox-demo-data](https://github.com/netbox-community/netbox-demo-data) repo on GitHub, which houses a collection of sample data that can be easily imported to any new NetBox deployment. (This sample data is used to populate the public demo instance at <https://demo.netbox.dev>.)
Once you have your development environment up and running, it might be helpful to populate some "dummy" data to make interacting with the UI and APIs more convenient. Check out the [netbox-demo-data](https://github.com/netbox-community/netbox-demo-data) repo on GitHub, which houses a collection of sample data that can be easily imported to any new NetBox deployment. This sample data is used to populate the [public demo instance](https://demo.netbox.dev).
The demo data is provided in JSON format and loaded into an empty database using Django's `loaddata` management command. Consult the demo data repo's `README` file for complete instructions on populating the data.
You generally want to avoid merging branches that exist on the remote (upstream) repository, such as `develop` and `feature`: Merges into these branches should be done via a pull request on GitHub. Only merge branches when it is necessary to consolidate work you've done locally.
You generally want to avoid merging branches that exist on the remote (upstream) repository, namely `main` and `feature`: Merges into these branches should be done via a pull request on GitHub. Only merge branches when it is necessary to consolidate work you've done locally.
### Show Pending Changes
@@ -196,7 +196,7 @@ index 93e125079..4344fb514 100644
@@ -8,11 +8,10 @@ NetBox and many of its related projects are maintained on [GitHub](https://githu

There are three permanent branches in the repository:
There are two permanent branches in the repository:
*`master` - The current stable release. Individual changes should never be pushed directly to this branch, but rather merged from `develop`.
*`develop` - Active development for the upcoming patch release. Pull requests will typically be based on this branch unless they introduce breaking changes that must be deferred until the next minor release.
*`feature` - New feature work to be introduced in the next minor release (e.g. from v3.3 to v3.4).
*`main` - Active development for the upcoming patch release. Pull requests will typically be based on this branch unless they introduce breaking changes that must be deferred until the next minor release.
*`feature` - New feature work to be introduced in the next minor release (e.g. from v4.2 to v4.3).
NetBox components are arranged into Django apps. Each app holds the models, views, and other resources relevant to a particular function:
@@ -57,4 +56,4 @@ NetBox follows the [benevolent dictator](http://oss-watch.ac.uk/resources/benevo
## Licensing
The entire NetBox project is licensed as open source under the [Apache 2.0 license](https://github.com/netbox-community/netbox/blob/master/LICENSE.txt). This is a very permissive license which allows unlimited redistribution of all code within the project. Note that all submissions to the project are subject to the same license.
The entire NetBox project is licensed as open source under the [Apache 2.0 license](https://github.com/netbox-community/netbox/blob/main/LICENSE.txt). This is a very permissive license which allows unlimited redistribution of all code within the project. Note that all submissions to the project are subject to the same license.
@@ -10,19 +10,26 @@ The Django [content types](https://docs.djangoproject.com/en/stable/ref/contrib/
Depending on its classification, each NetBox model may support various features which enhance its operation. Each feature is enabled by inheriting from its designated mixin class, and some features also make use of the [application registry](./application-registry.md#model_features).
| [Change logging](../features/change-logging.md) | `ChangeLoggingMixin` | - | Changes to these objects are automatically recorded in the change log |
| Cloning | `CloningMixin` | - | Provides the `clone()` method to prepare a copy |
| [Custom fields](../customization/custom-fields.md) | `CustomFieldsMixin`| `custom_fields` | These models support the addition of user-defined fields |
| [Custom links](../customization/custom-links.md) | `CustomLinksMixin` | `custom_links` | These models support the assignment of custom links |
| [Custom validation](../customization/custom-validation.md) | `CustomValidationMixin`| - | Supports the enforcement of custom validation rules |
| [Export templates](../customization/export-templates.md) | `ExportTemplatesMixin` | `export_templates` | Users can create custom export templates for these models |
| [Job results](../features/background-jobs.md) | `JobsMixin`| `jobs` | Users can create custom export templates for these models |
| [Journaling](../features/journaling.md) | `JournalingMixin` | `journaling` | These models support persistent historical commentary |
| [Synchronized data](../integrations/synchronized-data.md) | `SyncedDataMixin` | `synced_data` | Certain model data can be automatically synchronized from a remote data source |
| [Tagging](../models/extras/tag.md) | `TagsMixin` | `tags` | The models can be tagged with user-defined tags |
| [Event rules](../features/event-rules.md) | `EventRulesMixin`| `event_rules` | Event rules can send webhooks or run custom scripts automatically in response to events |
| [Bookmarks](../features/customization.md#bookmarks) | `BookmarksMixin` | `bookmarks` | These models can be bookmarked natively in the user interface |
| [Change logging](../features/change-logging.md) | `ChangeLoggingMixin`| `change_logging` | Changes to these objects are automatically recorded in the change log |
| Cloning | `CloningMixin` | `cloning` | Provides the `clone()` method to prepare a copy |
| [Contacts](../features/contacts.md) | `ContactsMixin` | `contacts` | Contacts can be associated with these models |
| [Custom fields](../customization/custom-fields.md) | `CustomFieldsMixin`| `custom_fields` | These models support the addition of user-defined fields |
| [Custom links](../customization/custom-links.md) | `CustomLinksMixin` | `custom_links` | These models support the assignment of custom links |
| [Custom validation](../customization/custom-validation.md) | `CustomValidationMixin`| - | Supports the enforcement of custom validation rules |
| [Event rules](../features/event-rules.md) | `EventRulesMixin` | `event_rules` | Event rules can send webhooks or run custom scripts automatically in response to events |
| [Export templates](../customization/export-templates.md) | `ExportTemplatesMixin` | `export_templates` | Users can create custom export templates for these models |
| [Image attachments](../models/extras/imageattachment.md) | `ImageAttachmentsMixin` | `image_attachments` | Image uploads can be attached to these models |
| [Jobs](../features/background-jobs.md) | `JobsMixin` | `jobs` | Background jobs can be scheduled for these models |
| [Journaling](../features/journaling.md) | `JournalingMixin` | `journaling` | These models support persistent historical commentary |
| [Notifications](../features/notifications.md) | `NotificationsMixin` | `notifications` | These models support user notifications |
| [Synchronized data](../integrations/synchronized-data.md) | `SyncedDataMixin` | `synced_data` | Certain model data can be automatically synchronized from a remote data source |
| [Tagging](../models/extras/tag.md) | `TagsMixin` | `tags` | The models can be tagged with user-defined tags |
!!! note
The above listed features are supported natively by NetBox. Beginning with NetBox v4.4.0, plugins can register their own model features as well.
## Models Index
@@ -34,7 +41,9 @@ These are considered the "core" application models which are used to model netwo
This documentation describes the process of packaging and publishing a new NetBox release. There are three types of release:
This documentation describes the process of packaging and publishing a new NetBox release. There are three types of releases:
* Major release (e.g. v2.11 to v3.0)
* Minor release (e.g. v3.2 to v3.3)
* Patch release (e.g. v3.3.0 to v3.3.1)
* Major release (e.g. v3.7.8 to v4.0.0)
* Minor release (e.g. v4.0.10 to v4.1.0)
* Patch release (e.g. v4.1.0 to v4.1.1)
While major releases generally introduce some very substantial change to the application, they are typically treated the same as minor version increments for the purpose of release packaging.
While major releases generally introduce some very substantial changes to the application, they are typically treated the same as minor version increments for the purpose of release packaging.
For patch releases (e.g. upgrading from v4.2.2 to v4.2.3), begin at the [patch releases](#patch-releases) heading below. For minor or major releases, complete the entire checklist.
## Minor Version Releases
@@ -29,6 +31,17 @@ Close the [release milestone](https://github.com/netbox-community/netbox/milesto
Check that a link to the release notes for the new version is present in the navigation menu (defined in `mkdocs.yml`), and that a summary of all major new features has been added to `docs/index.md`.
### Update System Requirements
If a new Django release is adopted or other major dependencies (Python, PostgreSQL, Redis) change:
* Update the installation guide (`docs/installation/index.md`) with the new minimum versions.
* Update the upgrade guide (`docs/installation/upgrading.md`) for the current version.
* Update the minimum versions for each dependency.
* Add a new row to the release history table. Bold any version changes for clarity.
* Update the minimum PostgreSQL version in the programming error template (`netbox/templates/exceptions/programming_error.html`).
* Update the minimum and supported Python versions in the project metadata file (`pyproject.toml`)
### Manually Perform a New Install
Start the documentation server and navigate to the current version of the installation docs:
@@ -37,11 +50,25 @@ Start the documentation server and navigate to the current version of the instal
mkdocs serve
```
Follow these instructions to perform a new installation of NetBox in a temporary environment. This process must not be automated: The goal of this step is to catch any errors or omissions in the documentation, and ensure that it is kept up-to-date for each release. Make any necessary changes to the documentation before proceeding with the release.
Follow these instructions to perform a new installation of NetBox in a temporary environment. This process must not be automated: The goal of this step is to catch any errors or omissions in the documentation and ensure that it is kept uptodate for each release. Make any necessary changes to the documentation before proceeding with the release.
### Merge the Release Branch
### Test Upgrade Paths
Submit a pull request to merge the `feature` branch into the `develop` branch in preparation for its release. Once it has been merged, continue with the section for patch releases below.
Upgrading from a previous version typically involves database migrations, which must work without errors.
Test the following supported upgrade paths:
- From one minor version to another within the same major version (e.g. 4.0 to 4.1).
- From the latest patch version of the previous minor version (e.g. 3.7 to 4.0 or 4.1).
Prior to release, test all these supported paths by loading demo data from the source version and performing:
```no-highlight
./manage.py migrate
```
### Merge the `feature` Branch
Submit a pull request to merge the `feature` branch into the `main` branch in preparation for its release. Once it has been merged, continue with the section for the patch releases below.
### Rebuild Demo Data (After Release)
@@ -51,6 +78,15 @@ After the release of a new minor version, generate a new demo data snapshot comp
## Patch Releases
### Create a Release Branch
Begin by creating a new branch (based on `main`) to effect the release. This will comprise the changes listed below.
```
git checkout main
git checkout -B release-vX.Y.Z
```
### Notify netbox-docker Project of Any Relevant Changes
Notify the [`netbox-docker`](https://github.com/netbox-community/netbox-docker) maintainers (in **#netbox-docker**) of any changes that may be relevant to their build process, including:
@@ -72,7 +108,47 @@ In cases where upgrading a dependency to its most recent release is breaking, it
### Update UI Dependencies
Check whether any UI dependencies (JavaScript packages, fonts, etc.) need to be updated by running `yarn outdated` from within the `project-static/` directory. [Upgrade these dependencies](./web-ui.md#updating-dependencies) as necessary, then run `yarn bundle` to generate the necessary files for distribution.
Check whether any UI dependencies (JavaScript packages, fonts, etc.) need to be updated by running `yarn outdated` from within the `project-static/` directory. [Upgrade these dependencies](./web-ui.md#updating-dependencies) as necessary, then run `yarn bundle` to generate the necessary files for distribution:
```
$ yarn bundle
yarn run v1.22.19
$ node bundle.js
✅ Bundled source file 'styles/external.scss' to 'netbox-external.css'
✅ Bundled source file 'styles/netbox.scss' to 'netbox.css'
✅ Bundled source file 'styles/svg/rack_elevation.scss' to 'rack_elevation.css'
✅ Bundled source file 'styles/svg/cable_trace.scss' to 'cable_trace.css'
✅ Bundled source file 'index.ts' to 'netbox.js'
✅ Copied graphiql files
Done in 1.00s.
```
### Update & Compile Translations
Updated language translations should be pulled from [Transifex](https://app.transifex.com/netbox-community/netbox/dashboard/) and re-compiled for each new release. First, retrieve any updated translation files using the Transifex CLI client:
```no-highlight
tx pull --force
```
Then, compile these portable (`.po`) files for use in the application:
```no-highlight
./manage.py compilemessages
```
!!! tip
Consult the translation documentation for more detail on [updating translated strings](./translations.md#updating-translated-strings) if you've not set up the Transifex client already.
### Update Version and Changelog
* Update the version number and published date in `netbox/release.yaml`. Add or remove the designation (e.g. `beta1`) if applicable.
* Copy the version number from `release.yaml` to `pyproject.toml` in the project root.
* Update the example version numbers in the feature request and bug report templates under `.github/ISSUE_TEMPLATES/`.
* Add a section for this release at the top of the changelog page for the minor version (e.g. `docs/release-notes/version-4.2.md`) listing all relevant changes made in this release.
!!! tip
Put yourself in the shoes of the user when recording change notes. Focus on the effect that each change has for the end user, rather than the specific bits of code that were modified in a PR. Ensure that each message conveys meaning absent context of the initial feature request or bug report. Remember to include keywords or phrases (such as exception names) that can be easily searched.
### Rebuild the Device Type Definition Schema
@@ -84,57 +160,30 @@ Run the following command to update the device type definition validation schema
This will automatically update the schema file at `contrib/generated_schema.json`.
### Update & Compile Translations
### Update the OpenAPI Schema
Updated language translations should be pulled from [Transifex](https://app.transifex.com/netbox-community/netbox/dashboard/) and re-compiled for each new release. Follow the documented process for [updating translated strings](./translations.md#updating-translated-strings) to do this.
Update the static OpenAPI schema definition at `contrib/openapi.json` with the management command below. If the schema file is up-to-date, only the NetBox version will be changed.
### Update Version and Changelog
* Update the `VERSION` constant in `settings.py` to the new release version.
* Update the example version numbers in the feature request and bug report templates under `.github/ISSUE_TEMPLATES/`.
* Replace the "FUTURE" placeholder in the release notes with the current date.
Commit these changes to the `develop` branch and push upstream.
### Verify CI Build Status
Ensure that continuous integration testing on the `develop` branch is completing successfully. If it fails, take action to correct the failure before proceeding with the release.
Submit a pull request titled **"Release vX.Y.Z"** to merge the `develop` branch into `master`. Copy the documented release notes into the pull request's body.
Commit the above changes and submit a pull request titled **"Release vX.Y.Z"** to merge the current release branch (e.g. `release-vX.Y.Z`) into `main`. Copy the documented release notes into the pull request's body.
Once CI has completed on the PR, merge it. This effects a new release in the `master` branch.
Once CI has completed and a colleague has reviewed the PR, merge it. This effects a new release in the `main` branch.
!!! warning
To ensure a streamlined review process, the pull request for a release **must** be limited to the changes outlined in this document. A release PR must never include functional changes to the application: Any unrelated "cleanup" needs to be captured in a separate PR prior to the release being shipped.
### Create a New Release
Create a [new release](https://github.com/netbox-community/netbox/releases/new) on GitHub with the following parameters.
* **Tag:** Current version (e.g. `v3.3.1`)
* **Target:** `master`
* **Title:** Version and date (e.g. `v3.3.1 - 2022-08-25`)
* **Tag:** Current version (e.g. `v4.2.1`)
* **Target:** `main`
* **Title:** Version and date (e.g. `v4.2.1 - 2025-01-17`)
* **Description:** Copy from the pull request body, then promote the `###` headers to `##` ones
Once created, the release will become available for users to install.
### Update the Development Version
On the `develop` branch, update `VERSION` in `settings.py` to point to the next release. For example, if you just released v3.3.1, set:
```
VERSION = 'v3.3.2-dev'
```
Commit this change with the comment "PRVB" (for _post-release version bump_) and push the commit upstream.
### Update the Public Documentation
After a release has been published, the public NetBox documentation needs to be updated. This is accomplished by running two actions on the [netboxlabs-docs](https://github.com/netboxlabs/netboxlabs-docs) repository.
First, run the `build-site` action, by navigating to Actions > build-site > Run workflow. This process compiles the documentation along with an overlay for integration with the documentation portal at <https://netboxlabs.com/docs>. The job should take about two minutes.
Once the documentation files have been compiled, they must be published by running the `deploy-kinsta` action. Select the desired deployment environment (staging or production) and specify `latest` as the deploy tag.
Clear the CDN cache from the [Kinsta](https://my.kinsta.com/) portal. Navigate to _Sites_ / _NetBox Labs_ / _Live_, select _Cache_ in the left-nav, click the _Clear Cache_ button, and confirm the clear operation.
Finally, verify that the documentation at <https://netboxlabs.com/docs/netbox/en/stable/> has been updated.
NetBox generally follows the [Django style guide](https://docs.djangoproject.com/en/stable/internals/contributing/writing-code/coding-style/), which is itself based on [PEP 8](https://www.python.org/dev/peps/pep-0008/). [Pycodestyle](https://github.com/pycqa/pycodestyle) is used to validate code formatting, ignoring certain violations.
NetBox generally follows the [Django style guide](https://docs.djangoproject.com/en/stable/internals/contributing/writing-code/coding-style/), which is itself based on [PEP 8](https://www.python.org/dev/peps/pep-0008/). [ruff](https://docs.astral.sh/ruff/) is used for linting (with certain [exceptions](#linter-exceptions)).
## Code
@@ -20,32 +20,32 @@ NetBox generally follows the [Django style guide](https://docs.djangoproject.com
* Nested API serializers generate minimal representations of an object. These are stored separately from the primary serializers to avoid circular dependencies. Always import nested serializers from other apps directly. For example, from within the DCIM app you would write `from ipam.api.nested_serializers import NestedIPAddressSerializer`.
### PEP 8 Exceptions
### Linting
NetBox ignores certain PEP8 assertions. These are listed below.
The [ruff](https://docs.astral.sh/ruff/) linter is used to enforce code style, and is run automatically by [pre-commit](./getting-started.md#5-install-pre-commit). To invoke `ruff` manually, run:
#### Wildcard Imports
```
ruff check netbox/
```
#### Linter Exceptions
The following rules are ignored when linting.
##### [E501](https://docs.astral.sh/ruff/rules/line-too-long/): Line too long
NetBox does not enforce a hard restriction on line length, although a maximum length of 120 characters is strongly encouraged for Python code where possible. The maximum length does not apply to HTML templates or to automatically generated code (e.g. database migrations).
##### [F403](https://docs.astral.sh/ruff/rules/undefined-local-with-import-star/): Undefined local with import star
Wildcard imports (for example, `from .constants import *`) are acceptable under any of the following conditions:
* The library being import contains only constant declarations (e.g. `constants.py`)
* The library being imported explicitly defines `__all__`
#### Maximum Line Length (E501)
##### [F405](https://docs.astral.sh/ruff/rules/undefined-local-with-import-star-usage/): Undefined local with import star usage
NetBox does not restrict lines to a maximum length of 79 characters. We use a maximum line length of 120 characters, however this is not enforced by CI. The maximum length does not apply to HTML templates or to automatically generated code (e.g. database migrations).
#### Line Breaks Following Binary Operators (W504)
Line breaks are permitted following binary operators.
### Enforcing Code Style
The [`pycodestyle`](https://pypi.org/project/pycodestyle/) utility (formerly `pep8`) is used by the CI process to enforce code style. A [pre-commit hook](./getting-started.md#3-enable-pre-commit-hooks) which runs this automatically is included with NetBox. To invoke `pycodestyle` manually, run:
```
pycodestyle --ignore=W504,E501 netbox/
```
The justification for ignoring this rule is the same as F403 above.
### Introducing New Dependencies
@@ -76,4 +76,4 @@ When adding a new dependency, a short description of the package and the URL of
* When referring to NetBox in writing, use the proper form "NetBox," with the letters N and B capitalized. The lowercase form "netbox" should be used in code, filenames, etc. but never "Netbox" or any other deviation.
* There is an SVG form of the NetBox logo at [docs/netbox_logo.svg](../netbox_logo.svg). It is preferred to use this logo for all purposes as it scales to arbitrary sizes without loss of resolution. If a raster image is required, the SVG logo should be converted to a PNG image of the prescribed size.
* There are SVG forms of the NetBox logo for both [light mode](../netbox_logo_light.svg) and [dark mode](../netbox_logo_dark.svg) available. It is preferred to use the SVG logo for all purposes as it scales to arbitrary sizes without loss of resolution. If a raster image is required, the SVG logo should be converted to a PNG image of the desired size.
@@ -14,7 +14,10 @@ To update the English `.po` file from which all translations are derived, use th
./manage.py makemessages -l en -i "project-static/*"
```
Then, commit the change and push to the `develop` branch on GitHub. Any new strings will appear for translation on Transifex automatically.
Then, commit the change and push to the `main` branch on GitHub. Any new strings will appear for translation on Transifex automatically.
!!! note
It is typically not necessary to update source strings manually, as this is done nightly by a [GitHub action](https://github.com/netbox-community/netbox/blob/main/.github/workflows/update-translation-strings.yml).
## Updating Translated Strings
@@ -22,25 +25,30 @@ Typically, translated strings need to be updated only as part of the NetBox [rel
Check the Transifex dashboard for languages that are not marked _ready for use_, being sure to click _Show all languages_ if it appears at the bottom of the list. Use machine translation to round out any not-ready languages. It's not necessary to review the machine translation immediately as the translation teams will handle that aspect; the goal at this stage is to get translations included in the Transifex pull request.
To update translated strings, start by initiating a sync from Transifex. From the Transifex dashboard, navigate to Settings > Integrations > GitHub > Manage, and click the **Manual Sync** button at top right.
To download translated strings automatically, you'll need to:
1. Install the [Transifex CLI client](https://github.com/transifex/cli)
2. Generate a [Transifex API token](https://app.transifex.com/user/settings/api/)
Enter a threshold percentage of 1 (to ensure all translations are captured) and select the `develop` branch, then click **Sync**. This will initiate a pull request to GitHub to update any newly modified translation (`.po`) files.
Once you have the client set up, run the following command from the project root (e.g. `/opt/netbox/`):
!!! tip
The new PR should appear within a few minutes. If it does not, check that there are in fact new translations to be added.
This will download all portable (`.po`) translation files from Transifex, updating them locally as needed. (The `--force` argument instructs the client to disregard the timestamps of local translation files.)
Once the PR has been merged, the updated strings need to be compiled into new `.mo` files so they can be used by the application. Update the `develop` branch locally to pull in the changes from the Transifex PR, then run Django's [`compilemessages`](https://docs.djangoproject.com/en/stable/ref/django-admin/#django-admin-compilemessages) management command:
Once retrieved, the updated strings need to be compiled into new `.mo` files so they can be used by the application. Run Django's [`compilemessages`](https://docs.djangoproject.com/en/stable/ref/django-admin/#django-admin-compilemessages) management command to compile them:
```nohighlight
```no-highlight
./manage.py compilemessages
```
Once any new `.mo` files have been generated, they need to be committed and pushed back up to GitHub. (Again, this is typically done as part of publishing a new NetBox release.)
!!! tip
Run `git status` to check that both `*.mo` & `*.po` files have been updated as expected.
## Proposing New Languages
If you'd like to add support for a new language to NetBox, the first step is to [submit a GitHub issue](https://github.com/netbox-community/netbox/issues/new?assignees=&labels=type%3A+translation&projects=&template=translation.yaml) to capture the proposal. While we'd like to add as many languages as possible, we do need to limit the rate at which new languages are added. New languages will be selected according to community interest and the number of volunteers who sign up as translators.
The `users.UserConfig` model holds individual preferences for each user in the form of JSON data. This page serves as a manifest of all recognized user preferences in NetBox.
For end‑user guidance on resetting saved table layouts, see [Features > User Preferences](../features/user-preferences.md#clearing-table-preferences).
* Synchronization of [remote data sources](../integrations/synchronized-data.md)
* Housekeeping tasks
Additionally, NetBox plugins can enqueue their own background tasks. This is accomplished using the [Job model](../models/core/job.md). Background tasks are executed by the `rqworker` process(es).
@@ -8,6 +8,12 @@ When a request is made, a UUID is generated and attached to any change records r
Change records are exposed in the API via the read-only endpoint `/api/extras/object-changes/`. They may also be exported via the web UI in CSV format.
## User Messages
!!! info "This feature was introduced in NetBox v4.4."
When creating, modifying, or deleting an object in NetBox, a user has the option of recording an arbitrary message that will appear in the change record. This can be helpful to capture additional context, such as the reason for the change.
## Correlating Changes by Request
Every request made to NetBox is assigned a random unique ID that can be used to correlate change records. For example, if you change the status of three sites using the UI's bulk edit feature, you will see three new change records (one for each site) all referencing the same request ID. This shows that all three changes were made as part of the same request.
While NetBox strives to meet the needs of every network, the needs of users to cater to their own unique environments cannot be ignored. NetBox was built with this in mind, and can be customized in many ways to better suit your particular needs.
For end‑user personalization topics (bookmarks, table preferences, language, CSV delimiter, and more), see [Features > User Preferences](../features/user-preferences.md).
## Tags
Most objects in NetBox can be assigned user-created tags to aid with organization and filtering. Tag values are completely arbitrary: They may be used to store data in key-value pairs, or they may be employed simply as labels against which objects can be filtered. Each tag can also be assigned a color for quicker differentiation in the user interface.
@@ -18,10 +20,6 @@ The `tag` filter can be specified multiple times to match only objects which hav
GET /api/dcim/devices/?tag=monitored&tag=deprecated
```
## Bookmarks
Users can bookmark their most commonly visited objects for convenient access. Bookmarks are listed under a user's profile, and can be displayed with custom filtering and ordering on the user's personal dashboard.
## Custom Fields
While NetBox provides a rather extensive data model out of the box, the need may arise to store certain additional data associated with NetBox objects. For example, you might need to record the invoice ID alongside an installed device, or record an approving authority when creating a new IP prefix. NetBox administrators can create custom fields on built-in objects to meet these needs.
@@ -38,7 +36,7 @@ Custom links allow you to conveniently reference external resources related to N
http://server.local/vms/?name={{ object.name }}
```
Now, when viewing a virtual machine in NetBox, a user will see a handy button with the chosen title and link (complete with the name of the VM being viewed). Both the text and URL of custom links can be templatized in this manner, and custom links can be grouped together into dropdowns for more efficient display.
Now, when viewing a virtual machine in NetBox, a user will see a handy button with the chosen title and link (complete with the name of the VM being viewed). Both the text and URL of custom links can be templatized in this manner, and custom links can be grouped together into dropdowns for a more efficient display.
To learn more about this feature, check out the [custom link documentation](../customization/custom-links.md).
For example, suppose you want to automatically configure a monitoring system to start monitoring a device when its operational status is changed to active, and remove it from monitoring for any other status. You can create a webhook in NetBox for the device model and craft its content and destination URL to effect the desired change on the receiving system. You can then associate an event rule with this webhook and the webhook will be sent automatically by NetBox whenever the configured constraints are met.
@@ -46,7 +46,7 @@ Regions will always be listed alphabetically by name within each parent, and the
Like regions, site groups can be arranged in a recursive hierarchy for grouping sites. However, whereas regions are intended for geographic organization, site groups may be used for functional grouping. For example, you might classify sites as corporate, branch, or customer sites in addition to where they are physically located.
The use of both regions and site groups affords to independent but complementary dimensions across which sites can be organized.
The use of both regions and site groups affords two independent but complementary dimensions across which sites can be organized.
## Sites
@@ -56,6 +56,10 @@ A site typically represents a building within a region and/or site group. Each s
A location can be any logical subdivision within a building, such as a floor or room. Like regions and site groups, locations can be nested into a self-recursive hierarchy for maximum flexibility. And like sites, each location has an operational status assigned to it.
## Rack Types
A rack type represents a unique specification of a rack which exists in the real world. Each rack type can be setup with weight, height, and unit ordering. New racks of this type can then be created in NetBox, and any associated specifications will be automatically replicated from the device type.
## Racks
Finally, NetBox models each equipment rack as a discrete object within a site and location. These are physical objects into which devices are installed. Each rack can be assigned an operational status, type, facility ID, and other attributes related to inventory tracking. Each rack also must define a height (in rack units) and width, and may optionally specify its physical dimensions.
@@ -62,8 +62,8 @@ VRF modeling in NetBox very closely follows what you find in real-world network
An often overlooked component of IPAM, NetBox also tracks autonomous system (AS) numbers and their assignment to sites. Both 16- and 32-bit AS numbers are supported, and like aggregates each ASN is assigned to an authoritative RIR.
## Service Mapping
## Application Service Mapping
NetBox models network applications as discrete service objects associated with devices and/or virtual machines, and optionally with specific IP addresses attached to those parent objects. These can be used to catalog the applications running on your network for reference by other objects or integrated tools.
To model services in NetBox, begin by creating a service template defining the name, protocol, and port number(s) on which the service listens. This template can then be easily instantiated to "attach" new services to a device or virtual machine. It's also possible to create new services by hand, without a template, however this approach can be tedious.
To model application services in NetBox, begin by creating an application service template defining the name, protocol, and port number(s) on which the service listens. This template can then be easily instantiated to "attach" new services to a device or virtual machine. It's also possible to create new application services by hand, without a template, however this approach can be tedious.
NetBox includes a system for generating user notifications, which can be marked as read or deleted by individual users. There are two built-in mechanisms for generating a notification:
* A user can subscribe to an object. When that object is modified, a notification is created to inform the user of the change.
* An [event rule](./event-rules.md) can be defined to automatically generate a notification for one or more users in response to specific system events.
Additionally, NetBox plugins can generate notifications for their own purposes.
@@ -13,6 +13,9 @@ To enable remote data synchronization, the NetBox administrator first designates
!!! info
Data backends which connect to external sources typically require the installation of one or more supporting Python libraries. The Git backend requires the [`dulwich`](https://www.dulwich.io/) package, and the S3 backend requires the [`boto3`](https://boto3.amazonaws.com/v1/documentation/api/latest/index.html) package. These must be installed within NetBox's environment to enable these backends.
!!! info
If you are configuring Git and have `HTTP_PROXIES` configured to use the SOCKS protocol, you will also need to install the [`python_socks`](https://pypi.org/project/python-socks/) Python library.
Each type of remote source has its own configuration parameters. For instance, a git source will ask the user to specify a branch and authentication credentials. Once the source has been created, a synchronization job is run to automatically replicate remote files in the local database.
The following NetBox models can be associated with replicated data files:
NetBox stores per‑user options that control aspects of the web interface and data display. Preferences persist across sessions and can be managed under **User → Preferences**.
## Table configurations
When a list view is configured using **Configure**, NetBox records the selected columns and ordering as per‑user table preferences for that table. These preferences are applied automatically on subsequent visits.
### Clearing table preferences
Saved table preferences may need to be reset, for example, if a table fails to render or after an upgrade that changes available columns.
To clear saved preferences for one or more tables:
1. Click the username in the top‑right corner.
2. Select **Preferences** from the dropdown.
3. Scroll to the **Table Configurations** section.
4. Select the tables to reset.
5. Click **Submit** to clear the selected preferences.
After clearing preferences, reopen the list view and use **Configure** to set the desired columns and ordering.
!!! note
Per‑user table preferences are distinct from **Table Configs**, which are named, reusable configurations managed under *Customization → Table Configs*. Clearing preferences does not delete any Table Configs. See [Table Configs](../models/extras/tableconfig.md) for details.
## Other preferences
### Language
Selects the user interface language from installed translations (subject to system configuration).
### Page length
Sets the default number of rows displayed on paginated tables.
### Paginator placement
Controls where pagination controls are rendered relative to a table.
### Striped table rows
Toggles alternating row backgrounds on tables.
### Data format (raw views)
Sets the default format (JSON or YAML) when rendering raw data blocks.
### CSV delimiter
Overrides the delimiter used when exporting CSV data.
## Bookmarks
Users can bookmark frequently visited objects for convenient access. Bookmarks appear under the user menu and can be displayed on the personal dashboard using the bookmarks' widget. See [Bookmark](../models/extras/bookmark.md) for model details.
## Notifications and subscriptions
Users may subscribe to objects to receive notifications when changes occur. Notifications are listed under the user menu and can be marked as read or deleted. See [Features > Notifications](notifications.md) and the data‑model references for [Subscription](../models/extras/subscription.md) and [Notification](../models/extras/notification.md).
## Admin defaults
Administrators can define defaults for new users via [`DEFAULT_USER_PREFERENCES`](../configuration/default-values.md#default_user_preferences). Users may override these values under their own preferences.
## See also
- [Development > User Preferences](../development/user-preferences.md) (manifest of recognized preference keys)
@@ -17,7 +17,7 @@ Dedicate some time to take stock of your own sources of truth for your infrastru
* **Multiple conflicting sources** for a given domain. For example, there may be multiple versions of a spreadsheet circulating, each of which asserts a conflicting set of data.
* **Sources with no domain defined.** You may encounter that different teams within your organization use different tools for the same purpose, with no normal definition of when either should be used.
* **Inaccessible data formatting.** Some tools are better suited for programmatic usage than others. For example, spreadsheets are generally very easy to parse and export, however free-form notes on wiki or similar application are much more difficult to consume.
* **Inaccessible data formatting.** Some tools are better suited for programmatic usage than others. For example, spreadsheets are generally very easy to parse and export; however, free-form notes on wiki or similar application are much more difficult to consume.
* **There is no source of truth.** Sometimes you'll find that a source of truth simply doesn't exist for a domain. For example, when assigning IP addresses, operators may be just using any (presumed) available IP from a subnet without ever recording its usage.
See if you can identify each domain of infrastructure data for your organization, and the source of truth for each. Once you have these compiled, you'll need to determine what belongs in NetBox.
@@ -8,7 +9,7 @@ NetBox is the leading solution for modeling and documenting modern networks. By
## :material-server-network: Built for Networks
Unlike general-purpose CMDBs, NetBox has curated a data model which caters specifically to the needs of network engineers and operators. It delivers a wide assortment of object types carefully crafted to best serve the needs of infrastructure design and documentation. These cover all facets of network technology, from IP address managements to cabling to overlays and more:
Unlike general-purpose configuration management databases (CMDBs), NetBox has curated a data model which caters specifically to the needs of network engineers and operators. It delivers a wide assortment of object types carefully crafted to best serve the needs of infrastructure design and documentation. These cover all facets of network technology, from IP address managements to cabling to overlays and more:
This section entails the installation and configuration of a local PostgreSQL database. If you already have a PostgreSQL database service in place, skip to [the next section](2-redis.md).
!!! warning "PostgreSQL 12 or later required"
NetBox requires PostgreSQL 12 or later. Please note that MySQL and other relational databases are **not** supported.
!!! warning "PostgreSQL 14 or later required"
NetBox requires PostgreSQL 14 or later. Please note that MySQL and other relational databases are **not** supported.
## Installation
=== "Ubuntu"
```no-highlight
sudo apt update
sudo apt install -y postgresql
```
```no-highlight
sudo apt update
sudo apt install -y postgresql
```
=== "CentOS"
```no-highlight
sudo yum install -y postgresql-server
sudo postgresql-setup --initdb
```
CentOS configures ident host-based authentication for PostgreSQL by default. Because NetBox will need to authenticate using a username and password, modify `/var/lib/pgsql/data/pg_hba.conf` to support MD5 authentication by changing `ident` to `md5` for the lines below:
```no-highlight
host all all 127.0.0.1/32 md5
host all all ::1/128 md5
```
Once PostgreSQL has been installed, start the service and enable it to run at boot:
```no-highlight
sudo systemctl enable --now postgresql
```
Before continuing, verify that you have installed PostgreSQL 12 or later:
Before continuing, verify that you have installed PostgreSQL 14 or later:
```no-highlight
psql -V
@@ -62,6 +40,9 @@ GRANT CREATE ON SCHEMA public TO netbox;
!!! danger "Use a strong password"
**Do not use the password from the example.** Choose a strong, random password to ensure secure database authentication for your NetBox installation.
!!! danger "Use UTF8 encoding"
Make sure that your database uses `UTF8` encoding (the default for new installations). Especially do not use `SQL_ASCII` encoding, as it can lead to unpredictable and unrecoverable errors. Enter `\l` to check your encoding.
Once complete, enter `\q` to exit the PostgreSQL shell.
[Redis](https://redis.io/) is an in-memory key-value store which NetBox employs for caching and queuing. This section entails the installation and configuration of a local Redis instance. If you already have a Redis service in place, skip to [the next section](3-netbox.md).
=== "Ubuntu"
```no-highlight
sudo apt install -y redis-server
```
=== "CentOS"
```no-highlight
sudo yum install -y redis
sudo systemctl enable --now redis
```
```no-highlight
sudo apt install -y redis-server
```
Before continuing, verify that your installed version of Redis is at least v4.0:
Before continuing, check that your installed Python version is at least 3.10:
Before continuing, check that your installed Python version is at least 3.12:
```no-highlight
python3 -V
@@ -29,7 +23,7 @@ python3 -V
## Download NetBox
This documentation provides two options for installing NetBox: from a downloadable archive, or from the git repository. Installing from a package (option A below) requires manually fetching and extracting the archive for every future update, whereas installation via git (option B) allows for seamless upgrades by re-pulling the `master` branch.
This documentation provides two options for installing NetBox: from a downloadable archive, or from the git repository. Installing from a package (option A below) requires manually fetching and extracting the archive for every future update, whereas installation via git (option B) allows for seamless upgrades by checking out the latest release tag.
### Option A: Download a Release Archive
@@ -55,28 +49,17 @@ cd /opt/netbox/
If `git` is not already installed, install it:
=== "Ubuntu"
```no-highlight
sudo apt install -y git
```
=== "CentOS"
```no-highlight
sudo yum install -y git
```
Next, clone the **master** branch of the NetBox GitHub repository into the current directory. (This branch always holds the current stable release.)
The `git clone` command above utilizes a "shallow clone" to retrieve only the most recent commit. If you need to download the entire history, omit the `--depth 1` argument.
Next, clone the git repository:
The `git clone` command should generate output similar to the following:
Installation via git also allows you to easily try out different versions of NetBox. To check out a [specific NetBox release](https://github.com/netbox-community/netbox/releases), use the `git checkout` command with the desired release tag. For example, `git checkout v3.0.8`.
Finally, check out the tag for the desired release. You can find these on our [releases page](https://github.com/netbox-community/netbox/releases). Replace `vX.Y.Z` with your selected release tag below.
```
sudo git checkout vX.Y.Z
```
Using this installation method enables easy upgrades in the future by simply checking out the latest release tag.
## Create the NetBox System User
Create a system user account named `netbox`. We'll configure the WSGI and HTTP services to run under this account. We'll also assign this user ownership of the media directory. This ensures that NetBox will be able to save uploaded files.
Open `configuration.py` with your preferred editor to begin configuring NetBox. NetBox offers [many configuration parameters](../configuration/index.md), but only the following four are required for new installations:
* `ALLOWED_HOSTS`
* `DATABASE`
* `DATABASES` (or `DATABASE`)
* `REDIS`
* `SECRET_KEY`
### ALLOWED_HOSTS
This is a list of the valid hostnames and IP addresses by which this server can be reached. You must specify at least one name or IP address. (Note that this does not restrict the locations from which NetBox may be accessed: It is merely for [HTTP host header validation](https://docs.djangoproject.com/en/3.0/topics/security/#host-headers-virtual-hosting).)
This is a list of the valid hostnames and IP addresses by which this server can be reached. You must specify at least one name or IP address. (Note that this does not restrict the locations from which NetBox may be accessed: It is merely for [HTTP host header validation](https://docs.djangoproject.com/en/stable/topics/security/#host-headers-virtual-hosting).)
@@ -144,18 +120,39 @@ If you are not yet sure what the domain name and/or IP address of the NetBox ins
ALLOWED_HOSTS = ['*']
```
### DATABASE
### API_TOKEN_PEPPERS
This parameter holds the database configuration details. You must define the username and password used when you configured PostgreSQL. If the service is running on a remote host, update the `HOST` and `PORT` parameters accordingly. See the [configuration documentation](../configuration/required-parameters.md#database) for more detail on individual parameters.
Define at least one random cryptographic pepper, identified by a numeric ID starting at 1. This will be used to generate SHA256 checksums for API tokens.
As with [`SECRET_KEY`](#secret_key) below, you can use the `generate_secret_key.py` script to generate a random pepper:
```no-highlight
python3 ../generate_secret_key.py
```
### DATABASES
This parameter holds the PostgreSQL database configuration details. The default database must be defined; additional databases may be defined as needed e.g. by plugins.
A username and password must be defined for the default database. If the service is running on a remote host, update the `HOST` and `PORT` parameters accordingly. See the [configuration documentation](../configuration/required-parameters.md#databases) for more detail on individual parameters.
'PORT': '', # Database port (leave blank for default)
'CONN_MAX_AGE': 300, # Max database connection age (seconds)
}
}
```
@@ -205,7 +202,7 @@ All Python packages required by NetBox are listed in `requirements.txt` and will
### Remote File Storage
By default, NetBox will use the local filesystem to store uploaded files. To use a remote filesystem, install the [`django-storages`](https://django-storages.readthedocs.io/en/stable/) library and configure your [desired storage backend](../configuration/system.md#storage_backend) in `configuration.py`.
By default, NetBox will use the local filesystem to store uploaded files. To use a remote filesystem, install the [`django-storages`](https://django-storages.readthedocs.io/en/stable/) library and configure your [desired storage backend](../configuration/system.md#storages) in `configuration.py`.
```no-highlight
sudo sh -c "echo 'django-storages' >> /opt/netbox/local_requirements.txt"
@@ -244,7 +241,7 @@ Once NetBox has been configured, we're ready to proceed with the actual installa
* Create a Python virtual environment
* Installs all required Python packages
* Run database schema migrations
* Run database schema migrations (skip with `--readonly`)
* Builds the documentation locally (for offline use)
* Aggregate static resource files on disk
@@ -255,15 +252,18 @@ Once NetBox has been configured, we're ready to proceed with the actual installa
sudo /opt/netbox/upgrade.sh
```
Note that **Python 3.10 or later is required** for NetBox v4.0 and later releases. If the default Python installation on your server is set to a lesser version, pass the path to the supported installation as an environment variable named `PYTHON`. (Note that the environment variable must be passed _after_ the `sudo` command.)
Note that **Python 3.12 or later is required** for NetBox v4.5 and later releases. If the default Python installation on your server is set to a lesser version, pass the path to the supported installation as an environment variable named `PYTHON`. (Note that the environment variable must be passed _after_ the `sudo` command.)
Upon completion, the upgrade script may warn that no existing virtual environment was detected. As this is a new installation, this warning can be safely ignored.
!!! note
To run the script on a node connected to a database in read-only mode, include the `--readonly` parameter. This will skip the application of any database migrations.
## Create a Super User
NetBox does not come with any predefined user accounts. You'll need to create a super user (administrative account) to be able to log into NetBox. First, enter the Python virtual environment created by the upgrade script:
@@ -281,18 +281,6 @@ cd /opt/netbox/netbox
python3 manage.py createsuperuser
```
## Schedule the Housekeeping Task
NetBox includes a `housekeeping` management command that handles some recurring cleanup tasks, such as clearing out old sessions and expired change records. Although this command may be run manually, it is recommended to configure a scheduled job using the system's `cron` daemon or a similar utility.
A shell script which invokes this command is included at `contrib/netbox-housekeeping.sh`. It can be copied to or linked from your system's daily cron task directory, or included within the crontab directly. (If installing NetBox into a nonstandard path, be sure to update the system paths within this script first.)
See the [housekeeping documentation](../administration/housekeeping.md) for further details.
## Test the Application
At this point, we should be able to run NetBox's development server for testing. We can check by starting a development instance locally.
@@ -319,13 +307,6 @@ Quit the server with CONTROL-C.
Next, connect to the name or IP of the server (as defined in `ALLOWED_HOSTS`) on port 8000; for example, <http://127.0.0.1:8000/>. You should be greeted with the NetBox home page. Try logging in using the username and password specified when creating a superuser.
!!! note
By default RHEL based distros will likely block your testing attempts with firewalld. The development server port can be opened with `firewall-cmd` (add `--permanent` if you want the rule to survive server restarts):
```no-highlight
firewall-cmd --zone=public --add-port=8000/tcp
```
!!! danger "Not for production use"
The development server is for development and testing purposes only. It is neither performant nor secure enough for production use. **Do not use it in production.**
@@ -60,6 +60,3 @@ You should see output similar to the following:
If the NetBox service fails to start, issue the command `journalctl -eu netbox` to check for log messages that may indicate the problem.
Once you've verified that the WSGI workers are up and running, move on to HTTP server setup.
!!! note
There is a bug in the current stable release of gunicorn (v21.2.0) where automatic restarts of the worker processes can result in 502 errors under heavy load. (See [gunicorn bug #3038](https://github.com/benoitc/gunicorn/issues/3038) for more detail.) Users who encounter this issue may opt to downgrade to an earlier, unaffected release of gunicorn (`pip install gunicorn==20.1.0`). Note, however, that this earlier release does not officially support Python 3.11.
While the provided configuration should suffice for most initial installations, you may wish to edit this file to change the bound IP address and/or port number, or to make performance-related adjustments. See [the uWSGI documentation](https://uwsgi-docs-additions.readthedocs.io/en/latest/Options.html) for the available configuration parameters and take a minute to review the [Things to know](https://uwsgi-docs.readthedocs.io/en/latest/ThingsToKnow.html) page. Django also provides [additional documentation](https://docs.djangoproject.com/en/5.0/howto/deployment/wsgi/uwsgi/) on configuring uWSGI with a Django app.
While the provided configuration should suffice for most initial installations, you may wish to edit this file to change the bound IP address and/or port number, or to make performance-related adjustments. See [the uWSGI documentation](https://uwsgi-docs-additions.readthedocs.io/en/latest/Options.html) for the available configuration parameters and take a minute to review the [Things to know](https://uwsgi-docs.readthedocs.io/en/latest/ThingsToKnow.html) page. Django also provides [additional documentation](https://docs.djangoproject.com/en/stable/howto/deployment/wsgi/uwsgi/) on configuring uWSGI with a Django app.
* `is_active` - All users must be mapped to at least this group to enable authentication. Without this, users cannot log in.
* `is_staff` - Users mapped to this group are enabled for access to the administration tools; this is the equivalent of checking the "staff status" box on a manually created user. This doesn't grant any specific permissions.
* `is_superuser` - Users mapped to this group will be granted superuser status. Superusers are implicitly granted all permissions.
The instructions below are for installing NetBox as a standalone, self-hosted application. For a Cloud-delivered solution, check out [NetBox Cloud](https://netboxlabs.com/netbox-cloud/) by NetBox Labs.
<div class="grid cards" markdown>
The installation instructions provided here have been tested to work on Ubuntu 22.04 and CentOS 8.3. The particular commands needed to install dependencies on other distributions may vary significantly. Unfortunately, this is outside the control of the NetBox maintainers. Please consult your distribution's documentation for assistance with any errors.
- :material-clock-fast:{ .lg .middle } __Eager to Get Started?__
Check out the [NetBox Cloud Free Plan](https://netboxlabs.com/free-netbox-cloud/)! Skip the installation process and grab your own NetBox Cloud instance, preconfigured and ready to go in minutes. Completely free!
The installation instructions provided here have been tested to work on Ubuntu 22.04. The particular commands needed to install dependencies on other distributions may vary significantly. Unfortunately, this is outside the control of the NetBox maintainers. Please consult your distribution's documentation for assistance with any errors.
The following sections detail how to set up a new instance of NetBox:
@@ -20,8 +27,8 @@ The following sections detail how to set up a new instance of NetBox:
| Dependency | Supported Versions |
|------------|--------------------|
| Python | 3.10, 3.11, 3.12 |
| PostgreSQL | 12+ |
| Python | 3.12, 3.13, 3.14 |
| PostgreSQL | 14+ |
| Redis | 4.0+ |
Below is a simplified overview of the NetBox application stack for reference:
As with the initial installation, you can upgrade NetBox by either downloading the latest release package or by cloning the `master` branch of the git repository.
As with the initial installation, you can upgrade NetBox by either downloading the latest release package or by checking out the latest production release from the git repository.
!!! warning
Use the same method as you used to install NetBox originally
Use the same method as you used to install NetBox originally.
If you are not sure how NetBox was installed originally, check with this command:
@@ -36,10 +55,7 @@ If you are not sure how NetBox was installed originally, check with this command
ls -ld /opt/netbox /opt/netbox/.git
```
If NetBox was installed from a release package, then `/opt/netbox` will be a
symlink pointing to the current version, and `/opt/netbox/.git` will not
exist. If it was installed from git, then `/opt/netbox` and
`/opt/netbox/.git` will both exist as normal directories.
If NetBox was installed from a release package, then `/opt/netbox` will be a symlink pointing to the current version, and `/opt/netbox/.git` will not exist. If it was installed from git, then `/opt/netbox` and `/opt/netbox/.git` will both exist as normal directories.
### Option A: Download a Release
@@ -84,20 +100,24 @@ If you followed the original installation guide to set up gunicorn, be sure to c
This guide assumes that NetBox is installed at `/opt/netbox`. Pull down the most recent iteration of the master branch:
This guide assumes that NetBox is installed in `/opt/netbox`. First, determine the latest release either by visiting our [releases page](https://github.com/netbox-community/netbox/releases) or by running the following command:
If you need to upgrade to an older version rather than the current stable release, you can check out any valid [git tag](https://github.com/netbox-community/netbox/tags), each of which represents a release. For example, to checkout the code for NetBox v2.11.11, do:
Check out the desired release by specifying its tag. For example:
sudo git checkout v2.11.11
```
cd /opt/netbox && \
sudo git fetch --tags && \
sudo git checkout v4.2.7
```
## 4. Run the Upgrade Script
@@ -111,9 +131,12 @@ sudo ./upgrade.sh
If the default version of Python is not at least 3.10, you'll need to pass the path to a supported Python version as an environment variable when calling the upgrade script. For example:
```no-highlight
sudo PYTHON=/usr/bin/python3.10 ./upgrade.sh
sudo PYTHON=/usr/bin/python3.12 ./upgrade.sh
```
!!! note
To run the script on a node connected to a database in read-only mode, include the `--readonly` parameter. This will skip the application of any database migrations.
This script performs the following actions:
* Destroys and rebuilds the Python virtual environment
@@ -140,13 +163,3 @@ Finally, restart the gunicorn and RQ services:
```no-highlight
sudo systemctl restart netbox netbox-rq
```
## 6. Verify Housekeeping Scheduling
If upgrading from a release prior to NetBox v3.0, check that a cron task (or similar scheduled process) has been configured to run NetBox's nightly housekeeping command. A shell script which invokes this command is included at `contrib/netbox-housekeeping.sh`. It can be linked from your system's daily cron task directory, or included within the crontab directly. (If NetBox has been installed in a nonstandard path, be sure to update the system paths within this script first.)
NetBox provides a read-only [GraphQL](https://graphql.org/) API to complement its REST API. This API is powered by [Strawberry Django](https://strawberry-graphql.github.io/strawberry-django/).
NetBox provides a read-only [GraphQL](https://graphql.org/) API to complement its REST API. This API is powered by [Strawberry Django](https://strawberry.rocks/).
The response will include the requested data formatted as JSON:
@@ -47,23 +47,52 @@ NetBox provides both a singular and plural query field for each object type:
For example, query `device(id:123)` to fetch a specific device (identified by its unique ID), and query `device_list` (with an optional set of filters) to fetch all devices.
For more detail on constructing GraphQL queries, see the [GraphQL queries documentation](https://graphql.org/learn/queries/). For filtering and lookup syntax, please refer to the [Strawberry Django documentation](https://strawberry-graphql.github.io/strawberry-django/guide/filters/).
For more detail on constructing GraphQL queries, see the [GraphQL queries documentation](https://graphql.org/learn/queries/). For filtering and lookup syntax, please refer to the [Strawberry Django documentation](https://strawberry.rocks/docs/django/guide/filters).
## Filtering
The GraphQL API employs the same filtering logic as the UI and REST API. Filters can be specified as key-value pairs within parentheses immediately following the query name. For example, the following will return only sites within the North Carolina region with a status of active:
!!! note "Changed in NetBox v4.3"
The filtering syntax fo the GraphQL API has changed substantially in NetBox v4.3.
Filters can be specified as key-value pairs within parentheses immediately following the query name. For example, the following will return only active sites:
In addition, filtering can be done on list of related objects as shown in the following query:
Filters can be combined with logical operators, such as `OR` and `NOT`. For example, the following will return every site that is planned _or_ assigned to a tenant named Foo:
```
{
query {
site_list(
filters: {
status: STATUS_PLANNED,
OR: {
tenant: {
name: {
exact: "Foo"
}
}
}
}
) {
name
}
}
```
Filtering can also be applied to related objects. For example, the following query will return only enabled interfaces for each device:
```
query {
device_list {
id
name
@@ -98,9 +127,21 @@ Certain queries can return multiple types of objects, for example cable terminat
}
}
}
```
The field "class_type" is an easy way to distinguish what type of object it is when viewing the returned data, or when filtering. It contains the class name, for example "CircuitTermination" or "ConsoleServerPort".
## Pagination
Queries can be paginated by specifying pagination in the query and supplying an offset and optionaly a limit in the query. If no limit is given, a default of 100 is used. Queries are not paginated unless requested in the query. An example paginated query is shown below:
```
The field "class_type" is an easy way to distinguish what type of object it is when viewing the returned data, or when filtering. It contains the class name, for example "CircuitTermination" or "ConsoleServerPort".
If not needed, the GraphQL API can be disabled by setting the [`GRAPHQL_ENABLED`](../configuration/miscellaneous.md#graphql_enabled) configuration parameter to False and restarting NetBox.
If not needed, the GraphQL API can be disabled by setting the [`GRAPHQL_ENABLED`](../configuration/graphql-api.md#graphql_enabled) configuration parameter to False and restarting NetBox.
REST stands for [representational state transfer](https://en.wikipedia.org/wiki/Representational_state_transfer). It's a particular type of API which employs HTTP requests and [JavaScript Object Notation (JSON)](https://www.json.org/) to facilitate create, retrieve, update, and delete (CRUD) operations on objects within an application. Each type of operation is associated with a particular HTTP verb:
REST stands for [representational state transfer](https://en.wikipedia.org/wiki/REST). It's a particular type of API which employs HTTP requests and [JavaScript Object Notation (JSON)](https://www.json.org/) to facilitate create, retrieve, update, and delete (CRUD) operations on objects within an application. Each type of operation is associated with a particular HTTP verb:
*`GET`: Retrieve an object or list of objects
*`POST`: Create an object
@@ -80,7 +80,7 @@ Likewise, the site, rack, and device objects are located under the "DCIM" applic
The full hierarchy of available endpoints can be viewed by navigating to the API root in a web browser.
Each model generally has two views associated with it: a list view and a detail view. The list view is used to retrieve a list of multiple objects and to create new objects. The detail view is used to retrieve, update, or delete an single existing object. All objects are referenced by their numeric primary key (`id`).
Each model generally has two views associated with it: a list view and a detail view. The list view is used to retrieve a list of multiple objects and to create new objects. The detail view is used to retrieve, update, or delete a single existing object. All objects are referenced by their numeric primary key (`id`).
* `/api/dcim/devices/` - List existing devices or create a new device
* `/api/dcim/devices/123/` - Retrieve, update, or delete the device with ID 123
@@ -101,7 +101,7 @@ See the [filtering documentation](../reference/filtering.md) for more details on
## Serialization
The REST API employs two types of serializers to represent model data: base serializers and nested serializers. The base serializer is used to present the complete view of a model. This includes all database table fields which comprise the model, and may include additional metadata. A base serializer includes relationships to parent objects, but **does not** include child objects. For example, the `VLANSerializer` includes a nested representation its parent VLANGroup (if any), but does not include any assigned Prefixes.
The REST API generally represents objects in one of two ways: complete or brief. The base serializer is used to present the complete view of an object. This includes all database table fields which comprise the model, and may include additional metadata. A base serializer includes relationships to parent objects, but **does not** include child objects. For example, the `VLANSerializer` includes a nested representation its parent VLANGroup (if any), but does not include any assigned Prefixes. Serializers employ a minimal "brief" representation of related objects, which includes only the attributes prudent for identifying the object.
```json
{
@@ -139,7 +139,7 @@ The REST API employs two types of serializers to represent model data: base seri
### Related Objects
Related objects (e.g. `ForeignKey` fields) are represented using nested serializers. A nested serializer provides a minimal representation of an object, including only its direct URL and enough information to display the object to a user. When performing write API actions (`POST`, `PUT`, and `PATCH`), related objects may be specified by either numeric ID (primary key), or by a set of attributes sufficiently unique to return the desired object.
Related objects (e.g. `ForeignKey` fields) are included using nested brief representations. This is a minimal representation of an object, including only its direct URL and enough information to display the object to a user. When performing write API actions (`POST`, `PUT`, and `PATCH`), related objects may be specified by either numeric ID (primary key), or by a set of attributes sufficiently unique to return the desired object.
For example, when creating a new device, its rack can be specified by NetBox ID (PK):
@@ -151,7 +151,7 @@ For example, when creating a new device, its rack can be specified by NetBox ID
}
```
Or by a set of nested attributes which uniquely identify the rack:
Or by a set of attributes which uniquely identify the rack:
```json
{
@@ -217,26 +217,34 @@ If we wanted to assign this IP address to a virtual machine interface instead, w
### Brief Format
Most API endpoints support an optional "brief" format, which returns only a minimal representation of each object in the response. This is useful when you need only a list of available objects without any related data, such as when populating a drop-down list in a form. As an example, the default (complete) format of an IP address looks like this:
Most API endpoints support an optional "brief" format, which returns only a minimal representation of each object in the response. This is useful when you need only a list of available objects without any related data, such as when populating a drop-down list in a form. As an example, the default (complete) format of a prefix looks like this:
The bulk deletion of objects is an all-or-none operation, meaning that if NetBox fails to delete any of the specified objects (e.g. due a dependency by a related object), the entire operation will be aborted and none of the objects will be deleted.
## Changelog Messages
!!! info "This feature was introduced in NetBox v4.4."
Most objects in NetBox support [change logging](../features/change-logging.md), which generates a detailed record each time an object is created, modified, or deleted. Beginning in NetBox v4.4, users can attach a message to the change record as well. This is accomplished via the REST API by including a `changelog_message` field in the object representation.
For example, the following API request will create a new site and record a message in the resulting changelog entry:
```no-highlight
curl -s -X POST \
-H "Authorization: Token $TOKEN" \
-H "Content-Type: application/json" \
http://netbox/api/dcim/sites/ \
--data '{
"name": "Site A",
"slug": "site-a",
"changelog_message": "Adding a site for ticket #4137"
}'
```
This approach works when creating, modifying, or deleting objects, either individually or in bulk.
## Uploading Files
As JSON does not support the inclusion of binary data, files cannot be uploaded using JSON-formatted API requests. Instead, we can use form data encoding to attach a local file.
For example, we can upload an image attachment using the `curl` command shown below. Note that the `@` signifies a local file on disk to be uploaded.
```no-highlight
curl -X POST \
-H "Authorization: Token $TOKEN" \
-H "Accept: application/json; indent=4" \
-F "object_type=dcim.site" \
-F "object_id=2" \
-F "name=attachment1.png" \
-F "image=@local_file.png" \
http://netbox/api/extras/image-attachments/
```
## Authentication
The NetBox REST API primarily employs token-based authentication. For convenience, cookie-based authentication can also be used when navigating the browsable API.
### Tokens
A token is a unique identifier mapped to a NetBox user account. Each user may have one or more tokens which he or she can use for authentication when making REST API requests. To create a token, navigate to the API tokens page under your user profile.
A token is a secret, unique identifier mapped to a NetBox user account. Each user may have one or more tokens which he or she can use for authentication when making REST API requests. To create a token, navigate to the API tokens page under your user profile. When creating a token, NetBox will automatically populate a randomly-generated token value.
!!! note "Tokens cannot be retrieved once created"
Once a token has been created, its plaintext value cannot be retrieved. For this reason, you must take care to securely record the token locally immediately upon its creation. If a token plaintext is lost, it cannot be recovered: A new token must be created.
By default, all users can create and manage their own REST API tokens under the user control panel in the UI or via the REST API. This ability can be disabled by overriding the [`DEFAULT_PERMISSIONS`](../configuration/security.md#default_permissions) configuration parameter.
Each token contains a 160-bit key represented as 40 hexadecimal characters. When creating a token, you'll typically leave the key field blank so that a random key will be automatically generated. However, NetBox allows you to specify a key in case you need to restore a previously deleted token to operation.
Additionally, a token can be set to expire at a specific time. This can be useful if an external client needs to be granted temporary access to NetBox.
!!! info "Restricting Token Retrieval"
The ability to retrieve the key value of a previously-created API token can be restricted by disabling the [`ALLOW_TOKEN_RETRIEVAL`](../configuration/security.md#allow_token_retrieval) configuration parameter.
#### v1 and v2 Tokens
### Restricting Write Operations
Beginning with NetBox v4.5, two versions of API token are supported, denoted as v1 and v2. Users are strongly encouraged to create only v2 tokens and to discontinue the use of v1 tokens. Support for v1 tokens will be removed in a future NetBox release.
v2 API tokens offer much stronger security. The token plaintext given at creation time is hashed together with a configured [cryptographic pepper](../configuration/required-parameters.md#api_token_peppers) to generate a unique checksum. This checksum is irreversible; the token plaintext is never stored on the server and thus cannot be retrieved even with database-level access.
#### Restricting Write Operations
By default, a token can be used to perform all actions via the API that a user would be permitted to do via the web UI. Deselecting the "write enabled" option will restrict API requests made with the token to read operations (e.g. GET) only.
@@ -602,10 +685,22 @@ It is possible to provision authentication tokens for other users via the REST A
### Authenticating to the API
An authentication token is attached to a request by setting the `Authorization` header to the string `Token` followed by a space and the user's token:
An authentication token is included with a request in its `Authorization` header. The format of the header value depends on the version of token in use. v2 tokens use the following form, concatenating the token's prefix (`nbt_`) and key with its plaintext value, separated by a period:
```
$ curl -H "Authorization: Token $TOKEN" \
Authorization: Bearer nbt_<key>.<token>
```
Legacy v1 tokens use the prefix `Token` rather than `Bearer`, and include only the token plaintext. (v1 tokens do not have a key.)
```
Authorization: Token <token>
```
Below is an example REST API request utilizing a v2 token.
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.