Skip to content

Check 13: optionally detect an external log rotator targeting the same debug.log #46

Description

@BaumerCrypto

The cadence trap documented in v2.10.0 has a property that makes it worse than most misconfigurations: it leaves no runtime evidence.

When an external rotator shares a size threshold with DEBUG_LOG_MAX_MB, the monitor reaches it first on every crossing and truncates to zero, so logrotate never sees a file large enough to rotate. From the filesystem everything looks correct. The monitor rotates on schedule, debug.log.1 exists with a sane mtime and correct provenance, and logrotate leaves no trace precisely because it never runs. There is nothing to observe.

I originally wanted to detect the harm rather than the config, on the grounds that config-file heuristics are fragile. That argument does not survive this case. There is no harm to detect. The config is the only place the problem exists.

Evidence this is worth doing

Aussie Epic hit it on 2026-07-26 with size 2048M rotate 5 against the default DEBUG_LOG_MAX_MB=2048. His config promised five generations and delivered one, and nothing anywhere reported that. His own question was "will this be compatible with the oracle monitor?", which is exactly the question an operator cannot answer from the outside and the monitor is well placed to answer for them.

Why the naive version is wrong

Checking for /etc/logrotate.d/digibyte is a guess at a filename. It could be digibyted, dgb, an operator's own name, or a stanza sitting directly in /etc/logrotate.conf. Worse, finding a file by that name does not prove it targets this datadir, so it produces both false positives and false negatives.

Match on the path instead. Search for a stanza whose glob resolves to the monitor's actual ${DATADIR}/debug.log. That catches any naming convention and confirms the target in one step.

Proposed scope, tier 1

Presence detection only. Probably 80% of the value for 20% of the work.

  • Linux only. macOS and Windows emit nothing at all, no line.
  • Summary pass only, never the 5-minute path, and no Discord alert. This is a configuration observation, not an incident.
  • Scan /etc/logrotate.d/* and /etc/logrotate.conf for a path glob matching ${DATADIR}/debug.log.
  • Silent-degrade on anything unexpected: logrotate not installed, directory unreadable, permission denied, unparseable file. A check that cannot see the config says nothing rather than guessing.
  • If a match is found and DEBUG_LOG_ROTATE="yes", warn that two tools own the file and point at the cadence section of the hardening guide.
  • If a match is found and DEBUG_LOG_ROTATE="no", emit an info line confirming the clean split. Reassurance, not a warning.

Proposed scope, tier 2

Parse the stanza's directives, which is where the real diagnosis lives. Three distinct situations that deserve three different messages:

External stanza What actually happens Message
size at or below DEBUG_LOG_MAX_MB starved, never fires warn, name both numbers
size well above DEBUG_LOG_MAX_MB genuine backstop info, this is correct
time-based (weekly/daily, no size) both fire, no starvation check compress, warn on the debug.log.1 filename clash if absent

The third row matters more than it looks, because it is the shape of my own recommended example in the hardening guide. Time-based rotation does not starve, it double-owns, and without compress both tools write debug.log.1.

I would ship tier 1 first and only add tier 2 if the presence line proves useful.

Testing this needs

More than the feature itself, which is why it is its own issue rather than a rider on something else:

  • fixture trees under a mocked /etc/logrotate.d
  • glob matching against a real DATADIR, including * and brace patterns
  • include directives in logrotate.conf
  • permission-denied and logrotate-not-installed paths
  • a stanza targeting a different datadir, which must not match on a dual-instance box

Considered and rejected

Warning when rotation is off and no external rotator is found. Sounds symmetrical, but it would false-fire on anyone using a cron truncate (option C in the guide) or shrinkdebugfile=1, neither of which is discoverable this way. Check 13's existing size watchdog already covers the real risk of nobody owning the file.

Open questions

  • Does this need a config toggle, or is a summary-only info line cheap enough to be unconditional? The v2.10.0 chain/label check deliberately shipped without one.
  • Should the line count toward WARNINGS, or stay informational like the DD economy line?

Target

A future minor release. Not urgent: the v2.10.0 docs now cover the trap in all three config templates and the hardening guide, so a reader is warned. This catches the operator who did not read them.

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions