Tutorials

logrotate: Rotate Logs Before Your Server Disk Fills Up

Server disk is full and you don't know which log is to blame? Practical logrotate configuration, the difference between copytruncate and create, and testing without waiting a week.

Tutorials

The server disk is locked at 98 percent, the site won't come up, and when you run df -h you see that /var is full. Then you run du -sh /var/log/* | sort -h and a 12-gigabyte file is staring you in the face: syslog or access.log that no one has touched in months. This is exactly where logrotate should have been working and wasn't.

logrotate is a command-line tool that rotates logs based on time or size, compresses them, and deletes the old ones. It's pre-installed on almost every Linux distribution and runs via cron or a systemd timer. The problem is usually not the tool itself; it's a configuration that either doesn't exist, is written incorrectly, or a new log file was created outside the default paths and no one wrote a rule for it.

Why logrotate isn't running on your server

Before making any changes, figure out why rotation hasn't happened. I've seen three common causes in practice:

  • The logrotate service is disabled. Check the systemd timer status with systemctl status logrotate.timer. If it says inactive (dead), it means it has never run.
  • The log file is outside the standard paths. For example, an application that writes to /home/deploy/app/logs/app.log and there's no file in /etc/logrotate.d/ for it.
  • The configuration is broken and logrotate silently skips it. Run it in debug mode with logrotate -d /etc/logrotate.conf to see which file it's ignoring.

The debug mode output usually gives you the answer itself. If you see a line like error: skipping "/var/log/app.log" because parent directory has insecure permissions, the problem is the directory permissions, not the configuration. By default, logrotate is sensitive to directories where the group or others have write permission and skips rotation for them.

A configuration file that actually works

Suppose your application writes to /var/log/myapp/app.log. Create a new file at /etc/logrotate.d/myapp:

/var/log/myapp/app.log {
    daily
    rotate 14
    size 100M
    compress
    delaycompress
    missingok
    notifempty
    create 0640 www-data adm
    sharedscripts
    postrotate
        systemctl reload myapp > /dev/null 2>&1 || true
    endscript
}

A point many people miss: when you set both daily and size, the size condition wins. That means even if the file is only an hour old, it will be rotated as soon as it reaches 100 megabytes. This behavior is stated explicitly in the man page for logrotate.conf, but in practice it gets ignored.

The line create 0640 www-data adm is also important. If you give the new file the wrong owner and group, after the first rotation the application can no longer write to the file and the logs silently stop. This silent error is the worst kind of failure because no one notices it until days later.

copytruncate versus create: which should I choose

This is where the most mistakes happen. There are two methods for rotation, and choosing between them depends on the application's behavior, not on preference.

MethodHow it worksSuitable forCost
createThe old file is renamed, a new file is createdServices that reopen the file on a reload signal (Nginx, Apache, syslog)Requires postrotate and reload
copytruncateThe file contents are copied, then the original file is emptiedApplications that keep the file open and don't understand signalsA window of data loss at the moment of copying

If your application keeps the log file open and has no way to reload, copytruncate is the right choice. But know its cost: between the moment logrotate copies the contents and the moment it truncates the file, any line the application writes is lost. For transactional logs this isn't acceptable; for debug logs it usually is.

In 90 percent of the cases where I've configured my own server, I've chosen create because the services understand the reload signal and no data is lost. I only go for copytruncate when the application is a binary and its code isn't in my hands.

Here's where they make a mistake: many people put copytruncate and create together in the same block. logrotate doesn't reject this combination, but the result is unpredictable; sometimes a new file is created and the application keeps writing to the renamed file. The sign is this: the file app.log.1 keeps growing and app.log always stays empty. If you see this, remove one of the two options.

Testing the configuration without waiting a week

Waiting until tomorrow morning to see whether rotation worked is a waste of time. With -f you can force the rotation to run:

logrotate -vf /etc/logrotate.d/myapp

The -v flag prints every decision logrotate makes, and -f causes the rotation to happen regardless of the time condition. After running it, run ls -lh /var/log/myapp/ and see whether the file app.log.1 was created. If you've set delaycompress, the .1 file isn't compressed yet and .2.gz exists.

A practical tip: before testing on a production server, don't empty the log file with truncate -s 0. If the application has kept the file open, its internal offset gets messed up and it won't write anything until the next restart. For testing, create an artificial log file in a temporary path and try the configuration on it.

If you're working on shared or managed hosting and don't have root access, logrotate is usually already configured for the main services and you only need to manage your own application's logs from within the control panel. On WordPress hosting this is done through the panel's tools and there's no need to touch /etc/logrotate.d/.

When you send logs somewhere else

If you use rsyslog or journald, logrotate doesn't work on journal files. For journald you should use journalctl --vacuum-size=500M or set SystemMaxUse= in /etc/systemd/journald.conf. Many people don't know this difference and spend hours looking for a logrotate configuration file that doesn't exist.

For Nginx and Apache logs, the distribution's default configuration is usually enough, but if you have many domains on one server, each domain has a separate log file and you need to make sure the wildcard pattern is written correctly. A line like /var/log/nginx/*.log covers all of them, but if you add a new domain later, it's included automatically. This is better than writing each path by hand.

If you're not sure which service is responsible for logging, ServerNet's documentation and knowledge base lists the default paths for each service. Also, for quickly checking file sizes and access, the free tools can help.

Frequently asked questions

Why isn't logrotate rotating my log file?

There are three common causes: the systemd timer is disabled, the log file is in a non-standard path and no configuration has been written for it, or the parent directory permissions are inappropriate and logrotate skips the rotation. With logrotate -d /etc/logrotate.conf in debug mode, see exactly which file was skipped and why.

What's the difference between copytruncate and create in logrotate?

In create, the old file is renamed and a new file is created; the application must reopen the file with a reload signal. In copytruncate, the contents are copied and the original file is emptied; the application doesn't need a reload, but a few lines may be lost at the moment of copying.

How do I test logrotate without waiting until tomorrow?

With the command logrotate -vf /etc/logrotate.d/yourconfig, force the rotation to run with full output. The -f flag ignores the time condition and -v prints every decision. After running it, confirm the rotated file exists with ls -lh.

Does logrotate work on journald too?

No. journald keeps logs in a binary format and logrotate can't rotate them. To limit the journal size you should use journalctl --vacuum-size or set SystemMaxUse in the file /etc/systemd/journald.conf.

Run logrotate -d /etc/logrotate.conf once today and read its output. If you see an error, you've just solved the disk-filling problem for the coming months right there.

ServerNet Support

ServerNet engineering & editorial team — specialists in infrastructure, networking and web hosting.

WordPress Hosting
Share:

Comments 0

No comments yet — be the first!

Leave a comment

Related service

WordPress Hosting

A purpose-built WordPress stack on LiteSpeed Enterprise and NVMe — auto-install, secure updates, staging and caching that keeps you on top of Google.