A src/posts/hello-world.gmi => src/posts/hello-world.gmi +2 -0
@@ 0,0 1,2 @@
+# Hello World
+This is my first blog post!
A src/posts/mailserver-with-nixos.gmi => src/posts/mailserver-with-nixos.gmi +182 -0
@@ 0,0 1,182 @@
+# Mailserver with NixOS
+In this blog post I will go through how I setup a mailserver using the
+excellent [nixos-mailserver] module. If you want to follow along, you
+obviously need to setup a domain with a domain registrar.
+
+This post will only cover the details for the server, I will make a
+follow-up post on how I configure my laptop to deal with mail.
+
+
+=> https://gitlab.com/simple-nixos-mailserver/nixos-mailserver nixos-mailserver
+
+
+## What you get
+
+Before we actually use the module, it is probably a good idea to go
+over what it is that you get when using the module. The module will
+configure the following things for you
+
+* Dovecot for delivering mail using IMAP or POP3
+* Postfix for sending mail
+* Rspamd for filtering spam and greylisting
+* Let' Encrypt for SSL certificate
+* Opendkim for DKIM signing
+* Sieve for filtering mail
+
+
+## Download the modules
+
+The nixos-mailserver module is not part of the official Nixpkgs
+repository, this means that we have to download it separately to use
+it. You can do this in many different ways, I am currently using the
+experimental [nix-flakes] feature so I will put the following in my
+`flake.nix':
+
+```
+nixos-mailserver = {
+ url = "gitlab:simple-nixos-mailserver/nixos-mailserver/nixos-20.09";
+};
+```
+
+If you do not use flakes, you can put the following in your
+`configuration.nix':
+
+```
+{ config, pkgs, ... }:
+let release = "nixos-20.09";
+in {
+ imports = [
+ (builtins.fetchTarball {
+ url = "https://gitlab.com/simple-nixos-mailserver/nixos-mailserver/-/archive/${release}/nixos-mailserver-${release}.tar.gz";
+ # This hash needs to be updated
+ sha256 = "0000000000000000000000000000000000000000000000000000";
+ })
+ ];
+
+ #########################
+ # The rest of the config
+ ########################
+}
+```
+
+
+=> https://nixos.wiki/wiki/Flakes nix-flakes
+
+
+## Configuration
+
+All you have to configure is the domain for your server, the mailboxes
+you want to use and the user accounts, and that is it! Settings
+`certificateScheme' to `3' means that my SSL certificate will be
+created automatically with Let's Encrypt. For this to work, you also
+have to create an "A" record for the FQDN to point to your IP address.
+
+The account password should be a hash of the real password, this can
+be generated by running `mkpasswd -m sha-512' in the shell. I will go
+into more detail on the sieve script I am using in the next section.
+
+```
+{
+ mailserver = {
+ enable = true;
+ fqdn = "mail.yoctocell.xyz";
+ domains = [ "yoctocell.xyz" ];
+
+ loginAccounts = {
+ "public@yoctocell.xyz" = {
+ # mkpasswd -m sha-512
+ hashedPassword = "<hashed-password>";
+ sieveFilter = builtins.readFile ./filters.sieve;
+ };
+ };
+
+ mailboxes = {
+ Trash = {
+ auto = "no";
+ specialUse = "Trash";
+ };
+ Junk = {
+ auto = "subscribe";
+ specialUse = "Junk";
+ };
+ Drafts = {
+ auto = "subscribe";
+ specialUse = "Drafts";
+ };
+ Sent = {
+ auto = "subscribe";
+ specialUse = "Sent";
+ };
+ Archive = {
+ auto = "subscribe";
+ specialUse = "Archive";
+ };
+ };
+
+ certificateScheme = 3;
+ };
+
+ networking.firewall.allowedTCPPorts = [ 465 993 ];
+}
+```
+
+
+## Sieve
+
+I am subscribed to a few mailing lists, to better keep track of them I
+have a sieve filter on the server that refiles the emails to different
+folders. Every mailing list will get its own folder and the folder
+structure looks something like this (it follows the Maildir++ spec):
+
+```
+maildir
+├── .Archive
+├── .Sent
+├── .lists.emacs.git-email
+├── .lists.emacs.piem
+├── .lists.nix.nixpkgs-dev
+├── .lists.mail.public-inbox
+├── cur
+├── new
+└── tmp
+```
+
+I could write all of the sieve filters manually, but that would be
+very tedious. John Wiegley has a really nice [Haskell script] which
+generates the sieve script from a Haskell lookup table. I have
+modified it to filter the relevant mailing lists, and the result looks
+like this:
+
+```
+elsif anyof (header :contains ["List-Id"]
+ "<piem.inbox.kyleam.com>",
+ header :contains ["Sender","From","To","Reply-To","Cc"]
+ "piem@inbox.kyleam.com") {
+ fileinto "lists.emacs.piem";
+}
+
+elsif anyof (header :contains ["List-Id"]
+ "<~yoctocell/git-email-devel.lists.sr.ht>",
+ header :contains ["Sender","From","To","Reply-To","Cc"]
+ "~yoctocell/git-email-devel@lists.sr.ht") {
+ fileinto "lists.emacs.git-email";
+}
+
+elsif anyof (header :contains ["List-Id"]
+ "<meta.public-inbox.org>",
+ header :contains ["Sender","From","To","Reply-To","Cc"]
+ "meta@public-inbox.org") {
+ fileinto "lists.mail.public-inbox";
+}
+```
+
+Then I just import this file in my mailserver config with `sieveFilter
+= builtins.readFile ./filters.sieve;'.
+
+This is pretty much it for the server-side. There will be a follow up
+blog post about the client-side configuration (it is quite
+complicated). You can find the relevant configurations [here].
+
+
+=> https://github.com/jwiegley/scripts/blob/master/sievegen Haskell script
+=> https://git.sr.ht/~yoctocell/nixrc/tree/master/item/profiles/mail/mailserver here
A src/posts/nixos-on-btrfs-with-encrypted-root.gmi => src/posts/nixos-on-btrfs-with-encrypted-root.gmi +236 -0
@@ 0,0 1,236 @@
+# NixOS on Btrfs with encrypted root
+In this guide I will install NixOS on btrfs with an encrypted root
+partition.
+
+*Note*: This guide is mostly just some notes for myself, proceed at your
+own risk!
+
+
+## Prerequisites
+
+You are expected to have a basic knowledge of both [NixOS] and the
+[btrfs] filesystem, and you will need an installation media if you are
+doing this on bare metal.
+
+First, download the NixOS iso and flash it to your usb, where `sdX' is
+the name of the usb drive.
+
+```
+sudo dd if=/path/to/iso of=/dev/sdX bs=4M status=progress
+```
+
+
+=> https://nixos.org NixOS
+=> https://btrfs.wiki.kernel.org/index.php/Main_Page btrfs
+
+
+## Get started
+
+Boot from the usb and setup your wifi connection
+
+```
+wpa_supplicant -B -i interface -c <(wpa_passphrase '<SSID>' '<password>')
+```
+
+
+## Partitioning
+
+The next step is to partition your drives, I will create three
+partitions.
+
+ Name Type Size
+------------------------------------------------
+ `/dev/sdX1' EFI boot partition 512 MB
+ `/dev/sdX2' Swap partition 8 GB
+ `/dev/sdX3' Root partition with btrfs <rest>
+
+Use your favourite partition program, I will use `cfdisk'. Run `lsblk'
+to make sure everything you didn't mess things up.
+
+
+## Encryption
+
+We will encrypt the root partition (`/dev/sdX3') using
+[dm-crypt]. First, format the partition and enter a passphrase which
+will be used for decrypting the partition.
+
+```
+cryptsetup luksFormat /dev/sdX3
+```
+
+Decrypt the partition and give it a name, I will call it
+`crypted-nixos'.
+
+```
+cryptsetup open /dev/sdX3 crypted-nixos
+```
+
+
+=> https://gitlab.com/cryptsetup/cryptsetup/-/wikis/DMCrypt dm-crypt
+
+
+## Formatting
+
+Format the partition and label them.
+
+```
+mkfs.vfat -F32 -n boot /dev/sdX1 # Boot
+mkswap -L swap /dev/sdX2 # Swap
+swapon /dev/sdX2 # Activate swap
+mkfs.btrfs -L nixos /dev/mapper/crypted-nixos # Root
+```
+
+
+## Mounting & Subvolumes
+
+We now have one btrfs volume and we will have to create some
+subvolumes.
+
+ Name Mount point Purpose
+-------------------------------------------------------
+ @ `/' Root filesystem
+ @home `/home' Home directory, will be backed up
+
+The home directory will backed up, everything else is either managed
+by nix or just temporary files. We will first mount our encrypted root
+partition and then create the subvolumes.
+
+```
+mount -t btfs /dev/mapper/crypted-nixos /mnt # Remember the device name?
+
+btrfs subvolume create /mnt/@
+btrfs subvolume create /mnt/@home
+
+umount /mnt
+```
+
+Once the subvolumes have been created, we will mount them with our
+desired options.
+
+```
+mount -o subvol=@,compress=lzo,noatime /dev/mapper/crypted-nixos /mnt
+
+mkdir /mnt/home
+mount -o subvol=@home,compress=lzo,noatime /dev/mapper/crypted-nixos /mnt/home
+```
+
+And don't forget to mount the boot partition!
+
+```
+mkdir /mnt/boot
+mount /dev/sdX1 /mnt/boot
+```
+
+We can run `btrfs subvol list /mnt/' to list our subvolumes and make
+sure everything is correct.
+
+
+## Configuration
+
+Now we can install NixOS on the filesystem. First, generate a base
+config.
+
+```
+nixos-generate-config --root /mnt
+```
+
+Since we have encryption, we need to make sure that we have the
+following in our `hardware-configuration.nix' or `configuration.nix'.
+
+```
+{ config, lib, pkgs, ... }:
+
+{
+ boot.supportedFilesystems = [ "btrfs" ];
+
+ boot.initrd.luks.devices = {
+ "crypted-nixos" = {
+ device = "/dev/disk/by-uuid/<uuid>";
+ };
+ };
+}
+```
+
+Replace `crypted-nixos' with the name of your device, and replace
+`<uuid>' with the uuid of `/dev/sdX3'. The rest of the config is left
+for you to configure yourself.
+
+Go back to the shell and install the system.
+
+```
+nixos-install
+poweroff
+```
+
+If it all goes well, we should be able enter our dm-crypt passphrase
+and login as a user.
+
+
+## Post-installation
+
+When your system works you probably want to make snapshots on a
+regular basis in case something goes wrong. I like to take snapshots
+every time my system starts up and shuts down, so that's what we will
+configure in this guide.
+
+We first want to create a script which will take snapshot for us. The
+following script is based on a script from the [Gentoo wiki].
+
+```
+{ config, lib, pkgs, ... }:
+let
+ btrfsSnapshot = pkgs.writers.writeBashBin "btrfs-snapshot"
+ ''
+ NOW=$(date +"%Y-%m-%d_%H:%M:%S")
+
+ if [ ! -e /mnt/backup/home ]; then
+ mkdir -p /mnt/backup/home
+ fi
+
+ cd /
+ ${pkgs.btrfs-progs}/bin/btrfs subvolume snapshot /home "/mnt/backup/home/home_''${NOW}"
+ '';
+in
+{
+ environment.systemPackages = [
+ btrfsSnapshot
+ ];
+}
+```
+
+Now we want to create a systemd service that runs this script on
+startup and shutdown.
+
+```
+{ config, lib, pkgs, ... }:
+
+{
+ systemd.services."btrfs-snapshot" = {
+ description = "Create btrfs snapshot on startup and shutdown.";
+ serviceConfig = rec {
+ ExecStart = "${btrfsSnapshot}/bin/btrfs-snapshot";
+ ExecStop = ExecStart;
+ Type = "oneshot";
+ RemainAfterExit = true;
+ };
+ requiredBy = [ "multi-user.target" ];
+ };
+}
+```
+
+We can also scrub our file system once every month.
+
+```
+{ config, lib, pkgs, ... }:
+
+{
+ services.btrfs.autoScrub = {
+ enable = true;
+ fileSystems = [ "/" ];
+ interval = "monthly";
+ };
+}
+```
+
+
+=> https://wiki.gentoo.org/wiki/Btrfs#Snapshots Gentoo wiki
A src/posts/securing-nixos-with-yubikey.gmi => src/posts/securing-nixos-with-yubikey.gmi +149 -0
@@ 0,0 1,149 @@
+# Securing NixOS with Yubikey
+In this blog post I will go over some things I have configured with
+NixOS and a yubikey to improve the security of my system. I will not go
+into detail on how to setup a GPG keypair, there are already plenty of
+great tutorials. [1]
+
+
+## GnuPG
+
+To use GPG with a yubikey, we first need to install some packages, put
+the following in your `configuration.nix'
+
+```
+{
+ services.pcscd.enable = true;
+
+ environment.systemPackages = with pkgs; [
+ yubikey-personalization
+ ];
+
+ services.udev.packages = with pkgs; [
+ yubikey-personalization
+ ];
+}
+
+```
+
+We will export the subkeys to our yubikey so we can use it when
+signing and decrypting mail, but first plug in the yubikey and run
+
+```
+$ gpg --card-status
+```
+
+Then run `gpg --card-edit' and you should see a prompt like this.
+
+```
+gpg/card>
+```
+
+Type `admin' and then `passwd' to change the user and the admin
+pin. The user pin will be used for day-to-day things like signing and
+decrypting files, the admin pin will only be used for operations
+concerning the configuration of the yubikey, eg. adding subkeys. The
+default user pin is `123456' and the default admin pin is `12345678'.
+
+Now it's time to export the keys, beware that this process will remove
+the keys from your computer, so make sure your keys are backed up on
+an external drive.
+
+```
+gpg --edit-key <keyid>
+
+Secret subkeys are available.
+
+pub rsa4096/33947BA1AA8847FF
+ created: 2020-12-13 expires: never usage: C
+ trust: ultimate validity: ultimate
+ssb rsa4096/D1B318ACDABCAEE6
+ created: 2020-12-13 expires: 2021-12-13 usage: S
+ card-no: 0006 14257444
+ssb rsa4096/38E09A208656B970
+ created: 2020-12-13 expires: 2021-12-13 usage: E
+ card-no: 0006 14257444
+ssb rsa4096/18ED52D1A730A8CA
+ created: 2020-12-13 expires: 2021-12-13 usage: A
+ card-no: 0006 14257444
+[ultimate] (1). yoctocell <public@yoctocell.xyz>
+
+gpg>
+```
+
+Mark the signing subkey with `key 1' and run `keytocard' to export it
+to your yubikey. When it has been exported you have to unmark the
+signing key by running `key 1' again, you will see that the `*' next
+to the key disappears. Repeat the same process for `key 2' and `key
+3', then type `quit' to exit.
+
+Run `gpg -K' and you should see something like this
+
+```
+sec# rsa4096/33947BA1AA8847FF 2020-12-13 [C]
+ Key fingerprint = 4217 475C B91A 4C94 3FCE C870 3394 7BA1 AA88 47FF
+uid [ultimate] yoctocell <public@yoctocell.xyz>
+ssb> rsa4096/D1B318ACDABCAEE6 2020-12-13 [S] [expires: 2021-12-13]
+ssb> rsa4096/38E09A208656B970 2020-12-13 [E] [expires: 2021-12-13]
+ssb> rsa4096/18ED52D1A730A8CA 2020-12-13 [A] [expires: 2021-12-13]
+```
+
+The `>' next to `ssb' means that it is a pointer to the subkey on your
+yubikey.
+
+If you are currently running a live OS like Tails, you have to export
+your subkeys to an external drive.
+
+```
+gpg --armor --output=/path/to/external/drive --export-secret-subkeys <keyid>
+```
+
+You can import the subkeys on your main computer by running
+
+```
+gpg --import /path/to/external/drive
+```
+
+To test if everything is working, encrypt a file and then decrypt it
+with your private key
+
+```
+echo 'test' > test.txt
+gpg -o test.gpg -e -r <keyid>
+gpg --decrypt test.gpg
+```
+
+This should prompt you for the user pin you created for your yubikey.
+
+
+## PAM
+
+There is a PAM modules that allows us to use the yubikey to
+authenticate when logging in.
+
+```
+security.pam.yubico = {
+ enable = true;
+ debug = true;
+ mode = "challenge-response";
+ control = "required";
+}
+```
+
+You then need to run the following commands.
+
+```
+nix-shell -p yubico-pam -p yubikey-personalization
+ykpersonalize -2 -ochal-resp -ochal-hmac -ohmac-lt64 -oserial-api-visible
+ykpamcfg -2 -v
+```
+
+You now need your yubikey and your password to login to your machine,
+if don't want to enter the password just remove the `control =
+"required";' line.
+
+
+
+Footnotes
+_________
+
+[1] See [here], [here] and [here].