Chroot and syslog

When you develop chroot’ed web application, you have no syslog access by default. It’s quite simple to log with syslog with UDP, but it may be quite confusing if you set up such a configuration for a first time. There’re hints in documentation, but I could find no complete guide.

First, you need to set up syslog. I use debian with rsyslog, so you may need to adjust your logs format. Next, let’s define some specific web application may need:

  • Log to separate directory, every program name goes to specific file.
  • Use custom log format, for example use RFC-3339 time format.
  • Define program names in web application only to prevent hardcoding names list twice and let developers without access to system settings define new logs.
  • Do not write UDP syslog messages to syslog and other default log files.
  • Let all cluster write logs into the same files.

Every moment is quite simple when you think about it, but it took me a few time to figure out complex solution.


# Define dynamic log file name
template(name="udpLog" type="string" string="/var/log/webapp/%programname%.log")
# Define log format
template(name="udpFormat" type="list") {
property(name="timestamp" dateFormat="rfc3339")
constant(value=" ")
property(name="hostname")
constant(value=" ")
property(name="syslogtag")
property(name="msg" spifno1stsp="on" )
property(name="msg" droplastlf="on" )
constant(value="\n")
}
# Define ruleset for UDP traffic
ruleset(name="udpRules") {
action(template="udpFormat" type="omfile" DynaFile="udpLog")
stop
}
# Load module and apply udpRules to ALL traffic within this port
module(load="imudp")
input(type="imudp" port="514" ruleset="udpRules")

With Debian, you can just put this settings to file named something like /etc/rsyslog.d/webapp.conf and restart rsyslog. If you need multiple logs set, just add similar configuration with another port number. And don’t forget to limit access to UDP log 514 with firewall.

Now you can test logging, in PHP:
$socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
$date = date('c');
$host = $_SERVER['HTTP_HOST']; // host name as it appears in logs
foreach (explode("\n", $message) as $line) {
$syslog_message = "<22>$date $host {$this->logName}:$line";
socket_sendto(
$socket,
$syslog_message,
strlen($syslog_message),
0,
'127.0.0.1', // syslog server IP
514 // syslog UDP port
);
}
socket_close($socket);

Now, files are auto created. Just in case, sample /etc/logrotate.d/webapp:
/var/log/webapp/*.log {
daily
missingok
rotate 30
compress
delaycompress
notifempty
nocreate
su root root
sharedscripts
postrotate
invoke-rc.d rsyslog rotate > /dev/null
endscript
}

Add comment


%d bloggers like this: