Skip to content

Commit 5f6345e

Browse files
feat: add CI workflow, Dockerfile, Makefile, and documentation for netmon setup
1 parent 9c25d15 commit 5f6345e

File tree

6 files changed

+296
-0
lines changed

6 files changed

+296
-0
lines changed

.github/workflows/ci.yml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [master]
6+
pull_request:
7+
branches: [master]
8+
9+
jobs:
10+
build:
11+
name: Build & Vet
12+
runs-on: ubuntu-latest
13+
14+
steps:
15+
- uses: actions/checkout@v4
16+
17+
- name: Set up Go
18+
uses: actions/setup-go@v5
19+
with:
20+
go-version-file: go.mod
21+
22+
- name: Install C compiler (required for CGO/sqlite3)
23+
run: sudo apt-get install -y gcc
24+
25+
- name: Vet
26+
run: go vet ./...
27+
28+
- name: Build
29+
run: CGO_ENABLED=1 go build -o netmon ./cmd/netmon

CONTRIBUTING.md

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
# Contributing to netmon
2+
3+
## Prerequisites
4+
5+
- **Go 1.21+**[install](https://go.dev/dl/)
6+
- **C compiler** — required by the SQLite driver (`go-sqlite3` uses CGO)
7+
- macOS: `xcode-select --install`
8+
- Linux: `sudo apt install gcc` / `sudo dnf install gcc`
9+
- Windows: [TDM-GCC](https://jmeubank.github.io/tdm-gcc/) or WSL
10+
11+
## Run locally
12+
13+
```bash
14+
git clone https://github.com/decoded-cipher/netmon.git
15+
cd netmon
16+
make run # go run ./cmd/netmon
17+
# or
18+
make build && ./netmon
19+
```
20+
21+
Dashboard: **http://localhost:8080**
22+
23+
## Project structure
24+
25+
```
26+
cmd/netmon/ main.go — entry point, HTTP server setup
27+
internal/
28+
monitor/ Background workers: ping (60s) and speed test (30m)
29+
monitor.go Monitor struct, worker goroutines, ping cycle orchestration
30+
ping.go runPing, cross-platform output parsing, DNS measurement
31+
speed.go measureDownload, measureUpload
32+
network/ Cross-platform network identity detection
33+
network.go Detect(), DefaultGateway(), SSID helpers per OS
34+
server/ HTTP layer
35+
handlers.go GET /api/data handler, DashboardData response type
36+
store/ SQLite persistence
37+
store.go Schema, migrations, CRUD for all 4 tables
38+
web/
39+
index.html Single-page dashboard (TailwindCSS + ApexCharts)
40+
web.go embed.FS — bundles index.html into the binary
41+
```
42+
43+
## Making changes
44+
45+
- **Backend changes** — edit files under `internal/`. Run `make vet` and `make build` to verify.
46+
- **Dashboard changes** — edit `web/index.html`. Rebuild and refresh the browser.
47+
- **Adding a new metric** — add a column to the `measurements` table in `store.go → migrate()`, update `Measurement` struct, `SaveMeasurement`, and `GetHistory`; wire it through `monitor.go → runPingCycle()`; render it in `index.html`.
48+
49+
## Pull requests
50+
51+
1. Fork the repo and create a branch from `master`
52+
2. Keep changes focused — one logical change per PR
53+
3. Run `make vet` before pushing
54+
4. Describe *why* the change is needed in the PR description, not just what changed
55+
56+
## Reporting issues
57+
58+
Open an issue with:
59+
- OS and Go version (`go version`)
60+
- Steps to reproduce
61+
- Relevant log output (the structured log lines from the terminal)

Dockerfile

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# --- Build stage ---
2+
FROM golang:1.25-alpine AS builder
3+
4+
# gcc + musl-dev for CGO (go-sqlite3); sqlite-dev for headers
5+
RUN apk add --no-cache gcc musl-dev sqlite-dev
6+
7+
WORKDIR /app
8+
9+
COPY go.mod go.sum ./
10+
RUN go mod download
11+
12+
COPY . .
13+
14+
RUN CGO_ENABLED=1 GOOS=linux go build -ldflags="-s -w" -o netmon ./cmd/netmon
15+
16+
# --- Runtime stage ---
17+
FROM alpine:3.21
18+
19+
# ca-certificates for HTTPS speed tests; sqlite-libs for the CGO runtime
20+
RUN apk add --no-cache ca-certificates sqlite-libs
21+
22+
# Store database in /data so it can be mounted as a volume
23+
WORKDIR /data
24+
25+
COPY --from=builder /app/netmon /usr/local/bin/netmon
26+
27+
EXPOSE 8080
28+
VOLUME ["/data"]
29+
30+
CMD ["netmon"]

Makefile

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
BINARY := netmon
2+
CMD := ./cmd/netmon
3+
IMAGE := netmon
4+
5+
.PHONY: build run clean vet docker docker-run
6+
7+
build:
8+
CGO_ENABLED=1 go build -o $(BINARY) $(CMD)
9+
10+
run:
11+
go run $(CMD)
12+
13+
clean:
14+
rm -f $(BINARY) netmon.db netmon.db-shm netmon.db-wal
15+
16+
vet:
17+
go vet ./...
18+
19+
docker:
20+
docker build -t $(IMAGE) .
21+
22+
docker-run: docker
23+
docker run --rm -p 8080:8080 --network host -v netmon-data:/data $(IMAGE)

README.md

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
# netmon
2+
3+
A lightweight, self-hosted network monitoring dashboard. Tracks latency, jitter, packet loss, DNS resolution times, and bandwidth — displayed in a live web UI with no external services required.
4+
5+
![Build](https://github.com/decoded-cipher/netmon/actions/workflows/ci.yml/badge.svg)
6+
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
7+
[![Go](https://img.shields.io/badge/Go-1.21+-00ADD8?logo=go)](https://golang.org)
8+
9+
---
10+
11+
## Features
12+
13+
- **Live dashboard** — auto-refreshing charts for latency, throughput, packet loss, jitter, and DNS
14+
- **Network change detection** — automatically detects Wi-Fi/network switches and tags measurements per network; works on macOS, Linux, Windows, Docker, and Raspberry Pi
15+
- **Self-contained binary** — single executable with embedded UI, no config files needed
16+
- **Lightweight** — pings every 60s, speed test every 30min (1 MB); negligible network overhead
17+
- **SQLite storage** — no database server; data persists in a single file
18+
- **Cross-platform** — runs on Linux (x86, ARM/Pi), macOS, Windows, and Docker
19+
20+
---
21+
22+
## Quick Start
23+
24+
### Docker (recommended)
25+
26+
```bash
27+
docker run -d \
28+
--name netmon \
29+
--network host \
30+
-v netmon-data:/data \
31+
ghcr.io/decoded-cipher/netmon:latest
32+
```
33+
34+
Or with Docker Compose:
35+
36+
```bash
37+
docker compose up -d
38+
```
39+
40+
Then open **http://localhost:8080**.
41+
42+
### Build from source
43+
44+
Requires Go 1.21+ and a C compiler (`gcc`) for the SQLite driver.
45+
46+
```bash
47+
git clone https://github.com/decoded-cipher/netmon.git
48+
cd netmon
49+
make build
50+
./netmon
51+
```
52+
53+
### Makefile targets
54+
55+
```
56+
make build # compile binary → ./netmon
57+
make run # go run ./cmd/netmon (no build step)
58+
make clean # remove binary and local database
59+
make vet # run go vet on all packages
60+
make docker # build Docker image
61+
make docker-run # build + run Docker container
62+
```
63+
64+
---
65+
66+
## Configuration
67+
68+
All defaults live in `internal/monitor/monitor.go → DefaultConfig()`. There is no config file — rebuild or set env vars (support planned).
69+
70+
| Setting | Default | Description |
71+
|---------|---------|-------------|
72+
| Ping targets | `google.com`, `cloudflare.com` | Hosts to measure latency/loss against |
73+
| DNS targets | `google.com`, `cloudflare.com` | Hosts to measure DNS resolution time |
74+
| Ping interval | `60s` | How often to run a ping cycle |
75+
| Speed test interval | `30m` | How often to test download/upload |
76+
| Speed test size | `1 MB` | Payload size (kept small to avoid hogging the link) |
77+
| HTTP port | `:8080` | Dashboard address |
78+
79+
---
80+
81+
## Architecture
82+
83+
```
84+
cmd/netmon/ Entry point — wires packages, starts HTTP server
85+
internal/
86+
monitor/ Ping + speed workers (concurrent, 60s / 30m intervals)
87+
network/ Cross-platform gateway detection and SSID identification
88+
server/ HTTP handler, JSON API response types
89+
store/ SQLite layer — schema, UPSERT patterns, aggregation queries
90+
web/
91+
index.html Single-page dashboard (TailwindCSS + ApexCharts, embedded at build time)
92+
```
93+
94+
**Data flow:**
95+
1. `pingWorker` pings all targets concurrently, resolves DNS, detects network — saves a `Measurement` row every 60s
96+
2. `speedWorker` downloads/uploads 1 MB to Cloudflare every 30 min — updates latest bandwidth values
97+
3. Dashboard polls `GET /api/data` every 30s and renders charts client-side
98+
99+
---
100+
101+
## Platforms
102+
103+
| Platform | Tested | Notes |
104+
|----------|--------|-------|
105+
| macOS (Apple Silicon / Intel) | Yes | Native binary |
106+
| Linux x86-64 | Yes | Includes Docker |
107+
| Linux ARM (Raspberry Pi) | Yes | Build with `GOARCH=arm64` |
108+
| Windows | Partial | Ping parsing works; SSID detection via `netsh` |
109+
| Docker | Yes | See `Dockerfile` and `docker-compose.yml` |
110+
111+
### Raspberry Pi
112+
113+
```bash
114+
GOOS=linux GOARCH=arm64 CGO_ENABLED=1 CC=aarch64-linux-gnu-gcc \
115+
go build -o netmon ./cmd/netmon
116+
```
117+
118+
---
119+
120+
## Requirements
121+
122+
- **Go 1.21+** for building from source
123+
- **CGO enabled** (`CGO_ENABLED=1`) — required by the SQLite driver (`go-sqlite3`)
124+
- A C compiler (`gcc` / `musl-gcc` / `clang`) at build time; not needed at runtime
125+
- `ping` available in `PATH` at runtime (standard on all platforms)
126+
127+
---
128+
129+
## Contributing
130+
131+
See [CONTRIBUTING.md](CONTRIBUTING.md).
132+
133+
---
134+
135+
## License
136+
137+
[MIT](LICENSE)

docker-compose.yml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
services:
2+
netmon:
3+
build: .
4+
image: netmon
5+
container_name: netmon
6+
ports:
7+
- "8080:8080"
8+
volumes:
9+
- netmon-data:/data
10+
restart: unless-stopped
11+
# host network gives the monitor access to the local gateway for accurate latency
12+
# Remove if not needed or on Windows (host networking not supported there)
13+
network_mode: host
14+
15+
volumes:
16+
netmon-data:

0 commit comments

Comments
 (0)