Docs
Monitoring

Webserver monitors (Nginx)

Collect Nginx request and connection metrics, set thresholds and alert when data stops arriving.

What it checks

A Webserver monitor watches one Nginx instance through the OpenTelemetry Collector contrib distribution. The Collector reads Nginx's private stub_status endpoint and sends its metrics to Upty over HTTPS. Upty charts requests per second, active connections and connections that are reading, writing or waiting.

You can enable thresholds for Active connections and Requests per second. Even with both thresholds disabled, a previously connected monitor is watched for missing data. This is an ordinary monitor: it uses one monitor slot and appears in Monitors, rather than Hosts.

The first version supports Nginx only. It does not collect Apache or IIS metrics, aggregate HTTP status-code counts, or the latency of all visitor requests. Add a separate Website or API monitor for the HTTP response seen by a probe, a Host monitor for machine resources, or a Logs monitor for supported logs you send.

Before you start

  • A server running Nginx with the stub_status module available. See the Nginx module documentation.
  • An OpenTelemetry Collector contrib installation, or Docker on a Linux server. The current generated configuration pins Collector 0.163.2.
  • The Collector must reach the Nginx status endpoint and https://upty.io over HTTPS.
  • A role that can create monitors and available capacity in your plan. Webserver monitoring is included in the standard Free, Pro and Business plans.

The status endpoint stays private. Upty's probes do not connect to it. A loopback or private endpoint is read by the Collector on your server. The endpoint in the form describes where that Collector connects, not an address fetched by Upty.

Create the monitor

  1. Open /app, go to Monitors and click New monitor.
  2. Choose Webserver (Nginx) and enter a recognizable Name.
  3. Keep http://127.0.0.1:8080/nginx_status as the endpoint, or enter a private HTTP(S) status URL reachable by the Collector. Credentials in the URL, query strings and fragments are not supported.
  4. Choose an evaluation window. Optionally enable an Active connections or Requests per second threshold and set the value appropriate to this instance.
  5. Choose alert destinations and create the monitor.
  6. On the connection screen, copy the Nginx snippet and the Linux or Docker Collector configuration. The ingestion token is shown only at creation or rotation; save it securely now.

There is no Check from region or probe interval for this type. The generated Collector samples every 30 seconds; threshold evaluation runs every minute. Those are different from the external check intervals of a Website monitor.

Enable a private Nginx status endpoint

Use the snippet from the connection screen. A typical host installation uses a dedicated loopback listener:

server {
    listen 127.0.0.1:8080;
    server_name localhost;

    location = /nginx_status {
        stub_status;
        access_log off;
        allow 127.0.0.1;
        deny all;
    }
}

Save it in a configuration directory included by your Nginx installation. If port 8080 is already in use, choose an unused local port and update the monitor endpoint to match. Test the configuration before reloading:

sudo nginx -t
sudo systemctl reload nginx
curl --fail http://127.0.0.1:8080/nginx_status

The response contains active connections, cumulative accepted/handled connections and requests, and the reading/writing/waiting counts. A public virtual host must not expose this location. If Nginx and the Collector run in different containers or machines, use a private network and access rules that permit only the intended Collector.

Connect from Linux

The connection screen provides a complete configuration. Save that configuration as webserver-otel.yaml; it contains the monitor's private token. Use the contrib binary from the official Collector releases, choose the archive for your operating system and architecture, and verify the published SHA-256 before extracting it.

For a foreground check, run:

./otelcol-contrib --config=webserver-otel.yaml

To keep a separate Linux systemd service, the following paths and service name avoid replacing an existing Host Collector. These commands assume the verified otelcol-contrib binary and the saved configuration are in the current directory:

id upty-webserver >/dev/null 2>&1 || sudo useradd --system --no-create-home --shell /usr/sbin/nologin upty-webserver
sudo install -d -m 0755 /opt/upty-webserver-collector
sudo install -m 0755 ./otelcol-contrib /opt/upty-webserver-collector/otelcol-contrib
sudo install -d -o upty-webserver -g upty-webserver -m 0750 /etc/upty-webserver-collector
sudo install -o upty-webserver -g upty-webserver -m 0600 webserver-otel.yaml /etc/upty-webserver-collector/config.yaml

Save this as /etc/systemd/system/upty-webserver-collector.service:

[Unit]
Description=Upty Nginx metrics collector
After=network-online.target
Wants=network-online.target

[Service]
User=upty-webserver
ExecStart=/opt/upty-webserver-collector/otelcol-contrib --config=/etc/upty-webserver-collector/config.yaml
Restart=always
RestartSec=5
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
PrivateTmp=true

[Install]
WantedBy=multi-user.target

Start the service and inspect its output:

sudo systemctl daemon-reload
sudo systemctl enable --now upty-webserver-collector
sudo journalctl -u upty-webserver-collector -f

Use the generated configuration for this deployment. Its essential pipeline is:

receivers:
  nginx:
    endpoint: http://127.0.0.1:8080/nginx_status
    collection_interval: 30s
exporters:
  otlphttp/webserver:
    metrics_endpoint: https://upty.io/api/ingest/webserver/v1/metrics
    encoding: json
    headers:
      Authorization: "Bearer uwb_YOUR_WEBSERVER_TOKEN"
service:
  pipelines:
    metrics/webserver:
      receivers: [nginx]
      exporters: [otlphttp/webserver]

Keep request counters cumulative. Upty derives request rates from successive accepted samples; adding counter-to-rate processors changes the input this monitor expects. OTLP/HTTP JSON is supported, including gzip; protobuf is not.

Connect with Docker Compose

On a Linux host, save the generated Docker configuration as webserver-otel.yaml and the supplied Compose file next to it. It uses its own service name, upty-webserver-collector, and host networking so the Collector can reach Nginx on 127.0.0.1. It does not need the host filesystem mounts used by Host monitoring.

Start it from that directory:

docker compose up -d
docker compose logs -f upty-webserver-collector

Use the Collector image shown by the connection screen. Ensure the container can read the mounted file while limiting host access to the file owner or a dedicated group. Do not commit a file containing the token. Host networking here is a Linux setup; Docker Desktop's loopback behavior is different. For Nginx in another container, use an endpoint reachable from the Collector's network namespace and keep access private.

Keep an existing Collector

You do not have to replace an existing Collector or its host configuration. You can merge the generated Nginx receiver, a separate named exporter containing the uwb_ token, and a dedicated metrics pipeline into the existing contrib configuration. Preserve the existing hostmetrics pipeline and its uph_ host token. Rename component IDs if they would collide.

  • Send the Nginx pipeline to /api/ingest/webserver/v1/metrics with its webserver token.
  • Keep the Host pipeline's existing endpoint and host token unchanged.
  • Do not send both pipelines through the same token: their metric allowlists and resource identities are different.
  • Validate the combined Collector configuration before restarting it. If separate operations are easier for your setup, use the independent service or Docker container above.

Metrics and thresholds

MetricWhat it means
Requests per secondChange in the cumulative Nginx request counter divided by the elapsed sample time.
Active connectionsAll current client connections, including waiting connections.
ReadingConnections for which Nginx is reading the request header.
WritingConnections for which Nginx is writing the response.
WaitingIdle client connections waiting for another request.

The current values also include the supported cumulative connection/request totals. The charts offer 1 hour, 6 hours, 24 hours or 7 days. Missing samples are shown as gaps, not invented zeroes.

Active connections and Requests per second thresholds start disabled; the suggested value for each is 1000. Choose a threshold based on the instance's normal workload. This monitor does not treat traffic volume by itself as proof of an outage.

Request rate needs two compatible samples between 1 and 120 seconds apart. Its first sample, a reset or decreased counter, a changed counter start timestamp, an out-of-order sample or a long gap does not create a rate reading. After rotation, the rate baseline also starts again. Connections can appear while the request rate is still waiting for a comparison sample.

Status, evaluation and alerts

Choose an evaluation window of 5, 10, 15, 30 or 60 minutes, default 5 minutes.

  • Pending: this monitor has never received accepted fresh metrics.
  • Starting: fresh data has begun arriving and the initial window is filling. Threshold evaluation starts after fresh data has filled the chosen window.
  • Down: an enabled metric stays above its threshold for the evaluation window, or the evaluation window contains no metrics. Missing-data status is evaluated by the monitoring backend; ingestion and minute-based evaluation can delay the visible change.
  • Recovery follows fresh accepted data and the relevant healthy threshold evaluation. Data delivery and metric evaluation can take time; receiving the first request is not an instant guarantee of a healthy result.

The minute-based evaluation and the window handle threshold timing; this type does not use a consecutive probe-failure count. Pausing stops evaluation and notifications. Existing alert destinations, reminders, quiet hours, maintenance and recovery notifications work as described in Alerts.

Tokens and access

Each Webserver monitor has its own token beginning with uwb_. Only a hash is stored. The token allows ingestion for that monitor; it cannot read workspace data or manage monitors. The server assigns the resource identity instead of trusting a collector-supplied name.

The token is shown once when the monitor is created, cloned or rotated. Cloning creates an independent token: do not run both collectors with one token. Ordinary monitor reads, exports and MCP responses do not reveal it.

If you lose a token, open the monitor's connection settings and choose Rotate token. Confirm, copy the replacement, update the Collector configuration and restart that Collector. The old token stops working immediately. A later visit shows a placeholder rather than recovering the token.

Webserver monitoring is included in standard Free, Pro and Business plans and uses one ordinary monitor slot. API-key and MCP access are separate entitlements. The same monitor-type and quota rules apply to creation through the API or MCP.

Troubleshooting

ProblemWhat to check
Still PendingConfirm the Collector is running and can reach the exact nginx_status URL from its own network namespace. Look for scrape or export errors in its log.
Nginx returns 404 or 403Check the location path, listener, allowed client address and whether stub_status is available. Test from the same host or container as the Collector.
Export returns 401Use this monitor's uwb_ token. A Host token or workspace API key cannot ingest its metrics. Update the token after rotation.
Export returns 413 or 429Keep the generated 30-second collection interval, avoid duplicate collectors and remove unrelated telemetry from this pipeline. The Collector can retry temporary failures.
Export returns 502The metrics backend did not accept the batch. Keep the Collector running and inspect its retry logs; do not replace the token to solve a backend failure.
Empty or rejected payloadKeep OTLP/HTTP encoding: json, use the dedicated webserver ingestion URL and send the generated Nginx metrics without renaming them.
Requests per second is blankTwo compatible cumulative samples are needed. A first sample, reset or gap produces a missing rate rather than a false spike.
Metrics appeared but status is StartingAllow the configured evaluation window, at least five minutes, to fill. Check the Collector continues to send fresh samples.
No data after a token changeReplace the token in the correct webserver Collector file and restart that service or container. The Host Collector has its own file and token.

For API creation, safe connection information and rotation operations, see Monitor API workflows.

On this page