summaryrefslogtreecommitdiff
path: root/content/posts/2022
diff options
context:
space:
mode:
Diffstat (limited to 'content/posts/2022')
-rw-r--r--content/posts/2022/2022-02-14-librewolf.md92
-rw-r--r--content/posts/2022/2022-02-20-nginx-tls.md92
-rw-r--r--content/posts/2022/2022-03-05-deprecating-reiserfs.md74
-rw-r--r--content/posts/2022/2022-04-15-fixing-w-in-tremc.md140
-rw-r--r--content/posts/2022/2022-04-23-a-cookbook.md52
-rw-r--r--content/posts/2022/2022-05-07-bashtard-introduction.md265
-rw-r--r--content/posts/2022/2022-08-06-installing-gentoo-encrypted-zfs-efistub.md242
-rw-r--r--content/posts/2022/_index.md3
8 files changed, 960 insertions, 0 deletions
diff --git a/content/posts/2022/2022-02-14-librewolf.md b/content/posts/2022/2022-02-14-librewolf.md
new file mode 100644
index 0000000..0152244
--- /dev/null
+++ b/content/posts/2022/2022-02-14-librewolf.md
@@ -0,0 +1,92 @@
+---
+date: 2022-02-14
+title: Trying out LibreWolf
+tags:
+- Firefox
+- LibreWolf
+---
+
+Over the past week, I've been trying out [LibreWolf](https://librewolf.net/) as
+an alternative to mainline Firefox. I generally don't hold a high opinion on any
+"modern" browser to begin with, but Firefox has been the least bad for quite
+some time. I used to actually like Firefox, but Mozilla has done their best to
+alienate their user base in search for profits, and is eventually left with
+neither. Their latest effort in digging their own grave is teaming up with Meta.
+
+As such, I have been searching for an alternative (modern) browser for a long
+time. One major requirement that I've had is to have something like
+[uMatrix](https://addons.mozilla.org/en-US/firefox/addon/umatrix/). And
+obviously major features to block any and all advertisements, as these are a
+major detriment to your own mental health, and to the resources your machine
+uses. So, when someone recommended me LibreWolf, which is just a more
+user-respecting fork of Firefox, I didn't hesitate to try it out.
+
+The migration from Firefox to LibreWolf was remarkably simple. Since I use [a
+small
+wrapper](https://git.tyil.nl/dotfiles/tree/.local/bin/firefox?id=1c8e9b136d9d00decc1d3570fe58072427107148)
+to launch Firefox with a specific profile directory, I just had to update that
+to launch LibreWolf instead. It kept all my settings, installed add-ons, and even
+open tabs. It seems that by default, however, it will use its own directory for
+configuration. If you want to try out LibreWolf and have a similar experience,
+you can just copy over your old Firefox configuration directory to a new
+location for use with LibreWolf. In hindsight, that probably would've been the
+safer route for me as well, but it already happened and it all went smooth, so
+no losses.
+
+Now, while LibreWolf is more-or-less like Firefox, but less harmful to its own
+users, some of the tweaks made by the LibreWolf team may or may not be desired.
+I've taken note of any differences that could be conceived as issues. So far,
+they're not breaking for me, but these may be of interest to you if you're
+looking to try LibreWolf out as well.
+
+## HTTP
+
+By default, LibreWolf will not let you visit sites over HTTP. This is generally
+a very nice feature, but for some public hot-spots, this may cause issues. These
+are generally completely unencrypted, and LibreWolf will refuse to connect. The
+page presented instead will inform you that the page you're trying to visit is
+unencrypted, and allow you to make a temporary exception. Not a very big issue,
+but it may be a little bit more annoying than you're used to.
+
+## Add-ons
+
+While all my add-ons were retained, I did want to get another add-on to redirect
+me away from YouTube, to use an Invidious instance. The page for installing
+add-ons itself seems to work fine, but upon clicking the Install button, and
+accepting the installation, LibreWolf throws an error that it simply failed to
+install anything. The Install button is nothing more than a fancy anchor with a
+link to the `xpi` file, so you can manually download the file and install the
+add-on manually through the [Add-ons Manager](about:addons).
+
+## Element
+
+I've been using Matrix for a while, as an atechnical-friendly, open source
+platform, for those unwilling to use IRC. Their recommended client,
+[Element](https://app.element.io/), is just another web page, because that's
+sadly how most software is made these days. The chat itself works without a
+hitch, but there are two minor inconveniences compared to my regular Firefox
+setup.
+
+The first one is that LibreWolf does not share my local timezone with the
+websites I visit. This causes timestamps to be off by one hour in the Element
+client. A very minor issue that I can easily live with.
+
+The other is that the "default" icons, which is a capital letter with a colored
+background, [don't look so well](https://dist.tyil.nl/blog/matrix-icons.png).
+There's some odd artifacts in the icons, which doesn't seem to affect the letter
+shown. Since I mostly use the
+[weechat-matrix](https://github.com/poljar/weechat-matrix) plugin, it's not
+really an issue. And for the few times I do use Element, it doesn't bother me
+enough to consider it a real issue.
+
+## Jellyfin
+
+For consuming all sorts of media, I have [Jellyfin](https://jellyfin.org/) set
+up for personal use. This worked fine in my regular Firefox setup, but does not
+seem to be willing to play any videos in LibreWolf. The console logs show some
+issues with websockets, and I've not been able to find a good way to work around
+this yet. For now, I'll stick to using `mpv` to watch any content to deal with
+this issue.
+
+All in all, I think LibreWolf is a pretty solid browser, and unless I discover
+something major to turn me off, I'll keep using it for the foreseeable future.
diff --git a/content/posts/2022/2022-02-20-nginx-tls.md b/content/posts/2022/2022-02-20-nginx-tls.md
new file mode 100644
index 0000000..0baef43
--- /dev/null
+++ b/content/posts/2022/2022-02-20-nginx-tls.md
@@ -0,0 +1,92 @@
+---
+date: 2022-02-20
+title: Updating NginX TLS settings for 2022
+tags:
+- TLS
+- NginX
+---
+
+My blog (and pretty much every other site I host) is using Let's Encrypt
+certificates in order to be served over https. Using any certificate at all is
+generally an upgrade when it comes to security, but your webserver's
+configuration needs to be up to standard as well. Unlike the Let's Encrypt
+certificates, keeping the configs up to date requires manual intervention, and
+is therefore something I don't do often.
+
+This week I decided I should check up on the state of my SSL configuration in
+nginx. I usually check this through [SSL Lab's SSL Server
+Test](https://www.ssllabs.com/ssltest/analyze.html). This is basically
+[testssl.sh](https://testssl.sh/) in a shiny web frontend, and assigns you a
+score. I aim to always have A or higher, but it seemed my old settings were
+capped at a B. This was due to the cipher list allowing ciphers which are
+nowadays considered insecure.
+
+While I could've just updated the cipher list, I decided to check up on all the
+other settings as well. There's a [GitHub
+gist](https://gist.github.com/gavinhungry/7a67174c18085f4a23eb) which shows you
+what settings to use with nginx to make it secure by modern standards, which
+I've used to check if I should update some of my own settings.
+
+My old settings looked as follows. Please don't be too scared of the giant list
+in the `ssl_ciphers`.
+
+```nginx
+# DHparams
+ssl_dhparam /etc/nginx/dhparam.pem;
+
+# SSL settings
+ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS';
+ssl_prefer_server_ciphers off;
+ssl_protocols TLSv1.2 TLSv1.3;
+ssl_session_cache shared:le_nginx_SSL:10m;
+ssl_session_tickets off;
+ssl_session_timeout 1440m;
+
+# Additional headers
+add_header Strict-Transport-Security "max-age=63072000" always;
+```
+
+With the new settings, I've added `ssl_buffer_size` and `ssl_ecdh_curve`. A
+friend on IRC pointed out I should enable `ssl_prefer_server_ciphers`, so this
+has been enabled too.
+
+But most notably, the list of `ssl_ciphers` has been dramatically reduced. I
+still allow TLSv1.2 in order to allow slightly older clients to connect without
+any issues, but the ciphers considered *WEAK* have been disabled explicitly.
+This leaves a total of 5 ciphers to use, all of them using ECDHE, so the
+`ssl_dhparam` could be dropped as well.
+
+Lastly, I've added a couple headers for security reasons, as recommended by
+[securityheaders.com](https://securityheaders.com).
+
+```nginx
+# SSL settings
+ssl_protocols TLSv1.3 TLSv1.2;
+
+ssl_buffer_size 4K;
+ssl_ecdh_curve secp521r1:secp384r1;
+ssl_prefer_server_ciphers on;
+ssl_session_cache shared:le_nginx_SSL:2m;
+ssl_session_tickets off;
+ssl_session_timeout 1440m;
+
+ssl_ciphers 'EECDH+AESGCM:EECDH+AES256:!ECDHE-RSA-AES256-SHA384:!ECDHE-RSA-AES256-SHA';
+
+# Additional headers
+add_header Content-Security-Policy "default-src 'self'" always;
+add_header Referrer-Policy "strict-origin-when-cross-origin" always;
+add_header Strict-Transport-Security "max-age=63072000" always;
+add_header X-Content-Type-Options "nosniff" always;
+add_header X-Frame-Options "SAMEORIGIN" always;
+```
+
+{{< admonition title="note" >}}
+I would still like the `ssl_ciphers` to be formatted in a more clean way, which
+I've tried to do with a variable through `set`, but it appears variables are not
+expanded within `ssl_ciphers`. If you have any methods to format the list of
+ciphers used in a cleaner way, I'd be very happy to know!
+{{< / admonition >}}
+
+This configuration is saved as a small snippet which I `include` in all other
+site configurations, so it is updated everywhere at once as well. Now I should
+be able to neglect this for another year or two again.
diff --git a/content/posts/2022/2022-03-05-deprecating-reiserfs.md b/content/posts/2022/2022-03-05-deprecating-reiserfs.md
new file mode 100644
index 0000000..9dcec8d
--- /dev/null
+++ b/content/posts/2022/2022-03-05-deprecating-reiserfs.md
@@ -0,0 +1,74 @@
+---
+date: 2022-03-05
+title: Deprecating ReiserFS
+tags:
+- BTRFS
+- Filesystems
+- GNU+Linux
+- ReiserFS
+- ZFS
+- bcachefs
+---
+
+[ReiserFS is getting deprecated from Linux](https://lkml.org/lkml/2022/2/20/89),
+mostly due to it not being ready for the year 2038. This is a little sad, as I
+still use it on some systems for storing the Gentoo Portage tree, and the Linux
+kernel sources. It works well for this because it supports
+[tail packing](https://en.wikipedia.org/wiki/Block_suballocation#Tail_packing),
+a form of block suballocation, which can save disk space.
+
+So, what alternatives are there for ReiserFS? After asking around and reading
+some comments around the Internet, I've narrowed it down to 3 potential
+candidates, bcachefs, btrfs, and zfs. Each comes with their own pros and cons,
+as things tend to do.
+
+## bcachefs
+
+There are several downsides for bcachefs for me. The first one I found was that
+the documentation on their main site seems a bit lacking, followed shortly by
+finding that there are no ebuilds for it in Gentoo.
+
+Since it was suggested several times on comments on a certain orange site, I
+asked around if it at least supported block suballocation, which is the main
+reason I would want to use it anyway. The answer came back as a "no", so I could
+safely ignore it for the rest of the journey.
+
+## BTRFS
+
+BTRFS seems like a more serious contender. It supports block suballocation, and
+has good enough documentation. As an additional benefit, it is supported in the
+mainline Linux kernel, making it easy to use on any modern setup. There are a
+few issues, such as having to rebalance in certain situations, and this
+rebalancing can itself cause issues. The files I'm storing are relatively easily
+recreated with a single git clone, or downloading a tarball and unpacking that,
+so that doesn't have to be problematic to me.
+
+## ZFS
+
+The final contestant, ZFS, supports block suballocation and has great
+documentation. It is not part of the mainline Linux kernel, however, so this may
+make things more complex on some systems. I run ZFS already on a few machines,
+but not all, so where it is not used already, it is a drawback.
+
+Since my main concern is storing many small files, I created a few logical
+volumes (and 1 ZFS subvol) and cloned the main reason for wanting a filesystem
+with block suballocation, the [Gentoo Portage
+tree](https://github.com/gentoo/portage). The cloning itself was done with
+`--depth=1`.For reference, I also created an ext4 volume.
+
+```
+/dev/mapper/edephas0-test.btrfs 5.0G 559M 3.8G 13% /tmp/test/btrfs
+/dev/mapper/edephas0-test.ext4 4.9G 756M 3.9G 17% /tmp/test/ext4
+/dev/mapper/edephas0-test.reiserfs 5.0G 365M 4.7G 8% /tmp/test/reiserfs
+tyilstore0/test 5.0G 1.1G 4.0G 21% /tmp/test/zfs
+```
+
+Looking at the output from `df -h`, ReiserFS seem to still be a clear winner
+when it comes to storing many small files. Nothing is even close. What does
+surprise me, however, is that ZFS is actually resulting in the largest space
+requirement. I'm not sure why this is, as it should support block suballocation
+just fine according to [the filesystem comparison chart on
+Wikipedia](https://en.wikipedia.org/wiki/Comparison_of_file_systems#Allocation_and_layout_policies).
+
+BTRFS comes out as the next best option, after ReiserFS, so that'll be what I am
+going to use on my systems for storing large trees of small files.
diff --git a/content/posts/2022/2022-04-15-fixing-w-in-tremc.md b/content/posts/2022/2022-04-15-fixing-w-in-tremc.md
new file mode 100644
index 0000000..c434a6e
--- /dev/null
+++ b/content/posts/2022/2022-04-15-fixing-w-in-tremc.md
@@ -0,0 +1,140 @@
+---
+date: 2022-04-15
+title: Fixing ^w in tremc
+tags:
+- Python
+- Transmission
+- tremc
+---
+
+I like collecting GNU+Linux ISOs. I'd like to think I have a pretty serious
+collection of these things. I have a pretty good and stable Internet connection,
+so I collect them in my torrent client, and let them seed pretty much forever,
+so other people can enjoy them too.
+
+For this hobby, I'm using [Transmission](https://transmissionbt.com/), with
+[tremc](https://github.com/tremc/tremc) as the frontend. I've been using it for
+a while, but there's always been a small thing bothering me. Whenever you get a
+prompt to specify the name of the torrent, or the directory to which its
+contents should be downloaded, `^w` immediately kills the entire application.
+
+By regular shell standards, I'm used to `^w` not killing the application, but
+just removing from the cursor to the start of the previous word. I don't often
+change the names of the torrents, but when I do, I often use `^w` to quickly
+remove one or two words in the path. With tremc, this sadly means me killing the
+application, being upset for a little while as I restart it, and hold down the
+backspace for a while to get the intended effect.
+
+Until last night. I set out to read the documentation to fix this issue once and
+for all. I dug into the manual, which specifies that a configuration file at
+`~/.config/tremc/settings.cfg` is read at startup. However, the manual
+doesn't specify anything about the format of this file. There's also no other
+manual pages included in the package.
+
+The Gentoo package specifies a homepage for this project on Github, so I open up
+my least-hated browser and see if there's anything there. Good news, the
+repository contains a sample `settings.cfg`, so I can read that and get an idea
+on how to do keybinds. And the examples do show how to _set_ keybinds. But it
+doesn't seem to be able to _remove_ keybinds. This is kind of a bummer. Setting
+a keybind to an empty value didn't seem to do the trick either. This leaves only
+one option, patching the defaults.
+
+This was actually pretty straightforward, just look for the list of default
+keybinds, and remove a single line.
+
+```patch
+@@ -222,7 +222,6 @@ class GConfig:
+ # First in list: 0=all 1=list 2=details 3=files 4=tracker 16=movement
+ # +256 for RPC>=14, +512 for RPC>=16
+ 'list_key_bindings': [0, ['F1', '?'], 'List key bindings'],
+- 'quit_now': [0, ['^w'], 'Quit immediately'],
+ 'quit': [1, ['q'], 'Quit'],
+ 'leave_details': [2, ['BACKSPACE', 'q'], 'Back to torrent list'],
+ 'go_back_or_unfocus': [2, ['ESC', 'BREAK'], 'Unfocus or back to torrent list'],
+```
+
+Since I'm just testing, and this program is a single Python file, I just edit
+the file in-place, and delay making a proper patch out of for later. Restarting
+tremc, going to the new torrent, pressing `m` (for "move"), and hitting `^w` to
+try and remove a single word, hoping for a quick and easy fix, I was met with
+tremc just quitting again. This was not what I wanted.
+
+So opening up the file again with everyone's favourite editor, I search around
+for the `quit_now` function. Surely that'll bring me closer? The `quit_now`
+string doesn't seem to be used anywhere else, apart from the function that
+defines what the keybind action should do, `action_quit_now`. This seems to
+simply defer to `exit_now`, which leads me to a bit of code with a special case
+to `exit_now` if a certain character is detected. This character appears to be a
+`^w`, which is exactly what I'm trying to stop. So, let's patch that out too.
+
+```patch
+@@ -3760,10 +3759,7 @@ class Interface:
+ self.update_torrent_list([win])
+
+ def wingetch(self, win):
+- c = win.getch()
+- if c == K.W_:
+- self.exit_now = True
+- return c
++ return win.getch()
+
+ def win_message(self, win, height, width, message, first=0):
+ ypos = 1
+```
+
+Restart tremc and test again. Still exiting immediately upon getting a `^w`.
+This bit of code gives me some new insights, it appears `K.W_` is related to the
+keycode of a `^w`. So I continue the search, this time looking for `K.W_`. This
+appears to be used later on to create a list of characters which should act as
+`esc` in certain contexts. Removing the `K.W_` from this is simple enough.
+
+```patch
+@@ -5039,7 +5047,7 @@ def parse_config_key(interface, config, gconfig, common_keys, details_keys, list
+ else:
+ gconfig.esc_keys = (K.ESC, K.q, curses.KEY_BREAK)
+ gconfig.esc_keys_no_ascii = tuple(x for x in gconfig.esc_keys if x not in range(32, 127))
+- gconfig.esc_keys_w = gconfig.esc_keys + (K.W_,)
++ gconfig.esc_keys_w = gconfig.esc_keys
+ gconfig.esc_keys_w_enter = gconfig.esc_keys_w + (K.LF, K.CR, curses.KEY_ENTER)
+ gconfig.esc_keys_w_no_ascii = tuple(x for x in gconfig.esc_keys_w if x not in range(32, 127))
+```
+
+Restart, test, and... Nothing. This is an improvement, the program isn't exiting
+immediately, it just does nothing. I know that `^u` works as I expect, so
+perhaps it needs some love to have `^w` work properly as well. I search for
+`K.U_`, and indeed, there is code dedicated to this keypress, in a long `elif`
+construct. So I add some code to get `^w` working as well. After a bit of
+fiddling, and realizing I've spent way too much time on adding a torrent, I've
+settled on this little bit of love.
+
+```patch
+@@ -3957,6 +3953,18 @@ class Interface:
+ # Delete from cursor until beginning of line
+ text = text[index:]
+ index = 0
++ elif c == K.W_:
++ # Delete from cursor to beginning of previous word... mostly
++ text_match = re.search("[\W\s]+", text[::-1])
++
++ if text_match.span()[0] == 0:
++ # This means the match was found immediately, I can't be
++ # bothered to make this any nicer.
++ text = text[:-1]
++ index -= 1
++ else:
++ text = text[:-text_match.span()[0]]
++ index -= text_match.span()[0]
+ elif c in (curses.KEY_HOME, K.A_):
+ index = 0
+ elif c in (curses.KEY_END, K.E_):
+```
+
+It looks for the first non-word character or a space, starting from the end of
+the string (`[::-1]` reverses a string in Python). The resulting `Match` object
+can tell me how many characters I need to delete in the `.span()[0]` value. A
+small exception is created if that value is `0`, otherwise the logic below
+doesn't work well.
+
+It's not perfect, but it gets the job done well enough, and I don't like Python
+enough to spend more time on it than I've already done. I am open for better
+solutions that work better, though!
diff --git a/content/posts/2022/2022-04-23-a-cookbook.md b/content/posts/2022/2022-04-23-a-cookbook.md
new file mode 100644
index 0000000..e86fcda
--- /dev/null
+++ b/content/posts/2022/2022-04-23-a-cookbook.md
@@ -0,0 +1,52 @@
+---
+date: 2022-04-23
+title: A cookbook!
+tags:
+- Food
+---
+
+Last week, I've decided to add a cookbook to my website. I've thought about
+doing so for a while, but was rather hesitent since my website was mostly a
+tech-minded blog. However, this time around I've decided to simply add a
+cookbook, and have seperate RSS feeds for my [blog posts](/posts/index.xml) and
+[recipes](/recipes/index.xml), so that readers can decide what they want to
+follow. Now I can easily share any recipes that visitors have asked me to share
+over the years.
+
+The cookbook has an overview of all recipes, and each invidual recipe has a
+layout greatly inspired by MartijnBraam's [FatHub](https://fathub.org). The
+JavaScript is an exact copy, even.
+
+The format of the recipes has been altered slightly. I found the FatHub format
+to be a little too verbose to make it simple enough to want to write down the
+recipes. So I've trimmed down on some of that. You can check the sources that I
+use on [git.tyil.nl](https://git.tyil.nl/blog/).
+
+Since my website is generated with [Hugo](https://gohugo.io), I had to do the
+template myself as well. But these were fairly simple to port over, and I am
+fairly happy with the result. I've made two changes compared to the layout used
+by FatHub: Every step in the instructions is numbered, and the checkboxes for
+the ingredients are at the left-hand side. The ingredients don't contain a
+preparation step in the tables, as I've made that part of the cooking
+instructions.
+
+The entire thing was done in an afternoon during Easter, so it was pretty
+straightforward to set up. I haven't included many recipes yet, as I want to
+double-check the right amounts of ingredients and instructions for many of them.
+The downside of a recipe is that people generally follow it to the letter, and
+I'm not a professional cook, I often cook just by tasting and adjusting as
+desired.
+
+There's one thing I didn't include, but which I might consider working on in the
+future: [baker's percentages](https://en.wikipedia.org/wiki/Baker_percentage).
+Some of my recipes have been written down in this notation, and for now I'll be
+converting them to regular quantities instead. There's also some downsides to
+baker's percentages such as harder to calculate what a serving size is, or the
+duration of certain steps, which has caused me to not make this a hard
+requirement for the cookbook section of my site.
+
+I think the cookbook is more than enough to get started with, and to try sharing
+some recipes in. If I've ever cooked something for you in person, and you would
+like to know the recipe, don't hesitate to ask me to include it in the cookbook.
+Additionally, if you have some tips on how to improve an existing recipe, I'd be
+very happy to hear about it!
diff --git a/content/posts/2022/2022-05-07-bashtard-introduction.md b/content/posts/2022/2022-05-07-bashtard-introduction.md
new file mode 100644
index 0000000..0f93fdd
--- /dev/null
+++ b/content/posts/2022/2022-05-07-bashtard-introduction.md
@@ -0,0 +1,265 @@
+---
+title: Configuring my Machines with Bashtard
+date: 2022-05-07
+tags:
+- Bash
+- Bashtard
+- FreeBSD
+- GNU+Linux
+- Programming
+---
+
+Over the past couple weeks I've been spending some time here and there to work
+on my own application for configuring my machines. Before this I've tried
+Ansible, but found it to be very convoluted to use, and requires a lot of
+conditionals if your machines aren't all running the same base system.
+
+So I made something in Bash, with a few abstractions to make certain
+interactions less annoying to do manually every time. This used to be called
+`tyilnet`, but I've discussed the setup with a few people on IRC, and decided it
+would be a fun project to make it a bit more agnostic, so other people could
+also easily start using it. This resulted in the creation of
+[Bashtard](https://git.tyil.nl/bashtard/), pronounced as "bash", followed by
+"tard" (as in "bastard").
+
+It works by simply writing Bash scripts to do the configuration, and provides
+abstractions for using the system's package manager, service manager, and some
+utilities such as logging and dealing with configured values. Configuration
+values can be set on a per-host or per-OS basis. Since I run a varied base of
+OSs, including Gentoo, Debian, and FreeBSD, the per-OS configuration comes in
+very handy to me.
+
+As for the reason to use Bash, I chose it because most of the systems I run
+already have this installed, so it doesn't add a dependency _most of the time_.
+I would've liked to do it in POSIX sh, but I feel that when you're reaching a
+certain level of complexity, Bash offers some very nice features which can make
+your code cleaner, or less likely to contain bugs. Features such as `[[ ]]`,
+`local`, and arrays come to mind.
+
+I've been kindly asked to guide potential new users to writing their first
+Bashtard script, known as a _playbook_, so if you want to know about how it
+works in practice, keep on reading. If you're satisfied with your current
+configuration management system, this might not be quite as interesting to you,
+so be warned.
+
+The first steps for a new user would obviously to install Bashtard, as it's not
+in any OSs package repositories yet. A `Makefile` is supplied in the repository,
+which should make this easy enough.
+
+```txt
+git clone https://git.tyil.nl/bashtard
+cd bashtard
+sudo make install
+hash -r
+```
+
+Once installed, it needs some initialization.
+
+```txt
+bashtard init
+```
+
+This will create the basic structure in `/etc/bashtard`, including a
+`playbooks.d`. Inside this `playbooks.d` directory, any directory is considered
+to be a playbook, which requires a `description.txt` and a `playbook.bash`.
+
+```txt
+cd /etc/bashtard/playbooks.d
+mkdir ssh
+cd ssh
+echo "OpenSSH configuration" > description.txt
+$EDITOR playbook.bash
+```
+
+The `playbook.bash` needs to contain 3 functions which are used by `bashtard`, a
+`playbook_add()`, `playbook_sync()`, and `playbook_del()`. These will be called
+by the `bashtard` subcommand `add`, `sync`, and `del` respectively.
+
+I generally start with the `playbook_sync()` function first, since this is the
+function that'll ensure all the configurations are kept in sync with my desires.
+I want to have my own `sshd_config`, which needs some templating for the
+`Subsystem sftp` line. There's a `file_template` function provided by bashtard,
+which does some very simple templating. I'll pass it the `sftp` variable to use.
+
+```bash
+playbook_sync() {
+ file_template sshd_config \
+ "sftp=$(config "ssh.sftp")" \
+ > /etc/ssh/sshd_config
+}
+```
+
+Now to create the actual template. The `file_template` function looks for
+templates in the `share` directory inside the playbook directory.
+
+```txt
+mkdir share
+$EDITOR share/sshd_config
+```
+
+Since I already know what I want my `sshd_config` to look like from previous
+installed systems, I'll just use that, but with a variable for the `Subsystem
+sftp` value.
+
+```cfg
+# Connectivity
+Port 22
+AddressFamily any
+ListenAddress 0.0.0.0
+ListenAddress ::
+
+# Fluff
+PrintMotd yes
+
+# SFTP
+Subsystem sftp ${sftp}
+
+# Authentication
+AuthorizedKeysFile /etc/ssh/authorized_keys .ssh/authorized_keys
+PermitRootLogin no
+PasswordAuthentication no
+ChallengeResponseAuthentication no
+PubkeyAuthentication no
+
+# Allow tyil
+Match User tyil
+ PubkeyAuthentication yes
+
+# Allow public key authentication over VPN
+Match Address 10.57.0.0/16
+ PubkeyAuthentication yes
+ PermitRootLogin prohibit-password
+```
+
+The `${sftp}` placeholder will be filled with whatever value is returned by
+`config "ssh.sftp"`. And for this to work properly, we will need to define the
+variable somewhere. These are written to the `etc` directory inside a playbook.
+You can specify defaults in a file called `defaults`, and this can be
+overwritten by OS-specific values, which in turn can be overwritten by
+host-specific values.
+
+```txt
+mkdir etc
+$EDITOR etc/defaults
+```
+
+The format for these files is a very simple `key=value`. It splits on the first
+`=` to determine what the key and value are. This means you can use `=` in your
+values, but not your keys.
+
+```txt
+ssh.sftp=/usr/lib/openssh/sftp-server
+```
+
+This value is correct for Debian and derivatives, but not for my Gentoo or
+FreeBSD systems, so I've created OS-specific configuration files for these.
+
+```txt
+mkdir etc/os.d
+cat etc/os.d/linux-gentoo
+ssh.sftp=/usr/lib64/misc/sftp-server
+```
+
+```txt
+cat etc/os.d/freebsd
+ssh.sftp=/usr/lib64/misc/sftp-server
+```
+
+My `sshd_config` template also specifies the use of a `Motd`, so that needs to
+be created as well. This can again be done using the `template` function.
+
+```bash
+file_template "motd" \
+ "fqdn=${BASHTARD_PLATFORM[fqdn]}" \
+ "time=$(date -u "+%FT%T")" \
+ > /etc/motd
+```
+
+The `motd` template gets saved at `share/motd`.
+
+```txt
+ ████████╗██╗ ██╗██╗██╗ ███╗ ██╗███████╗████████╗
+ ╚══██╔══╝╚██╗ ██╔╝██║██║ ████╗ ██║██╔════╝╚══██╔══╝
+ ██║ ╚████╔╝ ██║██║ ██╔██╗ ██║█████╗ ██║
+ ██║ ╚██╔╝ ██║██║ ██║╚██╗██║██╔══╝ ██║
+ ██║ ██║ ██║███████╗██╗██║ ╚████║███████╗ ██║
+ ╚═╝ ╚═╝ ╚═╝╚══════╝╚═╝╚═╝ ╚═══╝╚══════╝ ╚═╝
+
+Welcome to ${fqdn}, last updated on ${time}.
+```
+
+Lastly, we want to ensure the SSH daemon gets reloaded after every sync, so
+let's add that to the `playbook_sync()` function as well.
+
+```bash
+svc reload "sshd"
+```
+
+The `svc` utility looks for a configuration value that starts with `svc.`,
+followed by the service you're trying to act upon, so in this case that would be
+`svc.sshd`. We can add this to our configuration files in `etc`. Across all my
+machines, `sshd` seems to work as the value, so I only need to add one line to
+`etc/defaults`.
+
+```txt
+svc.sshd=sshd
+```
+
+This should take care of all the things I want automatically synced. The
+`playbook_add()` function is intended for all one-time setup required for any
+playbook. In this case that means the SSH daemon's service needs to be
+activated, since it is not active by default on all my setups.
+
+```bash
+playbook_add() {
+ svc enable "sshd"
+ svc start "sshd"
+}
+```
+
+However, `add` does not call a `sync`, and I don't want my SSH service to run
+with default configuration until a `sync` is initialized. So before enabling and
+starting the service, I will call `sync` manually, by running a `playbook_sync`
+first. This in turn, however, poses another problem, as `playbook_sync()` wants
+to reload the service, which it can't do unless it is already running. To fix
+this, I'll add an `if` statement to skip reloading if `bashtard` is running the
+`add` command.
+
+```bash
+playbook_add() {
+ playbook_sync
+
+ svc enable "sshd"
+ svc start "sshd"
+}
+
+playbook_sync() {
+ ...
+
+ [[ $BASHTARD_COMMAND == "add" ]] && return
+
+ svc reload "sshd"
+}
+```
+
+Now, `bashtard add sshd` will run the `playbook_add()` function, which calls the
+`playbook_sync()` function before enabling and starting the `sshd` service. All
+that is left is the `playbook_del()` function, which only really needs to stop
+and disable the service. The templated files can be removed here as well if
+desired, of course.
+
+```bash
+playbook_del() {
+ svc stop "sshd"
+ svc disable "sshd"
+}
+```
+
+Lastly, I configured my `crond` to run `bashtard sync` every 20 minutes, so
+whenever I update my configurations, it can take up to 20 minutes to propagate
+to all my machines. Having an abstraction to deal with `cron` (or SystemD timers
+where applicable) in Bashtard is something I'd like to add, but I have no
+concrete plans on how to do this, yet.
+
+You can find the full `playbook.bash` source on
+[git.tyil.nl](https://git.tyil.nl/tyilnet/tree/playbooks.d/ssh/playbook.bash?id=319ab064370cb1e65be115ffddf5c0cd519af2dd).
diff --git a/content/posts/2022/2022-08-06-installing-gentoo-encrypted-zfs-efistub.md b/content/posts/2022/2022-08-06-installing-gentoo-encrypted-zfs-efistub.md
new file mode 100644
index 0000000..2825b7c
--- /dev/null
+++ b/content/posts/2022/2022-08-06-installing-gentoo-encrypted-zfs-efistub.md
@@ -0,0 +1,242 @@
+---
+date: 2022-11-20
+title: "Installing Gentoo with encrypted ZFS rootfs and EFIstub kernel"
+tags:
+- GNU+Linux
+- Gentoo
+- Tutorial
+- ZFS
+---
+
+A little while ago, I got a new work laptop. As is customary, I installed my
+preferred GNU+Linux environment onto it. Consequently, a few people have asked
+me to detail my steps to get this system up and running, as they would like to
+try out a similar setup as I did. It's also been a while since I made another
+blog post, so here's killing two birds with one stone!
+
+## Preparing disks
+
+Make sure you get the right device name, or you'll purge the data on some other
+drive!
+
+```sh
+parted -a optimal /dev/nvme1n1
+mklabel gpt
+mkpart esp 1 5130
+mkpart rootfs 5130 -1
+set 1 boot on
+quit
+```
+
+### Get IDs of partitions
+
+For partitioning I've lately come to love using disk IDs, rather than their
+`/dev/sd*` entries. They're easy to look up, so copy them over to use them later
+on.
+
+```sh
+ls -l /dev/disk/by-id
+```
+
+- `nvme-eui.36483331545090280025385800000001-part1` -> ESP
+- `nvme-eui.36483331545090280025385800000001-part2` -> ZFS
+
+### Formatting
+
+#### ESP
+
+The ESP partition holds the kernel and initramfs, and _must_ be FAT32.
+
+```sh
+mkfs.vfat -F32 /dev/disk/by-id/nvme-eui.36483331545090280025385800000001-part1
+```
+
+#### zpool
+
+The zpool settings used here are the settings I used. You should verify these
+settings also work optimally for your setup! I generally name my pools after the
+device they're running from, in this case `ivdea`. Any name will work here, just
+make sure to be consistent later down the guide!
+
+```sh
+rm -f /etc/hostid && zgenhostid
+
+zpool create -f \
+ -O acltype=posixacl \
+ -O compression=lz4 \
+ -O dedup=off \
+ -O encryption=aes-256-gcm \
+ -O keyformat=passphrase \
+ -O keylocation=prompt \
+ -O relatime=on \
+ -O xattr=sa \
+ -R /mnt/gentoo \
+ -m none \
+ -o ashift=12 \
+ -o cachefile=/etc/zfs/zpool.cache \
+ ivdea0 \
+ /dev/disk/by-id/nvme-eui.36483331545090280025385800000001-part2
+
+zfs create -o mountpoint=none ivdea0/rootfs
+zfs create -o mountpoint=/ ivdea0/rootfs/gentoo
+zfs create -o mountpoint=none ivdea0/rootfs/gentoo/usr
+zfs create -o mountpoint=none ivdea0/rootfs/gentoo/var
+zfs create -o mountpoint=none ivdea0/rootfs/gentoo/var/lib
+zfs create -o mountpoint=none ivdea0/home
+zfs create -o mountpoint=/home/tyil ivdea0/home/tyil
+
+zpool set bootfs=ivdea0/rootfs/gentoo ivdea0
+```
+
+## Preparing chroot
+
+You will want to grab the latest Gentoo autobuild tarball for your architecture.
+I'm _not_ using systemd, if you do desire this for some reason, you may need to
+alter some steps.
+
+### Initial
+
+```sh
+cd /mnt/gentoo
+mkdir efi
+mount /dev/disk/by-id/nvme-eui.36483331545090280025385800000001-part1 efi
+wget $STAGE3 # Use whichever URL for the stage3 tarball you need
+tar xpf stage3*.tar.xz --xattrs-include='*.*' --numeric-owner
+```
+
+### Recovery
+
+This section is labeled "Recovery" to easily find it later, in case you need to
+go back into the chroot to fix up any issues that prevent you from booting it.
+
+```sh
+mkdir -p etc/zfs
+cp /etc/zfs/zpool.cache etc/zfs
+cp --dereference /etc/resolv.conf /mnt/gentoo/etc/
+mount -t proc /proc proc
+mount --rbind --make-rslave /sys sys
+mount --rbind --make-rslave /dev dev
+mount --rbind --make-rslave /run run
+chroot . /bin/bash -l
+```
+
+## Configuring the system
+
+The base system is now installed, and most of the following steps are for
+configuring it to actually work properly.
+
+### Portage
+
+Run the initial Portage tree download. This will use `webrsync`, you can
+configure it to use `git` at a later stage if desired.
+
+```sh
+mkdir -p /etc/portage/repos.conf
+cp /usr/share/portage/config/repos.conf /etc/portage/repos.conf/gentoo.conf
+emerge-webrsync
+```
+
+### Editor
+
+Ofcourse, you can stick to `nano`, but I've been a vim guy for a very long time
+now, and without it I feel sad. It is the first thing I install, to make the
+rest of the configuration easier to do, by virtue of having the best editor
+available.
+
+```sh
+emerge vim
+```
+
+Once `vim` (or whichever worse editor you prefer) is installed, you can go
+around editing configuration files as needed.
+
+### locale
+
+Enable all the locales you desire in `/etc/locale.gen`. Once all the desird
+locales are uncommented, you can generate the locales with `locale-gen`. You
+will most likely also want to add the locales to the `L10N` variable in your
+`make.conf`.
+
+### timezone
+
+Set your timezone by making `/etc/localtime` a symlink to the timezone you use.
+
+```sh
+ln -fs /usr/share/zoneinfo/Europe/Amsterdam /etc/localtime
+```
+
+### hostname
+
+Set the machine's short hostname in `/etc/conf.d/hostname` first, then add your
+hostname aliases to `/etc/hosts`.
+
+```txt
+# /etc/conf.d/hostname
+hostname="ivdea"
+
+# /etc/hosts
+127.0.0.1 ivdea.tyil.net ivdea
+::1 ivdea.tyil.net ivdea
+```
+
+### kernel
+
+{{< admonition title="Note" >}}
+This will build the initramfs twice, since emerging gentoo-kernel will build it
+automagically. This can be "fixed" by removing a USE flag, but this is easier to
+me.
+{{</ admonition >}}
+
+By the time you're reading this, the kernel version used here is probably
+outdated. You will want to update it to whichever kernel version you're going to
+use.
+
+```sh
+emerge \
+ busybox \
+ dracut \
+ efibootmgr \
+ gentoo-kernel \
+ intel-microcode \
+ linux-firmware
+
+emerge sys-fs/zfs-kmod sys-fs/zfs
+emerge --config gentoo-kernel
+
+rc-update add zfs-import boot
+rc-update add zfs-mount boot
+rc-update add zfs-share default
+rc-update add zfs-zed default
+
+zgenhostid
+
+cp /boot/vmlinuz-5.15.59-gentoo-dist /efi/efi/gentoo/vmlinuz-5.15.59-gentoo-dist.efi
+cp /boot/initramfs-5.15.59-gentoo-dist /efi/efi/gentoo/initramfs-5.15.59-gentoo-dist.img
+
+efibootmgr \
+ --disk /dev/disk/by-id/nvme-eui.36483331545090280025385800000001 \
+ --part 1 \
+ --create \
+ --label "Gentoo ZFS 5.15.59" \
+ --loader 'efi\gentoo\vmlinuz-5.15.59-gentoo-dist.efi' \
+ --unicode \
+ 'dozfs root=ZFS=ivdea0/rootfs/gentoo ro initrd=\efi\gentoo\initramfs-5.15.59-gentoo-dist.img encrypted'
+```
+
+### Root password
+
+Set the root password using `passwd`. This would also be a good time to add any
+other users you want to use, and configure them with the correct permissions and
+groups.
+
+## Misc
+
+If you have any other software requirements, such as wireless network management
+or privilege escalation utilities, this is the most appropriate time to install
+and configure them.
+
+## Reboot
+
+Now you can reboot into the system, and be done with this guide. If anything
+isn't working properly, return to the "Recovery" step and fix any outstanding
+issues.
diff --git a/content/posts/2022/_index.md b/content/posts/2022/_index.md
new file mode 100644
index 0000000..3bf91c1
--- /dev/null
+++ b/content/posts/2022/_index.md
@@ -0,0 +1,3 @@
+---
+title: 2022
+---