# NetBox Enterprise Backups (/docs/enterprise/nbe-backups)

























<Callout type="info" title="Embedded Cluster only">
  This guide covers backup procedures for **Embedded Cluster** deployments. For **Helm** deployments, see [Helm Backups](/enterprise/helm/guides/backups).
</Callout>

Much like the NetBox software itself, NetBox Enterprise uses 2 main datastores: PostgreSQL, and Redis.

PostgreSQL is used for the primary model data in NetBox, including sites, facilities, racks, and so on.

Redis is used for internal caching and the task queue.

For each type of datastore you can choose to use a built-in deployment, or configure NetBox Enterprise to use an existing external resource already in your environment.

## External Databases [#external-databases]

<Callout type="info">
  If you are providing your own database(s) for use by NetBox Enterprise, it is expected that you have your own processes for high availability, backup, and restore.
</Callout>

## Using Disaster Recovery for Backups [#using-disaster-recovery-for-backups]

A disaster recovery backup will preserve the complete state of your NetBox Enterprise install, from allocated volumes to databases to custom configuration.

This feature is included in NetBox Enterprise installs, and can be enabled by installing some extra dependencies to your cluster for KOTS installs.

### Backing Up the NetBox Enterprise Installation [#backing-up-the-netbox-enterprise-installation]

1. Navigate to the backup configuration by clicking the &#x2A;^^Backup settings^^* link in the **Disaster Recovery** section of the admin console.
   <img alt="Backup settings" src="__img0" />
2. Input your S3 bucket, credentials, endpoint, and region.<br />
   <img alt="Configure S3" src="__img1" />
3. Click **Update storage settings** -- it will spend a few moments validating that your settings work.<br />
   <img alt="Update storage settings" src="__img2" />
4. Perform a backup by clicking the **Backups** tab, and then clicking **Start backup**.<br />
   <img alt="Start backup" src="__img3" />

### Restoring the NetBox Enterprise Installation [#restoring-the-netbox-enterprise-installation]

1. Download the latest NetBox Enterprise installer following the same instructions you did for a new install, if you haven't already.
2. Run: `./netbox-enterprise restore`
3. Enter the same S3 credentials you use for backups.<br />
   <img alt="S3 Credentials" src="__img4" />
4. Next, it will take a few minutes to bring up the node.
   When it's complete, you will be prompted to continue the restore:<br />
   <img alt="Restore from backup instance?" src="__img5" />
5. Enter `Y` to continue, and the restore will launch the cluster.
6. (Optional) If you plan to have more than one node in the new cluster, you can go to the admin console and configure them when prompted.
7. Enter `continue` to finish bringing the NetBox Enterprise application up.<br />
   <img alt="Continue restore" src="__img6" />
8. It will take a few more minutes to finish bringing the application up, and then you will see "Application restored!"<br />
   <img alt="Application restored!" src="__img7" /><br />
   NetBox Enterprise and the Admin Console should now be completely restored and available as normal.

<!-- ### KOTS Install -->

## Manual Backup and Restore [#manual-backup-and-restore]

Besides disaster recovery, it is also a good idea to keep backups of your data in case you want to view, partially restore, or move your data to another system.

<Callout type="info" title="NetBox Enterprise Namespace">
  The default namespace is `kotsadm`.

  The instructions below default to `kotsadm`, but you can change the `NETBOX_NAMESPACE` variable to match your system.
</Callout>

### Backing Up Your Data [#backing-up-your-data]

Backing up NetBox Enterprise's data manually is reasonably simple, and Kubernetes makes it easy to access them from the command-line.

