How Opservo works
Opservo installs a tiny read-only agent on your server, and every ~60 seconds it collects plain facts about the machine. Those facts are scored into a single 0–100 Health Score you can always trace back to the exact reason. This guide explains what we measure, how we measure it, and what every number means.
What Opservo watches for you
- Performance — is the server keeping up, or are things about to feel slow?
- Storage — will the disks run out of space, and are the drives themselves healthy?
- Security — is the server locked down, and is anyone trying to break in?
- Reliability — is anything crashing or restarting behind the scenes?
- Maintenance — are updates, restarts and website certificates being kept up?
- Network — can the server actually reach the internet properly?
- Configuration — are the small settings right that cause big, confusing problems when wrong?
When something needs attention, Opservo tells you what it means and how to fix it in plain English — you never need to interpret a chart or open a terminal. The rest of this page is the detail, for whenever you want it.
The Health Score — how the number is built
The score is deterministic (the same facts always give the same number — no hidden AI, no time-of-day noise) and explainable (every point lost traces to a named rule). It’s built in four layers:
- Collectors gather facts (CPU %, is the firewall on, is a disk 96% full…). Facts only — never opinions.
- Rules turn a fact into a penalty when it crosses a threshold (e.g. disk >95% → −20).
- Each category starts at 100 and subtracts its penalties:
score = 100 − Σ penalties(floored at 0). - The overall score is a fixed-weight blend of the seven categories.
Category weights
| Performance | 25% |
| Storage | 15% |
| Security | 20% |
| Reliability | 15% |
| Maintenance | 10% |
| Network | 10% |
| Configuration | 5% |
Rating bands
| 100 | Perfect |
| 95–99 | Excellent |
| 90–94 | Very Good |
| 80–89 | Good |
| 70–79 | Fair |
| 60–69 | Needs Attention |
| 40–59 | Poor |
| 0–39 | Critical |
Example. A server with the firewall off (−20) and root SSH login allowed (−30) has a Security category of 100 − 50 = 50. At 20% weight that pulls the overall score down by 10 points — and the dashboard names exactly those two reasons.
Confidence, and why some checks read “n/a”
Every finding carries a confidence so you can trust it proportionally:
- Definitive — a hard fact (“firewall is disabled”, “disk is 96% full”).
- Likely — a strong but single-sample or derived signal (one CPU reading at 97%).
- Heuristic — a pattern-based guess (“suspicious process”), shown as “worth checking”.
A check shows “n/a” when the agent genuinely can’t measure it on this machine — a probe that needs a physical disk on a cloud VM, or a config file the agent can’t read because it isn’t running as root. Missing data never lowers your score — that category simply scores from the checks it can see, and the panel shows a coverage indicator so it’s honest, not a false “all-good”. Hover any “n/a” to see exactly why.
Every check, what it means, and how we measure it
These are grouped by category. Each check shows what it means for your server; the exact technical source the agent reads lives behind “Technical details” at the bottom of each category — nothing is changed on your server unless you explicitly ask.
Performance
weight 25%Is the server keeping up with its work right now — CPU, memory, and the pressure signals that precede a slowdown?
| Check | What it means | Penalty |
|---|---|---|
| CPU utilization | The processor is busy (≥90%) or saturated (≥95%). | −8 / −15 |
| Load vs cores | More work is queued than the CPUs can serve (load ≥ 2× cores). | −10 |
| IO wait | The CPU is stalling waiting on disk (>15%) — a storage bottleneck. | −10 |
| CPU steal | The hypervisor is taking cycles from this VM (>10%) — a noisy host. | −8 |
| Memory usage | RAM is under pressure (≥85%) or nearly exhausted (≥95%, OOM risk). | −8 / −15 |
| Swap usage | The server is spilling to disk (>25%) or thrashing (>50%). | −5 / −10 |
| Memory-stall (PSI) | Real time processes spent blocked waiting for memory (>10%). | −8 |
| CPU throttling | A cgroup is being CPU-capped (>5% of periods) — a container hitting its limit. | −8 |
| Disk latency | Each disk I/O is slow (>50 ms) on the busiest device. | −8 |
| File descriptors | Open files are near the system limit (>80%). | −6 |
Technical details — how each performance check is measured ▸
| CPU utilization | Sampled from the /proc/stat CPU counters between heartbeats. |
| Load vs cores | Kernel 1-minute load average ÷ CPU core count. |
| IO wait | “iowait” slice of the /proc/stat CPU delta. |
| CPU steal | “steal” slice of the /proc/stat CPU delta. |
| Memory usage | /proc/meminfo (used ÷ total). |
| Swap usage | /proc/meminfo swap used ÷ total. |
| Memory-stall (PSI) | Linux Pressure-Stall Info: /proc/pressure/memory. |
| CPU throttling | cgroup cpu.stat throttled-periods delta. |
| Disk latency | /proc/diskstats service-time delta. |
| File descriptors | /proc/sys/fs/file-nr. |
Storage
weight 15%Will the disks last — space, inodes, and the physical health of the drives themselves?
| Check | What it means | Penalty |
|---|---|---|
| Disk usage | A filesystem is nearly full (>90%) or critical (>95%). | −10 / −20 |
| Projected full | A mount is trending toward 100% within days. | −10 |
| Min free space | Very little absolute space remains on a data mount (<2 GiB). | −8 |
| Inode usage | A filesystem is running out of inodes (>90%) — can’t create files even with space free. | −15 |
| SMART health | The drive’s own self-assessment is WARN or FAIL. | −15 / −35 |
| SSD life | The SSD’s remaining write life is low (<20%). | −10 |
| Drive temperature | A drive is running hot (>60 °C). | −8 |
| RAID/array degraded | A software RAID/ZFS/LVM array lost redundancy. | −25 |
| Mount failed | A configured mount didn’t come up. | −20 |
| Read-only filesystem | A real filesystem is mounted read-only. | −20 |
| Deleted-open files | Space is held by deleted-but-still-open files (>2 GiB) — space that df can’t see. | −8 |
| Disk saturation | The busiest disk is doing I/O most of the time (>90% util). | −8 |
Technical details — how each storage check is measured ▸
| Disk usage | statfs on each real mount (like df). |
| Projected full | Linear projection over 48h of usage history. |
| Min free space | Smallest free-bytes across data mounts ≥10 GiB. |
| Inode usage | statfs inode counts (df -i). |
| SMART health | smartctl -H (needs smartmontools; physical disks only). |
| SSD life | smartctl wear-level attribute. |
| Drive temperature | smartctl temperature attribute. |
| RAID/array degraded | mdadm / zpool status. |
| Mount failed | systemd .mount unit in failed state. |
| Read-only filesystem | /proc/mounts flags. |
| Deleted-open files | Scan of /proc/*/fd for deleted inodes. |
| Disk saturation | /proc/diskstats busy-time delta. |
Security
weight 20%How locked-down the server is — no configuration required. Every finding is also actionable from the Security tab.
| Check | What it means | Penalty |
|---|---|---|
| Firewall | No host firewall is active, so every open port is reachable. | −20 |
| Root SSH login | SSH allows logging in directly as root. | −30 |
| Password authentication | SSH accepts passwords (brute-forceable). | −15 |
| Empty passwords | SSH permits accounts with no password. | −40 |
| Weak ciphers | SSH offers legacy/weak ciphers or MACs. | −10 |
| Failed SSH logins | Active brute-force pressure (>50/hr, or heavy >200/hr). | −10 / −25 |
| Brute-force guard | Brute-force is happening but no fail2ban/sshguard is running. | −10 |
| Security updates | Security (CVE) patches are pending. | −15 |
| Auto security updates | The OS won’t install security patches on its own. | −5 |
| Exposed database ports | A database is reachable from the public internet. | −15 ea (cap −30) |
| Public listening surface | Other services are bound to all interfaces beyond web/SSH/DB. | −2 ea (cap −8) |
| Passwordless sudo | A sudoers rule grants root with no password (NOPASSWD). | −10 |
| Suspicious processes | A process matches known-malicious patterns (heuristic). | −25 (low confidence) |
Technical details — how each security check is measured ▸
| Firewall | ufw status / iptables INPUT policy. |
| Root SSH login | PermitRootLogin in sshd_config. |
| Password authentication | PasswordAuthentication in sshd_config. |
| Empty passwords | PermitEmptyPasswords in sshd_config. |
| Weak ciphers | Ciphers/MACs lines in sshd_config. |
| Failed SSH logins | Counts failures in the auth journal (last hour). |
| Brute-force guard | systemctl is-active fail2ban / sshguard / crowdsec. |
| Security updates | apt / dnf pending security count. |
| Auto security updates | unattended-upgrades config / dnf-automatic timer. |
| Exposed database ports | Listening sockets on 3306/5432/6379/27017 bound publicly. |
| Public listening surface | Listening sockets on 0.0.0.0/:: (from the network collector). |
| Passwordless sudo | Parse /etc/sudoers + /etc/sudoers.d (needs root). |
| Suspicious processes | Process name/path/CWD pattern match. |
Reliability
weight 15%Is anything crashing, flapping, or failing under the hood — services, the kernel, and the hardware.
| Check | What it means | Penalty |
|---|---|---|
| Failed services | A systemd/PM2 service is in a failed or dead state. | −10 ea (cap −40) |
| Restart storms | A service is flapping (≥5 restarts). | −10 ea |
| Container crash loops | A container is restarting repeatedly. | −10 ea |
| OOM kills | The kernel killed a process for running out of memory. | −10 ea (cap −30) |
| Kernel panic | The kernel hit a fatal fault this boot. | −50 |
| Segfaults | Processes are crashing with segmentation faults. | −5 ea (cap −10) |
| Filesystem remount RO | The kernel forced a filesystem read-only after I/O errors. | −40 |
| Hardware errors (MCE) | Machine-check / hardware errors — failing CPU/RAM/PCIe. | −15 ea (cap −40) |
| Hung tasks | A task was blocked >120 s — an I/O stall or deadlock. | −5 ea (cap −15) |
| Frequent reboots | The server rebooted more than once in 24h (crash/flapping). | −8 ea (cap −25) |
| Core dumps | Crashed programs left core dumps. | −5 ea (cap −15) |
| Journal critical errors | An elevated burst of critical-priority log entries (>10/boot). | −8 (low confidence) |
Technical details — how each reliability check is measured ▸
| Failed services | systemctl / PM2 status (maintenance units excluded). |
| Restart storms | Unit restart counter. |
| Container crash loops | Docker restart count / “restarting” state. |
| OOM kills | Kernel log (journalctl -k / dmesg) “Killed process”. |
| Kernel panic | Kernel log “kernel panic”. |
| Segfaults | Kernel log “segfault / general protection fault”. |
| Filesystem remount RO | Kernel log “Remounting filesystem read-only”. |
| Hardware errors (MCE) | Kernel log “Hardware Error / machine check”. |
| Hung tasks | Kernel log “blocked for more than N seconds”. |
| Frequent reboots | journalctl --list-boots start times. |
| Core dumps | coredumpctl list / systemd-coredump spool. |
| Journal critical errors | journalctl -p 2 -b count. |
Maintenance
weight 10%Housekeeping that quietly turns into an outage if ignored — patches, reboots, certificates, packages.
| Check | What it means | Penalty |
|---|---|---|
| Reboot required | A kernel/libc update needs a reboot to take effect. | −10 |
| Pending updates | General package updates are available. | −5 |
| Security updates | Security patches pending (also scored under Security). | −15 |
| Certificate expiry | A TLS certificate is expired or expiring soon (<30/<7 days). | −5 / −10 / −15 |
| Broken packages | The package manager is in a half-configured state. | −10 |
| Orphaned packages | Many packages no longer have a source (>10). | −3 |
| Log rotation | Log rotation is broken — logs can fill the disk. | −5 |
Technical details — how each maintenance check is measured ▸
| Reboot required | /var/run/reboot-required (Debian) or equivalent. |
| Pending updates | apt / dnf pending count. |
| Security updates | apt / dnf pending security count. |
| Certificate expiry | Live TLS handshake per detected vhost. |
| Broken packages | dpkg / rpm consistency check. |
| Orphaned packages | Package-manager orphan query. |
| Log rotation | logrotate config/state check. |
Network
weight 10%Can the server actually reach the world — link, gateway, DNS, and packet health.
| Check | What it means | Penalty |
|---|---|---|
| Packet loss | The gateway is dropping pings (>5%). | −10 |
| Interface down | The primary network interface is down. | −15 |
| DNS resolution | The server can’t resolve names. | −10 |
| Gateway unreachable | The default gateway doesn’t answer. | −12 |
| Interface errors | The NIC is logging RX/TX errors or drops. | −8 |
Technical details — how each network check is measured ▸
| Packet loss | ICMP ping to the default gateway. |
| Interface down | /sys/class/net operstate. |
| DNS resolution | Live resolver lookup. |
| Gateway unreachable | ICMP ping / ARP to the gateway. |
| Interface errors | /sys/class/net error counters (per-heartbeat delta). |
Configuration
weight 5%Small settings that cause big, confusing problems when wrong.
| Check | What it means | Penalty |
|---|---|---|
| Time synchronized | The clock is not being kept in sync (breaks TLS, logs, tokens). | −10 |
| Swap configured | No swap is configured — a memory spike means instant OOM. | −5 |
Technical details — how each configuration check is measured ▸
| Time synchronized | timedatectl / NTP sync state. |
| Swap configured | /proc/swaps. |
Taking action — from the panel, not SSH
Every finding can be resolved without leaving the dashboard, three ways:
- Fix with AI — the AI diagnoses the specific problem and runs the fix, showing you every command first.
- Fix manually — the exact commands are shown to copy/run yourself over SSH (or run in-place if remote actions are on).
- One-click controls — the Security tab has toggles for Firewall, Root login, Brute-force guard (fail2ban) and Auto security updates, plus “Block this IP” for attackers — each with a plain-English confirm dialog.
Running anything requires Remote actions to be turned on for that server (see below). Until then, Opservo is strictly read-only and only shows you the fix.
The agent, installing, and updates
The agent is a single <10 MB Go binary. It only makes outbound HTTPS calls — there are no inbound ports to open — and every heartbeat is signed (HMAC) so the cloud can’t be spoofed.
- Install — “Add New Server” hands you a one-line command (
curl … | sudo … bash). First data appears in under 5 minutes. - Auto-update — agents check for a new build hourly and update themselves (download → verify checksum → swap → restart). New checks roll out on their own.
- Update from the panel — when a server is behind, an amber “Update agent” button appears in the server header; one click pushes the update (or shows the SSH command if remote actions are off).
- Reinstall — the ⋯ menu → “Re-install / upgrade agent…” gives a command that reuses the server’s credentials (no duplicate server).
- Run as root — a few checks (SSH hardening, sudoers, core dumps, SMART) can only be read as root; otherwise they show “n/a”, never a false pass.
Privacy & safety
- Read-only by default. The agent never runs a command unless you explicitly enable Remote actions for that specific server — and even then every command is confirmed and written to a permanent audit log.
- Opt-in per server. A fleet-wide agent update never makes a server remotely executable; each box is enabled individually.
- No inbound ports. Commands are pulled over the agent’s existing outbound HTTPS and HMAC-signed — the cloud never connects in.
- Data minimisation. Raw log lines are never stored; IPs/usernames in security findings are masked at the agent before they leave the box.
Scores are only comparable within a scoring version. Every rule, threshold and penalty above is enforced in code and unit-tested — the same facts always produce the same score.