Răsfoiți Sursa

Closes #23613: Adopt package-based installation as primary strategy

Jeremy Stretch 17 ore în urmă
părinte
comite
b262b4780a

+ 3 - 3
docs/configuration/index.md

@@ -4,10 +4,10 @@
 
 
 NetBox's configuration file contains all the important parameters which control how NetBox functions: database settings, security controls, user preferences, and so on. While the default configuration suffices out of the box for most use cases, there are a few [required parameters](./required-parameters.md) which **must** be defined during installation. 
 NetBox's configuration file contains all the important parameters which control how NetBox functions: database settings, security controls, user preferences, and so on. While the default configuration suffices out of the box for most use cases, there are a few [required parameters](./required-parameters.md) which **must** be defined during installation. 
 
 
-The configuration file is loaded from `$INSTALL_ROOT/netbox/netbox/configuration.py` by default. An example configuration is provided at `configuration_example.py`, which you may copy to use as your default config. Note that a configuration file must be defined; NetBox will not run without one.
+The configuration file is loaded from `$NETBOX_ROOT/conf/configuration.py` by default, where `NETBOX_ROOT` is the instance root (`/opt/netbox` unless set otherwise in the environment). Use `netbox setup --target <path>` to scaffold the local configuration from the bundled example, and keep configuration and mutable instance data outside the virtual environment and installed package. The setup target is not persisted; set `NETBOX_ROOT` for all commands and services when using a non-default path. Note that a configuration file must be defined; NetBox will not run without one.
 
 
-!!! note "Python package installations (experimental)"
-    An experimental Python package installation loads `$NETBOX_ROOT/conf/configuration.py` by default. `NETBOX_ROOT` defaults to `/opt/netbox`. Use `netbox setup --target <path>` to scaffold the local configuration, and keep configuration and mutable instance data outside the virtual environment and installed package. The setup target is not persisted; set `NETBOX_ROOT` for all commands and services when using a non-default path.
+!!! note "Release archive and Git installations"
+    When NetBox is run from a release archive or Git checkout, the configuration file is loaded from `$INSTALL_ROOT/netbox/netbox/configuration.py` by default. An example configuration is provided at `configuration_example.py`, which you may copy to use as your default config.
 
 
 !!! info "Customizing the Configuration Module"
 !!! info "Customizing the Configuration Module"
     A custom configuration module may be specified by setting the `NETBOX_CONFIGURATION` environment variable. This must be a dotted path to the desired Python module. For example, a file named `my_config.py` in the same directory as `settings.py` would be referenced as `netbox.my_config`.
     A custom configuration module may be specified by setting the `NETBOX_CONFIGURATION` environment variable. This must be a dotted path to the desired Python module. For example, a file named `my_config.py` in the same directory as `settings.py` would be referenced as `netbox.my_config`.

+ 2 - 2
docs/configuration/required-parameters.md

