
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/remotereadable 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/remoteto object storage or a second VPS.
At minimum, back up the remote log tree and your rsyslog configs:
/var/log/remote//etc/rsyslog.confand/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 514or6514. - Firewall: check
ufw status verboseon 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 -hand 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.