Devuan, Nginx, And Rsyslog (because of Fail2ban and Logger) 2020-01-21
Thie website you are currently reading is hosted on Devuan with Nginx. I use fail2ban to monitor the nginx log files and automatically ban [firewall] anyone who is abusing the web server. I also like to use Logger in my Fail2ban "action" definitions to add a log entry that tells me the IP address has been banned. That way, when someone is being an ass I will see the "bad" log entry in my logs, immediately followed by an entry announcing the ban, and then I should not see any subsequent log entries from that IP address. Simple enough, except that the Logger utility does not log to files, it only logs to syslog... which Nginx does not use by default. Now it is possible to setup your Fail2ban action to use
echo "blah blah blah" >> /var/log/coolguy.log
except that is a pain in the ass to get matching date syntax and it is kind of a sloppy workaround. So I finally got off my ass and cleaned up my logging so that Nginx uses syslog (provided by Rsyslog) and Fail2ban can have nice clean action files that use Logger instead of echo. Here's basically what I did:
In my /etc/rsyslog.conf file I added a couple of things. The first is an entry for "local7" which is the default facility Nginx likes to use... I pointed it at the file I want to log Nginx activity to like this:
The second thing I added was an exception. A half dozen lines up in my rsyslog.conf I found the entry that sends most syslog activity with a loglevel of "info", "notice", or "warn" to /var/log/messages. There were already some exceptions for auth, cron, mail, etc. so I just added local7 like this (the red part):
Next I went to my /etc/nginx/nginx.conf and told it to send log entries to syslog like this:
access_log syslog:server=unix:/dev/log,facility=local7,severity=info snorklog;
This basically sends the "access" log entries to syslog with the facility "local7" and loglevel "info". Now I also setup my own log format called "snorklog" which looks like this:
log_format snorklog '$remote_addr [$server_name:$server_port] "$request" $status "$http_referer" "$http_user_agent"';
This includes the information I am interested in and it excludes crap like the date/time since Rsyslog throws that in anyways. I also left the errorlog pointing to /var/log/nginx/error.log since I don't bother to monitor it with Fail2ban. Then I just had to restart Rsyslog and Nginx and my spiffy new log file started to fill up.
nginx -s reload
Next I setup all my Fail2ban actions with Logger commands that look like this:
logger -p local7.info -t fail2ban "Holy crap I am testing!"
and my log files now have nice comments showing who is banned and unbanned. Kickass.