├── .flake8 ├── .github ├── FUNDING.yml └── workflows │ └── amplify.yml ├── .gitignore ├── .travis.yml ├── .yamllint ├── DEVELOPING.md ├── LICENSE ├── README.adoc ├── Vagrantfile ├── defaults └── main.yml ├── examples ├── netbox_config.yml ├── netbox_ldap_config.py.j2 └── playbook_single_host_deploy.yml ├── handlers └── main.yml ├── meta └── main.yml ├── molecule └── default │ ├── converge.yml │ ├── molecule.yml │ ├── prepare.yml │ ├── requirements.yml │ └── tests │ └── test_default.py ├── tasks ├── deploy_netbox.yml ├── generate_secret_key.yml ├── install_packages_apt.yml ├── install_packages_dnf.yml ├── install_packages_yum.yml ├── install_via_git.yml ├── install_via_stable.yml ├── load_variables.yml ├── main.yml └── validate_variables.yml ├── templates ├── configuration.py.j2 ├── netbox-rqworker.service.j2 ├── netbox.service.j2 ├── netbox.socket.j2 ├── pip_constraints.j2 └── uwsgi.ini.j2 ├── tests ├── ansible.cfg ├── deploy.yml ├── group_vars │ ├── netbox │ ├── netbox_git │ ├── netbox_stable │ └── netbox_stable_2_7 ├── install.yml ├── inventory ├── reports │ └── nothing.py ├── scripts │ └── nothing.py ├── test.yml └── vagrant │ ├── group_vars │ └── all │ ├── package_role.yml │ ├── provision.yml │ └── templates │ └── detect-http-proxy.j2 └── vars ├── amazon-2023.yml ├── debian-10.yml ├── debian-11.yml ├── debian-12.yml ├── debian-9.yml ├── main.yml ├── redhat-7.yml ├── redhat-8.yml ├── redhat-9.yml ├── ubuntu-16.yml ├── ubuntu-18.yml ├── ubuntu-20.yml └── ubuntu-22.yml /.flake8: -------------------------------------------------------------------------------- 1 | [flake8] 2 | # Recommend matching the black line length (default 88), 3 | # rather than using the flake8 default of 79: 4 | max-line-length = 88 5 | extend-ignore = 6 | # See https://github.com/PyCQA/pycodestyle/issues/373 7 | E203, 8 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | --- 2 | ko_fi: sleepingkyoto 3 | custom: 4 | - "https://monappy.jp/u/lae" 5 | -------------------------------------------------------------------------------- /.github/workflows/amplify.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Amplify Security 3 | on: 4 | pull_request_target: {} 5 | workflow_dispatch: {} 6 | push: 7 | branches: ["main", "develop"] 8 | 9 | permissions: 10 | contents: read 11 | id-token: write 12 | 13 | jobs: 14 | authorize: 15 | environment: 16 | ${{ github.event_name == 'pull_request_target' && 17 | github.event.pull_request.head.repo.fork && 'external' || 'internal' }} 18 | runs-on: ubuntu-latest 19 | steps: 20 | - run: true 21 | 22 | amplify-security-scan: 23 | name: Amplify Security Scan 24 | needs: authorize 25 | runs-on: ubuntu-latest 26 | if: github.actor != 'dependabot[bot]' 27 | steps: 28 | - name: Checkout 29 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 30 | with: 31 | ref: ${{ github.event.pull_request.head.sha || github.ref }} 32 | - name: Amplify Runner 33 | uses: amplify-security/runner-action@926f003f3c9695a93cbc4e2f1e64eb784dcacbfc # v0.2.0 34 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vagrant/ 2 | .vscode/ 3 | .history 4 | *.retry 5 | *.code-workspace 6 | *.sw? 7 | .venv 8 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | sudo: required 3 | dist: bionic 4 | cache: 5 | directories: [ '$HOME/lxc' ] 6 | pip: true 7 | services: 8 | - postgresql 9 | addons: 10 | postgresql: "9.6" 11 | matrix: 12 | fast_finish: true 13 | # FIXME: Ansible 2.10.x going through major restructuring. 14 | # https://groups.google.com/forum/#!msg/ansible-project/eXsoOKEd0Mk/XTgbnPWbCAAJ 15 | include: 16 | # - python: '3.6' 17 | # env: ANSIBLE_GIT_VERSION='devel' # 2.10.x development branch 18 | - env: ANSIBLE_VERSION='~=2.10.0' 19 | - env: ANSIBLE_VERSION='~=2.9.0' 20 | install: 21 | - if [ "$ANSIBLE_GIT_VERSION" ]; then pip install "https://github.com/ansible/ansible/archive/${ANSIBLE_GIT_VERSION}.tar.gz"; 22 | else pip install "ansible${ANSIBLE_VERSION}"; fi; 23 | pip install --pre ansible-lint 24 | - ansible --version 25 | - ansible-galaxy install lae.travis-lxc,v0.10.1 26 | - ansible-playbook tests/install.yml -i tests/inventory 27 | - git archive --format tar.gz HEAD > lae.netbox.tar.gz && ansible-galaxy install 28 | lae.netbox.tar.gz,$(git rev-parse HEAD),lae.netbox && rm lae.netbox.tar.gz 29 | before_script: 30 | - echo "host all all 10.0.3.0/24 trust" | sudo tee -a /etc/postgresql/9.6/main/pg_hba.conf 31 | - echo "listen_addresses = '*'" | sudo tee -a /etc/postgresql/9.6/main/postgresql.conf 32 | - sudo service postgresql restart 33 | - sudo redis-server /etc/redis/redis.conf --bind 10.0.3.1 --protected-mode no --port 6379 34 | - cd tests/ 35 | script: 36 | - ansible-lint ../ || true 37 | - yamllint ../ || true 38 | - ansible-playbook -i inventory deploy.yml --syntax-check 39 | - ansible-playbook -i inventory deploy.yml 40 | - 'ANSIBLE_STDOUT_CALLBACK=debug ANSIBLE_DISPLAY_SKIPPED_HOSTS=no ANSIBLE_DISPLAY_OK_HOSTS=no 41 | unbuffer ansible-playbook -vvi inventory deploy.yml &>play.log; printf "Idempotence: "; 42 | sed -ne "/PLAY RECAP/,/^$/{/PLAY RECAP/d;/^$/d;p}" play.log | grep -vqP "changed=0 .*failed=0 .*" 43 | && (echo "FAIL"; cat play.log; exit 1) || (echo "PASS"; exit 0)' 44 | - ANSIBLE_STDOUT_CALLBACK=debug ansible-playbook -i inventory -v test.yml 45 | notifications: 46 | webhooks: 47 | urls: 48 | - https://galaxy.ansible.com/api/v1/notifications/ 49 | - https://t2d.idolactiviti.es/notify 50 | -------------------------------------------------------------------------------- /.yamllint: -------------------------------------------------------------------------------- 1 | --- 2 | extends: default 3 | 4 | rules: 5 | braces: 6 | max-spaces-inside: 1 7 | level: error 8 | brackets: 9 | max-spaces-inside: 1 10 | level: error 11 | line-length: disable 12 | # NOTE(retr0h): Templates no longer fail this lint rule. 13 | # Uncomment if running old Molecule templates. 14 | # truthy: disable 15 | 16 | ignore: .travis.yml 17 | -------------------------------------------------------------------------------- /DEVELOPING.md: -------------------------------------------------------------------------------- 1 | # Developing ansible-role-netbox 2 | 3 | Thanks for your interest in helping develop this role. 4 | 5 | ## Workflow Summary 6 | 7 | For any large feature requests, please open an issue to discuss it in further 8 | detail before working on it. 9 | 10 | 1. Fork https://github.com/lae/ansible-role-netbox/ on Github. 11 | 2. Clone your fork locally and create a new feature/issue branch (e.g. 12 | `git checkout -b feature/fix-some-bug`). 13 | 3. Make required changes and test locally if appropriate (see below). Try to 14 | keep your commits concise and relevant (either amend or squash your commits 15 | if you're fixing typos or something minor). 16 | 4. Regularly push your changes to Github and make sure CI tests pass on Travis. 17 | a. You may need to login to https://travis-ci.com with your Github account 18 | and enable tests for your forked repository. 19 | 5. Once you feel your branch is ready, open a pull request. 20 | 21 | ## Setting up a local development/testing environment 22 | 23 | You'll need to install the following to develop/test locally. 24 | 25 | - git 26 | - [vagrant](https://www.vagrantup.com/) 27 | - [VirtualBox](https://www.virtualbox.org/) 28 | - [molecule](https://molecule.readthedocs.io/en/latest/) 29 | 30 | ### Setup Vagrant additions 31 | 32 | Vagrant when working with molecule requires python-vagrant installed 33 | 34 | ```cli 35 | $ pip install python-vagrant 36 | ``` 37 | 38 | ## Molecule 39 | 40 | Molecule is used to run tests locally (these can be integrated into the CI pipeline however not done for this project at this point in time), currently this project only implements vagrant/virtualbox testing. 41 | 42 | Under the molecule directory contains testing scenarios, in this case there is a single default senario using vagrant and virtualbox, howver you may want to add your own in addition to the defaul, i.e. if you use parallels vm or you want to use docker. Please see molecule documentaton for more details. 43 | 44 | ``` 45 | molecule 46 | └── default 47 | ├── molecule.yml 48 | ├── playbook.yml 49 | ├── prepare.yml 50 | ├── requirements.yml 51 | └── tests 52 | └── test_default.py 53 | ``` 54 | 55 | **molecule.yml** - defines how the tests are run, linting is enabled/disabled from here, what images are used etc. 56 | 57 | **playbook.yml** - actual playbook that gets run during converge 58 | 59 | **prepare.yml** - any setups here that get executed as part of the prepare stage, do not modify when vagrant is used as the scenarios method as there are known issues. 60 | 61 | **requirements.yml** - any external role dependancey go here. 62 | 63 | **tests** - all tests live under here 64 | 65 | ### Running tests locally 66 | 67 | NOTE: please note that all molecule commands listed are executed from the root of the project directory. 68 | 69 | Mostly you will (or should be doing): 70 | 71 | 1. define a test 72 | 2. make changes to your code 73 | 3. run the suite of tests under the default scenario to make sure everything passes 74 | 75 | Tests are written using testinfra and are locally in test_default.py file. 76 | 77 | below is an example testing required services are running and enabled. If either of the two assets fail for any of the three services the test will fail. 78 | 79 | ```python 80 | def test_services(host): 81 | services = [ 82 | "netbox.socket", 83 | "netbox.service", 84 | "netbox-rqworker.service" 85 | ] 86 | for service in services: 87 | s = host.service(service) 88 | assert s.is_enabled 89 | assert s.is_running 90 | ``` 91 | 92 | Easiest way to perform all the required steps and tests is: 93 | 94 | ```cli 95 | molecule test 96 | ``` 97 | 98 | This will perform all the correct sequences 99 | 100 | However you may want to manually run indiviual stages to troubleshoot the code changes. 101 | 102 | ### Troubleshooting the role under test 103 | 104 | To troublshoot a failed molecule test you can first start with a clean slate 105 | 106 | ```cli 107 | molecule destroy 108 | ``` 109 | 110 | Then converge the environment via `molecule converge` command. 111 | 112 | The converge will provision the test machine and then apply the role, but will not run any tests beside lint (if enabled), however unlike the `molecule test` command, when it completes it will still keep the vagrant environment up and running so you can: 113 | 114 | 1. execute the suite of default tests via the `molecule verify` or `molecule indempotent` 115 | 2. allows you to log into the vagrant machine and poke around. `molecule login` 116 | 117 | To re-setup/reprovision the test environment, first perform `molecule destroy` then `molecule converge` 118 | 119 | #### What tests can you do locally? 120 | 121 | (Please refer to molecule documentation for more details) 122 | 123 | **Self Check molecule scenario** 124 | 125 | helpful if you make changes to anything under the scenario 126 | 127 | ```cli 128 | molecule check 129 | ``` 130 | 131 | **Lint** 132 | 133 | YAML Lint checking 134 | Ansible Lint checking 135 | 136 | These can be enabled/disabled in molecule.yml (currently disabled) 137 | 138 | ```cli 139 | molecule lint 140 | ``` 141 | 142 | **Syntax** 143 | 144 | ```cli 145 | molecule syntax 146 | ``` 147 | 148 | **Idempotence** 149 | 150 | ```cli 151 | molecule idempotence 152 | ``` 153 | 154 | **Side effects** 155 | 156 | ```cli 157 | molecule side-effect 158 | ``` 159 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2017-2018 Musee "lae" Ullah 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /README.adoc: -------------------------------------------------------------------------------- 1 | :role-author: lae 2 | :role-name: netbox 3 | :role: {role-author}.{role-name} 4 | :role-version: 1.0.7 5 | :gh-name: {role-author}/ansible-role-{role-name} 6 | :netbox-version: 3.7.3 7 | = {role} 8 | :toc: 9 | :toc-placement: preamble 10 | ifdef::env-github[] 11 | :note-caption: :memo: 12 | :tip-caption: :bulb: 13 | :warning-caption: :warning: 14 | endif::[] 15 | 16 | Deploys and configures https://github.com/netbox-community/netbox[NetBox], an IP address management (IPAM) and data center infrastructure management (DCIM) tool. 17 | 18 | This role will deploy NetBox within its own virtualenv either by release tarball or via git using uWSGI as the application server. 19 | 20 | Supports CentOS 7, 8 / RHEL 9 / Debian 9, 10, 11, 12 / Ubuntu 16, 18, 20 and 22. 21 | 22 | Note that this role is slightly opinionated and differs from installation instructions from the NetBox documentation. 23 | The main differences are: 24 | 25 | * Uses distro-provided systemd instead of supervisord 26 | * Uses uWSGI as an application server instead of gunicorn 27 | * Hardens the NetBox/uWSGI service (see `templates/netbox.service.j2`) 28 | * Will hot reload on upgrades and configuration changes 29 | 30 | To install this role, add the following to your `requirements.yml`: 31 | 32 | [source,yaml,subs="attributes"] 33 | ---- 34 | --- 35 | - name: {role} 36 | src: https://github.com/{gh-name}.git 37 | version: v{role-version} 38 | ---- 39 | 40 | == Quickstart 41 | 42 | Provided you have Ansible installed and are using defaults: 43 | 44 | [source,bash,subs="attributes"] 45 | ---- 46 | ansible-galaxy install geerlingguy.postgresql davidwittman.redis https://github.com/{gh-name}/archive/refs/tags/v{role-version}.tar.gz,v{role-version},{role} 47 | ansible-galaxy collection install community.postgresql 48 | ansible-playbook -i your.server.fqdn, ~/.ansible/roles/{role}/examples/playbook_single_host_deploy.yml -K 49 | ---- 50 | 51 | This will deploy NetBox and PostgreSQL on `your.server.fqdn`; once complete it should be accessible on port 80. 52 | Modify if needed. Read below for more insight. 53 | 54 | You can also use Vagrant, if you prefer, to bring up NetBox at `localhost:8080`: 55 | 56 | [source,bash,subs="attributes"] 57 | ---- 58 | ansible-galaxy install geerlingguy.postgresql davidwittman.redis https://github.com/{gh-name}/archive/refs/tags/v{role-version}.tar.gz,{role} 59 | ansible-galaxy collection install community.postgresql 60 | cd ~/.ansible/roles/{role}/ 61 | vagrant up 62 | ---- 63 | 64 | == Support/Contributing 65 | 66 | 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. 67 | 68 | == Prerequisites 69 | 70 | === PostgreSQL 71 | 72 | This role does not setup a PostgreSQL server (but will create a database if needed), 73 | so you'll need to setup a PostgreSQL server and create a database user separate from this role. 74 | Take a look at the _Example Playbook_ section. 75 | 76 | In addition, for Ansible 2.10+, you may need to install the `community.postgresql` collection. 77 | It is recommended to specify this in your playbook's `requirements.yml` file. 78 | For example: 79 | 80 | [source,yaml] 81 | ---- 82 | --- 83 | collections: 84 | - name: community.postgresql 85 | version: 3.4.0 86 | ---- 87 | 88 | WARNING: NetBox v2.2.0+ require PostgreSQL 9.4 at the minimum, which may not be available in your distribution's repos. 89 | You may want to use a role for this. 90 | 91 | === Redis 92 | 93 | This role does not setup or manage a Redis instance. 94 | 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 95 | https://galaxy.ansible.com/davidwittman/redis[DavidWittman.redis]. 96 | 97 | WARNING: NetBox v2.9.0+ require Redis 4.0 at the minimum. 98 | 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. 99 | 100 | == Role Variables 101 | 102 | TIP: See `examples/` for some playbooks you could write for different scenarios. 103 | 104 | WARNING: A few role variables are mandatory. Look for the bold *required* below. 105 | 106 | [source,yaml] 107 | ---- 108 | netbox_stable: false 109 | netbox_git: false 110 | ---- 111 | 112 | It's *required* to set one of the above variables to `true`. 113 | `netbox_stable` tells the role to deploy by extracting tarball releases from GitHub, 114 | while `netbox_git` tells the role to clone a NetBox git repository - they're mutually exclusive. 115 | 116 | [source,yaml,subs="attributes"] 117 | ---- 118 | netbox_stable_version: {netbox-version} 119 | netbox_stable_uri: "https://github.com/netbox-community/netbox/archive/v{{ netbox_stable_version }}.tar.gz" 120 | ---- 121 | 122 | These can be configured to pin a version (e.g. increment to trigger an upgrade) or deploy using a tarball located somewhere else. 123 | Useful for when you need to modify something in a release or are deploying locally behind a firewall. 124 | 125 | [source,yaml] 126 | ---- 127 | netbox_git_version: develop 128 | netbox_git_uri: "https://github.com/netbox-community/netbox.git" 129 | ---- 130 | 131 | `netbox_git_version` can be any valid ref within a git repository. 132 | `netbox_git_uri` can be used to point to e.g. an on-premise repo or a fork. 133 | 134 | [source,yaml] 135 | ---- 136 | netbox_superuser_enabled: true 137 | netbox_superuser_username: admin 138 | #netbox_superuser_password: changeme 139 | netbox_superuser_email: admin@localhost 140 | netbox_superuser_create_token: false 141 | ---- 142 | 143 | These variables are used to configure a local superuser account. 144 | 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). 145 | When enabled, it is *required* to set the superuser password. 146 | 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. 147 | (Yes, you can use this to reset your superuser password if you forget it.) 148 | `netbox_superuser_create_token` can be used to generate a random API token for the superuser, if needed. 149 | 150 | [source,yaml] 151 | ---- 152 | netbox_database: netbox 153 | netbox_database_user: netbox 154 | #netbox_database_password: changeme 155 | #netbox_database_host: localhost 156 | netbox_database_port: 5432 157 | #netbox_database_socket: /var/run/postgresql 158 | #netbox_database_alt_socket: false 159 | ---- 160 | 161 | It is *required* to configure either a socket directory (to communicate over UNIX sockets) or a host/password (to use TCP/IP). 162 | See the _Example Playbook_ section for more information on configuring the database. 163 | 164 | Setting `netbox_database_alt_socket` to `true` will skip the database connectivity check 165 | tasks and also set `netbox_database_port` alongside the socket connection for the 166 | database configuration. This will help with environments that may be running pgbouncer 167 | on the same server as NetBox. 168 | 169 | Note that these are used to configure `DATABASE` in `configuration.py`. 170 | 171 | [source,yaml] 172 | ---- 173 | netbox_database_conn_age: 300 174 | ---- 175 | 176 | To configure Netbox to keep database connections open longer than a single requests, 177 | set `netbox_database_conn_age` to your preferred maximum connection age, in seconds. 178 | 300 seconds (5 minutes) is typically a good number to start with. 179 | 180 | [source,yaml] 181 | ---- 182 | netbox_database_maintenance: postgres 183 | ---- 184 | 185 | If the postgres database is configured to only allow access to specific tables of the DB for the user configured with Netbox, 186 | you can set `netbox_database_maintenance` to replace the default database used for connection checking to a different table than the default `postgres`. 187 | This is an empty table in every postgres database by default, but some configurations might block access to this table, 188 | so a different table (i.e. `netbox_prod`) can be used here instead. 189 | 190 | [source,yaml] 191 | ---- 192 | # Example usage, default is empty dict 193 | netbox_database_options: 194 | sslmode: require 195 | isolation_level: 3 196 | ---- 197 | 198 | If you need to set any other PostgreSQL parameter key words you can do so here. 199 | For cases like https://docs.djangoproject.com/en/3.1/ref/databases/#isolation-level[isolation levels] 200 | the numerical value must be used instead of the constant: `psycopg2.extensions.ISOLATION_LEVEL_SERIALIZABLE` vs `3`. 201 | Only add things here if you really know what you're doing. 202 | 203 | [source,yaml] 204 | ---- 205 | netbox_redis_host: 127.0.0.1 206 | netbox_redis_port: 6379 207 | netbox_redis_password: '' 208 | netbox_redis_database: 0 209 | netbox_redis_default_timeout: 300 210 | netbox_redis_ssl_enabled: false 211 | netbox_redis_insecure_skip_tls_verify: false 212 | 213 | netbox_redis_cache_host: "{{ netbox_redis_host }}" 214 | netbox_redis_cache_port: "{{ netbox_redis_port }}" 215 | netbox_redis_cache_database: 1 216 | netbox_redis_cache_password: "{{ netbox_redis_password }}" 217 | netbox_redis_cache_default_timeout: "{{ netbox_redis_default_timeout }}" 218 | netbox_redis_cache_ssl_enabled: "{{ netbox_redis_ssl_enabled }}" 219 | netbox_redis_cache_insecure_skip_tls_verify: "{{ netbox_redis_insecure_skip_tls_verify }}" 220 | ---- 221 | 222 | This populates the `REDIS` config dictionary in `configuration.py`. 223 | Use the second set of variables if you wish to split your cache database from your webhooks database. 224 | 225 | [source,yaml] 226 | ---- 227 | netbox_redis_sentinels: 228 | - { host: '192.168.0.1', port: '5000' }, 229 | - { host: '192.168.0.2', port: '5000' } 230 | netbox_redis_sentinel_service: 'netbox' 231 | netbox_redis_password: '' 232 | netbox_redis_database: 0 233 | netbox_redis_default_timeout: 300 234 | netbox_redis_ssl_enabled: false 235 | 236 | netbox_redis_cache_sentinels: "{{ netbox_redis_sentinels }}" 237 | netbox_redis_cache_sentinel_service: "{{ netbox_redis_sentinel_service }}" 238 | netbox_redis_cache_database: 1 239 | netbox_redis_cache_password: "{{ netbox_redis_password }}" 240 | netbox_redis_cache_default_timeout: "{{ netbox_redis_default_timeout }}" 241 | netbox_redis_cache_ssl_enabled: "{{ netbox_redis_ssl_enabled }}" 242 | ---- 243 | 244 | Use this syntax if your redis is installed with sentinet architecture (multiple nodes). 245 | Use the second set of variables if you wish to split your cache database from your webhooks database. 246 | 247 | [source,yaml] 248 | ---- 249 | netbox_rqworker_processes: 1 250 | ---- 251 | 252 | Specify how many request queue workers should be started by the systemd service. 253 | You can leave this at the default of 1, unless you have a large number of reports, scripts and other background tasks. 254 | 255 | [source,yaml] 256 | ---- 257 | netbox_config: 258 | #SECRET_KEY: 259 | ALLOWED_HOSTS: 260 | - localhost 261 | - 127.0.0.1 262 | #NAPALM_USERNAME: 263 | #NAPALM_PASSWORD: 264 | MEDIA_ROOT: "{{ netbox_shared_path }}/media" 265 | REPORTS_ROOT: "{{ netbox_shared_path }}/reports" 266 | SCRIPTS_ROOT: "{{ netbox_shared_path }}/scripts" 267 | ---- 268 | 269 | This is a dictionary of settings used to template NetBox's `configuration.py`. 270 | See http://netbox.readthedocs.io/en/stable/configuration/mandatory-settings/[Mandatory Settings] 271 | and http://netbox.readthedocs.io/en/stable/configuration/optional-settings/[Optional Settings] 272 | from the NetBox documentation for more details, as well as `examples/netbox_config.yml` in this repository. 273 | 274 | It is not necessary to define `SECRET_KEY` here - this role will automatically create one for you at `{{ netbox_shared_path }}/generated_secret_key`. 275 | The `SECRET_KEY` will then be read from this file on subsequent runs, unless you later do set this in your playbook. 276 | Note that you should define the `SECRET_KEY` if you are deploying multiple NetBox instances behind one load balancer. 277 | 278 | If you have enabled NAPALM integration in this role, you will need to configure NAPALM credentials here as well. 279 | 280 | `MEDIA_ROOT`/`REPORTS_ROOT`/`SCRIPTS_ROOT`, while not mandatory in the NetBox documentation, 281 | is mandatory in this role to prevent losing these files during upgrades (this role does not upgrade NetBox in-place). 282 | It should be set to a directory that is permanent and not lost on upgrade (the default, listed above, can be used without issue). 283 | This role will attempt to create these directories and change their ownership to whatever `netbox_user` is set to. 284 | 285 | [source,yaml] 286 | ---- 287 | netbox_scripts: [] 288 | netbox_reports: [] 289 | ---- 290 | 291 | https://netbox.readthedocs.io/en/stable/additional-features/custom-scripts/[Scripts] 292 | and https://netbox.readthedocs.io/en/stable/additional-features/reports/[Reports] to upload for use within NetBox. 293 | These should be lists of dictionaries with a `src` attribute, specifying the local path to the script or report, 294 | and a `name` attribute, specifying the module name (script/report name). 295 | For example: 296 | 297 | [source,yaml] 298 | ---- 299 | ## Example 300 | netbox_scripts: 301 | - src: netbox_scripts/migrate_application.py 302 | name: migrate_application 303 | netbox_reports: 304 | - src: netbox_reports/devices.py 305 | name: devices 306 | ---- 307 | 308 | This will copy `netbox_scripts/migrate_application.py` from your playbook directory to `{{ netbox_config.SCRIPTS_ROOT }}/migrate_application.py` 309 | and `netbox_reports/devices.py` to `{{ netbox.config.REPORTS_ROOT }}/devices.py`. 310 | 311 | [source,yaml] 312 | ---- 313 | netbox_pip_packages: [] 314 | 315 | ## Example: 316 | netbox_pip_packages: 317 | - https://github.com/steffann/netbox-example-plugin.git 318 | - netbox-topology-views 319 | ---- 320 | 321 | This is a list of extra packages to install via `pip` within NetBox' virtualenv. 322 | You can specify any valid artifact that `pip` understands. 323 | 324 | NOTE: If you specify any plugins here, be sure to include the appropriate plugin configurations within the `netbox_config` role variable. 325 | You may also need to configure `netbox_local_settings_file` in some situations. 326 | Read https://netbox.readthedocs.io/en/stable/plugins/[Plugins] for more info. 327 | 328 | [source,yaml] 329 | ---- 330 | netbox_user: netbox 331 | netbox_group: netbox 332 | netbox_home: /srv/netbox 333 | netbox_releases_path: "{{ netbox_home }}/releases" 334 | netbox_git_repo_path: "{{ netbox_releases_path }}/git-repo" 335 | netbox_git_deploy_path: "{{ netbox_releases_path }}/git-deploy" 336 | netbox_stable_path: "{{ netbox_releases_path }}/netbox-{{ netbox_stable_version }}" 337 | netbox_current_path: "{{ netbox_home }}/current" 338 | netbox_shared_path: "{{ netbox_home }}/shared" 339 | ---- 340 | 341 | These are all deployment details that you can modify to change the application user and application storage locations. 342 | `netbox_releases_path` stores all NetBox releases you've ever deployed. 343 | `netbox_git_repo_path` is where the Git repository will be cloned to and should remain untouched, 344 | whilst `netbox_git_deploy_path` is where a `git archive` using the ref `netbox_git_version` will be extracted to. 345 | `netbox_stable_path` is the extracted folder from a release tarball. 346 | `netbox_current_path` will be symlinked to the selected release and used in service/configuration files as the location NetBox is installed. 347 | `netbox_shared_path` is intended to store configuration files and other "shared" content, like logs. 348 | 349 | [source,yaml] 350 | ---- 351 | netbox_socket: "127.0.0.1:8000" 352 | netbox_protocol: http 353 | netbox_processes: "{{ ansible_processor_vcpus }}" 354 | ---- 355 | 356 | `netbox_socket` defines what the uWSGI service will bind to and can be set to any valid 357 | https://www.freedesktop.org/software/systemd/man/systemd.socket.html#ListenStream=[ListenStream] address (systemd socket). 358 | Set `netbox_protocol` to `uwsgi` if you want uWSGI to speak WSGI (for instance if you're running nginx as a load balancer). 359 | `netbox_processes` defines how many NetBox workers uWSGI will bring up to serve requests. 360 | 361 | [source,yaml] 362 | ---- 363 | netbox_application_log: "file:{{ netbox_shared_path }}/application.log" 364 | netbox_requests_log: "file:{{ netbox_shared_path }}/requests.log" 365 | ---- 366 | 367 | These define where logs will be stored. 368 | You can use external logging facilities instead of local files if you wish, 369 | http://uwsgi-docs.readthedocs.io/en/latest/Logging.html#pluggable-loggers[as long as uWSGI supports it]. 370 | Application log correlates to `logger` and requests log to `req-logger`. 371 | 372 | [source,yaml] 373 | ---- 374 | netbox_ldap_enabled: false 375 | netbox_ldap_config_template: netbox_ldap_config.py.j2 376 | ---- 377 | 378 | Toggle `netbox_ldap_enabled` to `true` to configure LDAP authentication for NetBox. 379 | `netbox_ldap_config_template` should be the path to your template - by default, Ansible will search your playbook's `templates/` directory for this. 380 | You can find an example in `examples/`. 381 | You will also need to set `netbox_config.REMOTE_AUTH_BACKEND` to `netbox.authentication.LDAPBackend`. 382 | 383 | TIP: By default, a local (non-LDAP) superuser will still be created by this role. 384 | If this is undesirable, consider toggling `netbox_superuser_enabled`. 385 | 386 | [source,yaml] 387 | ---- 388 | # netbox_local_settings_file: "{{ playbook_dir }}/files/netbox/local_settings.py" 389 | ---- 390 | 391 | If you need to override any settings or extend the functionality in NetBox' `settings.py` 392 | in a way that is not supported by the `configuration.py` (i.e. the `netbox_config` role variable), 393 | you can set `netbox_local_settings_file` to a local file path in your playbook to deploy a `local_settings.py` file within NetBox. 394 | This feature was https://github.com/netbox-community/netbox/issues/16127[introduced in NetBox v4.0.2]. 395 | You may need to use this file for deploying certain NetBox plugins. 396 | 397 | NOTE: Commenting or removing this role variable from your playbook will remove `local_settings.py` from your NetBox deployment. 398 | 399 | [source,yaml] 400 | ---- 401 | netbox_napalm_enabled: false 402 | netbox_napalm_packages: 403 | - napalm 404 | ---- 405 | 406 | Toggle `netbox_napalm_enabled` to enable NAPALM integration in NetBox. 407 | You must define `NAPALM_USERNAME` and `NAPALM_PASSWORD` in the `netbox_config` variable to be able to use NAPALM. 408 | Add extra NAPALM python libraries by listing them in `netbox_napalm_packages` (e.g. `napalm-eos`). 409 | 410 | [source,yaml] 411 | netbox_metrics_enabled: false 412 | 413 | Toggle `netbox_metrics_enabled` to `true` to enable application metrics (via https://github.com/korfuri/django-prometheus[django-prometheus]). 414 | This adds relevant pieces of configuration for proper metrics handling. 415 | (https://netbox.readthedocs.io/en/stable/additional-features/prometheus-metrics/[more info]). 416 | 417 | [source,yaml] 418 | ---- 419 | netbox_metrics_dir: netbox_metrics 420 | netbox_metrics_path: "/run/{{ netbox_metrics_dir }}" 421 | ---- 422 | 423 | The directory name where the metrics files are stored can be set with `netbox_metrics_dir`. 424 | 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`). 425 | 426 | [source,yaml] 427 | netbox_keep_uwsgi_updated: false 428 | 429 | Toggle `netbox_keep_uwsgi_updated` to `true` if you wish to ensure your uwsgi server is the latest release, 430 | otherwise uwsgi will not be updated on subsequent runs of your playbook. 431 | 432 | [source,yaml] 433 | netbox_uwsgi_options: {} 434 | 435 | Specify extra configuration options to insert into `uwsgi.ini` here. 436 | This is expected to be a dictionary of key/value pairs, e.g. `buffer-size: 65535`. 437 | 438 | [source,yaml] 439 | netbox_uwsgi_in_venv: false 440 | 441 | Toggle `netbox_uwsgi_in_venv` to `true` if you want `uwsgi` to be installed in the same virtual environment as NetBox. 442 | Otherwise, it will be installed system-wide into the library path of the python version used to created the virtual environment (normal/legacy behavior). 443 | 444 | WARNING: There's a possibility that this may become the default in a later version of this role (I think after further cross-platform testing). 445 | See https://github.com/lae/ansible-role-netbox/issues/144[issue #144] for further details. 446 | 447 | [source,yaml] 448 | netbox_install_epel: true 449 | 450 | Toggle `netbox_install_epel` to `false` if you do not want this role to install the Fedora EPEL for you. 451 | This can be useful for enterprise environments where the system's repositories are managed/mirrored by the enterprise. 452 | 453 | [source,yaml] 454 | ---- 455 | netbox_packages: [] 456 | netbox_python_packages: [] 457 | netbox_python_binary: /usr/bin/python{{ some version }} 458 | netbox_ldap_packages: [] 459 | ---- 460 | 461 | These variables are dynamically generated based on the target distribution. 462 | You can check the defaults for these underneath the `vars/` directory. 463 | You can use these variables to target an unsupported operating system (although feel free to open a PR to add in support!) 464 | or to specify a custom Python interpreter (such as PyPy) to be used for deployment. 465 | Although, please note that support by this role may be limited for alternative Python installations. 466 | 467 | == Example Playbook 468 | 469 | The following installs PostgreSQL and creates a user with @geerlingguy's robust Postgres role, 470 | then proceeds to deploy and configure NetBox using a local unix socket to talk to the Postgres server with the default netbox database user. 471 | 472 | [source,yaml,subs="attributes"] 473 | ---- 474 | - hosts: netbox.idolactiviti.es 475 | become: yes 476 | roles: 477 | - geerlingguy.postgresql 478 | - davidwittman.redis 479 | - {role} 480 | vars: 481 | netbox_stable: true 482 | netbox_database_socket: "{{ postgresql_unix_socket_directories[0] }}" 483 | netbox_superuser_password: netbox 484 | netbox_socket: "0.0.0.0:80" 485 | netbox_config: 486 | ALLOWED_HOSTS: 487 | - netbox.idolactiviti.es 488 | MEDIA_ROOT: "{{ netbox_shared_path }}/media" 489 | REPORTS_ROOT: "{{ netbox_shared_path }}/reports" 490 | SCRIPTS_ROOT: "{{ netbox_shared_path }}/scripts" 491 | postgresql_users: 492 | - name: "{{ netbox_database_user }}" 493 | role_attr_flags: CREATEDB,NOSUPERUSER 494 | redis_bind: 127.0.0.1 495 | redis_version: 6.0.9 496 | redis_checksum: sha256:dc2bdcf81c620e9f09cfd12e85d3bc631c897b2db7a55218fd8a65eaa37f86dd 497 | ---- 498 | 499 | Note the `CREATEDB` attribute. 500 | 501 | Assuming you have a PG server already running with the user `netbox_prod_user` created, it owns a database called `netbox_prod`, 502 | and it allows the host you're installing NetBox on to authenticate with it over TCP: 503 | 504 | [source,yaml,subs="attributes"] 505 | ---- 506 | - hosts: netbox.idolactiviti.es 507 | become: yes 508 | roles: 509 | - davidwittman.redis 510 | - {role} 511 | vars: 512 | netbox_stable: true 513 | netbox_superuser_password: netbox 514 | netbox_socket: "0.0.0.0:80" 515 | netbox_config: 516 | ALLOWED_HOSTS: 517 | - "{{ inventory_hostname }}" 518 | MEDIA_ROOT: "{{ netbox_shared_path }}/media" 519 | REPORTS_ROOT: "{{ netbox_shared_path }}/reports" 520 | SCRIPTS_ROOT: "{{ netbox_shared_path }}/scripts" 521 | netbox_database_host: pg-netbox.idolactiviti.es 522 | netbox_database_port: 15432 523 | netbox_database: netbox_prod 524 | netbox_database_user: netbox_prod_user 525 | netbox_database_password: "very_secure_password_for_prod" 526 | netbox_database_maintenance: netbox_prod 527 | redis_bind: 127.0.0.1 528 | redis_version: 6.0.9 529 | redis_checksum: sha256:dc2bdcf81c620e9f09cfd12e85d3bc631c897b2db7a55218fd8a65eaa37f86dd 530 | ---- 531 | 532 | See the `examples/` directory for more. 533 | 534 | == Troubleshooting 535 | 536 | === uWSGI resetting TCP connections 537 | 538 | When `netbox_protocol` is set to `http`, uWSGI might exhibit strange behaviour and reset TCP connections seemingly at random. 539 | This can manifest in a `connection reset by peer` error, for example when working with the API using https://github.com/netbox-community/pynetbox[pynetbox]. 540 | 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. 541 | See https://github.com/lae/ansible-role-netbox/issues/130#issuecomment-847571006[this GitHub issue] for a related discussion. 542 | 543 | [source,yaml,subs="attributes"] 544 | ---- 545 | netbox_uwsgi_options: 546 | http-keepalive: "true" 547 | http-auto-chunked: "true" 548 | add-header: "Connection: Close" 549 | ---- 550 | -------------------------------------------------------------------------------- /Vagrantfile: -------------------------------------------------------------------------------- 1 | Vagrant.configure("2") do |config| 2 | config.vm.box = "debian/buster64" 3 | config.vm.network "forwarded_port", guest: 80, host: 8080, auto_correct: true 4 | 5 | config.vm.provision :ansible do |ansible| 6 | ansible.limit = "all,localhost" 7 | ansible.playbook = "tests/vagrant/package_role.yml" 8 | ansible.verbose = true 9 | end 10 | 11 | config.vm.provision :ansible do |ansible| 12 | ansible.limit = "all" 13 | ansible.playbook = "tests/vagrant/provision.yml" 14 | ansible.verbose = true 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # defaults file for lae.netbox 3 | netbox_stable: false 4 | netbox_stable_version: 3.0.12 5 | netbox_stable_uri: "https://github.com/netbox-community/netbox/archive/v{{ netbox_stable_version }}.tar.gz" 6 | 7 | netbox_git: false 8 | netbox_git_version: develop 9 | netbox_git_uri: "https://github.com/netbox-community/netbox.git" 10 | 11 | netbox_install_epel: true 12 | 13 | netbox_superuser_enabled: true 14 | netbox_superuser_username: admin 15 | # netbox_superuser_password: changeme 16 | netbox_superuser_email: admin@localhost 17 | netbox_superuser_create_token: false 18 | 19 | netbox_database: netbox 20 | netbox_database_user: netbox 21 | # netbox_database_password: changeme 22 | # netbox_database_host: localhost 23 | netbox_database_port: 5432 24 | # netbox_database_socket: /var/run/postgresql 25 | netbox_database_alt_socket: false 26 | netbox_database_conn_age: 0 27 | netbox_database_options: {} 28 | netbox_database_maintenance: "postgres" 29 | 30 | netbox_redis_host: 127.0.0.1 31 | netbox_redis_sentinels: [] 32 | netbox_redis_sentinel_service: 'netbox' 33 | netbox_redis_port: 6379 34 | netbox_redis_password: '' 35 | netbox_redis_database: 0 36 | netbox_redis_default_timeout: 300 37 | netbox_redis_ssl_enabled: false 38 | netbox_redis_insecure_skip_tls_verify: false 39 | 40 | netbox_redis_cache_host: "{{ netbox_redis_host }}" 41 | netbox_redis_cache_sentinels: "{{ netbox_redis_sentinels }}" 42 | netbox_redis_cache_sentinel_service: "{{ netbox_redis_sentinel_service }}" 43 | netbox_redis_cache_port: "{{ netbox_redis_port }}" 44 | netbox_redis_cache_database: 1 45 | netbox_redis_cache_password: "{{ netbox_redis_password }}" 46 | netbox_redis_cache_default_timeout: "{{ netbox_redis_default_timeout }}" 47 | netbox_redis_cache_ssl_enabled: "{{ netbox_redis_ssl_enabled }}" 48 | netbox_redis_cache_insecure_skip_tls_verify: "{{ netbox_redis_insecure_skip_tls_verify }}" 49 | 50 | netbox_metrics_enabled: false 51 | netbox_metrics_dir: netbox_metrics 52 | netbox_metrics_path: "/run/{{ netbox_metrics_dir }}" 53 | 54 | netbox_config: {} 55 | 56 | netbox_scripts: [] 57 | netbox_reports: [] 58 | 59 | netbox_user: netbox 60 | netbox_group: netbox 61 | netbox_home: /srv/netbox 62 | netbox_releases_path: "{{ netbox_home }}/releases" 63 | netbox_git_repo_path: "{{ netbox_releases_path }}/git-repo" 64 | netbox_git_deploy_path: "{{ netbox_releases_path }}/git-deploy" 65 | netbox_stable_path: "{{ netbox_releases_path }}/netbox-{{ netbox_stable_version }}" 66 | netbox_current_path: "{{ netbox_home }}/current" 67 | netbox_shared_path: "{{ netbox_home }}/shared" 68 | 69 | netbox_socket: "127.0.0.1:8000" 70 | netbox_protocol: http 71 | netbox_processes: "{{ ansible_processor_vcpus | default(1) }}" 72 | netbox_application_log: "file:{{ netbox_shared_path }}/application.log" 73 | netbox_requests_log: "file:{{ netbox_shared_path }}/requests.log" 74 | 75 | netbox_ldap_enabled: false 76 | netbox_ldap_config_template: netbox_ldap_config.py.j2 77 | 78 | # netbox_local_settings_file: "{{ playbook_dir }}/files/netbox/local_settings.py" 79 | 80 | netbox_napalm_enabled: false 81 | netbox_napalm_packages: 82 | - napalm 83 | 84 | netbox_pip_packages: [] 85 | netbox_pip_constraints: 86 | # Blacklist pynacl 1.3.0 due to https://github.com/pyca/pynacl/issues/479 87 | - 'pynacl!=1.3.0' 88 | # Blacklist django-rq 2.3.1 due to https://github.com/rq/django-rq/issues/421 89 | # https://github.com/netbox-community/netbox/issues/4633 90 | - 'django-rq!=2.3.1' 91 | # If you're using Netbox 2.11.3 or below, uncomment the below to fix database 92 | # migrations. https://github.com/pallets/markupsafe/issues/284 93 | # - 'MarkupSafe<2.1.0' 94 | 95 | netbox_keep_uwsgi_updated: false 96 | netbox_uwsgi_in_venv: false 97 | netbox_uwsgi_options: {} 98 | netbox_rqworker_processes: 1 99 | -------------------------------------------------------------------------------- /examples/netbox_config.yml: -------------------------------------------------------------------------------- 1 | --- 2 | netbox_config: 3 | # SECRET_KEY: "hLk3ED%o#P0teb&UjKN)Quvr=SW$HcM^Z(Rzy_sBXFfpY+5TVC" # let this be generated by the role so you don't have to store it 4 | ALLOWED_HOSTS: 5 | - 127.0.0.1 6 | - localhost 7 | ALLOWED_URL_SCHEMES: 8 | - https 9 | - http 10 | - ftp 11 | - mailto 12 | ADMINS: 13 | - 14 | - Hank Hill 15 | - hhill@example.com 16 | - 17 | - Dale Gribble 18 | - dgribble@example.com 19 | # note that the array is nested above 20 | BANNER_LOGIN: '' 21 | BANNER_TOP: &BANNER_TOP 'Your banner text' 22 | BANNER_BOTTOM: *BANNER_TOP 23 | # you probably won't need this, but you can reference other variables like above 24 | BASE_PATH: netbox/ 25 | CACHE_TIMEOUT: 900 26 | CHANGELOG_RETENTION: 90 27 | CORS_ORIGIN_ALLOW_ALL: false 28 | # CORS_ORIGIN_REGEX_WHITELIST: 29 | CORS_ORIGIN_WHITELIST: 30 | - hostname.domain.example 31 | DATE_FORMAT: N j, Y 32 | DATETIME_FORMAT: 'N j, Y g:i a' 33 | DEBUG: true 34 | # yes, no, false, true, False, True are all valid booleans in Ansible - they will be inserted correctly in configuration.py 35 | DOCS_ROOT: docs/ 36 | ENFORCE_GLOBAL_UNIQUE: false 37 | EMAIL: 38 | SERVER: localhost 39 | PORT: 25 40 | USERNAME: user@localhost 41 | PASSWORD: password 42 | TIMEOUT: 10 43 | FROM_EMAIL: notifications@localhost 44 | EXEMPT_VIEW_PERMISSIONS: 45 | - dcim.site 46 | - ipam.prefix 47 | HTTP_PROXIES: 48 | http: http://localhost:3128 49 | INTERNAL_IPS: 50 | - 127.0.0.1 51 | - ::1 52 | LOGGING: 53 | version: 1 54 | disable_existing_loggers: false 55 | handlers: 56 | console: 57 | class: logging.StreamHandler 58 | loggers: 59 | django: 60 | handlers: 61 | - console 62 | level: INFO 63 | LOGIN_REQUIRED: true 64 | LOGIN_TIMEOUT: 1209600 65 | MAINTENANCE_MODE: false 66 | MAPS_URL: https://maps.google.com/?q= 67 | MAX_PAGE_SIZE: 500 68 | MEDIA_ROOT: /srv/netbox_media 69 | METRICS_ENABLED: true 70 | NAPALM_USERNAME: netbox 71 | NAPALM_PASSWORD: NetBox42 72 | NAPALM_TIMEOUT: 30 73 | NAPALM_ARGS: 74 | keepalive: 60 75 | PAGINATE_COUNT: 100 76 | PREFER_IPV4: false 77 | RACK_ELEVATION_DEFAULT_UNIT_HEIGHT: 22 78 | RACK_ELEVATION_DEFAULT_UNIT_WIDTH: 220 79 | REPORTS_ROOT: /srv/netbox_reports 80 | SESSION_FILE_PATH: "{{ netbox_shared_path }}/sessions" 81 | # quotes aren't necessary as you can see - but in my opinion quotes make this more readable 82 | SHORT_DATE_FORMAT: 'Y-m-d' 83 | SHORT_DATETIME_FORMAT: 'Y-m-d H:i' 84 | SHORT_TIME_FORMAT: 'H:i:s' 85 | TIME_FORMAT: 'g:i a' 86 | TIME_ZONE: UTC 87 | WEBHOOKS_ENABLED: false 88 | -------------------------------------------------------------------------------- /examples/netbox_ldap_config.py.j2: -------------------------------------------------------------------------------- 1 | {{ ansible_managed | comment }} 2 | import ldap 3 | from django_auth_ldap.config import LDAPSearch, GroupOfNamesType 4 | 5 | """ 6 | Read the NetBox LDAP configuration documentation if you need assistance: 7 | http://netbox.readthedocs.io/en/latest/installation/ldap/ 8 | 9 | This is just an example. Modify it to your liking and place it in your 10 | playbook's templates/ directory (or anywhere, but make sure 11 | "netbox_ldap_config_template" is configured to whatever location you place the 12 | template in should it not be in templates/. 13 | """ 14 | 15 | # Use variables like the below if you prefer: 16 | AUTH_LDAP_SERVER_URI = "{{ ldap_server_uri }}" 17 | 18 | # Or just store all your values in this file: 19 | AUTH_LDAP_BIND_DN = "CN=NETBOXSA, OU=Service Accounts,DC=example,DC=com" 20 | # I would however recommend putting passwords in vaulted variables. 21 | AUTH_LDAP_BIND_PASSWORD = "demo" 22 | 23 | AUTH_LDAP_CONNECTION_OPTIONS = { 24 | ldap.OPT_REFERRALS: 0 25 | } 26 | 27 | LDAP_IGNORE_CERT_ERRORS = False 28 | 29 | AUTH_LDAP_USER_SEARCH = LDAPSearch("ou=Users,dc=example,dc=com", 30 | ldap.SCOPE_SUBTREE, 31 | "(sAMAccountName=%(user)s)") 32 | AUTH_LDAP_USER_ATTR_MAP = { 33 | "first_name": "givenName", 34 | "last_name": "sn" 35 | } 36 | 37 | AUTH_LDAP_GROUP_SEARCH = LDAPSearch("dc=example,dc=com", ldap.SCOPE_SUBTREE, 38 | "(objectClass=group)") 39 | AUTH_LDAP_GROUP_TYPE = GroupOfNamesType() 40 | AUTH_LDAP_REQUIRE_GROUP = "CN=NETBOX_USERS,DC=example,DC=com" 41 | AUTH_LDAP_USER_FLAGS_BY_GROUP = { 42 | "is_active": "cn=active,ou=groups,dc=example,dc=com", 43 | "is_staff": "cn=staff,ou=groups,dc=example,dc=com", 44 | "is_superuser": "cn=superuser,ou=groups,dc=example,dc=com" 45 | } 46 | AUTH_LDAP_FIND_GROUP_PERMS = True 47 | AUTH_LDAP_CACHE_GROUPS = True 48 | AUTH_LDAP_GROUP_CACHE_TIMEOUT = 3600 49 | 50 | # vim: ft=python 51 | -------------------------------------------------------------------------------- /examples/playbook_single_host_deploy.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: all 3 | become: true 4 | roles: 5 | - geerlingguy.postgresql 6 | - davidwittman.redis 7 | - lae.netbox 8 | vars: 9 | netbox_stable: true 10 | netbox_socket: "0.0.0.0:80" 11 | netbox_superuser_password: netbox 12 | netbox_config: 13 | ALLOWED_HOSTS: 14 | - "{{ inventory_hostname }}" 15 | # The following should not be used in production, probably. 16 | # This playbook gets used by Vagrant where we don't know the actual hostname. 17 | - "*" 18 | MEDIA_ROOT: "{{ netbox_shared_path }}/media" 19 | REPORTS_ROOT: "{{ netbox_shared_path }}/reports" 20 | SCRIPTS_ROOT: "{{ netbox_shared_path }}/scripts" 21 | netbox_database_socket: "{{ postgresql_unix_socket_directories[0] }}" 22 | netbox_keep_uwsgi_updated: true 23 | postgresql_users: 24 | - name: "{{ netbox_database_user }}" 25 | role_attr_flags: CREATEDB,NOSUPERUSER 26 | redis_bind: 127.0.0.1 27 | redis_version: 6.0.9 28 | redis_checksum: sha256:dc2bdcf81c620e9f09cfd12e85d3bc631c897b2db7a55218fd8a65eaa37f86dd 29 | pre_tasks: 30 | - name: Enable Subscription Manager Repos 31 | rhsm_repository: 32 | name: "{{ item }}" 33 | loop: 34 | - rhel-*-optional-rpms 35 | - rhel-*-extras-rpms 36 | when: "ansible_distribution == 'Red Hat Enterprise Linux'" 37 | - block: 38 | - name: Set PostgreSQL facts to use PG10 for RedHat distributions 39 | set_fact: 40 | postgresql_version: 10 41 | postgresql_packages: 42 | - postgresql10 43 | - postgresql10-server 44 | - postgresql10-contrib 45 | - postgresql10-libs 46 | postgresql_data_dir: /var/lib/pgsql/10/data 47 | postgresql_bin_path: /usr/pgsql-10/bin 48 | postgresql_config_path: /var/lib/pgsql/10/data 49 | postgresql_daemon: postgresql-10 50 | - name: Install the EPEL yum repository 51 | yum: 52 | name: epel-release 53 | - name: Install the PostgreSQL yum repository 54 | yum: 55 | name: "https://download.postgresql.org/pub/repos/yum/reporpms/EL-{{ ansible_distribution_major_version }}-x86_64/pgdg-redhat-repo-latest.noarch.rpm" 56 | when: "ansible_os_family == 'RedHat' and ansible_distribution_major_version =='7'" 57 | 58 | # You can use this playbook as-is to setup a full NetBox server, just change 59 | # the FQDN below. It'll accept HTTP requests on specified FQDN. 60 | # 61 | # ansible-playbook -i netbox.example.com, playbook_single_host_deploy.yml 62 | # 63 | # Note that for RH systems, PostgreSQL is installed from upstream. 64 | -------------------------------------------------------------------------------- /handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # handlers file for lae.netbox 3 | - name: restart netbox.socket 4 | systemd: 5 | name: netbox.socket 6 | state: restarted 7 | daemon_reload: true 8 | 9 | - name: restart netbox.service 10 | systemd: 11 | name: netbox.service 12 | state: restarted 13 | daemon_reload: true 14 | 15 | - name: reload netbox.service 16 | systemd: 17 | name: netbox.service 18 | state: reloaded 19 | 20 | - name: restart netbox-rqworker.service 21 | systemd: 22 | name: "netbox-rqworker@{{ item }}.service" 23 | state: restarted 24 | daemon_reload: true 25 | with_sequence: count="{{ netbox_rqworker_processes }}" 26 | -------------------------------------------------------------------------------- /meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | galaxy_info: 3 | namespace: lae 4 | role_name: netbox 5 | author: Musee Ullah 6 | description: Installs and configures NetBox, a DCIM suite, in a production setting. 7 | license: MIT 8 | min_ansible_version: 2.5 9 | platforms: 10 | - name: Ubuntu 11 | versions: 12 | - bionic 13 | - xenial 14 | - focal 15 | - jammy 16 | - name: Debian 17 | versions: 18 | - buster 19 | - stretch 20 | - bullseye 21 | - bookworm 22 | - name: EL 23 | versions: 24 | - 7 25 | - 8 26 | - 9 27 | galaxy_tags: 28 | - dcim 29 | - ipam 30 | - web 31 | - networking 32 | - datacenter 33 | dependencies: [] 34 | -------------------------------------------------------------------------------- /molecule/default/converge.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Converge 3 | hosts: all 4 | become: true 5 | vars: 6 | redis_version: 6.2.1 7 | netbox_stable_version: 2.10.8 8 | netbox_stable: true 9 | netbox_socket: "0.0.0.0:80" 10 | netbox_superuser_password: netbox 11 | netbox_superuser_create_token: true 12 | netbox_config: 13 | ALLOWED_HOSTS: 14 | - "{{ inventory_hostname }}" 15 | # The following should not be used in production, probably. 16 | # This playbook gets used by Vagrant where we don't know the actual hostname. 17 | - "*" 18 | MEDIA_ROOT: "{{ netbox_shared_path }}/media" 19 | REPORTS_ROOT: "{{ netbox_shared_path }}/reports" 20 | SCRIPTS_ROOT: "{{ netbox_shared_path }}/scripts" 21 | netbox_database_socket: "{{ postgresql_unix_socket_directories[0] }}" 22 | # webhooks 23 | netbox_webhooks_enabled: true 24 | # db 25 | postgresql_users: 26 | - name: "{{ netbox_database_user }}" 27 | role_attr_flags: CREATEDB,NOSUPERUSER 28 | ## REDIS server install 29 | redis_bind: 127.0.0.1 30 | netbox_rqworker_processes: 2 31 | roles: 32 | - geerlingguy.postgresql 33 | - davidwittman.redis 34 | - ansible-role-netbox 35 | -------------------------------------------------------------------------------- /molecule/default/molecule.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependency: 3 | name: galaxy 4 | driver: 5 | name: vagrant 6 | provider: 7 | name: virtualbox 8 | lint: | 9 | set -e 10 | yamllint . 11 | ansible-lint 12 | flake8 13 | platforms: 14 | - name: debian-9 15 | box: generic/debian9 16 | provisioner: 17 | name: ansible 18 | log: true 19 | lint: 20 | name: ansible-lint 21 | enabled: false 22 | scenario: 23 | name: default 24 | verifier: 25 | name: testinfra 26 | lint: | 27 | set -e 28 | flake8 29 | -------------------------------------------------------------------------------- /molecule/default/prepare.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Prepare 3 | hosts: all 4 | gather_facts: false 5 | tasks: [] 6 | -------------------------------------------------------------------------------- /molecule/default/requirements.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - src: geerlingguy.postgresql 3 | - src: davidwittman.redis 4 | -------------------------------------------------------------------------------- /molecule/default/tests/test_default.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | import testinfra.utils.ansible_runner 4 | 5 | testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner( 6 | os.environ['MOLECULE_INVENTORY_FILE']).get_hosts('all') 7 | 8 | 9 | def test_services(host): 10 | services = [ 11 | "netbox.socket", 12 | "netbox.service", 13 | "netbox-rqworker@1.service" 14 | "netbox-rqworker@2.service" 15 | ] 16 | for service in services: 17 | s = host.service(service) 18 | assert s.is_enabled 19 | assert s.is_running 20 | 21 | 22 | def test_sockets(host): 23 | assert host.socket("tcp://0.0.0.0:80") 24 | 25 | 26 | def test_files(host): 27 | files = [ 28 | "/srv/netbox/shared/application.log", 29 | "/srv/netbox/shared/configuration.py" 30 | ] 31 | for file in files: 32 | assert host.file(file) 33 | -------------------------------------------------------------------------------- /tasks/deploy_netbox.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Create NetBox application directories 3 | file: 4 | path: "{{ item }}" 5 | state: directory 6 | owner: "{{ netbox_user }}" 7 | group: "{{ netbox_group }}" 8 | loop: 9 | - "{{ netbox_home }}" 10 | - "{{ netbox_releases_path }}" 11 | - "{{ netbox_shared_path }}" 12 | - "{{ _netbox_config.MEDIA_ROOT }}" 13 | - "{{ _netbox_config.MEDIA_ROOT }}/image-attachments" 14 | - "{{ _netbox_config.REPORTS_ROOT }}" 15 | - "{{ _netbox_config.SCRIPTS_ROOT }}" 16 | 17 | - include_tasks: "install_via_{{ 'git' if netbox_git else 'stable' }}.yml" 18 | 19 | - import_tasks: generate_secret_key.yml 20 | when: 21 | - _netbox_config.SECRET_KEY is not defined 22 | 23 | - name: Create NetBox virtualenv 24 | pip: 25 | name: 26 | - pip 27 | - setuptools 28 | state: latest 29 | virtualenv: "{{ netbox_virtualenv_path }}" 30 | virtualenv_command: "{{ netbox_python_binary }} -m venv" 31 | become: true 32 | become_user: "{{ netbox_user }}" 33 | retries: 2 34 | register: _netbox_virtualenv_setup 35 | until: _netbox_virtualenv_setup is succeeded 36 | 37 | - name: Create constraints files 38 | ansible.builtin.template: 39 | src: pip_constraints.j2 40 | dest: "{{ netbox_shared_path }}/constraints.txt" 41 | owner: "{{ netbox_user }}" 42 | group: "{{ netbox_group }}" 43 | 44 | - name: Copy requirements.txt from netbox current path to shared path 45 | ansible.builtin.copy: 46 | src: "{{ netbox_current_path }}/requirements.txt" 47 | dest: "{{ netbox_shared_path }}/requirements.txt" 48 | owner: "{{ netbox_user }}" 49 | group: "{{ netbox_group }}" 50 | remote_src: true 51 | changed_when: false 52 | 53 | - name: Override exact version requirements in shared path's requirements.txt if conflicting constraint is specified 54 | ansible.builtin.replace: 55 | path: "{{ netbox_shared_path }}/requirements.txt" 56 | regexp: '^({{ item | regex_replace("(==.*)", "") }})==.*' 57 | replace: '\1' 58 | loop: "{{ netbox_pip_constraints }}" 59 | changed_when: false 60 | when: "'==' in item" 61 | 62 | - name: Install needed Python dependencies 63 | ansible.builtin.pip: 64 | requirements: "{{ netbox_shared_path }}/requirements.txt" 65 | extra_args: "-c {{ netbox_shared_path }}/constraints.txt" 66 | virtualenv: "{{ netbox_virtualenv_path }}" 67 | become: true 68 | become_user: "{{ netbox_user }}" 69 | retries: 2 70 | register: _netbox_virtualenv_setup 71 | until: _netbox_virtualenv_setup is succeeded 72 | 73 | - name: Install selected optional Python dependencies 74 | ansible.builtin.pip: 75 | name: "{{ item }}" 76 | state: present 77 | virtualenv: "{{ netbox_virtualenv_path }}" 78 | become: true 79 | become_user: "{{ netbox_user }}" 80 | retries: 2 81 | register: _netbox_pip_additional_install 82 | until: _netbox_pip_additional_install is succeeded 83 | when: (_netbox_python_deps | length) > 0 84 | loop: "{{ _netbox_python_deps }}" 85 | notify: 86 | - restart netbox.service 87 | - restart netbox-rqworker.service 88 | 89 | # local_requirements.txt 90 | - name: Copy selected optional Python dependencies to local_requirements.txt 91 | ansible.builtin.copy: 92 | content: | 93 | {% for dep in _netbox_python_deps %} 94 | {{ dep }} 95 | {% endfor %} 96 | dest: "{{ netbox_current_path }}/local_requirements.txt" 97 | owner: "{{ netbox_user }}" 98 | group: "{{ netbox_group }}" 99 | when: (_netbox_python_deps | length) > 0 100 | 101 | - name: NetBox Configuration 102 | block: 103 | # configuration.py 104 | - name: Generate NetBox configuration file 105 | ansible.builtin.template: 106 | src: templates/configuration.py.j2 107 | dest: "{{ netbox_shared_path }}/configuration.py" 108 | owner: "{{ netbox_user }}" 109 | group: "{{ netbox_group }}" 110 | mode: 0640 111 | validate: "{{ netbox_virtualenv_path }}/bin/python -c \"import py_compile,os; f=r'%s';\ 112 | c='/tmp/' + os.path.basename(os.path.dirname(f)) + '-' + os.path.basename(f) + 'c';\ 113 | py_compile.compile(f, c); os.remove(c)\"" 114 | notify: 115 | - restart netbox-rqworker.service 116 | 117 | - name: Symlink NetBox configuration file into the active NetBox release 118 | ansible.builtin.file: 119 | src: "{{ netbox_shared_path }}/configuration.py" 120 | dest: "{{ netbox_config_path }}/configuration.py" 121 | owner: "{{ netbox_user }}" 122 | group: "{{ netbox_group }}" 123 | state: link 124 | 125 | # ldap_config.py 126 | - name: Generate LDAP configuration for NetBox if enabled 127 | ansible.builtin.template: 128 | src: "{{ netbox_ldap_config_template }}" 129 | dest: "{{ netbox_shared_path }}/ldap_config.py" 130 | owner: "{{ netbox_user }}" 131 | group: "{{ netbox_group }}" 132 | mode: 0640 133 | validate: "{{ netbox_virtualenv_path }}/bin/python -c \"import py_compile,os; f=r'%s';\ 134 | c='/tmp/' + os.path.basename(os.path.dirname(f)) + '-' + os.path.basename(f) + 'c';\ 135 | py_compile.compile(f, c); os.remove(c)\"" 136 | when: 137 | - netbox_ldap_enabled 138 | 139 | - name: Symlink/Remove NetBox LDAP configuration file into/from the active NetBox release 140 | ansible.builtin.file: 141 | # Omitting the src attribute is necessary when state: absent 142 | src: "{{ netbox_shared_path + '/ldap_config.py' if netbox_ldap_enabled else omit }}" 143 | dest: "{{ netbox_config_path }}/ldap_config.py" 144 | owner: "{{ netbox_user }}" 145 | group: "{{ netbox_group }}" 146 | mode: 0640 147 | state: "{{ 'link' if netbox_ldap_enabled else 'absent' }}" 148 | 149 | # local_settings.py 150 | - name: Copy NetBox local_settings.py into shared (ignore if it doesn't exist) 151 | ansible.builtin.copy: 152 | src: "{{ netbox_local_settings_file }}" 153 | dest: "{{ netbox_shared_path }}/local_settings.py" 154 | owner: "{{ netbox_user }}" 155 | group: "{{ netbox_group }}" 156 | mode: 0640 157 | when: 158 | - netbox_local_settings_file is defined 159 | 160 | - name: Symlink/Remove NetBox local_settings.py file into/from the active NetBox release 161 | ansible.builtin.file: 162 | # Omitting the src attribute is necessary when state: absent 163 | src: "{{ netbox_shared_path + '/local_settings.py' if netbox_local_settings_file is defined else omit }}" 164 | dest: "{{ netbox_config_path }}/local_settings.py" 165 | owner: "{{ netbox_user }}" 166 | group: "{{ netbox_group }}" 167 | mode: 0640 168 | state: "{{ 'link' if netbox_local_settings_file is defined else 'absent' }}" 169 | notify: 170 | - reload netbox.service 171 | 172 | - name: Copy NetBox scripts into SCRIPTS_ROOT 173 | copy: 174 | src: "{{ item.src }}" 175 | dest: "{{ _netbox_config.SCRIPTS_ROOT }}/{{ item.name }}.py" 176 | owner: "{{ netbox_user }}" 177 | group: "{{ netbox_group }}" 178 | loop: "{{ netbox_scripts }}" 179 | 180 | - name: Copy NetBox reports into REPORTS_ROOT 181 | copy: 182 | src: "{{ item.src }}" 183 | dest: "{{ _netbox_config.REPORTS_ROOT }}/{{ item.name }}.py" 184 | owner: "{{ netbox_user }}" 185 | group: "{{ netbox_group }}" 186 | loop: "{{ netbox_reports }}" 187 | 188 | - name: Schedule daily housekeeping cronjob 189 | cron: 190 | name: "Netbox housekeeping" 191 | special_time: daily 192 | job: "{{ netbox_virtualenv_path }}/bin/python {{ netbox_current_path }}/netbox/manage.py housekeeping" 193 | user: "{{ netbox_user }}" 194 | cron_file: "netbox" 195 | when: 196 | - netbox_stable and netbox_stable_version is version('3.0.0', '>=') 197 | or netbox_git and _netbox_git_contains_housekeeping.rc == 0 198 | 199 | - block: 200 | - name: Run database migrations for NetBox 201 | django_manage: 202 | command: migrate 203 | app_path: "{{ netbox_current_path }}/netbox" 204 | virtualenv: "{{ netbox_virtualenv_path }}" 205 | retries: 2 206 | register: _netbox_db_migration 207 | until: _netbox_db_migration is success 208 | 209 | - name: Trace missing cable paths for NetBox 210 | django_manage: 211 | command: "trace_paths --no-input" 212 | app_path: "{{ netbox_current_path }}/netbox" 213 | virtualenv: "{{ netbox_virtualenv_path }}" 214 | when: 215 | - netbox_stable and netbox_stable_version is version('2.10.0', '>=') 216 | or netbox_git and _netbox_git_contains_trace_paths.rc == 0 217 | 218 | - name: Build the local documentation 219 | shell: 220 | cmd: "{{ netbox_virtualenv_path }}/bin/mkdocs build" 221 | chdir: "{{ netbox_current_path }}" 222 | when: 223 | - netbox_stable and netbox_stable_version is version('3.0.0', '>=') 224 | or netbox_git and _netbox_git_contains_mkdocs.rc == 0 225 | 226 | - name: Create a super user for NetBox 227 | shell: "printf '{{ netbox_superuser_script }}' |\ 228 | {{ netbox_virtualenv_path }}/bin/python {{ netbox_current_path }}/netbox/manage.py shell" 229 | register: _netbox_superuser_result 230 | changed_when: "'changed' in _netbox_superuser_result.stdout" 231 | when: 232 | - netbox_superuser_enabled 233 | 234 | - name: Create a super user token for NetBox 235 | shell: "printf '{{ netbox_superuser_token }}' |\ 236 | {{ netbox_virtualenv_path }}/bin/python {{ netbox_current_path }}/netbox/manage.py shell" 237 | register: _netbox_superuser_token 238 | changed_when: "'changed' in _netbox_superuser_token.stdout" 239 | when: 240 | - netbox_superuser_create_token 241 | - netbox_superuser_enabled 242 | 243 | - name: Generate static assets for NetBox 244 | django_manage: 245 | command: collectstatic 246 | app_path: "{{ netbox_current_path }}/netbox" 247 | virtualenv: "{{ netbox_virtualenv_path }}" 248 | 249 | - name: Clear expired user sessions in NetBox 250 | django_manage: 251 | command: clearsessions 252 | app_path: "{{ netbox_current_path }}/netbox" 253 | virtualenv: "{{ netbox_virtualenv_path }}" 254 | 255 | - name: Clear stale content types in NetBox 256 | django_manage: 257 | command: "remove_stale_contenttypes --no-input" 258 | app_path: "{{ netbox_current_path }}/netbox" 259 | virtualenv: "{{ netbox_virtualenv_path }}" 260 | 261 | - name: Clear cached data in NetBox < 3 262 | django_manage: 263 | command: "invalidate all" 264 | app_path: "{{ netbox_current_path }}/netbox" 265 | virtualenv: "{{ netbox_virtualenv_path }}" 266 | when: 267 | - netbox_stable and netbox_stable_version is version('3.0.0', '<') 268 | or netbox_git and _netbox_git_contains_invalidate_removed.rc != 0 269 | 270 | - name: Clear cached data in NetBox 3.2.3 to 3.6 271 | django_manage: 272 | command: "clearcache" 273 | app_path: "{{ netbox_current_path }}/netbox" 274 | virtualenv: "{{ netbox_virtualenv_path }}" 275 | when: 276 | - netbox_stable and netbox_stable_version is version('3.2.2', '>') 277 | and netbox_stable_version is version('3.7.0', '<') 278 | or netbox_git and ( _netbox_git_contains_add_clearcache.rc == 0 279 | and _netbox_git_contains_remove_clearcache.rc != 0 ) 280 | 281 | - name: Rebuild the search cache (lazily) 282 | django_manage: 283 | command: "reindex --lazy" 284 | app_path: "{{ netbox_current_path }}/netbox" 285 | virtualenv: "{{ netbox_virtualenv_path }}" 286 | when: 287 | - netbox_stable and netbox_stable_version is version('3.4.4', '>') 288 | or netbox_git and _netbox_git_contains_reindex_lazy.rc == 0 289 | 290 | become: true 291 | become_user: "{{ netbox_user }}" 292 | -------------------------------------------------------------------------------- /tasks/generate_secret_key.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Generate a SECRET_KEY for NetBox if unspecified 3 | shell: "set -o pipefail; {{ netbox_python_binary }} {{ netbox_current_path }}/netbox/generate_secret_key.py\ 4 | | tr -d $'\n' > {{ netbox_shared_path }}/generated_secret_key" 5 | args: 6 | creates: "{{ netbox_shared_path }}/generated_secret_key" 7 | executable: /bin/bash 8 | become: true 9 | become_user: "{{ netbox_user }}" 10 | 11 | - name: Load saved SECRET_KEY 12 | slurp: 13 | src: "{{ netbox_shared_path }}/generated_secret_key" 14 | register: _netbox_secret_key_file 15 | 16 | - name: Set netbox_config.SECRET_KEY to generated SECRET_KEY 17 | set_fact: 18 | _netbox_config: "{{ _netbox_config | combine({'SECRET_KEY': _netbox_secret_key_file['content'] | b64decode}) }}" 19 | -------------------------------------------------------------------------------- /tasks/install_packages_apt.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Install required packages for selected NetBox configuration 3 | apt: 4 | name: "{{ _netbox_apt_packages | flatten }}" 5 | state: present 6 | cache_valid_time: 3600 7 | update_cache: true 8 | vars: 9 | _netbox_apt_packages: 10 | - "{{ netbox_python_packages }}" 11 | - "{{ netbox_packages }}" 12 | - "{{ netbox_ldap_packages if netbox_ldap_enabled else [] }}" 13 | - "{{ 'git' if netbox_git else [] }}" 14 | - "{{ 'acl' if ('SUDO_USER' in ansible_env and ansible_env.SUDO_USER != 'root') else [] }}" 15 | -------------------------------------------------------------------------------- /tasks/install_packages_dnf.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Install required packages for selected NetBox configuration 3 | dnf: 4 | name: "{{ _netbox_dnf_packages | flatten }}" 5 | state: present 6 | update_cache: true 7 | vars: 8 | _netbox_dnf_packages: 9 | - "{{ 'epel-release' if netbox_install_epel else [] }}" 10 | - "{{ netbox_python_packages }}" 11 | - "{{ netbox_packages }}" 12 | - "{{ netbox_ldap_packages if netbox_ldap_enabled else [] }}" 13 | - "{{ 'git' if netbox_git else [] }}" 14 | - "{{ 'acl' if ('SUDO_USER' in ansible_env and ansible_env.SUDO_USER != 'root') else [] }}" 15 | -------------------------------------------------------------------------------- /tasks/install_packages_yum.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Install EPEL repository 3 | yum: 4 | name: epel-release 5 | state: installed 6 | when: netbox_install_epel 7 | 8 | - name: Install required packages for selected NetBox configuration 9 | yum: 10 | name: "{{ _netbox_yum_packages | flatten }}" 11 | state: present 12 | update_cache: true 13 | vars: 14 | _netbox_yum_packages: 15 | - "{{ netbox_python_packages }}" 16 | - "{{ netbox_packages }}" 17 | - "{{ netbox_ldap_packages if netbox_ldap_enabled else [] }}" 18 | - "{{ 'git' if netbox_git else [] }}" 19 | - "{{ 'acl' if ('SUDO_USER' in ansible_env and ansible_env.SUDO_USER != 'root') else [] }}" 20 | 21 | # python3 pip package not available on EPEL. 22 | - name: Ensure pip is available on Red Hat-based distros 23 | shell: "{{ netbox_python_binary }} -m pip -V || {{ netbox_python_binary }} -m ensurepip" 24 | register: _existence_of_pip 25 | changed_when: "'Successfully installed pip' in _existence_of_pip.stdout" 26 | 27 | # python3 psycopg2/selinux packages are not available on EPEL. 28 | - name: Install psycopg2/selinux via pip on Red Hat-based distros 29 | pip: 30 | name: 31 | - psycopg2-binary 32 | - selinux 33 | state: present 34 | vars: 35 | ansible_python_interpreter: "{{ netbox_python_binary }}" 36 | environment: 37 | PATH: "/usr/local/bin:{{ _path }}" 38 | -------------------------------------------------------------------------------- /tasks/install_via_git.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Clone specified NetBox git repository 3 | git: 4 | repo: "{{ netbox_git_uri }}" 5 | dest: "{{ netbox_git_repo_path }}" 6 | version: "{{ netbox_git_version }}" 7 | register: _netbox_git_repo 8 | become: true 9 | become_user: "{{ netbox_user }}" 10 | 11 | - name: Create git deployment directory for NetBox 12 | file: 13 | path: "{{ netbox_git_deploy_path }}" 14 | owner: "{{ netbox_user }}" 15 | group: "{{ netbox_group }}" 16 | state: directory 17 | 18 | - name: Check for presence of various commits in git history 19 | block: 20 | - name: Check existence of commit 1fb67b7, fixing issue netbox#2239 21 | shell: 'set -o pipefail; git log --format=%H "{{ netbox_git_version }}" | grep ^1fb67b791f1a91c624dae4a1cd256e4cf3ddbb77' 22 | args: 23 | chdir: "{{ netbox_git_repo_path }}" 24 | executable: /bin/bash 25 | register: _netbox_git_contains_issue_2239_fix 26 | changed_when: false 27 | failed_when: "_netbox_git_contains_issue_2239_fix.rc not in [0, 1]" 28 | 29 | - name: Check existence of commit 3590ed3, renaming webhooks to tasks 30 | shell: 'set -o pipefail; git log --format=%H "{{ netbox_git_version }}" | grep ^3590ed378d161dd724fad2dc73ff56da746352f8' 31 | args: 32 | chdir: "{{ netbox_git_repo_path }}" 33 | executable: /bin/bash 34 | register: _netbox_git_contains_tasks_rename 35 | changed_when: false 36 | failed_when: "_netbox_git_contains_tasks_rename.rc not in [0, 1]" 37 | 38 | - name: Check existence of commit 90dbe9b, renaming DEFAULT_TIMEOUT to RQ_DEFAULT_TIMEOUT 39 | shell: 'set -o pipefail; git log --format=%H "{{ netbox_git_version }}" | grep ^90dbe9bf60ab3c72be10fd070c65c26dca543ca5' 40 | args: 41 | chdir: "{{ netbox_git_repo_path }}" 42 | executable: /bin/bash 43 | register: _netbox_git_contains_rq_timeout 44 | changed_when: False 45 | failed_when: "_netbox_git_contains_rq_timeout.rc not in [0, 1]" 46 | 47 | - name: Check existence of commit f560693, introducing trace_paths management command 48 | shell: 'set -o pipefail; git log --format=%H "{{ netbox_git_version }}" | grep ^f560693748d1f35e79ad9d006a8a9b75ef5ae37b' 49 | args: 50 | chdir: "{{ netbox_git_repo_path }}" 51 | executable: /bin/bash 52 | register: _netbox_git_contains_trace_paths 53 | changed_when: False 54 | failed_when: "_netbox_git_contains_trace_paths.rc not in [0, 1]" 55 | 56 | - name: Check existence of commit e165dca, introducing mkdocs command during update 57 | shell: 'set -o pipefail; git log --format=%H "{{ netbox_git_version }}" | grep ^7058d6ca5ae2901383874bcea5fedad31e165dca' 58 | args: 59 | chdir: "{{ netbox_git_repo_path }}" 60 | executable: /bin/bash 61 | register: _netbox_git_contains_mkdocs 62 | changed_when: False 63 | failed_when: "_netbox_git_contains_mkdocs.rc not in [0, 1]" 64 | 65 | - name: Check existence of commit d87ec82, introducing nightly housekeeping command 66 | shell: 'set -o pipefail; git log --format=%H "{{ netbox_git_version }}" | grep ^d87ec82fe34d92a84ee6f2a97ba0a87a53eed015' 67 | args: 68 | chdir: "{{ netbox_git_repo_path }}" 69 | executable: /bin/bash 70 | register: _netbox_git_contains_housekeeping 71 | changed_when: False 72 | failed_when: "_netbox_git_contains_housekeeping.rc not in [0, 1]" 73 | 74 | - name: Check existence of commit 028c876, removing the invalidate command 75 | shell: 'set -o pipefail; git log --format=%H "{{ netbox_git_version }}" | grep ^028c876bcafbaede2731f191512bbebe3f1b6a9e' 76 | args: 77 | chdir: "{{ netbox_git_repo_path }}" 78 | executable: /bin/bash 79 | register: _netbox_git_contains_invalidate_removed 80 | changed_when: False 81 | failed_when: "_netbox_git_contains_invalidate_removed.rc not in [0, 1]" 82 | 83 | - name: Check existence of commit b172ae6, adding the clearcache command 84 | shell: 'set -o pipefail; git log --format=%H "{{ netbox_git_version }}" | grep ^b172ae65d24f6dc161c4b609477a4547bb62a50b' 85 | args: 86 | chdir: "{{ netbox_git_repo_path }}" 87 | executable: /bin/bash 88 | register: _netbox_git_contains_add_clearcache 89 | changed_when: False 90 | failed_when: "_netbox_git_contains_add_clearcache.rc not in [0, 1]" 91 | 92 | - name: Check existence of commit 2d1f882, removing the clearcache command 93 | shell: 'set -o pipefail; git log --format=%H "{{ netbox_git_version }}" | grep ^2d1f88272497ca72d2e1eca8e291c04538c6810e' 94 | args: 95 | chdir: "{{ netbox_git_repo_path }}" 96 | executable: /bin/bash 97 | register: _netbox_git_contains_remove_clearcache 98 | changed_when: False 99 | failed_when: "_netbox_git_contains_remove_clearcache.rc not in [0, 1]" 100 | 101 | - name: Check existence of commit 5a4d8a7, adding the reindex lazy command 102 | shell: 'set -o pipefail; git log --format=%H "{{ netbox_git_version }}" | grep ^5a4d8a71075a4529be8d5ef22d76d69861240f45' 103 | args: 104 | chdir: "{{ netbox_git_repo_path }}" 105 | executable: /bin/bash 106 | register: _netbox_git_contains_reindex_lazy 107 | changed_when: False 108 | failed_when: "_netbox_git_contains_reindex_lazy.rc not in [0, 1]" 109 | 110 | become: true 111 | become_user: "{{ netbox_user }}" 112 | 113 | - name: Archive and extract snapshot of git repository 114 | shell: 'set -o pipefail; git archive "{{ netbox_git_version }}" | tar -x -C "{{ netbox_git_deploy_path }}"' 115 | args: 116 | chdir: "{{ netbox_git_repo_path }}" 117 | executable: /bin/bash 118 | notify: 119 | - reload netbox.service 120 | when: 121 | - _netbox_git_repo is changed 122 | become: true 123 | become_user: "{{ netbox_user }}" 124 | 125 | - name: Symlink git repository to current NetBox directory 126 | file: 127 | src: "{{ netbox_git_deploy_path }}" 128 | dest: "{{ netbox_current_path }}" 129 | owner: "{{ netbox_user }}" 130 | group: "{{ netbox_group }}" 131 | state: link 132 | -------------------------------------------------------------------------------- /tasks/install_via_stable.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Download and extract stable NetBox release 3 | unarchive: 4 | src: "{{ netbox_stable_uri }}" 5 | dest: "{{ netbox_releases_path }}" 6 | creates: "{{ netbox_stable_path }}" 7 | owner: "{{ netbox_user }}" 8 | group: "{{ netbox_group }}" 9 | remote_src: true 10 | 11 | - name: Symlink stable release to current NetBox directory 12 | file: 13 | src: "{{ netbox_stable_path }}" 14 | dest: "{{ netbox_current_path }}" 15 | owner: "{{ netbox_user }}" 16 | group: "{{ netbox_group }}" 17 | state: link 18 | notify: 19 | - reload netbox.service 20 | -------------------------------------------------------------------------------- /tasks/load_variables.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Gather OS specific variables 3 | include_vars: "{{ item }}" 4 | with_first_found: 5 | - "{{ ansible_distribution|lower }}-{{ ansible_distribution_version }}.yml" 6 | - "{{ ansible_distribution|lower }}-{{ ansible_distribution_major_version }}.yml" 7 | - "{{ ansible_distribution|lower }}.yml" 8 | - "{{ ansible_os_family|lower }}-{{ ansible_distribution_major_version }}.yml" 9 | 10 | - name: Define netbox_packages 11 | set_fact: 12 | netbox_packages: "{{ _netbox_packages | list }}" 13 | when: netbox_packages is not defined 14 | 15 | - name: Define netbox_python_packages 16 | set_fact: 17 | netbox_python_packages: "{{ _netbox_python_packages | list }}" 18 | when: netbox_python_packages is not defined 19 | 20 | - name: Define netbox_python_binary 21 | set_fact: 22 | netbox_python_binary: "{{ _netbox_python_binary }}" 23 | when: netbox_python_binary is not defined 24 | 25 | - name: Define netbox_ldap_packages 26 | set_fact: 27 | netbox_ldap_packages: "{{ _netbox_ldap_packages | list }}" 28 | when: netbox_ldap_packages is not defined 29 | 30 | - name: Define _netbox_config 31 | set_fact: 32 | _netbox_config: "{{ _netbox_default_config | combine(netbox_config, recursive=True) }}" 33 | 34 | - name: Generate list of optional Python dependencies 35 | set_fact: 36 | _netbox_python_deps: 37 | - "{{ netbox_napalm_packages if netbox_napalm_enabled else [] }}" 38 | - "{{ 'django-auth-ldap' if netbox_ldap_enabled else [] }}" 39 | - "{{ 'django-storages' if _netbox_storages_module is defined else [] }}" 40 | - "{{ _netbox_storages_map[_netbox_storages_module] if _netbox_storages_module is defined else [] }}" 41 | - "{{ netbox_pip_packages }}" 42 | 43 | - name: Flatten that list of dependencies 44 | set_fact: 45 | _netbox_python_deps: "{{ _netbox_python_deps | flatten }}" 46 | 47 | - name: Identify current execution PATH 48 | shell: "echo $PATH" 49 | register: _path_exec 50 | changed_when: false 51 | check_mode: false 52 | 53 | - name: Set a fact for current execution PATH 54 | set_fact: 55 | _path: "{{ _path_exec.stdout }}" 56 | check_mode: false 57 | 58 | - name: Capture the current Python interpreter 59 | set_fact: 60 | _netbox_global_python: "{{ ansible_python_interpreter }}" 61 | when: ansible_python_interpreter is defined 62 | 63 | - name: Set the execution uwsgi command 64 | set_fact: 65 | netbox_uwsgi_cmd: "/usr/bin/env uwsgi" 66 | when: "not netbox_uwsgi_in_venv | bool" 67 | -------------------------------------------------------------------------------- /tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # tasks file for lae.netbox 3 | - import_tasks: validate_variables.yml 4 | 5 | - import_tasks: load_variables.yml 6 | 7 | - include_tasks: "install_packages_{{ ansible_pkg_mgr }}.yml" 8 | 9 | - name: Switch Ansible's Python interpreter to Python 3 10 | set_fact: 11 | ansible_python_interpreter: "{{ netbox_python_binary }}" 12 | 13 | - name: Recheck new Python interpreter's version 14 | setup: 15 | gather_subset: min 16 | filter: ansible_python_version 17 | 18 | # Can't quite check the effective version of a git installation this early since 19 | # the repo isn't checked out, but most users will be on develop in the first 20 | # place so this dumb check should be good enough. 21 | - name: Ensure Python version installed is compatible with this version of Netbox 22 | assert: 23 | that: 24 | - "ansible_python_version is version(item.python_needed, '>=')" 25 | msg: > 26 | NetBox {{ item.netbox_version_min }} requires at least Python {{ item.python_needed }}. 27 | Please either specify an older NetBox version, upgrade to a newer 28 | distribution that provides Python at least {{ item.python_needed }}, or 29 | set netbox_python_binary to an appropriate Python {{ item.python_needed }} binary. 30 | when: 31 | - netbox_stable and netbox_stable_version is version(item.netbox_version_min, '>=') or netbox_git 32 | loop: "{{ netbox_python_compat_matrix }}" 33 | 34 | - name: Create NetBox user group 35 | group: 36 | name: "{{ netbox_group }}" 37 | 38 | - name: Create NetBox user and home directory 39 | user: 40 | name: "{{ netbox_user }}" 41 | group: "{{ netbox_group }}" 42 | home: "{{ netbox_home }}" 43 | 44 | - name: Ensure Postgres database exists (via socket) 45 | community.postgresql.postgresql_db: 46 | name: "{{ netbox_database }}" 47 | login_user: "{{ netbox_database_user }}" 48 | login_unix_socket: "{{ netbox_database_socket }}" 49 | maintenance_db: "{{ netbox_database_maintenance }}" 50 | become: true 51 | become_user: "{{ netbox_database_user }}" 52 | when: 53 | - netbox_database_socket is defined 54 | - netbox_database_host is not defined 55 | - not netbox_database_alt_socket 56 | 57 | - name: Ensure Postgres database exists (via TCP) 58 | community.postgresql.postgresql_db: 59 | name: "{{ netbox_database }}" 60 | login_host: "{{ netbox_database_host }}" 61 | port: "{{ netbox_database_port }}" 62 | login_user: "{{ netbox_database_user }}" 63 | login_password: "{{ netbox_database_password }}" 64 | maintenance_db: "{{ netbox_database_maintenance }}" 65 | when: 66 | - netbox_database_socket is not defined 67 | - netbox_database_host is defined 68 | 69 | - import_tasks: deploy_netbox.yml 70 | 71 | - name: Install uWSGI via pip 72 | pip: 73 | name: uwsgi 74 | state: "{{ 'latest' if netbox_keep_uwsgi_updated else 'present' }}" 75 | umask: "0022" 76 | virtualenv: "{{ omit if not netbox_uwsgi_in_venv else netbox_virtualenv_path }}" 77 | environment: 78 | PATH: "/usr/local/bin:{{ _path }}" 79 | notify: 80 | - reload netbox.service 81 | retries: 2 82 | register: _netbox_uwsgi_install 83 | until: _netbox_uwsgi_install is succeeded 84 | 85 | - name: Configure uWSGI NetBox application 86 | template: 87 | src: uwsgi.ini.j2 88 | dest: "{{ netbox_shared_path }}/uwsgi.ini" 89 | owner: "{{ netbox_user }}" 90 | group: "{{ netbox_group }}" 91 | notify: 92 | - reload netbox.service 93 | 94 | - name: Install NetBox socket unit file 95 | template: 96 | src: netbox.socket.j2 97 | dest: /lib/systemd/system/netbox.socket 98 | notify: 99 | - restart netbox.socket 100 | 101 | - name: Install NetBox service unit file 102 | template: 103 | src: netbox.service.j2 104 | dest: /lib/systemd/system/netbox.service 105 | notify: 106 | - restart netbox.service 107 | 108 | - name: Install NetBox-rqworker service unit file 109 | template: 110 | src: netbox-rqworker.service.j2 111 | dest: /lib/systemd/system/netbox-rqworker@.service 112 | notify: 113 | - restart netbox-rqworker.service 114 | 115 | - name: Start and enable NetBox' socket and service 116 | systemd: 117 | name: "{{ item }}" 118 | state: started 119 | enabled: true 120 | daemon_reload: true 121 | loop: 122 | - netbox.socket 123 | - netbox.service 124 | 125 | - name: Start and enable netbox-rqworker.service 126 | systemd: 127 | name: "netbox-rqworker@{{ item }}.service" 128 | state: started 129 | enabled: true 130 | with_sequence: count="{{ netbox_rqworker_processes }}" 131 | 132 | - name: Restore the previous Ansible Python interpreter 133 | set_fact: 134 | ansible_python_interpreter: "{{ _netbox_global_python if _netbox_global_python is defined else 'auto_legacy' }}" 135 | 136 | - name: Recheck the previous Python interpreter's version 137 | setup: 138 | gather_subset: min 139 | filter: ansible_python_version 140 | -------------------------------------------------------------------------------- /tasks/validate_variables.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: A single NetBox installation scenario must be enabled 3 | assert: 4 | that: 5 | - netbox_stable or netbox_git 6 | - not (netbox_stable and netbox_git) 7 | msg: "Please choose either the stable or git scenario." 8 | 9 | - name: A database host/password or socket must be specified 10 | assert: 11 | that: 12 | - netbox_database_socket is defined or 13 | (netbox_database_host is defined and netbox_database_password is defined) 14 | - not (netbox_database_socket is defined and netbox_database_host is defined) 15 | msg: "Please define either a socket (local) or host/password (TCP)." 16 | 17 | - name: A super user password for NetBox must be specified 18 | assert: 19 | that: 20 | - netbox_superuser_password is defined 21 | msg: "Please set an admin password with netbox_superuser_password." 22 | 23 | - name: The netbox_config variable should not configure PostgreSQL/Redis 24 | assert: 25 | that: 26 | - "'DATABASE' not in netbox_config" 27 | - "'REDIS' not in netbox_config" 28 | msg: "Please remove the DATABASE and/or REDIS keys in netbox_config and use their dedicated role variables instead." 29 | 30 | - name: netbox_config must specify a list of ALLOWED_HOSTS 31 | assert: 32 | that: 33 | - "'ALLOWED_HOSTS' in netbox_config" 34 | - netbox_config.ALLOWED_HOSTS is iterable 35 | msg: "Please define ALLOWED_HOSTS in netbox_config." 36 | 37 | - name: NAPALM credentials must be specified in netbox_config if NAPALM is enabled 38 | assert: 39 | that: 40 | - "'NAPALM_USERNAME' in netbox_config" 41 | - "'NAPALM_PASSWORD' in netbox_config" 42 | msg: "Please define NAPALM_USERNAME and NAPALM_PASSWORD in netbox_config to use NAPALM." 43 | when: "netbox_napalm_enabled | bool" 44 | 45 | - name: Script/Report module names should follow PEP8 46 | assert: 47 | that: 48 | - "(netbox_scripts | map(attribute='name') | map('regex_search', '^[a-z][a-z0-9_]*$') | select('string') | list | length) == (netbox_scripts | length)" 49 | - "(netbox_reports | map(attribute='name') | map('regex_search', '^[a-z][a-z0-9_]*$') | select('string') | list | length) == (netbox_reports | length)" 50 | msg: "Please ensure that your script/report module names start with a lowercase letter and contain only lowercase letters, numbers, and underscores." 51 | 52 | - block: 53 | - name: Identify selected storage module 54 | set_fact: 55 | _netbox_storages_module: "{{ netbox_config.STORAGE_BACKEND | regex_search('(?<=storages\\.backends\\.).*(?=\\.)') }}" 56 | 57 | - name: Ensure storage module is a valid option 58 | assert: 59 | that: 60 | - _netbox_storages_module in _netbox_storages_map 61 | msg: "Please ensure your STORAGE_BACKEND is correct." 62 | when: "'STORAGE_BACKEND' in netbox_config" 63 | -------------------------------------------------------------------------------- /templates/configuration.py.j2: -------------------------------------------------------------------------------- 1 | {{ ansible_managed | comment }} 2 | import json 3 | import os 4 | 5 | {% if netbox_metrics_enabled %} 6 | if "prometheus_multiproc_dir" in os.environ: 7 | try: 8 | import prometheus_client 9 | import uwsgi 10 | prometheus_client.values.ValueClass = prometheus_client.values.MultiProcessValue( 11 | uwsgi.worker_id 12 | ) 13 | except ImportError: 14 | pass # not running in uwsgi 15 | {% endif %} 16 | 17 | DATABASE = { 18 | 'NAME': '{{ netbox_database }}', 19 | 'USER': '{{ netbox_database_user }}', 20 | {% if netbox_database_host is defined %} 21 | 'PASSWORD': '{{ netbox_database_password }}', 22 | 'HOST': '{{ netbox_database_host }}', 23 | 'PORT': '{{ netbox_database_port }}', 24 | {% else %} 25 | {% if netbox_database_password is defined %} 26 | 'PASSWORD': '{{ netbox_database_password }}', 27 | {% endif %} 28 | {% if netbox_database_alt_socket and netbox_database_socket is defined %} 29 | 'PORT': '{{ netbox_database_port }}', 30 | {% endif %} 31 | 'HOST': '{{ netbox_database_socket }}', 32 | {% endif %} 33 | 'CONN_MAX_AGE': {{ netbox_database_conn_age }}, 34 | {% if netbox_database_options|length > 0 %} 35 | 'OPTIONS': { 36 | {% for setting, value in netbox_database_options.items() %} 37 | {% if value is string or value is number %} 38 | "{{ setting }}": {{ value | to_nice_json }}, 39 | {% endif %} 40 | {% endfor %} 41 | }, 42 | {% endif %} 43 | } 44 | 45 | {% if netbox_stable and netbox_stable_version is version('2.9.4', '>=') or 46 | netbox_git and _netbox_git_contains_rq_timeout.rc == 0 %} 47 | {% set _default_timeout = "RQ_DEFAULT_TIMEOUT" %} 48 | {% else %} 49 | {% set _default_timeout = "DEFAULT_TIMEOUT" %} 50 | {% endif %} 51 | 52 | REDIS = { 53 | {# https://github.com/netbox-community/netbox/pull/4366 #} 54 | {% if netbox_stable and netbox_stable_version is version('2.7.11', '>=') or 55 | netbox_git and _netbox_git_contains_tasks_rename.rc == 0 %} 56 | 'tasks': { 57 | {% else %} 58 | 'webhooks': { 59 | {% endif %} 60 | {% if netbox_redis_sentinels|length == 0 %} 61 | 'HOST': '{{ netbox_redis_host }}', 62 | 'PORT': {{ netbox_redis_port }}, 63 | '{{ _default_timeout }}': {{ netbox_redis_default_timeout }}, 64 | {% else %} 65 | 'SENTINELS': [ 66 | {% for sentinel in netbox_redis_sentinels %} 67 | ('{{ sentinel.host }}', {{ sentinel.port }}), 68 | {% endfor %} 69 | ], 70 | 'SENTINEL_SERVICE': '{{ netbox_redis_sentinel_service }}', 71 | 'SENTINEL_TIMEOUT': {{ netbox_redis_default_timeout }}, 72 | {% endif %} 73 | 'PASSWORD': '{{ netbox_redis_password }}', 74 | 'DATABASE': {{ netbox_redis_database }}, 75 | 'SSL': {{ netbox_redis_ssl_enabled }}, 76 | 'INSECURE_SKIP_TLS_VERIFY': {{ netbox_redis_insecure_skip_tls_verify }}, 77 | }, 78 | 'caching': { 79 | {% if netbox_redis_cache_sentinels|length == 0 %} 80 | 'HOST': '{{ netbox_redis_cache_host }}', 81 | 'PORT': {{ netbox_redis_cache_port }}, 82 | '{{ _default_timeout }}': {{ netbox_redis_default_timeout }}, 83 | {% else %} 84 | 'SENTINELS': [ 85 | {% for sentinel in netbox_redis_cache_sentinels %} 86 | ('{{ sentinel.host }}', {{ sentinel.port }}), 87 | {% endfor %} 88 | ], 89 | 'SENTINEL_SERVICE': '{{ netbox_redis_cache_sentinel_service }}', 90 | 'SENTINEL_TIMEOUT': {{ netbox_redis_default_timeout }}, 91 | {% endif %} 92 | 'PASSWORD': '{{ netbox_redis_cache_password }}', 93 | 'DATABASE': {{ netbox_redis_cache_database }}, 94 | 'SSL': {{ netbox_redis_cache_ssl_enabled }}, 95 | 'INSECURE_SKIP_TLS_VERIFY': {{ netbox_redis_cache_insecure_skip_tls_verify }}, 96 | } 97 | } 98 | 99 | {% if netbox_metrics_enabled %} 100 | METRICS_ENABLED = True 101 | {% endif %} 102 | 103 | {% for setting, value in _netbox_config.items() %} 104 | {% if value in [True, False] %} 105 | {{ setting }} = {{ 'True' if value else 'False' }} 106 | {% elif value is string or value is number %} 107 | {{ setting }} = {{ value | to_nice_json }} 108 | {% else %} 109 | {{ setting }} = json.loads(r'''{{ value | to_json }}''') 110 | {% endif %} 111 | {% endfor %} 112 | 113 | # vim: ft=python 114 | -------------------------------------------------------------------------------- /templates/netbox-rqworker.service.j2: -------------------------------------------------------------------------------- 1 | {{ ansible_managed | comment }} 2 | [Unit] 3 | Description=NetBox Request Queue Worker %i 4 | Documentation=https://docs.netbox.dev/ 5 | After=network-online.target 6 | Wants=network-online.target 7 | 8 | [Service] 9 | Type=simple 10 | 11 | WorkingDirectory={{ netbox_shared_path }} 12 | ExecStart={{ netbox_virtualenv_path }}/bin/python {{ netbox_current_path }}/netbox/manage.py rqworker high default low 13 | 14 | StandardOutput=journal 15 | StandardError=journal 16 | User={{ netbox_user }} 17 | Group={{ netbox_group }} 18 | Restart=on-failure 19 | RestartSec=30 20 | 21 | NotifyAccess=all 22 | PrivateTmp=true 23 | ProtectSystem=full 24 | DeviceAllow=/dev/null rw 25 | DeviceAllow=/dev/urandom r 26 | DeviceAllow=/dev/zero r 27 | ProtectHome=yes 28 | NoNewPrivileges=yes 29 | 30 | [Install] 31 | WantedBy=multi-user.target 32 | -------------------------------------------------------------------------------- /templates/netbox.service.j2: -------------------------------------------------------------------------------- 1 | {{ ansible_managed | comment }} 2 | [Unit] 3 | Description=NetBox IPAM/DCIM Tool 4 | Documentation=http://netbox.readthedocs.io/en/{{ 'latest' if netbox_git else 'stable' }}/ 5 | Requires=netbox.socket 6 | After=syslog.target 7 | 8 | [Service] 9 | ExecStart={{ netbox_uwsgi_cmd }} --ini {{ netbox_shared_path }}/uwsgi.ini 10 | ExecReload=/bin/kill -1 $MAINPID 11 | ExecStop=/bin/kill -2 $MAINPID 12 | StandardInput=socket 13 | StandardOutput=journal 14 | StandardError=journal 15 | User={{ netbox_user }} 16 | Group={{ netbox_group }} 17 | Restart=on-failure 18 | SuccessExitStatus=15 17 29 30 19 | KillSignal=SIGQUIT 20 | Type=notify 21 | StandardError=syslog 22 | NotifyAccess=all 23 | PrivateTmp=yes 24 | ProtectSystem=full 25 | ReadWriteDirectories={{ netbox_shared_path }} 26 | {% if netbox_database_socket is defined %} 27 | ReadWriteDirectories={{ netbox_database_socket }} 28 | {% endif %} 29 | DeviceAllow=/dev/null rw 30 | DeviceAllow=/dev/urandom r 31 | DeviceAllow=/dev/zero r 32 | ProtectHome=yes 33 | NoNewPrivileges=yes 34 | {% if netbox_metrics_enabled %} 35 | RuntimeDirectory={{ netbox_metrics_dir }} 36 | {% endif %} 37 | 38 | [Install] 39 | WantedBy=multi-user.target 40 | -------------------------------------------------------------------------------- /templates/netbox.socket.j2: -------------------------------------------------------------------------------- 1 | {{ ansible_managed | comment }} 2 | [Unit] 3 | Description=Socket for NetBox IPAM/DCIM Tool 4 | 5 | [Socket] 6 | ListenStream={{ netbox_socket }} 7 | SocketUser={{ netbox_user }} 8 | SocketGroup={{ netbox_group }} 9 | 10 | [Install] 11 | WantedBy=sockets.target 12 | -------------------------------------------------------------------------------- /templates/pip_constraints.j2: -------------------------------------------------------------------------------- 1 | {{ ansible_managed | comment }} 2 | {% if (netbox_stable and netbox_stable_version is version_compare('2.3.5', '<=')) or 3 | (netbox_git and _netbox_git_contains_issue_2239_fix.rc == 1) %} 4 | django-filter<2.0.0 5 | {% endif %} 6 | 7 | {% for constraint in netbox_pip_constraints %} 8 | {{ constraint }} 9 | {% endfor %} 10 | -------------------------------------------------------------------------------- /templates/uwsgi.ini.j2: -------------------------------------------------------------------------------- 1 | {{ ansible_managed | comment }} 2 | [uwsgi] 3 | master=true 4 | protocol={{ netbox_protocol }} 5 | uid={{ netbox_user }} 6 | gid={{ netbox_group }} 7 | processes={{ netbox_processes }} 8 | module=netbox.wsgi 9 | virtualenv={{ netbox_virtualenv_path }} 10 | chdir={{ netbox_current_path }}/netbox 11 | {% if _netbox_config.BASE_PATH is defined %} 12 | {% set _base_path = _netbox_config.BASE_PATH.strip('/') ~ '/' %} 13 | {% else %} 14 | {% set _base_path = '' %} 15 | {% endif %} 16 | static-map=/{{ _base_path }}static={{ netbox_current_path }}/netbox/static 17 | logger={{ netbox_application_log }} 18 | req-logger={{ netbox_requests_log }} 19 | {% if netbox_metrics_enabled %} 20 | env=prometheus_multiproc_dir={{ netbox_metrics_path }} 21 | {% endif %} 22 | {% for key, value in netbox_uwsgi_options.items() %} 23 | {% if 'prometheus_multiproc_dir' not in value|string %} 24 | {{ key }}={{ value }} 25 | {% endif %} 26 | {% endfor %} 27 | 28 | # vim: ft=dosini 29 | -------------------------------------------------------------------------------- /tests/ansible.cfg: -------------------------------------------------------------------------------- 1 | [defaults] 2 | callback_whitelist=profile_tasks 3 | forks=20 4 | internal_poll_interval = 0.001 5 | -------------------------------------------------------------------------------- /tests/deploy.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: netbox 3 | become: true 4 | any_errors_fatal: true 5 | roles: 6 | - lae.netbox 7 | -------------------------------------------------------------------------------- /tests/group_vars/netbox: -------------------------------------------------------------------------------- 1 | --- 2 | netbox_socket: "0.0.0.0:8080" 3 | netbox_pip_packages: 4 | - netbox-topology-views 5 | netbox_config: 6 | ALLOWED_HOSTS: 7 | - "{{ inventory_hostname }}" 8 | MEDIA_ROOT: "{{ netbox_shared_path }}/media" 9 | REPORTS_ROOT: "{{ netbox_shared_path }}/reports" 10 | SCRIPTS_ROOT: "{{ netbox_shared_path }}/scripts" 11 | NAPALM_USERNAME: manager 12 | NAPALM_PASSWORD: null 13 | NAPALM_ARGS: 14 | use_keys: true 15 | key_file: '/srv/netbox/.ssh/id_rsa' 16 | PLUGINS: 17 | - netbox_topology_views 18 | netbox_scripts: 19 | - src: scripts/nothing.py 20 | name: nothing 21 | netbox_reports: 22 | - src: reports/nothing.py 23 | name: nothing 24 | netbox_napalm_enabled: true 25 | netbox_superuser_password: netbox 26 | netbox_superuser_create_token: true 27 | netbox_database: "netbox_{{ inventory_hostname_short }}" 28 | netbox_database_host: 10.0.3.1 29 | netbox_database_password: 30 | netbox_database_user: postgres 31 | netbox_webhooks_enabled: true 32 | netbox_metrics_enabled: true 33 | netbox_redis_host: 10.0.3.1 34 | netbox_uwsgi_options: 35 | buffer-size: 65535 36 | -------------------------------------------------------------------------------- /tests/group_vars/netbox_git: -------------------------------------------------------------------------------- 1 | --- 2 | netbox_git: true 3 | netbox_git_version: develop-2.10 4 | -------------------------------------------------------------------------------- /tests/group_vars/netbox_stable: -------------------------------------------------------------------------------- 1 | --- 2 | netbox_stable: true 3 | -------------------------------------------------------------------------------- /tests/group_vars/netbox_stable_2_7: -------------------------------------------------------------------------------- 1 | --- 2 | netbox_stable: true 3 | netbox_stable_version: 2.7.12 4 | -------------------------------------------------------------------------------- /tests/install.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: localhost 3 | connection: local 4 | roles: 5 | - lae.travis-lxc 6 | vars: 7 | test_profiles: 8 | - profile: debian-buster 9 | - profile: ubuntu-bionic 10 | - profile: centos-7 11 | test_host_suffixes: 12 | - git 13 | -------------------------------------------------------------------------------- /tests/inventory: -------------------------------------------------------------------------------- 1 | [netbox:children] 2 | netbox_git 3 | 4 | [netbox_git] 5 | debian-buster-git 6 | ubuntu-bionic-git 7 | centos-7-git 8 | -------------------------------------------------------------------------------- /tests/reports/nothing.py: -------------------------------------------------------------------------------- 1 | from extras.reports import Report 2 | 3 | 4 | class NothingReport(Report): 5 | description = "A report." 6 | 7 | def test_nothing(self): 8 | self.log_success("Success! Hm? What is, you ask? That's a secret.") 9 | -------------------------------------------------------------------------------- /tests/scripts/nothing.py: -------------------------------------------------------------------------------- 1 | from extras.scripts import Script 2 | 3 | 4 | class Nothing(Script): 5 | def run(self, data, commit=False): 6 | return "" 7 | -------------------------------------------------------------------------------- /tests/test.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: netbox 3 | become: true 4 | tasks: 5 | - block: 6 | - name: uWSGI/NetBox service status # noqa 303 305 7 | shell: "systemctl status netbox.service" 8 | changed_when: false 9 | - name: uWSGI/NetBox service journal # noqa 305 10 | shell: "journalctl --no-pager -xu netbox.service" 11 | changed_when: false 12 | - name: uWSGI configuration # noqa 305 13 | shell: cat /srv/netbox/shared/uwsgi.ini 14 | changed_when: false 15 | - name: NetBox rq-worker service status # noqa 303 305 16 | shell: "systemctl status netbox-rqworker@1.service" 17 | changed_when: false 18 | - name: NetBox application log # noqa 305 19 | shell: cat /srv/netbox/shared/application.log 20 | changed_when: false 21 | - name: NetBox configuration # noqa 305 22 | shell: cat /srv/netbox/shared/configuration.py 23 | changed_when: false 24 | ignore_errors: true 25 | - name: Ensure that NetBox returns a successful HTTP response 26 | uri: 27 | url: "http://{{ inventory_hostname }}:8080" 28 | - name: Check that Netbox metrics endpoint works 29 | uri: 30 | url: "http://{{ inventory_hostname }}:8080/metrics" 31 | -------------------------------------------------------------------------------- /tests/vagrant/group_vars/all: -------------------------------------------------------------------------------- 1 | --- 2 | ansible_python_interpreter: /usr/bin/python3 3 | 4 | netbox_stable: true 5 | netbox_socket: "0.0.0.0:80" 6 | netbox_superuser_password: netbox 7 | netbox_config: 8 | ALLOWED_HOSTS: 9 | - "{{ inventory_hostname }}" 10 | # The following should not be used in production, probably. 11 | # This playbook gets used by Vagrant where we don't know the actual hostname. 12 | - "*" 13 | MEDIA_ROOT: "{{ netbox_shared_path }}/media" 14 | REPORTS_ROOT: "{{ netbox_shared_path }}/reports" 15 | SCRIPTS_ROOT: "{{ netbox_shared_path }}/scripts" 16 | netbox_database_socket: "{{ postgresql_unix_socket_directories[0] }}" 17 | netbox_keep_uwsgi_updated: true 18 | postgres_users_no_log: False 19 | postgresql_users: 20 | - name: "{{ netbox_database_user }}" 21 | role_attr_flags: CREATEDB,NOSUPERUSER 22 | redis_bind: 127.0.0.1 23 | redis_version: 6.0.9 24 | redis_checksum: sha256:dc2bdcf81c620e9f09cfd12e85d3bc631c897b2db7a55218fd8a65eaa37f86dd 25 | -------------------------------------------------------------------------------- /tests/vagrant/package_role.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: localhost 3 | connection: local 4 | vars: 5 | role_name: lae.netbox 6 | tasks: 7 | - block: 8 | - shell: pwd 9 | - name: Package up current working role 10 | shell: "cd $(git rev-parse --show-toplevel); git ls-files -z | xargs -0 tar -czvf $OLDPWD/{{ role_name }}.tar.gz" 11 | - name: Install packaged role 12 | shell: "ansible-galaxy install {{ role_name }}.tar.gz,devel-$(git rev-parse HEAD),{{ role_name }} --force" 13 | - name: Remove packaged role artifact 14 | file: 15 | dest: "{{ role_name }}.tar.gz" 16 | state: absent 17 | -------------------------------------------------------------------------------- /tests/vagrant/provision.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: all 3 | become: True 4 | pre_tasks: 5 | - name: Copy apt proxy detection script 6 | ansible.builtin.template: 7 | src: detect-http-proxy.j2 8 | dest: /etc/apt/detect-http-proxy 9 | mode: 0755 10 | - name: Configure apt to use detection script 11 | ansible.builtin.copy: 12 | content: "Acquire::Retries 0;\nAcquire::http::ProxyAutoDetect \"/etc/apt/detect-http-proxy\";" 13 | dest: /etc/apt/apt.conf.d/30detectproxy 14 | roles: 15 | - geerlingguy.postgresql 16 | - davidwittman.redis 17 | - lae.netbox 18 | -------------------------------------------------------------------------------- /tests/vagrant/templates/detect-http-proxy.j2: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | APT_CACHE_HOST="{{ lookup('env', 'APT_CACHE_HOST') }}" 4 | 5 | # Check if we can connect to the given host and provide it if so 6 | if [ ! -z "${APT_CACHE_HOST}" ]; then 7 | if $(nc -zw1 "${APT_CACHE_HOST}" 3142); then 8 | echo "http://${APT_CACHE_HOST}:3142" 9 | exit 10 | fi 11 | fi 12 | 13 | # Otherwise, don't use a proxy 14 | echo "DIRECT" 15 | -------------------------------------------------------------------------------- /vars/amazon-2023.yml: -------------------------------------------------------------------------------- 1 | --- 2 | netbox_install_epel: false 3 | _netbox_packages: 4 | - gcc 5 | - libpq-devel 6 | - libxml2-devel 7 | - libxslt-devel 8 | - libffi-devel 9 | - libjpeg-turbo-devel 10 | - graphviz 11 | - openssl-devel 12 | _netbox_python_packages: 13 | - python3 14 | - python3-devel 15 | - python3-setuptools 16 | - python3-psycopg2 17 | - python3-libselinux 18 | - python3-pip 19 | _netbox_python_binary: /usr/bin/python3.9 20 | _netbox_ldap_packages: 21 | - openldap-devel 22 | -------------------------------------------------------------------------------- /vars/debian-10.yml: -------------------------------------------------------------------------------- 1 | --- 2 | _netbox_packages: 3 | - libxml2-dev 4 | - libxslt1-dev 5 | - libffi-dev 6 | - libjpeg-dev 7 | - graphviz 8 | - libpq-dev 9 | - libssl-dev 10 | _netbox_python_packages: 11 | - python3.7 12 | - python3.7-dev 13 | - python3-venv 14 | - python3-pip 15 | - python3-psycopg2 # used by ansible's postgres modules 16 | _netbox_python_binary: /usr/bin/python3.7 17 | _netbox_ldap_packages: 18 | - libldap2-dev 19 | - libsasl2-dev 20 | -------------------------------------------------------------------------------- /vars/debian-11.yml: -------------------------------------------------------------------------------- 1 | --- 2 | _netbox_packages: 3 | - libxml2-dev 4 | - libxslt1-dev 5 | - libffi-dev 6 | - libjpeg-dev 7 | - graphviz 8 | - libpq-dev 9 | - libssl-dev 10 | _netbox_python_packages: 11 | - python3.9 12 | - python3.9-dev 13 | - python3-venv 14 | - python3-pip 15 | - python3-psycopg2 # used by ansible's postgres modules 16 | _netbox_python_binary: /usr/bin/python3 17 | _netbox_ldap_packages: 18 | - libldap2-dev 19 | - libsasl2-dev 20 | -------------------------------------------------------------------------------- /vars/debian-12.yml: -------------------------------------------------------------------------------- 1 | --- 2 | _netbox_packages: 3 | - libxml2-dev 4 | - libxslt1-dev 5 | - libffi-dev 6 | - libjpeg-dev 7 | - graphviz 8 | - libpq-dev 9 | - libssl-dev 10 | - systemd-cron 11 | _netbox_python_packages: 12 | - python3.11 13 | - python3.11-dev 14 | - python3-venv 15 | - python3-pip 16 | - python3-psycopg2 # used by ansible's postgres modules 17 | _netbox_python_binary: /usr/bin/python3 18 | _netbox_ldap_packages: 19 | - libldap2-dev 20 | - libsasl2-dev 21 | netbox_uwsgi_in_venv: true 22 | -------------------------------------------------------------------------------- /vars/debian-9.yml: -------------------------------------------------------------------------------- 1 | --- 2 | _netbox_packages: 3 | - libxml2-dev 4 | - libxslt1-dev 5 | - libffi-dev 6 | - libjpeg-dev 7 | - graphviz 8 | - libpq-dev 9 | - libssl-dev 10 | _netbox_python_packages: 11 | - python3.5 12 | - python3.5-dev 13 | - python3-venv 14 | - python3-pip 15 | - python3-psycopg2 # used by ansible's postgres modules 16 | _netbox_python_binary: /usr/bin/python3.5 17 | _netbox_ldap_packages: 18 | - libldap2-dev 19 | - libsasl2-dev 20 | -------------------------------------------------------------------------------- /vars/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # vars file for lae.netbox 3 | netbox_config_path: "{{ netbox_current_path }}/netbox/netbox" 4 | netbox_virtualenv_path: "{{ netbox_current_path }}/venv-py3" 5 | netbox_uwsgi_cmd: "{{ netbox_virtualenv_path }}/bin/uwsgi" 6 | 7 | _netbox_default_config: 8 | ALLOWED_HOSTS: 9 | - localhost 10 | - 127.0.0.1 11 | MEDIA_ROOT: "{{ netbox_shared_path }}/media" 12 | REPORTS_ROOT: "{{ netbox_shared_path }}/reports" 13 | SCRIPTS_ROOT: "{{ netbox_shared_path }}/scripts" 14 | 15 | _netbox_storages_map: 16 | s3boto3: boto3 17 | apache_libcloud: "apache-libcloud" 18 | azure_storage: "django-storages[azure]" 19 | dropbox: "django-storages[dropbox]" 20 | gcloud: "django-storages[google]" 21 | ftp: [] 22 | sftpstorage: [] 23 | 24 | netbox_superuser_script: | 25 | from django.contrib.auth import get_user_model 26 | from base64 import b64decode 27 | User = get_user_model() 28 | password = b64decode("{{ netbox_superuser_password | b64encode }}").decode("UTF-8") 29 | query = User.objects.filter(username="{{ netbox_superuser_username }}") 30 | if not query.exists(): 31 | User.objects.create_superuser("{{ netbox_superuser_username }}", "{{ netbox_superuser_email }}", password) 32 | print("changed") 33 | else: 34 | user = User.objects.get(username="{{ netbox_superuser_username }}") 35 | if not user.is_superuser or user.email != "{{ netbox_superuser_email }}" or not user.check_password(password): 36 | user.is_superuser = True 37 | user.is_staff = True 38 | user.email = "{{ netbox_superuser_email }}" 39 | user.set_password(password) 40 | user.save() 41 | print("changed") 42 | 43 | netbox_superuser_token: | 44 | from users.models import Token 45 | from django.contrib.auth import get_user_model 46 | User = get_user_model() 47 | user = User.objects.get(username="{{ netbox_superuser_username }}") 48 | query = Token.objects.filter(user=user) 49 | if not query.exists(): 50 | token = Token.objects.create(user=user) 51 | print("api-token: " + token.key) 52 | print("changed") 53 | 54 | netbox_python_compat_matrix: 55 | - { netbox_version_min: '2.8.0', python_needed: '3.6.0' } 56 | - { netbox_version_min: '3.0.0', python_needed: '3.7.0' } 57 | - { netbox_version_min: '3.2.0', python_needed: '3.8.0' } 58 | - { netbox_version_min: '4.0.0', python_needed: '3.10.0' } 59 | -------------------------------------------------------------------------------- /vars/redhat-7.yml: -------------------------------------------------------------------------------- 1 | --- 2 | _netbox_packages: 3 | - gcc 4 | - postgresql-devel 5 | - libxml2-devel 6 | - libxslt-devel 7 | - libffi-devel 8 | - libjpeg-devel 9 | - graphviz 10 | - openssl-devel 11 | _netbox_python_packages: 12 | - python36 13 | - python36-devel 14 | - python36-setuptools 15 | _netbox_python_binary: /usr/bin/python3.6 16 | _netbox_ldap_packages: 17 | - openldap-devel 18 | -------------------------------------------------------------------------------- /vars/redhat-8.yml: -------------------------------------------------------------------------------- 1 | --- 2 | _netbox_packages: 3 | - gcc 4 | - postgresql-devel 5 | - libxml2-devel 6 | - libxslt-devel 7 | - libffi-devel 8 | - libjpeg-devel 9 | - graphviz 10 | - openssl-devel 11 | _netbox_python_packages: 12 | - python36 13 | - python36-devel 14 | - python3-setuptools 15 | - python3-psycopg2 16 | - python3-libselinux 17 | - python3-pip 18 | _netbox_python_binary: /usr/bin/python3.6 19 | _netbox_ldap_packages: 20 | - openldap-devel 21 | -------------------------------------------------------------------------------- /vars/redhat-9.yml: -------------------------------------------------------------------------------- 1 | --- 2 | _netbox_packages: 3 | - gcc 4 | - postgresql-devel 5 | - libxml2-devel 6 | - libxslt-devel 7 | - libffi-devel 8 | - libjpeg-devel 9 | - graphviz 10 | - openssl-devel 11 | _netbox_python_packages: 12 | - python3 13 | - python3-devel 14 | - python3-setuptools 15 | - python3-psycopg2 16 | - python3-libselinux 17 | - python3-pip 18 | _netbox_python_binary: /usr/bin/python3.9 19 | _netbox_ldap_packages: 20 | - openldap-devel 21 | -------------------------------------------------------------------------------- /vars/ubuntu-16.yml: -------------------------------------------------------------------------------- 1 | --- 2 | _netbox_packages: 3 | - libxml2-dev 4 | - libxslt1-dev 5 | - libffi-dev 6 | - libjpeg-dev 7 | - graphviz 8 | - libpq-dev 9 | - libssl-dev 10 | _netbox_python_packages: 11 | - python3.5 12 | - python3.5-dev 13 | - python3-pip 14 | - python3-venv 15 | - python3-psycopg2 # used by ansible's postgres modules 16 | _netbox_python_binary: /usr/bin/python3.5 17 | _netbox_ldap_packages: 18 | - libldap2-dev 19 | - libsasl2-dev 20 | -------------------------------------------------------------------------------- /vars/ubuntu-18.yml: -------------------------------------------------------------------------------- 1 | --- 2 | _netbox_packages: 3 | - libxml2-dev 4 | - libxslt1-dev 5 | - libffi-dev 6 | - libjpeg-dev 7 | - graphviz 8 | - libpq-dev 9 | - libssl-dev 10 | _netbox_python_packages: 11 | - python3.6 12 | - python3.6-dev 13 | - python3-pip 14 | - python3-venv 15 | - python3-psycopg2 # used by ansible's postgres modules 16 | _netbox_python_binary: /usr/bin/python3.6 17 | _netbox_ldap_packages: 18 | - libldap2-dev 19 | - libsasl2-dev 20 | -------------------------------------------------------------------------------- /vars/ubuntu-20.yml: -------------------------------------------------------------------------------- 1 | --- 2 | _netbox_packages: 3 | - libxml2-dev 4 | - libxslt1-dev 5 | - libffi-dev 6 | - libjpeg-dev 7 | - graphviz 8 | - libpq-dev 9 | - libssl-dev 10 | _netbox_python_packages: 11 | - python3 12 | - python3-dev 13 | - python3-pip 14 | - python3-venv 15 | - python3-psycopg2 # used by ansible's postgres modules 16 | _netbox_python_binary: /usr/bin/python3 17 | _netbox_ldap_packages: 18 | - libldap2-dev 19 | - libsasl2-dev 20 | -------------------------------------------------------------------------------- /vars/ubuntu-22.yml: -------------------------------------------------------------------------------- 1 | --- 2 | _netbox_packages: 3 | - libxml2-dev 4 | - libxslt1-dev 5 | - libffi-dev 6 | - libjpeg-dev 7 | - graphviz 8 | - libpq-dev 9 | - libssl-dev 10 | _netbox_python_packages: 11 | - python3 12 | - python3-dev 13 | - python3-pip 14 | - python3-venv 15 | - python3-psycopg2 # used by ansible's postgres modules 16 | _netbox_python_binary: /usr/bin/python3 17 | _netbox_ldap_packages: 18 | - libldap2-dev 19 | - libsasl2-dev 20 | --------------------------------------------------------------------------------