newline

Table of Contents

  1. nginx logs: goaccess
  2. Firewall blocks
  3. Checking btmp and auth.log for failed attempts
  4. Next steps

References

Analyzing logs on a public VPS

Shell

September 12, 2026

I run a public VPS that hosts many things, including this blog. Since it’s public, there will inevitably be people and bots trying to figure out how to hack it. I regularly check what’s going on; here’s my write-up of what I checked and what I found.

nginx logs: goaccess

First, I analyzed nginx access logs with GoAccess.

I generated a static HTML report like this:

goaccess access.log* --log-format=COMBINED -o report.html

and opened it in the browser. Here’s what I found. A lot (most) of it can be faked actually, but I think it’s still interesting to look at, probably a good portion of it is not fake.

GoAccess dashboard showing statistics

Between August 26 to and September 9, I got 683,448 requests. Average of around 45k hits per day, 3.5k visitors. without crawlers, 35k and 2k. Most hits were from datacenters in Germany, then France. But even the IP with the most hits was only 4.6% of all, the hits are spread over many IPs. Most visitors are crawlers, then Windows. I even saw some BSD users!

The automated scanners were asking for a few interesting endpoints:

The top referring search engine is duckduckgo, then bing, then google.br, then a few other googles, and even yahoo search. I see a noai.duckduckgo.com, which was looking for my blog posts. It seems I was included in a Netcraft survey, like this one. People from Reddit were looking for my troubleshooting blog posts. Somebody found my blog post about uBlock Origin through Kagi search. I got a hit from verfood.weebly.com and another from aressay.pages.dev, pointing to images from my lecture notes. I need to do something to disable hotlinking…it doesn’t matter that much with a low volume, but still, it’s better to do it anyway. Regarding LLM prompt loops: ChatGPT found one of my troubleshooting blog posts, Copilot found an image from my lecture notes, and some Perplexity user was trying to find API keys, settings, credentials, private keys, etc.

This all tracks with what I see on stats.alex.balgavy.eu. It also seems that bots (and maybe some people) found my RSS-bridge and SearxNG instances.

Firewall blocks

I use the ufw frontend for iptables, so I can see who was trying to access what ports on the actual machine. The IPs are quite evenly distributed, either there are a lot of bots, or it was a lot of VPN sessions (or both). Top ports: 8448 (Matrix/dendrite, from when I was running my own Matrix server), 23 (telnet, 4.5k requests), 22 (SSH, 1.5k requests), port 8080 (web servers, 850 requests), 3389 (RDP, 820), port 5060 (SIP, 512 requests), port 53 (DNS, 505 requests), port 1433 (Microsoft SQL server, 401 requests). On average there were 4.7-4.8k attempts per day.

Checking btmp and auth.log for failed attempts

The btmp file shows who failed to authenticate with the server. Checking it with last -f btmp shows no failed logins. I attribute that to running SSH on a non-standard port. While that does nothing for security, it at least gets rid of all the bots that would otherwise be spamming my VPS with login requests.

Similarly, auth.log does not show anything that I don’t recognize.

Next steps

First, I deleted all logs with shred, and truncated any that were currently open. I’d done my analysis and didn’t need to keep that info around any longer.

Next, I customized the nginx log format. Here’s what I’m logging at the moment:

log_format analysis
    '$remote_addr - $remote_user [$time_iso8601] '
    '"$request" $status $body_bytes_sent '
    'rt=$request_time '
    'urt=$upstream_response_time '
    'ua="$http_user_agent" '
    'ref="$http_referer" '
    'upstream="$upstream_addr" '
    'upstream_status="$upstream_status"';

And I added this block to a new file in /etc/nginx/snippets/, and included it in relevant server definitions to prevent hotlinking (or at least make it harder):

location ~* \.(jpg|jpeg|png|gif|webp|svg)$ {
    valid_referers none blocked alex.balgavy.eu *.alex.balgavy.eu;
    if ($invalid_referer) {
        return 403;
    }
}

Then I changed logrotate settings and set rotate -1 for a lot of things: I don’t want to automatically delete anything, because I look at it and clear it out periodically.