Back to tutorials
Tutorial

VPS log auditing tutorial (2026): Set up centralized logs with rsyslog + logrotate on Ubuntu for faster incident response

VPS log auditing tutorial (2026): centralize syslogs with rsyslog, rotate safely, and speed up security investigations on Ubuntu.

By Anurag Singh
Updated on Jun 10, 2026
Category: Tutorial
Share article
VPS log auditing tutorial (2026): Set up centralized logs with rsyslog + logrotate on Ubuntu for faster incident response

Your VPS already records every login attempt, service crash, and strange request. The problem is access. Evidence is split across files, rotated too quickly, or stuck on the same machine that might be down (or compromised). This VPS log auditing tutorial shows you how to centralize logs on a dedicated “log collector” VPS with rsyslog, secure transport, and manage retention with logrotate on Ubuntu.

Once it’s in place, incidents get easier. When someone reports “my site was hacked” or “emails disappeared,” you can respond with timestamps and traceable events—not guesses.

What you’ll build (and why it matters on a hosting VPS)

By the end, you’ll have:

  • A log collector VPS receiving logs over TCP (optionally TLS) from one or more web/mail/app VPS nodes.
  • Per-host log directories like /var/log/remote/web-01/ so investigations don’t turn into grep chaos.
  • Rotation and retention tuned for hosting reality (busy Nginx, PHP-FPM, Postfix, cron, auth).
  • A short “audit playbook” for common incidents: brute-force, privilege escalation, web 404 spikes, mail abuse.

If you manage customer sites, reseller accounts, or multiple environments, centralized logs cut your “time to answers.”

They also reduce the odds that critical evidence disappears during rotation. The same is true during an outage or compromise.

Prerequisites and quick sizing checklist

You need two Ubuntu servers (24.04 LTS is a sensible default in 2026):

  • Collector: a small VPS dedicated to logs.
  • Client(s): your web/mail/app VPS nodes forwarding logs.

Disk sizing depends on what you ship. For a typical WordPress VPS with moderate traffic, plan roughly 1–3 GB/day if you also forward verbose web logs.

If you forward only system/auth/mail logs, it’s often much lower.

  • Start point: 2 vCPU / 4 GB RAM / 80–160 GB NVMe for the collector for a handful of servers.
  • Filesystem: XFS or ext4 is fine; use a separate volume/mount if you expect growth.

If you’d rather not babysit OS updates and baseline security hardening, managed VPS hosting from HostMyCode fits well for both log collectors and production nodes.

Step 1 — Provision a log collector VPS and create a storage layout

On the collector, update packages and install rsyslog:

sudo apt update
sudo apt -y upgrade
sudo apt -y install rsyslog logrotate

Create a directory structure where each client gets its own path.

This separation keeps timelines clean and audits fast.

sudo mkdir -p /var/log/remote
sudo chown syslog:adm /var/log/remote
sudo chmod 0750 /var/log/remote

Make sure rsyslog runs:

systemctl status rsyslog --no-pager

Step 2 — Configure rsyslog to receive remote logs (TCP, then optional TLS)

On Ubuntu, rsyslog config usually lives in /etc/rsyslog.conf plus drop-ins under /etc/rsyslog.d/.

Create a dedicated receiver config:

sudo nano /etc/rsyslog.d/10-receiver.conf

Paste the following (TCP 514). It sorts logs into per-host folders based on the sender hostname.

# Enable TCP syslog reception
module(load="imtcp")
input(type="imtcp" port="514")

# Template: /var/log/remote/<hostname>/<program>.log
template(name="RemotePerHost" type="string"
  string="/var/log/remote/%HOSTNAME%/%PROGRAMNAME%.log")

# Store everything received remotely
if ($fromhost-ip != "127.0.0.1" and $fromhost-ip != "::1") then {
  action(type="omfile" dynaFile="RemotePerHost" createDirs="on" dirCreateMode="0750" fileCreateMode="0640")
  stop
}

Restart rsyslog and confirm it listens:

sudo systemctl restart rsyslog
sudo ss -lntp | grep ':514'

Security note: TCP beats UDP for reliability, but it’s still plaintext.

If traffic stays inside a private network/VPC, plain TCP may be acceptable. If logs cross the public internet, enable TLS (next step) and restrict by firewall.

Step 3 — Lock down the collector firewall to only accept known senders

Allow TCP/514 only from your VPS IPs. Use UFW or iptables; here’s UFW on the collector:

sudo ufw allow OpenSSH
sudo ufw allow from 203.0.113.10 to any port 514 proto tcp
sudo ufw allow from 203.0.113.11 to any port 514 proto tcp
sudo ufw enable
sudo ufw status verbose

