Overview
Plex media server has the ability to send webhooks when used with a Plex Pass
(premium) account. This project documents how to set up a webhook to log and
alert on media activity. The design goals include logging all media playing
activity (play, stop, pause, resume) on my Plex server, and sending email
notifications. Technologies used: apache, shell, selinux, jq, mailx
Architecture
Plex can be configured to point to a webhook, e.g.,
http://plex.example.com/cgi-bin/plex-log.cgi. The webhook file is
documented below. The webhook is a script that acts upon the data passed from
Plex. The actions include copying important values to different log files, and
invoking a separate script that sends an email to the admin.
Involved files
Multiple files are a part of this project.
- /var/server1/shares/public/www/cgi-bin/plex-log.cgi
- /var/server1/shares/public/Support/Systems/server1/var/log/plex-webhook/activity.log
- /var/server1/shares/public/Support/Systems/server1/var/log/plex-webhook/short.log
- /usr/local/bin/send-plex-alert.sh
- /usr/src/selinux/plexlog.te
Webhook script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82 |
#!/bin/sh
# File: server1:/var/server1/shares/public/www/cgi-bin/plex-log.cgi
# License: CC-BY-SA 4.0
# Author: bgstack15
# Startdate: 2020-08-06 07:55
# Title: Logging Webhook for Plex
# Project: Plex Activity Logging and Alerting Project
# History:
# References:
# send from bgscripts
# /posts/2017/08/05/send-authenticated-gmail-from-cli-with-mailx/
# Not sure which mail I have https://unix.stackexchange.com/questions/15405/how-do-i-send-html-email-using-linux-mail-command/15463#15463
# Related files:
# /usr/local/bin/send-plex-alert.sh
# Improve:
# Dependencies:
# /usr/local/bin/send-plex-alert.sh
# Webhook functionality of Plex with a Plex Pass account
# apache cgi capability
# Documentation:
# /mnt/public/Support/Programs/Plex/webhooks/palap-readme.md
LOGFILE=/var/server1/shares/public/Support/Systems/server1/var/log/plex-webhook/activity.log
LOGFILESHORT=/var/server1/shares/public/Support/Systems/server1/var/log/plex-webhook/short.log
VERBOSE=0 # set to anything to display extra things
ALERT_ON_EVENTS="play:stop:pause:resume" # options include play stop resume pause, colon separated
NOW="$( date -u "+%FT%TZ" )"
TMPFILE1="$( mktemp )"
TMPFILE2="$( mktemp )"
TMPFILE3="$( mktemp )"
printf "%s\n\n" "Content-type: text/html"
echo "<html><head><title>Plex webhook</title>"
echo "</head><body>"
echo "<pre>"
cat > "${TMPFILE1}"
boundary="$( echo "${CONTENT_TYPE}" | awk '{print $2}' | awk -F'=' '{print $2}' )"
{
test "${VERBOSE}" -gt 0 && {
printf "%s\n" "" >> "${LOGFILE}"
echo "REQUEST-START: ${NOW}"
env
set
echo "BEGIN RAW"
}
sed -r -e "s/-*${boundary}-*/\n/g;" "${TMPFILE1}" | tee "${TMPFILE2}" | \
{
test "${VERBOSE}" -gt 0 && { cat ; } || { cat >/dev/null ; }
}
test "${VERBOSE}" -gt 0 && {
echo "END RAW"
echo "BEGIN JQ"
}
json="$( grep -aE "^.{0,4}\"event\"" "${TMPFILE2}" | jq -c ". += {timestamp: \"${NOW}\", useragent: \"${HTTP_USER_AGENT}\" }" 2>&1 )"
# full json for log
echo "${json}"
# send truncated json to mail account for alerts
echo "${json}" | jq '{timestamp: .timestamp, event: .event, user: .Account.title, player: .Player.title, ipAddress: .Player.publicAddress, file: {type: .Metadata.type, title: .Metadata.title, parentTitle: .Metadata.parentTitle, grandparentTitle: .Metadata.grandparentTitle } }' > "${TMPFILE3}"
# log to short log and send email only if it has contents
printf "%s" "${json}" | grep -qE '.' && {
cat "${TMPFILE3}" >> "${LOGFILESHORT}"
# only alert if it matches. This syntax relies on the event syntax from Plex to be "media.play" or "media.stop" et al.
alert_regex="(media\.)$( echo "${ALERT_ON_EVENTS}" | sed -r -e 's/^://g;' -e 's/:$//g;' -e 's/:+/|/g;' )"
if grep -qE "${alert_regex}" "${TMPFILE3}" ;
then
# magic to get fixed-width font in gmail by using html pre tags
{ echo "<html><body><pre>" ; cat "${TMPFILE3}" ; echo "</pre></html></body>" ; } | mailsubject="Media activity
Content-Type: text/html" /usr/local/bin/send-plex-alert.sh STDIN
else
test "${VERBOSE}" -gt 0 && {
echo "SKIPPING EMAIL because event does not match ${ALERT_ON_EVENTS}"
}
fi
}
test "${VERBOSE}" -gt 0 && {
echo "END JQ"
echo "REQUEST-STOP: ${NOW}"
}
} | tee -a "${LOGFILE}"
echo "</pre>"
echo "</body></html>"
# clean up
rm -f "${TMPFILE1}" "${TMPFILE2}" "${TMPFILE3}"
|
The above webhook script contains its own comments. The VERBOSE attribute
can be set to a non-zero amount (usually 1 ) to log much more information
useful for debugging. Attribute ALERT_ON_EVENTS is a colon-separated list
of event types passed from Plex that should trigger an email to the admin.
This syntax depends on Plex's syntax not changing. The two log files are
configured in the main webhook script. The LOGFILE contains the verbose
logging (if enabled) and the full json object from Plex. The LOGFILESHORT
contains the trimmed contents that will be used for the email.
Email script
A separate script holds the logic to send the email, file
/usr/local/bin/send-plex-alert.sh.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 |
#!/bin/sh
# File: send-plex-alert.sh
# Project: Plex Activity Logging and Alerting Project
# startdate: 2020-08-07 17:21
# Documentation:
# this one worked, but took a while, probably due to ISP smtp relay delay. echo "echo juliet oscar 10" | mailx -S 'from="bgstack15@ipa.example.com"' -S "Subject line" bgstack15@gmail.com ; echo $?
# worked immediately: echo "hotel whiskey zulu 14" | mailx -v -S "Another thread here" -S smtp-use-starttls -S ssl-verify=ignore -S smtp-auth=login -S smtp=smtp://smtp.gmail.com:587 -S from="B Stack <bgstack15@gmail.com>" -S smtp-auth-user="bgstack15@gmail.com" -S smtp-auth-password='FIXME' -S nss-config-dir=/etc/pki/nssdb/ bgstack15@gmail.com
# Improve:
# learn how to use a custom MAILRC env var which holds the "set smtp-user-password=" contents
# Dependencies:
# mailx (mailx-12.5-19.el7.x86_64 @base)
# Google account security set to allow "insecure apps" or similar https://support.google.com/accounts/answer/6010255?authuser=2&p=lsa_blocked&hl=en&authuser=2&visit_id=637324418441299012-2559162990&rd=1
test -z "${mailmessage}" && export mailmessage="${1}"
test "${mailmessage}" = "STDIN" && export mailmessage="$( cat 2>/dev/null )"
test -z "${mailuser}" && export mailuser="bgstack15@gmail.com"
test -z "${mailpassword}" && export mailpassword='SUPERSAFESTRING;'
test -z "${mailfrom}" && export mailfrom="Plex activity <bgstack15@gmail.com>"
test -z "${mailsubject}" && export mailsubject="Media activity"
test -z "${mailto}" && export mailto=bgstack15@gmail.com
printf "%s\n" "${mailmessage}" | mailx -s "${mailsubject}" \
-S smtp-use-starttls \
-S ssl-verify=ignore \
-S smtp=smtp://smtp.gmail.com:587 \
-S smtp-auth=login \
-S from="${mailfrom}" \
-S smtp-auth-user="${mailuser}" \
-S smtp-auth-password="${mailpassword}" \
-S nss-config-dir=/etc/pki/nssdb \
"${mailto}"
|
SELinux policy
To use the webhook script and mail script with SELinux enforcing, you need to
add a custom policy. File /usr/src/selinux/plexlog.te contains the uncompiled
policy.
# File: /usr/src/selinux/plexlog.te
# Startdate: 2020-08-07 20:45
# Title: SELinux policy to allow webhook to send email
# Project: Plex Activity Logging and Alerting Project
module plexlog 1.0;
require {
type httpd_sys_script_t;
type init_t;
type httpd_t;
type smtp_port_t;
type var_t;
class process { noatsecure rlimitinh siginh };
class unix_stream_socket { read write };
class capability net_admin;
class file { append execute getattr open read };
class tcp_socket name_connect;
}
#============= httpd_sys_script_t ==============
#!!!! WARNING: 'var_t' is a base type.
allow httpd_sys_script_t var_t:file { append execute getattr open read };
#!!!! This avc can be allowed using one of the these booleans:
# httpd_can_network_connect, nis_enabled
allow httpd_sys_script_t smtp_port_t:tcp_socket name_connect;
#============= httpd_t ==============
allow httpd_t httpd_sys_script_t:process { noatsecure rlimitinh siginh };
allow httpd_t self:capability net_admin;
To use this policy, you need to compile and install it.
sudo checkmodule -M -m -o plexlog.mod plexlog.te && sudo semodule_package -o plexlog.pp -m plexlog.mod && sudo semodule -i plexlog.pp
References
Weblinks
- Running Starbound server on CentOS 7
- Technical Notes: How to setup/configure/use mailx for Office365 account?
Comments