diff options
Diffstat (limited to 'content/posts/2022')
-rw-r--r-- | content/posts/2022/2022-02-14-librewolf.md | 92 | ||||
-rw-r--r-- | content/posts/2022/2022-02-20-nginx-tls.md | 92 | ||||
-rw-r--r-- | content/posts/2022/2022-03-05-deprecating-reiserfs.md | 74 | ||||
-rw-r--r-- | content/posts/2022/2022-04-15-fixing-w-in-tremc.md | 140 | ||||
-rw-r--r-- | content/posts/2022/2022-04-23-a-cookbook.md | 52 | ||||
-rw-r--r-- | content/posts/2022/2022-05-07-bashtard-introduction.md | 265 | ||||
-rw-r--r-- | content/posts/2022/2022-08-06-installing-gentoo-encrypted-zfs-efistub.md | 242 | ||||
-rw-r--r-- | content/posts/2022/_index.md | 3 |
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 +--- |