<Callout type="warn" title="Before You Back Up: Accessing Your Cluster">
  Before you can back anything up, you must first make sure you can access the cluster on the command line.

  See the [advanced tools documentation](/enterprise/nbe-troubleshooting/#command-line-access) for details on connecting to your NetBox Enterprise cluster.
</Callout>

#### Media, Scripts, and Reports [#media-scripts-and-reports]

Runtime files are stored in a volume accessible from the NetBox containers.
To back them up, you can run this:

```shell
NETBOX_NAMESPACE="$(kubectl get deployments \
  -A -l 'app.kubernetes.io/component=netbox' \
  -ojsonpath='{.items[0].metadata.namespace}')" && \
NETBOX_MAIN_POD="$(kubectl get pod \
  -o name \
  -n "${NETBOX_NAMESPACE}" \
  -l 'app.kubernetes.io/component=netbox' \
  | head -n 1 \
  )" && \
kubectl exec "${NETBOX_MAIN_POD}" \
  -n "${NETBOX_NAMESPACE}" \
  -c netbox \
  -- /bin/sh -c ' \
      cd /opt/netbox/netbox && \
      find media scripts reports static -type f > /tmp/files.txt && \
      tar -czf - \
      --owner=0 \
      --group=0 \
      -T /tmp/files.txt' > netbox-data.tar.gz
```

#### Built-In PostgreSQL [#built-in-postgresql]

The built-in PostgreSQL is deployed using the CrunchyData Postgres Operator.

Since the PostgreSQL CLI tools are already available inside the cluster, all we need to do to dump the database is to call into the correct container and run a `pg_dump` there.

To perform a database dump, run these commands:

```shell
NETBOX_NAMESPACE="$(kubectl get deployments \
  -A -l 'app.kubernetes.io/component=netbox' \
  -ojsonpath='{.items[0].metadata.namespace}')" && \
NETBOX_DATABASE_FILE="netbox-enterprise.pgsql" && \
POSTGRESQL_MAIN_POD="$(kubectl get pod \
  -o name \
  -n "${NETBOX_NAMESPACE}" \
  -l 'postgres-operator.crunchydata.com/role=master' \
  | head -n 1 \
  )" && \
EXCLUDE_DATABASES="$(kubectl exec "${POSTGRESQL_MAIN_POD}" \
  -n "${NETBOX_NAMESPACE}" \
  -c database \
  -- \
    psql -t -c "SELECT CONCAT('--exclude-database=', datname) \
      FROM pg_database \
      WHERE datname <> ALL ('{netbox,diode,hydra}')" \
)" && \
kubectl exec "${POSTGRESQL_MAIN_POD}" \
  -n "${NETBOX_NAMESPACE}" \
  -c database \
  -- \
    pg_dumpall \
      $EXCLUDE_DATABASES \
    > "${NETBOX_DATABASE_FILE}"
```

This will create a `netbox-enterprise.pgsql` file in your local directory.
Save it somewhere safe for future restores.

For more details on backing up NetBox databases, see [the official NetBox documentation](https://netboxlabs.com/docs/netbox/en/stable/administration/replicating-netbox/).

#### Cluster Secrets [#diode-and-hydra-secrets-netbox-110-and-up]

A manual database restore is only useful if the rest of the cluster can decrypt the data and authenticate against the restored databases. Back up:

* **Operator-managed secrets**, including the NetBox `SECRET_KEY` and API token peppers, the auto-generated superuser credentials, the Diode OAuth2 client secret, and the Hydra system secret.
* **PGO-managed `pguser` secrets**, which hold the per-user PostgreSQL passwords that match the password hashes inside the `pg_dumpall` output.

Run this set of commands:

```shell
NETBOX_NAMESPACE="$(kubectl get deployments \
  -A -l 'app.kubernetes.io/component=netbox' \
  -ojsonpath='{.items[0].metadata.namespace}')" && \
(
  kubectl get secrets \
    --namespace "${NETBOX_NAMESPACE}" \
    --selector 'app.kubernetes.io/managed-by=netbox-operator' \
    --output name; \
  kubectl get secrets \
    --namespace "${NETBOX_NAMESPACE}" \
    --output name \
    | grep -E '/[^/]+-postgres-pguser-[^/]+$'; \
) | sort -u | while read -r SECRET; do \
  echo "---" && \
  kubectl get "${SECRET}" \
    --namespace "${NETBOX_NAMESPACE}" \
    -o yaml \
  | grep -v -E '^  (creationTimestamp|resourceVersion|uid):'; \
done > netbox-enterprise-secrets.yaml
```

Save the resulting `netbox-enterprise-secrets.yaml` alongside your `netbox-enterprise.pgsql` for future restores. Open the file before stashing it and confirm it contains multiple `kind: Secret` documents -- an empty or single-document file means the selectors did not match anything in your cluster.

#### Admin Console Configuration [#admin-console-configuration]

You can export the current Admin Console configuration as a `ConfigValues` file. This is useful when migrating to a new host or reinstalling, as it captures all your Admin Console settings (database connections, TLS configuration, feature toggles, etc.) in a portable YAML file.

From within the [cluster shell](/enterprise/nbe-troubleshooting/#command-line-access), run:

```shell
kubectl exec deploy/kotsadm -n kotsadm -- \
  /kots get config --current --decrypt --namespace kotsadm \
  > netbox-enterprise-config.yaml
```

The `--decrypt` flag ensures that password fields (like database credentials) are included in plaintext rather than encrypted. Store this file securely alongside your other backups.

To apply a saved configuration to a new install, run:

```shell
kubectl exec -i deploy/kotsadm -n kotsadm -- \
  /kots set config netbox-enterprise \
    --config-file /dev/stdin --deploy --namespace kotsadm \
  < netbox-enterprise-config.yaml
```

### Restoring Your Backups [#restoring-your-backups]

Restoring is almost as simple as backing up.
You just need to put NetBox Enterprise into maintenance mode first.

#### Enabling and Disabling Maintenance Mode [#enabling-and-disabling-maintenance-mode]

1. Put NetBox Enterprise into maintenance mode by going to the *Config* tab and checking the *Enable Maintenance Mode* checkbox.
   <img alt="Enable Maintenance Mode" src="__img8" />
2. Click the "Save config" button at the bottom of the form, and then when the admin console prompts you, click "go to updated version".<br />
   <img alt="Go to updated version" src="__img9" />
3. Confirm that the *New version available* at the top denotes it's a config change, and if so click the "Deploy" button.
   <img alt="Deploy" src="__img10" />

This will shut down NetBox but leave the other NetBox Enterprise infrastructure up, so you can safely restore.

When you are done restoring your data, just follow the same steps, unchecking *Enable Maintenance Mode* and deploying the updated configuration.

#### Media, Scripts, and Reports [#media-scripts-and-reports-1]

To restore media, scripts, and reports, you just need to unpack them into the correct directory inside a NetBox container.

<Callout type="info">
  The backup instructions above back up all three of the `media/`, `scripts/`, and `reports/` subdirectories in one file.

  If you are restoring a backup from another NetBox instance, you might need to change the name of the tarball and the path after the `-C` at the end of this command to unpack your backup into the right location.
</Callout>

```shell
NETBOX_NAMESPACE="$(kubectl get deployments \
  -A -l 'app.kubernetes.io/component=netbox' \
  -ojsonpath='{.items[0].metadata.namespace}')" && \
NETBOX_MAINTENANCE_POD="$(kubectl get pod \
  -o name \
  -n "${NETBOX_NAMESPACE}" \
  -l 'maintenance-mode=true' \
  | head -n 1 \
  )" && \
cat netbox-data.tar.gz | kubectl exec ${NETBOX_MAINTENANCE_POD} \
  -n "${NETBOX_NAMESPACE}" \
  -i \
  -- tar -xvzf - \
    --no-same-owner \
    --no-same-permission \
    -C /opt/netbox/netbox
```

<a id="addreplace-existing-diode-secrets"></a>

#### Cluster Secrets [#diode-and-hydra-secrets-netbox-110-and-up-1]

Restore the secrets **before** the database dump. The operator and PGO need them in place so that pods can decrypt session data, authenticate to Postgres, and serve Diode OAuth flows against the restored data.

```shell
NETBOX_NAMESPACE="$(kubectl get deployments \
  -A -l 'app.kubernetes.io/component=netbox' \
  -ojsonpath='{.items[0].metadata.namespace}')" && \
kubectl apply \
  --server-side \
  --force-conflicts \
  --namespace "${NETBOX_NAMESPACE}" \
  --filename netbox-enterprise-secrets.yaml
```

After applying, restart any pods that mounted the old secret values so they pick up the restored credentials:

```shell
kubectl rollout restart deployment \
  --namespace "${NETBOX_NAMESPACE}" \
  -l 'app.kubernetes.io/managed-by=netbox-operator'
```

## Built-In PostgreSQL [#built-in-postgresql-1]

To restore from a dump file, pipe the `netbox-enterprise.pgsql` created during backup into `psql` in the PostgreSQL pod:

```shell
NETBOX_NAMESPACE="$(kubectl get deployments \
  -A -l 'app.kubernetes.io/component=netbox' \
  -ojsonpath='{.items[0].metadata.namespace}')" && \
NETBOX_DATABASE_FILE="netbox-enterprise.pgsql" && \
DIODE_DEPLOYMENT_COUNT="$(kubectl get deployments -n "${NETBOX_NAMESPACE}" -o name | grep -c diode || :)" && \
HYDRA_DEPLOYMENT_COUNT="$(kubectl get deployments -n "${NETBOX_NAMESPACE}" -o name | grep -c hydra || :)" && \
POSTGRESQL_MAIN_POD="$(kubectl get pod \
  -o name \
  -n "${NETBOX_NAMESPACE}" \
  -l 'postgres-operator.crunchydata.com/role=master' \
  | head -n 1 \
  )" && \
for DB in netbox diode hydra; do
  kubectl exec "${POSTGRESQL_MAIN_POD}" \
    -n "${NETBOX_NAMESPACE}" \
    -c database \
    -- dropdb --if-exists --force "${DB}"; \
done && \
( \
  if [ "${DIODE_DEPLOYMENT_COUNT}" -gt 0 ]; then \
    echo "CREATE DATABASE diode WITH TEMPLATE = template0 ENCODING = 'UTF8';"; \
  fi && \
  if [ "${HYDRA_DEPLOYMENT_COUNT}" -gt 0 ]; then \
    echo "CREATE DATABASE hydra WITH TEMPLATE = template0 ENCODING = 'UTF8';"; \
  fi && \
  echo "CREATE DATABASE netbox WITH TEMPLATE = template0 ENCODING = 'UTF8';"; \
) \
| kubectl exec "${POSTGRESQL_MAIN_POD}" \
  -n "${NETBOX_NAMESPACE}" \
  -i \
  -c database \
    -- psql -d template1 -f- && \
grep -v -E '^(ALTER|CREATE|DROP) (DATABASE|ROLE) ' "${NETBOX_DATABASE_FILE}" \
| kubectl exec "${POSTGRESQL_MAIN_POD}" \
  -n "${NETBOX_NAMESPACE}" \
  -i \
  -c database \
    -- psql -d netbox -f-
```

Following this run the below to ensure all database permissions are correct:

```shell
NETBOX_NAMESPACE="$(kubectl get deployments \
  -A -l 'app.kubernetes.io/component=netbox' \
  -ojsonpath='{.items[0].metadata.namespace}')" && \
POSTGRESQL_MAIN_POD="$(kubectl get pod \
  -o name \
  -n "${NETBOX_NAMESPACE}" \
  -l 'postgres-operator.crunchydata.com/role=master' \
  | head -n 1 \
  )" && \
for DB in $(kubectl exec "${POSTGRESQL_MAIN_POD}" \
  -n "${NETBOX_NAMESPACE}" \
  -c database \
  -- \
    psql -t -c "SELECT datname FROM pg_database WHERE datname IN ('netbox', 'hydra', 'diode');"; \
); do \
  kubectl exec "${POSTGRESQL_MAIN_POD}" \
  -n "${NETBOX_NAMESPACE}" \
  -i \
  -c database \
  -- \
    psql --dbname "${DB}" -e -c "\
      ALTER DATABASE ${DB} OWNER TO ${DB}; \
      GRANT ALL PRIVILEGES ON DATABASE ${DB} TO ${DB}; \
      GRANT CREATE ON SCHEMA public TO ${DB}; \
      GRANT ALL PRIVILEGES ON ALL FUNCTIONS IN SCHEMA public TO ${DB}; \
      GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO ${DB}; \
      GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO ${DB}; \
    "; \
done
```
