GuidesNetwork and VPNNetwork docs with NetBox

Document your network with NetBox and rootless Podman

NetBox 4.7 on Debian 13, the open-source source of truth for networks and server rooms, in rootless Podman with PostgreSQL and Valkey under a user of its own behind Caddy, with sites, racks, cables, IP addresses, an API and backups.

Tested on NetBox 4.7.3 on Debian 13 (trixie) on a Melonslab server Updated October 14, 2026

Recommended server for this guide

SSD RAID 1 · ECC DDR4 · 10 Gbit

VC-P Alloy · 2 vCPU · 8 GB Memory · 60 GB Storage

Month to month, no lock-in 7-day money-back guarantee

These steps were tested on VC-P Titanium. This uses so little that VC-P Alloy, with the same number of vCPUs and memory on an older CPU, is enough at a small scale and costs less.

€8.99/mo

Deploy now
On this page

What you will set up

NetBox keeps track of what your network and server rooms contain and how it fits together: sites, racks and what is mounted where, devices and their interfaces, the cables between them, and the IP addresses, prefixes and VLANs in use. It is meant to be the one place where that is written down, the source of truth that people look things up in and scripts read from, instead of spreadsheets that drift apart. Everything is in a web interface and in a REST API, and every change is logged.

NetBox was started by Jeremy Stretch at DigitalOcean and published as open source in 2016. Today it is developed in the open on GitHub by NetBox Labs, an American company, with its community. NetBox itself is open source under the Apache 2.0 licence, with no feature limits. NetBox Labs sells two things on top, checked on netboxlabs.com on 14 October 2026: NetBox Cloud, which is NetBox run by them, with a free plan for up to 100 devices and 500 IP addresses and without plugins, webhooks or custom scripts, and paid plans with SSO, backups and support; and NetBox Enterprise, which you run yourself, with an installer, built-in backup and restore, single sign-on, certified plugins, support, and an Air Gap edition for networks without internet access. They also sell separate products that work with NetBox: Discovery, which finds devices on your network, Assurance, which compares the network with what NetBox says, and Copilot, an AI assistant that runs as their cloud service. None of that is needed for what this guide does.

NetBox Labs publish no container image of their own. This guide uses the one from the netbox-docker project, run by volunteers in the netbox-community organisation on GitHub, also under Apache 2.0. Its tag v4.7 follows every NetBox 4.7 release.

NetBox needs PostgreSQL for its data, and Redis for its task queue and cache. Its documentation asks for Redis 6.0 or later and does not mention Valkey, the open-source fork of Redis, but netbox-docker ships with Valkey and that is what this guide uses. It worked throughout our tests.

Here NetBox runs as a pod under a user of its own called netbox, with four containers: PostgreSQL, Valkey, NetBox's web server, and a worker that runs background jobs such as webhooks. Earlier versions of netbox-docker had a fifth, housekeeping container; NetBox now does that itself, as a daily job in the worker. Caddy from the Podman guide is in front.

Every step below was run on a fresh Melonslab VC-P Titanium (4 vCPU, 16 GB) with Debian 13:

  • NetBox 4.7.3 started with PostgreSQL 18 and Valkey 9.1. The first admin was created and tested over an SSH tunnel before Caddy was set up.
  • Without a login, every page sent visitors to the login page, uploaded images too, and the API answered 403.
  • A site, a rack, three devices with interfaces from imported device types, two cables, a VLAN, a prefix and IP addresses were created, in the web interface and by CSV and YAML import. NetBox showed the next free address, and the API handed it out.
  • A colleague in a read-only group could see everything in the inventory, and got 403 when trying to change anything.
  • An API token worked from outside. A token limited to certain addresses was refused from others, also when the request claimed another address, once Caddy set the header as in step 5.
  • An event rule sent a webhook for each new IP address.
  • A capture of the server's traffic showed NetBox contacting NetBox Labs for usage statistics, news and the plugin list. With ISOLATED_DEPLOYMENT=true it made no outside connections at all, while webhooks still went out.
  • The Topology Views plugin was built into the image and drew the devices and cables.
  • An update from NetBox 4.6.10 to 4.7.3 ran its database migrations in about three minutes. NetBox was restored from a backup for a new user, with the same data, users, images and API tokens, and everything came back by itself after a reboot.

