I’ve recently had the need to better manage my homelab and have been using netbox to do so. However, when you have a lot of VM’s, it gets daunting to catalog them. So I’ve written a role to do my baselining.

The convenient thing about having your entire infrastructure in netbox means that you can use it for dynamically generating your inventories afterwards. But that’s another post entirely. This first post focuses on installing netbox automatically with an ansible script.

Netbox is mostly a one-shot installation. However, it can be useful to have a tool such as netbox if you’re repetitively baselining infrastructure. This can be the case if you’re an IT admin in a consultancy managing several clients; or perhaps if you suddenly have to catalog an entire infrastructure and you have nothing but a default set of credentials. Perhaps you want to deploy this on your ludus instance for practice.

Whatever your use-case may be, here’s a simple role on which you can base your installations.

I’m operating on the assumption that you already have python3-pip and python3-venv installed on a debian-based distro, with a bash shell.

Note: I first posted this article on the 26th of October, but I’ve since come back and modified it. I realized that it didn’t work out of the box and I wanted something at least functional; I’ve since published a ludus netbox role which you’ll find here: https://github.com/Inf0Junki3/inf0junki3.ludus

# Set up a virtual environment.
python3 -m venv venv
source venv/bin/activate
# Install the tools we need - in this case we'll set up both ansible and netbox.
pip install ansible pynetbox

Next, we’ll set up a collection and a role:

ansible-galaxy collection init heapspray.netbox # Be sure to edit your galaxy.yml file with the appropriate metadata.
cd heapspray/netbox/roles
ansible-galaxy role init installation # For the installation of the netbox instance.
# Don't forget to fill out meta/main.yml!
ansible-galaxy role init inventory # For populating the netbox instance with your inventory.
# Don't forget to fill out this meta/main.yml too!

Now for the role. You’ll need some default variables in default/main.yml:

GENERIC_TIMEZONE: "America/New_York"
TZ: "America/New_York"
PUID: "1000"
PGID: "1000"
SUPERUSER_EMAIL: "[email protected]"
SUPERUSER_PASSWORD: "changeme"
ALLOWED_HOST: "castle.mario.time"
POSTGRES_USER: "postgres"
POSTGRES_DB: "netbox"
# You know what to do here :) Generate those users and passwords with `pwgen -s -B -1 16 4`
DB_NAME: "netbox"
DB_USER: "postgres"
DB_PASSWORD: "badpassword"
DB_HOST: "postgres"
DB_PORT: ""
REDIS_HOST: "redis"
REDIS_PORT: ""
REDIS_PASSWORD: "badpassword"
REDIS_DB_TASK: ""
REDIS_DB_CACHE: ""
# BASE_PATH: #optional
# REMOTE_AUTH_ENABLED: #optional
# REMOTE_AUTH_BACKEND: #optional
# REMOTE_AUTH_HEADER: #optional
# REMOTE_AUTH_AUTO_CREATE_USER: #optional
# REMOTE_AUTH_DEFAULT_GROUPS: #optional
# REMOTE_AUTH_DEFAULT_PERMISSIONS: #optional

Next, we create a tasks file in tasks/main.yml. This one is simple - I’m going off the premise that you’ll set up an unencrypted docker compose file here and will add your traefik or caddy proxy afterwards.

---
- name: Create the directory for the certs
  ansible.builtin.file:
    path: "{{ item }}"
    mode: "0755"
    state: directory
  loop:
    - /opt/netbox
    - /opt/netbox/config

- name: Set up the docker compose file
  ansible.builtin.template:
    src: docker-compose.yml.j2
    dest: /opt/netbox/docker-compose.yml

- name: Run the compose project
  community.docker.docker_compose_v2:
    project_src: /opt/netbox

Last but not least, the templates/docker-compose.yml.j2 file will allow you to spin up a docker project:

---
services:
  postgres:
    image: postgres
    environment:
      POSTGRES_PASSWORD: {{ DB_PASSWORD }}
      POSTGRES_DB: {{ DB_NAME }}
    volumes:
      - /opt/postgres/data:/var/lib/postgresql
    networks:
      - netbox
  redis:
    image: redis
    command: ["redis-server", "--requirepass", "${REDIS_PASSWORD}"]
    environment:
      REDIS_PASSWORD: {{ REDIS_PASSWORD }}
    volumes:
      - /opt/redis/data:/data
    networks:
      - netbox
  netbox:
    image: lscr.io/linuxserver/netbox:latest
    container_name: netbox
    environment:
      - PUID={{ PUID }}
      - PGID={{ PGID }}
      - TZ={{ TZ }}
      - SUPERUSER_EMAIL={{ SUPERUSER_EMAIL }}
      - SUPERUSER_PASSWORD={{ SUPERUSER_PASSWORD }}
      - ALLOWED_HOST={{ ALLOWED_HOST }}
      - DB_NAME={{ DB_NAME }}
      - DB_USER={{ DB_USER | default('postgres') }}
      - DB_PASSWORD={{ DB_PASSWORD }}
      - DB_HOST={{ DB_HOST | default('postgres') }}
      - DB_PORT={{ DB_PORT }}
      - REDIS_HOST={{ REDIS_HOST | default('redis') }}
      - REDIS_PORT={{ REDIS_PORT }}
      - REDIS_PASSWORD={{ REDIS_PASSWORD }}
      - REDIS_DB_TASK={{ REDIS_DB_TASK }}
      - REDIS_DB_CACHE={{ REDIS_DB_CACHE }}
      - BASE_PATH= #optional
      - REMOTE_AUTH_ENABLED= #optional
      - REMOTE_AUTH_BACKEND= #optional
      - REMOTE_AUTH_HEADER= #optional
      - REMOTE_AUTH_AUTO_CREATE_USER= #optional
      - REMOTE_AUTH_DEFAULT_GROUPS= #optional
      - REMOTE_AUTH_DEFAULT_PERMISSIONS= #optional
    volumes:
      - /opt/netbox/config:/config
      - /opt/netbox/certs:/certs
    ports:
      - 8000:8000
    restart: unless-stopped
    networks:
      - netbox

networks:
  netbox: