Library / SDK
vozlt/nginx-module-vts avatar
vozlt/nginx-module-vts

nginx-module-vts: per-vhost traffic status inside Nginx

Nginx virtual host traffic status module

3,504 stars489 forksCBSD-2-Clause

At a glance

What is it?
nginx-module-vts is a BSD-2-Clause Nginx module that keeps per-server, per-upstream and per-filter traffic counters in shared memory and exposes them as HTML, JSON or JSONP. It is for operators who want vhost-level traffic numbers without an external exporter, and it is compiled into Nginx rather than loaded from a package.
Who is it for?
Adopt nginx-module-vts if you already build Nginx from source and want per-vhost, per-upstream and per-filter counters served straight from shared memory, with the ability to reset or delete a zone through the control endpoint. Do not adopt it if you need a stock distro package, or if you expect the module to answer questions about request latency rather than traffic volume.
Can I use it commercially?
Yes. BSD-2-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 18 days ago.
What is it written in?
Mainly C, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The gap nginx-module-vts fills

Stock Nginx gives you access logs and, with stub_status, a handful of connection counters for the whole server. Neither answers a question like how many bytes vhost a.example.com served today, or which upstream returned the most 5xx responses in the last hour. Answering that usually means shipping logs somewhere and aggregating them after the fact.

nginx-module-vts moves that aggregation into the worker process. Traffic is counted as requests are handled, stored in shared memory, and read back over an HTTP location. The README describes the project as an "Nginx virtual host traffic status module", and the directive list backs that up: counters exist per server, per upstream, and per filter key you define yourself. The audience is the operator who runs several virtual hosts on one Nginx and wants numbers without a log pipeline.

It is not a metrics exporter and it does not push anything. You pull the status page, or something else pulls it for you.

How the zone counters actually work

The module is configured in two layers. vhost_traffic_status_zone declares the shared memory zone that holds every counter; without it the module has nowhere to write. vhost_traffic_status turns collection on for a server or location block.

On top of that sits a filter layer. vhost_traffic_status_filter_by_host splits counters by the Host header, so each virtual host gets its own entry. vhost_traffic_status_filter_by_set_key goes further: you supply a key expression, and the module maintains a separate node for every distinct value it produces. The README's use cases use this to break traffic down by country with GeoIP, by user agent, by detailed HTTP status code, and by storage volume. vhost_traffic_status_filter_max_node caps how many nodes a filter may create, which matters because each distinct key consumes shared memory.

The display side is vhost_traffic_status_display, with vhost_traffic_status_display_format choosing html, json or jsonp and vhost_traffic_status_display_jsonp setting the callback name. The control endpoint under the same location accepts requests that reset zones, delete zones, or return them, and the README documents separate forms for all zones, a group of zones, and a single zone. There is also a Set section for writing values into the statistics.

Two directives shape the arithmetic rather than the plumbing. vhost_traffic_status_average_method selects how averages are computed, and vhost_traffic_status_histogram_buckets defines the buckets for histogram output. The README points to a Calculations and Intervals section for the details, which is the part worth reading closely before you trust a number.

Installing nginx-module-vts and reading the status page

The module is not packaged. The README's installation section is four steps: clone the repository, add --add-module to the build configuration, build the nginx binary, install it. That means you need the Nginx source tree and a working toolchain, and it means the module's version is tied to the Nginx version you compile against.

The README's first step is to clone the repository:

bash
git clone git://github.com/vozlt/nginx-module-vts.git

The second step is to add the module to the build configuration by adding --add-module=/path/to/nginx-module-vts, which is the exact form the README gives:

bash
--add-module=/path/to/nginx-module-vts

After the binary is built and installed, the directives become available. The README's directive list is the reference for how they combine: vhost_traffic_status_zone declares the shared memory zone, vhost_traffic_status enables collection, and vhost_traffic_status_display together with vhost_traffic_status_display_format exposes the status page. The README shows screenshots of the default view and of the filtered view rather than a full configuration file, so the exact block layout is something you assemble from the directive list.

Requesting the status location returns the HTML view shown in the README screenshots. Setting vhost_traffic_status_display_format to json returns the same data as a JSON document, which is the form the README documents for the status and control endpoints and the form most external scrapers would consume.

The README also documents a Profile-Guided Optimization build using gcc fprofile options, with a configure line that passes -fprofile-generate and -fprofile-dir through --with-cc-opt and -lgcov through --with-ld-opt. The README explicitly says to use that process at your own risk, so treat it as an experiment rather than a default build.

For tests, the README gives `sudo prove -r t` and notes that sudo is required because the test suite needs Nginx listening on port 80. Running that on a machine already serving port 80 will conflict.

Where the design costs you

The counters live in shared memory, and that is the source of most of the module's sharp edges. Every filter key you create is a node, and vhost_traffic_status_filter_max_node exists precisely because unbounded key cardinality is a problem. A filter keyed on user agent or on a dynamic DNS name can produce a long tail of one-hit nodes, and the README's own use cases include both. Set the limit deliberately.

Persistence is opt-in. vhost_traffic_status_dump writes the statistics to a file so they can be restored, and the README lists maintaining statistics data permanently as a use case. Without it, the numbers are process state: a restart clears them. The README does not document rollback or a migration path between dump formats, so an upgrade that changes the on-disk layout is something you would discover rather than plan for.

The module is also the wrong tool for latency. Nothing in the directive list measures request duration or time-to-first-byte; the histograms are traffic histograms, not latency histograms. If your question is why a vhost got slow, an access log with $request_time or a tracing setup is the right instrument. This module tells you how much traffic moved and how it was classified, not how long it took.

Finally, the control endpoint can reset and delete zones. The README documents that capability plainly, which means the status location needs the same access control you would apply to any administrative URL. The README does not document authentication for it.

Alternatives and how they differ

The most direct alternative is nginx-vts-exporter, which appears in the related searches around this project. The split is architectural: nginx-module-vts collects and serves, while an exporter is a separate process that reads the module's JSON endpoint and re-publishes it in a metrics format for a time-series database. If your monitoring already runs on a scrape-based system, the exporter is the missing half rather than a competitor, and it still depends on the module being compiled in.

A second alternative is not collecting in Nginx at all: parse the access log. That keeps Nginx stock, works with any distro build, and gives you per-request detail the module never stores, including timing. The cost is latency between the request and the number being available, plus a log pipeline to run. The module's advantage is that the number is already aggregated when you ask for it.

A third option is Nginx Plus, whose built-in status API covers some of the same ground. That is a commercial product with its own licensing, and it is not a drop-in for someone already running the open source build. The honest comparison is that nginx-module-vts gives you vhost and filter breakdowns for the price of maintaining a custom Nginx build, and that build is the real cost.

Maintenance, licence and the build you now own

The repository is not archived, and the last push was on 2026-09-12. The most recent tagged release is v0.2.7 from 2026-08-08, preceded by v0.2.6 on 2026-07-29 and v0.2.5 on 2025-12-28. The compatibility list in the README names tested Nginx versions from 1.4.x through 1.30.x, with 1.30.4 as the last tested, and states that earlier versions were not tested.

That list is the maintenance story. Because the module is compiled in with --add-module, every Nginx upgrade means recompiling and re-testing, and a new Nginx release may not appear in the tested set yet. The README does not describe a stable ABI or a loadable-module path, so there is no way to decouple the two upgrade cycles.

The licence is BSD-2-Clause, per the repository and the badge in the README. That is a permissive licence, and the practical implication is that you can ship a binary containing the module without publishing your own source. It says nothing about the licence of Nginx itself, which you are also building, and nothing here is legal advice; check both licences against your distribution obligations.

The frontend is a separate concern. The Makefile defines front-install, front-build, front-dev and front-clean targets that run npm install and npm run build inside the front/ directory, and the README has a React Dashboard section. Those targets are for working on the bundled dashboard, not for installing the module, and front-build writes to front/dist/.

What to check before you build it in

Confirm your Nginx version against the compatibility list first. If you run a version newer than 1.30.4, you are outside what the README says was tested, and you will find that out during the build rather than before it.

Decide the filter keys before you deploy. Each key you pass to vhost_traffic_status_filter_by_set_key becomes a shared-memory node, and vhost_traffic_status_filter_max_node is the only ceiling. A key with high cardinality will hit that ceiling and the README does not describe what happens to the excess beyond the limit.

Decide whether you need vhost_traffic_status_dump. If the counters must survive a restart, the dump file is the mechanism, and its location and write frequency are configuration decisions you make once.

Then check who can reach the status location. It serves the statistics and accepts control requests that reset and delete zones, and the README documents no authentication for either.

Editorial conclusion

Adopt nginx-module-vts if you already build Nginx from source and want per-vhost, per-upstream and per-filter counters served straight from shared memory, with the ability to reset or delete a zone through the control endpoint. Do not adopt it if you need a stock distro package, or if you expect the module to answer questions about request latency rather than traffic volume. Before you commit, verify that the Nginx version you run appears in the compatibility list, and decide where vhost_traffic_status_dump writes its file, because that path is what survives a restart.

Frequently asked questions

How do I install nginx-module-vts on Ubuntu or Debian?

The README does not describe a distribution package. Installation is to clone the repository, add --add-module=/path/to/nginx-module-vts to the Nginx build configuration, build the nginx binary and install it, so you need the Nginx source and a toolchain rather than apt.

Does nginx-module-vts expose Prometheus metrics?

No. The module serves its own HTML, JSON and JSONP formats through vhost_traffic_status_display. Related search terms pair it with nginx-vts-exporter, which is a separate process that reads the module's output and republishes it in a metrics format; the module itself does not speak Prometheus.

How do I get per-vhost traffic instead of one total?

Enable vhost_traffic_status_filter_by_host, which splits the counters by the Host header so each virtual host gets its own entry. The README also documents vhost_traffic_status_filter_by_set_key for custom breakdowns such as country, user agent or HTTP status code.

Do the traffic counters survive an Nginx restart?

Only if you configure vhost_traffic_status_dump, which writes the statistics to a file so they can be restored. The README lists maintaining statistics data permanently as a use case, so persistence is a configuration choice rather than default behaviour.

Official sources

  1. Issues
  2. License: BSD-2-Clause
  3. README
  4. Releases
  5. vozlt/nginx-module-vts on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/vozlt-nginx-module-vts.svg)](https://hysenlabs.com/projects/vozlt-nginx-module-vts)