Getting Nginx logs into Victoria-Logs

My goal today: get nginx logs into Victoria-Logs. I’ve already gotten Victoria-Logs running on FreeBSD and replaced syslog with syslog-ng to get TLS

NOTE: This post was originally only about Nginx. I’ve since added general syslog messages to the configuration.

Also, the Adding an nginx proxy in front of Victoria-Labs post might be helpful before proceeding here.

Over the past 48 hours or so, I’ve managed to get Nginx logs flowing from an Nginx host on dev.freshports.org into Victoria-Logs via syslog-ng.

Why syslog-ng? It can do TLS.

In this post:

  • FreeBSD 15.0
  • victoria-logs-1.50.0_2 (running on logs.int.unixathome.org)
  • nginx-1.30.2_2,3 (running on dev.freshports.org)
  • syslog-ng-4.11.0_2 (also running on that host)

First test: can it POST?

My first test, which I should have done ages ago, not this afternoon. This is curl posting into the Victoria-Logs instance.

[13:35 logs dvl ~] % curl -i -X POST "http://logs.int.unixathome.org:9428/insert/jsonline" \
  -H "Content-Type: application/json" \
  -d "{\"_msg\":\"GET /commit.php?category=net-p2p HTTP/1.1\",\"_time\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\",\"_stream\":{\"app\":\"nginx\"},\"status\":\"200\",\"remote_addr\":\"127.0.0.1\",\"body_bytes_sent\":\"1245\",\"request_time\":\"0.015\",\"http_user_agent\":\"CurlLiveTimeClientDVL/1.0\"}"

HTTP/1.1 200 OK
Content-Type: application/json
Vary: Accept-Encoding
X-Server-Hostname: logs.int.unixathome.org
Date: Wed, 17 Jun 2026 13:36:05 GMT
Content-Length: 0

That is a sample post which gave me this within the Victoria-Logs UI:

{
  "_msg": "GET /commit.php?category=net-p2p HTTP/1.1",
  "_stream": "{}",
  "_stream.app": "nginx",
  "_stream_id": "0000000000000000e934a84adb05276890d7f7bfcadabe92",
  "_time": "2026-06-17T13:36:05Z",
  "body_bytes_sent": "1245",
  "http_user_agent": "CurlLiveTimeClientDVL/1.0",
  "remote_addr": "127.0.0.1",
  "request_time": "0.015",
  "status": "200"
}

Which seems accurate.

The UI looks like this:

That sample post
That sample post

Now, let’s convert that into something syslog-ng can use.

Getting raw metrics

This section is just FYI.

At one point, the debugging led me to running this query. Over time, I could see that none of these metrics were changing. That helped me to confirm that data wasn’t getting there. Something else was wrong.

[14:08 logs dvl ~] % curl -ks "https://logs.int.unixathome.org/metrics" | grep vl_rows
vl_rows_dropped_total{reason="debug"} 0
vl_rows_dropped_total{reason="too_many_fields"} 0
vl_rows_ingested_total{type="elasticsearch_bulk"} 1
vl_rows_ingested_total{type="jsonline"} 6922
vl_rows_ingested_total{type="syslog_tcp"} 52692
vl_rows_merged_total{type="storage/inmemory"} 5808
vl_rows_merged_total{type="storage/small"} 202451
vl_rows_merged_total{type="storage/big"} 0
vl_rows_merged_total{type="indexdb/inmemory"} 8417
vl_rows_merged_total{type="indexdb/file"} 35921
vl_rows_dropped_total{reason="too_big_timestamp"} 0
vl_rows_dropped_total{reason="too_small_timestamp"} 0

Nginx configuration

This is the configuration on the nginx instance which will be sending logs to Victoria-Logs.


# this define the format Nginx will save to disk.

log_format victorialogs_json escape=json '{'
    '"_time":"$time_iso8601",'
    '"_msg":"$request",'
    '"status":"$status",'
    '"remote_addr":"$remote_addr",'
    '"body_bytes_sent":"$body_bytes_sent",'
    '"request_time":"$request_time",'
    '"http_user_agent":"$http_user_agent",'
    '"_stream.app":"nginx",'
    '"http_referer":"$http_referer",'
    '"request_method":"$request_method"'
'}';

# the above goes outside the vhost definition.
# the following goes inside the vhost

  # the regular logs, already in place
  error_log     /var/log/nginx/freshports.org-error.log;
  access_log    /var/log/nginx/freshports.org-access.log combined;

  # the addition, which syslog-ng will read
  access_log /var/log/nginx/access_json.log victorialogs_json;

syslog-ng config

This is the syslog-ng config:

source s_nginx_json {
    file("/var/log/nginx/access_json.log" flags(no-parse));
};

destination d_victorialogs_json {
    http(
        url("https://logs.int.unixathome.org:9428/insert/jsonline")
        method("POST")
 
        headers("Content-Type: application/x-ndjson")
        body("{\"_msg\":\"${.json._msg}\",\"_time\":\"${.json._time}\",\"_stream.app\":\"nginx\",\"status\":\"${.json.status}\",\"remote_addr\":\"${.json.remote_addr}\",\"body_bytes_sent\":\"${.json.body_bytes_sent}\",\"http_user_agent\":\"${.json.http_user_agent}\",\"request_time\":\"${.json.request_time}\",\"request_method\":\"${.json.request_method}\"}\n")

        tls(
            peer-verify(yes)
        )

        # LOG LOSS PROTECTION:
        disk-buffer(
            disk-buf-size(1073741824)        # 1 GB max buffer storage size
            reliable(yes)                    # Synchronous disk writes protect against power loss
        )
        workers(2)
    );
};

log {
    source(s_nginx_json);
    parser(p_json);
    destination(d_victorialogs_json);
};

In short, syslog-ng is tailing the log, which is already in JSON, then pulling fields out, and putting them into the fields which Victoria-Logs expect. The data is transmitted via https.

General syslog configuration

For the general syslog messages, not just nginx, these are my settings.

These are the settings I added to /etc/rc.conf so Victoria-Logs will present an incoming TLS connection. Again, this was all on one line.

-syslog.listenAddr.tcp=:29514 -syslog.tls=true \
-syslog.tlsCertFile=/usr/local/etc/ssl/logs.int.unixathome.org.fullchain.cer \
-syslog.tlsKeyFile=/usr/local/etc/ssl/logs.int.unixathome.org.key

On the dev.freshports.org server sending syslog messages to Victoria-Logs, I added these entries to /usr/local/etc/syslog-ng.conf:

destination d_victorialogs_syslog {
    syslog("logs.int.unixathome.org"
        port(29514) 
        transport("tls")
        tls(
            # Path to the FreeBSD master trust store we verified earlier
            ca-file("/usr/local/share/certs/ca-root-nss.crt")
            # Enforce peer validation using the trusted certs
            peer-verify(yes)
        )
    );
};


# Log path linking your sources to VictoriaLogs
log {
    source(src);
    destination(d_victorialogs_syslog);
};

Verifying the TLS

This was the tcpdump command I was using to verify nothing was in clear-text:

[21:05 r730-01 dvl ~] % sudo tcpdump -Ani lo0 host 10.55.0.39 and port 29514
Website Pin Facebook Twitter Myspace Friendfeed Technorati del.icio.us Digg Google StumbleUpon Premium Responsive

Leave a Comment

Scroll to Top