Trigger keyword: authelia. Icon colour: #113155. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
13 KiB
Stupid Simple Network Inventory
Aplicación web autoalojada para inventario de red y visualización de topología lógica
✨ 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 |
| Web / proxy | Authelia | authelia |
| 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 |
| 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.