The pod used about 1.5 GB of memory, most of it the four web server processes.

Before you start

You need:

  • a server set up as in the Podman guide, with Caddy running;
  • an A record and an AAAA record for netbox.example.com pointing at your server.

The examples use netbox.example.com for NetBox, 203.0.113.10 for your server's IPv4 address, anna for your own account and erik for a colleague. Replace them throughout.

1. Create the user

As root:

useradd -m -s /bin/bash netbox
loginctl enable-linger netbox
machinectl shell netbox@

Everything up to step 5 runs as netbox.

2. Create the secrets

openssl rand -base64 48 | tr -d '\n' | podman secret create netbox-secret-key -
openssl rand -base64 48 | tr -d '\n' | podman secret create netbox-api-pepper -
openssl rand -hex 24 | tr -d '\n' | podman secret create netbox-db-password -

The first is NetBox's secret key, which signs logins and sessions. The second is the pepper NetBox mixes into API tokens before it stores their hashes: without it, the tokens you create in step 10 stop working, so step 15 saves a copy of both. The third is the database password. All three are stored by Podman, not in the files below.

3. Define the pod

mkdir -p ~/.config/containers/systemd
cd ~/.config/containers/systemd

Create netbox.pod:

[Pod]
PodName=netbox
# Only Caddy, on this server, can reach NetBox: the port is not open to the internet.
PublishPort=127.0.0.1:8190:8080

[Install]
WantedBy=default.target

Create netbox-db.container:

[Container]
ContainerName=netbox-db
Image=docker.io/library/postgres:18-alpine
Pod=netbox.pod
Volume=netbox-db:/var/lib/postgresql
Environment=POSTGRES_DB=netbox POSTGRES_USER=netbox POSTGRES_PASSWORD_FILE=/run/secrets/db_password
Secret=netbox-db-password,target=db_password
HealthCmd=pg_isready -U netbox -d netbox
HealthInterval=10s
Notify=healthy
AutoUpdate=registry

[Service]
Restart=always

Create netbox-valkey.container:

[Container]
ContainerName=netbox-valkey
Image=docker.io/valkey/valkey:9.1-alpine
Pod=netbox.pod
Volume=netbox-valkey:/data
Exec=valkey-server --appendonly yes
HealthCmd=valkey-cli ping
HealthInterval=10s
Notify=healthy
AutoUpdate=registry

[Service]
Restart=always

Create netbox.container:

[Unit]
Requires=netbox-db.service netbox-valkey.service
After=netbox-db.service netbox-valkey.service

[Container]
ContainerName=netbox
Image=docker.io/netboxcommunity/netbox:v4.7
Pod=netbox.pod
User=netbox
Group=root
EnvironmentFile=%h/netbox.env
Secret=netbox-secret-key,target=secret_key
Secret=netbox-db-password,target=db_password
Secret=netbox-api-pepper,target=api_token_pepper_1
Volume=netbox-media:/opt/netbox/netbox/media
Volume=netbox-scripts:/opt/netbox/netbox/scripts
HealthCmd=curl -sf http://localhost:8080/login/ -o /dev/null
HealthInterval=15s
Notify=healthy
AutoUpdate=registry

[Service]
Restart=always
# The first start, and an update, can spend minutes on database migrations.
TimeoutStartSec=1800

And netbox-worker.container:

[Unit]
Requires=netbox.service
After=netbox.service

