# OpenMesh ISP

OpenMesh ISP is a community-operated mesh network that provides affordable, resilient internet access using neighborhood relay nodes and shared gateway connections.

Each node forwards traffic for nearby peers, allowing the network to grow organically and continue serving local resources when an upstream gateway is unavailable. The project includes node provisioning, encrypted mesh routing, gateway management, monitoring, and a lightweight subscriber portal.

> **Status:** OpenMesh ISP is under active development. Test deployments should use dedicated hardware and isolated network segments.

## Features

- Automatic peer discovery and encrypted mesh links
- Multi-gateway routing with health checks and failover
- Bandwidth limits and service plans per subscriber
- Captive portal for registration and account management
- Local DNS and access to community-hosted services
- Node inventory, topology, and link-quality monitoring
- Prometheus metrics and structured system logs
- Configuration through YAML files and environment variables
- Support for common OpenWrt-compatible routers
- Rolling configuration updates with automatic rollback
- Optional IPv6 prefix delegation
- No dependency on a central controller for local mesh traffic

## Architecture

An OpenMesh deployment consists of three main components:

- **Nodes** are routers installed in homes, businesses, or public spaces. They create wireless or wired links with neighboring nodes.
- **Gateways** provide upstream internet connectivity and announce default routes into the mesh.
- **Controller** manages provisioning, subscriber policies, monitoring, and configuration distribution. Mesh routing continues if the controller is temporarily unavailable.

OpenMesh uses WireGuard for encrypted node-to-node tunnels and Babel for dynamic route selection. The controller exposes an HTTP API consumed by the node agent and administration portal.

## Requirements

### Controller

- Linux server or virtual machine
- Docker Engine 25 or later
- Docker Compose v2
- 2 CPU cores
- 4 GB RAM
- 20 GB available storage
- A domain name with HTTPS
- PostgreSQL 15 or later when not using the bundled database

### Mesh nodes

- OpenWrt 23.05 or later
- 16 MB flash and 128 MB RAM minimum
- At least one supported wireless or Ethernet interface
- WireGuard and Babel packages
- Accurate system time through NTP

For production deployments, use separate interfaces for client access and mesh backhaul whenever possible.

## Installation

Clone the repository and create a local configuration file:

```sh
git clone https://github.com/openmesh-isp/openmesh.git
cd openmesh
cp .env.example .env
```

Generate application secrets:

```sh
./scripts/generate-secrets
```

Edit `.env` and set the public controller URL, database credentials, and initial administrator address:

```dotenv
OPENMESH_PUBLIC_URL=https://mesh.example.org
OPENMESH_ADMIN_EMAIL=admin@example.org
POSTGRES_PASSWORD=replace-with-a-strong-password
```

Start the controller services:

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

Run the database migrations and create the initial administrator:

```sh
docker compose exec controller openmesh migrate
docker compose exec controller openmesh admin create \
  --email admin@example.org
```

Verify the installation:

```sh
curl https://mesh.example.org/api/v1/health
```

A healthy installation returns:

```json
{"status":"ok"}
```

The administration portal is available at the URL configured in `OPENMESH_PUBLIC_URL`.

## Node Installation

Create a provisioning token from the administration portal under **Network → Nodes → Add node**, or with the CLI:

```sh
docker compose exec controller openmesh node token create \
  --name roof-node-07 \
  --site west-market
```

On an OpenWrt node, install the required packages:

```sh
opkg update
opkg install ca-bundle curl wireguard-tools babeld
```

Download and run the node installer:

```sh
curl -fsSL https://mesh.example.org/install/node.sh | sh
```

Provision the node using the generated token:

```sh
openmesh-node enroll \
  --controller https://mesh.example.org \
  --token om_enroll_REPLACE_ME
```

After enrollment, the node downloads its signed configuration, creates mesh interfaces, and begins advertising routes. It should appear online in the administration portal within two minutes.

Provisioning tokens are single-use and expire after 30 minutes by default.

## Usage

### Check network status

```sh
docker compose exec controller openmesh status
```

### List registered nodes

```sh
docker compose exec controller openmesh node list
```

### Inspect a node

```sh
docker compose exec controller openmesh node show roof-node-07
```

### Mark a node as an internet gateway

```sh
docker compose exec controller openmesh node update roof-node-07 \
  --gateway \
  --uplink-capacity 500mbit
```

### Create a subscriber plan

```sh
docker compose exec controller openmesh plan create community-25 \
  --download 25mbit \
  --upload 10mbit \
  --monthly-quota unlimited
```

