summaryrefslogtreecommitdiff
path: root/_posts
diff options
context:
space:
mode:
authorPatrick Spek <p.spek@tyil.nl>2018-07-08 15:46:56 +0200
committerPatrick Spek <p.spek@tyil.nl>2018-07-08 15:46:56 +0200
commitd16530d61a04435fd8cb4d4770c4ac715ac8ef0e (patch)
tree46499a98c6f890622e5ccbf9cf43725a7597c7e4 /_posts
Initial commit
Diffstat (limited to '_posts')
-rw-r--r--_posts/2016-10-01-on-pastebin.md80
-rw-r--r--_posts/2016-10-01-on-systemd.md288
-rw-r--r--_posts/2016-10-01-on-winmail-dat.md41
-rw-r--r--_posts/2016-10-03-install-funtoo.md808
-rw-r--r--_posts/2016-10-25-setup-a-vpn-with-cjdns.md212
-rw-r--r--_posts/2016-10-25-setup-nginx-with-lets-encrypt-ssl.md229
-rw-r--r--_posts/2016-10-31-freebsd-mailserver-part-1-preparations.md141
-rw-r--r--_posts/2016-10-31-freebsd-mailserver-part-2-mailing-with-postfix.md316
-rw-r--r--_posts/2016-10-31-freebsd-mailserver-part-3-dovecot-imap-sasl.md227
-rw-r--r--_posts/2016-10-31-freebsd-mailserver-part-4-message-authentication.md159
-rw-r--r--_posts/2016-10-31-freebsd-mailserver-part-5-filtering-mail.md132
-rw-r--r--_posts/2016-11-24-freebsd-mailserver-calendars-and-contacts.md140
-rw-r--r--_posts/2017-09-14-how-to-git.md185
-rw-r--r--_posts/2017-09-28-perl6-creating-a-background-service.adoc159
-rw-r--r--_posts/2017-11-01-hacktoberfest-2017.adoc197
-rw-r--r--_posts/2017-11-16-perl6-setting-up-a-raspberry-perl.adoc236
-rw-r--r--_posts/2017-12-17-on-cloudflare.adoc128
-rw-r--r--_posts/2017-12-21-funding-yourself-as-free-software-developer.adoc231
-rw-r--r--_posts/2018-02-05-why-perl6.adoc280
-rw-r--r--_posts/2018-03-20-perl6-introduction-to-application-programming.adoc784
-rw-r--r--_posts/2018-05-07-sparrowdo-getting-started.adoc231
21 files changed, 5204 insertions, 0 deletions
diff --git a/_posts/2016-10-01-on-pastebin.md b/_posts/2016-10-01-on-pastebin.md
new file mode 100644
index 0000000..775cbe4
--- /dev/null
+++ b/_posts/2016-10-01-on-pastebin.md
@@ -0,0 +1,80 @@
+---
+layout: post
+title: On Pastebin
+date: 2016-10-01 10:20:27 +0200
+tags: Article Harmful Pastebin
+authors:
+ - ["Patrick Spek", "http://tyil.work"]
+---
+
+# Pastebin
+Pastebin offers itself as a gratis paste service. Although it is probably the
+most well known option out there, it is certainly not the best.
+
+## The security issue
+Pastebin has a couple of issues that harm the visitor's security. This on
+itself should be considered such a bad practice that no-one should consider
+their service at all.
+
+### Cloudflare
+Cloudflare is a [MITM][mitm]. It completely breaks the secure chain of TLS on
+the web, and should not be used. Any service still using Cloudflare should be
+shunned. There is [another article][cloudflare] on this site which has more
+information on this specific issue. In addition, Cloudflare can be considered a
+privacy issue for the same reasons, as is detailed below.
+
+### Advertisements
+Another issue with regards to security on pastebin are the advertisements.
+While it can be argued that "they need to make money somehow", using ads always
+seems like the worst possible solution. Especially given the way they're
+serving it. The past couple years have shown that advertisements on the web are
+easily abused to serve malware to good netizens who decided to not block all
+ads.
+
+A rant on the state of ads might be appropriate, but this article is
+specifically about Pastebin, so I will just keep it at "third party
+advertisements are a security risk, avoid sites who use them"
+
+## The privacy issue
+Apart from their security issues, Pastebin also offers some privacy issues. As
+stated above, they make use of Cloudflare. This means that whenever you visit
+them, Cloudflare takes note of this. They may even decide that you need to
+perform some additional tasks in order to be allowed to the resource. This
+doesn't happen to most users, but if you're using any anonymization practices,
+this will happen almost every time you visit a site behind Cloudflare.
+
+In addition to telling Cloudflare, you will also tell another third party,
+Google, in case this "additional step" is required. This is done via the new
+reCaptcha system which will inform Google of almost every detail of your
+browser and the behaviour used to solve the puzzle. Incredibly useful for
+fingerprinting you accross multiple locations.
+
+### Then there is Tor
+But, if you're using an anonymization proxy such as Tor, even if you do not
+care about the Cloudflare issue, and you solve the "security check" presented
+to you, Pastebin still refuses to offer you their service. If they are going to
+refuse you service, they should tell you up front, not after you have already
+informed two other harmful parties of your attempt of accessing the resource.
+
+Actually, they should not. They should simply not require you to give up your
+privacy and serve you the content you were looking for. Blocking resources to a
+certain group of users is simply censorship, and should not be the status quo
+on the free internet.
+
+## Alternatives
+Luckily, there are plenty of alternatives that do not treat their users with
+such disrespect. I ask anyone who is still using Pastebin to stop doing this,
+and use any of the alternatives.
+
+* [0bin.net](https://0bin.net/)
+* [cry.nu][crynu] (works like termbin: `nc cry.nu 9999 < file`)
+* [ix.io][ix]
+- [p.tyil.nl][tyilnl] (worsk like termbin: `nc p.tyil.nl 9999 < file`)
+
+[cloudflare]: /articles/on-cloudflare/
+[crynu]: https://cry.nu
+[hastebin]: http://hastebin.com
+[ix]: http://ix.io/
+[mitm]: https://en.wikipedia.org/wiki/Man-in-the-middle_attack
+[termbin]: http://termbin.com
+[tyilnl]: /
diff --git a/_posts/2016-10-01-on-systemd.md b/_posts/2016-10-01-on-systemd.md
new file mode 100644
index 0000000..b85c82f
--- /dev/null
+++ b/_posts/2016-10-01-on-systemd.md
@@ -0,0 +1,288 @@
+---
+layout: post
+title: On Systemd
+date: 2016-10-01 10:20:27 +0200
+tags: Article Harmful Systemd
+authors:
+ - ["Patrick Spek", "http://tyil.work"]
+ - ["Samantha McVey", "https://cry.nu"]
+---
+
+# Systemd
+Systemd once presented itself as being the next generation init system for
+GNU+Linux. When the project started it seemed to be headed in a good direction.
+Unfortunately, it quickly became clear that systemd's goal was not only to
+bring you a quick, new init system. It planned to do so much more. This was
+part of the plan, since init systems were generally considered to be in a bad
+state overall it was quickly accepted by most mainstream GNU+Linux
+distributions. What was at first only an init system became so much more:
+systemd-logind was made to manage tty's, systemd-resolvd was added to act as a
+caching DNS server. Even networking was added with systemd-networkd to manage
+network interfaces.
+
+**DISCLAIMER**: Systemd is a fast moving project, this may result in
+information here to becoming outdated. If you find any information that is no
+longer correct, please contact me. You can find my contact details [on my
+homepage][tyil].
+
+## Technical issues
+### Security
+From experience, we have seen that systemd's creator, Lennart Poettering, will
+try to assimilate any functionality he can find and add it into systemd. This
+causes systemd to have a large surface area of attack, adding to and magnifying
+security attack vectors. An init system should be exactly the opposite. To
+compound this issue, we have bugs like [the user-level DoS][systemd-dos],
+which seem to indicate that the software is hardly tested or written by
+programmers who don't use best practices.
+
+### POSIX
+POSIX compliance. Systemd developers seem to detest it. Their common argument
+against retaining POSIX compliance is that "systemd must break POSIX compliance
+in order to further the development of GNU+Linux userland utilities". While
+this may be true in some sense, it is a very bad idea to ignore POSIX
+altogether.
+
+POSIX is one of the reasons that most applications running on GNU+Linux and
+other Unix like systems are very portable. It's a standard that most OS's and
+distro's try to meet, making it easy to port software.
+
+[natermeer on Reddit][reddit-natermeer] said
+> POSIX has almost no relevance anymore.
+>
+> [...]
+>
+> If you care about portability you care about it running on OS X and Windows
+> as well as your favorite \*nix system. POSIX gains you nothing here. A lot
+> of the APIs from many of these systems will resemble POSIX closely, but if
+> you don't take system-specific differences into account you are not going
+> to accomplish much.
+
+> I really doubt that any Init system from any Unix system uses only POSIX
+> interfaces, except maybe NetBSD. All of them are going to use scripts and
+> services that are going to be running commands that use kernel-specific
+> features at some point. Maybe a init will compile and can be executed on
+> pure POSIX api, but that is a FAR FAR cry from actually having a booted and
+> running system.
+
+Which was replied to by [aidanjt][reddit-aidanjt]
+> Wrong, both OS X and Windows have POSIX support, although Window's is emulated,
+> OS X certainly is not, it's fully POSIX compliant. and b) POSIX doesn't have to
+> work identically everywhere, it only has to be more or less the same in most
+> places and downstream can easily patch around OS-specific quirks. Even
+> GNU/Linux and a bunch of the BSDs are merely regarded as 'mostly' POSIX
+> compliant, after all. But if you ignore POSIX entirely, there's ZERO hope of
+> portability.
+>
+> Actually sysvinit is very portable, init.c only has 1 single Linux header which
+> has been #ifdef'ed, to handle the three-finger-salute. You see, init really
+> isn't that complicated a programme, you tell the kernel to load it after it's
+> done it's thing, init starts, and loads distro scripts which starts userspace
+> programmes to carry on booting. No special voodoo magic is really required.
+> POSIX is to thank for that. POSIX doesn't need to be the only library eva, it
+> only needs to handle most of the things you can't do without, without having to
+> directly poke at kernel-specific interfaces.
+>
+> This is why with POSIX, we can take a piece of software written for a PPC AIX
+> mainframe, and make it work on x86 Linux without a complete rewrite, usually
+> with only trivial changes.
+
+### Dependencies and unportability
+Another common issue with systemd is that applications have started to
+needlessly depend on it, forcing systemd onto users that do not wish to use
+systemd for obvious reasons outlined here, reasons outside of this article, or
+simply being unable to use it. Because systemd complies to no cross-platform
+standard and uses many features only available in recent Linux version, it's
+either very hard or impossible to implement systemd in some circumstances.
+
+The list of features it requires is no small one either, as you can see in the
+list [posted by ohset][reddit-ohet]:
+
+- `/dev/char`
+- `/dev/disk/by-label`
+- `/dev/disk/by-uuid`
+- `/dev/random`
+- `/dev/rtc`
+- `/dev/tty0`
+- `/proc/$PID/cgroup`
+- `/proc/${PID}/cmdline`
+- `/proc/${PID}/comm`
+- `/proc/${PID}/fd`
+- `/proc/${PID}/root`
+- `/proc/${PID}/stat`
+- `/proc/cmdline`
+- `/sys/class/dmi/id`
+- `/sys/class/tty/console/active`
+- `BTRFS_IOC_DEFRAG`
+- `CLONE_xxx`
+- `F_SETPIPE_SZ`
+- `IP_TRANSPORT`
+- `KDSKBMODE`
+- `O_CLOEXEC`
+- `PR_CAPBSET_DROP`
+- `PR_GET_SECUREBITS`
+- `PR_SET_NAME`
+- `PR_SET_PDEATHSIG`
+- `RLIMIT_RTPRIO`
+- `RLIMIT_RTTIME`
+- `SCHED_RESET_ON_FORK`
+- `SOCK_CLOEXEC`
+- `TIOCLINUX`
+- `TIOCNXCL`
+- `TIOCVHANGUP`
+- `VT_ACTIVATE`
+- `\033[3J`
+- `audit`
+- `autofs4`
+- `capabilities`
+- `cgroups`
+- `fanotify`
+- `inotify`
+- `ionice`
+- `namespaces`
+- `oom score adjust`
+- `openat()` and friends
+- `selinux`
+- `settimeofday()` and its semantics
+- `udev`
+- `waitid()`
+- numerous GNU APIs like `asprintf`
+
+This made [Gnome][gnome] unavailable for a long time to BSD users and GNU+Linux
+users who wanted to remain with a sane and proven system. Utilities like
+[Gummiboot][gummiboot] are now being absorbed by systemd too. It is only a
+matter of time before you can no longer use this utility without a systemd init
+behind it. There are too many examples of software to list, which are being
+assimilated or made unavailable by lazy or bad developers who choose to depend
+on systemd for whatever reason.
+
+### Speed
+The main selling point many systemd users hail all the time, is speed. They
+place an unusual high amount of value on being a couple seconds faster on boot.
+Systemd gains this speed gain by using parallelization, and many think this is
+unique to systemd. Luckily for those who want to stick to a more sane system,
+this is false. Other init systems, such as [OpenRC][openrc], used by
+[Funtoo][funtoo], and [runit][runit], used by [Voidlinux][voidlinux] both
+support parallel startup of services. Both these systems use small and
+effective shell scripts for this, and support startup dependencies and the
+like. Systemd brings nothing new to the init world, it just advertises these
+features more agressively.
+
+### Modularity
+The UNIX principle, *make an application perform one task very well*, seems to
+be very unpopular among systemd developers. This principle is one of the
+reasons why UNIX based systems have gotten so popular. Yet, the systemd
+developers seem to despise this principle, and even try to argue that systemd
+actually is modular because **it compiles down to multiple binaries**. This
+shows a lack of understanding, which would make most users uneasy when they
+consider that these people are working on one of the most critical pieces of
+their OS.
+
+The technical problem this brings is that it is very hard to use systemd with
+existing tools. `journald` for instance doesn't just output plain text you can
+easily filter through, save or apply to a pager. I decides for you how to
+represent this information, even if this might be an ineffective way to go
+about it.
+
+### Binary logs
+Hailed by systemd users and developers as a more efficient, fast and secure way
+to store your logs, it is yet another middle finger to the UNIX principles,
+which state that documents intended for the user should be human readable.
+Binary logs are exactly not that. This forces you to use the tools bundled with
+systemd, instead of your preferred solution. This means you need a system with
+systemd in order to read your logs, which you generally need the most when the
+system that generated it crashed. Thanks to systemd, these logs are now useless
+unless you have another systemd available for it.
+
+These logs are also very fragile. It is a common "issue" to have corrupted logs
+when using systemd. Corrupted is here within quotes because the systemd
+developers do not recognize this as a bug. Instead, you should just rotate your
+logs and hope it does not happen again.
+
+The usual counter to this issue is that you *can* tell systemd to use another
+logger. However, this does not stop `journald` from processing them first or
+just not having `journald` at all. As systemd is not modular, you will always
+have all the pieces installed. It should also be noted that this is a
+*workaround*, not a fix to the underlying problem.
+
+## Political issues
+### Aggressively forced upon users
+A point that has made many systemd opponents very wary of this huge piece of
+software is the way it was introduced. Unlike most free software packages,
+systemd was forced into the lives of many users by getting hard dependencies on
+them, or simply absorbing a critical piece of software by the use of political
+power. The two most prominent pieces of software where this has happened are
+[Gnome][gnome] and [`udev`][udev].
+
+The Gnome developers made a hard dependency on systemd. This in effect made
+every gnome user suddenly require systemd. As a result, FreeBSD had to actually
+drop Gnome for a while, as systemd does not run outside of GNU+Linux.
+
+The other, `udev`, was a critical piece of software to manage devices in
+GNU+Linux. Sadly, some political power was shown by Red Hat and `udev` got
+absorbed into systemd. Luckily, the Gentoo guys saw this issue and tried to
+resolve it. As the systemd developers dislike anything that's not systemd
+itself, they stubbornly refused the patches from the Gentoo folks which would
+keep `udev` a single component (and thus usable without systemd). In the end,
+the Gentoo developers forked `udev` into [`eudev`][eudev].
+
+### Unwillingness to cooperate
+Whenever someone from outside the systemd fangroups steps up to actually
+improve systemd in whatever way, the systemd devs seem to be rather
+uncooperative. It is not uncommon for developers from other projects to make a
+change in order for their projects (and usually others) to improve. This
+removes a lot of the cost for the systemd maintainers to deal with all the
+issues created they are creating.
+
+There are some references to the systemd developers being against changes that
+might make systemd less of a problem, but these changes are usually denied with
+petty excuses.
+
+- https://lists.freedesktop.org/archives/systemd-devel/2012-June/005466.html
+- https://lists.freedesktop.org/archives/systemd-devel/2012-June/005507.html
+
+## How to avoid it
+### Choosing a better OS or distribution
+Nowadays, the only way to avoid it without too much trouble, is by simply
+choosing a better OS or distro that does not depend on systemd at all. There
+are a few choices for this:
+
+- \*BSD ([FreeBSD][freebsd], [OpenBSD][openbsd], and others)
+- [Devuan][devuan]
+- [Funtoo][funtoo]
+- [Voidlinux][voidlinux]
+
+It is a shame that it renders a very large chunk of the GNU+Linux world
+unavailable when choosing a distro, but they have chosen laziness over a
+working system. The only way to tell them at this point that they have made a
+wrong decision, is to simply stop using these distros.
+
+### More links
+
+- [Broken by design: systemd][broken-systemd]
+- [Without systemd][without-systemd]
+- [systemd is the best example of Suck][suckless-systemd]
+- [Thoughts on the systemd root exploit][agwa-systemd-root-exploit] (In response to [CVE-2016-10156][cve-2016-10156])
+- ["systemd: Please, No, Not Like This"](https://fromthecodefront.blogspot.nl/2017/10/systemd-no.html)
+
+[agwa-systemd-root-exploit]: https://www.agwa.name/blog/post/thoughts_on_the_systemd_root_exploit
+[broken-systemd]: http://ewontfix.com/14/
+[cve-2016-10156]: http://www.openwall.com/lists/oss-security/2017/01/24/4
+[devuan]: https://devuan.org/
+[eudev]: https://wiki.gentoo.org/wiki/Eudev
+[freebsd]: https://www.freebsd.org/
+[funtoo]: http://www.funtoo.org/Welcome
+[gentoo]: https://gentoo.org
+[gnome]: http://www.gnome.org/
+[gummiboot]: https://en.wikipedia.org/wiki/Gummiboot_(software)
+[openbsd]: https://www.openbsd.org/
+[openrc]: https://en.wikipedia.org/wiki/OpenRC
+[reddit-aidanjt]: https://www.reddit.com/r/linux/comments/132gle/eli5_the_systemd_vs_initupstart_controversy/c72saay
+[reddit-natermeer]: https://www.reddit.com/r/linux/comments/132gle/eli5_the_systemd_vs_initupstart_controversy/c70hrsq
+[reddit-ohet]: https://www.reddit.com/r/linux/comments/132gle/eli5_the_systemd_vs_initupstart_controversy/c70cao2
+[runit]: http://smarden.org/runit/
+[suckless-systemd]: http://suckless.org/sucks/systemd
+[systemd-dos]: https://github.com/systemd/systemd/blob/b8fafaf4a1cffd02389d61ed92ca7acb1b8c739c/src/core/manager.c#L1666
+[tyil]: http://tyil.work
+[udev]: https://wiki.gentoo.org/wiki/Eudev
+[voidlinux]: http://www.voidlinux.eu/
+[without-systemd]: http://without-systemd.org/wiki/index.php/Main_Page
diff --git a/_posts/2016-10-01-on-winmail-dat.md b/_posts/2016-10-01-on-winmail-dat.md
new file mode 100644
index 0000000..2522614
--- /dev/null
+++ b/_posts/2016-10-01-on-winmail-dat.md
@@ -0,0 +1,41 @@
+---
+layout: post
+title: On winmail.dat
+date: 2016-10-01 10:20:27 +0200
+wip: true
+authors:
+ - ["Patrick Spek", "http://tyil.work"]
+---
+
+# winmail.dat
+This article is intended for sysadmins who run email systems and those who
+maintain the Outlook instances for their workforce. If you do not belong into
+either of these categories, the following article is probably not too useful.
+
+If you are one of the many people that suffers from a sysadmin who has yet to
+fix the `winmail.dat` issues on his network, you can kindly redirect them here
+and hope that they are kind enough to improve their services. If they do not,
+you may want to look for a better sysadmin.
+
+## What is this `winmail.dat`?
+A `winmail.dat` is a file that Outlook will attach if an Outlook user sends an
+email containing actual attachments or any kind of markup unless Outlook has
+been configured not to do so. It is a binary format that holds all the
+information to the markup used in the email and the actual attachment that the
+user was trying to send. As is typical with Microsoft, this is incompatible
+with other Microsoft products. It will only "fix" itself if the receiver is
+also using Outlook.
+
+## Why should I care?
+This means that recipients of any mail sent using such a badly configured
+Outlook instance cannot see any markup used by the sender, nor can the
+recipient see any attachment. Most people can live without the markup, but not
+being able to see the actual attachments is generally a pretty big issue.
+
+Now, there are shady tools available to try and decode these `winmail.dat`
+files, but these will not work correctly in all circumstances. Furthermore, an
+end-user should not be required to depend on a shady tool to fix the symptom of
+a misconfigured email client from another party.
+
+## How can I fix this?
+
diff --git a/_posts/2016-10-03-install-funtoo.md b/_posts/2016-10-03-install-funtoo.md
new file mode 100644
index 0000000..6526093
--- /dev/null
+++ b/_posts/2016-10-03-install-funtoo.md
@@ -0,0 +1,808 @@
+---
+title: Install Funtoo
+wip: true
+date: 2016-10-03 18:05:59
+tags: Tutorial Installation Funtoo
+layout: post
+authors:
+ - ["Patrick Spek", "http://tyil.work"]
+---
+
+# Install Funtoo
+It has come to my attention that many people consider installing Gentoo, and in
+effect, Funtoo, a hard task to complete. Some people have also shown interest in
+my particular setup. In addition, my favourite English teacher, Anne the Lion,
+has tasked us students to write a tutorial to assess our English skills.
+
+As such, I have written this tutorial to show people my installation steps, and
+mentally please my teacher. If you have any suggestions or criticism, please
+find me on IRC. The networks I frequent and the nickname I use can be found on
+[my homepage][tyil].
+
+## Assumptions
+This tutorial assumes a few things from you. If you do not meet most of these
+assumptions, this guide is probably not for you. You can of course still read
+it, however, there might be a lot of jargon you do not understand, making the
+tutorial more complex to understand.
+
+- You have experience with GNU+Linux
+- You know your way in the terminal
+- You are not afraid of using text-based applications
+- You have experience reading through manuals and documentation
+- You are not afraid to spend some hours on IRC to help you troubleshoot issues
+
+## Installing Funtoo
+This tutorial will guide you through a not-so-basic installation of the Funtoo
+GNU+Linux distribution. It is based on one of my own installations, but
+slightly simplified.
+
+### The live environment
+Before you can get started with setting up the system, you will need something to
+set it up with. We will be using a live environment for this purpose. My
+personal choice for this task is [the Gentoo-based SystemRescueCD][sysrescuecd].
+
+You can use any other live environment your prefer, however, this tutorial will
+only guide you into preparing the System Rescue CD.
+
+#### Getting the live USB image
+You can download the System Rescue CD at one of the following locations:
+
+- [Funtoo][Funtoo]
+- [Osuosl][osuosl]
+
+#### Setting up the live USB
+After downloading the image, mount it somewhere:
+
+{% highlight sh %}
+mount path/to/sysrescuecd.iso /mnt/cdrom
+{% endhighlight %}
+
+Once it is mounted, you can run the installer bundled with the image by running
+
+{% highlight sh %}
+/mnt/cdrom/usb_inst.sh
+{% endhighlight %}
+
+Select the right device and wait for the installer to finish up.
+
+#### Booting the USB
+To begin using the live environment so you can install something with it, boot
+it up. Make sure the USB is in the machine, and reboot it. Enter the BIOS/UEFI
+settings and make sure to either make the USB device a higher boot priority, or
+select it to be the boot device for one boot. The availability and location of
+these options differs per machine, so be sure to check the manual or look around
+online for instructions if it is not clear to you.
+
+### Hardware preparation
+The hardware you are installing on needs to be prepared. This could mean
+manually configuring your hardware RAID if you use this and configuring other
+exotic setups. This tutorial will not go into details for such setups, as there
+is a near infinite amount of possible options. Instead, you should stick to
+simply configuring your storage device.
+
+The size of your storage device should be at least 35GB to be safe and have
+some space for personal data. The partitioning layout this guide is aiming for
+is the following:
+
+{% highlight plain %}
+DEVICE FILESYSTEM SIZE MOUNTPOINT
+sda
+ sda1 fat32 2GB /boot
+ sda2 lvm
+ funtoo0-root xfs 8GB /
+ funtoo0-home zfs /home
+ funtoo0-sources ext4 3GB /usr/src
+ funtoo0-portage reiserfs 2GB /usr/portage
+ funtoo0-swap swap
+ funtoo0-packages xfs 10GB /var/packages
+ funtoo0-distfiles xfs 10GB /var/distfiles
+{% endhighlight %}
+
+If you already an advanced user, you are of course free to diverge from the
+guide here.
+
+#### Partition the drive
+The first part is to setup partitions. This can be done by calling `gdisk
+/dev/sda`.
+
+Let us wipe the entire disk and start with a clean slate. You can do this by
+typing `o` and pressing enter. When asked wether you are sure, type `y` and
+enter again.
+
+Now you are going to create two partitions, one for `/boot` and one for
+[`lvm`][wikipedia-lvm]. Following is a list of what to enter. `<CR>` denotes
+pressing the enter key.
+
+- `n` `<CR>`
+- `<CR>`
+- `<CR>`
+- `+500M` `<CR>`
+- `EF00` `<CR>`
+
+- `n` `<CR>`
+- `<CR>`
+- `<CR>`
+- `<CR>`
+- `<CR>`
+
+#### Setting up encryption
+Any system should be safe. Encryption is just a small part, but in my opinion
+very important. We are going to encrypt the entire `lvm` partition using
+[`luks`][wikipedia-luks]. The frontend tool to be used for this is
+[`cryptsetup`][wikipedia-cryptsetup]:
+
+{% highlight sh %}
+cryptsetup --cipher aes-xts-plain64 --hash sha512 --key-size 256 luksFormat /dev/sda2
+{% endhighlight %}
+
+`cryptsetup` will ask you for a passphrase. Make sure to use a good one,
+preferably at least 20 characters in length.
+
+Once the partition has been encrypted, open the device so it can be used by
+invoking `cryptsetup luksOpen /dev/sda2 dmcrypt_lvm`.
+
+#### Set up LVM
+Once the encrypted partition has been unlocked, you can setup `lvm` on it. To
+initialize an lvm volume on this partition, run the following:
+
+{% highlight sh %}
+pvcreate /dev/mapper/dmcrypt_lvm
+vgcreate funtoo0 /dev/mapper/dmcrypt_lvm
+{% endhighlight %}
+
+The lvm volume has now been prepared, and you can start adding volumes to it to
+be used as partitions. It is recommended to have a swap partition as well. The
+size of this partition depends on the amount of RAM you have available. Due to
+my availability to big disks, I generally opt for a swap partition the same size
+as my total RAM in the machine. To make the tutorial work for this as well, a
+subshell is called to figure out the size of the swap partition.
+
+{% highlight sh %}
+lvcreate -L8G -n root funtoo0
+lvcreate -L3G -n sources funtoo0
+lvcreate -L2G -n portage funtoo0
+lvcreate -L10G -n packages funtoo0
+lvcreate -L10G -n distfiles funtoo0
+lvcreate -L$(free -h | grep -i mem: | awk '{print $2}') -n swap funtoo0
+lvcreate -l 100%FREE -n home funtoo0
+{% endhighlight %}
+
+#### Create filesystems
+Now you are ready to create usable filesystems on the partitions:
+
+{% highlight sh %}
+mkfs.vfat -F32 /dev/sda1
+mkfs.xfs /dev/mapper/funtoo0-root
+mkfs.xfs /dev/mapper/funtoo0-packages
+mkfs.xfs /dev/mapper/funtoo0-distfiles
+mkfs.reiserfs /dev/mapper/funtoo0-portage
+mkfs.ext4 /dev/mapper/funtoo0-sources
+mkswap /dev/mapper/funtoo0-swap
+{% endhighlight %}
+
+If you're thinking at this point "where's my home partition?", it's not
+initialized here. [ZFS][wikipedia-zfs] requires custom kernel modules which will
+be built later, after the initial kernel has been compiled.
+
+#### Mount the filesystems
+Next up is mounting all filesystems so you can install files to them. First, you
+mount the root filesystem:
+
+{% highlight sh %}
+mount /dev/mapper/funtoo0-root /mnt/gentoo
+{% endhighlight %}
+
+Now you can add some directories for the other mountpoints. This can be done in
+one well-made `mkdir` invocation:
+
+{% highlight sh %}
+mkdir -p /mnt/gentoo/{boot,home,usr/{portage,src},var/{tmp,distfiles,packages},tmp}
+{% endhighlight %}
+
+Next you can mount all other mountpoints on the new directories:
+
+{% highlight sh %}
+mount /dev/sda1 /mnt/gentoo/boot
+mount /dev/mapper/funtoo0-portage /mnt/gentoo/usr/portage
+mount /dev/mapper/funtoo0-sources /mnt/gentoo/usr/src
+mount /dev/mapper/funtoo0-distfiles /mnt/gentoo/var/distfiles
+mount /dev/mapper/funtoo0-packages /mnt/gentoo/var/packages
+{% endhighlight %}
+
+Let's also enable swap and ramdisks for the temporary storage directories:
+
+{% highlight sh %}
+swapon /dev/mapper/funtoo0-swap
+mount -t tmpfs none /mnt/gentoo/tmp
+mount --rbind /mnt/gentoo/tmp /mnt/gentoo/var/tmp
+{% endhighlight %}
+
+### Initial setup
+Now that all mountpoints have been set up, installation of the actual OS can
+begin. This is done by downloading a "stage 3" tarball containing a bare minimal
+Funtoo installation and extracting it with the right options.
+
+The stage 3 tarball can be downloaded from [build.funtoo.org][funtoo-build]. It
+is easiest to download and extract the tarball in the root filesystem, so let's
+do that:
+
+{% highlight sh %}
+cd /mnt/gentoo
+wget http://build.funtoo.org/funtoo-current/x86-64bit/generic_64/stage3-latest.tar.xz
+tar xpf stage3-latest.tar.xz
+{% endhighlight %}
+
+Once extraction is complete, you can opt to delete the tarball as it is no
+longer needed at this point. You can delete it by invoking `rm stage3-latest.tar.gz`.
+
+### System configuration
+You now have a bare Funtoo installation ready on your machine. But before you
+can actually use it, you should do some configuration.
+
+#### Chrooting
+Before you get to the configuration part, you should [`chroot`][wikipedia-chroot]
+into the system. This allows you to enter your new Funtoo installation before it
+can properly boot. If your system ever breaks and you are unable to boot into it
+anymore, you can redo the mounting section of this guide and this chrooting
+section to get into it and resolve your issues.
+
+The chrooting requires a couple extra mounts, so the chroot can interface with
+the hardware provided by the system above it:
+
+{% highlight sh %}
+mount -t proc none proc
+mount --rbind /dev dev
+mount --rbind /sys sys
+{% endhighlight %}
+
+Once these mountpoints are set, you will need to copy over `resolv.conf` so the
+chroot can resolve DNS names:
+
+{% highlight sh %}
+cp /etc/resolv.conf etc
+{% endhighlight %}
+
+Now that everything is prepared in the chroot, you can enter your Funtoo
+installation using the following:
+
+{% highlight sh %}
+chroot . bash -l
+{% endhighlight %}
+
+#### Set up the portage tree
+The portage tree is a collection of files which are used by the package manager
+to find out which software it can install, and more importantly, how to install
+it.
+
+The default location in Funtoo for your portage tree is in `/usr/portage`.
+However, as I use multiple sources for my portage tree, I prefer to set it up
+under `/usr/portage/funtoo`. This is not a required step, but advised nonetheless.
+
+In order to change this, open up `/etc/portage/repos.conf/gentoo` in your
+favourite editor. Funtoo comes with [`vi`][wikipedia-vi],
+[`nano`][wikipedia-nano] and [`ed`][wikipedia-ed] by default. `ed` is
+recommended as the standard editor. After opening the file, change the
+`location` key to point to `/usr/portage/funtoo`.
+
+When you have modified `/etc/portage/repos.conf/gentoo` (or not, if you do not
+want to change this default), continue to download your first version of the
+portage tree:
+
+{% highlight sh %}
+emerge --sync
+{% endhighlight %}
+
+Everytime you want to update your system, you will have to do an `emerge --sync`
+to update the portage tree first. It is managed by [`git`][wikipedia-git], which
+can bring some side effects. The most notable one is that the tree will grow
+over time with old commit data. If you wish to clean this up, simply
+`rm -rf /usr/portage/* && emerge --sync` to regenerate it from scratch
+
+#### Setting up your system settings
+In order to make the system work properly, some setup has to be performed. This
+will involve editing some text files, for which you can use your favourite
+editor again.
+
+##### /etc/fstab
+We will begin with the most important one, `/etc/fstab`. This file holds
+information on your mountpoints. Some of the mountpoints are best configured
+with UUIDs, because the device enumeration can sometimes differ. If you have
+multiple storage devices in your system, this could as well be a hard
+requirement. UUIDs are unique to each storage device, so you will have to figure
+out your UUIDs yourself. You can do this by running `lsblk -o +UUID`. Take note
+of the UUID of your boot device.
+
+Once you know the UUID, open up `/etc/fstab` with whatever editor you feel
+comfortable with and make it look like the following block of text. Do not
+forget to update the UUIDs!
+
+{% highlight plain %}
+# boot device
+/dev/sda1 /boot vfat noauto,noatime 1 2
+
+# lvm volumes
+/dev/mapper/funtoo0-root / xfs rw,relatime,data=ordered 0 1
+/dev/mapper/funtoo0-portage /usr/portage reiserfs defaults 0 0
+/dev/mapper/funtoo0-sources /usr/src ext4 noatime 0 1
+/dev/mapper/funtoo0-packages /var/packages xfs defaults 0 1
+/dev/mapper/funtoo0-distfiles /var/distfiles xfs defaults 0 1
+
+# ramdisks
+tmpfs /tmp tmpfs defaults 0 0
+
+# swap
+/dev/mapper/funtoo0-swap none swap defaults 0 0
+
+# binds
+/tmp /var/tmp none rbind 0 0
+{% endhighlight %}
+
+##### /etc/localtime
+The localtime comes next. This is to make sure your time is set correctly. An
+incorrect time can cause issues such as secure connections failing. To set your
+localtime, all you need to do is create a symlink. The file you need to symlink
+to is stored in `/usr/share/zoneinfo`. The files are sorted by continent. As
+someone who lives in the Netherlands, I'd use
+`/usr/share/zoneinfo/Europe/Amsterdam`:
+
+{% highlight sh %}
+ln -fs /usr/share/zoneinfo/Europe/Amsterdam /etc/localtime
+{% endhighlight %}
+
+It is important to also correctly set your hardware clock, in case it is off.
+Check if your time and date are correct by invoking `date`. If these settings
+are correct, you can skip towards the next heading. Otherwise, keep on reading
+this bit.
+
+To set the correct time, you can use the `date` utility again. When invoked with
+an argument in the form of `MMDDhhmmYYYY`, it will set the date and time instead
+of check it. The following command would set the date to the first of October
+2016, and the time to 17:29:
+
+{% highlight sh %}
+date 011017292016
+{% endhighlight %}
+
+After you correctly set the date and time to whatever it currently is, sync it
+to the hardware clock so it is correct across reboots:
+
+{% highlight sh %}
+hwclock --systohc
+{% endhighlight %}
+
+##### /etc/portage/make.conf
+Another important part to configure is the `make.conf` file. This file contains
+settings for portage and some options for compilers. This file can also be made
+a directory. This way, you can split off your configs into multiple files for
+easier maintainance. The files will be loaded alphabetically. The way you set it
+up is completely up to you, though I would recommend removing the default
+`/etc/portage/make.conf` and making it a directory instead.
+
+Once you have decided how to setup your make.conf, it is time to add some data
+in the file(s). Following is a list of useful variables to set up, with a block
+containing my own settings for it. You can copy these for yourself, or dig
+aroudn some manpages to find out what you exactly want yourself.
+
+###### USE
+`USE` holds global USE flags. These are used to configure your packages. You can
+turn features on and off using these, and the ebuilds will configure the
+packages to enable or disable these features.
+
+{% highlight sh %}
+USE="
+ ${USE}
+ alsa
+ gtk
+ gtkstyle
+ infinality
+ vim-syntax
+ zsh-completion
+ -pulseaudio
+ -systemd
+ -gnome
+ -kde
+"
+{% endhighlight %}
+
+###### FEATURES
+The `FEATURES` variable allows enabling of various portage features. Mine are
+setup to drop privileges so root is used as little as possible and to do as much
+parallel as possible to speed up the process. Additionally, I use the `buildpkg`
+feature to build binary packages for use on other systems. This can save you a
+great deal of time if you have multiple systems running Funtoo.
+
+{% highlight sh %}
+FEATURES="
+ ${FEATURES}
+ buildpkg
+ network-sandbox
+ parallel-fetch
+ parallel-install
+ sandbox
+ userfetch
+ userpriv
+ usersandbox
+ usersync
+"
+{% endhighlight %}
+
+###### EMERGE_DEFAULT_OPTS
+`EMERGE_DEFAULT_OPTS` can be used to add some flags to every emerge you invoke.
+This way you can force emerge to always ask for confirmation.
+
+{% highlight sh %}
+EMERGE_DEFAULT_OPTS="
+ ${EMERGE_DEFAULT_OPTS}
+ --alert
+ --ask
+ --binpkg-changed-deps=y
+ --binpkg-respect-use=y
+ --keep-going
+ --tree
+ --usepkg
+ --verbose
+"
+{% endhighlight %}
+
+###### C/XXFLAGS
+The `CFLAGS` and `CXXFLAGS` variables hold compiler-specific options. It is
+**very** important to not use newlines in these two, as [they will break
+`cmake`][bug-cmake]. Other than that, it is just a regular shell variable like
+the others.
+
+{% highlight sh %}
+CFLAGS="-O2 -pipe"
+CXXFLAGS="-O2 -pipe"
+{% endhighlight %}
+
+###### ACCEPT_LICENSE
+This variable is not as important as the others. You can even opt to leave it
+out completely. If, however, you wish to limit portage to only install free
+software (free as in freedom, not gratis), you can set it to the same value as
+me. Do note that if you use this, you will need to setup the
+`/etc/portage/package.license` as well.
+
+{% highlight sh %}
+ACCEPT_LICENSE="
+ -*
+ @FREE
+"
+{% endhighlight %}
+
+###### MAKEOPTS
+`MAKEOPTS` are the arguments passed to `make`. This can be used to instruct
+`make` to use multiple threads when compiling software. The amount of threads
+can be set with the `-j` flag. The general rule of thumb for this is to use
+`$(($(nproc) + 1))`.
+
+{% highlight sh %}
+MAKEOPTS="
+ -j9
+"
+{% endhighlight %}
+
+###### PKG/DISTDIR
+The `PKGDIR` and `DISTDIR` variables set the location to store binary packages
+after building, and the location to store distfiles. In order to use the
+`/var/distfiles` and `/var/packages` partitions, these must be set.
+
+{% highlight sh %}
+DISTDIR=/var/distfiles
+PKGDIR=/var/packages
+{% endhighlight %}
+
+##### /etc/portage/package.mask
+Like the `make.conf` file, `package.mask` can be made a directory containing
+seperate files.
+
+The `package.mask` file(s) allow you to "mask" packages, instructing portage to
+ignore these. It can also let you mask certain versions of packages. This way
+you can skip a broken version or stick to a certain version for whatever reason.
+Since this tutorial uses ZFS, there is such a reason to do exactly that.
+
+ZFS requires a Linux at version 4.4 or lower. The latest kernel is much higher
+than that, so it is necessary to mask newer kernel versions. This is a single
+line of configuration, and as such can be done without a fancy editor. Simply
+invoke the following magic:
+
+{% highlight sh %}
+mkdir -p /etc/portage/package.mask
+echo ">sys-kernel/gentoo-sources-4.4.6" > /etc/portage/package.mask/20-zfs.mask
+{% endhighlight %}
+
+##### /etc/portage/package.license
+This file can be setup as a directory too, just like `make.conf` and
+`package.mask`. Using this file or directory you can add per-package license
+exceptions. This is therefore only needed if you setup a strict license limit.
+The kernel comes with some sources under the `freedist` license, which is not
+part of `@FREE`. As such, if you want to install kernel sources you will have to
+make an exception for this license on this package.
+
+{% highlight sh %}
+mkdir -p /etc/portage/package.license
+echo "sys-kernel/gentoo-sources freedist" > /etc/portage/package.license/20-freedist.license
+{% endhighlight %}
+
+##### /etc/conf.d/hostname
+As one of the last files to setup, the hostname should be set in
+`/etc/conf.d/hostname`. The `hostname` variable in this file should be set to
+the hostname of the machine. You can pick any name you like, but should be
+unique across your network.
+
+#### Preparing your first kernel
+Every system needs a kernel, a piece of software to interface with the hardware.
+Funtoo, like every GNU+Linux distribution, uses the Linux kernel for this task.
+
+For this task, you will first need to decide on a source set to use. All source
+sets share the same base, but they have different patches applied. It is
+recommended to use `sys-kernel/gentoo-sources`. If this isn't bleeding edge
+enough, you can use `sys-kernel/git-sources` instead. If you just want the
+latest official kernel without the gentoo patchset, pick
+`sys-kernel/vanilla-sources`. No matter which source set you use, the
+compilation and installation process remains the same.
+
+Install whichever source set you want to use, this guide will use
+`sys-kernel/gentoo-sources`. In order to save some yes-pressing later on, the
+`emerge` command here will install some additional packages which are needed for
+the system to function properly.
+
+{% highlight sh %}
+emerge boot-update cryptsetup lvm2 gentoo-sources
+genkernel --menuconfig --lvm --luks all
+{% endhighlight %}
+
+The `genkernel` command will run the kernel menuconfig utility. If you have
+exotic hardware that needs special support, this is the place to enable it. The
+defaults are sane for most systems. If you have nothing to configure here, just
+exit the menuconfig and let `genkernel` build a custom kernel and initramfs for
+you. As the guide uses LVM and LUKS, you will need to have support for these
+things in your kernel. You will need to enable the following options at the
+very least:
+
+{% highlight plain %}
+General setup --->
+ [*] Initial RAM filesystem and RAM disk (initramfs/initrd) support
+{% endhighlight %}
+
+{% highlight plain %}
+Device Drivers --->
+ Generic Driver Options --->
+ [*] Maintain a devtmpfs filesystem to mount at /dev
+{% endhighlight %}
+
+{% highlight plain %}
+Device Drivers --->
+ [*] Multiple devices driver support --->
+ <*>Device Mapper Support
+ <*> Crypt target support
+{% endhighlight %}
+
+{% highlight plain %}
+Cryptographic API --->
+ <*> XTS support
+ -*-AES cipher algorithms
+{% endhighlight %}
+
+#### Setup ZFS
+The kernel is now installed at `/boot`, and all the required parts to build
+custom kernel modules are available. This means it is now possible to build the
+ZFS modules.
+
+First install the kernel module here. Since the live kernel does not have the
+zfs modules from the chroot, you must create the pool and the volumes after the
+first reboot.
+
+{% highlight sh %}
+emerge zfs
+{% endhighlight %}
+
+Once it has been compiled, you can add the ZFS services to start up by default.
+This will load the kernel module for you and all additional services that make
+ZFS perform its job well.
+
+{% highlight sh %}
+rc-update add zfs-import boot
+rc-update add zfs-mount boot
+rc-update add zfs-share default
+rc-update add zfs-zed default
+{% endhighlight %}
+
+#### Installing a bootloader
+Before building your kernel, `boot-update` was installed. This pulls in
+[`grub`][wikipedia-grub], the recommended bootloader for Funtoo. It doesn't
+require a lot of configuration thanks to the `boot-update` script, which will
+configure `grub` for you.
+
+Before running the script, there's one place to update as this setup uses `luks`
+and `lvm`.
+
+Open up `/etc/boot.conf` in your favourite editor and let the file display
+something like this:
+
+{% highlight plain %}
+boot {
+ generate grub
+ default "Funtoo GNU+Linux"
+ timeout 3
+}
+
+"Funtoo GNU+Linux" {
+ kernel kernel[-v]
+ initrd initramfs[-v]
+ params += crypt_root=/dev/sda2 real_root=/dev/mapper/funtoo0-root rootfstype=xfs dolvm
+}
+{% endhighlight %}
+
+Now that `boot-update` is configured, install `grub` as an UEFI bootloader and
+generate the configs for it using `boot-update`. You should make sure the
+`grub` directory exists in `/boot` as well.
+
+{% highlight sh %}
+mkdir -p /boot/grub
+grub-install --target=x86_64-efi --efi-directory=/boot --bootloader-id="Funtoo GNU+Linux" --recheck /dev/sda
+boot-update
+{% endhighlight %}
+
+#### Set your system profile
+Your system is now ready to boot and use. However, some things are still not
+configured. These can in some cases be configured after rebooting, but it is
+recommended to fix it all up now. The first part is setting your system profile.
+
+For a full list of settings, check `epro list`. Maybe you want to use this
+system as something other than a workstation, or want to enable the `gnome`
+mix-in.
+
+To get the same profile settings as I use for my work environments, run the
+following:
+
+{% highlight sh %}
+epro flavor workstation
+epro mix-ins +no-systemd
+{% endhighlight %}
+
+#### Running the first full system update
+The stage 3 tarball may have been the latest, but it might still have some
+slightly outdated packages. In addition, now that your system profile is set up,
+some applications may be configured to have different feature sets enabled. To
+make sure everything is in the best possible state, it is recommended to run a
+full system update now. Since some of our options are already set as
+`EMERGE_DEFAULT_OPTS`, this is as simple as
+
+{% highlight sh %}
+emerge -uDN @world
+{% endhighlight %}
+
+#### Installing supporting software
+This is software you will more than likely need on any standard system. If
+you're an advanced user you can decide to skip this and make your own choices,
+otherwise it is recommended to install this software as well.
+
+{% highlight sh %}
+emerge connman sudo vim linux-firmware
+{% endhighlight %}
+
+#### Configuring supporting software
+Some of the supporting software has to be turned on explicitly or have a
+configuration file tweaked. If you opted to not use a given recommended package,
+you can skip the section with the same name.
+
+##### connman
+[`connman`][wikipedia-connman] is a simple **conn**ection **man**ager. It's
+lightweight, fast and does its job pretty well. To enable this service at boot,
+run
+
+{% highlight sh %}
+rc-update add connman default
+{% endhighlight %}
+
+If you want to setup wireless connection authentication credentials, read up on
+`man connman-service.conf`.
+
+##### sudo
+The [`sudo`][wikipedia-sudo] utility allows certain users, based on their
+username or groups they belong to, access to privileged commands. It can also be
+used to run a command as a different user. The most basic setup allows people
+from the `wheel` group to execute commands normally reserved for `root`.
+
+Because sudo is a critical utility, it comes with its own editor that basically
+just wraps your preferred editor in a script that will complain if the
+configuration is wrong. To use this tool, invoke
+
+{% highlight sh %}
+visudo
+{% endhighlight %}
+
+Scroll to the line which contains `# %wheel ALL=(ALL) ALL`, and remove the `# `.
+
+#### Set passwords
+We probably want to be able to login to the system as well. By default, users
+without passwords are disabled, so you'll need to set a password for the users
+you want to be able to use:
+
+{% highlight sh %}
+passwd root
+{% endhighlight %}
+
+If you used a different username than `tyil`, be sure to change it here as well.
+
+### First boot
+Installation is now finished, so it is time to boot into your new Funtoo system.
+First you should cleanly unmount all partitions and then issue a reboot:
+
+{% highlight sh %}
+exit
+cd
+umount -lR /mnt/gentoo
+reboot
+{% endhighlight %}
+
+If you set your UEFI to favour the USB system over the standard drive in the
+booting order, be sure to either change this back, or simply remove the USB
+device.
+
+### First boot configurations
+After your system has succesfully booted, login as root using the password you
+set using `passwd` before rebooting.
+
+#### ZFS
+Now you can finally setup the ZFS partition. Issue the following commands to
+create a pool and a subvolume for `/home`:
+
+{% highlight sh %}
+zpool create funtooz /dev/sda
+zfs create -o mountpoint=/home funtooz/home
+{% endhighlight %}
+
+#### Create a user
+Create a user for yourself on the system, as you should not perform regular
+usage as root. You can use any other value for `tyil` if you so desire:
+
+{% highlight sh %}
+useradd -m -g users -G wheel tyil
+passwd tyil
+{% endhighlight %}
+
+The `-G wheel` part is optional, but recommended if you wish to use this account
+for administrative tasks. This option adds the user to the `wheel` group, which
+will allow the user to execute root commands using `sudo`.
+
+#### Login
+Now you have a non-privileged user to login to. Log out of the root user by
+running `exit`. Next, log in on your normal user account.
+
+## What's next
+Now you have a working Funtoo installation. Next steps would be installing all
+the software you wish to use and configuring it to your liking. I would greatly
+advise looking at other people's configurations and publishing your
+configurations as well. These configuration collections are often called
+*dotfiles*. Mine can be found [on c.darenet.org][dotfiles].
+
+If this is your first time using Funtoo as your distro of choice, I would
+recommend looking through [Funtoo (GNU+)Linux First Steps][funtoo-first] on the
+official Funtoo wiki.
+
+If you need assistance on maintainance, you can always drop by in `#sqt` on
+[Gratisnode][freenode].
+
+[bug-cmake]: https://bugs.gentoo.org/show_bug.cgi?id=500034#c6
+[dotfiles]: https://c.darenet.org/tyil/dotfiles-gohan
+[funtoo-first]: http://www.funtoo.org/Funtoo_Linux_First_Steps
+[freenode]: https://freenode.net
+[funtoo-build]: http://build.funtoo.org/
+[funtoo]: http://build.funtoo.org/distfiles/sysresccd/systemrescuecd-x86-4.7.1.iso
+[osuosl]: http://ftp.osuosl.org/pub/funtoo/distfiles/sysresccd/systemrescuecd-x86-4.7.1.iso
+[sysrescuecd]: http://www.system-rescue-cd.org/SystemRescueCd_Homepage
+[tyil]: http://tyil.work
+[wikipedia-chroot]: https://en.wikipedia.org/wiki/Chroot
+[wikipedia-connman]: https://en.wikipedia.org/wiki/ConnMan
+[wikipedia-cryptsetup]: https://en.wikipedia.org/wiki/Dm-crypt#cryptsetup
+[wikipedia-ed]: https://en.wikipedia.org/wiki/Ed_(text_editor)
+[wikipedia-git]: https://en.wikipedia.org/wiki/Git
+[wikipedia-grub]: https://en.wikipedia.org/wiki/GNU_GRUB
+[wikipedia-luks]: https://en.wikipedia.org/wiki/Linux_Unified_Key_Setup
+[wikipedia-lvm]: https://en.wikipedia.org/wiki/Logical_Volume_Manager_(Linux)
+[wikipedia-nano]: https://en.wikipedia.org/wiki/GNU_nano
+[wikipedia-sudo]: https://en.wikipedia.org/wiki/Sudo
+[wikipedia-vi]: https://en.wikipedia.org/wiki/Vi
+[wikipedia-zfs]: https://en.wikipedia.org/wiki/ZFS
+
diff --git a/_posts/2016-10-25-setup-a-vpn-with-cjdns.md b/_posts/2016-10-25-setup-a-vpn-with-cjdns.md
new file mode 100644
index 0000000..d97a42f
--- /dev/null
+++ b/_posts/2016-10-25-setup-a-vpn-with-cjdns.md
@@ -0,0 +1,212 @@
+---
+title: Setup a VPN with cjdns
+date: 2016-10-25 08:00:34
+tags: Tutorial Cjdns Installation VPN
+layout: post
+authors:
+ - ["Patrick Spek", "http://tyil.work"]
+---
+
+# Setup VPN with cjdns
+In this tutorial I will outline a simple setup for a [VPN][vpn] using
+[`cjdns`][cjdns]. Cjdns will allow you to setup a secure mesh vpn which uses
+IPv6 internally.
+
+## Requirements
+For this tutorial, I have used two client machines, both running Funtoo. A
+FreeBSD 11 server is used as a global connection point.
+
+You are ofcourse able to use any other OS or distro supported by cjdns, but you
+may have to update some steps to work on your environment in that case.
+
+## Installation of the server
+### Dependencies
+Before you can begin, we need some dependencies. There's only two of those, and
+they are available via `pkg` to make it even easier. Install them as follows:
+
+{% highlight sh %}
+pkg install gmake node
+{% endhighlight %}
+
+### Compiling
+Next up is getting the cjdns sources and compile these, as cjdns is not
+available as a prebuilt package:
+
+{% highlight sh %}
+mkdir -p ~/.local/src
+cd $_
+git clone https://github.com/cjdelisle/cjdns.git cjdns
+cd $_
+./do
+{% endhighlight %}
+
+To make the compiled binary available system-wide so we can use it with a
+system service, copy it to `/usr/local/bin` and rehash to make it available as
+a direct command:
+
+{% highlight sh %}
+cp cjdroute /usr/local/bin/.
+hash -r
+{% endhighlight %}
+
+### Configuring
+Cjdns provides a flag to generate the initial configuration. This will provide
+you with some sane defaults where only a couple of small changes are needed to
+make it work properly. Generate these defaults with `--genconf`:
+
+{% highlight sh %}
+(umask 177 && cjdroute --genconf > /usr/local/etc/cjdroute.conf)
+{% endhighlight %}
+
+The umask will make all following commands write files using `600` permissions.
+This makes sure the config file is not readable by people who shouldn't be able
+to read it. Be sure to check wether the owner of the file is `root`!
+
+Now you can start actually configuring the node to allow incoming connections.
+You have to find the `authorizedPasswords` array in the `cjdroute.conf` file
+and remove the contents of it. Then you can add your own machines in it. This
+guide follows the assumption of two clients, so the config for two clients will
+be shown here. You can add more clients if you wish, ofcourse.
+
+{% highlight json %}
+"authorizedPasswords":
+[
+ {"password": "aeQu6pa4Vuecai3iebah7ogeiShaeDaepha6Mae1yooThoF0oa0Eetha9oox", "user": "client_1"},
+ {"password": "aiweequuthohkahx4tahLohPiezee9OhweiShoNeephe0iekai2jo9Toorah", "user": "client_2"},
+]
+{% endhighlight %}
+
+If you need to generate a password, you can make use of the tool `pwgen`,
+available at your local package manager. You can then generate new passwords by
+running `pwgen 60 -1`. Change the `60` around if you want passwords of a
+different size.
+
+### Adding a startup service
+rcinit has deceptively easy scripts to make applications available as services.
+This in turn allows you to enable a service at startup. This way you can make
+sure cjdns starts whenever the server boots. You can copy the following
+contents directly into `/usr/local/etc/rc.d/cjdroute`:
+
+{% highlight sh %}
+#! /bin/sh
+
+# PROVIDE: cjdroute
+# KEYWORD: shutdown
+
+#
+# Add the following lines to /etc/rc.conf to enable cjdroute:
+#
+#cjdroute_enable="YES"
+
+. /etc/rc.subr
+
+name="cjdroute"
+rcvar="cjdroute_enable"
+
+load_rc_config $name
+
+: ${cjdroute_config:=/usr/local/etc/cjdroute.conf}
+
+command="/usr/local/bin/cjdroute"
+command_args=" < ${cjdroute_config}"
+
+run_rc_command "$1"
+{% endhighlight %}
+
+Afterwards, you must enable the service in `/etc/rc.conf.local` like follows:
+
+{% highlight sh %}
+echo 'cjdroute_enable="YES"' >> /etc/rc.conf.local
+{% endhighlight %}
+
+## Installation of the clients
+### Dependencies
+The dependencies are still on `gmake` and `node`, so simply install those on
+your clients. This guide assumes using Funtoo for the clients, so installation
+would go as follows:
+
+{% highlight sh %}
+emerge gmake nodejs
+{% endhighlight %}
+
+### Compiling
+Compilation is the same as for the server, so check back there for more
+information if you have already forgotten.
+
+### Configuring
+Generating the base configuration is again done using `cjdroute --genconf`,
+just like on the server. On Funtoo, config files generally reside in `/etc`
+instead of `/usr/local/etc`, so you should set the filepath you write the
+configuration to accordingly:
+
+{% highlight sh %}
+cjdroute --genconf > /etc/cjdroute.conf
+{% endhighlight %}
+
+Setting up the connections differs as well, as the clients are going to make an
+outbound connection to the server, which is configured to accept inbound
+connections.
+
+You should still clean the `authorizedPasswords` array, as it comes with a
+default entry that is uncommented.
+
+Now you can setup outbound connections on the clients. You set these up in the
+`connectTo` block of `cjdroute.conf`. For this example, the IP 192.168.1.1 is
+used to denote the server IP. Unsurprisingly, you should change this to your
+server's actual IP. You can find the `publicKey` value at the top of your
+server's `cjdroute.conf` file.
+
+On client 1, put the following in your `cjdroute.conf`:
+
+{% highlight json %}
+"connectTo":
+{
+ "192.168.1.1:9416":
+ {
+ "login": "client_1",
+ "password": "aeQu6pa4Vuecai3iebah7ogeiShaeDaepha6Mae1yooThoF0oa0Eetha9oox",
+ "publicKey": "thisIsJustForAnExampleDoNotUseThisInYourConfFile_1.k"
+ }
+}
+{% endhighlight %}
+
+On client 2:
+
+{% highlight json %}
+"connectTo":
+{
+ "192.168.1.1:9416":
+ {
+ "login": "client_2",
+ "password": "aiweequuthohkahx4tahLohPiezee9OhweiShoNeephe0iekai2jo9Toorah",
+ "publicKey": "thisIsJustForAnExampleDoNotUseThisInYourConfFile_1.k"
+ }
+}
+{% endhighlight %}
+
+That is all for configuring the nodes.
+
+### Adding a startup service
+You probably want cjdroute to run at system startup so you can immediatly use
+your VPN. For openrc based systems, such as Funtoo, cjdns comes with a ready to
+use service script. To make this available to your system, copy it over to the
+right directory:
+
+{% highlight sh %}
+cp ~/.local/src/cjdns/contrib/openrc/cjdns /etc/init.d/cjdroute
+{% endhighlight %}
+
+Now add the service to system startup and start the service:
+
+{% highlight sh %}
+rc-update add cjdroute default
+rc-service cjdroute start
+{% endhighlight %}
+
+That should be sufficient to get cjdns up and running for an encrypted VPN. You
+can find the IPs of each of your systems at the top of your `cjdroute.conf`
+files, in the `ipv6` attribute.
+
+[cjdns]: https://github.com/cjdelisle/cjdns
+[vpn]: https://en.wikipedia.org/wiki/Virtual_private_network
+
diff --git a/_posts/2016-10-25-setup-nginx-with-lets-encrypt-ssl.md b/_posts/2016-10-25-setup-nginx-with-lets-encrypt-ssl.md
new file mode 100644
index 0000000..62299a1
--- /dev/null
+++ b/_posts/2016-10-25-setup-nginx-with-lets-encrypt-ssl.md
@@ -0,0 +1,229 @@
+---
+title: Setup nginx with Let's Encrypt SSL
+date: 2016-10-25 08:00:34
+tags: Tutorial Installation LetsEncrypt Nginx SSL Encryption
+layout: post
+authors:
+ - ["Patrick Spek", "http://tyil.work"]
+---
+
+# Setup nginx with Let's Encrypt SSL
+This is a small tutorial to setup nginx with Let's Encrypt on a FreeBSD server
+to host a static site.
+
+## Install required software
+First you have to install all the packages we need in order to get this server
+going:
+
+{% highlight sh %}
+pkg install nginx py27-certbot
+{% endhighlight %}
+
+## Configure nginx
+Next is nginx. To make life easier, you should configure nginx to read all
+configuration files from another directory. This allows you to store all your sites in
+separate configurations in a separate directory. Such a setup is a regular site on
+nginx installations on GNU+Linux distributions, but not default on FreeBSD.
+
+Open up `/usr/local/etc/nginx/nginx.conf` and make the contents of the `http`
+block look a as follows:
+
+{% highlight nginx %}
+http {
+ include mime.types;
+ default_type application/octet-stream;
+
+ sendfile on;
+ #tcp_nopush on;
+
+ keepalive_timeout 65;
+
+ # default paths
+ index index.html;
+
+ # disable gzip - https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=773332
+ gzip off;
+
+ # default ssl settings
+ ssl_session_cache shared:SSL:1m;
+ ssl_session_timeout 5m;
+ ssl_ciphers HIGH:!aNULL:!MD5:!AES128:!CAMELLIA128;
+ ssl_protocols TLSv1.2;
+ ssl_prefer_server_ciphers on;
+ ssl_dhparam /usr/local/etc/ssl/dhparam.pem;
+
+ # default logs
+ error_log /var/log/nginx/error.log;
+ access_log /var/log/nginx/acces.log;
+
+ # default server
+ server {
+ listen 80;
+ server_name localhost;
+
+ location / {
+ root /usr/local/www/nginx;
+ index index.html index.htm;
+ }
+
+ error_page 404 /404.html;
+ error_page 500 502 503 504 /50x.html;
+
+ location = /50x.html {
+ root /usr/local/www/nginx-dist;
+ }
+ }
+
+ # include site-specific configs
+ include sites/*.conf;
+}
+{% endhighlight %}
+
+This sets default ssl settings for all server blocks that enable ssl. Note that
+these are settings I use, and are in no way guaranteed to be perfect. I did some
+minor research on these settings to get an acceptable rating on
+[SSL Labs][ssllabs]. However, security is not standing still, and there is a
+decent chance that my settings will become outdated. If you have better settings
+that result in a safer setup, please [contact me][contact].
+
+### Setup HTTP
+Due to the way `certbot` works, you need a functioning web server. Since there
+is no usable cert yet, this means hosting a HTTP version first. The tutorial
+assumes a static HTML website to be hosted, so the configuration is pretty
+easy.
+
+Put the following in `/usr/local/etc/nginx/sites/domain.conf`:
+
+{% highlight nginx %}
+# static HTTP
+server {
+ # listeners
+ listen 80;
+ server_name domain.tld www.domain.tld;
+
+ # site path
+ root /srv/www/domain/_site;
+
+ # / handler
+ location / {
+ try_files $uri $uri/ =404;
+ }
+
+ # logs
+ error_log /var/log/nginx/error.log;
+ access_log /var/log/nginx/access.log;
+}
+{% endhighlight %}
+
+If your site's sources do not reside in `/srv/www/domain/_site`, change the
+path accordingly. This guide will continue using this path for all examples, so
+be sure to modify this where needed. In the same vein, the domain `domain.tld`
+will be used. Modify this to your own domain.
+
+### Start nginx
+Nginx is now configured to host a single site over HTTP. Now is the time to enable
+the nginx service. Execute the following:
+
+{% highlight sh %}
+echo 'nginx_enable="YES"' >> /etc/rc.conf.local
+{% endhighlight %}
+
+This will enable nginx as a system service. On reboots, it will be started
+automatically. You can also start it up without rebooting by running the
+following:
+
+{% highlight sh %}
+service nginx start
+{% endhighlight %}
+
+## Configure Let's Encrypt
+Nginx is now running as your web server on port 80. Now you can request Let's
+Encrypt certificates using `certbot`. You can do so as follows:
+
+{% highlight sh %}
+certbot certonly --webroot -w /srv/www/domain/_site -d domain.tld -d www.domain.tld
+{% endhighlight %}
+
+In case you want to add any sub domains, simply add more `-d sub.domain.tld`
+arguments at the end. If the DNS entries for the domains resolve properly, and
+no unexpected errors occur on the Let's Encrypt side, you should see a message
+congratulating you with your new certs.
+
+If your domains do not resolve correctly, `certbot` will complain about this.
+You will have to resolve your DNS issues before attempting again.
+
+If `certbot` complains about an unexpected error on their side, wait a couple
+minutes and retry the command. It should work, eventually.
+
+Once `certbot` has ran without errors, the required files should be available
+in `/usr/local/etc/letsencrypt/live/domain.tld`.
+
+## Configure nginx with SSL
+The certificate has been issued and base nginx is running. Now is the time to
+re-configure your site on nginx to host the HTTPS version of your site instead.
+Open up `/usr/local/etc/nginx/sites/domain.conf` again, and make the contents
+look like the following:
+
+{% highlight nginx %}
+# redirect HTTPS
+server {
+ # listeners
+ listen 80;
+ server_name domain.tld *.domain.tld;
+
+ # redirects
+ return 301 https://$host$request_uri;
+}
+
+# static HTTPS
+server {
+ # listeners
+ listen 443 ssl;
+ server_name domain.tld www.domain.tld;
+
+ # site path
+ root /srv/www/domain/_site;
+
+ # / handler
+ location / {
+ try_files $uri $uri/ =404;
+ }
+
+ # enable HSTS
+ add_header Strict-Transport-Security "max-age=31536000; includeSubdomains; preload";
+
+ # keys
+ ssl_certificate /usr/local/etc/letsencrypt/live/domain.tld/fullchain.pem;
+ ssl_certificate_key /usr/local/etc/letsencrypt/live/domain.tld/privkey.pem;
+}
+{% endhighlight %}
+
+Do not forget to update all the paths to match your setup!
+
+As a final step, you should generate the dhparam file. This is to avoid the
+issues as described on [Weak DH][weakdh].
+
+{% highlight sh %}
+openssl gendh -out /usr/local/etc/ssl/dhparam.pem 4096
+{% endhighlight %}
+
+Be aware that this step can take a **very** long time. On the test machine I
+used to test this tutorial, with 1 core and 1 GB ram, it took nearly 1 hour to
+generate this file.
+
+### Reload nginx
+The final step is to reload the nginx configuration so it hosts the SSL version
+of your site, and redirects the HTTP version to the HTTPS version. To do this,
+simply run
+
+{% highlight sh %}
+service nginx reload
+{% endhighlight %}
+
+That should be all to get your site working with HTTP redirecting to HTTPS, and
+HTTPS running using a gratis Let's Encrypt certificate.
+
+[contact]: https://www.tyil.work/
+[ssllabs]: https://www.ssllabs.com/ssltest/analyze.html?d=tyil.work&latest
+[weakdh]: https://weakdh.org/
+
diff --git a/_posts/2016-10-31-freebsd-mailserver-part-1-preparations.md b/_posts/2016-10-31-freebsd-mailserver-part-1-preparations.md
new file mode 100644
index 0000000..96ba62d
--- /dev/null
+++ b/_posts/2016-10-31-freebsd-mailserver-part-1-preparations.md
@@ -0,0 +1,141 @@
+---
+title: "FreeBSD email server - Part 1: Preparations"
+date: 2016-10-31 07:57:50
+tags: Tutorial FreeBSD Email Installation
+layout: post
+authors:
+ - ["Patrick Spek", "https://www.tyil.work"]
+---
+
+# FreeBSD email server - Part 1: Preparations
+This tutorial is devised into multiple chapters to make it more manageable, and
+to be able to better explain why certain parts are needed.
+
+The tutorial is created out of experience setting up my own email server. I have
+read through quite a lot of documentation so you do not have to. Nonetheless, I
+would recommend doing so. Email business is a tricky one, with a lot of moving
+parts that have to fit into each other. Knowing how exactly each part works will
+greatly help understanding why they are needed in a proper email server.
+Besides that, it will make your life a lot more enjoyable if you want to tweak
+some things after this tutorial.
+
+To kick off, some preparations should be done before you start on setting up
+your own email server.
+
+## DNS setup
+Some DNS setup is required for mail. Most importantly, the MX records of a
+domain. Be sure you have a domain available, otherwise, get one. There are
+plenty of registrars and the price is pretty low for most domains. If you want
+to look hip, get a `.email` TLD for your email server.
+
+For the DNS records themselves, make sure you have an `A` record pointing to
+the server IP you're going to use. If you have an IPv6 address, set up an
+`AAAA` record as well. Mail uses the `MX` DNS records. Make one with the value
+`10 @`. If you have multiple servers, you can make MX records for these as
+well, but replace the `10` with a higher value each time (`20`, `30`, etc).
+These will be used as fallback, in case the server with pointed to by the `10`
+record is unavailable.
+
+## PostgreSQL
+Next up you will have to install and configure [PostgreSQL][postgres]. Although
+using a database is not required, this tutorial will make use of one. Using a
+database makes administration easier and allows you to add a pretty basic web
+interface for this task.
+
+### Installation
+Since the tutorial uses FreeBSD 11, you can install PostgreSQL easily by running
+
+{% highlight sh %}
+pkg install postgresql96-server
+{% endhighlight %}
+
+### Starting up
+In order to start Postfix, you should enable the system service for it. This
+way, `service` can be used to easily manage it. In addition, it will start
+automatically on boot.
+
+{% highlight sh %}
+echo 'postgresql_enable="YES"' >> /etc/rc.conf.local
+service postgresql start
+{% endhighlight %}
+
+### Database initialization
+Since PostgreSQL is a little different than the more popular [MySQL][mysql], I
+will guide you through setting up the database as well. To begin, switch user
+to `postgres`, which is the default administrative user for PostgreSQL. Then
+simply open up the PostgreSQL CLI.
+
+{% highlight sh %}
+su postgres
+psql
+{% endhighlight %}
+
+Once you are logged in to PostgreSQL, create a new user which will hold
+ownership of the database and make a database for this user.
+
+{% highlight sql %}
+CREATE USER postfix WITH PASSWORD 'incredibly-secret!';
+CREATE DATABASE mail WITH OWNER postfix;
+{% endhighlight %}
+
+Once this is done, create the tables which will hold some of our configuration
+data.
+
+#### domains
+{% highlight sql %}
+CREATE TABLE domains (
+ name VARCHAR(255) NOT NULL,
+ PRIMARY KEY (name)
+);
+{% endhighlight %}
+
+#### users
+{% highlight sql %}
+CREATE TABLE users (
+ local VARCHAR(64) NOT NULL,
+ domain VARCHAR(255) NOT NULL,
+ password VARCHAR(128) NOT NULL,
+ PRIMARY KEY (local, domain),
+ FOREIGN KEY (domain) REFERENCES domains(name) ON DELETE CASCADE
+);
+{% endhighlight %}
+
+#### aliases
+{% highlight sql %}
+CREATE TABLE aliases (
+ domain VARCHAR(255),
+ origin VARCHAR(256),
+ destination VARCHAR(256),
+ PRIMARY KEY (origin, destination),
+ FOREIGN KEY (domain) REFERENCES domains(name) ON DELETE CASCADE
+);
+{% endhighlight %}
+
+## Let's Encrypt
+### Installation
+Installing the [Let's Encrypt][letsencrypt] client is just as straightforward
+as the PostgreSQL database, using `pkg`.
+
+{% highlight sh %}
+pkg install py27-certbot
+{% endhighlight %}
+
+### Getting a certificate
+Requesting a certificate requires your DNS entries to properly resolve. If they
+do not resolve yet, Let's Encrypt will bother you with errors. If they do
+resolve correctly, use `certbot` to get your certificate.
+
+{% highlight sh %}
+certbot certonly --standalone -d domain.tld
+{% endhighlight %}
+
+## Conclusion
+This should be everything required to get started on setting up your own email
+server. Continue to [part 2][part-2] of this series to start setting up
+Postfix.
+
+[freebsd]: https://www.freebsd.org/
+[letsencrypt]: https://letsencrypt.org/
+[mysql]: https://www.mysql.com/
+[part-2]: https://www.tyil.work/tutorials/freebsd-mailserver-part-2-mailing-with-postfix/
+[postgres]: https://www.postgresql.org/
diff --git a/_posts/2016-10-31-freebsd-mailserver-part-2-mailing-with-postfix.md b/_posts/2016-10-31-freebsd-mailserver-part-2-mailing-with-postfix.md
new file mode 100644
index 0000000..17e5b49
--- /dev/null
+++ b/_posts/2016-10-31-freebsd-mailserver-part-2-mailing-with-postfix.md
@@ -0,0 +1,316 @@
+---
+title: "FreeBSD email server - Part 2: Mailing with Postfix"
+date: 2016-10-31 07:57:50
+tags: Tutorial FreeBSD Email Installation
+layout: post
+authors:
+ - ["Patrick Spek", "https://www.tyil.work"]
+---
+
+# FreeBSD email server - Part 2: Mailing with Postfix
+Welcome to the second part of my FreeBSD email server series. In this series, I
+will guide you through setting up your own email service. Be sure to done the
+preparations from [part 1][part-1] of this series.
+
+This part will guide you through setting up email service on your machine using
+[Postfix][postfix]. Basic installation is pretty straightforward, but there is
+a lot to configure. If you are not sure what some configuration options do,
+please read up on them. There is a lot to do wrong with a mail server, and
+doing things wrong will likely get you on a blacklist which will make other
+servers stop processing the mail you are trying to send out.
+
+Setting up Postfix is one of the harder parts of configuring a mail server. If
+you have questions after reading the full guide, please find me on IRC. You can
+find details on how to do so on [my homepage][home].
+
+## Installing Postfix
+Installation procedures on FreeBSD are pretty straightforward. Unlike `certbot`
+from the previous part, we will need to compile Postfix from source in order to
+use PostgreSQL as a database back-end. Thanks to FreeBSD's
+[ports][freebsd-ports], this is not difficult either. If this is your first
+port to compile, you probably need to get the ports tree first. You can
+download and extract this using the following command.
+
+{% highlight sh %}
+portsnap fetch extract
+{% endhighlight %}
+
+Once that has finished running, go into the directory containing the build
+instructions for Postfix, and start the installation process.
+
+{% highlight sh %}
+cd /usr/ports/mail/postfix
+make configure install
+{% endhighlight %}
+
+This will open a pop up with a number of options you can enable or disable. The
+enabled defaults are fine, but you will have to enable the `PGSQL` option. This
+will allow you to use the configuration tables created in part 1.
+
+## Enabling Postfix
+Enable the Postfix service for rcinit. This allows you to use `service postfix
+start` once configuration is done, and will auto start the service on system
+boot. In addition, the default mailer on FreeBSD, [sendmail][sendmail] should
+be disabled so nothing is in Postfix's way when trying to deal with processing
+email traffic.
+
+{% highlight sh %}
+# disable the default sendmail system
+echo 'daily_clean_hoststat_enable="NO"' >> /etc/periodic.conf.local
+echo 'daily_status_mail_rejects_enable="NO"' >> /etc/periodic.conf.local
+echo 'daily_status_include_submit_mailq="NO"' >> /etc/periodic.conf.local
+echo 'daily_submit_queuerun="NO"' >> /etc/periodic.conf.local
+echo 'sendmail_enable="NONE"' >> /etc/rc.conf.local
+
+# enable postfix
+echo 'postfix_enable="YES"' >> /etc/rc.conf.local
+{% endhighlight %}
+
+## Configuring Postfix
+There is a ton to configure for Postfix. This configuration happens in two
+files, `main.cf` and `master.cf`. Additionally, as some data is in the
+PostgreSQL database, three files with information on how to query for this
+information are needed. All of these files are in `/usr/local/etc/postfix`.
+
+The guide has a comment line for most blocks. It is advised that **if** you
+decide to just copy and paste the contents, you copy that along so you have
+some sort of indication of what is where. This could help you out if you ever
+need to change anything later on.
+
+### main.cf
+#### Compatibility
+The configuration file starts off by setting the compatibility level. If
+postfix updates the configuration scheme and deprecates certain options, you
+will be notified of this in the logs.
+
+{% highlight ini %}
+# compatibility
+compatibility_level = 2
+{% endhighlight %}
+
+#### Directory paths
+These options indicate where Postfix will look and keep certain files required
+for correct operation.
+
+{% highlight ini %}
+# directory paths
+queue_directory = /var/spool/postfix
+command_directory = /usr/local/sbin
+daemon_directory = /usr/local/libexec/postfix
+data_directory = /var/db/postfix
+{% endhighlight %}
+
+#### Domain configuration
+The domain configuration instruct the server of the domain(s) it should serve
+for. Use your FQDN without sub domains for `mydomain`. You can use a sub domain
+for `myhostname`, but you are not required to. The most common setting is
+using a `mail` sub domain for all mail related activities, which would
+result in something like this.
+
+{% highlight ini %}
+# domain configuration
+myhostname = mail.domain.tld
+mydomain = domain.tld
+myorigin = $mydomain
+{% endhighlight %}
+
+#### Listening directives
+All internet devices it should listen on, and all domains this server should
+consider itself the endpoint for, should be listed here. The defaults in the
+example block are good enough, as we put some of our data in the PostgreSQL
+database instead.
+
+{% highlight ini %}
+# listening directives
+inet_interfaces = all
+mydestination = $myhostname, localhost.$mydomain, localhost
+{% endhighlight %}
+
+#### Reject unknown recipients
+How to deal with messages sent to an email address whose domain points to your
+server's address, but have no actual mailbox. A code of `550` means to inform
+the remote server that delivery is not possible and will not be possible. This
+should stop the remote server from trying it again.
+
+{% highlight ini %}
+# reject unknown recipients
+unknown_local_recipient_reject_code = 550
+{% endhighlight %}
+
+#### Trust
+{% highlight ini %}
+# trust
+mynetworks_style = host
+{% endhighlight %}
+
+#### Address extensions
+This block is optional. It allows you to use email address extensions. These
+are addresses with an additional character in them that will drop the email in
+the non extended address' mailbox, but allows you to quickly filter on them as
+the sent-to address contains the extension.
+
+{% highlight ini %}
+# address extensions
+recipient_delimiter = +
+{% endhighlight %}
+
+#### Virtual domain directives
+This part is where things get important. Virtual domains allow you to handle
+mail for a large number of domains that are different from the actual server's
+domain. This is where the database configuration comes in to play. It is
+important to note the `static:125` values. The `125` should map to the `UID` of
+the `postfix` user account on your system.
+
+{% highlight ini %}
+# virtual domain directives
+virtual_mailbox_base = /srv/mail
+virtual_mailbox_domains = pgsql:/usr/local/etc/postfix/pgsql-virtual-domains.cf
+virtual_mailbox_maps = pgsql:/usr/local/etc/postfix/pgsql-virtual-users.cf
+virtual_alias_maps = pgsql:/usr/local/etc/postfix/pgsql-virtual-aliases.cf
+virtual_uid_maps = static:125
+virtual_gid_maps = static:125
+virtual_transport = lmtp:unix:private/dovecot-lmtp
+{% endhighlight %}
+
+#### TLS setup
+The TLS setup configures your server to use secure connections. The keys used
+here have been generated in the previous part of this series.
+
+{% highlight ini %}
+# TLS setup
+smtpd_tls_cert_file = /usr/local/etc/letsencrypt/live/domain.tld/fullchain.pem
+smtpd_tls_key_file = /usr/local/etc/letsencrypt/live/domain.tld/privkey.pem
+smtpd_use_tls = yes
+smtpd_tls_auth_only = yes
+{% endhighlight %}
+
+#### SASL setup
+SASL deals with the authentication of the users to your email server.
+
+{% highlight ini %}
+# SASL setup
+smtpd_sasl_type = dovecot
+smtpd_sasl_path = private/auth
+smtpd_sasl_auth_enable = yes
+smtpd_recipient_restrictions =
+ permit_sasl_authenticated,
+ permit_mynetworks,
+ reject_unauth_destination
+smtpd_relay_restrictions =
+ permit_sasl_authenticated,
+ permit_mynetworks,
+ reject_unauth_destination
+{% endhighlight %}
+
+#### Debugging
+The debugging options are generally useful in case things break. If you have
+little traffic, you could leave them on forever in case you want to debug
+something later on. Once your server is working as intended, you should turn
+these options off. The postfix logs get pretty big in a short amount of time.
+
+{% highlight ini %}
+# debugging
+debug_peer_level = 2
+debugger_command =
+ PATH=/bin:/usr/bin:/usr/local/bin:/usr/X11R6/binary
+ ddd $daemon_directory/$process_name $process_id & sleep 5
+{% endhighlight %}
+
+#### Installation time defaults
+These options should not be touched, but are very important to have for your
+server.
+
+{% highlight ini %}
+# install-time defaults
+sendmail_path = /usr/local/sbin/sendmail
+newaliases_path = /usr/local/bin/newaliases
+mailq_path = /usr/local/bin/mailq
+setgid_group = maildrop
+html_directory = /usr/local/share/doc/postfix
+manpage_directory = /usr/local/man
+sample_directory = /usr/local/etc/postfix
+readme_directory = /usr/local/share/doc/postfix
+inet_protocols = ipv4
+meta_directory = /usr/local/libexec/postfix
+shlib_directory = /usr/local/lib/postfix
+{% endhighlight %}
+
+### master.cf
+For the `master.cf` file, you can use the following configuration block.
+
+{% highlight cfg %}
+submission inet n - n - - smtpd
+ -o syslog_name=postfix/submission
+ -o smtpd_tls_security_level=encrypt
+ -o smtpd_sasl_auth_enable=yes
+ -o smtpd_reject_unlisted_recipient=no
+ -o smtpd_recipient_restrictions=permit_sasl_authenticated,reject
+ -o milter_macro_daemon_name=ORIGINATING
+pickup unix n - n 60 1 pickup
+cleanup unix n - n - 0 cleanup
+qmgr unix n - n 300 1 qmgr
+tlsmgr unix - - n 1000? 1 tlsmgr
+rewrite unix - - n - - trivial-rewrite
+bounce unix - - n - 0 bounce
+defer unix - - n - 0 bounce
+trace unix - - n - 0 bounce
+verify unix - - n - 1 verify
+flush unix n - n 1000? 0 flush
+proxymap unix - - n - - proxymap
+proxywrite unix - - n - 1 proxymap
+smtp unix - - n - - smtp
+relay unix - - n - - smtp
+showq unix n - n - - showq
+error unix - - n - - error
+retry unix - - n - - error
+discard unix - - n - - discard
+local unix - n n - - local
+virtual unix - n n - - virtual
+lmtp unix - - n - - lmtp
+anvil unix - - n - 1 anvil
+scache unix - - n - 1 scache
+{% endhighlight %}
+
+### SQL query files
+The following three configuration files deal with the SQL query files to make
+Postfix able of getting some of its configuration from a database. You
+obviously have to change the first 4 directives to match your database
+authentication credentials.
+
+#### pgsql-virtual-domains.cf
+{% highlight ini %}
+user = postgres
+password = incredibly-secret!
+hosts = 127.1
+dbname = mail
+query = SELECT 1 FROM domains WHERE name='%s';
+{% endhighlight %}
+
+#### pgsql-virtual-users.cf
+{% highlight ini %}
+user = postgres
+password = incredibly-secret!
+hosts = 127.1
+dbname = mail
+query = SELECT 1 FROM users WHERE local='%u' AND domain='%d';
+{% endhighlight %}
+
+#### pgsql-virtual-aliases.cf
+{% highlight ini %}
+user = postfix
+password = nope
+hosts = 127.1
+dbname = mail
+query = SELECT destination FROM aliases WHERE origin='%s';
+{% endhighlight %}
+
+## Conclusion
+This should be enough Postfix configuration, for now. Next part involves
+Dovecot, which will enable IMAP. It will also provide the SASL mechanism
+defined in this part.
+
+[freebsd-ports]: https://www.freebsd.org/ports/
+[home]: https://www.tyil.work/
+[part-1]: https://www.tyil.work/tutorials/freebsd-mailserver-part-1-preparations/
+[postfix]: http://www.postfix.org/
+[sendmail]: http://www.sendmail.com/sm/open_source/
diff --git a/_posts/2016-10-31-freebsd-mailserver-part-3-dovecot-imap-sasl.md b/_posts/2016-10-31-freebsd-mailserver-part-3-dovecot-imap-sasl.md
new file mode 100644
index 0000000..4fa4800
--- /dev/null
+++ b/_posts/2016-10-31-freebsd-mailserver-part-3-dovecot-imap-sasl.md
@@ -0,0 +1,227 @@
+---
+title: "FreeBSD email server - Part 3: Dovecot, IMAP and SASL"
+date: 2016-10-31 07:57:50
+tags: Tutorial FreeBSD Email Installation
+layout: post
+authors:
+ - ["Patrick Spek", "https://www.tyil.work"]
+---
+
+# FreeBSD email server - Part 3: IMAP and SASL with Dovecot
+Welcome to the second part of my FreeBSD email server series. In this series, I
+will guide you through setting up your own email service. Be sure to read the
+previous parts before trying to continue on this part in case you have not done
+so yet.
+
+This part will guide you through setting up [Dovecot][dovecot]. This service
+will deal with the SASL authentication to your email server and making your email
+boxes accessible via IMAP. While this guide does not cover POP3 functionality,
+Dovecot can handle this as well.
+
+Just like the Postfix setup, Dovecot has quite a few configuration options to
+set before it will work as expected in this setup. If you have questions after
+reading the full guide, please find me on IRC. You can find details on how to
+do so on [my homepage][home].
+
+## Installing Dovecot
+Dovecot will also be installed from the ports tree from FreeBSD. As this guide
+assumes you are working through them in order, explanation of acquiring the
+ports tree will be omitted here.
+
+You can start the installation procedure with the following commands.
+
+{% highlight sh %}
+cd /usr/ports/mail/dovecot2
+make configure install
+{% endhighlight %}
+
+Again, like with the Postfix installation, leave the default options on and add
+the `PGSQL` option so Dovecot can use PostgreSQL as the database back-end.
+
+## Enabling Dovecot
+Enable the Dovecot service for rcinit.
+
+{% highlight sh %}
+echo 'dovecot_enable="YES"' >> /etc/rc.conf.local
+{% endhighlight %}
+
+## Configuring Dovecot
+To start of with Dovecot configuration, copy over the sample files first.
+
+{% highlight sh %}
+cp -r /usr/local/etc/dovecot/example-config/* /usr/local/etc/dovecot/.
+{% endhighlight %}
+
+Now you can start editing a number of pesky files. The file names of the
+headings all appear relative to `/usr/local/etc/dovecot`.
+
+### dovecot.conf
+Here you only have to set which protocols you want to enable. Set them as
+follows.
+
+{% highlight ini %}
+protocols = imap lmtp
+{% endhighlight %}
+
+### conf.d/10-master.cf
+The `master.cf` configuration file indicates which sockets Dovecot should use
+and provide and as which user its processes should be ran. Keep the defaults as
+they are, with the exception of the following two blocks.
+
+#### service imap-login
+This will enable imaps, IMAP over SSL, and disable plain IMAP.
+
+{% highlight ini %}
+service-imap-login {
+ inet_listener imap {
+ port = 0
+ }
+
+ inet_listener imaps {
+ port = 993
+ ssl = yes
+ }
+}
+{% endhighlight %}
+
+#### services
+This will instruct Dovecot to provide a service for authentication and `lmtp`
+the **local mail transport protocol**. This is required to deliver the email
+files into the correct email box location in the file system.
+
+{% highlight ini %}
+service auth {
+ unix_listener auth-userdb {
+ mode = 0600
+ user = postfix
+ group = postfix
+ }
+
+ unix_listener /var/spool/postfix/private/auth {
+ mode = 0666
+ user = postfix
+ group = postfix
+ }
+
+ user = dovecot
+}
+
+service lmtp {
+ unix_listener /var/spool/postfix/private/dovecot-lmtp {
+ mode = 0600
+ user = postfix
+ group = postfix
+ }
+}
+
+service auth-worker {
+ user = postfix
+}
+{% endhighlight %}
+
+### conf.d/10-ssl.conf
+Here you have to enable SSL and provide the correct paths to your SSL key in
+order for Dovecot to work with them.
+
+{% highlight ini %}
+ssl = required
+ssl_cert = < /usr/local/etc/letsencrypt/live/domain.tld/fullchain.pem
+ssl_key = < /usr/local/etc/letsencrypt/live/domain.tld/privkey.pem
+{% endhighlight %}
+
+### conf.d/10-mail.conf
+The mail.conf location instructs Dovecot which location to appoint for storing
+the email files. `%d` expands to the domain name, while `%n` expands to the
+local part of the email address.
+
+{% highlight ini %}
+mail_home = /srv/mail/%d/%n
+mail_location = maildir:~/Maildir
+{% endhighlight %}
+
+Make sure the location set by `mail_home` exists and is owned by `postfix`!
+
+{% highlight sh %}
+mkdir -p /srv/mail
+chown postfix:postfix /srv/mail
+{% endhighlight %}
+
+### conf.d/10-auth.conf
+This file deals with the authentication provided by Dovecot. Mostly, which
+mechanisms should be supported and what mechanism should be used to get the
+actual credentials to check against. Make sure the following options are set
+as given
+
+{% highlight ini %}
+disable_plaintext_auth = yes
+auth_mechanisms = plain
+{% endhighlight %}
+
+Also, make sure `!include auth-system.conf.ext` is commented **out**. It is not
+commented out by default, so you will have to do this manually. In addition,
+you have to uncomment `!include auth-sql.conf.ext`.
+
+### conf.d/auth-sql.conf.ext
+This is the file included from `10-auth.conf`. It instructs Dovecot to use SQL as
+the driver for the password and user back-ends.
+
+{% highlight ini %}
+passdb {
+ driver = sql
+ args = /usr/local/etc/dovecot/dovecot-sql-conf.ext
+}
+
+userdb {
+ driver = prefetch
+}
+
+userdb {
+ driver = sql
+ args = /usr/local/etc/dovecot/dovecot-sql-conf.ext
+}
+{% endhighlight %}
+
+### dovecot-sql.conf.ext
+The final configuration file entails the queries which should be used to get the
+required information about the users. Make sure to update the `password` and possibly
+other parameters used to connect to the database. You may have to update the `125` as
+well, as this has to be identical to the `UID` of `postfix`.
+
+As a side note, if you are following this tutorial on a machine that does
+**not** support Blowfish in the default glib, which is nearly every GNU+Linux
+setup, you **can not** use `BLF-CRYPT` as the `default_pass_scheme`. You will
+have to settle for the `SHA-512` scheme instead.
+
+{% highlight ini %}
+driver = pgsql
+connect = host=127.1 dbname=mail user=postfix password=incredibly-secret!
+default_pass_scheme = BLF-CRYPT
+password_query = \
+ SELECT \
+ local AS user, \
+ password, \
+ '/srv/mail/%d/%n' AS userdb_home, \
+ 125 AS userdb_uid, \
+ 125 AS userdb_gid \
+ FROM users \
+ WHERE local='%n' AND domain='%d';
+
+user_query = \
+ SELECT \
+ '/srv/mail/%d/%n' AS home \
+ 125 AS uid, \
+ 125 AS gid \
+ FROM users \
+ WHERE local='%n' AND domain='%d';
+{% endhighlight %}
+
+## Conclusion
+After this part, you should be left with a functioning email server that
+provides IMAP over a secure connection. While this is great on itself, for
+actual use in the wild, you should setup some additional services. Therefore,
+in the next part, we will deal with practices that "authenticate" your emails
+as legit messages. Be sure to read up on it!
+
+[dovecot]: http://dovecot.org/
+[home]: https://www.tyil.work/
+
diff --git a/_posts/2016-10-31-freebsd-mailserver-part-4-message-authentication.md b/_posts/2016-10-31-freebsd-mailserver-part-4-message-authentication.md
new file mode 100644
index 0000000..d1c8631
--- /dev/null
+++ b/_posts/2016-10-31-freebsd-mailserver-part-4-message-authentication.md
@@ -0,0 +1,159 @@
+---
+title: "FreeBSD email server - Part 4: Message authentication"
+date: 2016-10-31 20:00:38
+tags: Tutorial FreeBSD Email Installation
+layout: post
+authors:
+ - ["Patrick Spek", "https://www.tyil.work"]
+---
+
+# FreeBSD email server - Part 4: Message authentication
+Welcome to another part in the FreeBSD email server series. This time, we are
+going to setup some mechanisms to deal with message authentication. This
+practice will make other email providers accept your email messages and deliver
+them properly in the inbox of the receiving user, instead of their spam box.
+
+We will do so using three of the most common practices: [SPF][spf],
+[DKIM][dkim] and [DMARC][dmarc].
+
+## DKIM
+### Installation
+The tools for DKIM are easily installed using `pkg`.
+
+{% highlight sh %}
+pkg install opendkim
+{% endhighlight %}
+
+### Configuration
+Write the following configuration into `/usr/local/etc/mail/opendkim.conf`.
+
+{% highlight conf %}
+# logging
+Syslog yes
+
+# permissions
+UserID postfix
+UMask 007
+
+# general settings
+AutoRestart yes
+Background yes
+Canonicalization relaxed/relaxed
+DNSTimeout 5
+Mode sv
+SignatureAlgorithm rsa-sha256
+SubDomains no
+X-Header yes
+OversignHeaders From
+
+# tables
+KeyTable /usr/local/etc/opendkim/key.table
+SigningTable /usr/local/etc/opendkim/signing.table
+
+# socket
+Socket inet:8891@localhost
+
+# domains
+Domain domain.tld.privkey
+KeyFile /usr/local/etc/opendkim/domain.tld
+Selector mail
+{% endhighlight %}
+
+#### Postfix
+Postfix needs to be instructed to sign the messages with a DKIM header using
+the opendkim service. You can do so by inserting the following configuration
+block somewhere around the end of `/usr/local/etc/postfix/main.cf`.
+
+{% highlight ini %}
+# milters
+milter_protocol = 2
+milter_default_action = reject
+smtpd_milters =
+ inet:localhost:8891
+ non_smtpd_milters =
+ inet:localhost:8891
+{% endhighlight %}
+
+#### System service
+OpenDKIM runs as a system service. As such, you will have to enable this
+service in rcinit. This is a simple step, achieved with the given command.
+
+{% highlight sh %}
+echo 'milteropendkim_enable="YES"' >> /etc/rc.conf.local
+{% endhighlight %}
+
+Do not forget to actually start the service when you are done with the
+tutorial!
+
+### Creating and using keys
+In order to use DKIM, you will need to generate some keys to sign the messages
+with. You cannot use your Let's Encrypt SSL keys for this. First, create a
+directory to house your domain's keys.
+
+{% highlight sh %}
+mkdir -p /usr/local/etc/opendkim/keys/domain.tld
+chown -R postfix:wheel $_
+{% endhighlight %}
+
+Next up, generate your first key.
+
+{% highlight sh %}
+opendkim-genkey -D /usr/local/etc/opendkim/keys -b 4096 -r -s $(date +%Y%m%d) -d domain.tld
+{% endhighlight %}
+
+I tend to use the current date for the key names so I can easily sort them by
+the most recent one.
+
+Afterwards, you will have to add a line to two separate files to instruct DKIM
+to use this key for a certain domain when signing mail. These are fairly
+straightforward and can be done using a simple `echo` as well.
+
+{% highlight sh %}
+echo '*@domain.tld domain.tld' >> /usr/local/etc/opendkim/signing.table
+echo "domain.tld domain.tld:$(date +%Y%m%d):/usr/local/etc/opendkim/keys/domain.tld/$(date +%Y%m%d).private" >> /usr/local/etc/opendkim/key.table
+{% endhighlight %}
+
+### Adding the DNS records
+You may have already noticed that `opendkim-genkey` also creates a `.txt` file
+in addition to the private key. This text file contains the DNS record value
+you need to add for your domain's DNS. Add the record to your DNS server, and
+simply wait for it to propagate.
+
+## SPF
+SPF is simply a DNS record that shows which IPs are allowed to email for that
+domain.
+
+### Adding the DNS records
+A simple example for an SPF record is the following. It allows mail to be sent
+in the domain's name from any IP listed in the MX records.
+
+{% highlight plain %}
+v=spf1 mx -all
+{% endhighlight %}
+
+## DMARC
+DMARC is, like SPF, a DNS record. It tells how to deal with messages coming
+from the server and where to report abuse of your server. Some of the larger
+email providers send out reports to the address given in the DMARC record so
+you can figure out whether someone is spamming from your servers, for example.
+
+### Adding the DNS records
+A simple DMARC policy to get started with is to quarantine all emails that fail
+authentication. This means the emails will go into the receiving user's spam
+box. In addition, abuse reports will be sent to the address defined in the
+`rua`.
+
+{% highlight plain %}
+v=DMARC1; p=quarantine; rua=mailto:abuse@domain.tld
+{% endhighlight %}
+
+## Conclusion
+These few simple measures will make receiving servers trust the authenticity of
+the mails you send. In effect, your messages will be much less likely to be
+marked as spam. However, you are a target of spam as well. How you can deal
+with that, will be available in the next part of this series.
+
+[dkim]: http://www.dkim.org/
+[dmarc]: http://dmarc.org/
+[spf]: https://en.wikipedia.org/wiki/Sender_Policy_Framework
+
diff --git a/_posts/2016-10-31-freebsd-mailserver-part-5-filtering-mail.md b/_posts/2016-10-31-freebsd-mailserver-part-5-filtering-mail.md
new file mode 100644
index 0000000..909449e
--- /dev/null
+++ b/_posts/2016-10-31-freebsd-mailserver-part-5-filtering-mail.md
@@ -0,0 +1,132 @@
+---
+title: "FreeBSD email server - Part 5: Filtering mail"
+date: 2016-10-31 20:02:19
+tags: Tutorial FreeBSD Email Installation
+layout: post
+authors:
+ - ["Patrick Spek", "https://www.tyil.work"]
+---
+
+# FreeBSD email server - Part 5: Filtering mail
+Being able to send mail and not be flagged as spam is pretty awesome on itself.
+But you also get hit by a lot of spam. The more you give out your email address
+and domain name, the more spam you will receive over time. I welcome you to
+another part of the FreeBSD email server series. In this part, we will set up
+email filtering at the server side.
+
+We will accomplish this with a couple packages, [SpamAssassin][spamassassin]
+and [Pigeonhole][pigeonhole]. The former deals with scanning the emails to
+deduce whether it is spam or not. The latter filters messages. We will use this
+filtering to drop emails marked as spam by SpamAssassin into the Junk folder,
+instead of the inbox.
+
+## Installing the packages
+Both packages are available through FreeBSD's `pkg` utility. Install them as
+such.
+
+{% highlight sh %}
+pkg install dovecot-pigeonhole spamassassin
+{% endhighlight %}
+
+## SpamAssassin
+### Enabling the service
+Like most services, you have to enable them as well. Pigeonhole is an extension
+to Dovecot, and Dovecot will handle this one. SpamAssassin requires you to
+configure the service as well. You can enable it and set sane configuration to
+it with the following two commands.
+
+{% highlight sh %}
+echo 'spamd_enable="YES"' >> /etc/rc.conf.local
+echo 'spamd_flags="-u spamd -H /srv/mail"' >> /etc/rc.conf.local
+{% endhighlight %}
+
+### Acquiring default spam rules
+SpamAssassin has to "learn" what counts as *spam* and what counts as *ham*. To
+fetch these rules, you should execute the updates for SpamAssassin with the
+following command.
+
+{% highlight sh %}
+sa-update
+{% endhighlight %}
+
+You most likely want to run this once every while, so it is advised to setup a
+[cronjob][cronjob] for this purpose.
+
+## Postfix
+In order to have mails checked by SpamAssassin, Postfix must be instructed to
+pass all email through to SpamAssassin, which will hand them back with a
+`X-Spam-Flag` header attached to them. This header can be used by other
+applications to treat it as spam.
+
+### master.cf
+There's not much to include to the already existing Postfix configuration to
+enable SpamAssassin to do its job. Just open `/usr/local/etc/postfix/master.cf`
+and append the block given below.
+
+{% highlight ini %}
+spamassassin unix - n n - - pipe
+ user=spamd argv=/usr/local/bin/spamc
+ -f -e /usr/sbin/sendmail -oi -f ${sender} ${recipient}
+{% endhighlight %}
+
+## Pigeonhole
+Pigeonhole is an implementation of Sieve for Dovecot. It deals with filtering
+messages on the server side using a set of rules, defined in a file usually
+named `sieve`. This file is generally saved at
+`/srv/mail/domain.tld/user/sieve`. A default file to filter spam out is the
+following example.
+
+{% highlight sieve %}
+require [
+ "fileinto",
+ "mailbox"
+];
+
+if header :contains "X-Spam-Flag" "YES" {
+ fileinto :create "Junk";
+ stop;
+}
+{% endhighlight %}
+
+This looks for the `X-Spam-Flag` header, which is added by SpamAssassin. If it
+is set to `YES`, this indicates SpamAssassin thinks the message is spam. As
+such, sieve is instructed to filter this message into the folder `Junk`, and to
+create this folder if it does not exist yet. The `stop;` makes sieve stop
+trying to process this message further based on later rules.
+
+## Dovecot
+Dovecot needs some additional configuration to work with Pigeonhole. Modify the
+following files and add the contents described.
+
+### conf.d/20-lmtp.conf
+This will enable Pigeonhole in Dovecot.
+
+{% highlight ini %}
+protocol lmtp {
+ mail_plugins = $mail_plugins sieve
+}
+{% endhighlight %}
+
+### conf.d/90-plugin.conf
+This configures Pigeonhole to look for a file named `sieve` in the mailbox
+homedir, and execute that when delivering mail.
+
+{% highlight ini %}
+plugin {
+ sieve = /srv/mail/%d/%n/sieve
+}
+{% endhighlight %}
+
+## Conclusion
+Spam is a pain, especially if you get a lot of it. The configuration added in
+this part of the FreeBSD email server series should get rid of most of it. This
+also concludes the series. If you have any questions or suggestions, please
+contact me via any of the methods detailed on [my home page][home].
+
+Thanks for reading along, and enjoy your very own email server!
+
+[cronjob]: #
+[home]: https://www.tyil.work/
+[pigeonhole]: http://pigeonhole.dovecot.org/
+[spamassassin]: https://spamassassin.apache.org/
+
diff --git a/_posts/2016-11-24-freebsd-mailserver-calendars-and-contacts.md b/_posts/2016-11-24-freebsd-mailserver-calendars-and-contacts.md
new file mode 100644
index 0000000..b29a123
--- /dev/null
+++ b/_posts/2016-11-24-freebsd-mailserver-calendars-and-contacts.md
@@ -0,0 +1,140 @@
+---
+title: "FreeBSD email server - Part +: Calendars and contacts"
+date: 2016-11-24 08:26:09
+tags: Tutorial FreeBSD Email CalDAV CardDAV Installation
+layout: post
+authors:
+ - ["Patrick Spek", "http://tyil.work"]
+---
+
+# FreeBSD email server - Part +: Calendars and contacts
+This guide is an addition to the [FreeBSD email server series][tutorial-email].
+It is not required for your email server to operate properly, but it is often
+considered a very important feature for those who want to switch from a third
+party email provider to their own solution. It does build upon the completed
+series, so be sure to work through that before starting on this.
+
+## Install required packages
+{% highlight sh %}
+pkg install py27-radicale
+{% endhighlight %}
+
+## Configure Radicale
+### /usr/local/etc/radicale/config
+Open up the `/usr/local/etc/radicale/config` file, and update each `[block]`.
+
+#### [server]
+The server is binding to `localhost` only. This way it is not accessible on
+`:5232` from outside the server. Outside access will be provided through an
+nginx reverse proxy instead.
+
+{% highlight ini %}
+hosts = 127.1:5232
+daemon = True
+
+dns_lookup = True
+
+base_prefix = /
+can_skip_base_prefix = False
+
+realm = Radicale - Password required
+{% endhighlight %}
+
+#### [encoding]
+{% highlight ini %}
+request = utf-8
+stock = utf-8
+{% endhighlight %}
+
+#### [auth]
+{% highlight ini %}
+type = IMAP
+
+imap_hostname = localhost
+imap_port = 143
+imap_ssl = False
+{% endhighlight %}
+
+#### [storage]
+{% highlight ini %}
+type = filesystem
+filesystem_folder = /usr/local/share/radicale
+{% endhighlight %}
+
+#### [logging]
+{% highlight ini %}
+config = /usr/local/etc/radicale/logging
+{% endhighlight %}
+
+### /usr/local/etc/radicale/logging
+This file is fine on the defaults in FreeBSD 11. This saves you from
+configuring a little bit.
+
+## Configure Dovecot
+### Enable imap
+This option was disabled in the [IMAP server tutorial][tutorial-email],
+however, if we want to auth using the same credentials as the mailserver, this
+option is needed again. Bind it to `localhost`, so it can only be used
+internally. In `/usr/local/etc/dovecont/conf.d/10-master.conf`, enable the
+`imap` port again:
+
+{% highlight conf %}
+...
+service imap-login {
+ inet_listener imap {
+ address = 127.1
+ port = 143
+ }
+ ...
+}
+...
+{% endhighlight %}
+
+## Configure nginx
+To make using the service easier, you can setup [nginx][nginx] to act as a
+reverse proxy. If you followed the [webserver tutorial][tutorial-webserver],
+you already have the basics for this set up. I do recommend you check this out,
+as I will only explain how to configure a virtual host to deal with the reverse
+proxy here.
+
+### Setup a reverse proxy
+Assuming you have taken the crash-course in setting up the nginx webserver, you
+can attain a reverse proxy using the following config block. Note that this block
+only does HTTPS, as I use HTTP only to redirect to HTTPS.
+
+{% highlight nginx %}
+# static HTTPS
+server {
+ # listeners
+ listen 443 ssl;
+ server_name radicale.domain.tld;
+
+ # enable HSTS
+ add_header Strict-Transport-Security "max-age=31536000; includeSubdomains; preload";
+
+ # keys
+ ssl_certificate /usr/local/etc/letsencrypt/live/domain.tld/fullchain.pem;
+ ssl_certificate_key /usr/local/etc/letsencrypt/live/domain.tld/privkey.pem;
+
+ # / handler
+ location / {
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_pass http://127.1:5232;
+ }
+}
+{% endhighlight %}
+
+## Enable the service at startup
+{% highlight sh %}
+echo 'radicale_enable="YES"' >> /etc/rc.conf.local
+{% endhighlight %}
+
+## Start the server
+{% highlight sh %}
+service radicale start
+{% endhighlight %}
+
+[nginx]: https://www.nginx.com/
+[tutorial-email]: https://www.tyil.work/tutorials/freebsd-mailserver-part-1-preparations/
+[tutorial-webserver]: https://www.tyil.work/tutorials/setup-nginx-with-lets-encrypt-ssl/
diff --git a/_posts/2017-09-14-how-to-git.md b/_posts/2017-09-14-how-to-git.md
new file mode 100644
index 0000000..7c4f21f
--- /dev/null
+++ b/_posts/2017-09-14-how-to-git.md
@@ -0,0 +1,185 @@
+---
+title: "How to: git"
+date: 2017-09-14 19:46:34
+tags: Tutorial Git
+layout: post
+authors:
+ - ["Patrick Spek", "http://tyil.work"]
+---
+
+# How to: git
+This guide will explain how to use `git` more efficiently, and why you should
+use it as such.
+
+## Forking
+When working in a team, there's generally a remote server which is used to sync
+your repositories. There are gratis services, such as [GitHub][github],
+[Gitlab][gitlab], [GOGS][gogs], and others. These services also allow you to
+*fork* a repository. This basically makes a copy of the entire repository for
+your own use. In it, you have full control over the branches, tags, merge
+process and everything else you want to do with it.
+
+One the main reasons to do this is so you do not have to clutter up the main
+repository with a ton of branches (these are explained later in the post). If
+there are two people working in the same branch, it can help reduce conflicts,
+as each developer is working on the branch in his own fork.
+
+As such, **always** use a fork. If the service does not have a fancy button for
+you to click, you can still fork manually. Simply clone their repository as
+usual, set a new remote and push it there:
+
+{% highlight sh %}
+git clone git@domain.tld:them/repo.git
+cd repo
+git remote rename origin upstream
+git remote add origin git@domain.tld:you/repo.git
+git push origin master
+{% endhighlight %}
+
+The default naming convention uses `upstream` for the base of your fork, and
+`origin` for your remote version of the repository. If a merge request is
+accepted on the original repo, you can apply it to your fork using
+
+{% highlight sh %}
+git pull upstream master
+{% endhighlight %}
+
+## Branching
+Branching is the art of using separate branches to introduce new code into your
+`master` branch. Every git repository starts with a `master` branch by default.
+This is the *main* branch of your repository.
+
+Every time you want to add new code to your project, make a branch for the
+feature or issue you are trying to solve. This way, you can commit freely
+without having to worry about having untested or possibly broken code in the
+`master` branch. If something were to come up with a higher priority, such as a
+critical bug, you can simply create a new branch off of `master`, fix it and
+merge that back into `master`, without having to worry about that other feature
+you were working on, which is not in a releasable state yet. Once the fix is
+applied, you go back to your feature branch on continue working on the cool new
+stuff you wanted to implement. Now, the bug is fixed, and no code has been
+released that should not have been released. If that's not convincing enough,
+try some of the [Stack Overflow posts][so-git-branch] on this very topic.
+
+Branches can be made at your leisure, with next to no overhead on your project.
+Do not be scared to play around with your code in a new branch to test
+something out. You can also delete branches as quickly as you made them if you
+are not satisfied with the result.
+
+Creating branches is done using `git checkout -b new-branch`. If you need to
+switch to another existing branch to change something, use
+`git checkout other-branch`. Deleting a branch can be done using
+`git branch -D old-branch`. You can get a list of all branches in the
+repository with `git branch`. The current branch is marked with an \*.
+
+If you start a new branch to implement a feature, be sure to always branch off
+of `master`, unless you have a very compelling reason not to do so. If you are
+not sure what reasons would validate branching off of another branch, you
+should just branch off of `master`. If you branch off of another branch, you
+will have the commit history of the other branch. This often includes commits
+not accepted into master yet, which might result into commits getting into
+master which should not be there (yet), or annoying merge conflicts later on.
+
+### Merging
+Using multiple branches brings along the concept of *merging* branches
+together. When working in a group, this is generally done by maintainers of the
+upstream repository, via a *merge request*. For some reason, certain services
+have named this as a *pull request* instead. The base idea of the process is as
+follows:
+
+- Pull the latest `upstream/master`
+- Create a new branch
+- Apply the change you want
+- Issue a merge request via the service you are using
+ - Generally, you want your change to be merged into their `master` branch
+- Add a title and a description of your change: What does it do, and why should it be accepted
+- Optionally, discuss the changes with the upstream maintainers
+- Optionally, make a couple of changes to your branch, and push it again
+- Upstream maintainer accepts your change
+
+When everything worked out, the upstream repository now contains your changes.
+If you pull their branch again, it will contain your code. Using the merge
+request process, your code can be easily reviewed by others, and discussed if
+needed.
+
+## Committing
+Whenever you have changed anything in the repository and you wish to share
+these changes, you have to commit the changes. Committing in general is not
+something people tend to have issues with. Simple add the changes you want to
+commit using `git add` (add the `-p` switch if you want to commit only parts of
+a changed file), then `git commit` and enter a descriptive message. And that is
+where most annoyances come from: the commit *message*. There are no hard rules
+on this forced by git itself. There are, however, some de-facto standards and
+best practices which you should always follow. Even if you never intend to
+share the repository with other people, having good commit messages can help
+you identify a certain change when you look back into the history.
+
+A git commit message should be short, no more than 79 characters, on the first
+line. It should be readable as "this commit message will ...", where your
+commit message will replace the "...". It is a de-facto standard to start your
+commit message with a capital letter, and leave off a finishing period. You do
+not *have* to adhere to if you hate this, but be sure that all your commits are
+consistent in how they are formatted.
+
+If you need to explain anything beyond that, such as a rationale for the
+change, or things the reviewer should pay attention to in this particular
+commit, you can leave an empty line and publish this message in the commit
+body.
+
+When you are using a bug tracking system, you might also want to have a footer
+with additional information. On services such as [Gitlab][gitlab] and
+[GitHub][github], you can close issues by adding "Closes: #1" in the commit
+message footer. A full commit message with all these things might look as
+follows:
+
+```
+Fix overflow issue in table rendering mechanism
+
+An overflow issue was found in the table rendering mechanism, as explained in
+CVE-0123-45678. Regression tests have been included as well.
+
+Closes: #35
+```
+
+In order to achieve these kind of messages, you need to be sure that your
+commits can fit in to this structure. This means you need to make small
+commits. Having many smaller commits makes it easier to review the changes,
+keep short, descriptive messages to describe each change, and revert a single
+change in case it breaks something.
+
+### Signing your commits
+You can set up git to cryptographically sign each commit you make. This will
+ensure that the commit you made is proven to be from you, and not someone
+impersonating you. People impersonating you might try to get harmful code into
+a repo where you are a trusted contributor. Having all commits signed in a
+repository can contribute in verifying the integrity of the project.
+
+Recently, [Github][github] has added the **Verified** tag to commits if the
+commit contains a correct signature.
+
+To enable signing of all commits, add the following configuration to your
+`~/.gitconfig`:
+
+{% highlight ini %}
+[commit]
+ gpgsign = true
+
+[user]
+ signingkey = 9ACFE193FFBC1F50
+{% endhighlight %}
+
+Ofcourse, you will have to update the value of the `signingkey` to match
+the key you want to sign your commits with.
+
+## Closing words
+I hope this post will help you in your adventures with git. It is a great tool
+or working on projects together, but it gets much better when you stick to some
+best practices. If you have any suggestions for this post, or any questions
+after finishing it, contact me via any method listed on [my home page][home].
+
+[github]: https://github.com
+[gitlab]: https://gitlab.com
+[gogs]: https://gogs.io
+[home]: https://tyil.work
+[so-git-branch]: https://softwareengineering.stackexchange.com/questions/335654/git-what-issues-arise-from-working-directly-on-master
+
diff --git a/_posts/2017-09-28-perl6-creating-a-background-service.adoc b/_posts/2017-09-28-perl6-creating-a-background-service.adoc
new file mode 100644
index 0000000..c642964
--- /dev/null
+++ b/_posts/2017-09-28-perl6-creating-a-background-service.adoc
@@ -0,0 +1,159 @@
+---
+date: 2017-09-28 15:11:43
+tags: Tutorial Perl6 Programming
+description: >
+ I've recently made some progress on Shinrin, a centralized logging system in
+ Perl 6. This has to run as service, which means that for most service
+ managers it has to be able to run in the background.
+---
+= Perl 6 - Creating a background service
+:toc: preamble
+
+I've recently made some progress on
+https://github.com/scriptkitties/perl6-Shinrin[Shinrin], a centralized logging
+system in Perl 6. This has to run as service, which means that for most service
+managers it has to be able to run in the background.
+
+[NOTE]
+====
+If you just want to get to the solution and don't care for the details, just
+head straight to link:#the-final-solution[the full script].
+====
+
+== It's not possible!
+After a lot of trying and talking with the folks at
+irc://chat.freenode.net:6697/#perl6[#perl6] I was told that it is not possible
+to do this in pure Perl 6, explained by people with more knowledge than I have
+on the internals:
+
+[quote, jnthn]
+____
+(jnthn suspects fork + multi-threaded VM = pain) Since fork only clones one
+thread - the one that called it. So suddenly you've got an instance of the VM
+missing most of its threads.
+____
+
+[quote, geekosaur]
+____
+The most common failure mode is that some thread is holding e.g. a mutex (or a
+userspace lock) during the fork. The thread goes away but the lock is process
+level and remains, with nothing around to know to unlock it. So then things
+work until something else needs that lock and suddenly you deadlock.
+____
+
+Not much later, `jnthn` https://github.com/perl6/doc/commit/8f9443c3ac[pushed a
+commit] to update the docs to clarify that a `fork` call through `NativeCall`
+will probably not give the result you were hoping for.
+
+== Or is it?
+Luckily, the same people were able to think up of a work-around, which can be
+made in POSIX sh, so it's usable on any decent OS. The workaround is to let a
+little shell script fork into the background, and let that run the Perl
+application.
+
+=== A first example
+This is fairly simple to create, as in this example to launch `shinrind` in the
+background:
+
+[source,sh]
+----
+#! /usr/bin/env sh
+
+main()
+{
+ perl6 -Ilib bin/shinrind "$@"
+}
+
+main "$@" &
+----
+
+This works just fine if the working directory is correct. This means you need
+to be in the parent directory to `lib` and `bin` of the program to make it
+work.
+
+== Improving the forking script
+While that short script works fine to show a proof of concept, in order to make
+it viable for real-world scenarios, it can use some improvements. After all, it
+would be annoying if you'd have to `cd` to a specific directory any time you
+want to start your application.
+
+=== Ensure you are in the directory you should be in
+So for starters, let's make sure that you can run it from anywhere on your
+system. For this, you should set the working directory for the script, so you
+don't have to do it manually. Because the script runs in its own subshell, the
+shell you're working from remains unaffected.
+
+A POSIX compliant way to get the directory the script is stored in is as
+follows:
+
+[source,sh]
+----
+DIR=$(CDPATH="" cd -- "$(dirname -- "$0")" && pwd)
+----
+
+This will set `$DIR` to the path of the directory the shell script is stored
+in. You can simply `cd` to that and be assured you're in the right directory.
+
+In Perl 6, it is expected for executable files to live in the `bin` directory
+of your project repository. So you should actually be in the parent of the
+directory holding your script. Furthermore, you should check the `cd` command
+executed correctly, just to be safe.
+
+[source,sh]
+----
+cd -- "${DIR}/.." || exit
+----
+
+=== Disable `STDOUT` and `STDERR`
+A started service should not be polluting your interactive shell, so you should
+disable (or otherwise redirect) `STDOUT` and `STDERR`. This is done in the
+shell using a small bit of code behind whatever you want to redirect:
+
+[source,sh]
+----
+> /dev/null 2>&1
+----
+
+This will set `STDOUT` to `/dev/null`, and set `STDERR` to the same stream as
+`STDOUT`, which in effect will make all output go to `/dev/null`. If you want
+to log everything to a single file, you can replace `/dev/null` with another
+file of your choice. If you don't want logs to be overwritten on each start,
+use a `>>` instead of a single `>` at the start.
+
+If you want to log errors and output in different files, you can use the
+following:
+
+[source,sh]
+----
+> /var/log/service.log 2> /var/log/service.err
+----
+
+This will put standard output in `/var/log/service.log` and errors in
+`/var/log/service.err`.
+
+=== Fork just the Perl 6 program
+In the initial example, I put the `&` behind the `main` call, at the bottom of
+the script. While this works just fine for most simple usage, if you want to do
+additional chores, like creating a pidfile after starting the Perl 6 program,
+you're out of luck. If you were to only fork the Perl 6 application, you could
+handle some other cases in the shell script.
+
+== The final solution
+For those eager to just get going with this, here is the complete example
+script to just fork your Perl program into the background:
+
+[source,sh]
+----
+#! /usr/bin/env sh
+
+readonly DIR=$(CDPATH="" cd -- "$(dirname -- "$0")" && pwd)
+
+main()
+{
+ cd -- "${DIR}/.." || exit
+
+ perl6 -Ilib bin/shinrind "$@" > /dev/null >2&1 &
+}
+
+main "$@"
+----
diff --git a/_posts/2017-11-01-hacktoberfest-2017.adoc b/_posts/2017-11-01-hacktoberfest-2017.adoc
new file mode 100644
index 0000000..ada4edd
--- /dev/null
+++ b/_posts/2017-11-01-hacktoberfest-2017.adoc
@@ -0,0 +1,197 @@
+---
+date: 2017-11-01 12:37:53
+tags: Article FreeSoftware Github Hacktoberfest Contributions
+description: >
+ This year I actively participated in the Hacktoberfest event, which is 'a
+ month-long celebration of open source software'. Ironic, given that the
+ companies organising it don't have their own software stack open source.
+ Nevertheless, I did contribute to free software, and this article lists these
+ contributions.
+---
+= Hacktoberfest 2017
+:toc: preamble
+
+This year I actively participated in the Hacktoberfest event, which is "a
+month-long celebration of open source software". Ironic, given that the
+companies organising it don't have their own software stack open source.
+
+I've found some issues to solve in https://perl6.org/[Perl 6] projects, and
+that lead to trying to solve issues in some other projects, and eventually I
+got more PRs out than there are days in the month. It did go at the cost of
+some sleep, but in the end it seems worth it. In this article, I'll give a
+small overview of all those PRs, in no particular order.
+
+== Projects contributed to
+=== Funtoo
+==== funtoo/boot-update
+- https://github.com/funtoo/boot-update/pull/14
+
+When reinstalling my server to try out https://docker.com[Docker], I noticed an
+error in the output of the `boot-update` utility, a tool from
+https://www.funtoo.org/Welcome[Funtoo] to make installing and configuring the
+bootloader easier. The error itself was a small type of a `-` which had to be a
+`_`.
+
+==== scriptkitties/overlay
+- https://github.com/scriptkitties/overlay/pull/14
+- https://github.com/scriptkitties/overlay/pull/15
+- https://github.com/scriptkitties/overlay/pull/16
+
+This is the overlay of the https://scriptkitties.church[Scriptkitties]
+community. It's got some additional software released under a free license that
+is not available in the main portage repository. Most of the packages in here
+are of software made by the Scriptkitties community.
+
+This month I updated the readme to be in asciidoc, my new favourite format for
+documentation. The Travis builds should also no longer throw errors, so those
+can be used again to ensure the overlay is meeting quality standards. One
+package has also been updated to be at it's latest version again.
+
+=== Perl 6
+==== moznion/p6-HTML-Escape
+- https://github.com/moznion/p6-HTML-Escape/pull/1
+
+On this repository, I added a subroutine to also handle unescaping HTML special
+characters. Sadly, the owner of this repository has shown no sign of life, and
+the PR remains open.
+
+==== rakudo/rakudo
+- https://github.com/rakudo/rakudo/pull/1180
+
+This is a rather small issue, but I noticed it when compiling Perl 6 with
+https://github.com/tadzik/rakudobrew[Rakudobrew] and it annoyed me.
+http://zoffix.com/[Zoffix] was a great help in getting me started on this one,
+and in general with many other Perl related contributions as well.
+
+==== scriptkitties/perl6-IRC-Client-Plugin-Github
+- https://github.com/scriptkitties/perl6-IRC-Client-Plugin-Github/pull/2
+
+A neat feature for the Github notification system, HMAC adds a header that can
+be used to verify the body of the request, and can be used to verify the other
+end of the connection knows the right "secret". Inspired by a Perl 6 bot that
+already did this, I made a PR to make this a proper
+https://github.com/zoffixznet/perl6-IRC-Client[IRC::Client] plugin. It is still
+being tested in https://github.com/scriptkitties/musashi[musashi].
+
+==== perl6/roast
+- https://github.com/perl6/roast/pull/342
+
+Roast is the test suite for Perl 6. There was an open issue for the IO::File
+tests, which needed expansion. As my first contribution during a Perl 6
+squashaton, I expanded these tests to fix the issue that was open for it.
+
+==== vim-perl/vim-perl6
+- https://github.com/vim-perl/vim-perl6/pull/9
+- https://github.com/vim-perl/vim-perl6/pull/10
+
+This first PR has become a bit of a drag, with the maintainers not responding
+for two weeks, but suddenly very eager to respond when I mention I'm going to
+fork off and update the reference on the Perl documentation to my fork.
+Nonetheless, it's sorted out, and the abbreviations for unicode operators
+have been merged in!
+
+==== timo/json_fast
+- https://github.com/timo/json_fast/pull/32
+
+`JSON::Fast` is the de-facto standard for dealing with JSON data in Perl 6 it
+seems. For my work with `App::Cpan6` I wanted the JSON data to be ordered, so I
+added that as an option when calling `to-json`. Having the JSON data ordered
+makes it easier to compare diffs of two different versions of the data, making
+git diffs a lot cleaner.
+
+Sadly, timo has not merged the PR yet, so I can't properly depend on it in
+`App::Cpan6`.
+
+==== scriptkitties/perl6-SemVer
+- https://github.com/scriptkitties/perl6-SemVer/pull/1
+
+This is one of the new projects I started. It is intended to be used in
+`App::Cpan6`, since that uses https://semver.org[Semantic Versioning] for all
+modules it works with. This module defines a class that can interpret a SemVer
+notation, and exposes methods to bump any part of the version.
+
+==== perl6/doc
+- https://github.com/perl6/doc/pull/1614
+
+This has been one of the more annoying PRs to work on, as the current `zef`
+maintainer insists everything but his module is wrong, and seemed very
+uninterested to improve the situation for users. After some discussion on IRC,
+some more discussion on IRC, and then some discussion on the PR itself, I
+decided to just word the paragraph differently.
+
+I am still interested in improving the documentation here and the ecosystem
+itself, mainly the `META6.json` specification, and getting `zef` to play nice
+with this spec. If anyone else is interested in helping me out on this, do
+message me on IRC!
+
+==== perl6/perl6.org
+- https://github.com/perl6/perl6.org/pull/86
+- https://github.com/perl6/perl6.org/pull/87
+
+There were some open issues for the https://perl6.org[perl6.org] website, and I
+decided to take a look at some and try to fix them. This resulted in NeoVim
+being added to the list of recommended editors for Perl 6, and the list of IRC
+bots being updated to include all bots in use right now.
+
+==== scriptkitties/p6-MPD-Client
+- https://github.com/scriptkitties/p6-MPD-Client/pull/1
+- https://github.com/scriptkitties/p6-MPD-Client/pull/2
+
+As I was making `App::MPD::AutoQueue` and `App::MPD::Notify`, I found some
+issues in `MPD::Client`. I fixed those to get my two new projects working
+nicely.
+
+==== melezhik/sparrowdo
+- https://github.com/melezhik/sparrowdo/pull/15
+- https://github.com/melezhik/sparrowdo/pull/18
+
+Sparrowdo is a configuration management system, written in Perl 6. I learned
+about it after a reference from the Perl 6 Weekly, and set out to try it. I ran
+into some issues, which I reported and eventually fixed.
+
+In addition, I also rewrote the testing script for Travis, which enables
+paralel builds of the tests. This has nearly halved the time required for
+running the full test suite.
+
+==== perl6/ecosystem
+- https://github.com/perl6/ecosystem/pull/371
+- https://github.com/perl6/ecosystem/pull/372
+- https://github.com/perl6/ecosystem/pull/374
+
+These PRs added a module, and removed that one and more later on, since I got a
+PAUSE ID and uploaded my modules to CPAN.
+
+==== scriptkitties/perl6-App-Cpan6
+- https://github.com/scriptkitties/perl6-App-Cpan6/pull/1
+- https://github.com/scriptkitties/perl6-App-Cpan6/pull/2
+- https://github.com/scriptkitties/perl6-App-Cpan6/pull/3
+- https://github.com/scriptkitties/perl6-App-Cpan6/pull/4
+- https://github.com/scriptkitties/perl6-App-Cpan6/pull/12
+- https://github.com/scriptkitties/perl6-App-Cpan6/pull/13
+- https://github.com/scriptkitties/perl6-App-Cpan6/pull/14
+- https://github.com/scriptkitties/perl6-App-Cpan6/pull/15
+
+`App::Cpan6` is a tool I've started working on to assist me in creating new
+Perl 6 modules. There's been a couple of tasks that I do often in the process
+of creating a module, and those tasks should become easier and faster using
+this module.
+
+If everything works out and I learn enough of the module installation process,
+I might consider letting this deal with the installation and updating of
+modules as well.
+
+== In retrospect
+The Hacktoberfest has been an interesting month for me. I've gotten to
+contribute to a project I have come to love a lot, Perl 6. I've also made some
+new friends with similar goals. Sadly I can't put in this much time every month
+of the year, but I would if I could!
+
+I learned many interesting things for Perl 6, new operators, new functions, all
+kinds of cool stuff to improve my Perl scripts with. I also got to learn about
+parallelizing Travis builds with the Sparrowdo project, of which I will write
+another tutorial post later.
+
+I've greatly enjoyed contributing to all the various projects, and would
+recommend other people to check it out too. The people on the respective
+project's IRC channels have been a great help to me to get started, and I can
+help out getting you started as well now.
diff --git a/_posts/2017-11-16-perl6-setting-up-a-raspberry-perl.adoc b/_posts/2017-11-16-perl6-setting-up-a-raspberry-perl.adoc
new file mode 100644
index 0000000..e58efc1
--- /dev/null
+++ b/_posts/2017-11-16-perl6-setting-up-a-raspberry-perl.adoc
@@ -0,0 +1,236 @@
+---
+date: 2017-11-16 11:58:40
+tags: Tutorial Perl6 RaspberryPi Installation
+description: >
+ In this tutorial I'll get you through setting up a Raspberry Pi with Perl 6.
+ I am using a Raspberry Pi 3 myself, but other versions should work fine too.
+ However, older versions are slower, so it might take a bit longer to install
+ completely.
+---
+= Perl 6 - Setting up a Raspberry Perl
+:toc: preamble
+
+In this tutorial I'll get you through setting up a Raspberry Pi with
+https://perl6.org/[Perl 6]. I am using a Raspberry Pi 3 myself, but other
+versions should work fine too. However, older versions are slower, so it might
+take a bit longer to install completely.
+
+[NOTE]
+====
+For those who have never had a Raspberry Pi before, you will need
+the following:
+
+- Raspberry Pi board
+- Power supply (5v 2A, micro USB)
+- SD card of at least 4gb, but I would advise at least 8gb
+- Monitor with HDMI cable
+- Keyboard
+====
+
+Perl 6 will be installed using
+https://github.com/tadzik/rakudobrew[Rakudobrew], which I'll also be using to
+get https://github.com/ugexe/zef[zef] installed. Zef is the recommended module
+manager for Perl 6.
+
+== Setting up Raspbian
+
+The first step is getting the OS set up. To keep this tutorial simple, I will
+stick to https://www.raspbian.org/[Raspbian], but if you feel confident in your
+skills you can use any other distribution or OS. Perl 6 installs the same on
+all UNIX(-like) operating systems.
+
+=== Get the image
+
+First, https://www.Raspberrypi.org/downloads/raspbian/[download the Raspbian
+image from the Raspberry Pi download page]. I chose the `LITE` version, but if
+you prefer having a graphical desktop you can go for the `DESKTOP` version
+instead.
+
+At the time of writing, this means I got the
+`2017-09-07-raspbian-stretch-lite.zip`. If you want to verify you got the
+correct download and nothing went wrong saving it to your disk, you can verify
+the checksum. The checksum for your download is noted below the download links.
+To get the checksum of the file you downloaded, use `sha256sum` as follows:
+
+NOTE: Lines prepended with a `$` are to be ran as your normal user, whereas
+lines with a `#` are ment to be ran as "super user". This can be done by using
+a privilege escalation program, such as
+https://www.linux.com/blog/how-use-sudo-and-su-commands-linux-introduction[`sudo`].
+
+[source]
+----
+$ sha256sum 2017-09-07-raspbian-stretch-lite.zip
+----
+
+If the checksum matches the one noted below the download button you used, it
+should be fine, and you can continue with extracting the image from the zip
+using `unzip`:
+
+[source]
+----
+$ unzip 2017-09-07-raspbian-stretch-lite.zip
+----
+
+This will result in a similarly named file, but with a `.img` extension instead
+of `.zip`. This is the image that you can write to the SD card.
+
+=== Write the image to the SD card
+
+This step is pretty easy, but typos here can be disastrous for the system
+you're using to write to the SD card.
+
+Open a terminal and run `dmesg -w` as super user (usually doable using `sudo
+dmesg -w`). This will give immediate feedback when you insert your SD card, and
+shows which device it is being assigned to. In my case, this was `sdb`, which
+means the device file resides at `/dev/sdb`.
+
+Now, to actually write the image, I'll use `dd` since this is everyone's
+favourite tool, it seems. If you feel adventurous enough to try out something
+different, feel free to read up on
+https://www.vidarholen.net/contents/blog/?p=479[Useless Use of dd].
+
+Make sure to make the `if` argument point to the correct path with your
+extracted raspbian image, and `of` to point to the correct device as identified
+earlier. In order to be allowed to run this command, you must be root, which
+can be achieved by using `sudo` or `doas` again.
+
+[source]
+----
+# dd bs=4M status=progress if=/path/to/2017-09-07-raspbian-stretch-lite.img of=/dev/sdb
+$ sync
+----
+
+Afterwards, plug it into your Raspberry Pi and attach all cables you might
+need. Think of stuff like a keyboard, mouse, monitor, internet, power. Do power
+last, as the Raspberry Pi will start immediatly once it receives power.
+
+=== First boot
+
+The Raspberry Pi should start booting the moment you supply it with power. If
+you attach the HDMI after the power, it's possible you won't have display
+working, so make sure HDMI is attached before powering up.
+
+You'll see some text scrolling by, up to a point where it asks you for a
+`login`, and accepts keyboard input. The default username is `pi`, and the
+default password is `Raspberry`. You are strongly advised to change the
+password upon login, which can be done in the next step.
+
+=== Configuration
+
+The Raspberry Pi comes with its own configuration tool, `raspi-config`. Run
+this with `sudo` prepended in front of it so you gain the right privileges. I
+would advise you to at least change the user password from here. After this you
+should go to `Advanced Options` and expand the filesystem. This will grow the
+filesystem to the entire SD card's size.
+
+TIP: To get to the buttons on the bottom (`Select`, `Finish` and `Back`), use
+the arrow keys to go left or right.
+
+You can look around the tool for other interesting things to modify. Once you
+are satisfied, go back to the main menu and choose `Finish`. It will ask to
+reboot, which you should accept. This will apply all the new configurations you
+just made.
+
+=== Updating and installing additional packages
+
+It's rare for the system to be completely up to date after installing the image
+on the SD card. Additionally, you also need some extra packages in order to get
+rakudobrew, and to install Perl 6 itself. For this, we use the package manager
+bundled with raspbian, `apt`:
+
+[source]
+----
+# apt update
+# apt upgrade
+----
+
+This will update the package lists, and then upgrade all outdated packages to
+their newest versions. You should do this at least once a week to make sure
+your system stays up to date.
+
+Once the upgrades are finished, you can install some new packages which are
+needed later on in this tutorial:
+
+[source]
+----
+# apt install git build-essential
+----
+
+`git` is required to get the rakudobrew repository and is also used by
+rakudobrew itself to get the sources needed to build Perl 6 and to install zef.
+The `build-essential` package comes with all sorts of tools to build software,
+which is required to build Perl 6.
+
+== Installing Perl 6
+
+Now, we've got a working Raspberry Pi installation. We can start doing things
+with it, such as playing around with Perl 6.
+
+=== Setting up Rakudobrew
+
+Rakudobrew is a nice tool to manage Perl 6 installations on your system. It can
+also install `zef` for you, so you don't have to deal with this manually. This
+is all documented on the repository's `README.md` file as well, but I'll
+explain it here too. I do make a few small tweaks here and there to match my
+preferred setup more closely.
+
+Clone the repository to your system, and add it to your `$PATH` to be able to
+use the scripts bundled with it:
+
+[source]
+----
+$ mkdir -p ~/.local/var
+$ git clone https://github.com/tadzik/rakudobrew.git ~/.local/var/rakudobrew
+$ export PATH=${HOME}/.local/var/rakudobrew/bin:$PATH
+$ hash -r
+----
+
+The `hash -r` call will rehash your PATH, so you can tab-complete `rakudobrew`.
+Next, initialize rakudobrew:
+
+[source]
+----
+$ rakudobrew init
+----
+
+This will give you a notification to automatically load rakudobrew next time.
+It is advised you follow that message, so you won't have to do it manually each
+time you log in to the system.
+
+=== Installing Perl 6 with MoarVM backend
+
+Now that rakudobrew is installed and available to use, it's time to make use of
+it to install Perl 6.
+
+[source]
+----
+$ rakudobrew build moar
+----
+
+=== Installing zef, the module manager
+
+Getting zef to work isn't much harder than installing Perl 6, but its a lot
+faster. You can have rakudobrew take care of this too:
+
+[source]
+----
+$ rakudobrew build zef
+----
+
+== Final words
+
+And that should be it, you now have a working Perl 6 installation with the zef
+module manager to take care of installing and upgrading modules. Now you just
+need to come up with a nice project to work on to start using and learning the
+wonders of Perl 6.
+
+If you need any help on getting started, try the `#perl6` IRC channel on
+Freenode, or check out some of the Perl 6 documentation and introduction sites:
+
+- https://docs.perl6.org/
+- http://perl6intro.com/
+
+For starting projects that are easy to start with and can bring quick results,
+consider making an IRC bot using
+https://github.com/zoffixznet/perl6-IRC-Client[`IRC::Client`], or a small web
+application using https://github.com/Bailador/Bailador[`Bailador`].
diff --git a/_posts/2017-12-17-on-cloudflare.adoc b/_posts/2017-12-17-on-cloudflare.adoc
new file mode 100644
index 0000000..8d730a7
--- /dev/null
+++ b/_posts/2017-12-17-on-cloudflare.adoc
@@ -0,0 +1,128 @@
+---
+date: 2017-12-17 10:13:26
+tags: Article Harmful Cloudflare
+description: >
+ Cloudflare is a threat to online security and privacy. I am not the first on
+ to address this issue, and I probably will not be the last either. Sadly,
+ people still seem to be very uninformed as to what issues Cloudflare actually
+ solves, or introduces.
+---
+= On Cloudflare
+:toc:
+
+== Foreword
+Cloudflare is a threat to online security and privacy. I am not the first on to
+address this issue, and I probably will not be the last either. Sadly, people
+still seem to be very uninformed as to what issues Cloudflare actually poses.
+There also seems to be a big misconception about the benefits provided by using
+Cloudflare. I would suggest reading the
+http://cryto.net/~joepie91/blog/2016/07/14/cloudflare-we-have-a-problem/[article
+on Cloudflare by joepie91] for a more thorough look at Cloudflare.
+
+If anyone is using Cloudflare, please tell them to stop doing it. Link them to
+this page or any of the articles referenced here. Cloudflare is harmful to your
+visitors, and if you do not care about them, they will stop caring about you
+too.
+
+== A literal MITM attack
+Cloudflare poses a huge risk by completely breaking the TLS/SSL chain used by
+browsers by setting itself up as a
+https://en.wikipedia.org/wiki/Man-in-the-middle_attack[man in the middle].
+Cloudflare doesn't do actual DDoS protection, they just make the request to the
+origin server for you. Once they have received the data, they decrypt it and
+re-encrypts it with their own certificate. This means that Cloudflare has
+access to all requests in plain text and can optionally modify the data you
+see. TLS/SSL is meant to prevent this very issue, but Cloudflare seems to care
+very little.
+
+If we would consider Cloudflare to be a benevolent entity and surely never
+modify any data ever, this is still an issue. Much data can be mined from the
+plain text communications between you and the origin server. This data can be
+used for all kinds of purposes. It is not uncommon for the USA government to
+request a massive amount of surveillance information from companies without the
+companies being able to speak up about it due to a gag order. This has become
+clear once more by the
+https://whispersystems.org/bigbrother/eastern-virginia-grand-jury/[subpoena on
+Signal]. It should be clear to anyone that end-to-end encryption has to be a
+standard and implemented properly. Cloudflare goes out of its way to break this
+implementation.
+
+=== Cloudbleed
+The danger of their MITM style of operation was shown be the
+https://en.wikipedia.org/wiki/Cloudbleed[Cloudbleed] vulnerability. It also
+shows that they make use of their MITM position to scan the data your site and
+a visitor are exchanging. This includes private data, such as passwords.
+
+Even if you have an SSL connection to Cloudflare, they still decrypt it on
+their end. They then serve the content under their own certificate. This makes
+it look to the visitor like everything is secure, the browser says so after
+all. But in reality, they don't have a secure connection to your server. They
+only have one up to Cloudflare, and when it reaches Cloudflare, they decrypt it
+and re-encrypt it using your certificate again. If you use one, of course,
+otherwise they'll pass it on in plaintext back to your server, which is even
+more dangerous. Whether or not you do, the content exists in plaintext on
+Cloudflare's servers, which is not what you want, if you truly care about
+security.
+
+== Eliminating your privacy
+If Cloudflare were to fix their MITM behavior, the privacy problem would not
+be solved all of a sudden. There are more questionable practices in use by
+Cloudflare.
+
+People who are using a VPN or an anonimization service such as Tor are usually
+greeted by a warning from Cloudflare. Let's not talk about this warning being
+incorrect about the reason behind the user receiving the warning, but instead
+about the methodology used to "pass" this "warning". Cloudflare presents you
+with a page that requires you to solve a reCaptcha puzzle, which is hosted by a
+well known third party that tries to harm your privacy as much as possible,
+Google. If you do not wish to have Google tracking you all the time, you will
+not be able to solve these puzzles, and in effect, unable to access the site
+you were visiting. It is also interesting to note that this reCaptcha system is
+sometimes broken if your browser does not identify itself as one of the regular
+mainstream browsers such as Firefox or Chrome.
+
+Some site administrators disable this specific check. However, this still means
+all your requests are logged by another third party, namely Cloudflare itself.
+As noted in _A literal MITM attack_, this data is still very interesting to
+some parties. And do not fool yourself: meta data is still very worthwhile and
+can tell a huge amount of information about a person.
+
+=== Forcing JavaScript
+This issue generally does not concern many people, as most people online
+nowadays use a big mainstream browser with JavaScript enabled. However, there
+are still people, services and applications that do not use JavaScript. This
+makes sites unavailable when they are in the "under attack" mode by Cloudflare.
+This will run a check sending Cloudflare your browser information before
+deciding whether you are allowed to access the website. This is yet another
+privacy issue, but at the same time, a usability issue. It makes your site
+unavailable to people who simply do not wish to use JavaScript or people who
+are currently limited to a browser with no JavaScript support.
+
+It is also common for Cloudflare to
+http://www.tedunangst.com/flak/post/cloudflare-and-rss[Break RSS readers] by
+presenting them with this check. This check is often presented to common user
+agents used by services and programs. Since these do not include a big
+JavaScript engine, there is no way for them to pass the test.
+
+== False advertising
+=== DDoS protection
+Cloudflare is hailed by many as a gratis DDoS protection service, and they
+advertise themselves as such. However, Cloudflare does not offer DDoS
+protection, they simply act as a pin cushion to soak the hit. Real DDoS
+protection works by analyzing traffic, spotting unusual patterns and blocking
+these requests. If they were to offer real DDoS protection like this, they
+would be able to tunnel TLS/SSL traffic straight to the origin server, thereby
+not breaking the TLS/SSL chain as they do right now.
+
+It should also be noted that this gratis "protection" truly gratis either. If
+your site gets attacked for long enough, or for enough times in a short enough
+time frame, you will be kicked off of the gratis plan and be moved onto the
+"business" plan. This requires you to pay $200 per month for a service that does
+not do what it is advertised to do. If you do not go to the business plan, you will
+have about the same protection as you would have without it, but with the
+addition of ruining the privacy and security of your visitors.
+
+=== Faster page loads
+This is very well explained on joepie91's article under the heading _But The
+Speed! The Speed!_. As such, I will refer to his article instead of
+repeating him here.
diff --git a/_posts/2017-12-21-funding-yourself-as-free-software-developer.adoc b/_posts/2017-12-21-funding-yourself-as-free-software-developer.adoc
new file mode 100644
index 0000000..d292790
--- /dev/null
+++ b/_posts/2017-12-21-funding-yourself-as-free-software-developer.adoc
@@ -0,0 +1,231 @@
+---
+title: Funding Yourself As A Free Software Developer
+date: 2017-12-21 05:29:26
+tags: Article FreeSoftware Development Funding
+description: >
+ An overview of multiple funding platforms, with pros and cons, from the
+ perspective of a free software developer. It's intent is to help others find
+ a possible form of income while doing what they love, and what I consider is
+ immensely important for society.
+---
+= Funding Yourself As A Free Software Developer
+:toc: preamble
+
+I've been meaning to spend more time on developing free software, helping out
+new users on IRC and writing more tutorials to get others started. All of these
+cost time, and time is money - so I've set out to set up donation accounts.
+In the hopes of helping other developers who struggle to fund their work, I've
+written up this article to talk about my experience. This is a living
+document! As you explore this yourself, please send me your thoughts on each
+platform and turn me on to interesting platforms I missed.
+
+I'll be focussing on platforms allowing for recurring donations, as these are
+more useful for procuring a stable income.
+
+== Platforms
+=== BountySource
+[WARNING]
+====
+- Requires 3rd-party link:/articles/on-cloudflare/[Cloudflare]-hosted
+ JavaScript sources to function.
+====
+
+BountySource lets people donate money towards an issue on Github your projects.
+Once an issue gets fixed, you can claim the "bounty" that was on this issue.
+This can also help in making clear which issue you should aim for next, and
+can increase interest in contributors for your project.
+
+There's also BountySource Salt, which is a recurring donation platform.
+Projects or teams can use this to gain monthly income to sustain the
+development of their project(s).
+
+Support for this platform is offered through the IRC channel
+https://kiwiirc.com/client/chat.freenode.net:+6697/#bountysource[`#bountysource`
+on Freenode].
+
+The BountySource platform itself is also free software, and the source code
+for it can be found https://github.com/bountysource/core[on github].
+
+You can find BountySource at https://www.bountysource.com/.
+
+=== LiberaPay
+This service seems to be completely free as in freedom. They even
+https://github.com/liberapay/liberapay.com[publish their source on GitHub].
+Their own funding comes through donations on their own platform, instead of
+taking a cut of each donation like most other services.
+
+It's possible to connect other accounts to your LiberaPay account. While this
+feature in general is pretty common, they allow you to link to sites which are
+interesting to show as developer, such as GitHub, GitLab, and BitBucket. They
+also let you link to a Mastodon account, if you have one.
+
+To let people know you're accepting donations through LiberaPay, you can use
+one of the widgets they make available for you. This will show a donate button
+which will link to you profile. Do note, this is not a regular HTML button or
+cleverly implemented anchor tag, but a JavaScript-based button.
+
+Another thing LiberaPay lacks is a rewards system. Most other platforms allow
+you to set reward tiers, which allow you to give certain benefits to donors.
+
+You can find Liberapay at https://liberapay.com/.
+
+=== MakerSupport
+[WARNING]
+====
+- The site requires a 3rd-party hosted jQuery.
+- You have to solve a Google reCaptcha in order to register a new account.
+====
+
+MakerSupport seems to be another option, aimed at content creators who might
+need freedom of speech more than others. It seems to be less focused on
+software development, as you cannot link to any of the major git hosting
+platforms.
+
+There are options here to set up "tiers" for your donors; which is a convenient
+way to provide them with perks for their support. For a free software
+developer, this might be something like access to more direct support from the
+developer.
+
+Sadly, registration wasn't as smooth as most other platforms. My preferred
+username, "tyil" is too short. There's no indication of the requirements of any
+of the fields, you just get a popup on submission of the form saying a field is
+wrong.
+
+Additionally, the registration form requires some 3rd-party JavaScript to work,
+and a Google reCaptcha to be solved in order to get the submit button to show
+up. As I have set up uMatrix in my browser, this cost me some extra time to
+finish registration.
+
+Setting a profile image proved to be a little harder. First off, I'm still
+using uMatrix so I had to allow a 3rd-party (Amazon, in this case) XHR
+requests. Secondly, their error when uploading a "wrong" format is also not
+very user friendly, as it won't give you any details on why it's disallowed,
+nor what images are allowed instead.
+
+[NOTE]
+====
+It seems they check the extension of the uploaded image's filename. As far as I
+can tell, you're allowed to upload files that end with `.jpg` and `.png`.
+====
+
+You can find MakerSupport at https://www.makersupport.com/.
+
+=== Patreon
+[WARNING]
+====
+- Requires 3rd-party link:/articles/on-cloudflare[Cloudflare]-hosted
+ JavaScript sources to function.
+- You have to solve a Google reCaptcha in order to register a new account.
+====
+
+Patreon is possibly the most famous donation-based funding platform available
+right now. Its popularity is a good thing, since this means there's probably
+many donors already using this platform.
+
+At Patreon, you can set up so-called goals. Goals are the thing I haven't found
+with other funding platforms. It allows you to set a goal for an amount of
+money, and add a reward to this. This way, you can inform your donors you will
+be creating a certain kind of content once a one-time goal has been reached.
+Basically, you can show your donors what you're going to do with the money
+they're donating to you.
+
+Another interesting thing that I haven't seen on other platforms is the option
+to charge donors per creation, instead of per month. While this may seem less
+fitting for software developers (unless you want to get paid per commit, I
+guess), it's an interesting feature that's pretty unique. If you publish many
+tutorials, guides or other posts, this might fit you very well.
+
+You can link your account to other services, similarly to other platforms, but
+it seems to only allow you to be linked with proprietary social media
+platforms.
+
+You can find Patreon at https://www.patreon.com/home.
+
+=== (Dis)honorable mentions
+==== Hatreon
+I've included this because I found people talking about it on IRC. However, it
+seems to be nothing more than a joke that's gone too far. Its main reason for
+existing seems to be to get away from the political correctness found with
+earlier crowdfunding platforms, yet their site is invite-only, so those who are
+actually interested can't even use it. It seems that pledging is currently
+disabled as well, and has been for at least 10 days.
+
+== But that's not all
+Just setting up an account on a funding platform isn't enough. There's more to
+keeping a healthy and happy supporter base.
+
+=== Spread awareness of your work
+Whether you're writing articles or publishing new releases of projects, tell
+the world you're doing whatever it is you're doing. If nobody knows about your
+project, they won't be able to give any kind of appreciation for it. Use social
+media outlets, public forums, mailing lists, anything! Tell them what you made,
+why it's useful and how they could use it to improve their digital life.
+
+[WARNING]
+====
+Ofcourse, don't spam it to unrelated communication channels. This will only
+backfire.
+====
+
+=== Using the rewards system
+On the platforms that support a rewards system, make use of it. There's some
+little things you can do that go a long way with your supporters. For instance,
+you can offer things like stickers to donors that donate a certain amount of
+money to you. These are reasonably cheap to produce and ship, and many people
+like these.
+
+Another idea that seems to strike well with donors is having a way to talk with
+the person they're supporting directly. This can be done by giving them access
+to an IRC channel for you and your donors. You can use another platform for
+this, but most free software enthousiasts are already on IRC, and there's few
+real-time communication alternatives that they're already using.
+
+=== Don't stick to a single platform
+There's multiple platforms out there, use them! Not all of them have the same
+userbase, and you can reach more people by giving them more options to work
+with.
+
+=== Let people know you're accepting donations
+If people don't know you're even accepting donations, chances are pretty high
+you won't get any. Or if it's too hard to figure out how to donate to you,
+people will simply not take the effort. Make sure people can easily find out
+that you're accepting donations, and how to donate to you.
+
+=== Show what you're doing with donation money
+Have a page with information about what you're using with the money. This can
+be as simple as just saying you pay the rent and buy food with it. Most donors
+don't mind too much what you're doing with the money they donate to you, but a
+few do appreciate having this information available to them.
+
+It can be as simple as adding a `/donate` link to your site where you explain
+how to donate to you, and what you do with the donation money.
+
+[WARNING]
+====
+Don't let it turn into an annoying advertisement though, this will surely have
+an opposite effect.
+====
+
+== Further reading
+There's more places to go for tips and tricks in getting funds to sustain your
+free software development work. I've listed a couple of these here for those
+interested.
+
+- https://wiki.snowdrift.coop/market-research/other-crowdfunding[snowdrift.coop wiki on crowdfunding/fundraising services]
+- https://github.com/nayafia/lemonade-stand[A handy guide to financial support for open source]
+
+== RFC
+I'd love to receive feedback on this, as I think being able to get donations
+easily for the work free software developers put in to their projects is
+important.
+
+Getting to know more platforms and giving them a small write-up should help out
+other developers like me looking for the best platform for their use case. I'd
+also like to hear from developers already using a platform, to extend this
+article with more useful information on how to successfully get donors for
+their work.
+
+If you want to contact me, do take a look at the link:/[Contact] section, and
+let me know about your experiences with funding.
+
+And if you liked this post, consider link:/support/[donating] ;)
diff --git a/_posts/2018-02-05-why-perl6.adoc b/_posts/2018-02-05-why-perl6.adoc
new file mode 100644
index 0000000..f482901
--- /dev/null
+++ b/_posts/2018-02-05-why-perl6.adoc
@@ -0,0 +1,280 @@
+---
+title: Why Perl 6?
+date: 2018-02-05 18:22:20
+tags: Article Perl6
+description: >
+ I've grown quite fond of Perl 6 the more I learn about it, yet the general
+ developer community still seems to think Perl is a dirty word. In this
+ article, I will detail some of the features that make me like Perl 6, and why
+ I try to use it wherever possible.
+---
+= Why Perl 6?
+:toc: preamble
+
+For about a year now, I've been working in Perl 6. Telling this to other people
+often brings about some confused faces. I've grown quite fond of Perl 6 the
+more I learn about it, yet the general developer community still seems to think
+Perl is a dirty word. In this article, I will detail some of the features that
+make me like Perl 6, and why I try to use it wherever possible.
+
+== Hassle-free command line arguments
+Whet creating an application, you usually want to be able to specify some
+arguments at runtime. Most times this happens using command line arguments or
+options. Perl 6 allows you to specify these in the
+https://docs.perl6.org/language/functions#index-entry-MAIN[`MAIN`] subroutine
+signature.
+
+For instance, if I want the application to accept two string arguments, I can
+do it as easy as this:
+
+[source,perl6]
+----
+sub MAIN (
+ Str $arg-one,
+ Str $arg-two,
+) {
+ ...
+}
+----
+
+Now, if you wanted to add an option like `--output=/path/to/file`, you can do
+it just like this:
+
+[source,perl6]
+----
+sub MAIN (
+ Str $arg-one,
+ Str $arg-two,
+ Str :$output,
+) {
+ ...
+}
+----
+
+By default, if there's a `MAIN` available in your Perl 6 program, but the
+arguments or options supplied by the user are incorrect, it will display the
+right way to invoke the command, called the
+https://docs.perl6.org/language/functions#index-entry-USAGE[`USAGE`]. Ofcourse,
+this message can be changed if you wish, but the default is quite good for most
+use-cases.
+
+However, sometimes you want to add a little explanation to what the argument or
+option is intended for. Just for a liitle bit of additional user friendliness.
+
+Fear not, for this is also already covered by the defaults. In Perl, there was
+POD to document your code. In Perl 6, we have
+https://docs.perl6.org/language/glossary#index-entry-POD[POD] as well. And
+these comments can be inspected at runtime to provide the user some
+information. And that's exactly what the default `USAGE` also does. So if you
+want to add some helpful comments to the arguments or the program itself,
+simply add the comments where you want them:
+
+[source,perl6]
+----
+#| This is a sample program, just to showcase the awesome stuff available in
+#| Perl 6.
+sub MAIN (
+ Str $arg-one, #= Just a random argument
+ Str $arg-two, #= Yet another argument used for showcasing
+ Str :$output, #= Last but not least, an option which allows for a value
+) {
+ ...
+}
+----
+
+== Unicode
+What if you could support all languages with a single implementation? That's
+where unicode comes in. And Perl 6 currently has the best support for Unicode
+out of all programming languages available. Its only real competitor seems to
+be Swift (at the time of writing this).
+
+But not just for handling strings, Perl 6 uses unicode as a core language
+feature. This means you can use them in your source code as well. And that
+opens up some nice possibilities. Using the right unicode characters allows you
+to write cleaner and more concise code, reducing the cognitive load while
+trying to understand the program.
+
+For instance, if you're trying to do any kind of math, you can just use the
+π character as a regular character. Or use the ² to get the square of a certain
+number. This little piece is completely valid in Perl 6:
+
+[source,perl6]
+----
+my $a = $r² ÷ π;
+----
+
+Now, if you're thinking "that looks neat, but how am I ever going to write
+these?", do not worry. Most operating systems and many editors have tools to
+let you input these. For instance, using `vim` with
+https://github.com/vim-perl/vim-perl6[`vim-perl6`], you can just write "pi" and
+hit space (or type any non-alphabetical character).
+
+But not everyone is using an OS or an editor that makes it easy. And for those
+people, Perl 6 simply supports using
+https://docs.perl6.org/language/unicode_ascii[ascii based operators]. The
+previous block could also be written as follows:
+
+[source,perl6]
+----
+my $a = $r ^ 2 / pi;
+----
+
+As unicode becomes more accepted, input methods will hopefully improve to make
+input easier for everyone in the long run. Those who can already input it
+easily don't have to wait for this future, Perl 6 already supports it.
+
+== Multithreading
+Multi-core processors are virtually everywhere these days. Yet many programming
+languages still don't support multithreaded application development natively,
+if at all. In Perl 6, running something in a different thread is as easy as
+wrapping it in a https://docs.perl6.org/routine/start[`start`] block:
+
+[source,perl6]
+----
+start {
+ do-something();
+}
+----
+
+`start` returns a https://docs.perl6.org/type/Promise[`Promise`], which you can
+store in a scalar variable just like any other object. You can check on whether
+the `Promise` has completed already and check whether it died, for instance.
+
+Other aspects which can often be spread over multiple threads are loops or
+maps. For instance, consider the following
+https://docs.perl6.org/routine/map[map] function:
+
+[source,perl6]
+----
+@cats.map: {
+ $^cat.pat;
+}
+----
+
+This will pat each cat in turn, in the order they appear in the list. But you
+can speed up the patting process by patting multiple cats at the same time. And
+to get there, all you need to do is add a
+https://docs.perl6.org/routine/race[`race`]:
+
+[source,perl6]
+----
+@cats.race.map: {
+ $^cat.pat;
+}
+----
+
+This will attempt to pat the cats over multiple threads, speeding up the
+process to pat all the cats. If the result of the pattings needs to be in the
+same order as the patting order, you use
+https://docs.perl6.org/routine/hyper[`hyper`] instead of `race`:
+
+[source,perl6]
+----
+@cats.hyper.map: {
+ $^cat.pat;
+}
+----
+
+== Object orientation
+Object oriented programming seems to be getting out of fashion with the new
+generation of developers. But it's still in wide use, being taught at most
+universities, and is often easy to explain to new developers as well.
+
+And Perl 6 has https://docs.perl6.org/language/classtut#index-entry-OOP[OO]
+support built into its core:
+
+[source,perl6]
+----
+class Foo
+{
+ has Str $some-field;
+
+ method bar (
+ Str $some-arg,
+ ) {
+ ...
+ }
+}
+----
+
+You can also have
+https://docs.perl6.org/language/glossary#index-entry-Multi-Dispatch[multi-dispatch]
+methods on your classes, which are methods with the same names, but accepting
+different arguments or argument types. For instance:
+
+[source,perl6]
+----
+class Foo
+{
+ multi method bar (
+ Str $some-arg,
+ ) {
+ ...
+ }
+
+ multi method bar (
+ Int $some-arg,
+ ) {
+ ...
+ }
+}
+----
+
+Which method is being used will be decided by the type of argument is being
+passed in, in this case either a https://docs.perl6.org/type/Str[`Str`] or an
+https://docs.perl6.org/type/Int[`Int`].
+
+== Functional programming
+Whilst OO is considered being old more and more, functional programming is
+gaining ground. And this paradigm is fully supported in the core of Perl 6 as
+well. You've seen the `map` example already while patting cats earlier, for
+instance.
+
+But there's much more on the functional playing field, such as the
+https://docs.perl6.org/routine/==%3E[`=\=>`] operator, known as the
+https://docs.perl6.org/language/operators#infix_==%3E[feed operator]. It simply
+passed the output of a statement as the last argument to the next statement:
+
+[source,perl6]
+----
+@grumpy-cats
+ ==> feed()
+ ==> pat()
+ ==> snuggle()
+ ==> my @happy-cats;
+----
+
+This will take the `@grumpy-cats`, feed them, pat them, snuggle them and put
+the result into `@happy-cats`. You could've chained the calls using a `.`
+instead, and Perl 6 allows you to do this too. But the `=\=>` looks much more
+readable to me, which is why I prefer using this instead.
+
+I'm still exploring the functional programming field myself, but these few
+things have made me happy exploring it.
+
+== Community
+(Almost) last, but certainly not least, the Perl 6 community is amazing. It's
+been the friendliest bunch I've been with, both on IRC, their mailing lists and
+in real life. Everyone is welcoming, and they try to help you whenever they
+can.
+
+Community is important to help you out whenever you get stuck for whatever
+reason. A friendly community is the best you can get here to keep you a happy
+developer yourself as well.
+
+== Other little aspects
+There's a few neat things I can do in Perl 6 that I can't do in (most) other
+languages, but aren't important enough to warrant a large section to show them
+off.
+
+=== Dashes in names
+You can use dashes in names: Things like `my $foo-bar` is valid, just like
+`method foo-bar`. It's nothing big on itself, but I've found it makes reading
+code much more enjoyable than pascalCase, CamelCase or snake_case.
+
+=== Gradual typing
+You don't *need* to use types in Perl 6. But when you want to use them (for
+making use of multi-dispatch, for example), you can just start using them. If
+types are added, the compiler will make sure the types are correct. If not, you
+can always do them yourself (but why would you, when the compiler can do a
+better job for free).
diff --git a/_posts/2018-03-20-perl6-introduction-to-application-programming.adoc b/_posts/2018-03-20-perl6-introduction-to-application-programming.adoc
new file mode 100644
index 0000000..6759d80
--- /dev/null
+++ b/_posts/2018-03-20-perl6-introduction-to-application-programming.adoc
@@ -0,0 +1,784 @@
+---
+title: "Perl 6 - Introduction to application programming"
+date: 2018-03-20 11:08:00
+tags: Tutorial Perl6 Assixt GTK tutorial programming
+layout: post
+authors:
+ - ["Patrick Spek", "https://tyil.nl"]
+---
+= Perl 6 - Introduction to application programming
+:toc: preamble
+
+In this tutorial, I'll be guiding you through creating a simple application in
+Perl 6. If you don't have Perl 6 installed yet, get the
+http://rakudo.org/how-to-get-rakudo/[Rakudo Star] distribution for your OS.
+Alternatively, you can use the https://hub.docker.com/_/rakudo-star/[Docker
+image].
+
+The application itself will be a simple dice-roller. You give it a number of
+dice to roll, and the number of sides the die has. We'll start off by creating
+it as a console application, then work to make it a GUI as well with the
+`GTK::Simple` module.
+
+== Preparation
+First, you'll want to install the libgtk headers. How to get these depends on
+your distro of choice. For Debian-based systems, which includes Ubuntu and
+derivatives, this command would be the following `apt` invocation:
+
+[source]
+----
+$ apt install libgtk-3-dev
+----
+
+For other distros, please consult your documentation.
+
+To ease up module/application building, I'll use `App::Assixt`. This module
+eases up on common tasks required for building other modules or applications.
+So we'll start by installing this module through `zef`.
+
+[source]
+----
+$ zef install App::Assixt
+----
+
+[NOTE]
+====
+You may need to rehash your `$PATH` as well, which can be done using `hash -r`
+on `bash`, or `rehash` for `zsh`. For other shells, consult your manual.
+====
+
+Next up, we can use `assixt` to create the new skeleton of our application,
+with the `new` subcommand. This will ask for some user input, which will be
+recorded in the `META6.json`, a json-formatted file to keep track of meta
+information about the module. `assixt` should take care of this file for you,
+so you never need to actually deal with it.
+
+[source]
+----
+$ assixt new
+----
+
+=== assixt input
+Since the `assixt new` command requires some input, I'll walk through these
+options and explain how these would affect your eventual application.
+
+==== Name of the module
+This is the name given to the module. This will be used for the directory name,
+which by default in `assixt` will be `perl6-` prepended to a lower-case version
+of the module name. If you ever wish to make a module that is to be shared in
+the Perl 6 ecosystem, this should be unique across the entire ecosystem. If
+you're interested in some guidelines, the
+https://pause.perl.org/pause/query?ACTION=pause_namingmodules[PAUSE guidelines]
+seem to apply pretty well to Perl 6 as well.
+
+For this application, we'll use `Local::App::Dicer`, but you can use whatever
+name you'd prefer here.
+
+==== Your name
+Your name. This will be used as the author's name in the `META6.json`. It is
+used to find out who made it, in order to report issues (or words of praise,
+of course).
+
+==== Your email address
+Your email address. Like your name, it will be used in case someone has to
+contact you in regards off the module.
+
+==== Perl 6 version
+This defaults to `c` right now, and you can just hit enter to accept it. In the
+future, there will be a Perl 6.d available as well, in which case you can use
+this to indicate you want to use the newer features introduced in 6.d. This is
+not the case yet, so you just want to go with the default `c` value here.
+
+==== Module description
+A short description of your module, preferably a single sentence. This is
+useful to people wondering what the module is for, and module managers can show
+to the user.
+
+==== License key
+This indicates the license under which your module is distributed. This
+defaults to `GPL-3.0`, which I strongly recommend to use. The de-facto
+default seems to be `Artistic-2.0`, which is also used for Perl 6 itself.
+
+This identifier is based on the https://spdx.org/licenses/[SPDX license list].
+Anything not mentioned in this list is not acceptable. #TODO Clarify why
+
+== Writing your first test
+With the creation of the directory structure and metadata being taken care of
+by `assixt`, we can now start on writing things. Tests are not mandatory, but
+are a great tool for quickly checking if everything works. If you make larger
+applications, it really helps not having to manually test anything. Another
+benefit is that you can quickly see if your changes, or those of someone else,
+break anything.
+
+Creating the base template for tests, `assixt` can help you out again: `assixt
+touch` can create templates in the right location, so you don't have to deal
+with it. In this case we want to create a test, which we'll call "basic".
+
+[source]
+----
+$ assixt touch test basic
+----
+
+This will create the file `t/basic.t` in your module directory. Its contents
+will look as follows:
+
+[source,perl6]
+----
+#! /usr/bin/env perl6
+
+use v6.c;
+
+use Test;
+
+ok True;
+
+done-testing;
+
+# vim: ft=perl6
+----
+
+The only test it has right now is `ok True`, which will always pass testing. We
+will change that line into something more usable for this application:
+
+[source,perl6]
+----
+use Local::App::Dicer;
+
+plan 2;
+
+subtest "Legal rolls", {
+ plan 50;
+
+ for 1..50 {
+ ok 1 ≤ roll($_) ≤ $_, "Rolls between 1 and $_";
+ }
+}
+
+subtest "Illegal rolls", {
+ plan 3;
+
+ throws-like { roll(0) }, X::TypeCheck::Binding::Parameter, "Zero is not accepted";
+ throws-like { roll(-1) }, X::TypeCheck::Binding::Parameter, "Negative rolls are not accepted";
+ throws-like { roll(1.5) }, X::TypeCheck::Binding::Parameter, "Can't roll half sides";
+}
+----
+
+[NOTE]
+====
+Perl 6 allows mathematical characters to make your code more concise, as with
+the ≤ in the above block. If you use http://www.vim.org/[vim], you can make use
+of the https://github.com/vim-perl/vim-perl6[vim-perl6] plugin, which has an
+option to change the longer, ascii-based ops (in this case `\<=`) into the
+shorter unicode based ops (in this case `≤`). This specific feature requires
+`let g:perl6_unicode_abbrevs = 1` in your `vimrc` to be enabled with
+`vim-perl6`.
+
+If that's not an option, you can use a
+https://en.wikipedia.org/wiki/Compose_key[compose key]. If that is not viable
+either, you can also stick to using the ascii-based ops. Perl 6 supports both
+of them.
+====
+
+This will run 53 tests, split up in two
+https://docs.perl6.org/language/testing#Grouping_tests[subtests]. Subtests are
+used to logically group your tests. In this case, the calls that are correct
+are in one subtest, the calls that should be rejected are in another.
+
+The `plan` keywords indicate how many tests should be run. This will help spot
+errors in case your expectations were not matched. For more information on
+testing, check out https://docs.perl6.org/language/testing[the Perl 6 docs on
+testing].
+
+We're making use of two test routines, `ok` and `throws-like`. `ok` is a
+simple test: if the given statement is truthy, the test succeeds. The other
+one, `throws-like`, might require some more explanation. The first argument it
+expects is a code block, hence the `{ }`. Inside this block, you can run any
+code you want. In this case, we run code that we know shouldn't work. The
+second argument is the exception it should throw. The test succeeds if the
+right exception is thrown. Both `ok` and `throws-like` accept a descriptive
+string as optional last argument.
+
+=== Running the tests
+A test is useless if you can't easily run it. For this, the `prove` utility
+exists. You can use `assixt test` to run these tests properly as well, saving
+you from having to manually type out the full `prove` command with options.
+
+[source]
+----
+$ assixt test
+----
+
+You might notice the tests are currently failing, which is correct. The
+`Local::App::Dicer` module doesn't exist yet to test against. We'll be working
+on that next.
+
+[NOTE]
+====
+For those interested, the command run by `assixt test` is `prove -e "perl6
+-Ilib" t`. This will include the `lib` directory into the `PERL6PATH` to be
+able to access the libraries we'll be making. The `t` argument specifies the
+directory containing the tests.
+====
+
+== Creating the library
+Again, let's start with a `assixt` command to create the base template. This
+time, instead of `touch test`, we'll use `touch lib`.
+
+[source]
+----
+$ assixt touch unit Local::App::Dicer
+----
+
+This will generate a template file at `lib/Local/App/Dicer.pm6` which some
+defaults set. The file will look like this.
+
+[source,perl6]
+----
+#! /usr/bin/env false
+
+use v6.c;
+
+unit module Local::App::Dicer;
+----
+
+The first line is a https://en.wikipedia.org/wiki/Shebang_(Unix)[shebang]. It
+informs the shell what to do when you try to run the file as an executable
+program. In this case, it will run `false`, which immediately exits with a
+non-success code. This file needs to be run as a Perl 6 module file, and
+running it as a standalone file is an error.
+
+The `use v6.c` line indicates what version of Perl 6 should be used, and is
+taken from the `META6.json`, which was generated with `assixt new`. The last
+line informs the name of this module, which is `Local::App::Dicer`. Beneath
+this, we can add subroutines, which can be exported. These can then be accessed
+from other Perl 6 files that `use` this module.
+
+=== Creating the `roll` subroutine
+Since we want to be able to `roll` a die, we'll create a subroutine to do
+exactly that. Let's start with the signature, which tells the compiler the name
+of the subroutine, which arguments it accepts, their types and what type the
+subroutine will return.
+
+[TIP]
+====
+Perl 6 is gradually typed, so all type information is optional. The subroutine
+arguments are optional too, but you will rarely want a subroutine that doesn't
+have an argument list.
+====
+
+[source,perl6]
+----
+sub roll($sides) is export
+{
+ $sides
+}
+----
+
+Let's break this down.
+
+- `sub` informs the compiler we're going to create a subroutine.
+- `roll` is the name of the subroutine we're going to create.
+- `$sides` defines an argument used by the subroutine.
+- `is export` tells the compiler that this subroutine is to be exported. This
+ allows access to the subroutine to another program that imports this module
+ through a `use`.
+- `{ $sides }` is the subroutine body. In Perl 6, the last statement is also
+ the return value in a code block, thus this returns the value of $sides. A
+ closing `;` is also not required for the last statement in a block.
+
+If you run `assixt test` now, you can see it only fails 1/2 subtests:
+
+[source]
+----
+# TODO: Add output of failing tests
+----
+
+Something is going right, but not all of it yet. The 3 tests to check for
+illegal rolls are still failing, because there's no constraints on the input of
+the subroutine.
+
+=== Adding constraints
+The first constraint we'll add is to limit the value of `$sides` to an `Int:D`.
+The first part of this constraint is common in many languages, the `Int` part.
+The `:D` requires the argument to be **defined**. This forces an actual
+existing instance of `Int`, not a `Nil` or undefined value.
+
+[source,perl6]
+----
+sub roll(Int:D $sides) is export
+----
+
+Fractional input is no longer allowed, since an `Int` is always a round number.
+But an `Int` is still allowed to be 0 or negative, which isn't possible in a
+dice roll. Nearly every language will make you solve these two cases in the
+subroutine body. But in Perl 6, you can add another constraint in the signature
+that checks for exactly that:
+
+[source,perl6]
+----
+sub roll(Int:D $sides where $sides > 0) is export
+----
+
+The `where` part specifies additional constraints, in this case `$sides > 0`.
+So now, only round numbers larger than 0 are allowed. If you run `assixt test`
+again, you should see all tests passing, indicating that all illegal rolls are
+now correctly disallowed.
+
+=== Returning a random number
+So now that we can be sure that the input is always correct, we can start on
+making the output more random. In Perl 6, you can take a number and call
+`.rand` on it, to get a random number between 0 and the value of the number you
+called it on. This in turn can be rounded up to get a number ranging from 1 to
+the value of the number you called `.rand` on. These two method calls can also
+be changed to yield concise code:
+
+[source,perl6]
+----
+sub roll(Int:D $sides where $sides > 0) is export
+{
+ $sides.rand.ceiling
+}
+----
+
+That's all we need from the library itself. Now we can start on making a usable
+program out of it.
+
+== Adding a console interface
+First off, a console interface. `assixt` can `touch` a starting point for an
+executable script as well, using `assixt touch bin`:
+
+[source]
+----
+$ assixt touch bin dicer
+----
+
+This will create the file `bin/dicer` in your repository, with the following
+template:
+
+[source,perl6]
+----
+#! /usr/bin/env perl6
+
+use v6.c;
+
+sub MAIN
+{
+ …
+}
+----
+
+The program will run the `MAIN` sub by default. We want to slightly change this
+`MAIN` signature though, since we want to accept user input. And it just so
+happens that you can specify the command line parameters in the `MAIN`
+signature in Perl 6. This lets us add constraints to the parameters and give
+them better names with next to no effort. We want to accept two numbers, one
+for the number of dice, and one for the number of sides per die:
+
+[source,perl6]
+----
+sub MAIN(Int:D $dice, Int:D $sides where { $dice > 0 && $sides > 0 })
+----
+
+Here we see the `where` applying constraints again. If you try running this
+program in its current state, you'll have to run the following:
+
+[source]
+----
+$ perl6 -Ilib bin/dicer
+Usage:
+ bin/dicer <dice> <sides>
+----
+
+This will return a list of all possible ways to invoke the program. There's one
+slight problem right now. The usage description does not inform the user that
+both arguments need to be larger than 0. We'll take care of that in a moment.
+First we'll make this part work the way we want.
+
+To do that, let's add a `use` statement to our `lib` directory, and call the
+`roll` function we created earlier. The `bin/dicer` file will come to look as
+follows:
+
+[source,perl6]
+----
+#! /usr/bin/env perl6
+
+use v6.c;
+
+use Local::App::Dicer;
+
+sub MAIN(Int:D $dice, Int:D $sides where { $dice > 0 && $sides > 0 })
+{
+ say $dice × roll($sides)
+}
+----
+
+[NOTE]
+====
+Just like the `≤` character, Perl 6 allows to use the proper multiplication
+character `×` (this is not the letter `x`!). You can use the more widely known
+`*` for multiplication as well.
+====
+
+If you run the program with the arguments `2` and `20` now, you'll get a random
+number between 2 and 40, just like we expect:
+
+[source]
+----
+$ perl6 -Ilib bin/dicer 2 20
+18
+----
+
+=== The usage output
+Now, we still have the trouble of illegal number input not clearly telling
+what's wrong. We can do a neat trick with
+https://docs.perl6.org/language/functions#index-entry-USAGE[the USAGE sub] to
+achieve this. Perl 6 allows a subroutine with the name `USAGE` to be defined,
+overriding the default behaviour.
+
+Using this, we can generate a friendlier message informing the user what they
+need to supply more clearly. The `USAGE` sub would look like this:
+
+[source,perl6]
+----
+sub USAGE
+{
+ say "Dicer requires two positive, round numbers as arguments."
+}
+----
+
+If you run the program with incorrect parameters now, it will show the text
+from the `USAGE` subroutine. If the parameters are correct, it will run the
+`MAIN` subroutine.
+
+You now have a working console application in Perl 6!
+
+== Making a simple GUI
+But that's not all. Perl 6 has a module to create GUIs with the
+https://www.gtk.org/[GTK library] as well. For this, we'll use the
+http://modules.perl6.org/dist/GTK::Simple:github:perl6[`GTK::Simple`] module.
+
+You can add this module as a dependency to the `Local::App::Dicer` repository
+with `assixt` as well, using the `depend` command. By default, this will also
+install the dependency locally so you can use it immediately.
+
+[source]
+----
+$ assixt depend GTK::Simple
+----
+
+=== Multi subs
+Next, we could create another executable file and call it `dicer-gtk`. However,
+I can also use this moment to introduce
+https://docs.perl6.org/language/glossary#index-entry-multi-method[multi
+methods]. These are subs with the same name, but differing signatures. If a
+call to such a sub could potentially match multiple signatures, the most
+specific one will be used. We will add another `MAIN` sub, which will be called
+when `bin/dicer` is called with the `--gtk` parameter.
+
+We should also update the `USAGE` sub accordingly, of course. And while we're
+at it, let's also include the `GTK::Simple` and `GTK::Simple::App` modules. The
+first pulls in all the different GTK elements we will use later on, while the
+latter pulls in the class for the base GTK application window. The updated
+`MAIN`, `USAGE` and `use` parts will now look like this:
+
+[source,perl6]
+----
+use Local::App::Dicer;
+use GTK::Simple;
+use GTK::Simple::App;
+
+multi sub MAIN(Int:D $dice, Int:D $sides where { $dice > 0 && $sides > 0 })
+{
+ say $dice × roll($sides)
+}
+
+multi sub MAIN(Bool:D :$gtk where $gtk == True)
+{
+ # TODO: Create the GTK version
+}
+
+sub USAGE
+{
+ say "Launch Dicer as a GUI with --gtk, or supply two positive, round numbers as arguments.";
+}
+----
+
+There's a new thing in a signature header here as well, `:$gtk`. The `:` in
+front of it makes it a named argument, instead of a positional one. When used
+in a `MAIN`, this will allow it to be used like a long-opt, thus as `--gtk`.
+Its use in general subroutine signatures is explained in the next chapter.
+
+Running the application with `--gtk` gives no output now, because the body only
+contains a comment. Let's fix that.
+
+=== Creating the window
+First off, we require a `GTK::Simple::App` instance. This is the main window,
+in which we'll be able to put elements such as buttons, labels, and input
+fields. We can create the `GTK::Simple::App` as follows:
+
+[source,perl6]
+----
+my GTK::Simple::App $app .= new(title => "Dicer");
+----
+
+This one line brings in some new Perl 6 syntax, namely the `.=` operator.
+There's also the use of a named argument in a regular subroutine.
+
+The `.=` operator performs a method on the variable on the left. In our case,
+it will call the `new` subroutine, which creates a new instance of the
+`GTK::Simple::App` class. This is commonly referred to as the **constructor**.
+
+The named argument list (`title \=> "Dicer"`) is another commonly used feature
+in Perl 6. Any method can be given a non-positional, named parameter. This is
+done by appending a `:` in front of the variable name in the sub signature.
+This has already been used in our code, in `multi sub MAIN(Bool :$gtk where
+$gtk == True)`. This has a couple of benefits, which are explained in the
+https://docs.perl6.org/type/Signature#index-entry-positional_argument_%28Signature%29_named_argument_%28Signature%29[Perl
+6 docs on signatures].
+
+=== Creating the elements
+Next up, we can create the elements we'd like to have visible in our
+application window. We needed two inputs for the console version, so we'll
+probably need two for the GUI version as well. Since we have two inputs, we
+want labels for them. The roll itself will be performed on a button press.
+Lastly, we will want another label to display the outcome. This brings us to 6
+elements in total:
+
+- 3 labels
+- 2 entries
+- 1 button
+
+[source,perl6]
+----
+my GTK::Simple::Label $label-dice .= new(text => "Amount of dice");
+my GTK::Simple::Label $label-sides .= new(text => "Dice value");
+my GTK::Simple::Label $label-result .= new(text => "");
+my GTK::Simple::Entry $entry-dice .= new(text => 0);
+my GTK::Simple::Entry $entry-sides .= new(text => 0);
+my GTK::Simple::Button $button-roll .= new(label => "Roll!");
+----
+
+This creates all elements we want to show to the user.
+
+=== Show the elements in the application window
+Now that we have our elements, let's put them into the application window.
+We'll need to put them into a layout as well. For this, we'll use a grid. The
+`GTK::Simple::Grid` constructor takes pairs, with the key being a tuple
+containing 4 elements, and the value containing the element you want to show.
+The tuple's elements are the `x`, `y`, `w` and `h`, which are the x
+coordinates, y coordinates, width and height respectively.
+
+This in turn takes us to the following statement:
+
+[source,perl6]
+----
+$app.set-content(
+ GTK::Simple::Grid.new(
+ [0, 0, 1, 1] => $label-dice,
+ [1, 0, 1, 1] => $entry-dice,
+ [0, 1, 1, 1] => $label-sides,
+ [1, 1, 1, 1] => $entry-sides,
+ [0, 2, 2, 1] => $button-roll,
+ [0, 3, 2, 1] => $label-result,
+ )
+);
+----
+
+Put a `$app.run` beneath that, and try running `perl6 -Ilib bin/dicer --gtk`.
+That should provide you with a GTK window with all the elements visible in the
+position we want. To make it a little more appealing, we can add a
+`border-width` to the `$app`, which adds a margin between the border of the
+application window, and the grid inside the window.
+
+[source,perl6]
+----
+$app.border-width = 20;
+$app.run;
+----
+
+You may notice that there's no `()` after the `run` method call. In Perl 6,
+these are optional if you're not supplying any arguments any way.
+
+=== Binding an action to the button
+Now that we have a visible window, it's time to make the button perform an
+action. The action we want to execute is to take the values from the two
+inputs, roll the correct number of dice with the correct number of sides, and
+present it to the user.
+
+The base code for binding an action to a button is to call `.clicked.tap` on it,
+and provide it with a code block. This code will be executed whenever the
+button is clicked.
+
+[source,perl6]
+----
+$button-roll.clicked.tap: {
+};
+----
+
+You see we can also invoke a method using `:`, and then supplying its
+arguments. This saves you the trouble of having to add additional `( )` around
+the call, and in this case it would be annoying to have to deal with yet
+another set of parens.
+
+Next, we give the code block something to actually perform:
+
+[source,perl6]
+----
+$button-roll.clicked.tap: {
+ CATCH {
+ $label-result.text = "Can't roll with those numbers";
+ }
+
+ X::TypeCheck::Binding::Parameter.new.throw if $entry-dice.text.Int < 1;
+
+ $label-result.text = ($entry-dice.text.Int × roll($entry-sides.text.Int)).Str;
+};
+----
+
+There's some new things in this block of code, so let's go over these.
+
+- `CATCH` is the block in which we'll end up if an exception is thrown in this
+ scope. `roll` will throw an exception if the parameters are wrong, and this
+ allows us to cleanly deal with that.
+- `X::TypeCheck::Binding::Parameter.new.throw` throws a new exception of type
+ `X::TypeCheck::Binding::Parameter`. This is the same exception type as thrown
+ by `roll` if something is wrong. We need to check the number of dice manually
+ here, since `roll` doesn't take care of it, nor does any signature impose any
+ restrictions on the value of the entry box.
+- `if` behind another statement. This is something Perl 6 allows, and in some
+ circumstances can result in cleaner code. It's used here because it improves
+ the readability of the code, and to show that it's possible.
+
+== The completed product
+And with that, you should have a dice roller in Perl 6, with both a console and
+GTK interface. Below you can find the complete, finished sourcefiles which you
+should have by now.
+
+=== t/basic.t
+[source,perl6]
+----
+#! /usr/bin/env perl6
+
+use v6.c;
+
+use Test;
+use Local::App::Dicer;
+
+plan 2;
+
+subtest "Legal rolls", {
+ plan 50;
+
+ for 1..50 {
+ ok 1 ≤ roll($_) ≤ $_, "Rolls between 1 and $_";
+ }
+}
+
+subtest "Illegal rolls", {
+ plan 3;
+
+ throws-like { roll(0) }, X::TypeCheck::Binding::Parameter, "Zero is not accepted";
+ throws-like { roll(-1) }, X::TypeCheck::Binding::Parameter, "Negative rolls are not accepted";
+ throws-like { roll(1.5) }, X::TypeCheck::Binding::Parameter, "Can't roll half sides";
+}
+
+done-testing;
+
+# vim: ft=perl6
+----
+
+=== lib/Local/App/Dicer.pm6
+[source,perl6]
+----
+#! /usr/bin/env false
+
+use v6.c;
+
+unit module Local::App::Dicer;
+
+sub roll(Int:D $sides where $sides > 0) is export
+{
+ $sides.rand.ceiling;
+}
+----
+
+=== bin/dicer
+[source,perl6]
+----
+#! /usr/bin/env perl6
+
+use v6.c;
+
+use Local::App::Dicer;
+use GTK::Simple;
+use GTK::Simple::App;
+
+multi sub MAIN(Int:D $dice, Int:D $sides where { $dice > 0 && $sides > 0 })
+{
+ say $dice × roll($sides)
+}
+
+multi sub MAIN(Bool:D :$gtk where $gtk == True)
+{
+ my GTK::Simple::App $app .= new(title => "Dicer");
+ my GTK::Simple::Label $label-dice .= new(text => "Number of dice");
+ my GTK::Simple::Label $label-sides .= new(text => "Number of sides per die");
+ my GTK::Simple::Label $label-result .= new(text => "");
+ my GTK::Simple::Entry $entry-dice .= new(text => 0);
+ my GTK::Simple::Entry $entry-sides .= new(text => 0);
+ my GTK::Simple::Button $button-roll .= new(label => "Roll!");
+
+ $app.set-content(
+ GTK::Simple::Grid.new(
+ [0, 0, 1, 1] => $label-dice,
+ [1, 0, 1, 1] => $entry-dice,
+ [0, 1, 1, 1] => $label-sides,
+ [1, 1, 1, 1] => $entry-sides,
+ [0, 2, 2, 1] => $button-roll,
+ [0, 3, 2, 1] => $label-result,
+ )
+ );
+
+ $button-roll.clicked.tap: {
+ CATCH {
+ $label-result.text = "Can't roll with those numbers";
+ }
+
+ X::TypeCheck::Binding::Parameter.new.throw if $entry-dice.text.Int < 1;
+
+ $label-result.text = ($entry-dice.text.Int × roll($entry-sides.text.Int)).Str;
+ };
+
+ $app.border-width = 20;
+
+ $app.run;
+}
+
+sub USAGE
+{
+ say "Launch Dicer as a GUI with --gtk, or supply two positive, round numbers as arguments.";
+}
+----
+
+== Installing your module
+Now that you have a finished application, you probably want to install it as
+well, so you can run it by calling `dicer` in your shell. For this, we'll be
+using `zef`.
+
+To install a local module, tell `zef` to try and install the local directory
+you're in:
+
+[source]
+----
+$ zef install .
+----
+
+This will resolve the dependencies of the local module, and then install it.
+You should now be able to run `dicer` from anywhere.
+
+[WARNING]
+====
+With most shells, you have to "rehash" your `$PATH` as well. On `bash`, this is
+done with `hash -r`, on `zsh` it's `rehash`. If you're using any other shell,
+please consult the manual.
+====
diff --git a/_posts/2018-05-07-sparrowdo-getting-started.adoc b/_posts/2018-05-07-sparrowdo-getting-started.adoc
new file mode 100644
index 0000000..7164c6b
--- /dev/null
+++ b/_posts/2018-05-07-sparrowdo-getting-started.adoc
@@ -0,0 +1,231 @@
+---
+date: 2018-05-07 14:04:43
+tags: Tutorial Tutorial Perl6 Sparrowdo GettingStarted
+description: >
+ Nondescript
+---
+= Sparrowdo - Getting started
+:toc: preamble
+
+https://github.com/melezhik/sparrowdo[Sparrowdo] is a Perl 6 project to
+facilitate automatic configuration of systems. There's a
+https://sparrowhub.org/[repository of useful modules] to make specific cases
+easier to work with, but the
+https://github.com/melezhik/sparrowdo/blob/master/core-dsl.md[Core DSL] can
+already take care of many tasks. In this tutorial, I'll guide you through
+setting up Sparrowdo, bootstrapping it onto your local system, writing a task
+and running it.
+
+== Install Sparrowdo
+Sparrowdo is a http://perl6.org/[Perl 6] project, so you'll need to have Perl 6
+installed. We'll also use the Perl 6 package manager
+https://github.com/ugexe/zef/[zef] to install Sparrowdo itself. Luckily for us,
+there's a stable distribution of Perl 6 with everything we need added to it,
+called https://rakudo.org/files[Rakudo Star]. And to make it easier for
+GNU+Linux users, I wrote a tool to fetch the latest Rakudo Star release, compile
+it and install it, called https://github.com/Tyil/lonestar[LoneStar]. Since this
+tutorial will aim at GNU+Linux users, I'll use that to install Perl 6.
+
+=== Installing Perl 6 with LoneStar
+LoneStar is a Bash application to download, compile and set up Perl 6. It's a
+standalone application, meaning you don't have to install it to your system. You
+can just run it from the source directory. First, we'll have to get the source
+directory, which we'll do using `git`.
+
+[source,sh]
+----
+mkdir -p ~/.local/src
+git clone https://github.com/tyil/lonestar.git ~/.local/src/lonestar
+cd !$
+----
+
+Now you have the LoneStar sources available in `~/.local/src/lonestar`. You can
+run the application using `./bin/lonestar`. Running it, you'll get some help
+output:
+
+[source]
+----
+$ ./bin/lonestar
+lonestar - Installation manager for Rakudo Star
+
+Usage: lonestar <action> [arguments...]
+
+Actions:
+ help [action]
+ init [version=latest]
+ install [version=latest]
+ path [version=latest]
+ reinstall [version=latest]
+ upgrade
+----
+
+We'll be needing the `install` action to get Perl 6 installed, and the `init`
+action to configure the `$PATH` environment variable. Depending on your
+hardware, `install` may take a couple minutes as it will compile Rakudo Perl 6
+and install some base modules. You might want to grab a drink during this
+period.
+
+[source]
+----
+$ ./bin/lonestar install
+$ eval $(./bin/lonestar init)
+$ perl6 -v
+This is Rakudo Star version 2018.04.1 built on MoarVM version 2018.04.1
+implementing Perl 6.c.
+----
+
+[NOTE]
+====
+If there's a newer version available of Rakudo Star, the version numbers given
+by `perl6 -v` will differ for you.
+====
+
+=== Installing Sparrowdo with zef
+Now that you have Perl 6 available and installed, you can continue on using
+`zef` to install Sparrowdo. `zef` is bundled with Rakudo Star, so you don't have
+to do anything to get it working.
+
+[source,sh]
+----
+zef install Sparrowdo
+----
+
+This will instruct `zef` to install Sparrowdo and all its dependencies. This can
+take a couple minutes, again depending on the hardware of your machine.
+
+== Bootstrapping your system
+The first step to working with Sparrowdo is bootstrapping the system you wish to
+use it with. In this case, that'll be the local system. There's a `--bootstrap`
+option to do this automatically.
+
+[source,sh]
+----
+sparrowdo --bootstrap
+----
+
+[TIP]
+====
+If you wish to bootstrap a remote system, you can use the `--host` option to
+specify the system. For example: `sparrowdo --host=192.168.1.2 --bootstrap`.
+====
+
+Now your system is ready to be configured automatically using Sparrowdo!
+
+== Sparrowfiles
+Sparrowfiles are the files that describe the tasks Sparrow should execute to
+get you the configuration you want. They are valid Perl 6 code, and call the
+subroutines (or _sparrowtasks_) that will handle the actual actions. By default,
+when running `sparrowdo`, it will look for a file named `sparrowfile` in the
+current directory.
+
+To make our sample, we'll create a new directory to work in, so we have clean
+directory that can be shared easily. You can also keep this directory under
+version control, so you can distribute the `sparrowfile` with all its templates.
+
+[TIP]
+====
+If you just want to create an empty directory to test things in, without
+"polluting" the rest of your system, just call `cd -- "$(mktemp -d)"`. This will
+create a temporary directory and change the working directory to there.
+====
+
+I'll be using `~/.local/sparrowdo/local-dns` to work in, as I'll be setting up a
+local dns cache with http://www.thekelleys.org.uk/dnsmasq/doc.html[dnsmasq] for
+the sample code.
+
+=== Writing a `sparrowfile`
+As noted in the previous paragraph, for the sake of a demo I'll guide you
+through creating a `sparrowfile` to install and configure `dnsmasq` as a local
+DNS cache. Using your favourite `$EDITOR`, write the following to `sparrowfile`:
+
+[source,perl6]
+----
+package-install "dnsmasq";
+directory "/etc/dnsmasq.d";
+file-create "/etc/dnsmasq.conf", %(content => slurp "dnsmasq.conf");
+file-create "/etc/dnsmasq.d/resolv.conf", %(content => slurp "resolv.conf");
+service-start "dnsmasq";
+----
+
+This `sparrowfile` will set up the following configuration for `dnsmasq`:
+
+- Install the `dnsmasq` package
+- Create the `/etc/dnsmasq.d` directory in which we'll store configuration files
+ for `dnsmasq`
+- Create the configuration files `dnsmasq.conf` at `/etc/dnsmasq.conf`
+- Create the `resolv.conf` in the `dnsmasq.d` directory
+- Start the `dnsmasq` service
+
+The configuration files will be created based on the configuration files in the
+current directory. So for this to work, you'll need to also create the
+appropriate configuration files. Let's start off with the main `dnsmasq`
+configuration in `dnsmasq.conf`:
+
+[source,conf]
+----
+listen-address=127.0.0.1
+
+no-dhcp-interface=
+resolv-file=/etc/dnsmasq.d/resolv.conf
+----
+
+This will make `dnsmasq` listen on the loopback interface, so it'll only be able
+to be used by the local machine. Furthermore, DHCP functionality will be
+disabled, and the upstream resolvers are read from `/etc/dnsmasq.d/resolv.conf`.
+The contents of that file are as follows:
+
+[source,conf]
+----
+nameserver 37.235.1.174
+nameserver 37.235.1.177
+----
+
+These nameservers are part of the https://freedns.zone/en/[FreeDNS] project. You
+can of course use whatever other DNS provider you want to use as your upstream
+servers. Now, for `dnsmasq` to be used, you will also need to set your machine's
+DNS resolvers to point to the `dnsmasq` service. This is defined in
+`/etc/resolv.conf`, so lets append the following to our `sparrowfile` to set
+that up.
+
+[source,conf]
+----
+bash "chattr -i /etc/resolv.conf";
+file-delete "/etc/resolv.conf";
+file-create "/etc/resolv.conf", %(content => "nameserver 127.0.0.1");
+bash "chattr +i /etc/resolv.conf";
+----
+
+This will remove the "immutable" attribute from `/etc/resolv.conf` if it's set.
+Next it will remove the current `/etc/resolv.conf` and write out a new one which
+only refers to the local machine as DNS resolver. This is to ensure an existing
+`/etc/resolv.conf` gets recreated with the configuration we want. Finally, it
+adds back the immutable attribute to the file, so other processes won't
+overwrite it.
+
+=== Running the `sparrowfile`
+To run the `sparrowfile` and get the setup you desire, run the `sparrowdo`
+command with `--local_mode` and wait.
+
+[source]
+----
+sparrowdo --local_mode
+----
+
+[NOTE]
+====
+If you want to run this on a remote machine to configure that one instead, you
+can use `--host=<ip>` instead of `--local_mode`.
+====
+
+You can check whether it actually worked by inspecting the files in
+`/etc/dnsmasq.d` and your `/etc/resolv.conf`. The easiest way to check their
+contents would be by using `cat`:
+
+[source]
+----
+cat /etc/dnsmasq.d/dnsmasq.conf
+cat /etc/dnsmasq.d/resolv.conf
+cat /etc/resolv.conf
+----
+
+== Closing words