[Container]
ContainerName=netbox-worker
Image=docker.io/netboxcommunity/netbox:v4.7
Pod=netbox.pod
User=netbox
Group=root
EnvironmentFile=%h/netbox.env
Secret=netbox-secret-key,target=secret_key
Secret=netbox-db-password,target=db_password
Secret=netbox-api-pepper,target=api_token_pepper_1
Volume=netbox-media:/opt/netbox/netbox/media
Volume=netbox-scripts:/opt/netbox/netbox/scripts
Exec=/opt/netbox/venv/bin/python /opt/netbox/netbox/manage.py rqworker
AutoUpdate=registry

[Service]
Restart=always

Both NetBox containers read the rest of their settings from one file. Create ~/netbox.env:

ALLOWED_HOSTS=netbox.example.com
TIME_ZONE=Europe/Stockholm
MEDIA_ROOT=/opt/netbox/netbox/media
DB_HOST=127.0.0.1
DB_NAME=netbox
DB_USER=netbox
REDIS_HOST=127.0.0.1
SKIP_SUPERUSER=true
ISOLATED_DEPLOYMENT=true

What the settings do:

  • The image reads each secret from a file in /run/secrets, named as in target=. That is where Podman puts them.
  • ALLOWED_HOSTS is the name NetBox answers to; a request for any other name gets "400 Bad Request". The image adds localhost by itself, for its own checks and for the SSH tunnel in step 4.
  • TIME_ZONE shows times in Swedish time.
  • MEDIA_ROOT must be set: without it, the image looks for uploads in a directory NetBox cannot write to, and uploading an image fails with a permission error.
  • ISOLATED_DEPLOYMENT=true stops NetBox from contacting NetBox Labs. Step 13 has the details.
  • SKIP_SUPERUSER=true stops the image from creating an admin account with a default password. You create your own in step 4.
  • Every NetBox container is on the same pod, so they reach PostgreSQL and Valkey on 127.0.0.1, and nothing outside the pod can. Valkey keeps the task queue on disk with --appendonly yes, so queued webhooks survive a restart.
  • The web server runs as the netbox user inside the container, as netbox-docker intends. The netbox-media volume holds uploaded images and files, and netbox-scripts any custom scripts you upload. Everything else is in the database.
  • The worker runs the background jobs: webhooks, scripts, and NetBox's daily housekeeping, which removes expired sessions and old change log entries.
  • PostgreSQL stays on 18 and Valkey on 9.1, and AutoUpdate=registry brings in their bug-fix releases. NetBox 4.7 needs PostgreSQL 15 or later.

Start it:

systemctl --user daemon-reload
systemctl --user start netbox-pod
systemctl --user enable --now podman-auto-update.timer

The first start downloads about 1 GB of images and then builds the database: the whole first start took ten minutes in our test. Follow it with journalctl --user -fu netbox. It is ready when the log says Initialisation is done and this prints 200:

curl -s -o /dev/null -w '%{http_code}\n' http://localhost:8190/login/

4. Create the first admin

podman exec -it netbox /opt/netbox/netbox/manage.py createsuperuser

Give a username, such as anna, your email address and a password. NetBox wants at least 12 characters, with upper and lower case letters and a digit, and asks whether to bypass that if the password is weaker: answer N and pick another.

Before NetBox goes online, check the account from your own computer through an SSH tunnel:

ssh -L 8190:127.0.0.1:8190 root@203.0.113.10

While that connection is open, http://localhost:8190 in your browser is NetBox on the server. Log in, then close the tunnel with exit.

5. Put Caddy in front

Go back to root with exit, switch to machinectl shell caddy@, and add this block at the end of ~/Caddyfile:

netbox.example.com {
    reverse_proxy 127.0.0.1:8190 {
        header_up X-Real-IP {remote_host}
    }
}

Restart Caddy with systemctl --user restart caddy, and open https://netbox.example.com.

NetBox takes the visitor's address from the X-Real-IP header first. Caddy does not set it by itself, so without the header_up line anyone could send their own and claim any address, which matters for API tokens limited to certain addresses (step 10). In our test, such a token accepted a forged header without the line, and refused it with the line in place.

6. Check who can get in

