mirror of
https://github.com/mail-in-a-box/mailinabox.git
synced 2025-08-07 04:50:54 +00:00
Web statistics using goaccess.
This commit is contained in:
parent
3cde9a8893
commit
e922401298
@ -3,5 +3,5 @@
|
|||||||
before = common.conf
|
before = common.conf
|
||||||
|
|
||||||
[Definition]
|
[Definition]
|
||||||
failregex=<HOST> - .*GET /admin/munin/.* HTTP/\d+\.\d+\" 401.*
|
failregex=^.+?:\d+ <HOST> - .*GET /admin/munin/.* HTTP/\d+\.\d+\" 401.*
|
||||||
ignoreregex =
|
ignoreregex =
|
||||||
|
2
conf/goaccess_persist
Normal file
2
conf/goaccess_persist
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
#!/usr/bin/env /bin/bash
|
||||||
|
/usr/bin/goaccess --process-and-exit
|
@ -10,3 +10,10 @@ upstream php-fpm {
|
|||||||
server unix:/var/run/php/php8.0-fpm.sock;
|
server unix:/var/run/php/php8.0-fpm.sock;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Reconfigure access log to include vhost to match goaccess VCOMBINED.
|
||||||
|
# Cancel default logging, re-enabled in servers.
|
||||||
|
access_log off;
|
||||||
|
# Log format to match goaccess.
|
||||||
|
log_format vcombined '$host:$server_port $remote_addr - $remote_user [$time_local] '
|
||||||
|
'"$request" $status $body_bytes_sent '
|
||||||
|
'"$http_referer" "$http_user_agent"';
|
||||||
|
@ -10,6 +10,8 @@ server {
|
|||||||
server_name $HOSTNAME;
|
server_name $HOSTNAME;
|
||||||
root /tmp/invalid-path-nothing-here;
|
root /tmp/invalid-path-nothing-here;
|
||||||
|
|
||||||
|
access_log /var/log/nginx/access.log vcombined;
|
||||||
|
|
||||||
# Improve privacy: Hide version an OS information on
|
# Improve privacy: Hide version an OS information on
|
||||||
# error pages and in the "Server" HTTP-Header.
|
# error pages and in the "Server" HTTP-Header.
|
||||||
server_tokens off;
|
server_tokens off;
|
||||||
@ -36,6 +38,8 @@ server {
|
|||||||
|
|
||||||
server_name $HOSTNAME;
|
server_name $HOSTNAME;
|
||||||
|
|
||||||
|
access_log /var/log/nginx/access.log vcombined;
|
||||||
|
|
||||||
# Improve privacy: Hide version an OS information on
|
# Improve privacy: Hide version an OS information on
|
||||||
# error pages and in the "Server" HTTP-Header.
|
# error pages and in the "Server" HTTP-Header.
|
||||||
server_tokens off;
|
server_tokens off;
|
||||||
|
@ -15,6 +15,11 @@ if [ "$(date "+%u")" -eq 1 ]; then
|
|||||||
management/mail_log.py -t week | management/email_administrator.py "Mail-in-a-Box Usage Report"
|
management/mail_log.py -t week | management/email_administrator.py "Mail-in-a-Box Usage Report"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# On Mondays, i.e. once a week, send the administrator a web analytics report.
|
||||||
|
if [ "$(date "+%u")" -eq 1 ]; then
|
||||||
|
goaccess -o html | management/email_administrator_attachment.py "MIAB Web Analytics Report" "Mail-in-a-Box Web analytics report is attached." "webstats.html"
|
||||||
|
fi
|
||||||
|
|
||||||
# Take a backup.
|
# Take a backup.
|
||||||
management/backup.py 2>&1 | management/email_administrator.py "Backup Status"
|
management/backup.py 2>&1 | management/email_administrator.py "Backup Status"
|
||||||
|
|
||||||
|
73
management/email_administrator_attachment.py
Executable file
73
management/email_administrator_attachment.py
Executable file
@ -0,0 +1,73 @@
|
|||||||
|
#!/usr/local/lib/mailinabox/env/bin/python
|
||||||
|
|
||||||
|
# Reads in STDIN. If the stream is not empty, mail it to the system administrator.
|
||||||
|
|
||||||
|
import sys
|
||||||
|
|
||||||
|
import html
|
||||||
|
import smtplib
|
||||||
|
import email
|
||||||
|
|
||||||
|
from email.mime.multipart import MIMEMultipart
|
||||||
|
from email.mime.text import MIMEText
|
||||||
|
from email.mime.base import MIMEBase
|
||||||
|
from email import encoders
|
||||||
|
|
||||||
|
# In Python 3.6:
|
||||||
|
#from email.message import Message
|
||||||
|
|
||||||
|
from utils import load_environment
|
||||||
|
|
||||||
|
# Load system environment info.
|
||||||
|
env = load_environment()
|
||||||
|
|
||||||
|
# Process command line args.
|
||||||
|
subject = sys.argv[1] or 'MIAB Administration'
|
||||||
|
body = sys.argv[2] or 'Please see the attachment. --Mail-in-a-Box'
|
||||||
|
attachmentname = sys.argv[3] or 'attachment.html'
|
||||||
|
|
||||||
|
# Administrator's email address.
|
||||||
|
admin_addr = "administrator@" + env['PRIMARY_HOSTNAME']
|
||||||
|
|
||||||
|
# Read in STDIN.
|
||||||
|
attachment = sys.stdin.read().strip()
|
||||||
|
|
||||||
|
# If there's nothing coming in, just exit.
|
||||||
|
if attachment == "":
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
# create MIME message
|
||||||
|
msg = MIMEMultipart('alternative')
|
||||||
|
|
||||||
|
# In Python 3.6:
|
||||||
|
#msg = Message()
|
||||||
|
|
||||||
|
msg['From'] = '"{}" <{}>'.format(env['PRIMARY_HOSTNAME'], admin_addr)
|
||||||
|
msg['To'] = admin_addr
|
||||||
|
msg['Subject'] = "[{}] {}".format(env['PRIMARY_HOSTNAME'], subject)
|
||||||
|
|
||||||
|
body_html = f'<html><body><pre style="overflow-x: scroll; white-space: pre;">{html.escape(body)}</pre></body></html>'
|
||||||
|
|
||||||
|
msg.attach(MIMEText(body, 'plain'))
|
||||||
|
msg.attach(MIMEText(body_html, 'html'))
|
||||||
|
|
||||||
|
# Attach content as file
|
||||||
|
part = MIMEBase('application', 'octet-stream')
|
||||||
|
part.set_payload(attachment);
|
||||||
|
encoders.encode_base64(part);
|
||||||
|
part.add_header('Content-Disposition', f"attachment; filename={attachmentname}")
|
||||||
|
|
||||||
|
msg.attach(part);
|
||||||
|
|
||||||
|
# In Python 3.6:
|
||||||
|
#msg.set_content(content)
|
||||||
|
#msg.add_alternative(content_html, "html")
|
||||||
|
|
||||||
|
# send
|
||||||
|
smtpclient = smtplib.SMTP('127.0.0.1', 25)
|
||||||
|
smtpclient.ehlo()
|
||||||
|
smtpclient.sendmail(
|
||||||
|
admin_addr, # MAIL FROM
|
||||||
|
admin_addr, # RCPT TO
|
||||||
|
msg.as_string())
|
||||||
|
smtpclient.quit()
|
42
setup/web.sh
42
setup/web.sh
@ -19,7 +19,7 @@ fi
|
|||||||
|
|
||||||
echo "Installing Nginx (web server)..."
|
echo "Installing Nginx (web server)..."
|
||||||
|
|
||||||
apt_install nginx php"${PHP_VER}"-cli php"${PHP_VER}"-fpm idn2
|
apt_install nginx php"${PHP_VER}"-cli php"${PHP_VER}"-fpm idn2 goaccess
|
||||||
|
|
||||||
rm -f /etc/nginx/sites-enabled/default
|
rm -f /etc/nginx/sites-enabled/default
|
||||||
|
|
||||||
@ -145,6 +145,46 @@ if [ ! -f "$STORAGE_ROOT/www/default/index.html" ]; then
|
|||||||
fi
|
fi
|
||||||
chown -R "$STORAGE_USER" "$STORAGE_ROOT/www"
|
chown -R "$STORAGE_USER" "$STORAGE_ROOT/www"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
echo "Setting up goaccess web analytics..."
|
||||||
|
|
||||||
|
# Set default configuration for goaccess web stats.
|
||||||
|
mkdir -p "/var/lib/mailinabox/goaccess_db"
|
||||||
|
tools/editconf.py /etc/goaccess/goaccess.conf -c '#' -s \
|
||||||
|
persist=true \
|
||||||
|
restore=true \
|
||||||
|
keep-last=7 \
|
||||||
|
db-path=/var/lib/mailinabox/goaccess_db \
|
||||||
|
html-report-title=Mailinabox \
|
||||||
|
log-file=/var/log/nginx/access.log \
|
||||||
|
log-format=VCOMBINED
|
||||||
|
|
||||||
|
|
||||||
|
# Create a pre-rotate action to preserve log info.
|
||||||
|
PREROT="/etc/logrotate.d/httpd-prerotate"
|
||||||
|
if [ -d "$PREROT" ] ; then
|
||||||
|
NOPREROT=1; # false, there is a prerotate
|
||||||
|
else
|
||||||
|
NOPREROT=0; # true, there is no prerotate
|
||||||
|
fi
|
||||||
|
mkdir -p "$PREROT"
|
||||||
|
|
||||||
|
# If the prerotate doesn't exist, configure.
|
||||||
|
if [ "$NOPREROT" -eq 0 ]; then
|
||||||
|
echo "- Configuring log prerotate action."
|
||||||
|
chown root:root "$PREROT"
|
||||||
|
chmod 755 "$PREROT";
|
||||||
|
else # There is a prerotate, no change.
|
||||||
|
echo "- No change to $PREROT";
|
||||||
|
fi
|
||||||
|
# Create action.
|
||||||
|
cp conf/goaccess_persist "$PREROT"
|
||||||
|
chown root:root "$PREROT/goaccess_persist"
|
||||||
|
chmod a+x "$PREROT/goaccess_persist"
|
||||||
|
|
||||||
|
|
||||||
# Start services.
|
# Start services.
|
||||||
restart_service nginx
|
restart_service nginx
|
||||||
restart_service php"$PHP_VER"-fpm
|
restart_service php"$PHP_VER"-fpm
|
||||||
|
@ -23,7 +23,7 @@ for fn in glob.glob("/var/log/nginx/access.log*"):
|
|||||||
# Find lines that are GETs on the bootstrap script by either curl or wget.
|
# Find lines that are GETs on the bootstrap script by either curl or wget.
|
||||||
# (Note that we purposely skip ...?ping=1 requests which is the admin panel querying us for updates.)
|
# (Note that we purposely skip ...?ping=1 requests which is the admin panel querying us for updates.)
|
||||||
# (Also, the URL changed in January 2016, but we'll accept both.)
|
# (Also, the URL changed in January 2016, but we'll accept both.)
|
||||||
m = re.match(rb"(?P<ip>\S+) - - \[(?P<date>.*?)\] \"GET /(bootstrap.sh|setup.sh) HTTP/.*\" 200 \d+ .* \"(?:curl|wget)", line, re.I)
|
m = re.match(rb"(?P<hostport>\S+) (?P<ip>\S+) - - \[(?P<date>.*?)\] \"GET /(bootstrap.sh|setup.sh) HTTP/.*\" 200 \d+ .* \"(?:curl|wget)", line, re.I)
|
||||||
if m:
|
if m:
|
||||||
date, time = m.group("date").decode("ascii").split(":", 1)
|
date, time = m.group("date").decode("ascii").split(":", 1)
|
||||||
date = dateutil.parser.parse(date).date().isoformat()
|
date = dateutil.parser.parse(date).date().isoformat()
|
||||||
|
Loading…
Reference in New Issue
Block a user