Kokil Thapa - Professional Web Developer in Nepal
Freelancer Web Developer in Nepal with 15+ Years of Experience

Kokil Thapa is an experienced full-stack web developer focused on building fast, secure, and scalable web applications. He helps businesses and individuals create SEO-friendly, user-focused digital platforms designed for long-term growth.

Ubuntu Server Monitoring Guide

By Kokil Thapa | Last reviewed: August 2026

Production outages rarely happen without warning; they happen because nobody was watching the right metrics when the warning signs appeared. This Ubuntu Server Monitoring Guide provides a battle-tested approach to observing Linux systems running PHP, Laravel, and database workloads in 2026. Whether you are managing a single VPS for a legal-tech portal or a cluster of eCommerce servers, effective monitoring bridges the gap between reactive firefighting and proactive reliability engineering.

Before installing complex dashboards, ensure your foundation is secure. Monitoring exposes internal metrics that attackers can use to fingerprint your infrastructure. As outlined in my article on how to secure your website and server in Nepal, always restrict monitoring ports via UFW and never expose raw metric endpoints to the public internet. In my experience maintaining client portals and high-traffic WooCommerce stores, the difference between a minor hiccup and a four-hour outage usually comes down to whether we had baseline data to compare against. You cannot optimize what you cannot measure, and you cannot debug what you did not record.

How do you perform real-time diagnostics on Ubuntu Server?

When a server is actively degrading, you do not have time to query a time-series database. You need immediate, low-overhead visibility into the current state. Native CLI tools remain the fastest way to triage issues on Ubuntu 22.04 and 24.04 LTS.

CPU and Process Inspection

The standard top command is insufficient for modern multi-core debugging. Use htop or the newer btop for granular process inspection. These tools show per-core usage, thread counts, and memory consumption in a sortable interface.

# Install essential diagnostic tools
sudo apt update
sudo apt install htop btop iotop sysstat

# Run btop for comprehensive resource visualization
btop

# Filter processes by specific user (e.g., www-data for PHP)
htop -u www-data

A common mistake I see on production Laravel servers is misinterpreting load average. On an 8-core EC2 instance, a load average of 8.0 means full saturation, not failure. However, if the load is 8.0 but CPU usage is only 20%, your bottleneck is likely disk I/O or network latency, not compute. The "Load Average" line in htop must always be interpreted relative to core count.

Disk I/O and Storage Latency

Database-driven applications like Magento or WordPress often stall due to storage throughput limits rather than SQL inefficiency. The iotop utility identifies which processes are actually consuming disk bandwidth.

# Show only processes doing actual I/O
sudo iotop -aoP

# Check cumulative I/O statistics from sysstat
iostat -xz 1 5

In the iostat output, focus on %util and await. If %util approaches 100% while await exceeds 10ms on NVMe storage (or 50ms on SSD), your storage subsystem is saturated. For eCommerce sites processing concurrent orders during peak hours like Dashain sales, this metric predicts checkout timeouts better than CPU usage ever could.

Real-Time Diagnostic Decision TreeSymptom DetectedHigh Load AvgSlow ResponseCheck htop / btopCheck iotop / ssCPU Bound? → Scale/OptimizeI/O Wait? → Check Disk/DBDisk Sat? → Upgrade StorageNet Wait? → Check Upstream
Diagnostic workflow for correlating symptoms with specific Ubuntu monitoring tools

What is the best persistent monitoring stack for Ubuntu in 2026?

Real-time tools vanish when you close the terminal. For production systems, you need a persistent time-series database. In 2026, the industry standard for self-hosted Ubuntu monitoring remains Prometheus paired with Grafana. While cloud providers offer managed alternatives, self-hosting keeps costs predictable for Nepal-based clients where monthly AWS CloudWatch bills can exceed Rs 15,000 (~USD 112) for moderate traffic sites.

Architecture Overview

The stack consists of three components: Prometheus (scrapes and stores metrics), Node Exporter (exposes OS-level metrics), and Grafana (visualizes data). All run as systemd services on Ubuntu 24.04.

# Create dedicated system users for security
sudo useradd --no-create-home --shell /bin/false prometheus
sudo useradd --no-create-home --shell /bin/false node_exporter

# Create directories with correct ownership
sudo mkdir /etc/prometheus /var/lib/prometheus
sudo chown prometheus:prometheus /etc/prometheus /var/lib/prometheus

Never run exporters as root. The principle of least privilege applies doubly to monitoring agents, which inherently read sensitive system state. When deploying this stack for legal-tech portals handling sensitive case documents, I enforce strict filesystem permissions and network isolation.

