]> git.vanrenterghem.biz Git - www2.vanrenterghem.biz.git/blob - source/posts/Implementing_Webmention_on_my_blog.org
991c9b381a05723f1e7292cb46881db6c41ddec8
[www2.vanrenterghem.biz.git] / source / posts / Implementing_Webmention_on_my_blog.org
1 #+date: 2023-05-14 20:32:00 +0800
2 #+opengraph2: ogimage="https://indieweb.org/File:indiewebcamp-logo-lockup-color@3x.png
3 #+filetags: indieweb blogging open_web
4 #+title: Implementing Webmention on my blog
6 Following on from my last [[Bring_Back_Blogging][post on joining the indieweb]]...
8 Back in February, I implemented Webmentions on my website. I took a roll-my-own approach, borrowing from [[http://superkuh.com/blog/2020-01-10-1.html][an idea by superkuh]]. It's a semi-automated solution which listens for webmentions using nginx. When (if) one is received, an email is generated that tells me about this, allowing me to validate it's a genuine comment.
10 Technically, nginx logs the body of POST requests in its logfile.
12 In the main configuration file `/etc/nginx/nginx.conf`, I've added
14 #+BEGIN_SRC sh
15 # Defined for Webmention logging support of www.vanrenterghem.biz
16 log_format postdata '$time_local,$remote_addr,"$http_user_agent",$request_body';
17 """]]
19 In the configuration for www.vanrenterghem.biz, the following lines enable logging webmention requests:
21 [[!format  sh """
22 # use proxying to self to get the HTTP post variables.
23     # https://stackoverflow.com/questions/4939382/logging-post-data-from-request-body
24     location = /webmention {
25         limit_req zone=webmention;
26         client_max_body_size 7k;
27         if ($request_method = POST) {
28                 access_log /var/log/nginx/postdata.log postdata;
29                 proxy_pass $scheme://www.vanrenterghem.biz/logsink;
30                 break;
31         }
32         return 204 $scheme://$host/serviceup.html;
33     }
34     location /logsink {
35         #return 200;
36         # use 204 instead of 200 so no 0 byte file is sent to browsers from HTTP forms.
37         return 204;
38     }
39 #+END_SRC
41 Before the `server` section in there, I'm reducing the risk of abuse by rate limiting requests:
43 #+BEGIN_SRC sh
44 limit_req_zone  $server_name  zone=webmention:1m   rate=2r/s;
45 #+END_SRC
47 The logfile is being monitored by a service calling a shell script:
49 #+BEGIN_SRC sh
50 #!/bin/sh
51 # Service starts on boot in /etc/systemd/system/webmention.service
52 TO=my@email.address
53 WEBMENTION_LOG=/var/log/nginx/postdata.log
54 inotifywait -s -m $WEBMENTION_LOG --format "%e %w%f" --event modify|
55 while read CHANGED;
56 do
57     echo "$CHANGED"
58     logger "Webmention received"
59     tail -n1 $WEBMENTION_LOG | /usr/bin/mail -a'From: niihau webmention service <webmaster@email.address>' -s 'Webmention received' $TO
60 done
61 #+END_SRC
63 This uses `inotifywait`, which is part of [[https://github.com/inotify-tools/inotify-tools][inotify-tools]]. Unfortunately, `logrotate` will remove the log file on a regular basis, which is done in 3 steps. The first 2 steps results in a MODIFY event, before a DELETE event is created. That results in 2 emails being sent every time logs are rotated if using the above script. I've not tried to ignore these yet - checking for `logrotate` running at the time an event is triggered could be a solution.
65 The systemd service is defined in `/etc/systemd/system/webmention.service`:
67 #+BEGIN_SRC sh
68 [Unit]
69 Description=Service to monitor nginx log for webmentions
70 After=multi-user.target
72 [Service]
73 ExecStart=/root/webmention_service.sh
75 [Install]
76 WantedBy=multi-user.target
77 #+END_SRC
79 Announcing I'm accepting webmentions is as simple as putting the endpoint in the header of the blog:
81 #+BEGIN_SRC html
82 <link rel="webmention" href="https://www.vanrenterghem.biz/webmention">
83 #+END_SRC
85 Clearly federating conversation as the final level of joining the indieweb is quite a bit more complicated than achieving 'level 2' status on [[https://indiewebify.me/][indiewebify.me]].