The final step in migrating ‘everything-email’ from my old server to a kubernetes setup is the migration of mailing lists based on mailman. In previous posts, I migrated the core mailserver and webmail to kubernetes. It s recommended to read the first post first because that one explains the full mail system architecture and dependencies. In this post we will be focusing on the last part, which is migrating mailman.
This is a continuation of my earlier post on migrating my mailserver to kubernetes. The next component of my mail setup to migrate is webmail. In the past I used squirrelmail for this, so I started with investigating that. However, it turns out that the squirrelmail project does not provide any docker containers. There are some containers you can get from docker hub, but these are largely unmaintained and are mostly private projects. After some looking around I found roundcube. Quick prototyping with roundcube containers, provided by the roundcube project, using docker compose showed that it was not difficult to get it to work.
It has been a long time since I setup a mail server. It started with my first mailserver on linux somewhere in 2000 using sendmail and University of Washington IMAP. This setup was assuming mail delivery to local system users. In other words, every e-mail had to correspond to a local system user. Getting it working was absolute hell, but it finally worked. Sendmail in particular seemed not to behave according to the documentation.
Then in 2006 my next setup was based on postfix and cyrus IMAP, decoupling mail boxes from system users. I bought a book about postfix and read it front to cover before starting. This was a much more pleasant experience. However, this was also not without fights in getting basic stuff to work. Over time, I added black listing, grey listing, and spam detection to the setup. I also added a webmail user interface using squirrelmail later on. Finally, my ISP increased security and my mails often would get rejected. To fix this, my ISP required my to relay outgoing mail through their mail server and it turned out my postfix version was too low and could not handle it. I made a quick workaround for that by relaying outgoing mail to a newer postfix mail server running on another virtual server in my network. Problem solved, but it was getting painfully clear that the old setup was nearing its expiration date.
However, now it is time to say goodbye to this old setup. As part of my home project to migrate every workload from VMs to containers using kubernetes this is an ideal chance to get a new setup. Still a lot of respect for these older versions of cyrus and postfix for running for such a long time (16 years!) with basically zero maintenance. Would it be easier now, after all this time, to setup a new mail system? (spoiler alert: yes).
As part of moving everything that is running in VMs on my server to kubernetes, the old wordpress installation had to be migrated to kubernetes as well. The website was previously running in a linux container based on systemd-nspawn, using a container which is basically running a full linux OS, including database.
The intention of the old setup was to move wordpress hosting away from an old server that also contained some private data. The intention was damage control by reducing the consequences of a hack of my wordpress website. At that time, my experiences running docker were not that positive regarding stability, so I chose to use standard linux containers with a simple interface on top called systemd-nspawn. Now, a few years on, the whole container ecosystem has matured, and now there are better ways to run containers such as kubernetes.
As mentioned in my previous post I would follow up with a tool for testing network policies. This tool is finally here and is available on github. It is written in python an available through install on PyPi.
An often overlooked topic in kubernetes is network security. This is probably caused by the fact that perople just assume it is secure by default because it is new, and because of the Service concept. The standard way to expose a service running in a pod is to create a Service for it and then reference the service from the consuming pod using its name. The advantage of this is that the service has a DNS name and also provides a fixed IP towards consumers, regardless of how many pods are running for this service or whether pods get deleted and created. However, direct communication between pods is possible by default.
This exposes a serious security issue if this network access is not restricted. This is because it would allow lateral movement by a hacker from one pod to the next since all ports are open. In particular, also access to the kubernetes API service is not restricted and pods, by default (!), also contain the mounted secrets for the service account.
As part of migrating all the stuff I have from virtual machines to a kubernetes infrastructure, some important pieces of infrastructure are needed. These are:
- RPM repository: I use custom RPM repositories for setting up virtual machines. These same RPMs are used for building container images that are required by kubernetes
- Docker repository: Custom docker images may be required for kubernetes
Since I want to run everything at home and make minimal use of internet services for my setup, I need to deploy solutions for this on my kubernetes cluster. Currently, I already use an RPM repository based on Nexus 2. In the mean while, a lot has happened. For instance Nexus 3 now natively supports RPM repositories and it also supports docker repositories. Therefore, as part of the setup, I need to run Nexus 3 and move all my RPM artifacts over from Nexus 2 to Nexus 3.
These days, it is ill-advised to run a website (such as this one), over HTTP, even if there is no security risk at all. When hosting your website on HTTP, users will see a warning triangle in the address bar and many users will simply turn away. This is especially painful if the website is blogging on devops and security related things.
Currently, I am migrating everything I have locally to a more secure and future proof setup from VMs to kubernetes. The approach I decided to take is to start with the front-facing services and move everything from there step by step. Therefore, the first step is to move the reverse proxy from a VM to kubernetes. Since I don’t want to pay for certificates, I will be using Let’s Encrypt. Unfortunately, Let’s Encrypt only supports 90 day certificates so this means a lot of certificate renewals.
This post explains how to host services on Google Compute Engine, parts of this are applicable to regular (non-GKE) Kubernetes clusters as well. This post will cover:
- allowing multiple services to be deployed in different namespaces
- allowing multiple (sub)domains to be deployed
- making a service available through a public and fixed IP accessible using a host name
- making it accessible over HTTPS using a certificate
- HTTP redirect to HTTPS
The treatment of the subject is a bit high level with focus on what resources and fields are relevant and on the way different Kubernetes resources relate to each other. Also some snippets of YAML configuration are given. This should be sufficient to ‘roll your own’.
There is a special type of mortgage in the Netherlands (Bank Savings Mortgage or bankspaarhypotheek in Dutch), which I presume, does not exist anywhere else in the world. The construct is that you have a mortgage on your house for a certain amount, say 200000 €, and split it up into two parts:
- one part with a loan (in this case 200000), where you pay only interest
- a second part which is a savings account.
Usually both of these accounts have the same interest rates and you pay a fixed amount per year so that in the end the savings account can be used to pay off the loan. For the bank, this construct is exactly identical to having just one account with a loan that is paid off like an annuitary mortgage with a fixed amount per month.
The difference is in the way this type of mortgage is taxed. On the loan part, the interest is tax deductable, and the savings account is not taxed at all. Therefore in comparison with an annuitary mortgage, where the loan gets less over time (it is equivalent before taxes), there is more tax deduction. And this is what makes it an attractive type of mortgage.
With this type of mortage it is possible to pay off parts of the loan part or to add extra money to the savings account. When given a choice, adding a given amount to the savings account is a lot more attractive than using it to pay off the mortgage. Even though it is equivalent to the bank, putting it into the savings account leads to a higher tax deduction.
But of course, the government has put forward some rules to prevent people from profiting too much, and these make it challenging to determine an optimal scheme to pay of the mortgage to minimize total payments made. For this purpose, this post examines a simple Mixed Linear Integer Program (MILP). Continue reading