Why trust this guide
By Victus Cloud · Reviewed by Victus Cloud · No individual author claimed. Verify paths, versions, and backups before changing a live service.
Evidence-led, product-agnostic
Start with a baseline, not alarms
You cannot declare a number 'abnormal' until you know what normal looks like for your workload. A VPS running a quiet static site has a very different daily rhythm than one hosting a database plus a reverse proxy plus scheduled jobs. Spend a normal week recording typical CPU, memory, disk usage, and network patterns during business hours, overnight, and during backups. A spike only means something when compared with that baseline and with user-visible symptoms. Without a baseline, every brief burst looks like an emergency and every real trend looks like noise.
Capture the baseline during representative activity, not a perfectly idle Sunday. If backups run at 02:00, observe 02:00. If traffic peaks at 18:00, observe 18:00. Note the recurring events—package updates, log rotation, certificate renewal, cron jobs—because they explain most of the 'weird' graphs you will later see. The goal is a mental model of the machine's heartbeat, so that when the heartbeat changes you can tell a normal variation from a developing fault.
Panel metrics are product-specific
What the VPS panel shows, how often it refreshes, which resources it covers, and whether it retains history depend on the current product and plan. Use it together with in-guest checks rather than as the only source of truth.
The signals that actually predict trouble
- CPU saturation sustained near limits during real load, not brief bursts from a single cron task.
- Memory creeping toward the limit with growing swap usage or repeated out-of-memory kills.
- Disk usage climbing toward full—this can silently break databases, logs, and backups at once.
- A service process that exited but the proxy or port still appears open to a health check.
- Certificate expiry and renewal failures that turn HTTPS off without an obvious error to users.
- Inbound or outbound network volume that departs from the baseline, which can indicate abuse or a leak.
Notice that most of these are trends, not instantaneous values. A CPU at 100% for three seconds during a backup is unremarkable; a CPU pinned at 95% for twenty minutes while users complain is a problem. Train yourself to watch 'sustained' and 'growing' rather than 'high right now.' The dangerous failures are slow: a disk that fills by 1% a day, a cache that leaks memory every request, a log file that never rotates.
Practical in-guest checks
On a self-managed Linux VPS you already have most of the tools you need. The following commands are starting points; adjust for your distribution and installed tooling. They are read-only and safe to run during normal operation.
uptime # load average vs CPU count
free -h # memory and swap
df -h # disk usage per mount
ss -tulpn # listening ports and processes
journalctl -p err -n 50 # recent system errorsThe load average from uptime only means something relative to your CPU count: a load of 2 on a two-core machine is saturated, while a load of 2 on a sixteen-core machine is comfortable. df -h should be checked on every mount, because a full /var or /tmp can break services even when the root filesystem looks fine. ss -tulpn confirms what is actually listening, which is more reliable than assuming a service is up because its process exists.
Why you also need an external vantage point
If the whole VM hangs, an in-guest monitoring agent cannot report—it is part of the thing that died. An external check, run from a different network, catches total outages and network-level problems that local tools miss. This can be as simple as a scheduled HTTP request against your site or a TCP check against a game port from a separate machine or monitoring service. The external probe answers the only question users care about: 'can the outside world reach the service right now?'
- Define the check target: an HTTPS endpoint, a specific port, or a synthetic transaction.
- Run it from outside the host, on a different provider or network where possible.
- Alert on 'expected up but unreachable' rather than on every single failed probe.
- Correlate external failures with in-guest evidence before concluding the cause.
- Keep the external check independent of the very service it monitors for credentials and location.
A green agent is not a healthy service
A monitoring agent that reports 'system online' only proves the agent's process is alive. It does not prove your application answers requests. Pair host checks with an application-level probe that exercises the real workload.
Choosing honest thresholds
Thresholds should come from the baseline, not from a generic internet template. A web server with steady 40% CPU at peak should warn well before 90%, because you want lead time. A batch box that briefly hits 100% during nightly jobs should not page anyone. The table below is a starting philosophy, not a rule to paste blindly; validate each value against your own graph.
| Signal | Warn idea | Critical idea | Why |
|---|---|---|---|
| Disk usage | 80% on any mount | 90% with a cleanup runbook | Full disks break databases, logs, and backups silently |
| Memory | Approaching plan limit | Sustained at limit with swap growth | OOM kills can take down unrelated services |
| CPU | Sustained high during real load | Pinned with user-visible slowness | Brief bursts from cron are normal |
| Service port | External probe fails twice | Fails for the alert window | Single blips can be transient network noise |
| Certificate | Renewal due within 14 days | Renewal failed | Expired TLS is an immediate outage for HTTPS |
Make alerts actionable, or don't send them
An alert without a defined response is just noise that trains people to ignore pages. For every alert, write the first diagnostic step and the rollback or mitigation. 'Disk at 90%' should link to the cleanup runbook; 'service port down' should name which service and where the logs live. Route alerts to a channel someone actually watches, and avoid alerting the same condition from three systems at once.
- Attach a runbook link or the first two commands to every alert message.
- Deduplicate: one incident, one notification thread, not a storm per metric.
- Use severity honestly—page only for things that need a human now.
- Review alerts weekly and delete or retune the ones nobody acted on.
- Test the alert path: trigger it on purpose so you know it reaches you.
The most overlooked discipline: disk growth
Disk fill is the single most common silent outage we see across self-managed VPS workloads. Logs without rotation, failed backups that leave partial files, container layers that never prune, and databases that grow without bounds all consume space steadily. By the time the disk is full, the symptoms are bizarre: a database that will not commit, an SSH session that cannot start a shell, a web server that returns 500 with no obvious cause. Set a recurring review of df -h output and automate cleanup where it is safe.
du -h --max-depth=1 /var 2>/dev/null | sort -h
journalctl --disk-usage
# Prune old logs only after you understand what writes themClose the loop with a weekly review
Monitoring is not 'set it and forget it.' Spend fifteen minutes weekly looking at trends, not just current values. Is memory's floor slowly rising week over week? Is disk usage on a steady climb that will hit 90% in two months? Catching those lines early turns a future 3 a.m. page into a calm Tuesday afternoon change. Keep a short note of what you observed and what you decided, so the next operator inherits context instead of starting blind.
The honest summary: good monitoring is a feedback loop between measurement, thresholds tuned to your reality, and a response you have already rehearsed. The panel and your own checks each cover blind spots the other cannot see, so use both.