### Register a subscriber

```sh
docker compose exec controller openmesh subscriber create \
  --name "Jordan Lee" \
  --email jordan@example.org \
  --plan community-25
```

### View mesh routes on a node

```sh
ssh root@192.0.2.10
openmesh-node routes
```

### Follow controller logs

```sh
docker compose logs -f controller
```

## Configuration

Controller configuration is loaded from `config/openmesh.yml`. Environment variables prefixed with `OPENMESH_` override corresponding file values.

Example configuration:

```yaml
server:
  public_url: https://mesh.example.org
  listen_address: 0.0.0.0
  port: 8080
  trusted_proxies:
    - 172.18.0.0/16

network:
  name: West Market Community Mesh
  domain: mesh.example.org
  ipv4_pool: 10.84.0.0/16
  ipv6_prefix: fd42:84::/48
  mesh_mtu: 1380

routing:
  protocol: babel
  gateway_failover_seconds: 30
  prefer_wired_links: true
  minimum_link_quality: 0.35

wireguard:
  listen_port: 51820
  key_rotation_days: 90
  persistent_keepalive_seconds: 25

dns:
  upstream:
    - 1.1.1.1
    - 9.9.9.9
  local_zone: community.mesh
  cache_size: 10000

subscribers:
  default_plan: community-25
  session_timeout: 24h
  allow_self_registration: false

telemetry:
  enabled: true
  prometheus_path: /metrics
  retention_days: 30

updates:
  channel: stable
  maintenance_window: "Sun 03:00-05:00"
  automatic_rollback: true
```

### Environment variables

Common environment variables include:

| Variable | Description | Default |
| --- | --- | --- |
| `OPENMESH_PUBLIC_URL` | Public HTTPS URL of the controller | Required |
| `OPENMESH_CONFIG` | Path to the YAML configuration file | `/etc/openmesh/openmesh.yml` |
| `OPENMESH_DATABASE_URL` | PostgreSQL connection string | Bundled database |
| `OPENMESH_LOG_LEVEL` | Logging level | `info` |
| `OPENMESH_ADMIN_EMAIL` | Initial administrator email | Required on first run |
| `OPENMESH_METRICS_ENABLED` | Enable Prometheus metrics | `true` |
| `OPENMESH_ENROLLMENT_TTL` | Node token lifetime | `30m` |

Restart the controller after changing configuration:

```sh
docker compose restart controller
```

Validate configuration before applying it:

```sh
docker compose exec controller openmesh config validate
```

## Backups

Back up the database and controller secrets regularly:

```sh
./scripts/backup ./backups
```

Restore from a backup:

```sh
./scripts/restore ./backups/openmesh-2026-07-15.tar.zst
```

Backups contain private network keys and subscriber data. Encrypt them at rest and restrict access.

## Monitoring

Prometheus metrics are exposed at `/metrics` when telemetry is enabled. Recommended alerts include:

- No active gateway for more than 60 seconds
- Node offline for more than 10 minutes
- Packet loss above 20% on a backbone link
- Gateway utilization above 85%
- Configuration rollout failure
- WireGuard key rotation overdue

The administration portal provides a topology view, current gateway state, client counts, link quality, and recent node events.

## Security

- Always expose the controller through HTTPS.
- Store enrollment tokens and backups securely.
- Use separate VLANs for management, mesh backhaul, and subscriber traffic.
- Do not expose node management interfaces to subscriber networks.
- Review gateway operators and physical node locations before granting administrative access.
- Keep OpenWrt packages and controller images current.
- Obtain informed consent before collecting traffic or subscriber telemetry.
- Follow applicable telecommunications, privacy, and lawful-access requirements in your jurisdiction.

OpenMesh encrypts traffic between mesh nodes. It does not replace end-to-end encryption between subscribers and internet services.

## Development

Start the development stack:

```sh
docker compose -f compose.dev.yml up
```

Run the test suite:

```sh
make test
```

Run formatting and static analysis:

```sh
make lint
```

See `CONTRIBUTING.md` for development setup, code style, and the proposal process.

## Community Operations

OpenMesh is designed for networks governed by the communities they serve. Before deployment, document:

- Who owns and maintains each node
- How gateway costs are shared
- Service expectations and outage procedures
- Privacy and logging policies
- The process for adding or removing operators
- How surplus funds are reinvested
- How network changes are proposed and approved

Technical redundancy works best when it is paired with clear, accountable community governance.

## License

OpenMesh ISP is licensed under the GNU Affero General Public License v3.0. See `LICENSE` for details.