# NeighborNet

NeighborNet is an operations toolkit for running a small community mesh-network ISP. It helps volunteer operators provision nodes, track links, monitor service health, publish a public status page, and manage subscriber access without requiring a full commercial WISP stack.

The project is designed for neighborhood networks using OpenWrt routers, 802.11s or BATMAN-adv mesh links, point-to-point backhaul, and one or more gateway nodes connected to upstream internet service.

## Features

- Node inventory with location, role, hardware model, firmware version, and owner contact
- Mesh topology discovery using LLDP, BATMAN-adv, and optional SNMP
- Gateway and backhaul monitoring with latency, packet loss, and throughput checks
- Subscriber records with service address, assigned VLAN, static lease, and status
- Configuration generation for OpenWrt, DHCP, DNS, firewall, and traffic shaping
- Outage detection with email, webhook, and Matrix notifications
- Public status page for maintenance windows and degraded service
- Simple billing export for external accounting tools
- Role-based admin access for coordinators, installers, and network operators

## Install

### Requirements

- Linux server or VM
- Docker and Docker Compose
- PostgreSQL 15+
- Redis 7+
- OpenWrt 23.05+ on managed mesh nodes

### Docker Compose

Clone the repository:

```sh
git clone https://github.com/example/neighbornet.git
cd neighbornet
```

Create an environment file:

```sh
cp .env.example .env
```

Start the stack:

```sh
docker compose up -d
```

Run database migrations:

```sh
docker compose exec app neighbornet migrate
```

Create the first admin user:

```sh
docker compose exec app neighbornet users create-admin
```

Open the dashboard:

```text
http://localhost:8080
```

## Usage

### Add a Gateway

```sh
neighbornet gateways add \
  --name main-library \
  --address 10.10.0.1 \
  --uplink eth0 \
  --mesh-interface wlan0-mesh
```

### Register a Mesh Node

```sh
neighbornet nodes add \
  --name oak-12-rooftop \
  --mac 02:11:22:33:44:55 \
  --model glinet-mt6000 \
  --zone north-loop
```

### Generate OpenWrt Config

```sh
neighbornet render openwrt --node oak-12-rooftop > oak-12-rooftop.conf
```

Apply the generated configuration on the node:

```sh
scp oak-12-rooftop.conf root@10.10.12.4:/tmp/neighbornet.conf
ssh root@10.10.12.4 "uci import < /tmp/neighbornet.conf && reload_config"
```

### Check Network Health

```sh
neighbornet status
```

Example output:

```text
Gateways:        2 online, 0 degraded
Mesh nodes:      38 online, 3 unreachable
Subscribers:     214 active
Average latency: 18 ms
Packet loss:     0.7%
Open incidents:  1
```

## Configuration

NeighborNet reads configuration from `config/neighbornet.yml` and environment variables. Environment variables override file values.

Example:

```yaml
site:
  name: "Eastside Community Mesh"
  timezone: "America/Toronto"
  public_status_url: "https://status.eastside-mesh.net"

server:
  bind: "0.0.0.0"
  port: 8080
  trusted_proxies:
    - "10.10.0.0/16"

database:
  url: "postgres://neighbornet:change-me@postgres:5432/neighbornet"

redis:
  url: "redis://redis:6379/0"

network:
  management_cidr: "10.10.0.0/16"
  subscriber_cidr: "100.64.0.0/10"
  default_dns:
    - "9.9.9.9"
    - "1.1.1.1"
  mesh:
    mode: "batman-adv"
    interface: "wlan0-mesh"
    mtu: 1532

gateways:
  default_bandwidth_mbps: 1000
  healthcheck_targets:
    - "1.1.1.1"
    - "9.9.9.9"

alerts:
  email:
    enabled: true
    from: "noc@eastside-mesh.net"
    smtp_url: "smtp://mail.example.net:587"
  webhook:
    enabled: false
    url: ""

status_page:
  enabled: true
  incident_retention_days: 180
```

Common environment variables:

| Variable | Description | Default |
| --- | --- | --- |
| `NEIGHBORNET_CONFIG` | Path to the YAML config file | `config/neighbornet.yml` |
| `DATABASE_URL` | PostgreSQL connection string | none |
| `REDIS_URL` | Redis connection string | none |
| `NEIGHBORNET_LOG_LEVEL` | Log level: `debug`, `info`, `warn`, `error` | `info` |
| `NEIGHBORNET_SECRET_KEY` | Secret used for sessions and signed tokens | none |
| `NEIGHBORNET_PUBLIC_URL` | External URL for dashboard links | none |

## Operational Notes

- Keep gateway nodes on battery backup where possible.
- Use separate management and subscriber VLANs.
- Do not expose router SSH directly to the public internet.
- Test generated OpenWrt configuration on one node before rolling it out fleet-wide.
- Document rooftop access, landlord contacts, and emergency shutoff procedures outside the application.

## License

NeighborNet is released under the MIT License.