If you prefer an iptables ruleset that’s easier to scale and version, adapt this: production web-hosting iptables ruleset.

Step 4 — (Recommended) Add TLS to rsyslog for internet-facing forwarding

If clients forward logs over the public internet, encrypt them.

Log streams often include usernames, URLs, and mailbox identifiers. You don’t want that in plaintext.

Install GnuTLS support:

sudo apt -y install rsyslog-gnutls

Create a simple internal CA and server cert. For small fleets, this is usually enough.

On the collector:

sudo mkdir -p /etc/rsyslog/keys
cd /etc/rsyslog/keys

# CA key + cert
sudo openssl genrsa -out ca.key 4096
sudo openssl req -x509 -new -nodes -key ca.key -sha256 -days 3650 \
  -subj "/C=US/O=HostMyCode-Labs/CN=rsyslog-ca" -out ca.crt

# Server key + CSR + cert
sudo openssl genrsa -out server.key 4096
sudo openssl req -new -key server.key \
  -subj "/C=US/O=HostMyCode-Labs/CN=log-collector" -out server.csr
sudo openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial \
  -out server.crt -days 1825 -sha256

Permissions matter:

sudo chown root:syslog /etc/rsyslog/keys/server.key
sudo chmod 0640 /etc/rsyslog/keys/server.key
sudo chmod 0644 /etc/rsyslog/keys/ca.crt /etc/rsyslog/keys/server.crt

Now configure rsyslog to listen on a TLS port (commonly 6514):

sudo nano /etc/rsyslog.d/11-tls-receiver.conf
module(load="imtcp")
module(load="gtls")

global(
  DefaultNetstreamDriver="gtls"
  DefaultNetstreamDriverCAFile="/etc/rsyslog/keys/ca.crt"
  DefaultNetstreamDriverCertFile="/etc/rsyslog/keys/server.crt"
  DefaultNetstreamDriverKeyFile="/etc/rsyslog/keys/server.key"
)

# TLS syslog listener
input(type="imtcp" port="6514" StreamDriver="gtls" StreamDriverMode="1" StreamDriverAuthMode="anon")

AuthMode note: anon encrypts transport but doesn’t require client certificates.

If you want stronger identity checks, move to mutual TLS (x509/name) later.

Restart and open the firewall only to known senders:

sudo systemctl restart rsyslog
sudo ufw allow from 203.0.113.10 to any port 6514 proto tcp
sudo ufw allow from 203.0.113.11 to any port 6514 proto tcp

Step 5 — Configure a client VPS to forward logs to the collector

On each client VPS (Ubuntu), install rsyslog if it isn’t already present:

sudo apt update
sudo apt -y install rsyslog

Create a forwarding config. If you’re using plain TCP/514:

sudo nano /etc/rsyslog.d/60-forward-to-collector.conf
# Forward everything to collector over TCP
*.* action(type="omfwd" target="LOG_COLLECTOR_IP" port="514" protocol="tcp"
  action.resumeRetryCount="-1"
  queue.type="linkedList" queue.size="10000")

If you enabled TLS (recommended) on 6514, copy the CA cert from the collector to the client:

sudo mkdir -p /etc/rsyslog/keys
# copy ca.crt securely (scp from collector or your secret store)
sudo nano /etc/rsyslog/keys/ca.crt
sudo chmod 0644 /etc/rsyslog/keys/ca.crt

Then use TLS forwarding:

sudo nano /etc/rsyslog.d/60-forward-to-collector.conf
module(load="gtls")

global(
  DefaultNetstreamDriver="gtls"
  DefaultNetstreamDriverCAFile="/etc/rsyslog/keys/ca.crt"
)

*.* action(type="omfwd" target="LOG_COLLECTOR_IP" port="6514" protocol="tcp"
  StreamDriver="gtls" StreamDriverMode="1" StreamDriverAuthMode="anon"
  action.resumeRetryCount="-1"
  queue.type="linkedList" queue.size="10000")

Restart rsyslog on the client:

sudo systemctl restart rsyslog

Generate a test event:

logger -p authpriv.notice "rsyslog forward test from $(hostname -f)"

On the collector, you should see a new file appear under the client hostname:

sudo ls -la /var/log/remote
sudo tail -n 50 /var/log/remote/<client-hostname>/<something>.log

Step 6 — Don’t drown in noise: filter what you forward (practical hosting defaults)

Forwarding *.* works for a tiny setup. It grows fast once you include access logs or chatty services.

