В этой заметке будет описан гайд по установке netbox сервер, который будет использоваться в качестве некой CMDB для учета адресного пространства или места в серверных стойках. У проекта очень хорошо прописана документация, и этот ман можно позиционировать просто как пошаговую инструкцию.

netbox-schemas.png (Схема стека)

Как видно из схема, предварительно нам нужно заинсталить и подготовить дополнительные компоненты:

  • Postgresql, 11 версия и выше
  • Redis, 4 версия и выше
  • Python - 3.8
  • WSGI обработчик и Nginx в качестве обратной прокси

Установка Postgresql

Как всегда начинаем с самого низкого слоя стека, установки и инициализации базы. В нашем кейсе, будем ставить postgresql версии 14.

Подключаем репозиторий:

[root@hostname yum.repos.d]# vi /etc/yum.repos.d/postgresql14.repo
---
[Postgresql-14]
name=Postgresql-14
enabled=1
baseurl=https://download.postgresql.org/pub/repos/yum/14/redhat/rhel-8-x86_64/
gpgcheck=0
repo_gpgcheck=0

Выключаем стандартный модуль с базой и ставим 14 версию:

[root@netbox ~]# yum module disable postgresql
[root@netbox ~]# yum install postgresql14-server postgresql14

Прежде чем начать работать с субд, нужно проинициализировать инстанс:

[root@netbox ~]# /usr/pgsql-14/bin/postgresql-14-setup initdb

Сразу же отредактируем конфиг - postgresql, раскоментим директивы listen_addresses и port:

[root@netbox ~]# vim /var/lib/pgsql/14/data/postgresql.conf
---
listen_addresses = 'localhost'
port = 5432  

Сохраняемся и запускаем сервис:

[root@netbox ~]# systemctl enable --now postgresql-14

Для доступа сервиса к базе нужно создать базу данных и пользователя с правами на эту базу. Подключаемся к базе и создаем:

[root@netbox ~]# sudo -u postgres psql
---
postgres=# set password_encryption = "scram-sha-256";
postgres=# create user netbox_user with encrypted password 'pass';
postgres=# create database netbox_db owner netbox_user;

Настройка Redis

Для кеширования и очередей Netbox использует in-memory хранилище Redis. Установим пакет:

[root@netbox ~]# yum install redis

Из стандартных репозиториев rhel идет версия 5, убедится в этом можно командой:

[root@netbox ~]# redis-server -v
Redis server v=5.0.3 sha=00000000:0 malloc=jemalloc-5.1.0 bits=64 build=14b81d825631ff0c

Ставим сервис, и чекаем его доступность.

[root@netbox ~]# systemctl enable --now redis
[root@netbox ~]# redis-cli ping
---
PONG

Настройка Netbox

Для установки основного сервиса, нужно предварительно заинсталить зависимости и python версии =< 3.8.

[root@netbox ~]# sudo yum install -y gcc libxml2-devel libxslt-devel libffi-devel libpq-devel openssl-devel redhat-rpm-config python38

Создаем симлинк для питона:

[root@netbox ~]# ln -s /bin/python3 /bin/python

И проверяем версию:

[root@netbox ~]# python -v
Python 3.8.12 (default, Apr 21 2022, 07:55:08)

Теперь качаем последний стабильный релиз приложения, и распаковываем в каталоге /opt:

[root@netbox ~]# cd /opt/
# Качаем архив
[root@netbox opt]# wget https://github.com/netbox-community/netbox/archive/refs/tags/v3.4.3.tar.gz
# Распаковываем архив
[root@netbox opt]# tar -zxvf v3.4.3.tar.gz
# Создаем симлинк
[root@netbox opt]# sudo ln -s /opt/netbox-3.4.3/ /opt/netbox

Для работы сервиса, требуется создать локального пользователя:

[root@netbox opt]# useradd --system -U netbox
# Меняем владельца в ./netbox/media/
[root@netbox opt]# chown -R netbox:netbox /opt/netbox/

Идем в каталог /opt/netbox/netbox/netbox, и отредактируем конфиг для сервиса:

[root@netbox opt]# cd netbox/netbox/netbox/
[root@netbox netbox]# sudo cp configuration_example.py configuration.py

Открываем конфиг - configuration.py, и указываем значения

[root@netbox netbox]# vim configuration.py
--
# Список хостов, с которых разрешается подключатся к нашему проекту
ALLOWED_HOSTS = ['netbox.office.local', '10.8.13.110']

# Настройки подключения к бд
DATABASE = {
    'NAME': 'netbox_db',         
    'USER': 'netbox_user',           
    'PASSWORD': 'pass',       
    'HOST': 'localhost',    
    'PORT': '5432',           
    'CONN_MAX_AGE': 300,
}

# Настройки подключения к Redis
REDIS = {
    'tasks': {
        'HOST': 'localhost',
        'PORT': 6379,
        'USERNAME': '',
        'PASSWORD': '',
        'DATABASE': 0,
        'SSL': False,
    },
    'caching': {
        'HOST': 'localhost',
        'PORT': 6379,
        'USERNAME': '',
        'PASSWORD': '',
        'DATABASE': 1,
        'SSL': False,
    }
}

В конфиге есть переменная SECRET_KEY, которая должная содержать хеш-ключ для кеширования криптографических объектов.

Сгенерить ключ можно командой:

[root@netbox netbox]# python3 /opt/netbox/netbox/generate_secret_key.py
_H^QugKJBrkMNwqdoe8OBmB_!XXXXXXXxxXXXXXLBZ)NseSb

Этот ключ вставляем конфиг.

Для установки зависимостей проекта, нужно запустить файлик - /opt/netbox/upgrade.sh. Скрипт создаст виртуальное окружение, установит все зависимости и мигранем схемы в бд. Так как у меня сервак спрятан за прокси, перед запуском скрипта, я в окружение добавить переменные с адресом прокси-сервера:

[root@netbox netbox]# export http_proxy=http://proxy-srv:8080
[root@netbox netbox]# export https_proxy=http://proxy-srv:8080
[root@netbox netbox]# /opt/netbox/upgrade.sh

После запуска ожидаем сборку всего проекта.

Создадим административного пользователя, для работы над проектом. Для этого переключаемся в вирт. окружение.

[root@netbox ~]# source /opt/netbox/venv/bin/activate
---
(venv) [root@netbox ~]# cd /opt/netbox/netbox/
(venv) [root@netbox netbox]# python3 manage.py createsuperuser

В netbox реализован механизм housekeeping, который очищает от старых сессий и прочего мусора. Скриптец нужно добавить в крон-задания, для переодического запуска.:

[root@netbox ~]# sudo ln -s /opt/netbox/contrib/netbox-housekeeping.sh /etc/cron.daily/netbox-housekeeping

Для доступа к приложению на django, будем использовать WSGI Http server - gunicorn. В архиве с netbox уже есть файл конфигурации для gunicorn. Просто копируем файл в корень проекта.

[root@netbox ~]# cp /opt/netbox/contrib/gunicorn.py /opt/netbox/gunicorn.py

Также в архиве есть готовые написаные systemd-юниты, для запуска worker процессов gunicorn и netbox. Также копируем их:

[root@netbox ~]# sudo cp -v /opt/netbox/contrib/*.service /etc/systemd/system/
'/opt/netbox/contrib/netbox-rq.service' -> '/etc/systemd/system/netbox-rq.service'
'/opt/netbox/contrib/netbox.service' -> '/etc/systemd/system/netbox.service'

Релодим systemd, и запускаем сервисы:

[root@netbox log]# systemctl daemon-reload
[root@netbox log]# systemctl enable --now netbox netbox-rq

Настройка Nginx

Осталось настроить последний компонент. Отключаем module с nginx:1.14 по умолчанию, и активируем версию nginx 1.20:

[root@netbox ~]# yum module reset nginx
[root@netbox ~]# yum module enable nginx:1.20

Устанавливаем nginx:

[root@netbox ~]# yum install nginx -y

Я заранее выпустил и подписал сертификат локальным CA, и положил их в каталог /etc/nginx/ssl. В архиве с netbox, также поставляется готовый конфиг для nginx. Будем юзать его, но внесем изменения под нашу среду.

Копируем конфиг и редактируем его.

[root@netbox opt]# cp /opt/netbox/contrib/nginx.conf /etc/nginx/conf.d/netbox.conf
[root@netbox opt]# vim /etc/nginx/conf.d/netbox.conf
---
server {
    listen [::]:443 ssl ipv6only=off;
    server_name netbox.office.local;

    ssl_certificate /etc/nginx/ssl/netbox.crt;
    ssl_certificate_key /etc/nginx/ssl/netbox.key;

    ssl_session_timeout 1d;
    ssl_session_cache shared:MozSSL:10m;  # about 40000 sessions
    ssl_session_tickets off;

    # intermediate configuration
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
    ssl_prefer_server_ciphers off;

    # HSTS (ngx_http_headers_module is required) (63072000 seconds)
    add_header Strict-Transport-Security "max-age=63072000" always;

    client_max_body_size 25m;

    location /static/ {
        alias /opt/netbox/netbox/static/;
    }

    location / {
        proxy_pass http://127.0.0.1:8001;
        proxy_set_header X-Forwarded-Host $http_host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}


server {
    listen [::]:80 ipv6only=off;
    server_name _;
    return 301 https://$

Запускаем nginx,

[root@netbox opt]# systemctl enable nginx --now

Не забываем на фаерволе открыть порты 80,443/tcp.

[root@netbox opt]# firewall-cmd --add-port={80,443}/tcp --permanent
[root@netbox opt]# firewall-cmd --reload

В процессе выявилась небольшая трабла, у nginx не было прав на отдачу статики. Исправить это удалось, путем смены группы на каталоге со статикой:

[root@netbox opt]# chown -R :nginx /opt/netbox/netbox/static/

Идем по ссылке - https://netbox.office.local . Для доступа к панельки, используем логин - Admin. И Пароль который мы указывали ранее при создании админ-пользователя джанги. netbox-login.png

Интеграция во FreeIPA (Опционально)

В этом разделе опишу процесс интеграции netbox во freeipa, для реализации единого доступа. Перед началом, нужно выполнить ряд предварительных настроек. Начнем с настроек на стороне FreeIPA Серверов.

Для подключения к ldap-каталогу во freeipa нужно создать сервисного пользователя. Воспользуемся способом через утилиту, которая идет с пакетами freeipa-сервера. Cоздаем binddn-файлик, в котором будем храниться информация по пользователю.

[root@ipa-ho ~]# vim netbox.updater
---
dn: uid=netbox-ldap,cn=sysaccounts,cn=etc,$SUFFIX
default:objectclass:account
default:objectclass:simplesecurityobject
default:uid:netbox-ldap
only:userPassword:PASSWORD
only:passwordExpirationTime:20380119031407Z
only:nsIdleTimeout:0

(В поле password, нужно указать пароль для ldap-пользователя)

Через утилиту ipa-ldap-updater, применяем изменения.

[root@ipa-ho ~]# ipa-ldap-updater netbox.updater
Update complete
The ipa-ldap-updater command was successful

Теперь идем на сервер netbox, и ставим пакеты для работы ldap.

[root@netbox ~]# yum install -y openldap-devel python38-devel

Переключаемся в виртуальное окружение нашего проекта, и ставим зависимость для django.

[root@netbox ~]# source /opt/netbox/venv/bin/activate
(venv) [root@netbox ~]# pip3 install python-ldap django-auth-ldap

После этого этапа осознал что косякнул. Cтавил зависимости питона из под рута и владельцем новых файлов в проекте стал рут. Что бы фиксануть это, по новой нужно сменить владельца и группу на каталог.:

[root@netbox ~]# chown -R netbox:netbox /opt/netbox/
[root@netbox ~]# chown -R :nginx /opt/netbox/netbox/static/

В основном файле конфигурации netbox, включаем удаленную авторизацию и прописываем бекенд.

[root@netbox netbox]# vim /opt/netbox/netbox/netbox/configuration.py
---
REMOTE_AUTH_ENABLED = True
REMOTE_AUTH_BACKEND = 'netbox.authentication.LDAPBackend'

В каталоге (/opt/netbox/netbox/netbox/), рядом с файлом configuration.py создаем файл - ldap_config.py. В котором опишем настройки подключения к freeipa.

import ldap
from django_auth_ldap.config import LDAPSearch, GroupOfNamesType

# Baseline configuration.
AUTH_LDAP_SERVER_URI = "ldap://ipa-ho.office.local"
AUTH_LDAP_BIND_DN = "uid=netbox-ldap,cn=sysaccounts,cn=etc,dc=office,dc=local"
AUTH_LDAP_BIND_PASSWORD = "PASSWORD"

# User configuration
AUTH_LDAP_USER_SEARCH = LDAPSearch("cn=users,cn=accounts,dc=office,dc=local", ldap.SCOPE_SUBTREE,"(sAMAccountName=%(user)s)")
AUTH_LDAP_USER_DN_TEMPLATE = "uid=%(user)s,cn=users,cn=accounts,dc=office,dc=local"
AUTH_LDAP_USER_ATTR_MAP = {
    "first_name": "givenName",
    "last_name": "sn",
    "email": "mail"
}

# Group permission
AUTH_LDAP_GROUP_SEARCH = LDAPSearch("cn=accounts,dc=office,dc=local", ldap.SCOPE_SUBTREE, "(objectClass=group)")
AUTH_LDAP_GROUP_TYPE = GroupOfNamesType()
AUTH_LDAP_REQUIRE_GROUP = "cn=netbox_admins,cn=groups,cn=accounts,dc=office,dc=local"
AUTH_LDAP_MIRROR_GROUPS = True
AUTH_LDAP_USER_FLAGS_BY_GROUP = {
    "is_active": "cn=netbox_admins,cn=groups,cn=accounts,dc=office,dc=local",
    "is_staff": "cn=netbox_admins,cn=groups,cn=accounts,dc=office,dc=local",
    "is_superuser": "cn=netbox_admins,cn=groups,cn=accounts,dc=office,dc=local"
}

AUTH_LDAP_FIND_GROUP_PERMS = True
AUTH_LDAP_CACHE_TIMEOUT = 3600

Конфиг - ldap_config.py можно разбить на 3 большие части:

  • Секция Baseline configuration в ней прописываем основные настройки подключения к ldap-серверу;
    • AUTH_LDAP_SERVER_URI - адрес ldap-сервера (в моем случаи, это ldap://ipa-ho.office.local);
    • AUTH_LDAP_BIND_DN - указывается полный DN пользователя, у которого есть доступ к каталогу;
    • AUTH_LDAP_BIND_PASSWORD - в значение этой переменной, указываем пароль от пользователя.
  • Блок User configuration, здесь прописываем основные настройки для поиска и сопоставления пользователей;
    • AUTH_LDAP_USER_SEARCH - в значении этой переменной, вызывается метод LDAPSearch. В метод мы передаем BaseDN, и атрибутт поиска;
    • AUTH_LDAP_USER_DN_TEMPLATE - тут определяется шаблон для поиска пользователей;
    • AUTH_LDAP_USER_ATTR_MAP - в значение этой переменной определяется словарь с маппингом атрибутов пользователя.
  • Блок Group permission, в этом блоке определяются настройки груп и их прав доступа.
    • AUTH_LDAP_GROUP_SEARCH - аналогично вызывается метод LDAPSearch. В метод мы передаем BaseDN, и класс объектов - группа;
    • AUTH_LDAP_REQUIRE_GROUP - тут в значении DN группы, которой разрешен доступ к сервису;
    • AUTH_LDAP_USER_FLAGS_BY_GROUP - здесь прописывается сопоставление групп и их прав доступа к сервису. У только одна группа для каждого типа.

После перезапускаем сервис netbox, и проверяем корректность работы авторизации.

[root@netbox ~]# systemctl restart netbox