Ahosting Logo
Knowledge Base

How to Manage Logs and Log Rotation on a VPS

Why the disk stays full after you cleared itWhat deleting a file does· removes the name from the directory· not the data, if a process still holds it open· so the space is not returnedWhat to do instead· truncate the file rather than deleting it· or restart the service that holds it open· then fix the rotation so it does not recurCap both storesThe journal and the log files each need a limit. Uncapped logging fills a disk quietly and takeseverything down at once.

Logs are how you find out what happened. They are also the most common reason a VPS runs out of disk, and a full disk stops everything at once, in a way whose error messages never mention disk.

Both facts point at the same job: keep the logs, keep them from growing without limit.

Where they are

On a modern system, two places.

The systemd journal holds most service and kernel messages, read with journalctl.

Files under /var/log hold what individual applications write directly: the web server's access and error logs, mail logs, and anything an application manages itself.

Knowing which you are looking at matters, because they are rotated by different mechanisms and a configuration that limits one does nothing for the other.

Reading the journal

journalctl -u nginx -n 100 --no-pager
journalctl -u nginx -f
journalctl --since "1 hour ago" -p err

The first shows the last hundred lines for one service, the second follows live, the third shows errors from every service in the last hour.

That last one is the most useful command here. When something broke and you do not know what, it is the fastest way to find out: far quicker than guessing which service to check.

Cap the journal

The journal grows until it hits its own limit, and on some systems that limit is a share of the disk large enough to matter on a small VPS.

In /etc/systemd/journald.conf:

SystemMaxUse=500M

Then restart journald. To reclaim space immediately:

journalctl --vacuum-size=200M
journalctl --vacuum-time=14d

Check the current usage with journalctl --disk-usage. On a server nobody has configured, several gigabytes is common.

logrotate handles the files

Everything under /var/log that is not the journal is rotated by logrotate: the current file is renamed, a new one started, old ones compressed, and the oldest deleted.

Distribution packages install sensible configurations for their own logs. What is not covered is anything you installed by hand or an application writing its own log, and that is exactly what fills a disk.

A config for an application log:

/var/log/myapp/*.log {
 weekly
 rotate 8
 compress
 missingok
 notifempty
 copytruncate
}

copytruncate copies the file and truncates the original, which is what you need when the application holds the file open and does not know how to reopen it. Without it, rotation leaves the application writing to a file that no longer has a name, and the log silently stops.

Test the config, do not wait for it

logrotate -d /etc/logrotate.d/myapp

Debug mode says what it would do without doing it. A rotation config that has never been tested usually has a path wrong, and it fails silently: the log keeps growing and nothing reports it.

Force a real run once to confirm:

logrotate -f /etc/logrotate.d/myapp

Find what is actually large

When disk is filling, this is the command:

du -sh /var/log/* | sort -h | tail -20

Three things account for most of it. A log nothing rotates. A debug setting left on in an application after troubleshooting. And an application logging every request at a volume nobody expected.

That middle one is worth checking explicitly: debug logging left enabled after a support call is a very common cause, and turning it off reclaims the space permanently rather than rotating it forever.

Deleting a log is not enough

The trap that makes a disk stay full after you cleared it.

Deleting a file an application has open removes the name, not the data. The space is not returned until the process closes the file, and the application carries on writing into nothing.

Truncate instead:

truncate -s 0 /var/log/myapp/big.log

That empties the file while the application keeps writing to it normally. Then fix the rotation so it does not happen again.

How long to keep them

Long enough to investigate something reported late, which is longer than most people set.

A compromise is often discovered a fortnight after it happened, and logs rotated away at seven days mean the entry point cannot be found, cleaning up a hacked site depends entirely on having them.

Four weeks of web and auth logs is a reasonable default. Compressed logs are small, and the disk is cheaper than the investigation you cannot do.

Get them off the machine

Logs on a server tell you nothing about the failure that took the server down, and an attacker's first act is often to clear them.

For anything that matters, ship logs to a second machine or a log service. Then a compromised server cannot erase the record of the compromise, and a server that will not boot still has its last hours available. Monitoring server health walks through the alerting side.

Alert on disk before it fills

The whole problem is preventable with one alert at 80%.

A full disk breaks mail, uploads, database writes and sessions simultaneously, and none of the errors say why. An alert a day earlier turns that into a five-minute cleanup. Managing VPS resources goes into setting it up.

Query the journal instead of reading it

Following a log and waiting for something to appear is the slowest way to use it, and the journal can be asked direct questions.

journalctl -u nginx --since '2 hours ago' -p err --no-pager
journalctl --since '2026-08-20 14:00' --until '2026-08-20 14:10'
journalctl -b -1 -p warning --no-pager | tail -40
journalctl -f -u nginx -u php-fpm

The first narrows to one service, a period and a severity at once. The second is what you use when somebody reports a problem at a specific time, which is the most common request you will get.

The third reads the previous boot, which is the only way to investigate why a machine restarted, since the current boot has no record of it. And the last follows several services together, so a request failing across two of them appears in order.

Rotation can lose the very lines you need

The two ways of rotating a file behave differently under load, and one of them drops records.

Creating a new file and signalling the process to reopen it is clean, and it requires the process to support the signal. Copying the contents and truncating the original avoids that requirement and leaves a small window during which anything written is lost.

grep -rn 'copytruncate\|create\|postrotate' /etc/logrotate.d/ | head
logrotate -d /etc/logrotate.conf 2>&1 | grep -A2 'considering log' | head -20

The debug run shows what would happen without doing it. Prefer the signal based approach wherever the service supports it, and keep the copy and truncate method for the software that does not.

Check what you are writing down

Logs are frequently readable by more people than the data they contain should be, and nobody audits them.

grep -riE 'password=|token=|api[_-]?key=|authorization: ' ~/logs/ 2>/dev/null | head
awk '{print $7}' ~/logs/example.com | grep -E '\?(.*)(token|key|password|email)=' | head

Anything sensitive placed in a query string is recorded in the access log by design, and stays there for the retention period, in backups, and in any copy shipped elsewhere.

The fix is at the application rather than at the log. Move those values into the request body or a header, and where a third party sends them to you in a query string, ask them to change it. Deleting the log lines is a one time cleanup of a problem that keeps producing more.

Verbose logging costs more than disk

Debug level output left on after an investigation is a performance problem, not only a storage one.

Every line is a write, and on a busy service those writes are synchronous often enough to matter. A site that became slower for no apparent reason after a troubleshooting session is a recognisable pattern.

ls -la --time-style=+%F ~/logs/ | sort -k5 -n | tail -5
find /var/log -type f -mmin -60 -size +50M 2>/dev/null

A log file growing tens of megabytes an hour is either a fault repeating thousands of times or a level nobody turned back down. Both are worth an immediate look, and the second is the more embarrassing to discover months later. Managing VPS resources goes into watching the effect.