Configuring Node Exporter Safely

Node Exporter 1.8.x is the current stable release for Ubuntu. It exposes over 500 metrics by default. Disable unnecessary collectors to reduce cardinality and attack surface.

# /etc/default/node_exporter
ARGS="--web.listen-address=127.0.0.1:9100 \
      --collector.disable-defaults \
      --collector.cpu \
      --collector.meminfo \
      --collector.diskstats \
      --collector.filesystem \
      --collector.netdev \
      --collector.systemd"

Binding to 127.0.0.1 prevents external access. Prometheus should scrape via SSH tunnel or internal VPC network, never over public HTTP. This configuration aligns with security best practices discussed in my cybersecurity trends analysis.

Persistent Monitoring ArchitectureNode Exporter:9100 (localhost)PHP-FPM Exporter:9253 (internal)PrometheusTSDB StorageScrape Interval: 15sGrafanaDashboardsAlert RulesHTTP ScrapeHTTP ScrapeQuery APIAll communication internal-only • UFW blocks external 9100/9090 • TLS optional for VPC
Secure Prometheus scraping topology with isolated metric endpoints for Ubuntu production servers

Which application-specific metrics matter for PHP and Laravel?

System metrics alone miss application-layer failures. A server can show 30% CPU usage while PHP-FPM has exhausted its worker pool and queued requests are timing out. For Laravel and WordPress deployments, you must instrument the runtime itself.

PHP-FPM Pool Monitoring

Enable the FPM status endpoint in your pool configuration (/etc/php/8.4/fpm/pool.d/www.conf):

pm.status_path = /status
ping.path = /ping
ping.response = pong

Restrict access to these paths in Nginx to localhost or internal IPs only. Then deploy php-fpm-exporter to translate the status page into Prometheus metrics. Key metrics to alert on:

  • active_processes / max_children: Sustained values above 80% indicate imminent request queuing
  • slow_requests: Counter increment signals backend bottlenecks even when CPU is idle
  • listen_queue_len: Non-zero values mean the kernel socket backlog is filling; users are experiencing latency

Laravel Queue and Job Health

For queue-heavy applications like order processing systems, monitor job throughput and failure rates. Laravel Horizon exposes Redis-backed metrics that can be scraped via custom exporters. Without Horizon, instrument your jobs directly:

// In AppServiceProvider or dedicated metric collector
$failedJobs = DB::table('failed_jobs')
    ->where('failed_at', '>', now()->subHour())
    ->count();

// Expose via /metrics endpoint or push to StatsD
Statsd::gauge('laravel.queue.failed_last_hour', $failedJobs);

I have seen numerous eCommerce deployments where the web server appeared healthy while queue workers silently died, leaving orders unprocessed for hours. Application-level health checks catch this; system metrics do not.

How should you configure alerts to avoid fatigue?

Alert fatigue destroys monitoring value. If more than 5% of alerts do not require immediate human action, tune or delete them. Effective alerting follows the symptom-based philosophy: alert on user pain, not cause.

Alert TypeExample (Bad)Example (Good)Rationale
Cause-BasedCPU > 80% for 5 minHTTP 5xx rate > 1% for 3 minHigh CPU may be normal during batch jobs; errors hurt users
SaturationDisk 90% fullDisk will fill within 4 hours at current ratePredictive alerts allow planned intervention vs panic
AvailabilityProcess not runningHealth endpoint failing for 2 minProcess restarts may be normal; failed health checks are not
PerformanceResponse time > 500msp95 latency > SLA threshold for 5 minAverages hide outliers; percentiles reflect real user experience

Implementing Alertmanager Routing

Route critical alerts (service down, data loss risk) to PagerDuty or SMS. Route warnings (disk trending up, certificate expiring soon) to Slack or email. Never send all alerts to all channels.

# /etc/prometheus/alertmanager.yml
route:
  receiver: 'slack-warnings'
  routes:
    - match:
        severity: critical
      receiver: 'pagerduty-critical'
      continue: false
    - match:
        severity: warning
      receiver: 'slack-warnings'

receivers:
  - name: 'pagerduty-critical'
    pagerduty_configs:
      - service_key: '<your-key>'
  - name: 'slack-warnings'
    slack_configs:
      - channel: '#infra-alerts'

For Nepal-based teams operating across time zones, consider routing critical alerts to local phone numbers via SMS gateways during business hours and PagerDuty after-hours. This operational awareness matters as much as the technical configuration.

