02.06 Log Rotation and Disk Management
SimpleRisk's logs land in three places — the file at /var/log/simplerisk/simplerisk.log, the audit_log database table, and the user_login_history database table. Here's how to manage each over time, the disk-usage patterns to watch, and the log-rotation conventions that keep them sustainable.
Why this matters
Three load-bearing categories of operational data accumulate in SimpleRisk over time: the file-based debug log, the database audit log, and the user-login history. Each grows continuously during normal operation, and each eventually fills disk if not managed. The growth rates differ (the debug log grows fastest because most operational events log to it; the audit log grows steadily; the login history grows slowest), but all three need a disposal strategy beyond "wait until disk fills."
The honest scope to know: SimpleRisk doesn't ship built-in log rotation for the file-based debug log. The application appends to /var/log/simplerisk/simplerisk.log; if you don't configure log rotation at the OS level, the file grows monotonically. On a busy install with debug-level logging enabled, the file can reach gigabytes in weeks. The standard pattern is to use the OS's logrotate (Linux) to rotate, compress, and prune the log on a schedule.
The other thing worth knowing: the audit log table is what auditors look at first. The audit_log table records every change to the SimpleRisk data — risk submissions, score changes, mitigation updates, review submissions, status transitions. It's the artifact that proves the program was operating during any audit period. Pruning it aggressively destroys evidence; keeping it forever is operationally fine for most installs (the table grows, but not at the disk-filling rate of the debug log). Most installs keep the audit log indefinitely or with multi-year retention.
The third thing: the file-based debug log's verbosity is configurable through six logging_* settings (logging_debug, logging_info, logging_notice, logging_warning, logging_error, logging_critical). Each is a boolean toggle. Most production installs keep logging_warning, logging_error, and logging_critical enabled; whether to enable logging_info, logging_notice, or logging_debug depends on the operational context (debug is appropriate during troubleshooting, not during normal operation).
Before you start
Have these in hand:
- Server-side access to the SimpleRisk host with root/sudo to configure
logrotateand read log files. - MySQL admin or read-only access for examining the database log tables.
- A retention policy decision: how long to keep file logs, how long to keep audit logs, how long to keep login history. Compliance regimes may dictate this (PCI DSS Requirement 10.7 mandates a minimum 12-month retention for audit logs; SOC 2 typically expects retention covering the audit period; HIPAA expects 6-year retention for relevant log data).
- A monitoring approach for disk usage on the SimpleRisk host (and on the database host, if separate). Disk-fill is one of the failure modes that's easy to detect and easy to prevent — but only if you're watching.
Step-by-step
1. Configure the file-based debug log
The file log lives at /var/log/simplerisk/simplerisk.log (the path is configurable; this is the default for most installs). The application's write_debug_log($value, $level = 'info') function writes to this file, with the level determining whether the log line is emitted at all.
Verbosity control is via six settings in the settings table:
SELECT name, value FROM settings WHERE name LIKE 'logging_%';
logging_critical
- Default:
'1' - When to enable: Always. Events that need immediate attention.
logging_error
- Default:
'1' - When to enable: Always. Runtime errors needing investigation.
logging_warning
- Default:
'1' - When to enable: Always. Unexpected but non-fatal conditions.
logging_notice
- Default: varies
- When to enable: When operator visibility into significant events matters (framework installations, encryption operations, etc.).
logging_info
- Default: varies
- When to enable: For installations that want operational visibility into routine events. Generates substantial volume.
logging_debug
- Default: usually
'0' - When to enable: Only during troubleshooting. Generates very substantial volume; not for production normal operation.
Adjust the settings to match your operational needs. For most production installs, the right starting point is critical/error/warning enabled, notice/info disabled, debug disabled.
To change a setting:
UPDATE settings SET value = '1' WHERE name = 'logging_notice';
(Or via the admin UI if there's a settings page exposing these.)
2. Configure logrotate for the debug log
On Debian/Ubuntu/RHEL with the logrotate package (typically pre-installed), create /etc/logrotate.d/simplerisk:
/var/log/simplerisk/*.log {
daily
rotate 14
compress
delaycompress
missingok
notifempty
create 0640 www-data www-data
sharedscripts
postrotate
# SimpleRisk doesn't need anything specific on rotation;
# the app re-opens the file on the next write.
endscript
}
(Adjust www-data to your distribution's web server user; adjust the rotation count to match your retention policy.)
Verify the configuration is syntactically valid:
sudo logrotate -d /etc/logrotate.d/simplerisk
The -d flag dry-runs the rotation logic without actually rotating. Confirm the output reflects what you expect; then let the daily logrotate cron pick it up.
For installs where the log volume genuinely warrants it (a busy install with logging_info enabled), the rotation cadence may need to be more aggressive (hourly rotation with a higher count).
3. Manage the audit_log table
The audit_log table records changes to SimpleRisk data, with messages encrypted via try_encrypt(). The schema:
id
- Type: INT AUTO_INCREMENT
- Notes: Primary key.
timestamp
- Type: TIMESTAMP DEFAULT CURRENT_TIMESTAMP
- Notes: When the event occurred.
risk_id
- Type: INT
- Notes: The affected risk's ID (offset by +1000 from the underlying ID).
user_id
- Type: INT
- Notes: The user who triggered the event.
message
- Type: TEXT
- Notes: The encrypted event description.
log_type
- Type: VARCHAR(100)
- Notes: Categorization:
risk(default),backup,vulnmgmt,notification, etc.
The audit_log table grows steadily. Disk-usage characteristics:
- An average row is a few hundred bytes (encrypted message plus the small fixed-size columns).
- A busy install might add tens of thousands of rows per month.
- The table generally fits comfortably in tens to hundreds of megabytes after years of operation.
For most installs, no active management is needed; the table grows and stays manageable. For high-volume installations or compliance regimes that mandate specific retention, a periodic prune is appropriate:
-- Delete audit_log rows older than 5 years (adjust per retention policy)
DELETE FROM audit_log WHERE timestamp < DATE_SUB(NOW(), INTERVAL 5 YEAR);
Run this in a scheduled job (an OS cron entry that invokes a SQL script, or a SimpleRisk cron customization) on whatever cadence your retention policy prescribes.
Caution about pruning audit logs: the audit log is forensic evidence. Once a row is deleted, the proof that the corresponding event occurred is gone. Don't prune more aggressively than your compliance requirements permit; if you're not sure of the requirement, default to longer retention.
4. Manage the user_login_history table
The user_login_history table records every successful login:
id
- Type: INT AUTO_INCREMENT
- Notes: Primary key.
user_id
- Type: INT
- Notes: The user who logged in.
timestamp
- Type: TIMESTAMP DEFAULT NOW()
- Notes: When the login occurred.
users
- Type: INT
- Notes: The total user count at login time (snapshot).
risks
- Type: INT
- Notes: The total risk count at login time (snapshot).
The login history grows with each login event; a 100-user install with daily activity adds roughly 100 rows per day. The table stays small by audit-log standards.
For most installs, no pruning is needed. For long-running installations approaching multi-year retention thresholds, the same DELETE pattern works:
DELETE FROM user_login_history WHERE timestamp < DATE_SUB(NOW(), INTERVAL 3 YEAR);
5. Manage the backups directory (built-in backup mechanism)
If you've enabled the built-in backup mechanism (backup_auto = 'true' per Database Backup and Restore), backup files accumulate in backup_path (default
). The backup_remove setting controls how many backups to keep; older backups are pruned automatically when the count exceeds this value.
Check disk usage periodically:
du -sh
ls -lh
| head
For installations using the manual mysqldump pattern instead, the cleanup is at the off-host backup destination (S3 lifecycle policies, Azure Blob lifecycle rules, etc.), not on the SimpleRisk host.
6. Manage the temporary files
The tmp_files table holds short-lived data (typically file uploads in progress, intermediate processing artifacts). The cron_temporary_cleanup.php cron script (see The Cron Jobs) deletes rows older than 24 hours on each run.
If the cron isn't running, tmp_files accumulates. Periodic check:
SELECT COUNT(*) FROM tmp_files WHERE timestamp < DATE_SUB(NOW(), INTERVAL 24 HOUR);
A high count of old rows means the cleanup cron isn't running; investigate the cron configuration.
7. Monitor overall disk usage
Set up monitoring on the SimpleRisk host's disk usage with alerting at sensible thresholds (warning at 70%, critical at 85%, page at 95%). The most common disk-fill culprits in SimpleRisk operational practice:
- The debug log file growing because logrotate isn't configured.
- Backup files accumulating in
backup_pathbecause the prune isn't running. - The MySQL data directory growing because of audit_log accumulation (less common; audit_log usually stays manageable).
- The MySQL binary log if binlog is enabled and not being purged.
- Application files if accumulated old releases are kept on the host (the
simplerisk.old.artifacts from bare-metal upgrades)./
Disk monitoring is OS-level, not SimpleRisk-specific; use whatever monitoring tooling your operations team already runs.
Common pitfalls
A handful of patterns recur with log management.
-
No logrotate configuration. The single most common log-management failure. SimpleRisk's debug log appends forever; without logrotate, it eventually fills disk. Configure logrotate as part of the install procedure, not as an afterthought when disk is full.
-
Debug logging enabled in production.
logging_debug = '1'produces enormous log volume — function-entry traces, internal state dumps, per-request diagnostic detail. Appropriate for short-term troubleshooting; inappropriate for long-running production operation. Turn debug back off after troubleshooting completes. -
Pruning the audit log too aggressively. The audit log is forensic evidence. PCI DSS expects 12 months minimum; SOC 2 expects coverage of the audit period; HIPAA expects 6 years. Pruning to "save space" before checking the retention requirement produces a compliance gap that surfaces during the audit.
-
Pruning the audit log without backup. Even within a retention policy that permits pruning, take a backup of the rows being pruned before deleting. The pruning is irreversible without that backup; an audit query against the now-deleted rows produces "we no longer have that data" which is rarely a comfortable answer.
-
Backup files filling disk silently. The built-in backup mechanism with
backup_removeworks for retention if configured correctly; the manual backup pattern needs an explicit prune step (or a cloud lifecycle policy at the destination). Without either, backups accumulate forever. -
Old SimpleRisk install directories left after upgrades. The bare-metal upgrade pattern moves the old install aside as
simplerisk.old/(per Upgrading on Bare Metal). After confirming the new install works, the old directory should be removed; multiple unremoved upgrade artifacts can accumulate substantial disk over time. -
Not monitoring disk usage at all. Disk-fill produces an outage when the database can't write or the application can't log. The outage is preventable with basic disk-usage monitoring; without it, the first signal is the failure itself.
-
Over-aggressive logrotate pruning. Rotating the debug log daily and keeping 1 day means a problem that surfaced yesterday has its evidence rotated out before the operator investigates today. Match the retention to the typical investigation timeframe; 14 days of daily-rotated logs is a reasonable minimum.
-
Relying on log rotation to "fix" excessive verbosity. If the debug log is filling disk because
logging_debugis on, the right fix is to turn debug off, not to rotate more aggressively. Logrotate manages volume; it doesn't reduce it. Reduce the volume at the source. -
MySQL binary logs accumulating without binlog purging. SimpleRisk doesn't manage MySQL binlog; if MySQL has binlog enabled (for replication or for point-in-time recovery), the binlog files need their own purge policy. Configure
expire_logs_daysin MySQL or usePURGE BINARY LOGS BEFOREon a schedule.
Related
- Database Backup and Restore
- The Cron Jobs
- The Upgrade Process
- Upgrading on Bare Metal
- The Audit Trail (for reading the audit_log table)
- The Debug Log (for reading the file-based debug log)
- Monitoring SimpleRisk
Reference
- Permission required: Server-side: read on
/var/log/simplerisk/, MySQL access for the log tables. SimpleRisk-side:check_adminfor changing logging settings via UI. - API endpoint(s): None for log management directly.
- Implementing files:
simplerisk/includes/functions.php(thewrite_debug_log()function);simplerisk/cron/cron_temporary_cleanup.php(the temporary-files cleanup);simplerisk/cron/cron_backup.php(built-in backup withbackup_removeretention). - Database tables:
audit_log(id,timestamp,risk_id,user_id,messageencrypted,log_type);user_login_history(id,user_id,timestamp,users,risks);backups(records of built-in backup runs);tmp_files(cleaned by the temporary-cleanup cron). config_settingskeys:logging_critical,logging_error,logging_warning,logging_notice,logging_info,logging_debug(file-log verbosity);backup_auto,backup_path,backup_schedule,backup_remove(built-in backup);cron_last_run(last cron execution timestamp).- External dependencies: OS
logrotatefor file-log rotation; OS-level disk monitoring; cloud lifecycle policies for off-host backup retention.