NetBox 4.7 always requires a login: a visitor without one is sent to the login page, and the API answers 403. Uploaded images need a login too. The old LOGIN_REQUIRED setting, which could turn that off, is deprecated, and NetBox 5.0 removes it; leave it out.

There is no sign-up page. You create every account yourself (step 9), and a user who forgets their password gets a new one from you: NetBox has no password reset by email. It only sends email for errors, to administrators listed in its ADMINS setting, which this guide leaves empty, so there is no email to set up.

NetBox can also leave logins to a single sign-on service, such as authentik, over OpenID Connect or SAML, or to LDAP. That is set with the REMOTE_AUTH_BACKEND and SOCIAL_AUTH_ settings in netbox-docker's documentation. We did not test it here.

7. Model a small server room

The menus on the left follow NetBox's own order: a site holds racks, a rack holds devices, devices have interfaces, and cables join interfaces. Everything you create shows up in the search at the top.

  1. Organization > Sites > Add: name Stockholm DC1, status Active, and the time zone. Create.
  2. Racks > Racks > Add: site Stockholm DC1, name R01. A 42U, 19-inch rack is the default. Create.
  3. Devices > Manufacturers > Add: name Generic. Create.

A device type describes a model of equipment once, with its height and its ports, so every device of that type gets them. Under Devices > Device Types, choose Import, paste this, set Format to YAML and choose Submit:

manufacturer: Generic
model: Switch 8
slug: generic-switch-8
u_height: 1
interfaces:
  - name: port1
    type: 1000base-t
  - name: port2
    type: 1000base-t
  - name: port3
    type: 1000base-t
  - name: port4
    type: 1000base-t
---
manufacturer: Generic
model: Server 1U
slug: generic-server-1u
u_height: 1
interfaces:
  - name: eth0
    type: 1000base-t
  - name: eth1
    type: 1000base-t

For real equipment, the community's device type library on GitHub, netbox-community/devicetype-library, has files like these for thousands of models, which you paste the same way.

Most lists have an Import button that takes CSV. Under Devices > Device Roles > Import, paste:

name,slug,color
Switch,switch,2196f3
Server,server,4caf50

And under Devices > Devices > Import:

name,role,manufacturer,device_type,site,rack,position,face,status
sw1,Switch,Generic,Switch 8,Stockholm DC1,R01,42,front,active
web1,Server,Generic,Server 1U,Stockholm DC1,R01,40,front,active
db1,Server,Generic,Server 1U,Stockholm DC1,R01,39,front,active

The rack's page now draws the three devices at their heights, and each device has the interfaces of its type. An import either creates every row or none: if one row is wrong, NetBox shows the error and nothing is saved. Each import page lists the columns it accepts below the form.

To connect a cable, open sw1, go to its Interfaces tab, and on the row for port1 open the green Connect cable button and choose Interface. Pick device web1 and interface eth0, give the cable a label such as C001 and a type, and choose Create. The second cable comes by CSV, under Connections > Cables > Import:

side_a_device,side_a_type,side_a_name,side_b_device,side_b_type,side_b_name,type,status,label
sw1,dcim.interface,port2,db1,dcim.interface,eth0,cat6,connected,C002

Each interface now shows what it is connected to, at the other end of which cable.

To attach a photo of the rack, open it and choose Attach an image. Images go in the netbox-media volume.

8. IP addresses and VLANs

  1. IPAM > VLANs > Add: VID 10, name Servers, status Active, site Stockholm DC1. Create.
  2. IPAM > Prefixes > Add: prefix 10.10.10.0/24, status Active, Scope DCIM > Site and Stockholm DC1, VLAN Servers, a description such as Server LAN. Create.

The prefix's page shows how much of it is used, and under First available IP the next free address, 10.10.10.1/24. Selecting it opens a new IP address with that address filled in: give it the description Gateway and choose Create. The IP Addresses tab on the prefix lists the used addresses with the free ranges between them.

To give a server its address, add another IP address from the same link, and under Assignment pick device web1 and interface eth0, and tick Make this the primary IP for the device/VM. The device's page then shows it as its primary IPv4 address.