Severity-Based Alert RoutingAlertmanagerRoute by Severity LabelCRITICALPagerDuty + SMSWARNINGSlack #infra-alertsINFOEmail DigestImmediate ResponseBusiness Hours ReviewWeekly Audit
Alert severity routing prevents notification fatigue in production Ubuntu monitoring setups

What are common monitoring pitfalls for Ubuntu servers?

Even well-instrumented systems fail when monitoring itself becomes unreliable. These patterns recur across projects I have maintained:

  1. Monitoring the monitor: Always set up a dead-man's switch. If Prometheus stops scraping or Alertmanager stops sending heartbeats, an external service (like Healthchecks.io or UptimeRobot) should alert you. Silent monitoring failures are worse than no monitoring at all.
  2. Cardinality explosions: Adding high-cardinality labels like user_id or request_id to metrics can crash Prometheus within hours. Keep label sets bounded and predictable. Use logs for per-request tracing, not metrics.
  3. Ignoring timezone consistency: Ensure all servers, databases, and monitoring components use UTC. Nepal operates on NPT (UTC+5:45), but mixing local time in logs with UTC in metrics makes correlation impossible during incidents.
  4. No runbook links in alerts: Every alert should include a link to remediation documentation. An alert saying "Disk Full" without context wastes 30 minutes of investigation. Link directly to your internal wiki or relevant guides like my DevOps automation practices article.
  5. Testing alerts only in staging: Staging environments rarely replicate production load patterns. Regularly verify that critical alerts actually fire and route correctly in production using synthetic tests or controlled fault injection.

Resource Budgeting for Monitoring

Monitoring consumes resources. On a 2GB RAM VPS, Prometheus and Grafana can consume 30-40% of available memory. For smaller instances, consider lightweight alternatives like Netdata (single-node, minimal overhead) or exporting metrics to a managed service. Never let monitoring starve the application it exists to protect.

# Limit Prometheus memory usage via retention and storage flags
# /etc/default/prometheus
ARGS="--storage.tsdb.retention.time=15d \
      --storage.tsdb.retention.size=8GB \
      --query.max-samples=50000000"

Adjust retention based on your compliance needs and disk capacity. For most web applications, 15 days of high-resolution data plus longer-term downsampling provides sufficient forensic capability without exhausting budget-constrained VPS storage.

Building Reliable Ubuntu Server Observability

Effective server monitoring is not about installing tools; it is about building organizational knowledge. Start with native diagnostics for immediate triage, layer Prometheus for persistent trending, instrument application runtimes for business-context awareness, and configure alerts that respect human attention. Test your monitoring as rigorously as your application code. Document every alert's meaning and remediation path. Review dashboards quarterly to remove stale panels and add missing signals.

This Ubuntu Server Monitoring Guide reflects patterns proven across production Laravel, WooCommerce, and legal-tech platforms serving real users. The specific tools may evolve, but the principles remain constant: measure what matters, alert on symptoms, and maintain the discipline to trust your instrumentation when pressure mounts. If your team needs help implementing production-grade observability or auditing existing monitoring gaps, reach out through my contact page to discuss your infrastructure requirements.

Frequently Asked Questions

Netdata, Prometheus with Node Exporter, and Glances are top choices. All run natively on Ubuntu 24.04 LTS without licensing fees or cloud dependencies.

Lightweight agents like Node Exporter use under 50MB. Full-stack tools like Netdata or Zabbix agent may require 200-400MB depending on metrics collected and retention settings.

Choose Prometheus for cloud-native, metric-driven environments using time-series data. Pick Nagios for traditional host/service checks, legacy infrastructure, or when state-based alerting is primary.

Run the official kickstart script which handles dependencies and service setup automatically. In my experience managing production servers, this method avoids package conflicts common with apt installs. Post-installation, edit netdata.conf to set memory limits and disable unused collectors. Configure streaming to a central node if monitoring multiple servers. The dashboard becomes available immediately on port 19999, but always restrict access via UFW or reverse proxy authentication in production environments to prevent information disclosure.

Beyond basic CPU and memory, monitor disk I/O wait, inode usage, TCP connection states, and PHP-FPM or Nginx worker saturation. On legal-tech portals I have built, tracking database connection pool exhaustion prevented more outages than raw CPU alerts. Always measure application-level latency alongside system metrics. Configure alerts for sustained high load averages rather than instantaneous spikes to reduce noise. Track swap activity as an early warning for memory pressure before OOM kills occur.

