Back to tutorials
Tutorial

Logrotate Tutorial (2026): Rotate and Retain Nginx, Apache, and PHP Logs on a Hosting VPS Without Disk Spikes

Logrotate tutorial for 2026: rotate web logs safely, cap disk use, avoid reload issues, and verify retention on your VPS.

By Anurag Singh
Updated on Sep 11, 2026
Category: Tutorial
Share article
Logrotate Tutorial (2026): Rotate and Retain Nginx, Apache, and PHP Logs on a Hosting VPS Without Disk Spikes

Web logs grow quietly—until they don’t. One noisy bot, a PHP warning loop, or a misconfigured access log can chew through tens of gigabytes overnight. When that happens, a full disk can take your VPS down.

This logrotate tutorial walks you through a hosting-safe setup for Nginx, Apache, and PHP logs. You’ll get predictable retention, compression, and clean reloads.

The goal isn’t “rotate occasionally.” You want clear disk limits and enough history to troubleshoot. You also want rotations that don’t break services or drop log lines.

What you’ll build in this log rotation setup

  • Daily rotation for busy logs, weekly for quieter ones
  • Compression with a delay (so today’s logs stay readable)
  • Safe truncation or reload (depending on daemon behavior)
  • Retention rules that match hosting realities (7–30 days)
  • Quick verification steps and a rollback plan

These steps apply to Ubuntu 24.04/26.04, Debian 12/13, AlmaLinux 9/10, and Rocky Linux 9/10. Paths vary by distro, but the approach stays the same.

If you want a VPS where you can enforce rotation policies (instead of hoping distro defaults behave), start with a HostMyCode VPS. You get root access, predictable storage, and room to tune logging without shared-host limits.

Prerequisites and safety checks (5 minutes)

Before you change anything, check disk headroom. Logrotate won’t rescue a server at 99% usage. Compression can also need brief extra space.

df -h
sudo du -xh /var/log --max-depth=1 | sort -h
sudo du -xh /var/log/nginx /var/log/apache2 2>/dev/null | sort -h