9. Users, groups and permissions

A user who is not a superuser can do nothing until a permission allows it. Permissions are given to groups, so give the colleague a group. Under Admin > Authentication:

  1. Groups > Add: name Read-only. Create.
  2. Permissions > Add: name View inventory. Under Object types, select every type in the Circuits, DCIM, IPAM, Tenancy, Virtualization, VPN and Wireless groups in the Available list (hold Shift to select several) and move them to Selected with the green button. Under Actions, tick Can view only, and under Assignment, pick the group Read-only. Create.
  3. Users > Add: username erik, a password, and the group Read-only. Create.

Erik can now open every device, rack, cable and address, but gets "403 Forbidden" when he tries to add or change anything, and cannot see users or permissions. The Core, Extras and Users groups are left out on purpose: they hold jobs, scripts, webhooks, users and tokens. A permission can also be limited to certain objects with Constraints, such as one site only. We did not test that.

NetBox is not translated into Swedish. Each user can choose one of its 17 languages, or the theme, under Preferences in the user menu at the top right.

10. Use the REST API

Scripts and other tools read and write NetBox through its REST API, with a token. In the user menu, choose API Tokens > Add a Token, keep Version at v2, tick Write enabled if the token should be able to change things, and choose Create. NetBox shows the token once, starting with nbt_; copy it then.

From any computer, with your token in place of nbt_…:

TOKEN='nbt_…'
curl -s -H "Authorization: Bearer $TOKEN" "https://netbox.example.com/api/ipam/prefixes/?prefix=10.10.10.0/24"

The answer has the prefix's id, here 1. Ask for its next free address:

curl -s -H "Authorization: Bearer $TOKEN" "https://netbox.example.com/api/ipam/prefixes/1/available-ips/?limit=1"

Or take it in the same call, so two scripts never get the same one:

curl -s -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{"description": "mail1", "dns_name": "mail1.example.com"}' \
  https://netbox.example.com/api/ipam/prefixes/1/available-ips/

NetBox answers with the new address, in our test 10.10.10.3/24, now saved as active. https://netbox.example.com/api/schema/swagger-ui/ describes every call. A token can be limited to certain addresses in its Allowed IPs field, and given an expiry date. It has the same rights as its user, so give a script a user of its own with only the permissions it needs.

11. Webhooks and event rules

An event rule makes NetBox act when something changes, for example call a webhook, another system's address, when an IP address is created. To see what NetBox sends, start its test receiver as netbox, in a second SSH session:

podman exec -it netbox /opt/netbox/netbox/manage.py webhook_receiver

It listens on port 9000 inside the pod. Then, under Operations > Integrations:

  1. Webhooks > Add: name Test receiver, URL http://127.0.0.1:9000/, method POST, and as Body template:
    {"text": "IP address {{ data.address }} was {{ event }} by {{ request.user }}"}
    

    Create.
  2. Event Rules > Add: name New IP addresses, object type IPAM > IP Address, event Object created, action type Webhook, webhook Test receiver. Create.

Create an IP address, by hand or with the API call above, and the receiver prints the request a second later, with "text": "IP address 10.10.10.4/24 was created by anna". Stop it with Ctrl+C. Use 127.0.0.1 rather than localhost in the URL: localhost is the IPv6 address in the container, where the receiver does not listen.

For real use, point the webhook at a service that takes it, such as a topic on ntfy or an automation in n8n. If that service runs on this server, add AddHost=ntfy.example.com:host-gateway under [Pod] in netbox.pod, as the Podman guide explains. The worker sends the webhooks, and failed ones are listed under Admin > System > Background Tasks, where you can send them again. Only let people you trust create webhooks: their templates run on the server.

12. The change log

Every change, in the web interface, by import or through the API, is recorded with who made it, when, and what the object looked like before and after. Operations > Logging > Change Log lists them all, and each object has a Changelog tab of its own. An import or a bulk edit shares one request ID, so you can see everything it changed together.

