aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastiano Tronto <sebastiano@tronto.net>2022-11-24 00:01:47 +0100
committerSebastiano Tronto <sebastiano@tronto.net>2022-11-24 00:01:47 +0100
commit1b69fbdce80f4ee2d46be63be34b4cfb4e4e11d7 (patch)
treed587a54bfd58054a441c3e6df980ca71290aea32
parentb473f7ce3895eccaf7691f6fc9296cb3c695a189 (diff)
downloadsebastiano.tronto.net-1b69fbdce80f4ee2d46be63be34b4cfb4e4e11d7.tar.gz
sebastiano.tronto.net-1b69fbdce80f4ee2d46be63be34b4cfb4e4e11d7.zip
Added blog post(s)
-rw-r--r--src/blog/2022-10-19-email-setup/email-setup.md201
-rw-r--r--src/blog/2022-11-23-git-host/git-host.md299
-rw-r--r--src/blog/blog.md2
-rw-r--r--src/blog/feed.xml14
4 files changed, 516 insertions, 0 deletions
diff --git a/src/blog/2022-10-19-email-setup/email-setup.md b/src/blog/2022-10-19-email-setup/email-setup.md
new file mode 100644
index 0000000..849efc6
--- /dev/null
+++ b/src/blog/2022-10-19-email-setup/email-setup.md
@@ -0,0 +1,201 @@
1# Keeping my email sorted (the hard way)
2
3I have recently made some changes to my email setup. In this post I'll
4explain the motivation behind these changes and what I did in practice.
5
6## Self-hosting?
7
8When I got my virtual machine up and running at
9[openbsd.amsterdam](https://openbsd.amsterdam/) - the one where this
10website is hosted - I originally planned to host my private email
11server there too. I knew this was probably a hard task, but you know,
12everything is hard until you learn how to do it.
13
14I wanted to do this for a couple of reasons. The main one was to use my
15`@tronto.net` email address, but I also liked the idea of staying away
16from large internet companies (my main email address was connected to my
17Google account). Not that there is anything inherently wrong with using
18services from this big companies, but I like the idea of not being too
19dependent on them.
20
21After reading
22[a nice tutorial at poolp.org](https://poolp.org/posts/2019-09-14/setting-up-a-mail-server-with-opensmtpd-dovecot-and-rspamd/)
23I was a bit discouraged. The guide was well-written, all the steps seemed
24doable if taken one by one, and I was happy to have dug into this topic
25because I learned a lot. However, an email server apparently consists of
26a lot of moving pieces: an smtp server, spam filter, DNS, DKIM... it is
27a lot to keep track of. Even assuming that I would be able to set this
28thing up AND to keep in mind what each of these pieces does, as soon as a
29problem of any kind arises - config-breaking updates? domain registration
30expiring? me messing up with my VM and making it unreachable? - I knew I
31had to be one to fix the mistake. And I cannot afford to be immediately
32available whenever something bad happens. Sometimes I might just have a
33full week were I don't have time to fiddle around with smtpd and whatnot,
34and I can't afford being unreachable via email for a week.
35
36## My old setup (until September 2022)
37
38Having abandoned the idea of self-hosting, I looked for alternatives. I
39figured that if my goals were just to use my own domain and stay away
40from Google, I could sign up for a smaller email provider that offers
41custom domains. It turns out there are a lot of them. After some careful
42considerations I decided to go with [mailbox.org](https://mailbox.org). I
43like their transparency and privacy focus and the fact that they are
44based in the EU. I pay 3€ per month (the 1€ tier does not offer
45custom domains) and I am happy with their service.
46
47Setting up the server side was quite simle. Using custom domains
48requires a tiny bit of work, but it was all well explained in the
49[FAQs](https://kb.mailbox.org/en/private/custom-domains).
50
51On my local machine I used (and still use) the amazing
52[mblaze](https://github.com/leahneukirchen/mblaze), which is essentially
53[MH](https://en.wikipedia.org/wiki/MH_Message_Handling_System)
54for [Maildir](https://en.wikipedia.org/wiki/Maildir) folders.
55In practice, mblaze is a set of commands to manage emails directly
56from the command line, without using a graphical environment or a
57[TUI](https://en.wikipedia.org/wiki/Text-based_user_interface) like
58[Mutt](https://en.wikipedia.org/wiki/Mutt_(email_client)). This system
59is incredibly flexible, check it out if you don't know it!
60
61Being just a mail user agent, mblaze cannot retrieve or send
62email. These tasks can be accomplished by other small pieces of
63software: I used [msmtp](https://marlam.de/msmtp) for sending
64email and [mpop](https://marlam.de/mpop) for downloading it
65from mailbox.org's server. As the name suggests, mpop uses the
66[POP3](https://en.wikipedia.org/wiki/Post_Office_Protocol)
67protocol instead of the more common
68[IMAP](https://en.wikipedia.org/wiki/Internet_Message_Access_Protocol).
69The main difference is that POP3 simply retrieves your email, while
70IMAP keeps the server and client folders synchronized. There are many
71advantages and disadvantages to this choice, I won't go into detail on
72them in this post.
73
74As for my other devices, my local mailfolder is kept in sync with my
75server using [syncthing](https://syncthing.net). I also use an amail
76client on my phone with IMAP, connected directly to the mail server.
77
78## Nitpicking
79
80Since I am subscribed to a couple of high-traffic mailing lists that
81I read just for curiosity, it is necessary for me to have an easy way
82to download and view regular emails separately from that coming from
83mailing lists.
84
85This was kinda easy to set up with mpop's filters, but my configuration
86was a bit of a hack. One disadvantage of this soution was that it
87only solved the problem on my laptop(s). On my webmail and on my phone,
88my inbox was a complete mess of mailing lists, newsletter and a few
89important emails.
90
91After thinking about it for a while I figured that an elegant solution
92would be to set up alternative email addresses for receiving mailing
93list emails, like `list@tronto.net`. Then I would manage those different
94mailboxes separately.
95
96Setting the aliases up on mailbox.org was easy, but unfortunately all my
97`@tronto.net` address used the same inbox, so I did not solve any problem
98at all. I could add some sub-folders and set up filters so that incoming
99mail gets sorted out, but the app on my phone could not read sub-folders
100and mailbox did not allow top-level folders (or I could not find a way to
101create them). Besides, tinkering with IMAP folders was not something
102that I found particularly exciting.
103
104But there was another solution...
105
106## My current setup (since September 2022)
107
108I decided to try and redirect the mailing list emails to my personal
109server. Configuring OpenBSD's smtp to receive emails from one specific
110outside source (my mailbox.org account) and sort them into some local
111folders is order of magnitudes easier than setting up a full-fledged
112email server. No problems with DKIM, no incoming spam, no nothing.
113
114It took me a few hours to figure our how to do this, but in the
115end it is just a matter of configuring a few filters on mailbox.org
116and adding a couple of lines to `/etc/mail/stmp.conf`.
117
118### mailbox.org filters
119
120On my mailbox.org webmail I simply set up a filter to redirect any email
121sent to `list@example.com` (a made-up name for the mailing list I am
122subscribed to) to my private server. No copy of these emails is kept on
123the server, so they don't clutter my normal (IMAP) inbox. I risk missing
124a few of these emails if my server goes down, but it is a public mailing
125list and I can always check the archives online.
126
127I could not just send these emails to `something@tronto.net`, otherwise
128they would simply be taken care of by mailbox - the MX records for my
129domain point to their servers. But it turns out you can send mail to
130a server using its IP address, as long as the server is configured to
131accept such mail. So I set up the redirects to `list@[46.23.91.214]` -
132where `46.23.91.214` is the IP address of my server.
133
134### smtpd.conf
135
136The second step is configuring smtpd, OpenBSD's default mail server
137daemon, to deal with incoming email.
138
139First of all we need to list the virtual user `list` in
140`/etc/mail/aliases` so that any mail sent to it is interpreted as being
141sent to my regular user.
142
143```
144# cat 'list: sebastiano' >> /etc/mail/aliases
145```
146
147Then we have to change the line `listen on lo0` to `listen on all`
148in `/etc/smtp.conf`.
149
150Then we need to add an `action` and a `match` lines to the same file:
151
152```
153# cat << EOF >> /etc/mail/smtpd.conf
154> action "list" maildir "~/mail/list" alias <aliases>
155> match from any for rcpt-to "list@[46.23.91.214]" action "list"
156> EOF
157```
158
159And finally restart smtpd with `rcctl restart smtpd`.
160
161This does the trick: now all email I receive from the `list@example.com`
162mailing list is redirected by my mailbox account to my private server,
163where smtpd takes care of sending it to the mail directory `~/mail/list`.
164
165### No mpop needed
166
167Once the mail is delivered to `~/mail/list`, I can get it from there
168to my laptop in any way I like - for example using syncthing, like I
169do for all my important files. In this way the mailing list emails are
170regularly downloaded and kept in sync, and I don't need to use mpop to
171retrieve them.
172
173This is quite convenient, one less piece of software to keep track of!
174In fact, I can do the same for all other email I receive. I just need
175to set up the appropriate rules on mailbox: this time I want the mail
176to be sent to `sebastiano@[46.23.91.214]` and *a copy to be kept on the
177mailbox.org server*, so that I can easily access it from my phone's app as
178well. Then I add two slightly different lines to `/etc/mail/smtpd.conf`:
179
180```
181# cat << EOF >> /etc/mail/smtpd.conf
182> action "seb" maildir "~/mail/inbox" user sebastiano
183> match from any for rcpt-to "sebastiano@[46.23.91.214]" action "seb"
184> EOF
185```
186
187And the new setup is ready!
188
189### Sending email
190
191I did not change the way I send email: I still use msmtp.
192
193## Happy now?
194
195Yes, this new setup works and I am always happy when things work.
196Of course, one might make the case that things worked before as well...
197
198I am happy that I could work my way around a basic smtpd configuration.
199Besides being useful knowledge on its own, it may make a second attempt
200at self-hosting my email less daunting. I don't know if I am ever going
201to try that, though.
diff --git a/src/blog/2022-11-23-git-host/git-host.md b/src/blog/2022-11-23-git-host/git-host.md
new file mode 100644
index 0000000..cc9fc27
--- /dev/null
+++ b/src/blog/2022-11-23-git-host/git-host.md
@@ -0,0 +1,299 @@
1# Self-hosted git pages with stagit (featuring ed, the standard editor)
2
3This is a follow-up to my earlier blog entry
4[How I update my website](../2022-08-14-website).
5
6If you work on one or more personal software projects as a hobby,
7chances are you are using `git`. To publish your project online
8you may be using a website like GitHub, or perhaps a more
9open source friendly alternative such as
10[GitLab](https://about.gitlab.com/) or [sourcehut](https://sourcehut.org/).
11
12But have you considered hosting your repositories, and serving them
13via web pages, on your personal server? In this post I am going to show
14you how I do it, in the usual minimalist and
15not-using-what-I-do-not-understand style.
16
17You can see the final result on my [git pages](https://git.tronto.net).
18The scripts and other files I use to set this up are accessible
19[here](https://git.tronto.net/git-hooks).
20
21## Hosting git repositories on your own server
22
23This step is quite simple, and you can just follow
24[Roman Zolotarev's tutorial](https://rgz.ee/git.html) like I did - adapting
25the first few steps to your OS if you are not running OpenBSD.
26
27To sum it up, you need to:
28
291. Create a dedicate `git` account on your server (optional, if you know
30 what you are doing).
31
322. Add your public SSH key to the `~/.ssh/authorized_keys` file of your newly
33 created remote account.
34
353. Initialize a git repository on your server with `git init REPOSITORY`.
36
374. Clone it via SSH with `git clone git@SERVER:REPOSITORY`.
38
39And you are done! If you want to use multiple remotes, for example your private
40server and GitHub, you can do so by adding a push-only URL with
41`git remote set-url --add --push origin URL`. But don't trust me on this
42exact command, I always have to look it up
43- you should do the same before running it.
44
45Now your repositories are online, but how can you make them browsable via web?
46
47## stagit
48
49The tool I use to serve my git repositories as static web pages is
50[stagit](https://codemadness.org/stagit.html). It is very easy to describe what
51stagit does: running it on a git reporitory produces some directories with
52a bunch of html files that you can simply move to your www hosting directory.
53
54After generating the pages you can personalize them by copying your logo,
55[favicon](https://en.wikipedia.org/wiki/Favicon) or CSS style sheet. You can
56use `stagit-index` to generate
57[an index page for your repositories](https://git.tronto.net/). Since everything
58consists of html files, you can simply edit them to personalize your git pages
59even further - and below you'll see some examples.
60
61But you definitely do not want to do this by hand every time you push a commit.
62Since the pages stagit generates are *static*, they do not update
63automatically: you'll have to run stagit again every time. You can automate
64this for example by running stagit periodically with cron, but there is an
65easier way:
66[git hooks](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks).
67
68## Git hooks
69
70By saving suitably named executable files inside your project's
71`.git/hooks` directory you can automate any process you want during
72certain stages of your git workflow. For example you can use a `pre-commit`
73script to run commands before you commit changes, or a `pre-push` script
74to do something before pushing a commit.
75
76The hooks are divided in client-side and server-side. We are interested in
77the server-side `post-receive` hook, which is executed on the remote every
78time a commit is received. This is the last ingredient we need for our setup:
79a simple `post-receive` hook that runs stagit and copies the files it
80generates to the appropriate folder will do the trick.
81
82## My setup
83
84Throughout the rest of the post I will use the following variables, to be
85set at the beginning of the script:
86
87```
88yourname="Sebastiano Tronto" # Author's name
89repo="$PWD" # The full path of the repository
90name="$(basename $repo .git)" # The name of the repository
91baseurl="https://git.tronto.net" # The base URL for the repository
92basedir="/var/www/htdocs/git.tronto.net" # The base directory for www files
93htdir="$basedir/$name" # The www directory for the repository
94```
95
96### Basic stagit usage
97
98The first thing we want to do is to set up some basic information in the
99`owner` and `url` files that stagit is going to use. The hook is run in the
100repository's directory, so it is not necessary to specify a full path:
101
102```
103echo "$yourname" > owner
104echo "$baseurl/$name" > url
105```
106
107Next we prepare the target directory by removing old files and creating
108it if necessary:
109
110```
111rm -rf "$htdir"
112mkdir -p "$basedir"
113```
114
115To make the repository clonable by anyone from the same URL used to
116view it, we need to copy the whole directory to the
117www directory we have just created:
118
119```
120cp -r "$repo" "$htdir"
121```
122
123And finally we can run stagit:
124
125```
126cd "$htdir"
127stagit -l 100 "$repo"
128```
129
130The `-l` option is used to specify how many commits should be visibile
131in the log page.
132
133For some basic personalization we can choose a different default page (index
134file). I like to have the file list:
135
136```
137cp "$htdir/files.html" "$htdir/index.html"
138```
139
140And we can use our css style sheet, logo and icon:
141
142```
143cp $filesdir/favicon.png ./
144cp $filesdir/logo.png ./
145cp $filesdir/style.css ./
146```
147
148### Bells and whistles
149
150I like stagit's simplicity, but there are a couple of things that I want to
151add or change:
152
153* I would like every page to show a simple footer at the bottom of
154 each page.
155* I would like to have a download button so that people who don't use git
156 can still download my files. This makes sense especially for those
157 repos that are mostly documents, such as my
158 [lecture notes](https://git.tronto.net/mathsoftware) or my
159 [FMC tutorial](https://git.tronto.net/fmctutorial).
160* I would like to convert README.md files to html.
161
162If I were calling stagit by hand after each `git push`, I
163could simply make these changes with a text editor. But I want to automate
164this! How can we edit files in a shell script?
165
166Enter `ed`, [the standard editor](https://www.gnu.org/fun/jokes/ed-msg.html).
167`ed` is a [line text editor](https://en.wikipedia.org/wiki/Line_editor)
168initially released with UNIX Version 1. I am going to talk about it more
169extensively in the next episode of my
170[man page reading club](../2022-05-29-man/)
171series. Without going into detail, `ed` does not show you the text you
172are editing in a 2-dimensional windows: instead, it offers you a command
173line prompt that you can use to run editing commands, such as `a` to add
174text or `p` to print one or more lines of the file.
175
176This might seems like a totally cumbersome way of editing a file, but
177there is one nice side-effect: `ed` is completely scriptable. This means
178that if you know exactly what the file you want to edit looks like,
179you can write the commands you want to run in advance and feed them to
180the editor via standard input, instead of typing them interactively.
181This is exactly what we want to do!
182
183Going back to my stagit setup, say we have a file `bottom.html` that
184looks like this:
185
186```
187<hr class="line">
188<footer> <table>
189<tr> <td class="contact">
190 Back to <a href="https://sebastiano.tronto.net"> sebastiano.tronto.net </a>
191</td>
192<td class="hosted">
193 Generated with <a href="https://codemadness.org/stagit.html">stagit</a>
194</td> </tr>
195</table> </footer>
196```
197
198and we want to insert its content in the file `file.html`, before
199the line that contains the closing tag `</body>`. We can use the
200following one-liner:
201
202```
203printf '%s\n' "/<\/body>" i "$(cat bottom.html)" . w | ed -s file.html
204```
205
206Here the `printf` command is used to feed the tokens `/<\/body>`, `i`,
207`$(cat bottom.html)`, `.` and `w` to `ed`. These are going to
208be interpreted as: "search for the closing tag `</body>`;
209insert the following text until you encounter a single dot on a line:
210[contents of the file `bottom.html`] single dot; save."
211If this seems obscure, I suggest you read
212[`ed`'s manual page](https://man.openbsd.org/OpenBSD-7.2/ed), or wait
213for my next blog post!
214
215The command for adding the download button is similar, after we
216generate a zip archive of the repository using `git archive`:
217
218```
219git archive HEAD -o "$basedir/$name.zip"
220printf '%s\n' \
221 "/log\.html\">Log<\/a>" i \
222 "<a href=\"$baseurl/$name.zip\">Download</a> |" . w \
223| ed -s file.html
224```
225
226Here I am using backlashes to ignore the newline character, so that
227I can use more lines for readability.
228
229The two code snippets above have to be run for every html file generated
230by stagit. To loop over all these files, you can use `find`:
231
232```
233for f in $(find "$htdir" -name "*.html"); do
234 [stuff...]
235done
236```
237
238The command to turn README.md files into a formatted html page is a bit
239more complicated, but I will try to keep the explanation short, since
240this post is already quite long. Feel free to send me an email if you
241have questions!
242
243To have an idea of what the README.md.html file generated by
244stagit looks like, you can check out the html of
245[this page](https://codemadness.org/git/stagit/file/README.html),
246for example (right click and "View page source" or something similar in
247most browsers, or `curl [URL]` if you are cool).
248
249First, since I am using bare git repositories, I need to actually "create"
250the original README.md file - instead of using its rendered-as-plain-text
251html version generated by stagit - using `git show`. Then we need to
252remove from README.md.html all the lines that
253are part of the code listing, i.e. all those that contain a `class="line"`
254string. The `ed` command to do this is `g/class=\"line\"/d`. Then we
255need to remove a couple more lines and finally we can insert the result
256of the command `lowdown file/README.md`, which converts the markdown
257file to html, into the correct place. The final result is:
258
259```
260git show master:README.md > file/README.md
261printf '%s\n' \
262 g/class=\"line\"/d \
263 "/<pre id=\"blob\">" d d i "$(lowdown file/README.md)" . w \
264| ed -s file/README.md.html > /dev/null
265```
266
267### stagit-index
268
269Just a quick mention to how I use stagit-index, the command used to
270generate the index page.
271The only change I make from the default configuration is to change
272the links to each repository to point to the file list instead
273of the log page. stagit-index writes its result to standard output, so
274I can simply use `sed`:
275
276```
277stagit-index /home/git/*.git | sed 's|/log\.html||g' > "$basedir/index.html"
278```
279
280And that's it. Well, I also copy the style files and add a bottom bar,
281and change the title from a `<span class="desc">` to an `<h1>` element,
282again using `ed`. If you want to see the details you can check them out
283[here](https://git.tronto.net/git-hooks/file/post-receive-stagit.html).
284
285## Conclusions
286
287stagit is the perfect minimalist tool to publish your git repository
288with a simple, static web interface. It requires nothing more than
289an http server capable of serving html files. Static files are also
290very simple to customize and tune to your needs.
291
292I have wanted to make this post for quite some time now, mainly
293as an excuse to clean up and document my scripts. I finally had some
294time to work on this - even if scattered around multiple days.
295
296As always, I have tried but failed to keep my post short - I am too
297eager to explain everything I know as clearly as possbile!
298I hope you enjoyed or found it useful. If you have questions or comments,
299feel free to send me an [email](mailto:sebastiano@tronto.net).
diff --git a/src/blog/blog.md b/src/blog/blog.md
index 8399626..3ffa250 100644
--- a/src/blog/blog.md
+++ b/src/blog/blog.md
@@ -2,6 +2,8 @@
2 2
3[RSS Feed](feed.xml) 3[RSS Feed](feed.xml)
4 4
5* 2022-11-23 [Self-hosted git pages with stagit (featuring ed, the standard editor)](2022-11-23-git-host)
6* 2022-10-19 [Keeping my email sorted (the hard way)](2022-10-19-email-setup)
5* 2022-10-01 [The man page reading club: tetris(6)](2022-10-01-tetris) 7* 2022-10-01 [The man page reading club: tetris(6)](2022-10-01-tetris)
6* 2022-09-20 [The man page reading club: sh(1) - part 2: commands and builtins](2022-09-20-sh-2) 8* 2022-09-20 [The man page reading club: sh(1) - part 2: commands and builtins](2022-09-20-sh-2)
7* 2022-09-13 [The man page reading club: sh(1) - part 1: shell grammar](2022-09-13-sh-1) 9* 2022-09-13 [The man page reading club: sh(1) - part 1: shell grammar](2022-09-13-sh-1)
diff --git a/src/blog/feed.xml b/src/blog/feed.xml
index 1cf4313..0efe9ec 100644
--- a/src/blog/feed.xml
+++ b/src/blog/feed.xml
@@ -9,6 +9,20 @@ Thoughts about software, computers and whatever I feel like sharing
9</description> 9</description>
10 10
11<item> 11<item>
12<title>Self-hosted git pages with stagit (featuring ed, the standard editor)</title>
13<link>https://sebastiano.tronto.net/blog/2022-11-23-git-host</link>
14<description>Self-hosted git pages with stagit (featuring ed, the standard editor)</description>
15<pubDate>2022-11-23</pubDate>
16</item>
17
18<item>
19<title>Keeping my email sorted (the hard way)</title>
20<link>https://sebastiano.tronto.net/blog/2022-10-19-email-setup</link>
21<description>Keeping my email sorted (the hard way)</description>
22<pubDate>2022-10-19</pubDate>
23</item>
24
25<item>
12<title>The man page reading club: tetris(6)</title> 26<title>The man page reading club: tetris(6)</title>
13<link>https://sebastiano.tronto.net/blog/2022-10-01-tetris</link> 27<link>https://sebastiano.tronto.net/blog/2022-10-01-tetris</link>
14<description>The man page reading club: tetris(6)</description> 28<description>The man page reading club: tetris(6)</description>

Generated with cgit - Back to sebastiano.tronto.net