A distributed system monitoring tool that tracks pending package updates across your home network. The system consists of client that run on each machine and a server that aggregates and displays update information via a web interface.
This project monitors system updates across multiple machines in your network:
- Client: Runs on each machine (macOS, Linux) and periodically checks for pending updates
- Server: Aggregates update information from all clients and provides a web dashboard
- Communication: Uses NATS for messaging between clients and server
- Linux: apt (Debian/Ubuntu), dnf (Fedora/RHEL), yum (older RHEL/CentOS), nixos-rebuild (NixOS)
- macOS: Homebrew (brew)
- macOS (darwin)
- Linux (ARM, ARM64, x86_64)
- Clients connect to a NATS server and publish system information including pending updates every minute
- Server can run an embedded NATS server (default) or connect to an external NATS instance
- Storage uses BoltDB to persist system state
- Web Interface provides a real-time dashboard to view all systems and their update status
make buildmake client # Build client only
make server # Build server onlymake linux # Build Linux binaries for all architectures (ARM, ARM64, AMD64)
make linux-all # Build both client and server for all Linux architecturesmake help # Show all available make targets
make clean # Clean build artifacts
make test # Run tests
make fmt # Format codeThe server can be configured via environment variables and CLI flags:
Environment Variables:
MUC_NATS_URL: NATS server URL (default:embedded- runs embedded NATS server)MUC_NATS_PORT: Port for embedded NATS server (default:4222)MUC_DB_PATH: Path to BoltDB database file (default:systems.db)MUC_HTTP_PORT: Web server port (default:8080)
CLI Flags:
--dev: Enable dev mode (debug logging enabled)--json: Output logs in JSON format (default: text format)
Example:
export MUC_HTTP_PORT=3000
export MUC_DB_PATH=/var/lib/muc/systems.db
./server --devThe client supports automatic server discovery using multiple methods, tried in order:
- Environment Variable Override:
MUC_NATS_URL(highest priority) - DNS SRV Records: Looks for
_muc-server._tcp,_muc-nats._tcp, or_nats._tcpservice records (tried in order) - Consul Service Discovery: Queries Consul for
nats,muc-nats, ormuc-serverservices (tried in order, most generic first) - Environment Variable Fallback:
MUC_NATS_SERVER_IPwith default port 4222 - Hardcoded Default:
192.168.1.157:4222(last resort)
Environment Variables:
MUC_NATS_URL: NATS server URL (e.g.,nats://192.168.1.157:4222) - explicit override, highest priorityMUC_NATS_SERVER_IP: NATS server IP address (fallback if discovery fails)MUC_NATS_PORT: NATS server port (default:4222)MUC_NATS_DISCOVERY_DOMAIN: Domain for DNS SRV lookup (default: tries hostname domain,local,lan,home.arpa)MUC_NATS_DISCOVERY_SERVICE: Service name for DNS SRV lookup (default: triesmuc-server,muc-nats,natsin order)MUC_CONSUL_HTTP_ADDR: Consul API address (default:localhost:8500)MUC_NATS_CONSUL_SERVICE: Consul service name to query (default: triesnats,muc-nats,muc-serverin order)
CLI Flags:
--dev: Enable dev mode (debug logging enabled)--json: Output logs in JSON format (default: text format)
Examples:
Explicit configuration:
export MUC_NATS_URL=nats://192.168.1.157:4222
./client --devDNS SRV record discovery (requires DNS configuration):
# Configure DNS SRV records (tried in order):
# - _muc-server._tcp.example.com (most specific, tried first)
# - _muc-nats._tcp.example.com
# - _nats._tcp.example.com (generic, tried last)
# Example: _muc-server._tcp.example.com -> server.example.com:4222
export MUC_NATS_DISCOVERY_DOMAIN=example.com
./client
# Or specify a specific service name:
export MUC_NATS_DISCOVERY_DOMAIN=example.com
export MUC_NATS_DISCOVERY_SERVICE=muc-server
./clientConsul service discovery:
# Ensure Consul is running and service is registered
# Service names tried in order: nats, muc-nats, muc-server
export MUC_CONSUL_HTTP_ADDR=consul.example.com:8500
export MUC_NATS_CONSUL_SERVICE=nats # Optional: specify a specific service name
./clientAutomatic discovery (no configuration needed if DNS/Consul is set up):
./client # Will try DNS SRV, then Consul, then fallback to defaultThe application uses structured logging with log/slog:
- Default: Info level, text format (syslog-like) on stdout
- Dev Mode (
--dev): Debug level enabled, shows detailed debug information - JSON Output (
--json): Outputs logs in JSON format for log aggregation systems
Examples:
# Default: Info level, text format
./server
# Dev mode: Debug level, text format
./server --dev
# JSON output
./server --json
# Dev mode with JSON output
./server --dev --jsonThe client can be run as a systemd service. See client/contrib/systemd.unit for an example systemd unit file.
-
Start the server:
cd server make run # Or with dev mode for debug logging: ./server --dev
The web interface will be available at
http://localhost:8080(or your configured MUC_HTTP_PORT). -
Run clients on each machine:
cd client ./client # Or with dev mode for debug logging: ./client --dev
The client will automatically connect to the NATS server and start reporting system information.
-
View the dashboard: Open your browser to the server's HTTP port to see all systems and their update status.
The web dashboard provides:
- Overview of all monitored systems
- System details (hostname, OS, architecture, IP address)
- Pending update lists with package names and versions
- Sortable columns
- Expandable rows to view detailed update information
- Last seen timestamps
Instead of using this tool, you could run a cron job or systemd timer to auto-update. However, this approach has drawbacks:
- Sometimes reboots are required after updates
- Services (like Docker) may crash during updates
- You lose visibility and control over when updates are applied
This tool gives you visibility into pending updates across all your systems, allowing you to plan updates appropriately.
This project is licensed under the Apache License. See the LICENSE file for details.