Never expose monitoring ports directly to the internet. Use Nginx as a reverse proxy with HTTP basic auth or OAuth2-proxy in front of Netdata, Grafana, or Prometheus. Restrict access via UFW to trusted IPs only. In production deployments I manage, monitoring interfaces sit behind VPNs or SSH tunnels. Rotate credentials regularly and audit access logs. Disable default admin accounts and enforce TLS even on internal networks to prevent credential sniffing during lateral movement.

This usually indicates single-threaded processes saturating one core while others remain idle. Check per-core utilization with htop or mpstat. Common causes include unoptimized PHP scripts, runaway cron jobs, or database queries lacking proper indexing. On Laravel applications I have debugged, synchronous queue workers often cause this pattern. Profile the specific process consuming CPU rather than relying on aggregate metrics. Consider cgroup limits to isolate noisy workloads from critical services.

Combine Promtail or Fluent Bit with Loki or Elasticsearch for log aggregation. Configure structured logging in your application to enable correlation between metrics and log events. On production systems I maintain, I tag logs with request IDs matching trace IDs in metrics. Set up alerting on error rate thresholds rather than individual log lines to avoid fatigue. Retain raw logs separately from aggregated metrics for forensic analysis. Ensure log rotation prevents disk exhaustion during traffic spikes.

Set warnings at 80% and critical alerts at 90% for root and data partitions. However, also monitor inode usage separately since many small files can exhaust inodes before space runs out. On eCommerce sites handling uploads, I have seen inode exhaustion crash systems with 40% disk space remaining. Configure alerts based on growth rate predictions, not just current usage. Exclude temporary directories from alerts but monitor them for cleanup failures. Test recovery procedures before relying on automated cleanup scripts.

Use certbot certificates command for Let's Encrypt managed certs or integrate ssl_exporter with Prometheus for comprehensive monitoring. Configure alerts thirty days before expiry to allow renewal buffer. On servers I manage with Deployer 7, certificate checks run as part of deployment validation. Monitor both leaf and intermediate chain validity. Test auto-renewal hooks monthly since silent failures are common. For wildcard certificates, track DNS propagation delays that can cause renewal timeouts during maintenance windows.

Yes, cAdvisor exposes container metrics via Prometheus endpoint without modifying containers. Alternatively, Docker daemon exposes stats API natively. In containerized Laravel deployments I have operated, cAdvisor provides sufficient visibility for most debugging. Avoid installing monitoring agents inside containers as it increases image size and attack surface. Use labels for service identification rather than container names which change on restart. Correlate container metrics with host metrics to distinguish application issues from resource contention.

Capture packet traces with tcpdump during incidents and analyze with Wireshark. Monitor TCP retransmission rates, connection resets, and DNS resolution times continuously. On production APIs I have maintained, intermittent timeouts often traced to conntrack table exhaustion or misconfigured keepalive settings. Check ethtool for NIC errors and driver issues. Verify MTU consistency across network path. Use mtr instead of ping to identify routing problems. Correlate network anomalies with application logs to distinguish infrastructure from code-level issues.

Centralize metrics with Prometheus federation or VictoriaMetrics and use Grafana for unified dashboards. Deploy consistent exporters via Ansible or Puppet to ensure configuration parity. On sister sites sharing Deployer 7 pipelines, standardized monitoring configs prevent drift across environments. Implement service discovery rather than static targets to handle dynamic scaling. Separate infrastructure metrics from business metrics in distinct dashboards. Establish baseline performance profiles per server role to detect anomalies faster than generic thresholds allow.

Audit alerts quarterly and remove those not requiring immediate human action. Group related alerts into single notifications using Alertmanager inhibition rules. On production systems I operate, fewer than five percent of configured alerts trigger pages. Use severity levels strictly: page only for user-impacting issues. Implement maintenance windows for planned work. Document runbooks linked directly from alert messages. Track mean time to acknowledge and resolve to identify poorly tuned alerts. Silence flapping metrics until root causes are fixed.

For teams under three engineers, managed services save operational overhead despite costing USD 15-30 per host monthly (NPR 2,000-4,000). Self-hosted stacks require ongoing maintenance time that small teams cannot spare. However, for Nepal-based projects with budget constraints, Prometheus and Grafana provide equivalent capability at zero licensing cost. I recommend starting self-hosted and migrating to managed only when monitoring maintenance exceeds development velocity. Evaluate total cost including engineer hours, not just subscription fees. Data residency requirements may also favor local self-hosted solutions.

Share this article

Quick Contact Options
Choose how you want to connect me: