A full-stack web application for managing Cisco Catalyst 9300/9200 switches across multiple sites. Provides device visibility via NetBox, real-time monitoring via SolarWinds, and network automation via Python scripts (SSH directly to devices) — all from a single pane of glass.
- Device Inventory — Hierarchical site/device navigation with real-time status indicators sourced from NetBox
- Monitoring Dashboard — Device health metrics (CPU, memory, response time, packet loss), events, alerts, and syslog aggregation via SolarWinds
- Network Automation — Trigger Python show scripts and config backup from the UI with live output — SSH directly to devices via Netmiko
- Real-Time Updates — WebSocket-powered status changes pushed to the browser instantly
- Configuration Backup — Back up running configs to Gitea for version control
- Authentication — Session-based login with server-side credential proxying (no secrets in the browser)
| Layer | Technology |
|---|---|
| Frontend | React 18, TypeScript, Vite, Tailwind CSS, Zustand, React Query |
| Backend | Express, TypeScript, Socket.io |
| Automation | Python 3, Netmiko (Ansible reserved for future config-push operations) |
| Inventory | NetBox (source of truth) |
| Monitoring | SolarWinds (SWIS REST API) |
| Version Control | Gitea |
- Node.js 20 LTS
- Python 3 with pip packages:
netmiko,python-dotenv,requests - Access to NetBox, SolarWinds, and Gitea instances
pip install netmiko python-dotenv requestsgit clone https://github.com/Derwynnm/NACC.git
cd NACC
cp .env.example .env
# Edit .env with your credentials and service URLsWindows:
npm install
npm run devLinux (native server or VirtualBox):
chmod +x scripts/setup-linux.sh
./scripts/setup-linux.sh
./scripts/start-dev.shThe app runs at:
- Frontend:
http://localhost:5173 - Backend API:
http://localhost:3001
Copy .env.example to .env and configure:
| Variable | Description |
|---|---|
APP_NAME |
Application display name |
API_PORT |
Backend server port (default: 3001) |
CORS_ORIGINS |
Comma-separated allowed origins |
NETBOX_URL |
NetBox server URL |
NETBOX_TOKEN |
NetBox API token |
SOLARWINDS_URL |
SolarWinds SWIS REST API URL (port 17778) |
SOLARWINDS_USERNAME |
SolarWinds username (DOMAIN\user format) |
SOLARWINDS_PASSWORD |
SolarWinds password |
SOLARWINDS_VERIFY_SSL |
SSL verification (default: false) |
GITEA_URL |
Gitea server URL |
GITEA_TOKEN |
Gitea API token |
GITEA_BACKUP_REPO |
Gitea repo for config backups (format: owner/repo) |
ADMIN_PASSWORD |
Application login password |
PYTHON_SCRIPTS_PATH |
Absolute path to scripts/python/ on the server |
NETWORK_USERNAME |
SSH username for network devices |
NETWORK_PASSWORD |
SSH password for network devices |
NETWORK_SECRET |
Enable secret for network devices |
ANSIBLE_PLAYBOOK_PATH |
Reserved — absolute path to ansible/playbooks/ |
ANSIBLE_INVENTORY_PATH |
Reserved — absolute path to ansible/inventory/netbox.yml |
| Method | Path | Description |
|---|---|---|
| POST | /api/auth/login |
User login |
| POST | /api/auth/logout |
User logout |
| GET | /api/auth/me |
Current user info |
| GET | /api/health |
Service health check |
| Method | Path | Description |
|---|---|---|
| GET | /api/dashboard |
Aggregated dashboard data |
| GET | /api/netbox/sites |
List all sites |
| GET | /api/netbox/devices |
List all devices |
| GET | /api/netbox/devices/:id |
Device details |
| GET | /api/solarwinds/health/bulk |
All device health (cached) |
| GET | /api/solarwinds/devices/:ip/health |
Device health by IP |
| GET | /api/solarwinds/devices/:ip/logs |
Unified events + alerts + syslog |
| GET | /api/solarwinds/devices/:ip/syslogs |
Syslog messages (Warning+) |
| GET | /api/solarwinds/events/recent |
Recent events across inventory |
| GET | /api/solarwinds/syslogs/recent |
Recent syslog across inventory |
| POST | /api/automation/run |
Trigger automation script |
| GET | /api/automation/jobs |
List automation jobs |
| GET | /api/automation/jobs/:id |
Job status and output |
| GET | /api/automation/playbooks |
List available scripts |
| POST | /api/automation/backup/:id |
Backup device config to Gitea |
All scripts are read-only — no configuration changes are made to devices. Scripts live in scripts/python/ and SSH directly to devices using Netmiko. See scripts/python/README.md for the interface contract.
| Script | Command(s) | Purpose |
|---|---|---|
show_version.py |
show version |
Device model, uptime, software version |
show_interfaces.py |
show ip interface brief |
Interface status and up/down counts |
show_vlan.py |
show vlan brief |
VLAN configuration |
show_running.py |
show running-config |
Current device configuration |
show_power_inline.py |
show power inline, show environment power all |
PoE power status |
backup_config.py |
show running-config |
Backup running config to Gitea via API |
NACC/
├── backend/ # Express API server
│ └── src/
│ ├── config/env.ts # Environment config
│ ├── middleware/auth.ts # Authentication
│ ├── routes/ # API route handlers
│ └── services/ # NetBox, SolarWinds, Ansible, Python clients
├── frontend/ # React application
│ └── src/
│ ├── api/client.ts # API hooks (React Query)
│ ├── components/ # UI components
│ ├── hooks/useSocket.ts # WebSocket connection
│ ├── store/ # Zustand state stores
│ └── types/ # TypeScript types
├── ansible/ # Ansible playbooks (reserved for future config-push)
│ ├── playbooks/
│ ├── inventory/
│ └── group_vars/
├── scripts/
│ ├── python/ # Python show/backup scripts (Netmiko)
│ ├── setup-linux.sh # Linux environment setup
│ ├── start-dev.sh # Start dev servers
│ └── mount-modules.sh # VirtualBox mount helper
├── docker-compose.yml # Docker Compose config
├── .env.example # Environment template
└── ARCHITECTURE.md # Detailed architecture docs
docker-compose up # Start frontend container
docker-compose down # Stop servicesIndividual images:
docker build -f Dockerfile.backend -t nacc-backend .
docker build -f Dockerfile.frontend -t nacc-frontend .npm run dev # Start both backend and frontend
npm run backend:dev # Backend only (port 3001)
npm run frontend:dev # Frontend only (port 5173)
npm run build # Production buildThe setup script auto-detects the filesystem type:
- Native server (git clone) — installs npm packages directly in the project directory, no extra steps needed
- VirtualBox shared folder — automatically bind-mounts
node_modulesto the VM's local disk to work around vboxsf I/O limitations. After a VM reboot, re-run./scripts/start-dev.sh(it handles remounting automatically)
See ARCHITECTURE.md for detailed architecture documentation including data flow, service interactions, and design decisions.
Private repository. All rights reserved.