mirror of
https://github.com/jcreek/OpenNetworkDiagram.git
synced 2026-09-10 23:23:43 +00:00
335 lines
14 KiB
Markdown
335 lines
14 KiB
Markdown
# Open Network Diagram
|
|
|
|
[](https://hub.docker.com/r/jcreek23/open-network-diagram)
|
|
[](https://github.com/jcreek/OpenNetworkDiagram/actions/workflows/release.yml)
|
|
[](https://github.com/jcreek/OpenNetworkDiagram/actions/workflows/docker.yml)
|
|
[](https://github.com/jcreek/OpenNetworkDiagram/releases)
|
|
[](https://opennetworkdiagram.jcreek.co.uk)
|
|
|
|
**A declarative, self-hosted containerised tool for visualising and managing home lab & network architecture diagrams.**
|
|
|
|
Open Network Diagram helps you document your infrastructure in a visual UI while keeping a real JSON source of truth you can back up, reuse, and optionally version after reviewing it for sensitive information.
|
|
|
|
- Homelab-friendly: run it in minutes with Docker.
|
|
- Practical: edit in the UI and autosave to `network.json`.
|
|
- Declarative: keep your topology in Git if you wish.
|
|
|
|
[Docker Hub](https://hub.docker.com/r/jcreek23/open-network-diagram) | [Live Demo (Read-Only)](https://opennetworkdiagram.jcreek.co.uk) | [GitHub Releases](https://github.com/jcreek/OpenNetworkDiagram/releases)
|
|
|
|

|
|
|
|
## Features
|
|
|
|
- Network view with ethernet labels to make physical and logical links easy to read.
|
|
- Hosts & VMs view for host-first inventory and service mapping.
|
|
- Rack view: managed racks with U positions and heights, side-by-side shelf items, and click-through to the editor.
|
|
- Node search that highlights matches by name, IP, role or OS and dims everything else.
|
|
- IPAM panel: per-subnet utilization, duplicate-IP conflict detection, and next-free-IP suggestions when adding machines, devices or VMs.
|
|
- Subnet and VLAN declarations, with nodes colour-coded by VLAN and a clickable legend filter.
|
|
- Cable tracking on connections (type, colour, length) with colour-coded links and hover details.
|
|
- Expandable VM lists per machine for quick virtualization visibility.
|
|
- Modal editor for machines/devices with live diagram updates, notes and MAC address fields.
|
|
- JSON-backed persistence with autosave in self-hosted mode.
|
|
- Docker-first deployment with writable data volume support.
|
|
- Optional read-only mode for public demos and safe sharing.
|
|
- Local vendored icon catalog for offline-friendly runtime behavior.
|
|
|
|
## Why Home Lab Users Use It
|
|
|
|
- Keep an always-up-to-date map of machines, VMs, and devices.
|
|
- Find a free IP and spot duplicate assignments without a spreadsheet.
|
|
- Know exactly what's in your rack and where, down to the U.
|
|
- Edit quickly through a modal UI instead of hand-editing large diagrams.
|
|
- Persist everything to JSON so backups and Git workflows stay simple.
|
|
- Stay fully self-hosted with no runtime dependency on external APIs.
|
|
|
|
## 2-Minute Docker Quick Start
|
|
|
|
This is the fastest way to run Open Network Diagram for a home lab.
|
|
|
|
1. Create a local data folder:
|
|
|
|
```bash
|
|
mkdir -p data
|
|
```
|
|
|
|
2. Run the published Docker image:
|
|
|
|
```bash
|
|
docker run -d \
|
|
--name open-network-diagram \
|
|
--restart unless-stopped \
|
|
-p 8080:3000 \
|
|
--user "$(id -u):$(id -g)" \
|
|
-e NETWORK_DATA_FILE=/app/data/network.json \
|
|
-e NETWORK_BACKUP_DIR=/app/data/.backups \
|
|
-v "$(pwd)/data:/app/data" \
|
|
jcreek23/open-network-diagram:latest
|
|
```
|
|
|
|
On first access, Open Network Diagram creates a valid blank `data/network.json` and shows the getting-started card.
|
|
|
|
3. Open the app at `http://localhost:8080`.
|
|
|
|
4. Add your first machine. Changes and rolling backups remain directly accessible in the local `data` directory across container updates and restarts.
|
|
|
|
Useful follow-up commands:
|
|
|
|
```bash
|
|
docker logs -f open-network-diagram
|
|
docker stop open-network-diagram
|
|
docker rm open-network-diagram
|
|
```
|
|
|
|
The `--user` option runs the container with your host UID and GID so files in the bind mount remain writable and owned by your account. Docker Desktop commonly handles bind-mount permissions without this mapping, so macOS users can omit `--user` if their Docker Desktop configuration requires the image's built-in user. If storage is not writable, the app leaves it untouched, loads the bundled read-only demo, and reports the exact permission problem in the UI.
|
|
|
|
### Optional Sample Data
|
|
|
|
The application starts with a blank network by default. To explore the sample topology instead, download it before starting the container:
|
|
|
|
```bash
|
|
curl -fsSL https://raw.githubusercontent.com/jcreek/OpenNetworkDiagram/main/data/network.json.example \
|
|
-o data/network.json
|
|
```
|
|
|
|
The sample is optional and is never required for startup.
|
|
|
|
## Deployment Security
|
|
|
|
Open Network Diagram does not include authentication or TLS. The quick-start port mapping `-p 8080:3000` listens on all host interfaces, so any device that can reach the host can view the topology and, in writable mode, change it.
|
|
|
|
Do not expose a writable deployment directly to the internet. Restrict access with a firewall, LAN or VPN, or place the application behind an authenticated reverse proxy that terminates TLS.
|
|
|
|
To make the service reachable only from the Docker host, replace the quick-start mapping with `-p 127.0.0.1:8080:3000`.
|
|
|
|
For a public demonstration, add `-e NETWORK_READ_ONLY=true` to `docker run`, or add `NETWORK_READ_ONLY: 'true'` under Compose's `environment`. Read-only mode prevents changes and uses the bundled demo if the configured data file is missing, but it does not hide a configured topology or replace authentication.
|
|
|
|
## What It Looks Like
|
|
|
|
| Network view with ethernet labels | Hosts & VMs view with VMs expanded | Modal editing a machine |
|
|
| -------------------------------------------------------------------------- | --------------------------------------------------------------------------- | ---------------------------------------------------------------- |
|
|
|  |  |  |
|
|
|
|
| IPAM panel with subnet utilization | Rack view with shelf items | Dark mode |
|
|
| --------------------------------------------------------------------------- | ------------------------------------------------------------------- | -------------------------------------------------- |
|
|
|  |  |  |
|
|
|
|
| Zero-setup first run | Read-only live demo |
|
|
| ------------------------------------------------------------------------ | ------------------------------------------------------------ |
|
|
|  |  |
|
|
|
|
## Docker Compose Option
|
|
|
|
If you prefer compose:
|
|
|
|
```yaml
|
|
services:
|
|
open-network-diagram:
|
|
image: jcreek23/open-network-diagram:latest
|
|
user: '${OND_UID:-1000}:${OND_GID:-1000}'
|
|
ports:
|
|
- '8080:3000'
|
|
volumes:
|
|
- ./data:/app/data
|
|
environment:
|
|
NETWORK_DATA_FILE: /app/data/network.json
|
|
NETWORK_BACKUP_DIR: /app/data/.backups
|
|
restart: unless-stopped
|
|
```
|
|
|
|
Start it with:
|
|
|
|
```bash
|
|
mkdir -p data
|
|
OND_UID="$(id -u)" OND_GID="$(id -g)" docker compose up -d
|
|
```
|
|
|
|
`OND_UID` and `OND_GID` are used only by Compose to select the container process identity; they are not application environment variables. The defaults suit common Linux installations. Docker Desktop users can remove the `user` line if their file-sharing configuration requires the image's built-in user.
|
|
|
|
### Using a Docker Named Volume
|
|
|
|
If host-directory permissions are inconvenient, Docker can manage the storage volume instead:
|
|
|
|
```bash
|
|
docker run -d \
|
|
--name open-network-diagram \
|
|
--restart unless-stopped \
|
|
-p 8080:3000 \
|
|
-e NETWORK_DATA_FILE=/app/data/network.json \
|
|
-e NETWORK_BACKUP_DIR=/app/data/.backups \
|
|
-v ond-data:/app/data \
|
|
jcreek23/open-network-diagram:latest
|
|
```
|
|
|
|
Docker creates the `ond-data` volume automatically. Use `docker volume inspect ond-data` to inspect its location or `docker cp open-network-diagram:/app/data/network.json ./network.json` to copy the data file out.
|
|
|
|
### Versioning Your Topology
|
|
|
|
`data/network.json` and `data/.backups` are ignored by Git because topology data may expose host names, addresses, MAC addresses, and other sensitive infrastructure details. If you have reviewed and sanitized the data and deliberately want to track it, opt in with:
|
|
|
|
```bash
|
|
git add -f data/network.json
|
|
git commit -m "Track network topology"
|
|
```
|
|
|
|
Once the file is tracked, normal Git commands include later changes. Backup files remain ignored.
|
|
|
|
## For Developers
|
|
|
|
### Local Development
|
|
|
|
```bash
|
|
git clone https://github.com/jcreek/OpenNetworkDiagram.git
|
|
cd OpenNetworkDiagram
|
|
pnpm install
|
|
pnpm run dev
|
|
```
|
|
|
|
App URL: `http://localhost:5173`
|
|
|
|
### Build Targets
|
|
|
|
```bash
|
|
pnpm run build # default build
|
|
pnpm run build:docker # Docker/static target
|
|
pnpm run build:netlify # Netlify target (read-only mode)
|
|
pnpm run icons:manifest # regenerate local vendor icon manifest
|
|
```
|
|
|
|
### Runtime and Persistence
|
|
|
|
- API endpoint: `GET/PUT /api/network-data`
|
|
- Writes are enabled unless `NETWORK_READ_ONLY=true`
|
|
- Writable deployments automatically initialize a missing or whitespace-only data file with a blank network.
|
|
- Read-only deployments never initialize or modify the configured data file and continue to use the bundled demo when the API data is unavailable.
|
|
- When writes are unavailable, API responses include `writableReason` for diagnostics.
|
|
- Writes are persisted atomically to the configured data file
|
|
- Rolling backups are kept in the backup directory (last 5)
|
|
|
|
Environment variables:
|
|
|
|
- `NETWORK_READ_ONLY` (default: `false`)
|
|
- Set to `true` to disable writes and force read-only mode.
|
|
- `NETWORK_DATA_FILE` (default: `data/network.json`)
|
|
- JSON file path to read/write.
|
|
- `NETWORK_BACKUP_DIR` (default: `data/.backups`)
|
|
- Directory for backup files.
|
|
|
|
### JSON Example
|
|
|
|
```json
|
|
{
|
|
"machines": [
|
|
{
|
|
"machineName": "ProxRouter",
|
|
"ipAddress": "10.0.0.3",
|
|
"role": "Hypervisor",
|
|
"operatingSystem": "Proxmox",
|
|
"notes": "Primary router box.",
|
|
"software": {
|
|
"vms": [
|
|
{
|
|
"name": "OpnSense",
|
|
"role": "Router",
|
|
"ipAddress": "10.0.0.4",
|
|
"macAddress": "bc:24:11:5a:2e:01"
|
|
}
|
|
]
|
|
},
|
|
"hardware": {
|
|
"cpu": "Intel N100",
|
|
"ram": "8GB",
|
|
"networkPorts": 4
|
|
},
|
|
"ports": [
|
|
{
|
|
"portName": "eth0",
|
|
"speedGbps": 1,
|
|
"connectedTo": {
|
|
"device": "Switch",
|
|
"port": "1",
|
|
"cable": { "type": "Cat6", "color": "blue", "lengthM": 1 }
|
|
}
|
|
}
|
|
],
|
|
"rack": { "name": "Lab Rack", "unit": 10 }
|
|
}
|
|
],
|
|
"devices": [
|
|
{
|
|
"name": "Switch",
|
|
"ipAddress": "10.0.0.2",
|
|
"type": "Network Switch",
|
|
"ports": [
|
|
{
|
|
"portName": "1",
|
|
"speedGbps": 1,
|
|
"connectedTo": {
|
|
"device": "ProxRouter",
|
|
"port": "eth0",
|
|
"cable": { "type": "Cat6", "color": "blue", "lengthM": 1 }
|
|
}
|
|
}
|
|
],
|
|
"rack": { "name": "Lab Rack", "unit": 12 }
|
|
}
|
|
],
|
|
"subnets": [{ "cidr": "10.0.0.0/24", "name": "LAN", "vlanId": 1 }],
|
|
"racks": [{ "name": "Lab Rack", "heightU": 12 }]
|
|
}
|
|
```
|
|
|
|
Notes on the optional fields:
|
|
|
|
- `subnets` powers the IPAM panel and VLAN colouring (`vlanId` is optional per subnet).
|
|
- `racks` declares rack names and total units for the rack view; machines/devices opt in with a `rack` placement (`unit` is the bottom U, `heightU` defaults to 1). Items with the identical U range render side by side as shelf-mates.
|
|
- `cable` on a `connectedTo` records type/colour/length and is kept identical on both ends automatically.
|
|
- `notes` (machines and devices) and `macAddress` (ports and VMs) are free text.
|
|
|
|
### Project Structure
|
|
|
|
```text
|
|
OpenNetworkDiagram/
|
|
├── src/ # Svelte app source
|
|
├── src/lib/shared/ # Schema + persistence core (shared with server.mjs)
|
|
├── src/lib/config/vendorIconManifest.ts # Generated local icon catalog
|
|
├── static/data/network.json # Demo dataset (Netlify)
|
|
├── static/icons/vendor/ # Vendored icon assets (runtime-local)
|
|
├── data/network.json.example # Optional starter data template
|
|
├── third_party/ # Third-party provenance + licensing
|
|
├── Dockerfile # Docker build/runtime image
|
|
├── server.mjs # Node runtime server (static + API)
|
|
├── docker-compose.yml # Local compose example (build from repo)
|
|
├── netlify.toml # Netlify build config
|
|
└── .github/workflows/ # CI workflows
|
|
```
|
|
|
|
### CI/CD
|
|
|
|
- `docker.yml`: validates AMD64 and ARM64 Docker builds on pull requests.
|
|
- `release.yml`: semantic release on `main` and multi-platform Docker Hub publish for tagged releases.
|
|
- Published images support AMD64 and 64-bit ARM (including Raspberry Pi systems); Docker selects the matching variant automatically.
|
|
- Docker Hub image: [`jcreek23/open-network-diagram`](https://hub.docker.com/r/jcreek23/open-network-diagram)
|
|
|
|
## Contributing
|
|
|
|
1. Fork the repository.
|
|
2. Create a feature branch.
|
|
3. Before committing, run:
|
|
|
|
```bash
|
|
pnpm lint
|
|
pnpm test
|
|
pnpm check
|
|
pnpm run build:docker
|
|
pnpm run build:netlify
|
|
```
|
|
|
|
4. Commit your changes.
|
|
5. Push your branch.
|
|
6. Open a pull request.
|
|
|
|
## License
|
|
|
|
[GNU GPL v3](LICENSE)
|