NetBox keeps changes for 90 days. To keep them longer, add CHANGELOG_RETENTION=365 to ~/netbox.env, or 0 to keep them forever, and restart as below.

systemctl --user restart netbox netbox-worker

13. Outside connections

We captured the server's DNS lookups and outgoing connections while NetBox started, while its pages were used and while its daily housekeeping ran. Without ISOLATED_DEPLOYMENT=true, NetBox made three kinds:

  • The daily housekeeping job sent census data to census.netbox.oss.netboxlabs.com: the NetBox version, the Python version and a random ID, so NetBox Labs can count installations. CENSUS_REPORTING_ENABLED=false stops only that.
  • The NetBox News panel on the home page made the server fetch news from api.netbox.oss.netboxlabs.com every four hours.
  • Admin > System > Plugins made the server fetch NetBox Labs' list of plugins from the same address.

Two more are off unless you turn them on. NetBox Copilot, NetBox Labs' AI assistant, is off for every user until they switch it on under Preferences; then their browser loads it from static.copilot.netboxlabs.ai, and what they ask it goes to NetBox Labs. The check for new NetBox releases is off in this image, and turned on with RELEASE_CHECK_URL=https://api.github.com/repos/netbox-community/netbox/releases, which makes the server ask GitHub.

ISOLATED_DEPLOYMENT=true turns all of these off, and with it our capture showed no outside connections at all. The NetBox News panel then says "This RSS feed requires an external connection"; remove it from your home page with its ✕. It also hides the links to NetBox Labs' cloud and enterprise offers in the menu. Webhooks still go out, to the addresses you give them.

14. Add a plugin

Plugins add features to NetBox, and must be installed into the image. As netbox, make a directory for a small image of your own:

mkdir -p ~/netbox-plugins
cd ~/netbox-plugins

Create Containerfile, here with the Topology Views plugin, which draws your devices and cables as a map:

FROM docker.io/netboxcommunity/netbox:v4.7
RUN uv pip install netbox-topology-views==4.7.0
COPY plugins.py /etc/netbox/config/plugins.py
RUN mkdir -p /opt/netbox/netbox/static/netbox_topology_views/img && \
    DEBUG=true SECRET_KEY=only-used-while-building-only-used-while-building-xx \
    python /opt/netbox/netbox/manage.py collectstatic --no-input

And plugins.py:

PLUGINS = ["netbox_topology_views"]

Build it:

podman build --pull=newer -t localhost/netbox-plugins:v4.7 .

The SECRET_KEY there is only used to collect the plugin's files while building, and is not your real key. Then, in both netbox.container and netbox-worker.container, change two lines:

Image=localhost/netbox-plugins:v4.7
AutoUpdate=local

And restart:

systemctl --user daemon-reload
systemctl --user restart netbox netbox-worker

NetBox creates the plugin's tables when it starts, and it shows under Admin > System > Plugins. Under Topology Views > Topology, pick the site, tick Show Cables and choose Search to see the switch with the two servers.

Each plugin release works with certain NetBox versions only, which its page lists. Pin the version, as above, and check that a new one exists before you move to a new NetBox version (step 16).

15. Back up

As netbox:

umask 077
mkdir -p ~/backup
podman exec netbox-db pg_dump -U netbox netbox > ~/backup/netbox-db.sql
podman volume export netbox-media > ~/backup/netbox-media.tar
podman volume export netbox-scripts > ~/backup/netbox-scripts.tar
for s in netbox-secret-key netbox-api-pepper; do podman secret inspect --showsecret --format '{{.SecretData}}' $s > ~/backup/$s.txt; done

That is everything NetBox needs: the database, with all objects, users, permissions, tokens and the change log, the uploaded images and scripts, and the two secrets. The API tokens only work with the pepper they were made with. The dump runs while NetBox keeps working. Valkey holds only the cache and the task queue, which NetBox rebuilds. Copy ~/backup to another machine, for example with restic, and store it safely: the database holds your whole network map.

