File: README.md
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.
NetBox's Role
NetBox functions as the source of truth for your network infrastructure. Its job is to define and validate the intended state of all network components and resources. NetBox does not interact with network nodes directly; rather, it makes this data available programmatically to purpose-built automation, monitoring, and assurance tools. This separation of duties enables the construction of a robust yet flexible automation system.
The diagram above illustrates the recommended deployment architecture for an automated network, leveraging NetBox as the central authority for network state. This approach allows your team to swap out individual tools to meet changing needs while retaining a predictable, modular workflow.
Why NetBox?
Comprehensive Data Model
Racks, devices, cables, IP addresses, VLANs, circuits, power, VPNs, and lots more: NetBox is built for networks. Its comprehensive and thoroughly inter-linked data model provides for natural and highly structured modeling of myriad network primitives that just isn't possible using general-purpose tools. And there's no need to waste time contemplating how to build out a database: Everything is ready to go upon installation.
Focused Development
NetBox strives to meet a singular goal: Provide the best available solution for making network infrastructure programmatically accessible. Unlike "all-in-one" tools which awkwardly bolt on half-baked features in an attempt to check every box, NetBox is committed to its core function. NetBox provides the best possible solution for modeling network infrastructure, and provides rich APIs for integrating with tools that excel in other areas of network automation.
Extensible and Customizable
No two networks are exactly the same. Users are empowered to extend NetBox's native data model with custom fields and tags to best suit their unique needs. You can even write your own plugins to introduce entirely new objects and functionality!
Flexible Permissions
NetBox includes a fully customizable permission system, which affords administrators incredible granularity when assigning roles to users and groups. Want to restrict certain users to working only with cabling and not be able to change IP addresses? Or maybe each team should have access only to a particular tenant? NetBox enables you to craft roles as you see fit.
Custom Validation & Protection Rules
The data you put into NetBox is crucial to network operations. In addition to its robust native validation rules, NetBox provides mechanisms for administrators to define their own custom validation rules for objects. Custom validation can be used both to ensure new or modified objects adhere to a set of rules, and to prevent the deletion of objects which don't meet certain criteria. (For example, you might want to prevent the deletion of a device with an "active" status.)
Device Configuration Rendering
NetBox can render user-created Jinja2 templates to generate device configurations from its own data. Configuration templates can be uploaded individually or pulled automatically from an external source, such as a git repository. Rendered configurations can be retrieved via the REST API for application directly to network devices via a provisioning tool such as Ansible or Salt.
Custom Scripts
Complex workflows, such as provisioning a new branch office, can be tedious to carry out via the user interface. NetBox allows you to write and upload custom scripts that can be run directly from the UI. Scripts prompt users for input and then automate the necessary tasks to greatly simplify otherwise burdensome processes.
Automated Events
Users can define event rules to automatically trigger a custom script or outbound webhook in response to a NetBox event. For example, you might want to automatically update a network monitoring service whenever a new device is added to NetBox, or update a DHCP server when an IP range is allocated.
Comprehensive Change Logging
NetBox automatically logs the creation, modification, and deletion of all managed objects, providing a thorough change history. Changes can be attributed to the executing user, and related changes are grouped automatically by request ID.
[!NOTE]
A complete list of NetBox's myriad features can be found in the introductory documentation.
Getting Started
- Just want to explore? Check out our public demo right now!
- The official documentation offers a comprehensive introduction.
- Check out our wiki for even more projects to get the most out of NetBox!
Plugins
NetBox's functionality can be extended through plugins, which add new models, views, and integrations on top of the core application. A few of the most popular plugins include:
- NetBox Branching โ Work with isolated, mergeable branches of your NetBox data
- NetBox Custom Objects โ Define entirely new object types directly in the UI
- NetBox DNS โ Manage DNS zones and records as an authoritative source of truth
- NetBox BGP โ Document and manage BGP sessions and routing policies
- Browse all plugins โ Discover the full catalog of available plugins
Get Involved
- Follow @NetBoxOfficial on Twitter!
- Join the conversation on the discussion forum and Slack!
- Already a power user? You can suggest a feature or report a bug on GitHub.
- Contributions from the community are encouraged and appreciated! Check out our contributing guide to get started.
Screenshots
File: docs/development/adding-models.md
Adding Models
1. Define the model class
Models within each app are stored in either models.py or within a submodule under the models/ directory. When creating a model, be sure to subclass the appropriate base model from netbox.models. This will typically be NetBoxModel or OrganizationalModel. Remember to add the model class to the __all__ listing for the module.
Each model should define, at a minimum:
- A
Metaclass 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 if necessary; a standard version of the method is defined in theNetBoxFeatureSetbase class, but you will need to provide your own (returning an instance's direct URL usingreverse()) if not subclassing that base class
2. Define field choices
If the model has one or more fields with static choices, define those choices in choices.py by subclassing utilities.choices.ChoiceSet.
3. Generate database migrations
Once your model definition is complete, generate database migrations by running manage.py makemigrations -n $NAME --no-header. Always specify a short unique name when generating migrations.
!!! info "Configuration Required"
Set DEVELOPER = True in your NetBox configuration to enable the creation of new migrations.
4. Add all standard views
Most models will need view classes created in views.py to serve the following operations:
- List view
- Detail view
- Edit view
- Delete view
- Bulk import
- Bulk edit
- Bulk delete
5. Add URL paths
Add the relevant URL path for each view created in the previous step to urls.py.
6. Add relevant forms
Depending on the type of model being added, you may need to define several types of form classes. These include:
- A base model form (for creating/editing individual objects)
- A bulk edit form
- A bulk import form (for CSV-based import)
- A filterset form (for filtering the object list view)
7. Create the FilterSet
Each model should have a corresponding FilterSet class defined. This is used to filter UI and API queries. Subclass the appropriate class from netbox.filtersets that matches the model's parent class.
8. Create the table class
Create a table class for the model in tables.py by subclassing utilities.tables.BaseTable. Under the table's Meta class, be sure to list both the fields and default columns.
9. Create a SearchIndex subclass
If this model will be included in global search results, create a subclass of netbox.search.SearchIndex for it and specify the fields to be indexed.
10. Create the object template
Create the HTML template for the object view. (The other views each typically employ a generic template.) This template should extend generic/object.html.
11. Add the model to the navigation menu
Add the relevant navigation menu items in netbox/netbox/navigation/menu.py.
12. REST API components
Create the following for each model:
- Detailed (full) model serializer in
api/serializers.py - API view in
api/views.py - Endpoint route in
api/urls.py
13. GraphQL API components
Create the following for each model:
- GraphQL object type for the model in
graphql/types.py(subclass the appropriate class fromnetbox.graphql.types) - Add a GraphQL filter for the model in
graphql/filters.py - Extend the query class for the app in
graphql/schema.pywith 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.
14. Add tests
Add tests for the following:
- UI views
- API views
- Filter sets
15. Documentation
Create a new documentation page for the model in docs/models/<app_label>/<model_name>.md. Include this file under the "features" documentation where appropriate.
Also add your model to the index in docs/development/models.md.
File: docs/development/application-registry.md
Application Registry
The registry is an in-memory data structure which houses various application-wide parameters, such as the list of enabled plugins. It is not exposed to the user and is not intended to be modified by any code outside of NetBox core.
The registry behaves essentially like a Python dictionary, with the notable exception that once a store (key) has been declared, it cannot be deleted or overwritten. The value of a store can, however, be modified; e.g. by appending a value to a list. Store values generally do not change once the application has been initialized.
The registry can be inspected by importing registry from extras.registry.
Stores
`counter_fields`
A dictionary mapping of models to foreign keys with which cached counter fields are associated.
`data_backends`
A dictionary mapping data backend types to their respective classes. These are used to interact with remote data sources.
`denormalized_fields`
Stores registration made using netbox.denormalized.register(). For each model, a list of related models and their field mappings is maintained to facilitate automatic updates.
`filtersets`
A dictionary mapping each model (identified by its app and label) to its filterset class, if one has been registered for it. Filtersets are registered using the @register_filterset decorator.
`model_features`
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.
Core model features are listed in the features matrix.
`models`
!!! warning "Deprecated"
Usage of this key has been deprecated and will be removed in NetBox v4.7. Use ObjectType.objects.public() to find registered models.
This key lists all models which have been registered in NetBox which are not designated for private use. (Setting _netbox_private to True on a model excludes it from this list.) As with individual features under model_features, models are organized by app label.
`plugins`
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.
`tables`
A dictionary mapping table classes to lists of extra columns that have been registered by plugins using the register_table_column() utility function. Each column is defined as a tuple of name and column instance.
`views`
A hierarchical mapping of registered views for each model. Mappings are added using the register_model_view() decorator, and URLs paths can be generated from these using get_model_urls().
File: docs/development/extending-models.md
Extending Models
Below is a list of tasks to consider when adding a new field to a core model.
1. Add the field to the model class
Add the field to the model, taking care to address any of the following conditions.
When adding a GenericForeignKey field, you may need add an index under
Metafor its two concrete fields. (This is required only for non-unique GFK relationships, as the unique constraint introduces its own index.) For example:pythonclass Meta: indexes = ( models.Index(fields=('object_type', 'object_id')), )
2. Generate and run database migrations
Django migrations are used to express changes to the database schema. In most cases, Django can generate these automatically, however very complex changes may require manual intervention. Always remember to specify a short but descriptive name when generating a new migration.
./manage.py makemigrations <app> -n <name> --no-header
./manage.py migrateWhere possible, try to merge related changes into a single migration. For example, if three new fields are being added to different models within an app, these can be expressed in a single migration. You can merge a newly generated migration with an existing one by combining their operations lists.
!!! warning "Do not alter existing migrations"
Migrations can only be merged within a release. Once a new release has been published, its migrations cannot be altered (other than for the purpose of correcting a bug).
3. Add validation logic to `clean()`
If the new field introduces additional validation requirements (beyond what's included with the field itself), implement them in the model's clean() method. Remember to call the model's original method using super() before or after your custom validation as appropriate:
class Foo(models.Model):
def clean(self):
super().clean()
# Custom validation goes here
if self.bar is None:
raise ValidationError()4. Update relevant querysets
If you're adding a relational field (e.g. ForeignKey) and intend to include the data when retrieving a list of objects, be sure to include the field using prefetch_related() as appropriate. This will optimize the view and avoid extraneous database queries.
5. Update API serializer
Extend the model's API serializer in <app>.api.serializers to include the new field.
6. Add fields to forms
Extend any forms to include the new field(s) as appropriate. These are found under the forms/ directory within each app. Common forms include:
- Credit/edit - Manipulating a single object
- Bulk edit - Performing a change on many objects at once
- CSV import - The form used when bulk importing objects in CSV format
- Filter - Displays the options available for filtering a list of objects (both UI and API)
7. Extend object filter set
If the new field should be filterable, add it to the FilterSet for the model. If the field should be searchable, remember to query it in the FilterSet's search() method.
8. Add column to object table
If the new field will be included in the object list view, add a column to the model's table. For simple fields, adding the field name to Meta.fields will be sufficient. More complex fields may require declaring a custom column. Also add the field name to default_columns if the column should be present in the table by default.
9. Update the SearchIndex
Where applicable, add the new field to the model's SearchIndex for inclusion in global search.
10. Update the UI templates
Edit the object's view template to display the new field. There may also be a custom add/edit form template that needs to be updated.
11. Create/extend test cases
Create or extend the relevant test cases to verify that the new field and any accompanying validation logic perform as expected. This is especially important for relational fields. NetBox incorporates various test suites, including:
- API serializer/view tests
- Filter tests
- Form tests
- Model tests
- View tests
Be diligent to ensure all the relevant test suites are adapted or extended as necessary to test any new functionality.
12. Update the model's documentation
Each model has a dedicated page in the documentation, at models/<app>/<model>.md. Update this file to include any relevant information about the new field.
File: docs/development/getting-started.md
Getting Started
Setting up a Development Environment
Getting started with NetBox development is pretty straightforward, and should feel very familiar to anyone with Django development experience. There are a few things you'll need:
- A Linux system or compatible environment
- A PostgreSQL server, which can be installed locally per the documentation
- A Redis server, which can also be installed locally
- Python 3.12 or later
1. Fork the Repo
Assuming you'll be working on your own fork, your first step will be to fork the official git repository. (If you're a maintainer who's going to be working directly with the official repo, skip this step.) Click the "fork" button at top right (be sure that you've logged into GitHub first).
Copy the URL provided in the dialog box.
You can then clone your GitHub fork locally for development:
$ git clone https://github.com/$username/netbox.git
Cloning into 'netbox'...
remote: Enumerating objects: 85949, done.
remote: Counting objects: 100% (4672/4672), done.
remote: Compressing objects: 100% (1224/1224), done.
remote: Total 85949 (delta 3538), reused 4332 (delta 3438), pack-reused 81277
Receiving objects: 100% (85949/85949), 55.16 MiB | 44.90 MiB/s, done.
Resolving deltas: 100% (68008/68008), done.
$ ls netbox/
base_requirements.txt contrib docs mkdocs.yml NOTICE requirements.txt upgrade.sh
CHANGELOG.md CONTRIBUTING.md LICENSE.txt netbox README.md scripts2. Create a New Branch
The NetBox project utilizes two persistent git branches to track work:
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 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:
git checkout -B $branchnameWhen naming a new git branch, contributors are strongly encouraged to use the relevant issue number followed by a very brief description of the work:
$issue-$descriptionThe 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. Create a Python Virtual Environment
A virtual environment (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.
Create a virtual environment using the venv Python module:
mkdir ~/.venv
python3 -m venv ~/.venv/netboxThis will create a directory named .venv/netbox/ in your home directory, which houses a virtual copy of the Python executable and its related libraries and tooling. When running NetBox for development, it will be run using the Python binary at ~/.venv/netbox/bin/python.
!!! tip "Virtual Environments"
Keeping virtual environments in ~/.venv/ is a common convention but entirely optional: Virtual environments can be created almost wherever you please. Also consider using virtualenvwrapper to simplify the management of multiple environments.
Once created, activate the virtual environment:
source ~/.venv/netbox/bin/activateNotice 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.
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.
python -m pip install -r requirements.txt5. Install Pre-Commit
NetBox uses pre-commit to automatically validate code when commiting new changes. This includes the following operations:
- Run the
ruffPython linter - Run Django's internal system check
- Check for missing database migrations
- Validate any changes to the documentation with
zensical - 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:
python -m pip install ruff pre-commit
pre-commit installYou may also need to set up the yarn packages as shown in the Web UI Development Guide.
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 purposesDATABASES: PostgreSQL database connection parametersREDIS: Redis configuration (if different from the defaults)SECRET_KEY: Set to a random string (usegenerate_secret_key.pyin the parent directory to generate a suitable key)DEBUG: Set toTrueDEVELOPER: Set toTrue(this enables the creation of new database migrations)
7. Start the Development Server
Django provides a lightweight, auto-updating HTTP/WSGI server for development use. It is started with the runserver management command:
$ ./manage.py runserver
Performing system checks...
System check identified no issues (0 silenced).
August 18, 2022 - 15:17:52
Django version 4.0.7, using settings 'netbox.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.This ensures that your development environment is now complete and operational. The development server will monitor the development environment and automatically reload in response to any changes made.
!!! tip "IDE Integration"
Some IDEs, such as the highly-recommended PyCharm, will integrate with Django's development server and allow you to run it directly within the IDE. This is strongly encouraged as it makes for a much more convenient development environment.
UI Development
For UI development you will need to review the Web UI Development Guide
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 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.
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.
Running Tests
Prior to committing any substantial changes to the code base, be sure to run NetBox's test suite to catch potential errors. Tests are run using the test management command, which employs Python's unittest library. Remember to ensure that the Python virtual environment is active before running this command. Also keep in mind that these commands are executed in the netbox/ directory, not the root directory of the repository.
To avoid potential issues with your local configuration file, set the NETBOX_CONFIGURATION to point to the packaged test configuration at netbox/configuration_testing.py. This will handle things like ensuring that the dummy plugin is enabled for comprehensive testing.
export NETBOX_CONFIGURATION=netbox.configuration_testing
cd netbox/
python manage.py testIn cases where you haven't made any changes to the database schema (which is typical), you can append the --keepdb argument to this command to reuse the test database between runs. This cuts down on the time it takes to run the test suite since the database doesn't have to be rebuilt each time. (Note that this argument will cause errors if you've modified any model fields since the previous test run.)
python manage.py test --keepdbYou can also reduce testing time by enabling parallel test execution with the --parallel flag. (By default, this will run as many parallel tests as you have processors. To avoid sluggishness, it's a good idea to specify a lower number of parallel tests.) This flag can be combined with --keepdb, although if you encounter any strange errors, try running the test suite again with parallelization disabled.
python manage.py test --parallel <n>Finally, it's possible to limit the run to a specific set of tests, specified by their Python path. For example, to run only IPAM and DCIM view tests:
python manage.py test dcim.tests.test_views ipam.tests.test_viewsThis is handy for instances where just a few tests are failing and you want to re-run them individually.
!!! info
NetBox uses django-rich to enhance Django's default test management command.
SQL Query Count Baselines
The shared list-test mixins assert the number of SQL queries each list endpoint performs against a baseline checked in alongside the tests. This guards against the accidental introduction of new queries (e.g. N+1 patterns) when a queryset, serializer, or table changes. Baselines are stored per app at netbox/<app>/tests/query_counts.json, keyed by <model_name>:<test_name>.
If a list test fails with a message like Query count for dcim/site:list_objects changed: expected 16, got 18, first investigate whether the change is expected. If the new count is correct (e.g. you intentionally added a prefetch_related, or removed one), regenerate the baseline:
UPDATE_QUERY_COUNTS=1 python manage.py test --keepdbUPDATE_QUERY_COUNTS mode requires serial execution; do not combine it with --parallel. You can target a single test, app, or the full suite โ only the keys exercised by the run are updated. Review the resulting diff in the JSON files as part of the PR; a reviewer should be able to see and reason about every query-count change.
Submitting Pull Requests
Once you're happy with your work and have verified that all tests pass, commit your changes and push it upstream to your fork. Always provide descriptive (but not excessively verbose) commit messages. Be sure to prefix your commit message with the word "Fixes" or "Closes" and the relevant issue number (with a hash mark). This tells GitHub to automatically close the referenced issue once the commit has been merged.
git commit -m "Closes #1234: Add IPv5 support"
git push originOnce your fork has the new commit, submit a pull request to the NetBox repo to propose the changes. Be sure to provide a detailed accounting of the changes being made and the reasons for doing so.
Once submitted, a maintainer will review your pull request and either merge it or request changes. If changes are needed, you can make them via new commits to your fork: The pull request will update automatically.
!!! warning
Remember, pull requests are permitted only for accepted issues. If an issue you want to work on hasn't been approved by a maintainer yet, it's best to avoid risking your time and effort on a change that might not be accepted. (The one exception to this is trivial changes to the documentation or other non-critical resources.)
File: docs/development/git-cheat-sheet.md
git Cheat Sheet
This cheat sheet serves as a convenient reference for NetBox contributors who already somewhat familiar with using git. For a general introduction to the tooling and workflows involved, please see GitHub's guide Getting started with git.
Common Operations
Clone a Repo
This copies a remote git repository (e.g. from GitHub) to your local workstation. It will create a new directory bearing the repo's name in the current path.
git clone https://github.com/$org-name/$repo-name$ git clone https://github.com/netbox-community/netbox
Cloning into 'netbox'...
remote: Enumerating objects: 95112, done.
remote: Counting objects: 100% (682/682), done.
remote: Compressing objects: 100% (246/246), done.
remote: Total 95112 (delta 448), reused 637 (delta 436), pack-reused 94430
Receiving objects: 100% (95112/95112), 60.40 MiB | 45.82 MiB/s, done.
Resolving deltas: 100% (74979/74979), done.Pull New Commits
To update your local branch with any recent upstream commits, run git pull.
git pull$ git pull
remote: Enumerating objects: 1, done.
remote: Counting objects: 100% (1/1), done.
remote: Total 1 (delta 0), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (1/1), done.
From https://github.com/netbox-community/netbox
28bc76695..e0741cc9a develop -> origin/develop
Updating 28bc76695..e0741cc9a
Fast-forward
docs/release-notes/version-3.3.md | 1 +
netbox/netbox/settings.py | 1 +
2 files changed, 2 insertions(+)List Branches
git branch lists all local branches. Appending -a to this command will list both local (green) and remote (red) branches.
git branch -a$ git branch -a
* develop
remotes/origin/10170-changelog
remotes/origin/HEAD -> origin/develop
remotes/origin/develop
remotes/origin/feature
remotes/origin/masterSwitch Branches
To switch to a different branch, use the checkout command.
git checkout $branchname$ git checkout feature
Branch 'feature' set up to track remote branch 'feature' from 'origin'.
Switched to a new branch 'feature'Create a New Branch
Use the -b argument with checkout to create a new local branch from the current branch.
git checkout -b $newbranch$ git checkout -b 123-fix-foo
Switched to a new branch '123-fix-foo'Rename a Branch
To rename the current branch, use the git branch command with the -m argument (for "modify").
git branch -m $newname$ git branch -m jstretch-testing
$ git branch
develop
feature
* jstretch-testingMerge a Branch
To merge one branch into another, use the git merge command. Start by checking out the destination branch, and merge the source branch into it.
git merge $sourcebranch$ git checkout testing
Switched to branch 'testing'
Your branch is up to date with 'origin/testing'.
$ git merge branch2
Updating 9a12b5b5f..8ee42390b
Fast-forward
newfile.py | 0
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 newfile.py!!! warning "Avoid Merging Remote Branches"
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
After making changes to files in the repo, git status will display a summary of created, modified, and deleted files.
git status$ git status
On branch 123-fix-foo
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: README.md
Untracked files:
(use "git add <file>..." to include in what will be committed)
foo.py
no changes added to commit (use "git add" and/or "git commit -a")Stage Changed Files
Before creating a new commit, modified files must be staged. This is typically done with the git add command. You can specify a particular path, or just append -A to automatically staged all changed files within the current directory. Run git status again to verify what files have been staged.
git add -A$ git add -A
$ git status
On branch 123-fix-foo
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
modified: README.md
new file: foo.pyReview Staged Files
It's a good idea to thoroughly review all staged changes immediately prior to creating a new commit. This can be done using the git diff command. Appending the --staged argument will show staged changes; omitting it will show changes that have not yet been staged.
git diff --staged$ git diff --staged
diff --git a/README.md b/README.md
index 93e125079..4344fb514 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,8 @@
+
+Added some lines here
+and here
+and here too
+
diff --git a/foo.py b/foo.py
new file mode 100644
index 000000000..e69de29bbCreate a New Commit
The git commit command records your changes to the current branch. Specify a commit message with the -m argument. (If omitted, a file editor will be opened to provide a message.
git commit -m "Fixes #123: Fixed the thing that was broken"$ git commit -m "Fixes #123: Fixed the thing that was broken"
[123-fix-foo 9a12b5b5f] Fixes #123: Fixed the thing that was broken
2 files changed, 5 insertions(+)
create mode 100644 foo.py!!! tip "Automatically Closing Issues"
GitHub will automatically close any issues referenced in a commit message by Fixes: or Closes: when the commit is merged into the repository's default branch. Contributors are strongly encouraged to follow this convention when forming commit messages. (Use "Closes" for feature requests and "Fixes" for bugs.)
Push a Commit Upstream
Once you've made a commit locally, it needs to be pushed upstream to the remote repository (typically called "origin"). This is done with the git push command. If this is a new branch that doesn't yet exist on the remote repository, you'll need to set the upstream for it when pushing.
git push -u origin $branchname$ git push -u origin testing
Counting objects: 3, done.
Delta compression using up to 16 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 377 bytes | 377.00 KiB/s, done.
Total 3 (delta 2), reused 0 (delta 0)
remote: Resolving deltas: 100% (2/2), completed with 2 local objects.
remote:
remote: Create a pull request for 'testing' on GitHub by visiting:
remote: https://github.com/netbox-community/netbox/pull/new/testing
remote:
To https://github.com/netbox-community/netbox
* [new branch] testing -> testing
Branch 'testing' set up to track remote branch 'testing' from 'origin'.!!! tip
You can apply the following git configuration to automatically set the upstream for all new branches. This obviates the need to specify -u origin.
```
git config --global push.default current
```The GitHub CLI Client
GitHub provides a free CLI client to simplify many aspects of interacting with GitHub repositories. Note that this utility is separate from git, and must be installed separately.
This guide provides some examples of common operations, but be sure to check out the GitHub CLI manual for a complete accounting of available commands.
List Open Pull Requests
gh pr list$ gh pr list
Showing 3 of 3 open pull requests in netbox-community/netbox
#10223 #7503 API Bulk-Create of Devices does not check Rack-Space 7503-bulkdevice about 17 hours ago
#9716 Closes #9599: Add cursor pagination mode lyuyangh:cursor-pagination about 1 month ago
#9498 Adds replication and adoption for module import sleepinggenius2:issue_9361 about 2 months agoCheck Out a PR
This command will automatically check out the remote branch associated with an open pull request.
gh pr checkout $number$ gh pr checkout 10223
Branch '7503-bulkdevice' set up to track remote branch '7503-bulkdevice' from 'origin'.
Switched to a new branch '7503-bulkdevice'Fixing Mistakes
Modify the Previous Commit
Sometimes you'll find that you've overlooked a necessary change and need to commit again. If you haven't pushed your most recent commit and just need to make a small tweak or two, you can amend your most recent commit instead of creating a new one.
First, stage the desired files with git add and verify the changes, the issue the git commit command with the --amend argument. You can also append the --no-edit argument if you would like to keep the previous commit message.
git commit --amend --no-edit$ git add -A
$ git diff --staged
$ git commit --amend --no-edit
[testing 239b16921] Added a new file
Date: Fri Aug 26 16:30:05 2022 -0400
2 files changed, 1 insertion(+)
create mode 100644 newfile.py!!! danger "Don't Amend After Pushing"
Never amend a commit you've already pushed upstream unless you're certain no one else is working on the same branch. Force-pushing will overwrite the change history, which will break any commits from other contributors. When in doubt, create a new commit instead.
Undo the Last Commit
The git reset command can be used to undo the most recent commit. (HEAD~ is equivalent to HEAD~1 and references the commit prior to the current HEAD.) After making and staging your changes, commit using -c ORIG_HEAD to replace the erroneous commit.
git reset HEAD~$ git add -A
$ git commit -m "Erroneous commit"
[testing 09ce06736] Erroneous commit
Date: Mon Aug 29 15:20:04 2022 -0400
1 file changed, 1 insertion(+)
create mode 100644 BADCHANGE
$ git reset HEAD~
$ rm BADFILE
$ git add -A
$ git commit -m "Fixed commit"
[testing c585709f3] Fixed commit
Date: Mon Aug 29 15:22:38 2022 -0400
1 file changed, 65 insertions(+), 20 deletions(-)!!! danger "Don't Reset After Pushing"
Resetting only works until you've pushed your local changes upstream. If you've already pushed upstream, use git revert instead. This will create a new commit that reverts the erroneous one, but ensures that the git history remains intact.
Rebase from Upstream
If a change has been pushed to the upstream branch since you most recently pulled it, attempting to push a new local commit will fail:
$ git push
To https://github.com/netbox-community/netbox.git
! [rejected] develop -> develop (fetch first)
error: failed to push some refs to 'https://github.com/netbox-community/netbox.git'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally. This is usually caused by another repository pushing
hint: to the same ref. You may want to first integrate the remote changes
hint: (e.g., 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.To resolve this, first fetch the upstream branch to update your local copy, and then rebase your local branch to include the new changes. Once the rebase has completed, you can push your local commits upstream.
git fetch
git rebase origin/$branchname$ git fetch
remote: Enumerating objects: 1, done.
remote: Counting objects: 100% (1/1), done.
remote: Total 1 (delta 0), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (1/1), done.
From https://github.com/netbox-community/netbox
815b2d8a2..8c35ebbb7 develop -> origin/develop
$ git rebase origin/develop
First, rewinding head to replay your work on top of it...
Applying: Further tweaks to the PR template
Applying: Changelog for #10176, #10217
$ git push
Counting objects: 9, done.
Delta compression using up to 16 threads.
Compressing objects: 100% (9/9), done.
Writing objects: 100% (9/9), 1.02 KiB | 1.02 MiB/s, done.
Total 9 (delta 6), reused 0 (delta 0)
remote: Resolving deltas: 100% (6/6), completed with 5 local objects.
To https://github.com/netbox-community/netbox.git
8c35ebbb7..ada745324 develop -> developFile: docs/development/index.md
NetBox Development
Thanks for your interest in contributing to NetBox! This introduction covers a few important things to know before you get started.
The Code
NetBox and many of its related projects are maintained on GitHub. GitHub also serves as one of our primary discussion forums. While all the code and discussion is publicly accessible, you'll need register for a free GitHub account to engage in participation. Most people begin by forking the NetBox repository under their own GitHub account to begin working on the code.
There are two permanent branches in the repository:
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:
circuits: Communications circuits and providers (not to be confused with power circuits)dcim: Datacenter infrastructure management (sites, racks, and devices)extras: Additional features not considered part of the core data modelipam: IP address management (VRFs, prefixes, IP addresses, and VLANs)tenancy: Tenants (such as customers) to which NetBox objects may be assignedusers: Authentication and user preferencesutilities: Resources which are not user-facing (extendable classes, etc.)virtualization: Virtual machines and clusterswireless: Wireless links and LANs
All core functionality is stored within the netbox/ subdirectory. HTML templates are stored in a common templates/ directory, with model- and view-specific templates arranged by app. Documentation is kept in the docs/ root directory.
Proposing Changes
All substantial changes made to the code base are tracked using GitHub issues. Feature requests, bug reports, and similar proposals must all be filed as issues and approved by a maintainer before work begins. This ensures that all changes to the code base are properly documented for future reference.
To submit a new feature request or bug report for NetBox, select and complete the appropriate issue template. Once your issue has been approved, you're welcome to submit a pull request containing your proposed changes.
Check out our issue intake policy for an overview of the issue triage and approval processes.
!!! tip
Avoid starting work on a proposal before it has been accepted. Not all proposed changes will be accepted, and we'd hate for you to waste time working on code that might not make it into the project.
Getting Help
There are two primary forums for getting assistance with NetBox development:
- GitHub discussions - The preferred forum for general discussion and support issues. Ideal for shaping a feature requests prior to submitting an issue.
- #netbox on NetDev Community Slack - Good for quick chats. Avoid any discussion that might need to be referenced later on, as the chat history is not retained indefinitely.
!!! note
Don't use GitHub issues to ask for help: These are reserved for proposed code changes only.
Governance
NetBox follows the benevolent dictator model of governance, with Jeremy Stretch ultimately responsible for all changes to the code base. While community contributions are welcomed and encouraged, the lead maintainer's primary role is to ensure the project's long-term maintainability and continued focus on its primary functions.
Licensing
The entire NetBox project is licensed as open source under the Apache 2.0 license. 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.
File: docs/development/internationalization.md
Internationalization
Beginning with NetBox v4.0, NetBox will leverage Django's automatic translation to support languages other than English. This page details the areas of the project which require special attention to ensure functioning translation support. Briefly, these include:
- The
verbose_nameandverbose_name_pluralMeta attributes for each model - The
verbose_nameand (if defined)help_textfor each model field - The
labelfor each form field - Headers for
fieldsetson each form class - The
verbose_namefor each table column - All human-readable strings within templates must be wrapped with
{% trans %}or{% blocktrans %}
The rest of this document elaborates on each of the items above.
General Guidance
Wrap human-readable strings with Django's
gettext()orgettext_lazy()utility functions to enable automatic translation. Generally,gettext_lazy()is preferred (and sometimes required) to defer translation until the string is displayed.By convention, the preferred translation function is typically imported as an underscore (
_) to minimize boilerplate code. Thus, you will often see translation as e.g._("Some text"). It is still an option to import and use alternative translation functions (e.g.pgettext()andngettext()) normally as needed.Avoid passing markup and other non-natural language where possible. Everything wrapped by a translation function gets exported to a messages file for translation by a human.
Where the intended meaning of the translated string may not be obvious, use
pgettext()orpgettext_lazy()to include assisting context for the translator. For example:python# Context, string pgettext("month name", "May")Format strings do not support translation. Avoid "f" strings for messages that must support translation. Instead, use
format()to accomplish variable replacement:python# Translation will not work f"There are {count} objects" # Do this instead "There are {count} objects".format(count=count)
Models
- Import
gettext_lazyas_. - Ensure both
verbose_nameandverbose_name_pluralare defined under the model'sMetaclass and wrapped with thegettext_lazy()shortcut. - Ensure each model field specifies a
verbose_namewrapped withgettext_lazy(). - Ensure any
help_textattributes on model fields are also wrapped withgettext_lazy().
from django.utils.translation import gettext_lazy as _
class Circuit(PrimaryModel):
commit_rate = models.PositiveIntegerField(
...
verbose_name=_('commit rate (Kbps)'),
help_text=_("Committed rate")
)
class Meta:
verbose_name = _('circuit')
verbose_name_plural = _('circuits')Forms
- Import
gettext_lazyas_. - All form fields must specify a
labelwrapped withgettext_lazy(). - The name of each FieldSet on a form must be wrapped with
gettext_lazy().
from django.utils.translation import gettext_lazy as _
from utilities.forms.rendering import FieldSet
class CircuitBulkEditForm(NetBoxModelBulkEditForm):
description = forms.CharField(
label=_('Description'),
...
)
fieldsets = (
FieldSet('provider', 'type', 'status', 'description', name=_('Circuit')),
)Tables
- Import
gettext_lazyas_. - All table columns must specify a
verbose_namewrapped withgettext_lazy().
from django.utils.translation import gettext_lazy as _
class CircuitTable(TenancyColumnsMixin, ContactsColumnMixin, NetBoxTable):
provider = tables.Column(
verbose_name=_('Provider'),
...
)Templates
- Ensure translation support is enabled by including
{% load i18n %}at the top of the template. - Use the
{% trans %}tag (short for "translate") to wrap short strings. - Longer strings may be enclosed between
{% blocktrans %}and{% endblocktrans %}tags to improve readability and to enable variable replacement. (Remember to include thetrimmedargument to trim whitespace between the tags.) - Avoid passing HTML within translated strings where possible, as this can complicate the work needed of human translators to develop message maps.
{% load i18n %}
{# A short string #}
<h5 class="card-header">{% trans "Circuit List" %}</h5>
{# A longer string with a context variable #}
{% blocktrans trimmed with count=object.circuits.count %}
There are {count} circuits. Would you like to continue?
{% endblocktrans %}!!! warning
The {% blocktrans %} tag supports only limited variable replacement, comparable to the format() method on Python strings. It does not permit access to object attributes or the use of other template tags or filters inside it. Ensure that any necessary context is passed as simple variables.
!!! info
The {% trans %} and {% blocktrans %} support the inclusion of contextual hints for translators using the context argument:
```nohighlight
{% trans "May" context "month name" %}
```File: docs/development/models.md
NetBox Models
Model Types
A NetBox model represents a discrete object type such as a device or IP address. Per Django convention, each model is defined as a Python class and has its own table in the PostgreSQL database. All NetBox data models can be categorized by type.
The Django content types framework is used to map Django models to database tables. A ContentType instance references a model by its app_label and name: For example, the Site model within the DCIM app is referred to as dcim.site. The content type combined with an object's primary key form a globally unique identifier for the object (e.g. dcim.site:123).
Features Matrix
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.
| Feature | Feature Mixin | Registry Key | Description |
|---|---|---|---|
| Bookmarks | BookmarksMixin |
bookmarks |
These models can be bookmarked natively in the user interface |
| Change logging | 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 | ContactsMixin |
contacts |
Contacts can be associated with these models |
| Custom fields | CustomFieldsMixin |
custom_fields |
These models support the addition of user-defined fields |
| Custom links | CustomLinksMixin |
custom_links |
These models support the assignment of custom links |
| Custom validation | CustomValidationMixin |
- | Supports the enforcement of custom validation rules |
| Event rules | EventRulesMixin |
event_rules |
Event rules can send webhooks or run custom scripts automatically in response to events |
| Export templates | ExportTemplatesMixin |
export_templates |
Users can create custom export templates for these models |
| Image attachments | ImageAttachmentsMixin |
image_attachments |
Image uploads can be attached to these models |
| Jobs | JobsMixin |
jobs |
Background jobs can be scheduled for these models |
| Journaling | JournalingMixin |
journaling |
These models support persistent historical commentary |
| Notifications | NotificationsMixin |
notifications |
These models support user notifications |
| Synchronized data | SyncedDataMixin |
synced_data |
Certain model data can be automatically synchronized from a remote data source |
| Tagging | 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
Primary Models
These are considered the "core" application models which are used to model network infrastructure.
- circuits.Circuit
- circuits.Provider
- circuits.ProviderAccount
- circuits.ProviderNetwork
- core.DataFile
- core.DataSource
- core.Job
- dcim.Cable
- dcim.CableBundle
- dcim.Device
- dcim.DeviceType
- dcim.Module
- dcim.ModuleType
- dcim.PowerFeed
- dcim.PowerPanel
- dcim.Rack
- dcim.RackReservation
- dcim.RackType
- dcim.Site
- dcim.VirtualChassis
- dcim.VirtualDeviceContext
- ipam.Aggregate
- ipam.ASN
- ipam.FHRPGroup
- ipam.FHRPGroupAssignment
- ipam.IPAddress
- ipam.IPRange
- ipam.Prefix
- ipam.RouteTarget
- ipam.Service
- ipam.ServiceTemplate
- ipam.VLAN
- ipam.VRF
- tenancy.Contact
- tenancy.Tenant
- virtualization.Cluster
- virtualization.VirtualMachine
- virtualization.VirtualMachineType
- vpn.IKEPolicy
- vpn.IKEProposal
- vpn.IPSecPolicy
- vpn.IPSecProfile
- vpn.IPSecProposal
- vpn.L2VPN
- vpn.Tunnel
- wireless.WirelessLAN
- wireless.WirelessLink
Organizational Models
Organization models are used to organize and classify primary models.
- circuits.CircuitGroup
- circuits.CircuitType
- dcim.DeviceRole
- dcim.Manufacturer
- dcim.Platform
- dcim.RackGroup
- dcim.RackRole
- ipam.ASNRange
- ipam.RIR
- ipam.Role
- ipam.VLANGroup
- tenancy.ContactRole
- virtualization.ClusterGroup
- virtualization.ClusterType
- vpn.TunnelGroup
Nested Group Models
Nested group models behave like organizational model, but self-nest within a recursive hierarchy. For example, the Region model can be used to represent a hierarchy of countries, states, and cities.
- dcim.Location (formerly RackGroup)
- dcim.Region
- dcim.SiteGroup
- tenancy.ContactGroup
- tenancy.TenantGroup
- wireless.WirelessLANGroup
Component Models
Component models represent individual physical or virtual components belonging to a device or virtual machine.
- dcim.ConsolePort
- dcim.ConsoleServerPort
- dcim.DeviceBay
- dcim.FrontPort
- dcim.Interface
- dcim.InventoryItem
- dcim.ModuleBay
- dcim.PowerOutlet
- dcim.PowerPort
- dcim.RearPort
- virtualization.VirtualDisk
- virtualization.VMInterface
Component Template Models
These function as templates to effect the replication of device and virtual machine components. Component template models support a limited feature set, including change logging, custom validation, and event rules.
- dcim.ConsolePortTemplate
- dcim.ConsoleServerPortTemplate
- dcim.DeviceBayTemplate
- dcim.FrontPortTemplate
- dcim.InterfaceTemplate
- dcim.InventoryItemTemplate
- dcim.ModuleBayTemplate
- dcim.PowerOutletTemplate
- dcim.PowerPortTemplate
- dcim.RearPortTemplate
Connection Models
Connection models are used to model the connections, or connection endpoints between models.
File: docs/development/release-checklist.md
Release Checklist
This documentation describes the process of packaging and publishing a new NetBox release. There are three types of releases:
- 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 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 heading below. For minor or major releases, complete the entire checklist.
Minor Version Releases
Address Constrained Dependencies
Sometimes it becomes necessary to constrain dependencies to a particular version, e.g. to work around a bug in a newer release or to avoid a breaking change that we have yet to accommodate. (Another common example is to limit the upstream Django release.) For example:
# https://github.com/encode/django-rest-framework/issues/6053
djangorestframework==3.8.1These version constraints are added to base_requirements.txt to ensure that newer packages are not installed when updating the pinned dependencies in requirements.txt (see the Update Requirements section below). Before each new minor version of NetBox is released, all such constraints on dependent packages should be addressed if feasible. This guards against the collection of stale constraints over time.
Close the Release Milestone
Close the release milestone on GitHub after ensuring there are no remaining open issues associated with it.
Update the Release Notes
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:
zensical serveFollow 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.
Test Upgrade Paths
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:
./manage.py migrateMerge 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)
After the release of a new minor version, generate a new demo data snapshot compatible with the new release. See the netbox-demo-data repository for instructions.
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.ZNotify netbox-docker Project of Any Relevant Changes
Notify the netbox-docker maintainers (in #netbox-docker) of any changes that may be relevant to their build process, including:
- Significant changes to
upgrade.sh - Increases in minimum versions for service dependencies (PostgreSQL, Redis, etc.)
- Any changes to the reference installation
Update Python Dependencies
Before each release, update each of NetBox's Python dependencies to its most recent stable version. Loose runtime constraints (and per-package descriptions) live in base_requirements.txt; requirements.txt is the pinned, top-level dependency file consumed by the release archive, the git install flow (upgrade.sh), and the published wheel's dependency metadata. Optional dependency groups (for example ldap, saml2) are declared in pyproject.toml.
To update the pinned requirements:
Review each constraint in
base_requirements.txt.Upgrade the installed version of all required packages in your environment (
pip install -U -r base_requirements.txt).Run all tests and check that the UI and API function as expected.
Review each requirement's release notes for any breaking or otherwise noteworthy changes.
If upgrading a dependency is breaking, constrain it in
base_requirements.txtwith an explanatory comment and revisit it for the next major NetBox release (see the Address Constrained Dependencies section above).Update the pinned versions in
requirements.txtto the versions you just tested. Keeprequirements.txtin the existing barepackage==versionformat (one top-level package per line, the same package set asbase_requirements.txt).Verify there is no drift between the policy file and the pins:
no-highlightpython3 scripts/verify_dependencies.py
The published wheel's Requires-Dist is generated from requirements.txt at build time, so the package installs the same tested pins as the archive and git flows.
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 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 and re-compiled for each new release. First, retrieve any updated translation files using the Transifex CLI client:
tx pull --forceThen, compile these portable (.po) files for use in the application:
./manage.py compilemessages!!! tip
Consult the translation documentation for more detail on 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. - No manual
pyproject.tomlversion edit is needed: the package version is derived automatically fromrelease.yaml(versionplus anydesignation) by the build backend. - 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
Run the following command to update the device type definition validation schema:
./manage.py buildschema --writeThis will automatically update the schema file at contrib/generated_schema.json.
Update the OpenAPI Schema
!!! warning "Disable all plugins first"
Before generating the OpenAPI schema, disable any installed plugins. This will prevent their schemas from being pulled into the generated snapshot.
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.
./manage.py spectacular --format openapi-json > ../contrib/openapi.jsonUpdate Development Dependencies
Keep development tooling versions consistent across the project. If you upgrade a dev-only dependency, update all places where itโs pinned so local tooling and CI run the same versions.
- Ruff
.pre-commit-config.yaml.github/workflows/ci.yml
Submit a Pull Request
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 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 on GitHub with the following parameters.
- 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 from GitHub.
Publish to Test PyPI
Pushing a release tag triggers the Python package publishing workflow, which publishes the tagged release automatically to Test PyPI for maintainer validation. Installing NetBox via pip is not a supported installation path during the v4.6.x preview period; production PyPI publishing is planned for the v4.7.0 feature branch. A manual workflow_dispatch run publishes to Test PyPI only when the selected ref is a v* release tag; dispatching from a branch runs the build and verification jobs as a dry run without publishing.
After a publish run completes:
Verify that the build, CLI smoke-test (
cli-smoke-test), smoke-test, dependency-verification (verify-dependencies), and sdist-verification (verify-sdist) jobs succeeded. The dependency-verification job fails the release ifrequirements.txthas drifted frombase_requirements.txtor if the built wheel'sRequires-Distdoes not matchrequirements.txt; the sdist-verification job fails it if the sdist ships unexpected configuration files or cannot rebuild a valid wheel.Verify that the publish job used the expected trusted-publishing environment (
testpypi).Confirm that the new version is visible on Test PyPI.
Install the published wheel into a fresh virtual environment and run
netbox checkagainst a minimal configuration module. The preview artifact is published to Test PyPI while NetBox's pinned runtime dependencies are expected to resolve from PyPI; to avoid mixed-index dependency resolution during validation, install the pinned dependencies from PyPI first, then install the Test PyPI artifact without resolving dependencies again:no-highlightpip install -r requirements.txt pip install --no-deps --index-url https://test.pypi.org/simple/ netbox==<version>
!!! note "Trusted publishing prerequisites"
Publishing requires a one-time setup by the project owners: a netbox project and a configured GitHub trusted publisher on Test PyPI, plus the corresponding testpypi GitHub Actions environment.
The published package version is derived from netbox/release.yaml (the version field plus any designation, e.g. beta1 becomes 4.7.0b1), not from the git tag. Ensure the tag and release.yaml agree before tagging a pre-release.