Files
stupid-simple-network-inven…/README.es.md
T
olivier cd1be8eaa5 docs: add update procedure section to all READMEs
Explains that db_data/ is preserved across container rebuilds and that
database migrations run automatically on startup.

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

10 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 (18 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.


🧑‍💻 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.