Running syslog-ng in a chroot, logging by host, date and program

(on Debian)

Abstract

Instructions on running syslog-ng as non-root, in a chroot, writing logs to /var/spool/syslog-ng/$HOST/$YYYY/$MM/$DD/$PROGRAM.

Instructions

  1. Install syslog-ng, create user and setup filesystem:

    $ sudo apt-get install syslog-ng
    ...
    $ sudo adduser --system --home /var/log/syslog-ng --gecos 'syslog-ng' --group syslogng
    Adding system user `syslogng'...
    Adding new group `syslogng' (114).
    Adding new user `syslogng' (114) with group `syslogng'.
    Creating home directory `/var/log/syslog-ng'.
    $ sudo install -d -m0750 -o syslogng -g syslogng /var/log/syslog-ng
    
  2. Disable rotation of the old log files (or you will get error mail from cron every day):

    $ sudo perl -pe 's/^/#/' -i /etc/logrotate.d/syslog-ng
    
  3. Edit /etc/syslog-ng/syslog-ng.conf:

    options {
            use_fqdn(yes);
            use_dns(no);
            chain_hostnames(yes);
            use_time_recvd(no);
    #       sync(10);
    
    
            perm(0640);
            owner("syslogng");
            group("syslogng");
            create_dirs(yes);
            dir_perm(0750);
            dir_owner("syslogng");
            dir_group("syslogng");
    };
    
    
    source syslog {
            unix-stream("/dev/log");
    };
    
    
    source kernel {
            file("/proc/kmsg");
    };
    
    
    source syslog-ng {
            internal();
    };
    
    
    destination firewall {
            file("/spool/$HOST/$YEAR/$MONTH/$DAY/firewall");
    };
    
    
    destination kernel {
            file("/spool/$HOST/$YEAR/$MONTH/$DAY/kernel");
    };
    
    
    destination invalid {
            file("/spool/unknown/$YEAR/$MONTH/$DAY/invalid");
    };
    
    
    destination postfix {
            file("/spool/$HOST/$YEAR/$MONTH/$DAY/postfix");
    };
    
    
    destination cron {
            file("/spool/$HOST/$YEAR/$MONTH/$DAY/cron");
    };
    
    
    destination generic {
            file("/spool/$HOST/$YEAR/$MONTH/$DAY/$PROGRAM");
    };
    
    
    destination syslog-ng {
            file("/spool/$HOST/$YEAR/$MONTH/$DAY/syslog-ng");
    };
    
    
    destination misc {
            file("/spool/$HOST/$YEAR/$MONTH/$DAY/misc");
    };
    
    ## kernel
    filter firewall {
            match("^firewall:") or match("^NAT:");
    };
    
    
    filter notfirewall {
            not match("^firewall:") and not match("^NAT:");
    };
    
    
    log {
            source(kernel);
            filter(firewall);
            destination(firewall);
    };
    
    
    log {
            source(kernel);
            filter(notfirewall);
            destination(kernel);
    };
    
    ## internal
    log {
            source(syslog-ng);
            destination(syslog-ng);
    };
    
    ## syslog
    filter invalid {
            not host("^syslog@[a-z][a-z0-9-]*$");
    };
    
    
    filter postfix {
            host("^syslog@[a-z][a-z0-9-]*$")
            and program("^postfix/");
    };
    
    
    filter cron {
            host("^syslog@[a-z][a-z0-9-]*$")
            and program("^(/USR/SBIN/CRON|/usr/sbin/cron|CRON|cron)$");
    };
    
    
    filter generic {
            host("^syslog@[a-z][a-z0-9-]*$")
            and program("^([a-z][a-z0-9._-]*)$");
    };
    
    
    log {
            source(syslog);
            filter(invalid);
            destination(invalid);
    };
    
    
    log {
            source(syslog);
            filter(postfix);
            destination(postfix);
    };
    
    
    log {
            source(syslog);
            filter(cron);
            destination(cron);
    };
    
    
    log {
            source(syslog);
            filter(generic);
            destination(generic);
    };
    
    
    log {
            source(syslog);
            destination(misc);
            flags(fallback);
    };
    
  4. Edit /etc/init.d/syslog-ng:

    Add options -C /var/log/syslog-ng -u syslogng -g syslogng to where ever you see --start:

    syslogng_start() {
        echo -n "Starting system logging: syslog-ng"
        start-stop-daemon --start --quiet --exec "$SYSLOGNG" --pidfile "$PIDFILE" -- -p "$PIDFILE" \
        -C /var/log/syslog-ng -u syslogng -g syslogng \
          || { echo " start failed."; return 1; }
        echo "."
        return 0
    }
    

    Note Linux 2.6 won't let you run a kernel message logger as non-root

    Linux 2.6 checks the relevant access permissions on every read from /proc/kmsg, as opposed to just on open, as Linux 2.4 used to do. There is no easy way to work around this -- the proper solution is likely either to fix the kernel or drop root but retain a specific capability.

    For now, drop the -u and -g options, like this:

    syslogng_start() {
        echo -n "Starting system logging: syslog-ng"
        start-stop-daemon --start --quiet --exec "$SYSLOGNG" --pidfile "$PIDFILE" -- -p "$PIDFILE" \
        -C /var/log/syslog-ng \
          || { echo " start failed."; return 1; }
        echo "."
        return 0
    }
    
  5. Restart syslog-ng to make the changes take effect:

    $ sudo /etc/init.d/syslog-ng restart
    
  6. Give admin accounts read access to logs:

    $ sudo gpasswd -a <replaceable>youruseraccount</replaceable> syslogng
    
  7. Log out or use newgrp to make the added group take effect.