On cPanel servers, you’ll often see large trees under /usr/local/apache/logs. You may also find per-domain logs under /home/*/logs, depending on the setup.

This guide targets OS-level stacks (Nginx/Apache/PHP). These are common on VPS and dedicated servers without WHM.

Understand how logrotate runs on your distro

Most distros run logrotate daily via a systemd timer or cron. Identify which one you use so your tests match production.

Ubuntu/Debian (systemd timer is common)

systemctl list-timers | grep -i logrotate
systemctl status logrotate.timer

AlmaLinux/Rocky (often cron.daily)

ls -l /etc/cron.daily/logrotate
rpm -q logrotate

In both cases, the global config is typically /etc/logrotate.conf. Per-service rules usually live in /etc/logrotate.d/.

Set sane global defaults (and keep them boring)

Edit /etc/logrotate.conf and keep it simple. Put special behavior in per-service files. They’re easier to review and safer to change.

sudo nano /etc/logrotate.conf

A practical baseline for a hosting VPS:

# /etc/logrotate.conf
weekly
rotate 4
create
compress
delaycompress
missingok
notifempty
su root adm

# Packages install per-service rules here
include /etc/logrotate.d
  • weekly + rotate 4 gives you a predictable “about a month” of low-volume logs.
  • compress + delaycompress keeps the newest rotated file readable while older history gets compressed.
  • su root adm avoids permission failures on Debian/Ubuntu, where many logs are root:adm.

Keep the global policy conservative. Use daily and size caps only for logs that actually need them.

Rotate Nginx logs without losing lines

Nginx can reopen log files cleanly. That’s usually better than copytruncate on busy sites. It avoids the small window where writes can land in the wrong place during truncation.

Create or edit /etc/logrotate.d/nginx:

sudo nano /etc/logrotate.d/nginx
/var/log/nginx/*.log {
  daily
  rotate 14
  missingok
  notifempty
  compress
  delaycompress
  dateext
  dateformat -%Y%m%d
  sharedscripts
  postrotate
    [ -s /run/nginx.pid ] && kill -USR1 `cat /run/nginx.pid`
  endscript
}

A few details here pay off later:

  • daily + rotate 14 fits hosting well: enough history without hoarding.
  • dateext makes timelines obvious (“what happened on 2026-09-11?”) and reduces restore confusion.
  • kill -USR1 tells Nginx to reopen its log files immediately.

If your Nginx uses a different PID path, confirm it first:

ps -eo pid,cmd | grep [n]ginx
sudo nginx -T | grep -i pid

Rotate Apache logs safely (and handle both Debian and RHEL paths)

Apache log locations depend on the distro:

  • Debian/Ubuntu: /var/log/apache2/*.log
  • AlmaLinux/Rocky: /var/log/httpd/*log

Use the rule that matches your server. Keeping one file per platform is usually clearer than forcing a “universal” rule.

Debian/Ubuntu Apache logrotate rule

sudo nano /etc/logrotate.d/apache2
/var/log/apache2/*.log {
  daily
  rotate 14
  missingok
  notifempty
  compress
  delaycompress
  dateext
  sharedscripts
  postrotate
    /usr/sbin/apachectl graceful > /dev/null 2>/dev/null || true
  endscript
}

AlmaLinux/Rocky Apache logrotate rule

sudo nano /etc/logrotate.d/httpd
/var/log/httpd/*log {
  daily
  rotate 14
  missingok
  notifempty
  compress
  delaycompress
  dateext
  sharedscripts
  postrotate
    /bin/systemctl reload httpd.service > /dev/null 2>/dev/null || true
  endscript
}

If you run Apache behind Nginx (common in mixed PHP stacks), Apache logs can still grow quickly. Backend traffic stays high even when Nginx serves static files.

If you’re building that layout, this HostMyCode guide is a solid companion: Reverse proxy setup tutorial.

Rotate PHP logs (PHP-FPM, PHP errors, and per-pool files)

PHP logging varies because it depends on your PHP-FPM and app configuration. On a typical VPS you might see:

  • PHP-FPM master log: /var/log/php8.3-fpm.log (path varies)
  • Per-pool slowlog: /var/log/php-fpm/www-slow.log
  • App-level PHP error logs: often under /var/log/ or inside the site tree (usually a bad idea)

Start by inventorying what’s on disk:

sudo find /var/log -maxdepth 2 -type f \( -name '*php*' -o -name '*fpm*' \) -print

Example rule for PHP-FPM logs (systemd reload)

Create /etc/logrotate.d/php-fpm:

sudo nano /etc/logrotate.d/php-fpm
/var/log/php*-fpm*.log /var/log/php-fpm/*.log {
  weekly
  rotate 8
  missingok
  notifempty
  compress
  delaycompress
  dateext
  sharedscripts
  postrotate
    systemctl reload php8.3-fpm.service > /dev/null 2>/dev/null || true
    systemctl reload php8.2-fpm.service > /dev/null 2>/dev/null || true
    systemctl reload php-fpm.service > /dev/null 2>/dev/null || true
  endscript
}

The multiple reload lines are intentional. Across a fleet, PHP versions differ. This “try and continue” pattern keeps one missing unit from breaking the entire rotation run.

If you’re running PHP-FPM on a hosting VPS and want to tune performance too, pair this with: PHP-FPM setup guide tutorial.

Add a size-based safety net for sudden log storms

Daily rotation helps, but a log storm can fill a disk in hours. For the riskiest files, add a size threshold so they rotate early.

Example for Nginx access logs: rotate once the file hits 200MB, even if the daily schedule hasn’t rolled over yet.

/var/log/nginx/access.log {
  daily
  size 200M
  rotate 14
  missingok
  notifempty
  compress
  delaycompress
  dateext
  sharedscripts
  postrotate
    [ -s /run/nginx.pid ] && kill -USR1 `cat /run/nginx.pid`
  endscript
}

Important: size-based rotation is only evaluated when logrotate runs. If logrotate runs once per day, size 200M is checked once per day.

If you need more frequent checks, add an additional timer/cron (outside this tutorial). Or reduce log volume at the source (rate limiting, WAF, bot rules).

On WordPress sites, rate limiting often cuts log volume dramatically during brute-force waves. See: Nginx rate limiting tutorial.

Handle app logs in site directories (and why it’s risky)

A common VPS failure mode: an app writes logs under /var/www/site/storage/logs or wp-content/debug.log. Logrotate won’t manage those by default. They can grow unchecked.

If you must rotate logs inside a site directory, add an explicit rule. Keep permissions tight.

sudo nano /etc/logrotate.d/site-app-logs
/var/www/example.com/current/storage/logs/*.log {
  daily
  rotate 10
  missingok
  notifempty
  compress
  delaycompress
  copytruncate
}

Why copytruncate here? Many apps keep file handles open. They also don’t reopen logs on a signal. In that case, copytruncate is the practical option.

The tradeoff is a small chance you lose a few lines during rotation.

Test your rules safely (dry run, then forced run)

Test before you trust. One broken rule can stop rotation across the server.

1) Dry run (recommended first step)

sudo logrotate -d /etc/logrotate.conf

Focus on three things:

  • Any “error: …” output (fix this first)
  • Which logs logrotate plans to rotate
  • Which postrotate commands it will run

2) Force one run (use during maintenance window)

sudo logrotate -f /etc/logrotate.conf

Then confirm you got new rotated files. Also confirm services still write to the active logs:

sudo ls -lh /var/log/nginx | head
sudo tail -n 20 /var/log/nginx/error.log
sudo systemctl status nginx --no-pager

Verify retention and disk impact (your quick checklist)

  • Retention: count rotated files and confirm older ones disappear after the expected number of runs.
  • Compression: verify you see .gz after the delay period.
  • Permissions: make sure your log readers (often adm) can still read logs.
  • Reload safety: confirm reload/graceful actions didn’t fail and didn’t cause avoidable disruption.
# How big are the logs now?
sudo du -sh /var/log/nginx /var/log/apache2 2>/dev/null

# Are there old logs you expected to be gone?
sudo ls -1 /var/log/nginx | grep -E 'access|error' | tail -n 30

Troubleshooting: common logrotate failures on hosting servers

Problem: “permission denied” during rotation

Add an explicit su line in the rule that’s failing. On Debian/Ubuntu, this often fixes logs owned by root:adm.

/var/log/nginx/*.log {
  su root adm
  ...
}

Problem: rotated logs stop updating (service still running)

This usually means the daemon kept writing to the old file handle. Use the right reopen/reload action:

  • Nginx: USR1
  • Apache: reload/graceful
  • PHP-FPM: reload

Quick confirmation: if lsof shows the service writing to a “(deleted)” file, that’s the issue.

sudo lsof | grep '/var/log/nginx' | grep deleted

Problem: logs rotate too often, too many files

Lower rotate or move low-volume logs back to weekly rotation. For multi-GB access logs, keep daily rotation. Keep compression on, and shorten retention.

Problem: disk still fills up even with rotation

Rotation limits history. It does not reduce log generation. If the server is under attack or misconfigured, fix the cause:

  • Block brute-force and bots (rate limiting, firewall rules)
  • Fix PHP warning loops and plugin errors
  • Disable overly verbose debug logging in production

If you suspect a broader security issue, check the basics (SSH exposure, risky services, open mail relays). This checklist fits well alongside log cleanup work: VPS security audit tutorial.

Optional: keep logs useful for incident response

Short retention feels fine until you need to answer “when did this start?” Keep enough history to spot patterns. Avoid stockpiling junk.

  • Access logs: 7–14 days is usually enough on small-to-mid VPS.
  • Error logs: 14–30 days helps with slow-burn bugs.
  • Security/auth logs: 30+ days is often worth it if you have the disk.

If you run high-traffic workloads and want consistent IO under pressure, move from shared hosting to a VPS or dedicated server. That gives you control over disk and logging policy.

HostMyCode offers managed VPS hosting if you want guardrails without owning every midnight alert.

Summary: the hosting-safe logrotate routine you can keep for years

  • Set calm global defaults in /etc/logrotate.conf.
  • Use service-aware postrotate actions (Nginx reopen, Apache reload, PHP-FPM reload).
  • Rotate noisy logs daily with reasonable retention, and compress with delay.
  • Add a size threshold for “log storm” protection where it makes sense.
  • Test with logrotate -d and validate with lsof and service status.

If you’re running this in production and want predictable performance, storage, and root access for proper log hygiene, start with a HostMyCode VPS. If you’d rather not maintain rotation rules and service reloads yourself, managed VPS hosting is the lower-maintenance option.

If your VPS has ever flipped read-only because /var filled up, log rotation is the simplest permanent fix. HostMyCode gives you a clean base to implement it: a HostMyCode VPS for full control, or managed VPS hosting if you want us to handle the ongoing tuning.

FAQ

Should I use copytruncate for Nginx and Apache?

Prefer a reopen/reload. Use copytruncate only when the process can’t reopen logs, or for app logs with no signal handling.

What retention should I use on a small hosting VPS?

A common baseline is 14 days for access/error logs, and 30 days for auth/security logs if disk allows it. Adjust based on traffic and compliance needs.

Why are my rotated logs not compressing?

If you use delaycompress, the most recent rotated file stays uncompressed until the next rotation. That’s expected.

How do I confirm a service is writing to a deleted log file?

Run sudo lsof | grep deleted. If you see Nginx/Apache holding a deleted log, reload/reopen logs and fix your postrotate action.

Can logrotate help with WordPress debug.log?

Yes, if you explicitly add a rule for that path. Still, the better fix is disabling debug logging on production once you’re done troubleshooting.