From 74c795eaa99fb8b1c8c9efcf932a93c8d62a446b Mon Sep 17 00:00:00 2001 From: Guillermo Pages Date: Wed, 8 Jul 2026 21:13:53 +0200 Subject: [PATCH] docs: Logger daily rotation requires a PHP-user-writable log directory rename() needs write permission on the DIRECTORY; without it rotation fails silently while appends succeed, growing log.txt unbounded. Documents the correct ownership/mode, the health check, and the Nov 2021 - Jul 2026 production incident (945MB log.txt filled the 15GB disk and truncated a Solr reindex). Also notes that these logs contain raw authenticate() passwords and must be treated as secrets. --- README.md | 54 +++++++++++++++++++++++++++++++++++++ src/Utils/Logger/Logger.php | 6 +++++ 2 files changed, 60 insertions(+) diff --git a/README.md b/README.md index e69de29..623cef7 100644 --- a/README.md +++ b/README.md @@ -0,0 +1,54 @@ +# php-bsrutils (`bsr/utils`) + +Shared utilities for the Callio API family: `Configuration`, `Logger`, +`FileSystem`, `WhichEnv`. Consumed by `php-callioapi`, `bsr/webservice`, +`bsr/db`. + +## Logger + +Request/diagnostic logger writing plain-text lines to the file configured as +`log.file` (see `Configuration`). Used by `bsr/webservice` to log every API +call as: + +``` + - [] - - - () +``` + +### Built-in daily rotation — directory must be writable by the PHP user + +The Logger rotates its own file: on the first write after midnight it renames +`log.txt` → `log.txt.2` (shifting older files up) and keeps roughly ten days +(`log.txt.2` … `log.txt.9`; higher numbers are deleted). There is **no +logrotate involvement** — do not add a logrotate entry for these files, it +would race the built-in rotation. + +**Critical operational requirement:** `rename()` needs *write permission on +the log directory*, not just the file. The PHP process (typically `www-data`) +can happily keep appending to a `log.txt` it owns while every rotation +attempt silently fails, because the directory denies it — PHP's `rename()` +warning is not surfaced anywhere. + +Known real-world failure (production `callioapi`, Nov 2021 → Jul 2026): the +log directory was owned `guillermo:users` mode `755`, so `www-data` could not +rename. Rotation died silently and `log.txt` grew to ~945 MB, eventually +filling the 15 GB disk and truncating a Solr reindex. The rotated-file dates +freeze at the moment the directory permissions broke — that is the telltale +sign to look for. + +Correct setup (matches the vhosts where rotation works): + +```sh +chown :www-data /var/www//log +chmod g+w /var/www//log +``` + +Health check: `ls /var/www//log` — if `log.txt.2`'s mtime is older +than yesterday while `log.txt` keeps growing, rotation is broken; check the +directory permissions first. + +### Security note + +`bsr/webservice` logs every API call **with raw parameters**, which for +`authenticate(user, password)` means plaintext passwords end up in these +files. Treat the log directory as secret-bearing: never make it +world-readable, and scrub/redact before copying logs elsewhere. diff --git a/src/Utils/Logger/Logger.php b/src/Utils/Logger/Logger.php index 9f8a2e9..c9c7ae1 100644 --- a/src/Utils/Logger/Logger.php +++ b/src/Utils/Logger/Logger.php @@ -200,6 +200,12 @@ class Logger { } /** + * WARNING: rename() requires WRITE permission on the log DIRECTORY (not + * the file). When the PHP user lacks it, every rename here fails silently + * and log.txt grows unbounded while appends keep working — see README + * "Built-in daily rotation" for the required directory ownership/mode + * and the 2021-2026 production incident this caused. + * * @param array $files */ private static function renameExsitingLogFilesToHigherCounts($files)