In un homelab, presi dall’entusiasmo, è facile aggiungere servizi, VLAN, macchine virtuali e container in modo quasi compulsivo. In poco tempo, la rete diventa un labirinto di indirizzi IP: quali sono già assegnati? Quali sono liberi? Quali è possibile utilizzare senza generare conflitti? Tenere traccia manualmente di tutto questo risulta caotico e soggetto a errori, soprattutto con l’aumentare della complessità.

È in questo contesto che un IPAM o IP Address Management diventa imprescindibile: uno strumento progettato proprio per centralizzare, organizzare e automatizzare la gestione degli indirizzi IP.

ipam

Ultimamente ho testato diverse soluzioni open source, come NetBox e phpIPAM, ma mi sono sembrate eccessivamente complesse da installare e gestire e con funzionalità superflue per le mie esigenze attuali. Tra le altre soluzioni, NIPAP, nonostante i suoi limiti, rimane per me insostituibile: semplice, funzionale e focalizzato su ciò che realmente serve. Fa una cosa, e la fa bene.

Tuttavia, non è un software perfetto: lo sviluppo, sebbene attivo, procede lentamente, non ci sono nuove funzionalità da tempo, da interfaccia grafica non prevede alcun automatismo e, in molti aspetti, risulta ancora grezzo e macchinoso. Nonostante questo, per il mio utilizzo e per la mia rete interna, i pregi superano i difetti: per me, rimane la scelta migliore.

Installazione di NIPAP

Come descritto nell’articolo dedicato, il primo passaggio consiste nella creazione di una macchina virtuale Debian all’interno di Proxmox VE, utilizzando preferibilmente un template preconfigurato oppure una delle immagini ufficiali in formato qcow2.

Una volta completato il provisioning della macchina virtuale, procedere con l’installazione di Docker seguendo la documentazione ufficiale.

La VM verrà inserita nella VLAN di Management (10.0.5.0/24) e configurata automaticamente tramite Cloud-Init con i seguenti parametri di rete:

  • Indirizzo IP: 10.0.5.21/24
  • Gateway: 10.0.5.254
  • DNS: 10.0.5.254

Risulta superfluo specificare che indirizzi, subnet, VLAN, ecc. dipendono dal proprio laboratorio.

cloudinit-ipam

Dopo la creazione della macchina virtuale, è consigliabile includerla immediatamente nel piano di backup di Proxmox.

NIPAP dietro reverse proxy

Per consentire l’accesso al servizio in HTTPS, NIPAP viene pubblicato dietro un reverse proxy. Nella nostra infrastruttura, viene utilizzato Nginx Proxy Manager Plus, con un certificato self-signed.

proxy-host

custom-certificate

Nella sezione Advanced del Proxy Host aggiungere le seguenti direttive, che consentono di aumentare le dimensioni dei buffer utilizzati dal proxy e prevenire eventuali problemi con risposte HTTP di grandi dimensioni:

proxy_busy_buffers_size   512k;
proxy_buffers             4 512k;
proxy_buffer_size         256k;

Per una maggior sicurezza, possiamo anche impostare delle Access List, limitando l’accesso a soli determinati indirizzi IP.

acl

Bisogna creare la regola di firewall affinché NPM possa raggiungere NIPAP sulla porta 80.

fw-rules

Infine, creare un DNS override in OPNsense da Services > Unbound DNS > Overrides, in modo che ipam.home.lan punti all’indirizzo IP del reverse proxy (10.0.70.1 nel nostro homelab).

Creazione stack Docker compose

Una volta completata la creazione della macchina virtuale e terminate le configurazioni preliminari, accedere alla nuova VM tramite SSH e posizionarsi nella directory /opt, che verrà utilizzata per ospitare lo stack Docker.

Creare quindi la cartella /opt/nipap e, al suo interno, i file docker-compose.yml e .env.

  • docker-compose.yml
x-common-security: &common-security
  cap_drop:
    - ALL
  security_opt:
    - no-new-privileges:true

services:
  db:
    image: nipap/postgres-ip4r:latest
    container_name: nipap-db
    restart: unless-stopped
    <<: *common-security
    cap_add:
      - CHOWN
      - FOWNER
      - DAC_OVERRIDE
      - SETUID
      - SETGID
    stop_grace_period: 30s
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
      interval: 10s
      timeout: 5s
      retries: 10
    environment:
      POSTGRES_DB: ${POSTGRES_DB}
      POSTGRES_USER: ${POSTGRES_USER}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
    volumes:
      - ./postgres:/var/lib/postgresql/data

  nipapd:
    image: nipap/nipapd:latest
    container_name: nipapd
    restart: unless-stopped
    <<: *common-security
    depends_on:
      db:
        condition: service_healthy
    environment:
      # PostgreSQL connection
      DB_HOST: db
      DB_PORT: 5432
      DB_NAME: ${POSTGRES_DB}
      DB_USERNAME: ${POSTGRES_USER}
      DB_PASSWORD: ${POSTGRES_PASSWORD}
      # NIPAP API account
      # Used by nipap-www to authenticate against nipapd
      AUTH_BACKEND: local
      NIPAP_USERNAME: ${NIPAPD_USERNAME}
      NIPAP_PASSWORD: ${NIPAPD_PASSWORD}

  nipap-www:
    image: nipap/nipap-www:latest
    container_name: nipap-www
    restart: unless-stopped
    <<: *common-security
    depends_on:
      - nipapd
    ports:
      - "80:80"
    environment:
      # Connection to NIPAP backend
      NIPAPD_HOST: nipapd
      NIPAPD_PORT: 1337
      # Credentials used to access nipapd API
      NIPAPD_USERNAME: ${NIPAPD_USERNAME}
      NIPAPD_PASSWORD: ${NIPAPD_PASSWORD}
      # Web login credentials
      WWW_USERNAME: ${WWW_USERNAME}
      WWW_PASSWORD: ${WWW_PASSWORD}
  • .env:
POSTGRES_DB=nipap
POSTGRES_USER=nipap
POSTGRES_PASSWORD=

NIPAPD_USERNAME=admin
NIPAPD_PASSWORD=

WWW_USERNAME=admin
WWW_PASSWORD=

In estrema sintesi, il file compose definisce uno stack per l’esecuzione di NIPAP, composto da tre servizi principali: un database PostgreSQL, il demone nipapd e l’interfaccia web nipap-www.

Attraverso l’anchor &common-security, viene applicata a tutti i container una configurazione di sicurezza comune che rimuove tutte le Linux capabilities (cap_drop: ALL) e abilita l’opzione no-new-privileges, impedendo l’acquisizione di privilegi aggiuntivi durante l’esecuzione.

Il servizio db utilizza un’immagine PostgreSQL con supporto all’estensione IP4R, necessaria per la gestione degli indirizzi IP, esegue un controllo di integrità e aggiunge esclusivamente le capability minime richieste dal database per la gestione del filesystem e degli utenti.

Il servizio nipapd, che rappresenta il backend applicativo, viene avviato solo dopo che il database risulta operativo e riceve tramite variabili d’ambiente tutti i parametri necessari per la connessione al database.

Infine, il servizio nipap-www fornisce l’interfaccia web dell’applicazione, esponendo la porta HTTP 80 dell’host.

Una volta completata la configurazione dei file, avviare lo stack Docker dalla directory /opt/nipap eseguendo il comando docker compose up -d.

Al termine della procedura, verificare che tutti i container siano in esecuzione mediante il comando docker ps.

docker ps

CONTAINER ID   IMAGE                        COMMAND                  CREATED         STATUS                   PORTS                                 NAMES
22b1c0dcfa77   nipap/nipap-www:latest       "/nipap-www/entrypoi…"   2 minutes ago   Up 2 minutes             0.0.0.0:80->80/tcp, [::]:80->80/tcp   nipap-www
c86a4a423876   nipap/nipapd:latest          "/nipap/entrypoint.sh"   2 minutes ago   Up 2 minutes             1337/tcp                              nipapd
c1a483ad7546   nipap/postgres-ip4r:latest   "/docker-entrypoint.…"   2 minutes ago   Up 2 minutes (healthy)   5432/tcp                              nipap-db

Se l’installazione è stata completata correttamente, l’interfaccia web di NIPAP sarà raggiungibile all’indirizzo https://ipam.home.lan, utilizzando le credenziali definite dalle variabili WWW_USER e WWW_PASSWORD.

nipap

Configurazione dei prefix in NIPAP

NIPAP organizza le reti in modo gerarchico, utilizzando tre tipologie di prefissi:

  • Reservation: rappresenta uno spazio di indirizzi riservato che può contenere altre subnet
  • Assignment: identifica una subnet effettivamente assegnata a una rete o a una VLAN
  • Host: rappresenta un singolo indirizzo IP assegnato a un dispositivo

Ad esempio, nel nostro homelab in cui tutte le VLAN appartengono alla rete 10.0.0.0/8, è possibile organizzare la struttura come segue:

Reservation
└── 10.0.0.0/8
    ├── Assignment 10.0.5.0/24   (Management)
    ├── Assignment 10.0.10.0/24  (LAN)
    ├── Assignment 10.0.20.0/24  (WLAN)
    └── ...

È proprio durante la creazione di nuovi prefissi che emerge la legnosità a cui accennavamo: non è possibile indicare direttamente il prefisso o l’indirizzo IP desiderato. NIPAP assegna automaticamente il primo prefisso o il primo indirizzo disponibile compatibile con il CIDR richiesto.

Ad esempio, se esiste la reservation 10.0.0.0/8 e si richiede la creazione di un nuovo Assignment /24, il sistema potrebbe proporre automaticamente 10.0.0.0/24 oppure il primo blocco libero disponibile all’interno della Reservation.

Se invece si desidera creare, ad esempio, la VLAN Management sulla subnet 10.0.5.0/24, sarà necessario:

  • creare inizialmente l’assignment e lasciare quello proposto automaticamente da NIPAP
  • modificare successivamente l’assignment assegnato, sostituendolo con 10.0.5.0/24

Lo stesso comportamento si applica agli host: viene sempre proposto il primo indirizzo IP disponibile e, se necessario, questo deve essere modificato manualmente, dopo il salvataggio, come mostrato nelle immagini seguenti:

prefix-allocation

edit-prefix

save-new-prefix

Un altro difetto é che non risulta possibile, da web, impostare il range del DHCP.

Questo approccio può sembrare macchinoso durante la configurazione iniziale, soprattutto se si sta importando una rete già esistente. Una volta completata la fase di popolamento, tuttavia, il workflow diventa molto più naturale: per ogni nuova VM, server o dispositivo è sufficiente creare un nuovo host in NIPAP e lasciare che il sistema suggerisca il primo indirizzo libero, oppure modificare il valore proposto qualora sia necessario utilizzare un indirizzo specifico.

Al termine della configurazione, la struttura dei prefissi dovrebbe risultare simile alla seguente:

nipap-create-reservation

Riferimenti