Files
stupid-simple-network-inven…/README.es.md
T
olivier fb6bcdb968 feat: add generic archive server icon
Custom archive-box icon (stone #78716C) triggered by: archive, archiver
(FR/EN), archivage (FR), archivar (ES), archivebox.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-17 12:44:17 +02:00

14 KiB

Stupid Simple Network Inventory

Aplicación web autoalojada para inventario de red y visualización de topología lógica

English · Français

Python FastAPI Vue.js SQLite Nginx Docker License: GPL v3


Vista de Topología


Características

  • 🗂️ Inventario manual — añade y gestiona dispositivos (21 tipos) con IPs, VLANs, descripciones y enlaces web opcionales
  • 🗺️ Vista de topología — disposición en tarjetas por red (LAN / VLAN 802.1Q), con secciones WAN y puerta de enlace
  • 📡 Ping ICMP — comprueba la accesibilidad de todos los hosts conocidos con un clic
  • 🔍 Descubrimiento automático — ping sweep + consulta PTR DNS en una subred para importar nuevos hosts
  • 🏷️ Logos de fabricantes — detección y visualización automáticas de logos de editores/fabricantes (Proxmox, Cisco, Synology, Docker, y más de 30 más)
  • 🔐 Autenticación — inicio de sesión JWT con cambio de contraseña obligatorio en el primer uso
  • 🌙 Modo oscuro — alternancia entre tema claro y oscuro
  • 🌍 i18n — francés, inglés, español

🛠️ Stack

Capa Tecnología
Backend FastAPI + SQLAlchemy + SQLite (Python 3.11)
Frontend Vue 3 + Vite, servido por Nginx
Auth JWT HS256, expiración 24h
Runtime Docker Compose

🚀 Inicio rápido

# 1. Clonar y entrar en el proyecto
git clone https://git.raspot.in/olivier/stupid-simple-network-inventory.git
cd stupid-simple-network-inventory

# 2. Crear el directorio de datos propiedad del usuario actual
mkdir -p db_data

# 3. Configurar el entorno (necesario para la propiedad correcta del bind-mount)
cp .env.example .env
# Editar .env:
#   DOCKER_UID / DOCKER_GID → resultado de: id -u && id -g
#   INITIAL_ADMIN_PASSWORD  → definir para evitar el bootstrap admin/admin por defecto

# 4. Construir e iniciar
docker compose --env-file .env up --build -d

# 5. Abrir http://localhost:8080 en el navegador

Primer inicio de sesión

Caso Credenciales Comportamiento
INITIAL_ADMIN_PASSWORD definido admin / <tu contraseña> Inicio de sesión normal
INITIAL_ADMIN_PASSWORD no definido admin / admin Cambio de contraseña obligatorio antes de acceder a la aplicación

🔄 Actualización

Los datos se almacenan en ./db_data/ (bind-mount), que nunca es modificado al reconstruir los contenedores. La actualización es segura:

git pull
docker compose up --build -d

Las migraciones de base de datos se ejecutan automáticamente al iniciar — no se requieren pasos manuales.


⚙️ Configuración

Toda la configuración se realiza mediante variables de entorno. Ver .env.example para la lista completa con descripciones.

Variable Por defecto Descripción
SECRET_KEY auto-generada Clave de firma JWT. Definir explícitamente en producción.
INITIAL_ADMIN_PASSWORD (vacío) Contraseña de bootstrap del admin. Si no se define, se usa admin/admin con cambio forzado.
ALLOWED_ORIGINS * Orígenes CORS permitidos (separados por comas). Definir en tu dominio en producción.
BIND_ADDRESS 0.0.0.0 Dirección IP de escucha. Definir en la interfaz frente al reverse proxy.
DOCKER_UID / DOCKER_GID 1000 UID/GID para el proceso backend. Debe coincidir con el usuario propietario de ./db_data/.
cp .env.example .env
# Editar .env — definir como mínimo DOCKER_UID, DOCKER_GID, INITIAL_ADMIN_PASSWORD
docker compose --env-file .env up --build -d

🔒 Seguridad

Gestión de secretos

Dos opciones según sus requisitos de seguridad.

Opción A — Secreto auto-generado (recomendado para nodo único)

Dejar SECRET_KEY sin definir (o vacío) en .env. En el primer arranque, el backend genera una clave hexadecimal aleatoria de 64 caracteres, la escribe en db_data/secret_key.txt con permisos 0600 y la reutiliza en cada reinicio posterior. El secreto nunca aparece en una variable de entorno, un archivo compose o un log.

# .env — dejar la línea vacía o eliminarla
SECRET_KEY=

El único requisito es que db_data/ esté respaldado (ya contiene la base de datos).

Opción B — Secreto mediante archivo Docker Compose

Almacena el secreto en un archivo en el host, fuera del control de versiones, y lo monta en el contenedor. El valor nunca aparece en una variable de entorno.

# Generar y almacenar el secreto fuera del directorio del proyecto
mkdir -p ~/.secrets
python3 -c "import secrets; print(secrets.token_hex(32))" > ~/.secrets/topologie_secret_key
chmod 600 ~/.secrets/topologie_secret_key

Luego descomentar los bloques secrets: en docker-compose.yml (ver los comentarios en ese archivo) y eliminar SECRET_KEY de .env. Docker Compose fusiona la anulación automáticamente:

docker compose up -d

Rotación de clave

Para rotar el secreto JWT (invalida todas las sesiones activas):

# Opción A — variable de entorno (recomendado)
# Definir un nuevo SECRET_KEY en la configuración de despliegue y reiniciar

# Opción B — rotación por archivo
docker compose stop backend
rm db_data/secret_key.txt
docker compose start backend
# Todos los usuarios deberán iniciar sesión de nuevo

HTTPS

Esta aplicación no termina TLS. Para uso en producción, colócala detrás de un reverse proxy que gestione HTTPS.

Nginx

server {
    listen 443 ssl;
    server_name inventory.example.com;

    ssl_certificate     /etc/letsencrypt/live/inventory.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/inventory.example.com/privkey.pem;

    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Traefik — Labels Docker

Añadir estas etiquetas al servicio frontend y conectarlo a la red compartida con Traefik:

# docker-compose.override.yml
services:
  frontend:
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.inventory.rule=Host(`inventory.example.com`)"
      - "traefik.http.routers.inventory.entrypoints=websecure"
      - "traefik.http.routers.inventory.tls.certresolver=letsencrypt"
      - "traefik.http.services.inventory.loadbalancer.server.port=8080"
    networks:
      - internal
      - traefik_public  # red compartida con tu instancia de Traefik

networks:
  traefik_public:
    external: true

Traefik — Configuración dinámica (file provider)

Si Traefik no corre en Docker (o prefieres el file provider), deposita un archivo en tu directorio de configuración dinámica:

# /etc/traefik/dynamic/inventory.yml
http:
  routers:
    inventory:
      rule: "Host(`inventory.example.com`)"
      entryPoints:
        - websecure
      tls:
        certResolver: letsencrypt
      service: inventory-svc

  services:
    inventory-svc:
      loadBalancer:
        servers:
          - url: "http://127.0.0.1:8080"

Traefik detecta el archivo automáticamente — no se requiere reinicio.

Para uso solo local, enlazar a loopback para evitar exposición accidental en la LAN:

# docker-compose.override.yml
services:
  frontend:
    ports:
      - "127.0.0.1:8080:8080"

Endurecimiento de contenedores

Medida Backend Frontend
Usuario no-root DOCKER_UID:DOCKER_GID (usuario host) nginx (UID 101)
cap_drop: ALL
cap_add: NET_RAW ✓ (ping)
no-new-privileges — ¹
Healthcheck

¹ Omitido en el backend: el ping usa file capabilities (cap_net_raw=ep); no-new-privileges suprimiría el bit efectivo del archivo e impediría al subproceso adquirir CAP_NET_RAW en su conjunto efectivo aunque el padre lo tenga en su conjunto permitido.


💾 Persistencia de datos

Todos los datos se almacenan en ./db_data/:

Archivo Descripción
topology.db Base de datos SQLite
secret_key.txt Secreto JWT auto-generado (permisos 0600)

Copia de seguridad: cp -r db_data/ db_data.bak/

Restauración: detener la stack, reemplazar db_data/, reiniciar.


🏷️ Detección de logos de marcas

La detección se realiza automáticamente sobre el nombre y la descripción del equipo (coincidencia de palabras clave, sin distinción de mayúsculas). No se requiere configuración manual — basta con incluir una palabra clave reconocible en el nombre o la descripción.

Los logos se muestran en dos lugares:

  • Vista de topología — pequeños SVGs en línea junto al nombre del equipo en cada chip
  • Lista de equipos — badge(s) de color en la card del equipo

Pueden aparecer varios logos simultáneamente si coinciden varias palabras clave.

Categoría Marca Palabras clave
Virtualización Proxmox proxmox, pve
Virtualización Docker docker
NAS Synology synology, dsm
NAS TrueNAS truenas, freenas
Red Ubiquiti / UniFi ubiquiti, unifi, usg, udm
Red MikroTik mikrotik, routeros
Red Cisco cisco
Red TP-Link tp-link, tplink
Red ASUS asus
Red Netgear netgear
Red pfSense pfsense
Red OPNsense opnsense
Red OpenWrt openwrt
Web / proxy Apache apache, apache2, httpd
Web / proxy Traefik traefik
Auth / SSO Authelia authelia
Auth / SSO Keycloak keycloak
Auth / SSO Authentik authentik
Auth / SSO Okta okta
Auth / SSO Auth0 auth0
Gestor de contraseñas Vaultwarden vaultwarden
Gestor de contraseñas Bitwarden bitwarden
Gestor de contraseñas 1Password 1password, onepassword
Gestor de contraseñas KeePassXC keepass, keepassxc
Gestor de contraseñas HashiCorp Vault hashicorp vault, hashicorp
Archivado Servidor de archivado archive, archiver, archivage, archivar, archivebox
Correo Servidor de correo mail, smtp, imap, postfix, dovecot, mailcow, mailu, roundcube
Base de datos MariaDB mariadb
Orquestación Kubernetes kubernetes, k8s, kubectl, k3s
OS Debian debian
OS Ubuntu ubuntu
Automatización Ansible ansible
Servidores Dell dell, idrac, poweredge
Servidores HP proliant, ilo, hewlett
SBC / DIY Raspberry Pi raspberry, rpi, raspi
SBC / DIY Arduino arduino
Escritorio KDE / Plasma kde, plasma
Herramientas Excalidraw excalidraw
Self-hosted Nextcloud nextcloud
Self-hosted Paperless-NGX paperless, paperless-ngx
Self-hosted Uptime Kuma uptime-kuma, uptime kuma
Self-hosted MkDocs mkdocs
CMS / Blog WordPress wordpress
CMS / Blog Ghost ghost
CMS / Blog Grav grav
CMS / Blog Jekyll jekyll
CMS / Blog Hugo hugo
CMS / Blog Hexo hexo
CMS / Blog Drupal drupal
CMS / Blog Joomla joomla
CMS / Blog TYPO3 typo3
CMS / Blog OctoberCMS octobercms, october cms
CMS / Blog Textpattern textpattern
Analítica Matomo matomo
Analítica Plausible plausible
Medios / torrent Radarr radarr
Medios / torrent Sonarr sonarr
Medios / torrent Transmission transmission
Medios / domótica Jellyfin jellyfin
Medios / domótica Home Assistant homeassistant, home assistant, hassio
Medios / domótica Philips Hue philips hue, hue bridge
Medios / domótica Xiaomi xiaomi, mi home, yeelight

🧑‍💻 Desarrollo

Tests del backend

cd backend
pip install -r requirements.txt -r requirements-test.txt
pytest tests/ -v

Dev local (sin Docker)

# Backend
cd backend
pip install -r requirements.txt
uvicorn main:app --reload

# Frontend (terminal separada)
cd frontend
npm install
npm run dev   # Servidor dev Vite en :5173, proxifica /api/ hacia :8000

🏗️ Arquitectura

Ver docs/architecture.md para el flujo de solicitudes detallado, la configuración Docker y el modelo de autenticación.


🤖 Desarrollado con asistencia de IA

Esta aplicación fue desarrollada íntegramente con la ayuda de asistentes de código IA:

  • Claude Code (Anthropic) — utilizado a lo largo del proyecto para el diseño de la arquitectura, la API backend (FastAPI, SQLAlchemy, autenticación, descubrimiento ICMP), los componentes frontend (Vue 3, layout CSS de topología, i18n, modo oscuro), la configuración Docker & Nginx, y la documentación.
  • Codex (OpenAI) — también utilizado durante el desarrollo para la generación de código y sugerencias en todo el proyecto.

📄 Licencia

Este proyecto se distribuye bajo la Licencia Pública General GNU v3.0.

Eres libre de usar, modificar y distribuir este software bajo los términos de la GPL v3. Cualquier trabajo derivado debe distribuirse bajo la misma licencia.