@@ -37,7 +37,7 @@ API_TOKEN_PEPPERS = {
 !!! warning "Peppers are sensitive"
 !!! warning "Peppers are sensitive"
     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. 
     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. For a Python package installation, run the virtual environment's `netbox secret-key` command instead.
+Peppers must be at least 50 characters in length and should comprise a random string with a diverse character set. Consider using the virtual environment's `netbox secret-key` command to generate a pepper value. (For a release archive or Git installation, use the Python script at `$INSTALL_ROOT/netbox/generate_secret_key.py` instead.)
 
 
 It is recommended to start with a pepper ID of `1`. Additional peppers can be introduced later as needed to begin rotating token hashes.
 It is recommended to start with a pepper ID of `1`. Additional peppers can be introduced later as needed to begin rotating token hashes.
 
 
@@ -249,4 +249,4 @@ REDIS = {
 
 
 This is a secret, pseudorandom string used to assist in the creation new cryptographic hashes for passwords and HTTP cookies. The key defined here should not be shared outside the configuration file. `SECRET_KEY` can be changed at any time without impacting stored data, however be aware that doing so will invalidate all existing user sessions. NetBox deployments comprising multiple nodes must have the same secret key configured on all nodes.
 This is a secret, pseudorandom string used to assist in the creation new cryptographic hashes for passwords and HTTP cookies. The key defined here should not be shared outside the configuration file. `SECRET_KEY` can be changed at any time without impacting stored data, however be aware that doing so will invalidate all existing user sessions. NetBox deployments comprising multiple nodes must have the same secret key configured on all nodes.
 
 
-`SECRET_KEY` **must** be at least 50 characters in length, and should contain a mix of letters, digits, and symbols. The script located at `$INSTALL_ROOT/netbox/generate_secret_key.py` may be used to generate a suitable key. For a Python package installation, run the virtual environment's `netbox secret-key` command instead. Please note that this key is **not** used directly for hashing user passwords or for the encrypted storage of secret data in NetBox.
+`SECRET_KEY` **must** be at least 50 characters in length, and should contain a mix of letters, digits, and symbols. The virtual environment's `netbox secret-key` command may be used to generate a suitable key. (For a release archive or Git installation, use the script located at `$INSTALL_ROOT/netbox/generate_secret_key.py` instead.) Please note that this key is **not** used directly for hashing user passwords or for the encrypted storage of secret data in NetBox.

+ 2 - 2
docs/development/building-the-package.md

@@ -1,6 +1,6 @@
 # Building the Package
 # Building the Package
 
 
-NetBox package artifacts (a wheel and a source distribution) can be built and verified locally. Installing NetBox from the Python package is experimental in NetBox v4.7 and is not recommended for production use. This page is intended for maintainers and contributors working on the packaging itself. Routine development does not require building a package.
+NetBox package artifacts (a wheel and a source distribution) can be built and verified locally. This page is intended for maintainers and contributors working on the packaging itself. Routine development does not require building a package.
 
 
 Published artifacts are always built by CI from a clean checkout (see `.github/workflows/release.yml`). A local build is useful for testing packaging changes before they are merged.
 Published artifacts are always built by CI from a clean checkout (see `.github/workflows/release.yml`). A local build is useful for testing packaging changes before they are merged.
 
 
@@ -99,7 +99,7 @@ Without configuration, a wheel-installed NetBox looks for `$NETBOX_ROOT/conf/con
 
 
 ## Packaging architecture
 ## Packaging architecture
 
 
-This section is a developer-facing overview of how the package is assembled and how a pip-installed NetBox behaves at runtime. End-user installation steps live in [Install NetBox from the Python Package](../installation/3b-python-package.md).
+This section is a developer-facing overview of how the package is assembled and how a pip-installed NetBox behaves at runtime. End-user installation steps live in [Install NetBox](../installation/3-netbox.md).
 
 
 ### Dynamic metadata
 ### Dynamic metadata
 
 

+ 1 - 1
docs/development/release-checklist.md

@@ -214,7 +214,7 @@ Once created, the release will become available for users to install from GitHub
 
 
 ### Publish to PyPI
 ### Publish to PyPI
 
 
-Creating the GitHub release pushes the new tag and starts the Python package publishing workflow. With the prerequisites above in place, the workflow builds and verifies the wheel and source distribution, then holds the production upload until the `pypi` deployment is approved. Approving the deployment publishes the verified artifacts to **PyPI**. Installing NetBox from the Python package is experimental in NetBox v4.7 and is not recommended for production use.
+Creating the GitHub release pushes the new tag and starts the Python package publishing workflow. With the prerequisites above in place, the workflow builds and verifies the wheel and source distribution, then holds the production upload until the `pypi` deployment is approved. Approving the deployment publishes the verified artifacts to **PyPI**.
 
 
 A manual `workflow_dispatch` run from a `v*` release tag publishes to **Test PyPI** instead. This remains available as an optional rehearsal after packaging or publishing changes, but it is not required for every production release. Dispatching from a branch runs the build and verification jobs as a dry run without publishing anywhere.
 A manual `workflow_dispatch` run from a `v*` release tag publishes to **Test PyPI** instead. This remains available as an optional rehearsal after packaging or publishing changes, but it is not required for every production release. Dispatching from a branch runs the build and verification jobs as a dry run without publishing anywhere.
 
 

+ 284 - 110
docs/installation/3-netbox.md

@@ -1,6 +1,29 @@
-# Install NetBox from a Release Archive or Git
+# Install NetBox
 
 
-This page covers the established release archive and Git installation methods. To install NetBox from the experimental Python package instead, follow the [separate package installation guide](3b-python-package.md).
+NetBox is published as a [Python package on PyPI](https://pypi.org/project/netbox/). This guide uses `pip` to install the NetBox application and its Python dependencies into a virtual environment. Configuration, uploaded media, custom scripts and reports, collected static files, and deployment configuration are kept outside the installed package.
+
+This step does **not** configure PostgreSQL, Redis, a WSGI server, an HTTP server, or system services. These are covered by the other steps of the installation guide.
+
+!!! info "Installing from source"
+    NetBox can also be run from a clone of its [Git repository](https://github.com/netbox-community/netbox) or from a release archive (tarball) downloaded from [GitHub](https://github.com/netbox-community/netbox/releases). These methods are intended for developers working on NetBox itself; see the [development guide](../development/getting-started.md) to set up a development environment. Existing deployments installed by these methods can be [migrated to the Python package](#migrate-an-existing-archive-or-git-installation).
+
+## Understand the Installation Layout
+
+A package installation separates the application code from the files that belong to a particular NetBox instance.
+
+| Component | Example Location | Purpose |
+|-----------|------------------|---------|
+| Application code | `<venv>/lib/pythonX.Y/site-packages/` | Installed and replaced by `pip`; do not modify it directly |
+| Python virtual environment | `/opt/netbox/venv/` | Contains NetBox, its dependencies, and any plugins |
+| Instance root | `/opt/netbox/` | Holds local configuration and mutable instance data |
+| Configuration | `/opt/netbox/conf/configuration.py` | Contains settings and credentials for this instance |
+| Mutable data | `/opt/netbox/{media,reports,scripts,static}/` | Persists independently of package upgrades |
+| Deployment examples | `/opt/netbox/contrib/` | Local copies to review and adapt before use |
+
+The instance root defaults to `/opt/netbox` and may be changed with the `NETBOX_ROOT` environment variable. The virtual environment does not need to be located below the instance root; `/opt/netbox/venv` is used throughout this guide only to keep the example straightforward.
+
+!!! note "Custom instance roots"
+    The `--target` option for `netbox setup` selects where the local files are created. It does not permanently set the instance root. When using a location other than `/opt/netbox`, set `NETBOX_ROOT` for all NetBox commands and services.
 
 
 ## Install System Packages
 ## Install System Packages
 
 
@@ -21,85 +44,84 @@ Before continuing, check that your installed Python version is at least 3.12:
 python3 -V
 python3 -V
 ```
 ```
 
 
-## Download NetBox
+## Create the System User and Instance Root
 
 
-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
-
-Download the [latest stable release](https://github.com/netbox-community/netbox/releases) from GitHub as a tarball or ZIP archive and extract it to your desired path. In this example, we'll use `/opt/netbox` as the NetBox root.
+Create the `netbox` system account and the default instance root:
 
 
 ```no-highlight
 ```no-highlight
-sudo wget https://github.com/netbox-community/netbox/archive/refs/tags/vX.Y.Z.tar.gz
-sudo tar -xzf vX.Y.Z.tar.gz -C /opt
-sudo ln -s /opt/netbox-X.Y.Z/ /opt/netbox
+sudo adduser --system --group netbox
+sudo mkdir -p /opt/netbox
+sudo chown root:netbox /opt/netbox
+sudo chmod 755 /opt/netbox
 ```
 ```
 
 
-!!! note
-    It is recommended to install NetBox in a directory named for its version number. For example, NetBox v4.0.0 would be installed into `/opt/netbox-4.0.0`, and a symlink from `/opt/netbox/` would point to this location. (You can verify this configuration with the command `ls -l /opt | grep netbox`.) This allows for future releases to be installed in parallel without interrupting the current installation. When changing to the new release, only the symlink needs to be updated.
+## Create the Virtual Environment
 
 
-### Option B: Clone the Git Repository
-
-Create the base directory for the NetBox installation. For this guide, we'll use `/opt/netbox`.
+Create a Python virtual environment and update `pip`:
 
 
 ```no-highlight
 ```no-highlight
-sudo mkdir -p /opt/netbox/
-cd /opt/netbox/
+sudo python3 -m venv /opt/netbox/venv
+sudo /opt/netbox/venv/bin/python -m pip install --upgrade pip
 ```
 ```
 
 
-If `git` is not already installed, install it:
+If the default `python3` executable is older than Python 3.12, create the virtual environment with a supported interpreter instead (for example, `sudo python3.12 -m venv /opt/netbox/venv`).
+
+Install the desired NetBox release. Replace `X.Y.Z` with the exact version to install. (Available releases are listed on [PyPI](https://pypi.org/project/netbox/#history).)
 
 
 ```no-highlight
 ```no-highlight
-sudo apt install -y git
+sudo /opt/netbox/venv/bin/python -m pip install "netbox==X.Y.Z"
 ```
 ```
 
 
-Next, clone the git repository:
+Pinning the version makes the installed release explicit and prevents an unintended upgrade when the command is repeated later.
 
 
-```no-highlight
-sudo git clone https://github.com/netbox-community/netbox.git .
-```
+## Scaffold the Instance Root
 
 
-This command should generate output similar to the following:
+Run `netbox setup` to create the local configuration skeleton and copy the bundled deployment examples:
 
 
-```
-Cloning into '.'...
-remote: Enumerating objects: 148317, done.
-remote: Counting objects: 100% (183/183), done.
-remote: Compressing objects: 100% (115/115), done.
-remote: Total 148317 (delta 127), reused 68 (delta 68), pack-reused 148134 (from 3)
-Receiving objects: 100% (148317/148317), 165.12 MiB | 28.71 MiB/s, done.
-Resolving deltas: 100% (116428/116428), done.
+```no-highlight
+sudo /opt/netbox/venv/bin/netbox setup --target /opt/netbox
 ```
 ```
 
 
-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.
+The command creates the following files when they do not already exist:
 
 
+```no-highlight
+/opt/netbox/
+├── conf/
+│   ├── __init__.py
+│   └── configuration.py
+├── contrib/
+│   ├── apache.conf
+│   ├── gunicorn.py
+│   ├── netbox-rq.service
+│   ├── netbox.env
+│   ├── netbox.service
+│   ├── nginx.conf
+│   └── uwsgi.ini
+└── local_requirements.txt
 ```
 ```
-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
+`netbox setup` is intentionally non-destructive: existing files are left untouched. It does not install systemd units, configure an HTTP server, rewrite deployment examples for the local paths, or enable plugins.
 
 
-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.
+Create the directories used for mutable instance data and grant the NetBox service account ownership of them:
 
 
-```
-sudo adduser --system --group netbox
-sudo chown --recursive netbox /opt/netbox/netbox/media/
-sudo chown --recursive netbox /opt/netbox/netbox/reports/
-sudo chown --recursive netbox /opt/netbox/netbox/scripts/
+```no-highlight
+sudo mkdir -p /opt/netbox/{media,reports,scripts,static}
+sudo chown --recursive netbox:netbox \
+    /opt/netbox/media \
+    /opt/netbox/reports \
+    /opt/netbox/scripts \
+    /opt/netbox/static
 ```
 ```
 
 
-## Configuration
+## Configure NetBox
 
 
-Move into the NetBox configuration directory and make a copy of `configuration_example.py` named `configuration.py`. This file will hold all of your local configuration parameters.
+Open the scaffolded configuration file with your preferred editor:
 
 
 ```no-highlight
 ```no-highlight
-cd /opt/netbox/netbox/netbox/
-sudo cp configuration_example.py configuration.py
+sudo ${EDITOR:-vi} /opt/netbox/conf/configuration.py
 ```
 ```
 
 
-Open `configuration.py` with your preferred editor to begin configuring NetBox. NetBox offers [many configuration parameters](../configuration/index.md), but only the following five are required for new installations:
+NetBox offers [many configuration parameters](../configuration/index.md), but only the following five are required for new installations:
 
 
 * `ALLOWED_HOSTS`
 * `ALLOWED_HOSTS`
 * `API_TOKEN_PEPPERS`
 * `API_TOKEN_PEPPERS`
@@ -133,9 +155,9 @@ API_TOKEN_PEPPERS = {
 ```
 ```
 
 
 !!! tip
 !!! tip
-    As with [`SECRET_KEY`](#secret_key) below, you can use the `generate_secret_key.py` script to generate a random pepper:
+    As with [`SECRET_KEY`](#secret_key) below, you can use the `netbox secret-key` command to generate a random pepper. Run it separately for each value so that the pepper and `SECRET_KEY` are independent:
     ```no-highlight
     ```no-highlight
-    python3 ../generate_secret_key.py
+    sudo /opt/netbox/venv/bin/netbox secret-key
     ```
     ```
 
 
 ### DATABASES
 ### DATABASES
@@ -186,111 +208,111 @@ REDIS = {
 
 
 This parameter must be assigned a randomly-generated key employed as a salt for hashing and related cryptographic functions. (Note, however, that it is _never_ directly used in the encryption of secret data.) This key must be unique to this installation and is recommended to be at least 50 characters long. It should not be shared outside the local system.
 This parameter must be assigned a randomly-generated key employed as a salt for hashing and related cryptographic functions. (Note, however, that it is _never_ directly used in the encryption of secret data.) This key must be unique to this installation and is recommended to be at least 50 characters long. It should not be shared outside the local system.
 
 
-A simple Python script named `generate_secret_key.py` is provided in the parent directory to assist in generating a suitable key:
+Generate a suitable key with the installed `netbox secret-key` command:
 
 
 ```no-highlight
 ```no-highlight
-python3 ../generate_secret_key.py
+sudo /opt/netbox/venv/bin/netbox secret-key
 ```
 ```
 
 
 !!! warning "SECRET_KEY values must match"
 !!! warning "SECRET_KEY values must match"
     In the case of a highly available installation with multiple web servers, `SECRET_KEY` must be identical among all servers in order to maintain a persistent user session state.
     In the case of a highly available installation with multiple web servers, `SECRET_KEY` must be identical among all servers in order to maintain a persistent user session state.
 
 
-When you have finished modifying the configuration, remember to save the file.
-
-## Optional Requirements
+### Restrict Access to the Configuration
 
 
-All Python packages required by NetBox are listed in `requirements.txt` and will be installed automatically. NetBox also supports some optional packages. If desired, these packages must be listed in `local_requirements.txt` within the NetBox root directory.
-
-### 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#storages) in `configuration.py`.
+After saving the configuration, restrict access while allowing the NetBox service account to read it:
 
 
 ```no-highlight
 ```no-highlight
-sudo sh -c "echo 'django-storages' >> /opt/netbox/local_requirements.txt"
+sudo chown --recursive root:netbox /opt/netbox/conf
+sudo chmod 750 /opt/netbox/conf
+sudo chmod 640 /opt/netbox/conf/configuration.py
 ```
 ```
 
 
-### Remote Data Sources
+!!! note "Environment-based configuration"
+    Ensure that any environment variables referenced by `configuration.py` are present when running `netbox upgrade`, `netbox createsuperuser`, and other management commands, and provide the same variables to both NetBox services. The copied `contrib/netbox.env` file is an example only and is not loaded automatically.
 
 
-NetBox supports integration with several remote data sources via configurable backends. Each of these requires the installation of one or more additional libraries.
+## Install Optional Packages and Plugins
 
 
-* Amazon S3: [`boto3`](https://boto3.amazonaws.com/v1/documentation/api/latest/index.html)
-* Git: [`dulwich`](https://www.dulwich.io/)
+### Package Extras
 
 
-For example, to enable the Amazon S3 backend, add `boto3` to your local requirements file:
+NetBox provides optional package extras for several common integrations. Each extra installs the additional Python libraries required by an integration:
 
 
-```no-highlight
-sudo sh -c "echo 'boto3' >> /opt/netbox/local_requirements.txt"
-```
-
-!!! info
-    These packages were previously required in NetBox v3.5 but now are optional.
+| Extra | Installs | Purpose |
+|-------|----------|---------|
+| `ldap` | `django-auth-ldap` | [LDAP authentication](6-ldap.md) |
+| `saml2` | `python3-saml` | SAML single sign-on |
+| `remote-auth` | `django-auth-ldap`, `python3-saml` | LDAP authentication and SAML single sign-on |
+| `s3` | `boto3` | Amazon S3 [remote data sources](../features/synchronized-data.md) and [file storage](../configuration/system.md#storages) |
+| `git` | `dulwich` | Git [remote data sources](../features/synchronized-data.md) |
+| `swift` | `django-storage-swift` | OpenStack Swift [file storage](../configuration/system.md#storages) |
+| `sentry` | `sentry-sdk` | [Sentry error reporting](../administration/error-reporting.md) |
 
 
-### Sentry Integration
-
-NetBox may be configured to send error reports to [Sentry](../administration/error-reporting.md) for analysis. This integration requires installation of the `sentry-sdk` Python library.
+To install one or more extras, install NetBox again with the same pinned version, listing the extras in brackets. For example, to install the LDAP and Amazon S3 dependencies:
 
 
 ```no-highlight
 ```no-highlight
-sudo sh -c "echo 'sentry-sdk' >> /opt/netbox/local_requirements.txt"
+sudo /opt/netbox/venv/bin/python -m pip install "netbox[ldap,s3]==X.Y.Z"
 ```
 ```
 
 
-!!! info
-    Sentry integration was previously included by default in NetBox v3.6 but is now optional.
-
-## Run the Upgrade Script
+Remember which extras are in use and specify them again when upgrading. For LDAP authentication, create `ldap_config.py` beside the active configuration file at `/opt/netbox/conf/ldap_config.py` when following the [LDAP configuration guide](6-ldap.md). Give it the same ownership and permissions as `configuration.py`:
 
 
-Once NetBox has been configured, we're ready to proceed with the actual installation. We'll run the packaged upgrade script (`upgrade.sh`) to perform the following actions:
+```no-highlight
+sudo chown root:netbox /opt/netbox/conf/ldap_config.py
+sudo chmod 640 /opt/netbox/conf/ldap_config.py
+```
 
 
-* Create a Python virtual environment
-* Installs all required Python packages
-* Run database schema migrations (skip with `--readonly`)
-* Builds the documentation locally (for offline use)
-* Aggregate static resource files on disk
+### Plugins and Other Python Packages
 
 
-!!! warning
-    If you still have a Python virtual environment active from a previous installation step, disable it now by running the `deactivate` command. This will avoid errors on systems where `sudo` has been configured to preserve the user's current environment.
+Plugins and any other local Python requirements must be installed into the **same virtual environment** as NetBox before running the installation or upgrade tasks. Add each package to `/opt/netbox/local_requirements.txt`, then install the file:
 
 
 ```no-highlight
 ```no-highlight
-sudo /opt/netbox/upgrade.sh
+sudo ${EDITOR:-vi} /opt/netbox/local_requirements.txt
+sudo /opt/netbox/venv/bin/python -m pip install \
+    -r /opt/netbox/local_requirements.txt
 ```
 ```
 
 
-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.)
+Installing a plugin does not enable it. Add the plugin to the `PLUGINS` list in `/opt/netbox/conf/configuration.py` and complete any plugin-specific configuration separately.
+
+## Run the Installation Tasks
+
+Run the `netbox upgrade` command to perform the application installation tasks:
 
 
 ```no-highlight
 ```no-highlight
-sudo PYTHON=/usr/bin/python3.12 /opt/netbox/upgrade.sh
+sudo -u netbox /opt/netbox/venv/bin/netbox upgrade --no-input
 ```
 ```
 
 
-!!! note
-    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.
+The same command is used for both a fresh installation and future upgrades. It performs the following actions:
 
 
-## Create a Super User
+* Applies database schema migrations
+* Traces any missing cable paths
+* Collects static files to be served by the HTTP server
+* Removes stale content types from the database
+* Rebuilds the search index
+* Clears expired user sessions from the database
 
 
-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:
+For a custom instance root, pass `NETBOX_ROOT` explicitly. The virtual environment may remain elsewhere:
 
 
 ```no-highlight
 ```no-highlight
-source /opt/netbox/venv/bin/activate
+sudo -u netbox env NETBOX_ROOT=/srv/netbox \
+    /opt/netbox-venv/bin/netbox upgrade --no-input
 ```
 ```
 
 
-Once the virtual environment has been activated, you should notice the string `(venv)` prepended to your console prompt.
+!!! note
+    To run the command on a node connected to a database in read-only mode, include the `--readonly` option. This skips all tasks that modify the database or filesystem.
+
+## Create a Superuser
 
 
-Next, we'll create a superuser account using the `createsuperuser` Django management command (via `manage.py`). Specifying an email address for the user is not required, but be sure to use a very strong password.
+NetBox does not come with any predefined user accounts. Create a superuser (administrative account) to be able to log into NetBox. Specifying an email address for the user is not required, but be sure to use a very strong password.
 
 
 ```no-highlight
 ```no-highlight
-cd /opt/netbox/netbox
-python3 manage.py createsuperuser
+sudo -u netbox /opt/netbox/venv/bin/netbox createsuperuser
 ```
 ```
 
 
 ## Test the Application
 ## 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.
-
-!!! tip
-    Check that the Python virtual environment is still active before attempting to run the server.
+Start Django's development server temporarily to confirm that NetBox can load its configuration and connect to its dependencies:
 
 
 ```no-highlight
 ```no-highlight
-python3 manage.py runserver 0.0.0.0:8000 --insecure
+sudo -u netbox /opt/netbox/venv/bin/netbox \
+    runserver 0.0.0.0:8000 --insecure
 ```
 ```
 
 
 If successful, you should see output similar to the following:
 If successful, you should see output similar to the following:
@@ -314,3 +336,155 @@ Next, connect to the name or IP of the server (as defined in `ALLOWED_HOSTS`) on
     If the test service does not run, or you cannot reach the NetBox home page, something has gone wrong. Do not proceed with the rest of this guide until the installation has been corrected.
     If the test service does not run, or you cannot reach the NetBox home page, something has gone wrong. Do not proceed with the rest of this guide until the installation has been corrected.
 
 
 Type `Ctrl+c` to stop the development server.
 Type `Ctrl+c` to stop the development server.
+
+## Adapt the Deployment Examples
+
+The files copied to `/opt/netbox/contrib/` reference a source-tree layout and are not rewritten for the package layout. Adapt them before following the Gunicorn, uWSGI, and HTTP server instructions.
+
+For the default paths used in this guide, the following commands remove the source-tree references:
+
+```no-highlight
+sudo sed -i \
+    's| --pythonpath /opt/netbox/netbox||' \
+    /opt/netbox/contrib/netbox.service
+
+sudo sed -i \
+    's|/opt/netbox/venv/bin/python3 /opt/netbox/netbox/manage.py|/opt/netbox/venv/bin/netbox|' \
+    /opt/netbox/contrib/netbox-rq.service
+
+sudo sed -i \
+    's|chdir = netbox|chdir = /opt/netbox|' \
+    /opt/netbox/contrib/uwsgi.ini
+
+sudo sed -i \
+    's|/opt/netbox/netbox/static|/opt/netbox/static|g' \
+    /opt/netbox/contrib/nginx.conf \
+    /opt/netbox/contrib/apache.conf
+```
+
+These changes have the following effect:
+
+| File | Package Installation Change |
+|------|-----------------------------|
+| `netbox.service` | Imports `netbox.wsgi` from the virtual environment without a source-tree `--pythonpath` |
+| `netbox-rq.service` | Runs the RQ worker through the installed `netbox` command instead of `manage.py` |
+| `uwsgi.ini` | Uses the instance root rather than the absent `/opt/netbox/netbox/` source directory |
+| `nginx.conf` and `apache.conf` | Serve collected static files from `/opt/netbox/static/` |
+
+Review every file before installing it. When using a different instance root or virtual environment, update all `WorkingDirectory`, `ExecStart`, `chdir`, virtual environment, and static-file paths accordingly. Also add the following line to the `[Service]` section of both systemd units, replacing the path as needed:
+
+```ini
+Environment=NETBOX_ROOT=/srv/netbox
+```
+
+When using environment-based configuration, reference an appropriate environment file from both systemd units or define the required variables directly in each unit.
+
+## Continue the Installation
+
+With the deployment examples adapted, continue with either [Gunicorn](4a-gunicorn.md) or [uWSGI](4b-uwsgi.md). Then configure an [HTTP server](5-http-server.md) and, if needed, [LDAP authentication](6-ldap.md).
+
+The following pages copy files from `/opt/netbox/contrib/`, so make the package-specific changes above **before** copying those files into their final locations.
+
+## Migrate an Existing Archive or Git Installation
+
+!!! warning "Back up before migrating"
+    Migrating an existing deployment to the Python package changes its filesystem layout and upgrade procedure. Take a complete backup, document the current configuration, and verify a rollback procedure before proceeding.
+
+Deployments installed from a release archive or Git checkout can be migrated to the Python package. This is not an in-place conversion: the procedure below builds a new package-based deployment alongside the existing one, which is retained until the new deployment has been validated.
+
+Python package releases begin with NetBox v4.7. Before migrating an older deployment, first upgrade the existing archive or Git installation to a version that is available as a Python package.
+
+Migrate the layout separately from a NetBox version upgrade. Install the **same NetBox version** that is currently running, validate the package-based deployment, and only then upgrade to a newer release.
+
+The following example keeps the existing `/opt/netbox` installation in place during migration. It uses `/srv/netbox` as the new instance root and `/opt/netbox-venv` for the new virtual environment.
+
+1. Stop the existing NetBox services after completing a backup:
+
+    ```no-highlight
+    sudo systemctl stop netbox netbox-rq
+    ```
+
+2. Create the new virtual environment and install the same NetBox version as the existing deployment:
+
+    ```no-highlight
+    sudo python3 -m venv /opt/netbox-venv
+    sudo /opt/netbox-venv/bin/python -m pip install --upgrade pip
+    sudo /opt/netbox-venv/bin/python -m pip install "netbox==X.Y.Z"
+    ```
+
+3. Scaffold the new instance root and create its mutable directories:
+
+    ```no-highlight
+    sudo mkdir -p /srv/netbox
+    sudo chown root:netbox /srv/netbox
+    sudo chmod 755 /srv/netbox
+    sudo /opt/netbox-venv/bin/netbox setup --target /srv/netbox
+    sudo mkdir -p /srv/netbox/{media,reports,scripts,static}
+    sudo chown --recursive netbox:netbox \
+        /srv/netbox/media \
+        /srv/netbox/reports \
+        /srv/netbox/scripts \
+        /srv/netbox/static
+    ```
+
+4. Copy the active configuration from the existing installation. If `local_requirements.txt` exists, copy it over the empty file created by `netbox setup`:
+
+    ```no-highlight
+    sudo cp /opt/netbox/netbox/netbox/configuration.py \
+        /srv/netbox/conf/configuration.py
+
+    if [ -f /opt/netbox/local_requirements.txt ]; then
+        sudo cp /opt/netbox/local_requirements.txt \
+            /srv/netbox/local_requirements.txt
+    fi
+    ```
+
+    When the existing deployment uses `NETBOX_CONFIGURATION`, copy the active configuration module instead, together with any sibling modules or local files it imports. Review the copied configuration and update any filesystem paths that still reference the old source tree.
+
+    If LDAP is configured, also copy the active `ldap_config.py` to `/srv/netbox/conf/ldap_config.py`.
+
+5. Copy locally stored media, reports, and scripts. Do not copy collected static files; `netbox upgrade` will create them again.
+
+    ```no-highlight
+    sudo cp -a /opt/netbox/netbox/media/. /srv/netbox/media/
+    sudo cp -a /opt/netbox/netbox/reports/. /srv/netbox/reports/
+    sudo cp -a /opt/netbox/netbox/scripts/. /srv/netbox/scripts/
+    sudo chown --recursive netbox:netbox \
+        /srv/netbox/media \
+        /srv/netbox/reports \
+        /srv/netbox/scripts
+    ```
+
+    Use the paths configured by `MEDIA_ROOT`, `REPORTS_ROOT`, and `SCRIPTS_ROOT` instead when the existing deployment stores these files elsewhere.
+
+6. Install all plugins and local requirements into the new virtual environment **before** running the upgrade tasks:
+
+    ```no-highlight
+    sudo /opt/netbox-venv/bin/python -m pip install \
+        -r /srv/netbox/local_requirements.txt
+    ```
+
+    Repeat any [package extras](#package-extras) needed by the deployment, and verify that each plugin supports the installed NetBox version.
+
+7. Secure the configuration and run the package installation tasks against the existing database:
+
+    ```no-highlight
+    sudo chown --recursive root:netbox /srv/netbox/conf
+    sudo chmod 750 /srv/netbox/conf
+    sudo chmod 640 /srv/netbox/conf/configuration.py
+
+    sudo -u netbox env NETBOX_ROOT=/srv/netbox \
+        /opt/netbox-venv/bin/netbox upgrade --no-input
+    ```
+
+    If `ldap_config.py` was copied, also run `sudo chmod 640 /srv/netbox/conf/ldap_config.py`.
+
+8. Follow [Adapt the Deployment Examples](#adapt-the-deployment-examples), substituting `/srv/netbox` and `/opt/netbox-venv` for the example paths. Install the updated systemd and HTTP server configuration, switch the services to the package deployment, and ensure that both systemd units define `NETBOX_ROOT=/srv/netbox`.
+
+9. Start the services, test the web interface and background processing, and retain the previous installation until the new deployment has been validated:
+
+    ```no-highlight
+    sudo systemctl start netbox netbox-rq
+    ```
+
+After the migration is complete, use the [standard upgrade procedure](upgrading.md#upgrade-a-python-package-installation) for future releases.

+ 0 - 361
docs/installation/3b-python-package.md

@@ -1,361 +0,0 @@
-# Install NetBox from the Python Package (Experimental)
-
-!!! warning "Experimental in NetBox v4.7"
-    Installing NetBox from the Python package is experimental in NetBox v4.7 and is **not recommended for production use**. Use this workflow to evaluate the packaged installation, test upgrades and rollback procedures, and provide feedback.
-
-    The established [release archive and Git installation methods](3-netbox.md) remain supported and are not replaced by this workflow.
-
-The Python package installs the NetBox application and its Python dependencies into a virtual environment using `pip`. Configuration, uploaded media, custom scripts and reports, collected static files, and deployment configuration remain outside the installed package.
-
-This installation method does **not** configure PostgreSQL, Redis, a WSGI server, an HTTP server, or system services. These remain administrator-managed deployment tasks, just as they are for an archive or Git installation.
-
-## When to Use This Installation Method
-
-Use the Python package for a new test or evaluation deployment when you want `pip` to manage the NetBox application code in a dedicated virtual environment. While this workflow remains experimental, use a [release archive or Git checkout](3-netbox.md) for production deployments.
-
-A package installation is also available as a migration target for an existing deployment, but it is not an in-place conversion. Follow the [migration procedure](#migrate-an-existing-archive-or-git-installation) only after validating the workflow in a separate environment.
-
-## Understand the Installation Layout
-
-A package installation separates the application code from the files that belong to a particular NetBox instance.
-
-| Component | Example Location | Purpose |
-|-----------|------------------|---------|
-| Application code | `<venv>/lib/pythonX.Y/site-packages/` | Installed and replaced by `pip`; do not modify it directly |
-| Python virtual environment | `/opt/netbox/venv/` | Contains NetBox, its dependencies, and any plugins |
-| Instance root | `/opt/netbox/` | Holds local configuration and mutable instance data |
-| Configuration | `/opt/netbox/conf/configuration.py` | Contains settings and credentials for this instance |
-| Mutable data | `/opt/netbox/{media,reports,scripts,static}/` | Persists independently of package upgrades |
-| Deployment examples | `/opt/netbox/contrib/` | Local copies to review and adapt before use |
-
-The instance root defaults to `/opt/netbox` and may be changed with the `NETBOX_ROOT` environment variable. The virtual environment does not need to be located below the instance root; `/opt/netbox/venv` is used throughout this guide only to keep the example straightforward.
-
-!!! note "Custom instance roots"
-    The `--target` option for `netbox setup` selects where the local files are created. It does not permanently set the instance root. When using a location other than `/opt/netbox`, set `NETBOX_ROOT` for all NetBox commands and services.
-
-## Before You Begin
-
-Complete the [PostgreSQL](1-postgresql.md) and [Redis](2-redis.md) installation steps first. Then install the same [required system packages](3-netbox.md#install-system-packages) used by the archive and Git installation methods.
-
-## Create the System User and Instance Root
-
-Create the `netbox` system account and the default instance root:
-
-```no-highlight
-sudo adduser --system --group netbox
-sudo mkdir -p /opt/netbox
-sudo chown root:netbox /opt/netbox
-sudo chmod 755 /opt/netbox
-```
-
-## Create the Virtual Environment
-
-Create a Python virtual environment and update `pip`:
-
-```no-highlight
-sudo python3 -m venv /opt/netbox/venv
-sudo /opt/netbox/venv/bin/python -m pip install --upgrade pip
-```
-
-Install the desired NetBox release. Replace `X.Y.Z` with the exact version to install:
-
-```no-highlight
-sudo /opt/netbox/venv/bin/python -m pip install "netbox==X.Y.Z"
-```
-
-Pinning the version makes the installed release explicit and prevents an unintended upgrade when the command is repeated later.
-
-## Scaffold the Instance Root
-
-Run `netbox setup` to create the local configuration skeleton and copy the bundled deployment examples:
-
-```no-highlight
-sudo /opt/netbox/venv/bin/netbox setup --target /opt/netbox
-```
-
-The command creates the following files when they do not already exist:
-
-```no-highlight
-/opt/netbox/
-├── conf/
-│   ├── __init__.py
-│   └── configuration.py
-├── contrib/
-│   ├── apache.conf
-│   ├── gunicorn.py
-│   ├── netbox-rq.service
-│   ├── netbox.env
-│   ├── netbox.service
-│   ├── nginx.conf
-│   └── uwsgi.ini
-└── local_requirements.txt
-```
-
-`netbox setup` is intentionally non-destructive: existing files are left untouched. It does not install systemd units, configure an HTTP server, rewrite deployment examples for the local paths, or enable plugins.
-
-Create the directories used for mutable instance data and grant the NetBox service account ownership of them:
-
-```no-highlight
-sudo mkdir -p /opt/netbox/{media,reports,scripts,static}
-sudo chown --recursive netbox:netbox \
-    /opt/netbox/media \
-    /opt/netbox/reports \
-    /opt/netbox/scripts \
-    /opt/netbox/static
-```
-
-## Configure NetBox
-
-Open the scaffolded configuration file:
-
-```no-highlight
-sudo ${EDITOR:-vi} /opt/netbox/conf/configuration.py
-```
-
-Define the five [required configuration parameters](../configuration/required-parameters.md):
-
-* `ALLOWED_HOSTS`
-* `API_TOKEN_PEPPERS`
-* `DATABASES`
-* `REDIS`
-* `SECRET_KEY`
-
-Generate a suitable random value for `SECRET_KEY` with the installed command:
-
-```no-highlight
-sudo /opt/netbox/venv/bin/netbox secret-key
-```
-
-Run the command again to generate an independent value for the first entry in `API_TOKEN_PEPPERS`. Treat both values as sensitive and do not reuse the examples from the documentation.
-
-After saving the configuration, restrict access while allowing the NetBox service account to read it:
-
-```no-highlight
-sudo chown --recursive root:netbox /opt/netbox/conf
-sudo chmod 750 /opt/netbox/conf
-sudo chmod 640 /opt/netbox/conf/configuration.py
-```
-
-!!! note "Environment-based configuration"
-    Ensure that any environment variables referenced by `configuration.py` are present when running `netbox upgrade`, `netbox createsuperuser`, and other management commands, and provide the same variables to both NetBox services. The copied `contrib/netbox.env` file is an example only and is not loaded automatically.
-
-## Install Plugins and Optional Python Packages
-
-Plugins and any other local Python requirements must be installed into the **same virtual environment** as NetBox before running the installation or upgrade tasks. Add each package to `/opt/netbox/local_requirements.txt`, then install the file:
-
-```no-highlight
-sudo ${EDITOR:-vi} /opt/netbox/local_requirements.txt
-sudo /opt/netbox/venv/bin/python -m pip install \
-    -r /opt/netbox/local_requirements.txt
-```
-
-Installing a plugin does not enable it. Add the plugin to the `PLUGINS` list in `/opt/netbox/conf/configuration.py` and complete any plugin-specific configuration separately.
-
-NetBox also provides optional package extras for several common integrations. For example, install the LDAP dependencies together with the same pinned NetBox version as follows:
-
-```no-highlight
-sudo /opt/netbox/venv/bin/python -m pip install "netbox[ldap]==X.Y.Z"
-```
-
-Remember which extras are in use and specify them again when upgrading. For LDAP authentication, create `ldap_config.py` beside the active configuration file at `/opt/netbox/conf/ldap_config.py` when following the [LDAP configuration guide](6-ldap.md). Give it the same ownership and permissions as `configuration.py`:
-
-```no-highlight
-sudo chown root:netbox /opt/netbox/conf/ldap_config.py
-sudo chmod 640 /opt/netbox/conf/ldap_config.py
-```
-
-When using uWSGI, install `pyuwsgi` into the same virtual environment and record it as a local requirement:
-
-```no-highlight
-sudo sh -c "echo 'pyuwsgi' >> /opt/netbox/local_requirements.txt"
-sudo /opt/netbox/venv/bin/python -m pip install pyuwsgi
-```
-
-## Run the Installation Tasks
-
-Run the packaged upgrade command to apply database migrations, collect static files, and perform the remaining application installation tasks:
-
-```no-highlight
-sudo -u netbox /opt/netbox/venv/bin/netbox upgrade --no-input
-```
-
-The `netbox upgrade` command is used for both a fresh package installation and future package upgrades. It replaces the source installation's `upgrade.sh` workflow.
-
-For a custom instance root, pass `NETBOX_ROOT` explicitly. The virtual environment may remain elsewhere:
-
-```no-highlight
-sudo -u netbox env NETBOX_ROOT=/srv/netbox \
-    /opt/netbox-venv/bin/netbox upgrade --no-input
-```
-
-## Create a Superuser
-
-Create the first administrative account:
-
-```no-highlight
-sudo -u netbox /opt/netbox/venv/bin/netbox createsuperuser
-```
-
-## Test the Application
-
-Start Django's development server temporarily to confirm that NetBox can load its configuration and connect to its dependencies:
-
-```no-highlight
-sudo -u netbox /opt/netbox/venv/bin/netbox \
-    runserver 0.0.0.0:8000 --insecure
-```
-
-Connect to the server on port 8000 and log in with the superuser account. Type `Ctrl+c` to stop the development server after testing.
-
-!!! danger "Not for production use"
-    The development server is intended only for installation testing. It is neither performant nor secure enough for production use.
-
-## Adapt the Deployment Examples
-
-The files copied to `/opt/netbox/contrib/` are the same deployment examples shipped for archive and Git installations. They are not rewritten for the package layout. Adapt them before following the shared Gunicorn, uWSGI, and HTTP server instructions.
-
-For the default paths used in this guide, the following commands remove the source-tree references:
-
-```no-highlight
-sudo sed -i \
-    's| --pythonpath /opt/netbox/netbox||' \
-    /opt/netbox/contrib/netbox.service
-
-sudo sed -i \
-    's|/opt/netbox/venv/bin/python3 /opt/netbox/netbox/manage.py|/opt/netbox/venv/bin/netbox|' \
-    /opt/netbox/contrib/netbox-rq.service
-
-sudo sed -i \
-    's|chdir = netbox|chdir = /opt/netbox|' \
-    /opt/netbox/contrib/uwsgi.ini
-
-sudo sed -i \
-    's|/opt/netbox/netbox/static|/opt/netbox/static|g' \
-    /opt/netbox/contrib/nginx.conf \
-    /opt/netbox/contrib/apache.conf
-```
-
-These changes have the following effect:
-
-| File | Package Installation Change |
-|------|-----------------------------|
-| `netbox.service` | Imports `netbox.wsgi` from the virtual environment without a source-tree `--pythonpath` |
-| `netbox-rq.service` | Runs the RQ worker through the installed `netbox` command instead of `manage.py` |
-| `uwsgi.ini` | Uses the instance root rather than the absent `/opt/netbox/netbox/` source directory |
-| `nginx.conf` and `apache.conf` | Serve collected static files from `/opt/netbox/static/` |
-
-Review every file before installing it. When using a different instance root or virtual environment, update all `WorkingDirectory`, `ExecStart`, `chdir`, virtual environment, and static-file paths accordingly. Also add the following line to the `[Service]` section of both systemd units, replacing the path as needed:
-
-```ini
-Environment=NETBOX_ROOT=/srv/netbox
-```
-
-When using environment-based configuration, reference an appropriate environment file from both systemd units or define the required variables directly in each unit.
-
-## Continue the Installation
-
-With the deployment examples adapted, continue with either [Gunicorn](4a-gunicorn.md) or [uWSGI](4b-uwsgi.md). When using uWSGI and you installed `pyuwsgi` above, skip the **Installation** subsection on the uWSGI page and begin with its configuration steps. Then configure an [HTTP server](5-http-server.md) and, if needed, [LDAP authentication](6-ldap.md).
-
-The shared pages copy files from `/opt/netbox/contrib/`, so make the package-specific changes above **before** copying those files into their final locations.
-
-## Migrate an Existing Archive or Git Installation
-
-!!! warning "Experimental migration path"
-    Migrating an existing deployment to the Python package changes its filesystem and upgrade model. Take a complete backup, document the current configuration, and verify a rollback procedure before proceeding.
-
-Python package releases begin with NetBox v4.7. Before migrating an older deployment, first upgrade the existing archive or Git installation to a version that is available as a Python package.
-
-Migrate the layout separately from a NetBox version upgrade. Install the **same NetBox version** that is currently running, validate the package-based deployment, and only then upgrade to a newer release.
-
-The following example keeps the existing `/opt/netbox` installation in place during migration. It uses `/srv/netbox` as the new instance root and `/opt/netbox-venv` for the new virtual environment.
-
-1. Stop the existing NetBox services after completing a backup:
-
-    ```no-highlight
-    sudo systemctl stop netbox netbox-rq
-    ```
-
-2. Create the new virtual environment and install the same NetBox version as the existing deployment:
-
-    ```no-highlight
-    sudo python3 -m venv /opt/netbox-venv
-    sudo /opt/netbox-venv/bin/python -m pip install --upgrade pip
-    sudo /opt/netbox-venv/bin/python -m pip install "netbox==X.Y.Z"
-    ```
-
-3. Scaffold the new instance root and create its mutable directories:
-
-    ```no-highlight
-    sudo mkdir -p /srv/netbox
-    sudo chown root:netbox /srv/netbox
-    sudo chmod 755 /srv/netbox
-    sudo /opt/netbox-venv/bin/netbox setup --target /srv/netbox
-    sudo mkdir -p /srv/netbox/{media,reports,scripts,static}
-    sudo chown --recursive netbox:netbox \
-        /srv/netbox/media \
-        /srv/netbox/reports \
-        /srv/netbox/scripts \
-        /srv/netbox/static
-    ```
-
-4. Copy the active configuration from the existing installation. If `local_requirements.txt` exists, copy it over the empty file created by `netbox setup`:
-
-    ```no-highlight
-    sudo cp /opt/netbox/netbox/netbox/configuration.py \
-        /srv/netbox/conf/configuration.py
-
-    if [ -f /opt/netbox/local_requirements.txt ]; then
-        sudo cp /opt/netbox/local_requirements.txt \
-            /srv/netbox/local_requirements.txt
-    fi
-    ```
-
-    When the existing deployment uses `NETBOX_CONFIGURATION`, copy the active configuration module instead, together with any sibling modules or local files it imports. Review the copied configuration and update any filesystem paths that still reference the old source tree.
-
-    If LDAP is configured, also copy the active `ldap_config.py` to `/srv/netbox/conf/ldap_config.py`.
-
-5. Copy locally stored media, reports, and scripts. Do not copy collected static files; `netbox upgrade` will create them again.
-
-    ```no-highlight
-    sudo cp -a /opt/netbox/netbox/media/. /srv/netbox/media/
-    sudo cp -a /opt/netbox/netbox/reports/. /srv/netbox/reports/
-    sudo cp -a /opt/netbox/netbox/scripts/. /srv/netbox/scripts/
-    sudo chown --recursive netbox:netbox \
-        /srv/netbox/media \
-        /srv/netbox/reports \
-        /srv/netbox/scripts
-    ```
-
-    Use the paths configured by `MEDIA_ROOT`, `REPORTS_ROOT`, and `SCRIPTS_ROOT` instead when the existing deployment stores these files elsewhere.
-
-6. Install all plugins and local requirements into the new virtual environment **before** running the upgrade tasks:
-
-    ```no-highlight
-    sudo /opt/netbox-venv/bin/python -m pip install \
-        -r /srv/netbox/local_requirements.txt
-    ```
-
-    Repeat any NetBox package extras used by the deployment, and verify that each plugin supports the installed NetBox version.
-
-7. Secure the configuration and run the package installation tasks against the existing database:
-
-    ```no-highlight
-    sudo chown --recursive root:netbox /srv/netbox/conf
-    sudo chmod 750 /srv/netbox/conf
-    sudo chmod 640 /srv/netbox/conf/configuration.py
-
-    sudo -u netbox env NETBOX_ROOT=/srv/netbox \
-        /opt/netbox-venv/bin/netbox upgrade --no-input
-    ```
-
-    If `ldap_config.py` was copied, also run `sudo chmod 640 /srv/netbox/conf/ldap_config.py`.
-
-8. Follow [Adapt the Deployment Examples](#adapt-the-deployment-examples), substituting `/srv/netbox` and `/opt/netbox-venv` for the example paths. Install the updated systemd and HTTP server configuration, switch the services to the package deployment, and ensure that both systemd units define `NETBOX_ROOT=/srv/netbox`.
-
-9. Start the services, test the web interface and background processing, and retain the previous installation until the new deployment has been validated:
-
-    ```no-highlight
-    sudo systemctl start netbox netbox-rq
-    ```
-
-After the migration is complete, use the [Python package upgrade procedure](upgrading.md#upgrade-a-python-package-installation-experimental) for future releases.

+ 6 - 6
docs/installation/4a-gunicorn.md

@@ -51,12 +51,12 @@ You should see output similar to the following:
      Memory: 556.1M (peak: 556.3M)
      Memory: 556.1M (peak: 556.3M)
         CPU: 3.387s
         CPU: 3.387s
      CGroup: /system.slice/netbox.service
      CGroup: /system.slice/netbox.service
-             ├─7283 /opt/netbox/venv/bin/python3 /opt/netbox/venv/bin/gunicorn --pid /var/tmp/netbox.pid --pythonpath /opt/netbox/netbox>
-             ├─7285 /opt/netbox/venv/bin/python3 /opt/netbox/venv/bin/gunicorn --pid /var/tmp/netbox.pid --pythonpath /opt/netbox/netbox>
-             ├─7286 /opt/netbox/venv/bin/python3 /opt/netbox/venv/bin/gunicorn --pid /var/tmp/netbox.pid --pythonpath /opt/netbox/netbox>
-             ├─7287 /opt/netbox/venv/bin/python3 /opt/netbox/venv/bin/gunicorn --pid /var/tmp/netbox.pid --pythonpath /opt/netbox/netbox>
-             ├─7288 /opt/netbox/venv/bin/python3 /opt/netbox/venv/bin/gunicorn --pid /var/tmp/netbox.pid --pythonpath /opt/netbox/netbox>
-             └─7289 /opt/netbox/venv/bin/python3 /opt/netbox/venv/bin/gunicorn --pid /var/tmp/netbox.pid --pythonpath /opt/netbox/netbox>
+             ├─7283 /opt/netbox/venv/bin/python3 /opt/netbox/venv/bin/gunicorn --pid /var/tmp/netbox.pid --config /opt/netbox/gunicorn.py>
+             ├─7285 /opt/netbox/venv/bin/python3 /opt/netbox/venv/bin/gunicorn --pid /var/tmp/netbox.pid --config /opt/netbox/gunicorn.py>
+             ├─7286 /opt/netbox/venv/bin/python3 /opt/netbox/venv/bin/gunicorn --pid /var/tmp/netbox.pid --config /opt/netbox/gunicorn.py>
+             ├─7287 /opt/netbox/venv/bin/python3 /opt/netbox/venv/bin/gunicorn --pid /var/tmp/netbox.pid --config /opt/netbox/gunicorn.py>
+             ├─7288 /opt/netbox/venv/bin/python3 /opt/netbox/venv/bin/gunicorn --pid /var/tmp/netbox.pid --config /opt/netbox/gunicorn.py>
+             └─7289 /opt/netbox/venv/bin/python3 /opt/netbox/venv/bin/gunicorn --pid /var/tmp/netbox.pid --config /opt/netbox/gunicorn.py>
 
 
 Jan 26 11:00:00 netbox systemd[1]: Started netbox.service - NetBox WSGI Service.
 Jan 26 11:00:00 netbox systemd[1]: Started netbox.service - NetBox WSGI Service.
 ...
 ...

+ 2 - 8
docs/installation/4b-uwsgi.md

@@ -7,16 +7,10 @@ NetBox runs as a [WSGI application](https://en.wikipedia.org/wiki/Web_Server_Gat
 
 
 ## Installation
 ## Installation
 
 
-Activate the Python virtual environment and install the `pyuwsgi` package using pip:
-
-```no-highlight
-source /opt/netbox/venv/bin/activate
-pip3 install pyuwsgi
-```
-
-Once installed, add the package to `local_requirements.txt` to ensure it is re-installed during future rebuilds of the virtual environment:
+Install the `pyuwsgi` package into NetBox's virtual environment, and add it to `local_requirements.txt` to ensure it is re-installed whenever the virtual environment is rebuilt:
 
 
 ```no-highlight
 ```no-highlight
+sudo /opt/netbox/venv/bin/python -m pip install pyuwsgi
 sudo sh -c "echo 'pyuwsgi' >> /opt/netbox/local_requirements.txt"
 sudo sh -c "echo 'pyuwsgi' >> /opt/netbox/local_requirements.txt"
 ```
 ```
 
 

+ 4 - 2
docs/installation/5-http-server.md

@@ -105,11 +105,13 @@ With NetBox up and running, you may want to extend its capabilities by installin
 * [**NetBox DNS**](https://github.com/sys4/netbox-plugin-dns) — Manage DNS zones, records, and related data as an authoritative source of truth.
 * [**NetBox DNS**](https://github.com/sys4/netbox-plugin-dns) — Manage DNS zones, records, and related data as an authoritative source of truth.
 * [**NetBox BGP**](https://github.com/netbox-community/netbox-bgp) — Document and manage BGP sessions, communities, and routing policies.
 * [**NetBox BGP**](https://github.com/netbox-community/netbox-bgp) — Document and manage BGP sessions, communities, and routing policies.
 
 
-Installing a plugin generally involves adding its Python package to `/opt/netbox/local_requirements.txt`, enabling it in the `PLUGINS` list in `configuration.py`, and running NetBox's upgrade script:
+Installing a plugin generally involves adding its Python package to `/opt/netbox/local_requirements.txt` and installing it into NetBox's virtual environment, enabling it in the `PLUGINS` list in `configuration.py`, running `netbox upgrade`, and restarting the NetBox services:
 
 
 ```no-highlight
 ```no-highlight
 $ sudo sh -c "echo '<package>' >> /opt/netbox/local_requirements.txt"
 $ sudo sh -c "echo '<package>' >> /opt/netbox/local_requirements.txt"
-$ sudo /opt/netbox/upgrade.sh
+$ sudo /opt/netbox/venv/bin/python -m pip install -r /opt/netbox/local_requirements.txt
+$ sudo -u netbox /opt/netbox/venv/bin/netbox upgrade --no-input
+$ sudo systemctl restart netbox netbox-rq
 ```
 ```
 
 
 Each plugin is different and may require additional configuration or setup steps, so always consult the plugin's own documentation as well as NetBox's [plugin installation guide](../plugins/installation.md) before getting started.
 Each plugin is different and may require additional configuration or setup steps, so always consult the plugin's own documentation as well as NetBox's [plugin installation guide](../plugins/installation.md) before getting started.

+ 11 - 11
docs/installation/6-ldap.md

@@ -12,6 +12,16 @@ sudo apt install -y libldap2-dev libsasl2-dev libssl-dev
 
 
 ### Install django-auth-ldap
 ### Install django-auth-ldap
 
 
+=== "Python package"
+
+    Install NetBox's `ldap` optional dependency group, pinned to the installed NetBox version:
+
+    ```no-highlight
+    sudo /opt/netbox/venv/bin/python -m pip install "netbox[ldap]==X.Y.Z"
+    ```
+
+    Specify the `ldap` extra again when upgrading the NetBox package. See the [Python package upgrade procedure](upgrading.md#upgrade-a-python-package-installation).
+
 === "Release archive or Git"
 === "Release archive or Git"
 
 
     Activate the Python virtual environment and install the `django-auth-ldap` package using pip:
     Activate the Python virtual environment and install the `django-auth-ldap` package using pip:
@@ -27,16 +37,6 @@ sudo apt install -y libldap2-dev libsasl2-dev libssl-dev
     sudo sh -c "echo 'django-auth-ldap' >> /opt/netbox/local_requirements.txt"
     sudo sh -c "echo 'django-auth-ldap' >> /opt/netbox/local_requirements.txt"
     ```
     ```
 
 
-=== "Python package (experimental)"
-
-    Install NetBox's `ldap` optional dependency group, pinned to the installed NetBox version:
-
-    ```no-highlight
-    sudo /opt/netbox/venv/bin/python -m pip install "netbox[ldap]==X.Y.Z"
-    ```
-
-    Specify the `ldap` extra again when upgrading the NetBox package. See the [Python package upgrade procedure](upgrading.md#upgrade-a-python-package-installation-experimental).
-
 ## Configuration
 ## Configuration
 
 
 First, enable the LDAP authentication backend in `configuration.py`. (Be sure to overwrite this definition if it is already set to `RemoteUserBackend`.)
 First, enable the LDAP authentication backend in `configuration.py`. (Be sure to overwrite this definition if it is already set to `RemoteUserBackend`.)
@@ -45,7 +45,7 @@ First, enable the LDAP authentication backend in `configuration.py`. (Be sure to
 REMOTE_AUTH_BACKEND = 'netbox.authentication.LDAPBackend'
 REMOTE_AUTH_BACKEND = 'netbox.authentication.LDAPBackend'
 ```
 ```
 
 
-Next, create a file named `ldap_config.py` in the same directory as the active `configuration.py`. This is typically `/opt/netbox/netbox/netbox/` for a release archive or Git installation, or `/opt/netbox/conf/` for a Python package installation. Define all of the parameters required below in `ldap_config.py`. Complete documentation of all `django-auth-ldap` configuration options is included in the project's [official documentation](https://django-auth-ldap.readthedocs.io/).
+Next, create a file named `ldap_config.py` in the same directory as the active `configuration.py`. This is typically `/opt/netbox/conf/` for a Python package installation, or `/opt/netbox/netbox/netbox/` for a release archive or Git installation. Define all of the parameters required below in `ldap_config.py`. Complete documentation of all `django-auth-ldap` configuration options is included in the project's [official documentation](https://django-auth-ldap.readthedocs.io/).
 
 
 For a Python package installation, protect the file while allowing the NetBox service account to read it:
 For a Python package installation, protect the file while allowing the NetBox service account to read it:
 
 

+ 1 - 6
docs/installation/index.md

@@ -18,16 +18,11 @@ The following sections detail how to set up a new instance of NetBox:
 
 
 1. [PostgreSQL database](1-postgresql.md)
 1. [PostgreSQL database](1-postgresql.md)
 2. [Redis](2-redis.md)
 2. [Redis](2-redis.md)
-3. Install the NetBox application using either:
-    * a [release archive or Git checkout](3-netbox.md); or
-    * the [Python package](3b-python-package.md) (experimental)
+3. [NetBox](3-netbox.md) (Python package)
 4. [Gunicorn](4a-gunicorn.md) or [uWSGI](4b-uwsgi.md)
 4. [Gunicorn](4a-gunicorn.md) or [uWSGI](4b-uwsgi.md)
 5. [HTTP server](5-http-server.md)
 5. [HTTP server](5-http-server.md)
 6. [LDAP authentication](6-ldap.md) (optional)
 6. [LDAP authentication](6-ldap.md) (optional)
 
 
-!!! warning "Experimental Python package installation"
-    Installing NetBox from the Python package is experimental in NetBox v4.7 and is not recommended for production use. It is intended for evaluation and feedback. The release archive and Git workflows remain supported and are the established installation methods.
-
 ## Requirements
 ## Requirements
 
 
 | Dependency | Supported Versions |
 | Dependency | Supported Versions |

+ 80 - 80
docs/installation/upgrading.md

@@ -84,10 +84,90 @@ Alternatively, a database administrator can install the extension before upgradi
 CREATE EXTENSION IF NOT EXISTS ltree;
 CREATE EXTENSION IF NOT EXISTS ltree;
 ```
 ```
 
 
+## Upgrade a Python Package Installation
+
+This procedure applies to a deployment installed from the Python package per the [installation guide](3-netbox.md). A package installation does not use `upgrade.sh`; use the installed `netbox upgrade` command instead. For a release archive or Git installation, follow the [procedure below](#upgrade-a-release-archive-or-git-installation).
+
+Complete the preparation steps at the beginning of this page before proceeding.
+
+### 1. Stop the NetBox Services
+
+Stop the web application and background worker services before changing packages in the virtual environment:
+
+```no-highlight
+sudo systemctl stop netbox netbox-rq
+```
+
+### 2. Upgrade NetBox and Local Requirements
+
+Install the target NetBox version into the existing virtual environment. Replace `X.Y.Z` with the exact version being installed:
+
+```no-highlight
+sudo /opt/netbox/venv/bin/python -m pip install --upgrade "netbox==X.Y.Z"
+```
+
+If the deployment uses a package extra, include it in the upgrade command. For example, specify the `ldap` extra again when upgrading a deployment that uses LDAP authentication:
+
+```no-highlight
+sudo /opt/netbox/venv/bin/python -m pip install --upgrade \
+    "netbox[ldap]==X.Y.Z"
+```
+
+Install all plugins and other local Python requirements into the same virtual environment **before** running the NetBox upgrade tasks:
+
+```no-highlight
+sudo /opt/netbox/venv/bin/python -m pip install \
+    -r /opt/netbox/local_requirements.txt
+```
+
+!!! note "Changing the Python version"
+    A virtual environment cannot be moved to a different Python interpreter in place. If the target NetBox release requires another Python version, create a replacement virtual environment, install the target NetBox package and all local requirements into it, and update the service executable paths before restarting NetBox.
+
+### 3. Run the Upgrade Tasks
+
+Run the packaged upgrade command to apply database migrations, collect static files, and perform the remaining application upgrade tasks:
+
+```no-highlight
+sudo -u netbox /opt/netbox/venv/bin/netbox upgrade --no-input
+```
+
+For a non-default instance root or a virtual environment stored elsewhere, use the applicable paths and set `NETBOX_ROOT` explicitly:
+
+```no-highlight
+sudo -u netbox env NETBOX_ROOT=/srv/netbox \
+    /opt/netbox-venv/bin/netbox upgrade --no-input
+```
+
+Ensure that any environment variables referenced by the NetBox configuration are also available when running this command.
+
+### 4. Review the Deployment Configuration
+
+`netbox setup` is not part of a routine upgrade. It leaves existing configuration and deployment examples untouched. To compare the examples bundled with the new package against the local copies without modifying the instance root, scaffold them into a temporary directory:
+
+```no-highlight
+EXAMPLES_DIR=$(mktemp -d)
+/opt/netbox/venv/bin/netbox setup --target "$EXAMPLES_DIR"
+diff --recursive /opt/netbox/contrib "$EXAMPLES_DIR/contrib"
+rm -rf "$EXAMPLES_DIR"
+```
+
+The comparison will also show the package-layout changes made when the deployment examples were first adapted. Distinguish these local changes from updates introduced by the new release, and merge any relevant updates into the administrator-managed systemd, WSGI, and HTTP server configuration.
+
+### 5. Start the NetBox Services
+
+Start the services and verify that both the web application and background workers are operating normally:
+
+```no-highlight
+sudo systemctl start netbox netbox-rq
+```
+
 ## Upgrade a Release Archive or Git Installation
 ## Upgrade a Release Archive or Git Installation
 
 
 The following procedure applies to NetBox installations created from a release archive or Git checkout. Complete the preparation steps above, then use the same installation method that was used for the existing deployment.
 The following procedure applies to NetBox installations created from a release archive or Git checkout. Complete the preparation steps above, then use the same installation method that was used for the existing deployment.
 
 
+!!! tip "Migrating to the Python package"
+    The Python package is the recommended installation method for production deployments. To move an existing release archive or Git installation to the package, follow the [migration procedure](3-netbox.md#migrate-an-existing-archive-or-git-installation) separately from any version upgrade.
+
 ### 1. Install the Latest Release
 ### 1. Install the Latest Release
 
 
 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.
 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.
@@ -209,83 +289,3 @@ Finally, restart the gunicorn and RQ services:
 ```no-highlight
 ```no-highlight
 sudo systemctl restart netbox netbox-rq
 sudo systemctl restart netbox netbox-rq
 ```
 ```
-
-## Upgrade a Python Package Installation (Experimental)
-
-!!! warning "Experimental installation method"
-    Installing NetBox from the Python package is experimental in NetBox v4.7 and is **not recommended for production use**. Test the upgrade and rollback procedures in a non-production environment before relying on them.
-
-This procedure applies only to a deployment created using the [Python package installation method](3b-python-package.md). A package installation does not use `upgrade.sh`; use the installed `netbox upgrade` command instead. For a release archive or Git installation, follow the [procedure above](#upgrade-a-release-archive-or-git-installation).
-
-Complete the preparation steps at the beginning of this page before proceeding.
-
-### 1. Stop the NetBox Services
-
-Stop the web application and background worker services before changing packages in the virtual environment:
-
-```no-highlight
-sudo systemctl stop netbox netbox-rq
-```
-
-### 2. Upgrade NetBox and Local Requirements
-
-Install the target NetBox version into the existing virtual environment. Replace `X.Y.Z` with the exact version being installed:
-
-```no-highlight
-sudo /opt/netbox/venv/bin/python -m pip install --upgrade "netbox==X.Y.Z"
-```
-
-If the deployment uses a package extra, include it in the upgrade command. For example, specify the `ldap` extra again when upgrading a deployment that uses LDAP authentication:
-
-```no-highlight
-sudo /opt/netbox/venv/bin/python -m pip install --upgrade \
-    "netbox[ldap]==X.Y.Z"
-```
-
-Install all plugins and other local Python requirements into the same virtual environment **before** running the NetBox upgrade tasks:
-
-```no-highlight
-sudo /opt/netbox/venv/bin/python -m pip install \
-    -r /opt/netbox/local_requirements.txt
-```
-
-!!! note "Changing the Python version"
-    A virtual environment cannot be moved to a different Python interpreter in place. If the target NetBox release requires another Python version, create a replacement virtual environment, install the target NetBox package and all local requirements into it, and update the service executable paths before restarting NetBox.
-
-### 3. Run the Upgrade Tasks
-
-Run the packaged upgrade command to apply database migrations, collect static files, and perform the remaining application upgrade tasks:
-
-```no-highlight
-sudo -u netbox /opt/netbox/venv/bin/netbox upgrade --no-input
-```
-
-For a non-default instance root or a virtual environment stored elsewhere, use the applicable paths and set `NETBOX_ROOT` explicitly:
-
-```no-highlight
-sudo -u netbox env NETBOX_ROOT=/srv/netbox \
-    /opt/netbox-venv/bin/netbox upgrade --no-input
-```
-
-Ensure that any environment variables referenced by the NetBox configuration are also available when running this command.
-
-### 4. Review the Deployment Configuration
-
-`netbox setup` is not part of a routine upgrade. It leaves existing configuration and deployment examples untouched. To compare the examples bundled with the new package against the local copies without modifying the instance root, scaffold them into a temporary directory:
-
-```no-highlight
-EXAMPLES_DIR=$(mktemp -d)
-/opt/netbox/venv/bin/netbox setup --target "$EXAMPLES_DIR"
-diff --recursive /opt/netbox/contrib "$EXAMPLES_DIR/contrib"
-rm -rf "$EXAMPLES_DIR"
-```
-
-The comparison will also show the package-layout changes made when the deployment examples were first adapted. Distinguish these local changes from updates introduced by the new release, and merge any relevant updates into the administrator-managed systemd, WSGI, and HTTP server configuration.
-
-### 5. Start the NetBox Services
-
-Start the services and verify that both the web application and background workers are operating normally:
-
-```no-highlight
-sudo systemctl start netbox netbox-rq
-```

+ 10 - 9
docs/plugins/installation.md

@@ -7,13 +7,16 @@
 
 
 Download and install the plugin's Python package per its installation instructions. Plugins published via PyPI are typically installed using the [`pip`](https://packaging.python.org/en/latest/tutorials/installing-packages/) command line utility. Be sure to install the plugin within NetBox's virtual environment.
 Download and install the plugin's Python package per its installation instructions. Plugins published via PyPI are typically installed using the [`pip`](https://packaging.python.org/en/latest/tutorials/installing-packages/) command line utility. Be sure to install the plugin within NetBox's virtual environment.
 
 
-For production installations, the recommended method is to add the package to `/opt/netbox/local_requirements.txt` and then run NetBox's upgrade script. This installs the plugin as part of the standard NetBox installation and upgrade process and ensures that it will be reinstalled if the virtual environment is rebuilt.
+The recommended method is to add the package to `/opt/netbox/local_requirements.txt` and then install that file into NetBox's virtual environment. This records the plugin alongside NetBox's other local requirements, so that it can be reinstalled when NetBox is upgraded or the virtual environment is rebuilt.
 
 
 ```no-highlight
 ```no-highlight
 $ sudo sh -c "echo '<package>' >> /opt/netbox/local_requirements.txt"
 $ sudo sh -c "echo '<package>' >> /opt/netbox/local_requirements.txt"
-$ sudo /opt/netbox/upgrade.sh
+$ sudo /opt/netbox/venv/bin/python -m pip install -r /opt/netbox/local_requirements.txt
 ```
 ```
 
 
+!!! note "Release archive and Git installations"
+    For a NetBox installation created from a release archive or Git checkout, add the package to `/opt/netbox/local_requirements.txt`, enable and configure the plugin as described below, then run `sudo /opt/netbox/upgrade.sh` and [restart the services](#restart-wsgi-service). The upgrade script installs the package, applies database migrations, and collects static files.
+
 Installing packages into NetBox's virtual environment requires write permissions to that directory. For installations under `/opt/netbox`, a regular user typically does not have write permissions. Activating the virtual environment does not change file permissions, so a direct `pip install` command may result in a `Permission denied` error.
 Installing packages into NetBox's virtual environment requires write permissions to that directory. For installations under `/opt/netbox`, a regular user typically does not have write permissions. Activating the virtual environment does not change file permissions, so a direct `pip install` command may result in a `Permission denied` error.
 
 
 If you must install a package manually, use one of the following methods. You can switch to a root shell before activating the virtual environment:
 If you must install a package manually, use one of the following methods. You can switch to a root shell before activating the virtual environment:
@@ -58,16 +61,12 @@ PLUGINS_CONFIG = {
 }
 }
 ```
 ```
 
 
-!!! note
-    If you ran `/opt/netbox/upgrade.sh` after enabling and configuring the plugin, the script has already applied database migrations and collected static files. If you ran it only to install the package before enabling the plugin, continue with the migration and static file steps below.
-
 ## Run Database Migrations
 ## Run Database Migrations
 
 
 If the plugin introduces new database models, run the provided schema migrations:
 If the plugin introduces new database models, run the provided schema migrations:
 
 
 ```no-highlight
 ```no-highlight
-(venv) $ cd /opt/netbox/
-(venv) $ python3 netbox/manage.py migrate
+$ sudo -u netbox /opt/netbox/venv/bin/netbox migrate
 ```
 ```
 
 
 !!! tip
 !!! tip
@@ -78,10 +77,12 @@ If the plugin introduces new database models, run the provided schema migrations
 Plugins may package static resources like images or scripts to be served directly by the HTTP front end. Ensure that these are copied to the static root directory with the `collectstatic` management command:
 Plugins may package static resources like images or scripts to be served directly by the HTTP front end. Ensure that these are copied to the static root directory with the `collectstatic` management command:
 
 
 ```no-highlight
 ```no-highlight
-(venv) $ cd /opt/netbox/
-(venv) $ python3 netbox/manage.py collectstatic
+$ sudo -u netbox /opt/netbox/venv/bin/netbox collectstatic --no-input
 ```
 ```
 
 
+!!! tip
+    The `netbox upgrade` command performs both of the steps above, along with NetBox's other routine maintenance tasks, and may be run instead.
+
 ## Restart WSGI Service
 ## Restart WSGI Service
 
 
 Finally, restart the WSGI service and RQ workers to load the new plugin:
 Finally, restart the WSGI service and RQ workers to load the new plugin:

+ 7 - 8
docs/plugins/removal.md

@@ -3,6 +3,9 @@
 !!! warning
 !!! warning
     The instructions below detail the general process for removing a NetBox plugin. However, each plugin is different and may require additional tasks or modifications to the steps below. Always consult the documentation for a specific plugin **before** attempting to remove it.
     The instructions below detail the general process for removing a NetBox plugin. However, each plugin is different and may require additional tasks or modifications to the steps below. Always consult the documentation for a specific plugin **before** attempting to remove it.
 
 
+!!! note "Release archive and Git installations"
+    The `netbox` commands on this page apply to NetBox installed from the Python package. For a release archive or Git installation, run the equivalent `manage.py` command within NetBox's virtual environment instead (for example, `python3 /opt/netbox/netbox/manage.py reindex`).
+
 ## Disable the Plugin
 ## Disable the Plugin
 
 
 Disable the plugin by removing it from the `PLUGINS` list in `configuration.py`.
 Disable the plugin by removing it from the `PLUGINS` list in `configuration.py`.
@@ -19,14 +22,12 @@ Delete the plugin's entry (if any) in the `PLUGINS_CONFIG` dictionary in `config
 Run the `reindex` management command to reindex the global search engine. This will remove any stale entries pertaining to objects provided by the plugin.
 Run the `reindex` management command to reindex the global search engine. This will remove any stale entries pertaining to objects provided by the plugin.
 
 
 ```no-highlight
 ```no-highlight
-$ cd /opt/netbox/
-$ source /opt/netbox/venv/bin/activate
-(venv) $ python3 netbox/manage.py reindex
+$ sudo -u netbox /opt/netbox/venv/bin/netbox reindex
 ```
 ```
 
 
 ## Uninstall its Python Package
 ## Uninstall its Python Package
 
 
-If the plugin was installed by adding it to `/opt/netbox/local_requirements.txt`, remove its package entry from that file first. Otherwise, the package will be reinstalled the next time NetBox's upgrade script is run.
+If the plugin was installed by adding it to `/opt/netbox/local_requirements.txt`, remove its package entry from that file first. Otherwise, the package will be reinstalled the next time NetBox's local requirements are installed, such as during an upgrade.
 
 
 Use `pip` to remove the installed plugin from NetBox's virtual environment:
 Use `pip` to remove the installed plugin from NetBox's virtual environment:
 
 
@@ -47,7 +48,7 @@ $ sudo systemctl restart netbox
 !!! note
 !!! note
     This step is necessary only for plugins which have created one or more database tables (generally through the introduction of new models). Check your plugin's documentation if unsure.
     This step is necessary only for plugins which have created one or more database tables (generally through the introduction of new models). Check your plugin's documentation if unsure.
 
 
-Enter the PostgreSQL database shell (`manage.py dbshell`) to determine if the plugin has created any SQL tables. Substitute `pluginname` in the example below for the name of the plugin being removed. (You can also run the `\dt` command without a pattern to list _all_ tables.)
+Enter the PostgreSQL database shell (`netbox dbshell`) to determine if the plugin has created any SQL tables. Substitute `pluginname` in the example below for the name of the plugin being removed. (You can also run the `\dt` command without a pattern to list _all_ tables.)
 
 
 ```no-highlight
 ```no-highlight
 netbox=> \dt pluginname_*
 netbox=> \dt pluginname_*
@@ -103,9 +104,7 @@ Typically, the Content Type's `app_label` matches the plugin’s name.
 
 
 
 
 ```no-highlight
 ```no-highlight
-$ cd /opt/netbox/
-$ source /opt/netbox/venv/bin/activate
-(venv) $ python3 netbox/manage.py nbshell
+$ sudo -u netbox /opt/netbox/venv/bin/netbox nbshell
 ```
 ```
 
 
 Then, in the shell:
 Then, in the shell:

+ 1 - 2
mkdocs.yml

@@ -99,8 +99,7 @@ nav:
         - Installing NetBox: 'installation/index.md'
         - Installing NetBox: 'installation/index.md'
         - 1. PostgreSQL: 'installation/1-postgresql.md'
         - 1. PostgreSQL: 'installation/1-postgresql.md'
         - 2. Redis: 'installation/2-redis.md'
         - 2. Redis: 'installation/2-redis.md'
-        - 3a. Release Archive or Git: 'installation/3-netbox.md'
-        - 3b. Python Package (Experimental): 'installation/3b-python-package.md'
+        - 3. NetBox: 'installation/3-netbox.md'
         - 4a. Gunicorn: 'installation/4a-gunicorn.md'
         - 4a. Gunicorn: 'installation/4a-gunicorn.md'
         - 4b. uWSGI: 'installation/4b-uwsgi.md'
         - 4b. uWSGI: 'installation/4b-uwsgi.md'
         - 5. HTTP Server: 'installation/5-http-server.md'
         - 5. HTTP Server: 'installation/5-http-server.md'