Real-time dashboard for monitoring Syncthing relay nodes
- Go 50.3%
- TypeScript 46.1%
- Dockerfile 1.1%
- JavaScript 1.1%
- Makefile 0.8%
- Other 0.6%
Track cumulative bytes proxied that persists across relay process restarts by detecting start time changes and snapshotting previous bytesProxied into an accumulated total stored in a new relay_lifetime SQLite table. - Add StartTime field to RelayRawStatus model - Add LifetimeBytesProxied to RelayStatus (backend + frontend) - Create relay_lifetime table with accumulated_bytes, last_start_time, last_bytes_proxied - Detect restarts in collector when startTime changes - Add "Lifetime Proxied" summary card and sortable "Lifetime" column in relay table Co-authored-by: CommandCodeBot <noreply@commandcode.ai> |
||
|---|---|---|
| cmd/server | ||
| frontend | ||
| internal | ||
| .dockerignore | ||
| .gitignore | ||
| config.example.yaml | ||
| docker-compose.yml | ||
| Dockerfile | ||
| embed.go | ||
| go.mod | ||
| go.sum | ||
| Makefile | ||
| README.md | ||
Syncthing Relay Stats Dashboard
A real-time dashboard for monitoring your Syncthing relay nodes. Displays live stats including active sessions, connections, data proxied, throughput, and relay locations on a world map.
Architecture
- Backend: Go (single binary, embeds the React frontend)
- Frontend: React + TypeScript + Tailwind CSS + Recharts + react-simple-maps
- Real-time: WebSocket for live updates
- Storage: SQLite for persistent history
- GeoIP: MaxMind GeoLite2 (with free API fallback)
Quick Start
1. Configure your relays
cp config.example.yaml config.yaml
# Edit config.yaml with your relay URLs
Your relay status endpoints should be accessible at http://<relay-ip>:22070/status.
2. Build & Run
make build
make run
Or for development with hot-reload:
make dev
3. Open Dashboard
Navigate to http://localhost:8080
Docker Deployment
Using Docker Compose (Recommended)
# 1. Configure your relays
cp config.example.yaml config.yaml
# Edit config.yaml with your relay URLs
# 2. Build and start
docker compose up -d
# 3. View logs
docker compose logs -f
The dashboard will be available at http://localhost:8080.
Using Docker directly
# Build the image
docker build -t syncthing-relay-stats .
# Run with config mounted
docker run -d \
--name syncthing-relay-stats \
-p 8080:8080 \
-v $(pwd)/config.yaml:/app/config.yaml:ro \
syncthing-relay-stats
Container Details
- Base: Alpine Linux (minimal footprint)
- Port: 8080
- Config: Mount your
config.yamlto/app/config.yaml - Data: Persisted in
/app/datavolume (SQLite database) - Health check: Built-in at
/healthendpoint
Configuration
See config.example.yaml for all options:
| Option | Default | Description |
|---|---|---|
server.listen |
:8080 |
HTTP listen address |
server.dev_mode |
false |
Proxy to Vite dev server |
relays[].status_url |
— | Status endpoint URL (http://ip:22070/status) |
relays[].name |
— | Human-friendly label |
polling.interval |
5s |
How often to fetch stats |
polling.timeout |
3s |
HTTP timeout per relay |
history.max_points |
720 |
Max history points per relay |
geoip.database_path |
./GeoLite2-City.mmdb |
MaxMind database path |
geoip.fallback_api |
true |
Use ip-api.com if DB missing |
database.path |
./relay-stats.db |
SQLite database path |
GeoIP Setup
For the world map, download the free MaxMind GeoLite2-City database:
- Create a free account at maxmind.com
- Download
GeoLite2-City.mmdb - Place it in the project root
If the database isn't available, the app falls back to ip-api.com (rate-limited to 45 req/min).
API Endpoints
| Method | Path | Description |
|---|---|---|
GET |
/api/relays |
Current status of all relays |
GET |
/api/relays/{id}/history |
Time-series history for a relay |
GET |
/ws |
WebSocket for real-time updates |
GET |
/health |
Health check |
Project Structure
├── cmd/server/main.go # Entry point
├── internal/
│ ├── api/ # HTTP router & WebSocket handler
│ ├── collector/ # Background relay polling
│ ├── config/ # YAML config loading
│ ├── geoip/ # MaxMind + fallback IP lookup
│ ├── hub/ # WebSocket broadcast hub
│ ├── models/ # Shared data types
│ └── storage/ # SQLite persistence
├── frontend/ # React app (Vite + TypeScript)
│ └── src/
│ ├── components/ # UI components
│ ├── hooks/ # WebSocket + Zustand store
│ ├── types/ # TypeScript interfaces
│ └── utils/ # Formatting helpers
├── embed.go # go:embed for frontend assets
├── config.example.yaml # Example configuration
└── Makefile # Build commands