To restore on a new server, follow steps 1 to 3, but create the first two secrets from the backup instead of new ones, and do not start the pod yet:

tr -d '\n' < ~/backup/netbox-secret-key.txt | podman secret create netbox-secret-key -
tr -d '\n' < ~/backup/netbox-api-pepper.txt | podman secret create netbox-api-pepper -
openssl rand -hex 24 | tr -d '\n' | podman secret create netbox-db-password -

If you used a plugin, build the same image as in step 14. Then load the backup into empty volumes:

systemctl --user daemon-reload
for v in media scripts; do podman volume create netbox-$v; podman volume import netbox-$v ~/backup/netbox-$v.tar; done
systemctl --user start netbox-db
podman exec -i netbox-db psql -q -o /dev/null -U netbox -d netbox < ~/backup/netbox-db.sql
systemctl --user start netbox-pod
systemctl --user enable --now podman-auto-update.timer

Starting only the database first loads the backup before NetBox sets up an empty one. Skip step 4: your accounts are in the backup. To restore on the same server, first stop the pod with systemctl --user stop netbox-pod and remove the old volumes with podman volume rm netbox-db netbox-valkey netbox-media netbox-scripts.

16. Update

podman auto-update checks once a day for new images of NetBox, PostgreSQL and Valkey, and restarts the pod when one has changed. The v4.7 tag gets every NetBox 4.7 bug-fix release. To update now:

podman auto-update

A new minor version, such as 4.8, changes the database and can drop old settings, so it is a step you take yourself:

  1. Read the release notes on GitHub, netbox-community/netbox, for the breaking changes.
  2. Take a backup as in step 15.
  3. Change v4.7 to the new version in netbox.container and netbox-worker.container, or in the Containerfile if you use plugins, with plugin versions that support it, and build again.
  4. Restart:
systemctl --user daemon-reload
systemctl --user restart netbox netbox-worker

NetBox runs its database migrations when it starts. From 4.6.10 to 4.7.3 that took three minutes in our test, during which the web interface was down; follow it with journalctl --user -fu netbox. Within NetBox 4 you can skip minor versions; NetBox 5.0 will need the last 4.x release first. Let the background jobs finish first: the 4.7 release notes warn that queued webhooks from the old version fail after the update.

With plugins, the daily auto-update does not fetch new NetBox images. Build the image again with the command from step 14 to get the latest 4.7 release, and run podman auto-update, which restarts the containers on the new image.

Troubleshooting

NetBox does not answer for several minutes after the first start or an update. It is building or migrating its database, and systemctl --user status netbox shows activating until it is done. journalctl --user -fu netbox shows each migration. The service only fails after 30 minutes, the TimeoutStartSec in netbox.container.

"Bad Request (400)". The name in the address bar is not in ALLOWED_HOSTS. Fix ~/netbox.env and restart.

Uploading an image fails with "A file permission error was detected" and /etc/netbox/media. MEDIA_ROOT is missing from ~/netbox.env.

The log keeps warning that "LOGIN_REQUIRED is deprecated". netbox-docker's own configuration still sets it, and NetBox warns on every start. It is harmless, and logins are still required.

"Password must have at least one uppercase letter." NetBox's password rules apply to every account: 12 characters or more, with upper and lower case letters and a digit.

A webhook fails with "Connection refused". The receiving address does not answer from inside the pod. A service on this server needs the AddHost= line from step 11, and localhost means IPv6 there.

Run it on your own server

SSD RAID 1 · ECC DDR4 · 10 Gbit

VC-P Alloy

€8.99/mo

vCPU
2
Memory
8 GB
Storage
60 GB
Transfer
10 TB
Performance
SSD · RAID 1
  • Full root access
  • Native /64 IPv6
  • RAID-protected storage
  • Malmö, Sweden
  • Month to month, no lock-in
  • 7-day money-back guarantee

These steps were tested on VC-P Titanium. This uses so little that VC-P Alloy, with the same number of vCPUs and memory on an older CPU, is enough at a small scale and costs less.

All guides