A workable default for hosting looks like this:

  • Always forward auth, syslog, mail, daemon, kern (high signal).
  • Ship web access logs only during investigations, or keep them local and forward summaries.

Example: forward only key facilities (client-side):

# /etc/rsyslog.d/60-forward-to-collector.conf
auth,authpriv.*  action(type="omfwd" target="LOG_COLLECTOR_IP" port="6514" protocol="tcp" StreamDriver="gtls" StreamDriverMode="1" StreamDriverAuthMode="anon")
mail.*           action(type="omfwd" target="LOG_COLLECTOR_IP" port="6514" protocol="tcp" StreamDriver="gtls" StreamDriverMode="1" StreamDriverAuthMode="anon")
daemon.*         action(type="omfwd" target="LOG_COLLECTOR_IP" port="6514" protocol="tcp" StreamDriver="gtls" StreamDriverMode="1" StreamDriverAuthMode="anon")
kern.*           action(type="omfwd" target="LOG_COLLECTOR_IP" port="6514" protocol="tcp" StreamDriver="gtls" StreamDriverMode="1" StreamDriverAuthMode="anon")
*.warning        action(type="omfwd" target="LOG_COLLECTOR_IP" port="6514" protocol="tcp" StreamDriver="gtls" StreamDriverMode="1" StreamDriverAuthMode="anon")

If SSH brute-force and WordPress credential stuffing are your daily headaches, pair logging with active blocking.

HostMyCode’s Fail2Ban setup tutorial is a clean baseline that won’t trip up normal admin access.

Step 7 — Configure logrotate on the collector for remote logs

Rsyslog creates files dynamically. Without rotation, a single auth.log-style file per program can quietly grow into a disk outage.

Create a logrotate rule for your remote directory:

sudo nano /etc/logrotate.d/rsyslog-remote
/var/log/remote/*/*.log {
  daily
  rotate 30
  compress
  delaycompress
  missingok
  notifempty
  su syslog adm
  create 0640 syslog adm
  sharedscripts
  postrotate
    systemctl kill -s HUP rsyslog.service >/dev/null 2>&1 || true
  endscript
}

This keeps 30 days by default. Many hosting teams land on 30–90 days, depending on storage and any compliance requirements.

Test rotation in “dry run” mode first:

sudo logrotate -d /etc/logrotate.d/rsyslog-remote

Then force a rotation once to confirm permissions and directory patterns:

sudo logrotate -f /etc/logrotate.d/rsyslog-remote

Step 8 — Basic integrity: restrict access and monitor disk growth

Central logs are sensitive. Treat them like you treat SSH keys.

  • Keep /var/log/remote readable only by admins (adm) and rsyslog (syslog).
  • Limit SSH access to the collector. Use keys and allowlists.
  • Track disk usage and alert early (70%, 85%, 95%).

Quick disk watch commands you’ll actually use:

df -h
sudo du -h --max-depth=2 /var/log/remote | sort -h | tail -n 20

If you want lightweight daily summaries without building a full monitoring stack, set up Logwatch.

HostMyCode has a solid walk-through: Logwatch daily security and service reports.

Step 9 — Fast audit playbook: common incidents and the exact greps

This is where centralization earns its keep. Run these checks on the collector for one host. Or repeat them across many.

Audit 1: SSH brute-force and suspicious logins

Start with repeated failures. Then check whether the same IP later logged in successfully.

# Failures
sudo grep -R "Failed password" -n /var/log/remote/web-01/ | tail -n 50

# Success logins
sudo grep -R "Accepted" -n /var/log/remote/web-01/ | tail -n 50

# Quick IP tally (adjust path as needed)
sudo grep -R "Failed password" /var/log/remote/web-01/ \
  | awk '{print $(NF-3)}' | sort | uniq -c | sort -nr | head

If you want a stronger SSH stance than “grep after the fact,” stick to your hardening baseline.

For an opinionated checklist with allowlists and audit logs, use: secure SSH access on a hosting VPS.

Audit 2: Web spikes that look like bot scans

If you forward Nginx/Apache access logs, search for endpoint patterns and user agents.

If you don’t forward access logs, use system logs to line up load spikes with restarts and error bursts.

# Example if you forward nginx access logs as programname nginx
sudo grep -R "wp-login.php" /var/log/remote/web-01/nginx*.log | head
sudo grep -R "xmlrpc.php" /var/log/remote/web-01/nginx*.log | head

For mitigation, rate limiting works well on login endpoints and noisy APIs.

Keep it as a targeted control alongside logging, not tangled into it.

Audit 3: “My emails are stuck” or “the server is sending spam”

Mail incidents often trace back to a compromised script or weak SMTP credentials.

With centralized logs, you can correlate auth failures, queue growth, and bounce patterns without bouncing between servers.

# Find SASL auth failures (common with brute-force SMTP)
sudo grep -R "SASL" /var/log/remote/mail-01/ | tail -n 100

# Look for a sudden flood from one sender
sudo grep -R "from=<" /var/log/remote/mail-01/ | awk -F'from=<' '{print $2}' | awk -F'>' '{print $1}' \
  | sort | uniq -c | sort -nr | head

If you’re troubleshooting Postfix queue behavior, this pairs well with: fix a stuck Postfix mail queue.

Audit 4: Sudden restarts, crashes, or OOM kills

OOM kills show up often on small VPS plans or during unexpected traffic spikes.

On the collector:

sudo grep -R "Out of memory" /var/log/remote/web-01/ | tail -n 50
sudo grep -R "Killed process" /var/log/remote/web-01/ | tail -n 50

If you want a structured “why is this site slow?” workflow, combine logs with basic system metrics: diagnose slow website response on Ubuntu.

Step 10 — Back up the collector (because logs are evidence)

A log collector without backups turns into a single point of regret. Two approaches usually make sense:

  • Snapshot-based (fast restore): take daily VPS snapshots plus offsite copies of /var/log/remote.
  • File-based (portable): archive /var/log/remote to object storage or a second VPS.

At minimum, back up the remote log tree and your rsyslog configs:

  • /var/log/remote/
  • /etc/rsyslog.conf and /etc/rsyslog.d/
  • /etc/rsyslog/keys/ (if you use TLS)

If you want a routine that includes restore drills, adapt: automated snapshots, offsite copies, and restore tests.

Troubleshooting: quick fixes when logs don’t arrive

  • No listener: on collector, confirm ss -lntp | grep 514 or 6514.
  • Firewall: check ufw status verbose on collector and client egress rules.
  • Hostname mismatch: remote directory is based on %HOSTNAME%. Confirm client hostname: hostnamectl.
  • TLS issues: verify the CA file path and permissions on the client; check journalctl -u rsyslog -n 200.
  • Disk full: rsyslog may stop writing. Check df -h and rotate sooner.

Rsyslog is noisy in the journal when something breaks. On either side, this command usually points at the real cause:

sudo journalctl -u rsyslog --since "30 min ago" --no-pager

VPS log auditing tutorial: production-ready centralized logging in 20 minutes

  • Collector: rsyslog installed; receives on TCP/514 or TLS/6514
  • Collector: firewall allows only known sender IPs
  • Collector: per-host directory template under /var/log/remote
  • Collector: logrotate rule for /var/log/remote/*/*.log
  • Client: forwarding configured with retry queue enabled
  • Test event sent with logger, verified on collector
  • Disk growth monitored; backups enabled for /var/log/remote

If you run multiple sites or reseller workloads, a dedicated log collector is one of the highest-ROI changes you can make. It speeds up troubleshooting and gives you clean evidence during security work. Start with a HostMyCode VPS for the collector, or choose managed VPS hosting if you want the OS baseline maintained while you focus on day-to-day operations.

FAQ

Do I need a separate VPS for centralized logging?

For single-server setups, no. For anything you expect to restore, investigate, or audit, yes. If the web VPS fails or gets compromised, you still have the logs somewhere else.

Should I forward Nginx/Apache access logs too?

Only if you have a reason. They grow fast. Many teams forward system/auth/mail logs all the time, then forward access logs temporarily during incident windows.

Is rsyslog good enough in 2026, or should I use a full SIEM?

Rsyslog covers small fleets and straightforward audit questions. A SIEM helps when you need dashboards, correlation, and longer retention at scale. Centralize first either way; it’s the foundation.

How long should I retain logs for a hosting business?

Common baselines are 30–90 days. Pick a number you can store and back up reliably. If you have contractual or regulatory requirements, let those set the floor.

What’s the most common mistake?

Leaving TCP/514 open to the world. Your collector will get spammed. Restrict by IP, and use TLS if traffic crosses the public internet.

Summary

Centralized logging doesn’t require a heavyweight stack to be useful. With rsyslog listening on a locked-down port, a per-host directory template, and sensible logrotate retention, you get faster audits and clearer post-incident timelines.

If you’re growing past a single server, keep the collector separate from production workloads. A reliable HostMyCode VPS is an easy place to start, and it keeps your evidence off the machine you’re actively investigating.