Deploys and configures NetBox, an IP address management (IPAM) and data center infrastructure management (DCIM) tool.
This role will deploy NetBox within its own virtualenv either by release tarball or via git using uWSGI as the application server.
Supports CentOS 7, 8 / RHEL 9 / Debian 9, 10, 11, 12 / Ubuntu 16, 18, 20 and 22.
Note that this role is slightly opinionated and differs from installation instructions from the NetBox documentation. The main differences are:
-
Uses distro-provided systemd instead of supervisord
-
Uses uWSGI as an application server instead of gunicorn
-
Hardens the NetBox/uWSGI service (see
templates/netbox.service.j2
) -
Will hot reload on upgrades and configuration changes
To install this role, add the following to your requirements.yml
:
---
- name: lae.netbox
src: https://github.com/lae/ansible-role-netbox.git
version: v1.0.7
Provided you have Ansible installed and are using defaults:
ansible-galaxy install geerlingguy.postgresql davidwittman.redis https://github.com/lae/ansible-role-netbox/archive/refs/tags/v1.0.7.tar.gz,v1.0.7,lae.netbox
ansible-galaxy collection install community.postgresql
ansible-playbook -i your.server.fqdn, ~/.ansible/roles/lae.netbox/examples/playbook_single_host_deploy.yml -K
This will deploy NetBox and PostgreSQL on your.server.fqdn
; once complete it should be accessible on port 80.
Modify if needed. Read below for more insight.
You can also use Vagrant, if you prefer, to bring up NetBox at localhost:8080
:
ansible-galaxy install geerlingguy.postgresql davidwittman.redis https://github.com/lae/ansible-role-netbox/archive/refs/tags/v1.0.7.tar.gz,lae.netbox
ansible-galaxy collection install community.postgresql
cd ~/.ansible/roles/lae.netbox/
vagrant up
If you would like to contribute to this role, please read DEVELOPING.md
for this repository’s workflow and (optional) instructions on setting up a development environment.
This role does not setup a PostgreSQL server (but will create a database if needed), so you’ll need to setup a PostgreSQL server and create a database user separate from this role. Take a look at the Example Playbook section.
In addition, for Ansible 2.10+, you may need to install the community.postgresql
collection.
It is recommended to specify this in your playbook’s requirements.yml
file.
For example:
---
collections:
- name: community.postgresql
version: 3.4.0
|
NetBox v2.2.0+ require PostgreSQL 9.4 at the minimum, which may not be available in your distribution’s repos. You may want to use a role for this. |
This role does not setup or manage a Redis instance.
You may want to either install redis-server
via a task in pre_tasks
within your playbook or use a Redis installation role such as
DavidWittman.redis.
|
NetBox v2.9.0+ require Redis 4.0 at the minimum. The role suggested above defaults to a 2.8 version, so make sure you specify a newer version in a role variable or deploy Redis 4.0+ another way. |
💡
|
See examples/ for some playbooks you could write for different scenarios.
|
|
A few role variables are mandatory. Look for the bold required below. |
netbox_stable: false
netbox_git: false
It’s required to set one of the above variables to true
.
netbox_stable
tells the role to deploy by extracting tarball releases from GitHub,
while netbox_git
tells the role to clone a NetBox git repository - they’re mutually exclusive.
netbox_stable_version: 3.7.3
netbox_stable_uri: "https://github.com/netbox-community/netbox/archive/v{{ netbox_stable_version }}.tar.gz"
These can be configured to pin a version (e.g. increment to trigger an upgrade) or deploy using a tarball located somewhere else. Useful for when you need to modify something in a release or are deploying locally behind a firewall.
netbox_git_version: develop
netbox_git_uri: "https://github.com/netbox-community/netbox.git"
netbox_git_version
can be any valid ref within a git repository.
netbox_git_uri
can be used to point to e.g. an on-premise repo or a fork.
netbox_superuser_enabled: true
netbox_superuser_username: admin
#netbox_superuser_password: changeme
netbox_superuser_email: admin@localhost
netbox_superuser_create_token: false
These variables are used to configure a local superuser account.
Disable this if you do not want to create one (when using LDAP for example - though having a local superuser may still be beneficial in that case).
When enabled, it is required to set the superuser password.
This role will create a new superuser if the user does not exist, or will modify an existing user if they’re not a superuser/have a different email or password.
(Yes, you can use this to reset your superuser password if you forget it.)
netbox_superuser_create_token
can be used to generate a random API token for the superuser, if needed.
netbox_database: netbox
netbox_database_user: netbox
#netbox_database_password: changeme
#netbox_database_host: localhost
netbox_database_port: 5432
#netbox_database_socket: /var/run/postgresql
It is required to configure either a socket directory (to communicate over UNIX sockets) or a host/password (to use TCP/IP). See the Example Playbook section for more information on configuring the database.
Note that these are used to configure DATABASE
in configuration.py
.
netbox_database_conn_age: 300
To configure Netbox to keep database connections open longer than a single requests,
set netbox_database_conn_age
to your preferred maximum connection age, in seconds.
300 seconds (5 minutes) is typically a good number to start with.
netbox_database_maintenance: postgres
If the postgres database is configured to only allow access to specific tables of the DB for the user configured with Netbox,
you can set netbox_database_maintenance
to replace the default database used for connection checking to a different table than the default postgres
.
This is an empty table in every postgres database by default, but some configurations might block access to this table,
so a different table (i.e. netbox_prod
) can be used here instead.
# Example usage, default is empty dict
netbox_database_options:
sslmode: require
isolation_level: 3
If you need to set any other PostgreSQL parameter key words you can do so here.
For cases like isolation levels
the numerical value must be used instead of the constant: psycopg2.extensions.ISOLATION_LEVEL_SERIALIZABLE
vs 3
.
Only add things here if you really know what you’re doing.
netbox_redis_host: 127.0.0.1
netbox_redis_port: 6379
netbox_redis_password: ''
netbox_redis_database: 0
netbox_redis_default_timeout: 300
netbox_redis_ssl_enabled: false
netbox_redis_insecure_skip_tls_verify: false
netbox_redis_cache_host: "{{ netbox_redis_host }}"
netbox_redis_cache_port: "{{ netbox_redis_port }}"
netbox_redis_cache_database: 1
netbox_redis_cache_password: "{{ netbox_redis_password }}"
netbox_redis_cache_default_timeout: "{{ netbox_redis_default_timeout }}"
netbox_redis_cache_ssl_enabled: "{{ netbox_redis_ssl_enabled }}"
netbox_redis_cache_insecure_skip_tls_verify: "{{ netbox_redis_insecure_skip_tls_verify }}"
This populates the REDIS
config dictionary in configuration.py
.
Use the second set of variables if you wish to split your cache database from your webhooks database.
netbox_redis_sentinels:
- { host: '192.168.0.1', port: '5000' },
- { host: '192.168.0.2', port: '5000' }
netbox_redis_sentinel_service: 'netbox'
netbox_redis_password: ''
netbox_redis_database: 0
netbox_redis_default_timeout: 300
netbox_redis_ssl_enabled: false
netbox_redis_cache_sentinels: "{{ netbox_redis_sentinels }}"
netbox_redis_cache_sentinel_service: "{{ netbox_redis_sentinel_service }}"
netbox_redis_cache_database: 1
netbox_redis_cache_password: "{{ netbox_redis_password }}"
netbox_redis_cache_default_timeout: "{{ netbox_redis_default_timeout }}"
netbox_redis_cache_ssl_enabled: "{{ netbox_redis_ssl_enabled }}"
Use this syntax if your redis is installed with sentinet architecture (multiple nodes). Use the second set of variables if you wish to split your cache database from your webhooks database.
netbox_rqworker_processes: 1
Specify how many request queue workers should be started by the systemd service. You can leave this at the default of 1, unless you have a large number of reports, scripts and other background tasks.
netbox_config:
#SECRET_KEY:
ALLOWED_HOSTS:
- localhost
- 127.0.0.1
#NAPALM_USERNAME:
#NAPALM_PASSWORD:
MEDIA_ROOT: "{{ netbox_shared_path }}/media"
REPORTS_ROOT: "{{ netbox_shared_path }}/reports"
SCRIPTS_ROOT: "{{ netbox_shared_path }}/scripts"
This is a dictionary of settings used to template NetBox’s configuration.py
.
See Mandatory Settings
and Optional Settings
from the NetBox documentation for more details, as well as examples/netbox_config.yml
in this repository.
It is not necessary to define SECRET_KEY
here - this role will automatically create one for you at {{ netbox_shared_path }}/generated_secret_key
.
The SECRET_KEY
will then be read from this file on subsequent runs, unless you later do set this in your playbook.
Note that you should define the SECRET_KEY
if you are deploying multiple NetBox instances behind one load balancer.
If you have enabled NAPALM integration in this role, you will need to configure NAPALM credentials here as well.
MEDIA_ROOT
/REPORTS_ROOT
/SCRIPTS_ROOT
, while not mandatory in the NetBox documentation,
is mandatory in this role to prevent losing these files during upgrades (this role does not upgrade NetBox in-place).
It should be set to a directory that is permanent and not lost on upgrade (the default, listed above, can be used without issue).
This role will attempt to create these directories and change their ownership to whatever netbox_user
is set to.
netbox_scripts: []
netbox_reports: []
Scripts
and Reports to upload for use within NetBox.
These should be lists of dictionaries with a src
attribute, specifying the local path to the script or report,
and a name
attribute, specifying the module name (script/report name).
For example:
## Example
netbox_scripts:
- src: netbox_scripts/migrate_application.py
name: migrate_application
netbox_reports:
- src: netbox_reports/devices.py
name: devices
This will copy netbox_scripts/migrate_application.py
from your playbook directory to {{ netbox_config.SCRIPTS_ROOT }}/migrate_application.py
and netbox_reports/devices.py
to {{ netbox.config.REPORTS_ROOT }}/devices.py
.
netbox_pip_packages: []
## Example:
netbox_pip_packages:
- https://github.com/steffann/netbox-example-plugin.git
- netbox-topology-views
This is a list of extra packages to install via pip
within NetBox' virtualenv.
You can specify any valid artifact that pip
understands.
📝
|
If you specify any plugins here, be sure to include the appropriate plugin configurations within the netbox_config role variable.
You may also need to configure netbox_local_settings_file in some situations.
Read Plugins for more info.
|
netbox_user: netbox
netbox_group: netbox
netbox_home: /srv/netbox
netbox_releases_path: "{{ netbox_home }}/releases"
netbox_git_repo_path: "{{ netbox_releases_path }}/git-repo"
netbox_git_deploy_path: "{{ netbox_releases_path }}/git-deploy"
netbox_stable_path: "{{ netbox_releases_path }}/netbox-{{ netbox_stable_version }}"
netbox_current_path: "{{ netbox_home }}/current"
netbox_shared_path: "{{ netbox_home }}/shared"
These are all deployment details that you can modify to change the application user and application storage locations.
netbox_releases_path
stores all NetBox releases you’ve ever deployed.
netbox_git_repo_path
is where the Git repository will be cloned to and should remain untouched,
whilst netbox_git_deploy_path
is where a git archive
using the ref netbox_git_version
will be extracted to.
netbox_stable_path
is the extracted folder from a release tarball.
netbox_current_path
will be symlinked to the selected release and used in service/configuration files as the location NetBox is installed.
netbox_shared_path
is intended to store configuration files and other "shared" content, like logs.
netbox_socket: "127.0.0.1:8000"
netbox_protocol: http
netbox_processes: "{{ ansible_processor_vcpus }}"
netbox_socket
defines what the uWSGI service will bind to and can be set to any valid
ListenStream address (systemd socket).
Set netbox_protocol
to uwsgi
if you want uWSGI to speak WSGI (for instance if you’re running nginx as a load balancer).
netbox_processes
defines how many NetBox workers uWSGI will bring up to serve requests.
netbox_application_log: "file:{{ netbox_shared_path }}/application.log"
netbox_requests_log: "file:{{ netbox_shared_path }}/requests.log"
These define where logs will be stored.
You can use external logging facilities instead of local files if you wish,
as long as uWSGI supports it.
Application log correlates to logger
and requests log to req-logger
.
netbox_ldap_enabled: false
netbox_ldap_config_template: netbox_ldap_config.py.j2
Toggle netbox_ldap_enabled
to true
to configure LDAP authentication for NetBox.
netbox_ldap_config_template
should be the path to your template - by default, Ansible will search your playbook’s templates/
directory for this.
You can find an example in examples/
.
You will also need to set netbox_config.REMOTE_AUTH_BACKEND
to netbox.authentication.LDAPBackend
.
💡
|
By default, a local (non-LDAP) superuser will still be created by this role.
If this is undesirable, consider toggling netbox_superuser_enabled .
|
# netbox_local_settings_file: "{{ playbook_dir }}/files/netbox/local_settings.py"
If you need to override any settings or extend the functionality in NetBox' settings.py
in a way that is not supported by the configuration.py
(i.e. the netbox_config
role variable),
you can set netbox_local_settings_file
to a local file path in your playbook to deploy a local_settings.py
file within NetBox.
This feature was introduced in NetBox v4.0.2.
You may need to use this file for deploying certain NetBox plugins.
📝
|
Commenting or removing this role variable from your playbook will remove local_settings.py from your NetBox deployment.
|
netbox_napalm_enabled: false
netbox_napalm_packages:
- napalm
Toggle netbox_napalm_enabled
to enable NAPALM integration in NetBox.
You must define NAPALM_USERNAME
and NAPALM_PASSWORD
in the netbox_config
variable to be able to use NAPALM.
Add extra NAPALM python libraries by listing them in netbox_napalm_packages
(e.g. napalm-eos
).
netbox_metrics_enabled: false
Toggle netbox_metrics_enabled
to true
to enable application metrics (via django-prometheus).
This adds relevant pieces of configuration for proper metrics handling.
(more info).
netbox_metrics_dir: netbox_metrics
netbox_metrics_path: "/run/{{ netbox_metrics_dir }}"
The directory name where the metrics files are stored can be set with netbox_metrics_dir
.
However, netbox_metrics_path
must remain the default (seen above) in order to work with systemd
and the RuntimeDirectory
parameter (which only points to /run
).
netbox_keep_uwsgi_updated: false
Toggle netbox_keep_uwsgi_updated
to true
if you wish to ensure your uwsgi server is the latest release,
otherwise uwsgi will not be updated on subsequent runs of your playbook.
netbox_uwsgi_options: {}
Specify extra configuration options to insert into uwsgi.ini
here.
This is expected to be a dictionary of key/value pairs, e.g. buffer-size: 65535
.
netbox_uwsgi_in_venv: false
Toggle netbox_uwsgi_in_venv
to true
if you want uwsgi
to be installed in the same virtual environment as NetBox.
Otherwise, it will be installed system-wide into the library path of the python version used to created the virtual environment (normal/legacy behavior).
|
There’s a possibility that this may become the default in a later version of this role (I think after further cross-platform testing). See issue #144 for further details. |
netbox_install_epel: true
Toggle netbox_install_epel
to false
if you do not want this role to install the Fedora EPEL for you.
This can be useful for enterprise environments where the system’s repositories are managed/mirrored by the enterprise.
netbox_packages: []
netbox_python_packages: []
netbox_python_binary: /usr/bin/python{{ some version }}
netbox_ldap_packages: []
These variables are dynamically generated based on the target distribution.
You can check the defaults for these underneath the vars/
directory.
You can use these variables to target an unsupported operating system (although feel free to open a PR to add in support!)
or to specify a custom Python interpreter (such as PyPy) to be used for deployment.
Although, please note that support by this role may be limited for alternative Python installations.
The following installs PostgreSQL and creates a user with @geerlingguy’s robust Postgres role, then proceeds to deploy and configure NetBox using a local unix socket to talk to the Postgres server with the default netbox database user.
- hosts: netbox.idolactiviti.es
become: yes
roles:
- geerlingguy.postgresql
- davidwittman.redis
- lae.netbox
vars:
netbox_stable: true
netbox_database_socket: "{{ postgresql_unix_socket_directories[0] }}"
netbox_superuser_password: netbox
netbox_socket: "0.0.0.0:80"
netbox_config:
ALLOWED_HOSTS:
- netbox.idolactiviti.es
MEDIA_ROOT: "{{ netbox_shared_path }}/media"
REPORTS_ROOT: "{{ netbox_shared_path }}/reports"
SCRIPTS_ROOT: "{{ netbox_shared_path }}/scripts"
postgresql_users:
- name: "{{ netbox_database_user }}"
role_attr_flags: CREATEDB,NOSUPERUSER
redis_bind: 127.0.0.1
redis_version: 6.0.9
redis_checksum: sha256:dc2bdcf81c620e9f09cfd12e85d3bc631c897b2db7a55218fd8a65eaa37f86dd
Note the CREATEDB
attribute.
Assuming you have a PG server already running with the user netbox_prod_user
created, it owns a database called netbox_prod
,
and it allows the host you’re installing NetBox on to authenticate with it over TCP:
- hosts: netbox.idolactiviti.es
become: yes
roles:
- davidwittman.redis
- lae.netbox
vars:
netbox_stable: true
netbox_superuser_password: netbox
netbox_socket: "0.0.0.0:80"
netbox_config:
ALLOWED_HOSTS:
- "{{ inventory_hostname }}"
MEDIA_ROOT: "{{ netbox_shared_path }}/media"
REPORTS_ROOT: "{{ netbox_shared_path }}/reports"
SCRIPTS_ROOT: "{{ netbox_shared_path }}/scripts"
netbox_database_host: pg-netbox.idolactiviti.es
netbox_database_port: 15432
netbox_database: netbox_prod
netbox_database_user: netbox_prod_user
netbox_database_password: "very_secure_password_for_prod"
netbox_database_maintenance: netbox_prod
redis_bind: 127.0.0.1
redis_version: 6.0.9
redis_checksum: sha256:dc2bdcf81c620e9f09cfd12e85d3bc631c897b2db7a55218fd8a65eaa37f86dd
See the examples/
directory for more.
When netbox_protocol
is set to http
, uWSGI might exhibit strange behaviour and reset TCP connections seemingly at random.
This can manifest in a connection reset by peer
error, for example when working with the API using pynetbox.
If you are affected by this, try switching netbox_protocol
to uwsgi
and using a load balancer, or adjusting your netbox_uwsgi_options
as follows.
See this GitHub issue for a related discussion.
netbox_uwsgi_options:
http-keepalive: "true"
http-auto-chunked: "true"
add-header: "Connection: Close"