Successfully unfucking a fucked partition set in an A/B android device

I own a very nice piece of plastic and chips since the end of 2018. My previous smartphone was a shiny almost-everlasting Nexus 5, that unfortunately fall out of the grace of its creators (google + LG stopped to provide updates a long time ago, but the community of OSS tinkerers maintained an updated version of LineageOS for a while). I bought a OnePlus 6 to replace it, hoping to find a very similar experience: full of support from the LineageOS community and easily rootable.

Turned out I was quite wrong, but the OSS community is not to blame. The main source of pain has come from the new A/B layout of the partitions in android.

TL;DR

Having care of replacing the value for healthy_part with the correct one for your case, use this script from recovery, entering via adb shell

healthy_part="a"
if [[ "$healthy_part" == "a" ]]; then
  broken_part="b";
else
  broken_part="a"
fi
for part in /dev/block/by-name/*_$healthy_part; do
  source=$(readlink -fn $part)
  dest=$(readlink -fn ${part%%_$healthy_part}_$broken_part
  if ! [[ "$dest" == *"/data"* ]]; then
    dd if=$source of=$dest
    echo "done: $source -> $dest"
  fi
done

The long version

Since the beginning, I bought this smartphone with the idea of using it with LineageOS, hoping to easily add a su binary as an easy add-on. This is not the case, if one wants to have a usable phone with banking and identity-sensitive apps. The modern© way to do it is using Magisk. I was also bound to install the google apps (universally called Gapps), because many apps do expect to find such services on the phone and the lovely homebrewed microG project is quite dead.

All this comes to a cost. The process I was supposed to follow is the following:

      1. Unlock the bootloader
      2. Restart into the bootloader (turn off the phone and then start long pressing the power button + volume up button)
      3. Start the phone using a custom recovery (I used TWRP, with<sudo fastboot boot path_to_twrp.img)
      4. Install LineageOS (either sideloading it or pushing it with adb push lineageos.img /sdcard and then using the install menu)
      5. (HERE IS THE IMPORTANT BIT) Reboot to recovery AND install first the Gapps and then Magisk, either by sideload or pushing the zips as the previous point

Why the last step is so important? Because of this A/B layout. The thing is that, when installing the update for the OS (in this case, the lastest LineageOS that replaces OxygenOS), the installer is performed on the inactive partition. Which partition it is, depends on the currently active one. If you are, let’s say, on the A partition when rebooting to bootloader, such is the active partition. In this case, the update will be flashed on the B partition. But we want to install the Gapps and the Magisk magic before the first boot into the new, updated, system. This because both these applications do have some sort of high privilege and make changes to the system partition and, as such, are needed before the first boot of the new OS. But both the Gapps and Magisk installer act on the currently active partition. If we’d install them right after installing the update, we’d be installing them to the A partition, the one that has not been touched by the update!

Flow to upgrade to LineageOS with Gapps and Magisk
Flow to upgrade to LineageOS with Gapps and Magisk

At the end of this process, after the first successful reboot into partition B, the OS updates itself onto A. What bothers me is that I am not aware if this is the case also with the Gapps and Magisk.

Missing flow for Gapps and Magisk
Missing flow for Gapps and Magisk

Useless to say, this is not what I did and I have evidently fucked up at some point in time. After many failed upgrade attempts, with an apparently random failure rate, I got all that I wrote above, and realized that only the A partition set was healthy (because it was the only I was able to upgrade) and that the B was somehow fucked up.

The fix

I remembered that the nice LineageOS people gave the people the possibility to copy all the set of A partitions to the B set. This because, sometimes, the OEM (the phone manufacturer) shipped the handset with only one set of partitions, the A one, clean and working, and to be sure to reach a working state after upgrading to LineageOS, they devised that the right thing was to pour in all the A partitions content into the B ones. I looked into the script and extracted the only part I needed, taking care of avoiding any partition that was not directly mapped to a block device (therefore filtering out the partitions linked to an .img file on the data partition).

I hope you won’t never need it. Nevertheless, if you got here, you’re welcome.

Why so much ado with crates.io?

Disclaimer

If you stumbled upon this post, coming from crates.io, I am sorry. This is just a little sleight of hand to raise the issue on the (absence of) policy choices in crates.io.

I am aware of this part of the Policies:

Using an automated tool to claim ownership of a large number of package names is not permitted. We reserve the right to block traffic or revoke ownership of any package we determine to have been claimed by an automated tool.

I am fine if any of the crates created with the small tool I’ve assembled, and spammed through this github user, are removed altogether.

What did you do?

I created a small cli utility that leverages the cargo crates and spams crates.io with almost-empty crates, varying only the name. The names may be generated at random, or read from a file (and in this case, may be mangled, as to find unused crate names to be used in typosquatting attacks).

I then used this tool to publish some crates. The first ones were tests of the tool, using the random source, then I proceeded using the mangling feature on the most popular crates.

Why did you do that?

I recently discovered a crates.io user that registered some 3 years ago some crate with names that are common English words. This is not the only squatter around the registry, but the description of each registered crate sounds quite offensive to me

WIP. Contact me if you want to use this name!

I promptly engaged with the crates.io team, but I was bounced to this closed issue about this very same user, which then referenced to this stale eRFC from 2018, where an experimental moderator team for crates.io is proposed (at the time of writing, the issue is open but the last comment is from Jun 11, 2020).

I understand that rust, and then the crates.io repository, was born inside Mozilla with limited resources. I also understand that moderating and policing is a very time-consuming and potentially frustrating activity (I myself wouldn’t feel comfortable in doing it). Nevertheless, rust is not anymore a Mozilla-only backed project, and indeed it has been embraced by a number of big corps around the world (and many laid down by Mozilla have been hired by some of those very same big corps, but I digress).

To add more on this: this issue seems a dejavu from a previous incident I did know nothing about.

What then?

I understand this is a delicate matter to face, and I don’t feel qualified to point to any specific solution. This seems to me the result of a questionable design choice, namely the absence of namespacing. This is still an open issue and there is no consensus on how to proceed (see here and here and here).

As I said above, my aim is to raise this issue. I am comfortable with all the packages I generated with the tool I wrote being removed from the registry by the crates.io team. I also want to point out that all the crates I registered that are dangerously similar to other very popular crates have a benign purpose (and I feel more easy about them being under my control than some other malicious actor).

I closed the issue section on the code repository, but feel free to drop me an email (but please, don’t be rude).

Edit

The account I used is currently locked

Failed to log in: This account is indefinitely locked. Reason: Using a script (https://github.com/blallo/xkcd-386) to reserve crate names is against our policies.

Edit 2 (20211122)

Apparently, something is happening among the rust teams. I am not able to say how much this is related to the aforementioned issue.

The resignation letter from the rust moderation team
The resignation letter from the rust moderation team

 

Academia and capitalism

With this post I try to materialize some thoughts that have been in my head since I quit academia. The reason why I am doing it now, 6 years after I parted ways with professional research, comes from this twitter thread (from an account I have never heard of, but the content tickled me). While I sympathize with the author and deeply feel for his o her condition, my purpose is to show the underlying elitist assumptions and criticize some of its conclusions.

I report it here in full quote:

Academic Job Discourseᵀᴹ is back (it’s never gone).

Tl;dr: There are no jobs.

Headline: Commodification of academia has decoupled the value of research from the chance of employability.

Long read: Research and teaching simply cannot be conducted on business principles… 1/

…but since the marketization of the higher education sector, the output in academia *is* reviewed according to capitalist principles. In effect we are led to believe that people producing research output (primarily social capital: what allows the society to run) should be… 2/
…employed according to the principles of the market. This is insane. There is no „market saturation“ of palaeographers or biochemists. The number of people researching a particular topic or discipline cannot be dependent on the perceived market value of their output. 3/
But in effect researchers (whose output is not monetary capital) are forced to compete for the right to conduct their research as if it was. This causes a severe deficit of jobs and job market becomes job lottery. 4/
This has to be presented as a meritocratic competition because the system will only sustain itself if enough brilliant minds buy the lottery tickets (do PhDs, publish, teach and research in precarious posts). 5/
The technological progress in research is not a byproduct of the marketization. Accessibility of data changes nothing in the sheer knowledge and training needed to assess it in order to produce actual *research*. 6/
The progressive drive to monetize research output (sth that can be given a price, sure, but this price will always be *completely* arbitrary) causes basic research and teaching posts to first precarise and then disappear (no „market value“) 7/
This process only inflates the lottery model making brilliant researchers leave their fields not because they didn’t produce good work but because they didn’t have the resources to keep buying the lottery tickets (they couldn’t survive the precarity any longer) 8/
In completely marketized systems (UK for example) this leads to sharp decline in student numbers in those areas (students are forced to pay large sums of money and thus forced to treat the education system like the stock market) This allows to further limit the number of jobs. 9/
This system allows also monetary exploitation of researchers‘ output and skills through the academic publishing system. Articles become lottery tickets first, research capital second. 10/
A few points on this first:
  • I agree with the idea that it is wrong to try to give a monetary (or market) value to the scientific output of someone/some group
  • I lived on my body what here is called job lottery
  • While it is nonsensical to try to monetize abstract or highly theoretical research, there is basic research with a direct market value (I am thinking to biomedical research, but also to material science, for example)
  • The twitter lyric/canon is awful, especially to convey ideas and themes like this that would deserve some more room for reasoning

Caveat

I am not willing to uphold any capitalistic or econometric point of view here, for example that there is a meaningful way to attribute a value to anything. But. I see as necessary to face at least the matter of the cost related to research.

The argument runs on a slippery slope, so let me be clear: I don’t want to say that one must conform his or her aspirations to the expectations of society.

Last warnings:

  • here I often use science as a container term that should also be understood as culture and knowledge
  • the way I use the term society is very fuzzy, and I don’t mean to assume that we all agree on the fact that anyone of us is comfortable in being encased in a catch-all concept (I would not), but it is a handy way to indicate our collective mean action as species

The issue

There is a problem that is apparent: having a work in research is a privilege, given someone manages to enter such elusive realm, having overcome the issues clearly expressed in the thread. It is a privilege not only because, as noted, research jobs are scarce and accessing it is a lottery, but also because the possibilities one has to win the lottery are closely related to the class one belongs to. As paraphrased in the cited thread, the more lottery tickets you can buy, the more chances you have to win. This is closely related to, for example, how many years one can manage to survive with precarious jobs, often accepting to relocate in a different nation, maybe a different continent, every 2-3 years.

This is not entirely a matter of class, of course. Assuming academic evaluation to be fair with respect to someone’s class (spoiler: it is not), it is a very personal stance to accept a life like this.

Social expectations

But moving from the personal kind of issues, there are also social ones: a job in research is, usually, well paid. Research activity itself is costly, especially experimental research (because of, you know, experiments; they are usually costly). All of this is often financed with money from states’ budged (by state here I mean nation states). When it is not, it comes from private endeavor. Such funds are not for free, in the sense that the ones (both private and public) giving this money away seek something in return from the professional researcher. As noted in the thread, it’s quite nonsensical trying to quantify research, but this comes from the need to justify the amount of investment made in some specific research, by means of the aforementioned money.

So, what does the lenders (and society at large, we might say), do expect from a research professional?

  • Measurable output (publications, patents, conferences)
  • Teaching (i.e. the transmission of one’s specialized knowledge in the field of study)
  • (ever more frequently) Public outreach (in the form of social media active presence, public speaking as a recognized expert, popular books on the matter)

I may say nothing here is unreasonable: given that the possibility to earn a living with science is mainly a public (or private, for what matters) founded activity, one might very well cope with these obligations. The main problem here is that the amount of money society puts into science is limited and, to decide how to distribute it, a very nasty concept is used: value.

Value?

The way value is attributed to this research is, in my humble opinion, ludicrous, and I’ve seen quite a few times the young professional scientists season into either the research workforce manager or, even worse, some form of sales representative for his or her own research line. I don’t mean to judge anyone with this words. I am not in a different position now: having chosen to enter professional software industry does not shield me from the very same critiques. Nevertheless, the ideal conception I upheld once about the brave intellectual, working for the sake of human knowledge advancement, armed only with the clarity of pure reasoning and scientific honesty…has been notched a bit along the way.

Back to the value, is is often a matter of either: potential return of investment, mainly in research fields that may have practical industrial applications (material science, biomedical research, computer science to name a few); or brag (i.e. the possibility for the moneylender to boast the achievement as its own praiseworthy and wise choice) ((I am admittedly ignoring political motivations, for example when a research line is encouraged (read: financed) for some political aim, to lay ground for some claim shielded by some scientific research (as if this worlds have become the new way of saying that some endeavor is the will of God). I am assuming such motivations alone are enough to undermine the assumption of honesty any research needs to be defined scientific.)).

While these reason are laughable in light of pure scientific advancement, they determine, together with the underlying omnipresent drive for profit, the main research lines in every scientific field I know.

So what?

Where all these rumblings meet ends with the academic career stuff? The fact is that there is paucity of jobs in research is true. What upsets me is that it is often met with contempt the idea to seek a job outside research. Why should a brilliant mind™©® like those who roam the highness of reason descend into this purgatory of everyday people ((As it is noticeable from the last words, I might be a bit resentful with that world.))?

Being employed in research is a privilege, and should be understood as such. While I embrace fully the idea that society should invest more and more in research and education, this is not the current reality. And I would also love to see demands of wealth redistribution from that side, asking more funds to be taken from the wealthy (using wealth and not income as indicator).

So, to me is unacceptable the idea that one can safely live thinking that his or her position of privilege are just and deserved, just because one managed to sneak into the right place.

It also seems arrogant the very premise of the thread. Let me paraphrase in this way: because science is the truth and the highest human activity, it is of course reasonable that the best minds want to do science, so be scientist fed and be science nurtured ad libitum.

The assumption should be inverted: science is not a market because of the output it produces, but (mainly) because of the demand the community of scientists has to keep on existing. This generates competition for the (scarce) resources: money and jobs.

Should I suffer?

Let me finish, going back to the personal aspect of this quarrel.

This is obviously far fetched and does not apply in equal measure to anyone, but the issue here seems to be twofold:

  1. from one side a research professional, while in the game (i.e. while still holding a job in academia) may fairly fear that leaving academia and finding an employment outside of it automatically corresponds to a devaluation of his or her professional value, and that it will not be possible to fully take advantage of the knowledge acquired in any other job;
  2. even more, the fundamental question might be “why should I give up my privilege? why should I assume I have not earned it?”.

As for the first point, I might humbly point out that this is an issue shared by any elitist profession: the professional dancer or musician, artists in general suffer the very same dilemma.

I might also note that the very narrow sectors that attract interest from some industry have the opposite problem to paucity ((toc toc: AI and machine learning PhDs, I am thinking of you)), academia suffers such a heavy competition from the world of production that retaining people into academia is a problem ((because you know, academia pays well, but FAANG pays waaaaaaaaay better)).

Regarding the latter, I let the easy task of answering the question to the reader ((Before thinking I am a total douchebag, let be reminded that this is the pun used in most scientific books (mainly in mathematics or quantitative sciences) by the authors to encourage the readers reflecting autonomously into the matter under consideration)).

Note for all my friends still into research

I am sorry, this might have sounded rough and unfair, especially for the many that are keeping hard, working in research and living a tough life because they are doing what they love. These words are not aimed at hurting you. But I feel this is the best approximation I could paint of the current state of life in research. You are (as always) very welcome to send me your thought, also the harsh ones.

TIL: apcupsd wants no device

After some time, I found this very useful piece of information, on how to make function again apcupsd. The gotcha is this

you should change DEVICE /dev/ttys0 to DEVICE in /etc/apsupsd/apsupsd.conf with nothing after it, this way apcupsd search everywhere on the system to find the UPS and connect correctly

Thanks internet!

TIL: Dovecot stubbornness

Today I learned that restarting dovecot with the systemd unit provided by debian (on buster) is not enough to reload the configuration.

systemctl restart dovecot

I had to manually run

doveadm reload

Then I realized that this is integrated in the systemd unit, using reload instead of restart:

[Unit]
Description=Dovecot IMAP/POP3 email server
Documentation=man:dovecot(1)
Documentation=http://wiki2.dovecot.org/
After=local-fs.target network-online.target

[Service]
Type=simple
ExecStart=/usr/sbin/dovecot -F
PIDFile=/var/run/dovecot/master.pid
ExecReload=/usr/bin/doveadm reload
ExecStop=/usr/bin/doveadm stop
PrivateTmp=true
NonBlocking=yes
ProtectSystem=full
ProtectHome=no
PrivateDevices=true

# You can add environment variables with e.g.:
#Environment='CORE_OUTOFMEM=1'
# If you have trouble with `Too many open files', increase
LimitNOFILE=65535
# If you want to allow the Dovecot services to produce core dumps, use:
#LimitCORE=infinity

[Install]
WantedBy=multi-user.target

Starting the erlang observer from within a docker container

I am currently working with elixir. It is a neat language, with a lot of good tooling. It’s rooted in the erlang world. A very useful tool to have some overview on the internals of the BEAM is the erlang observer.

Nowadays, the common workflow relies on containers. It is a very common issue to try to start graphical applications from within a container. Let’s prepare a playground

FROM elixir:1.10.4

ARG uid=1000
ARG gid=1000

RUN groupadd -g ${gid} alchymist \
    && useradd -u ${uid} -g alchymist alchymist \
    && mkdir -p /test \
 && chown alchymist:alchymist /test

USER alchymist
WORKDIR /test

ENTRYPOINT ["iex"]
CMD []

We can build it with

docker build --build-arg=uid=$(id -u) --build-arg=gid=$(id -g) -t alchymist:0 .

Let’s start normally

docker run --rm -ti alchymist:0

Trying to start the observer, we get an error

Erlang/OTP 22 [erts-10.7.2.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [hipe]

Interactive Elixir (1.10.4) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> :observer.start()
09:46:02: Error: Unable to initialize GTK+, is DISPLAY set properly?
                                                                    {:error,
 {{:einval, 'Could not initiate graphics'},
  [
    {:wxe_server, :start, 1, [file: 'wxe_server.erl', line: 65]},
    {:wx, :new, 1, [file: 'wx.erl', line: 115]},
    {:observer_wx, :init, 1, [file: 'observer_wx.erl', line: 107]},
    {:wx_object, :init_it, 6, [file: 'wx_object.erl', line: 372]},
    {:proc_lib, :init_p_do_apply, 3, [file: 'proc_lib.erl', line: 249]}
  ]}}
iex(2)>

The trick is to mount the needed files and pass the correct value for the environment variable DISPLAY.

docker run --rm \
    -v $HOME/.Xauthority:$HOME/.Xauthority:rw \
    -v /tmp/.X11-unix:/tmp/.X11-unix \
    -e DISPLAY=$DISPLAY \
    -ti alchymist:0

Starting the observer, we then succeed

Erlang/OTP 22 [erts-10.7.2.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [hipe]

Interactive Elixir (1.10.4) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> :observer.start()
:ok
iex(2)>
the erlang observer started from a process inside a container
the erlang observer started from a process inside a container

OpenSSH keys on a FIDO2 dongle

OpenSSH recently introduced support for ECDSA keys (and Ed25519) on external dongles. I own a solo key. I wanted to try it, but the majority of the machines I have access to over ssh do not yet support this feature (as far as I get, the server version must be >= 8.2).

I created a docker image to allow me to test this feature. First I created the keypair:

ssh-keygen -t ecdsa-sk -f ~/.ssh/my_ecdsa_sk

I am prompt first to touch the dongle, then to insert a passphrase to secure the key.

I used this Dockerfile

FROM debian:sid

ARG uid=1000
ARG gid=1000
ENV DEBIAN_FRONTEND=noninteractive

RUN apt update && apt install --no-install-recommends -y openssh-server \
    && sed -i 's/PermitRootLogin prohibit-password/PermitRootLogin without-password/g' /etc/ssh/sshd_config \
    && mkdir /run/sshd \
    && groupadd -g ${gid} uzer \
    && useradd -u ${uid} -g ${gid} -m -d /uzer uzer \
    && mkdir /uzer/.ssh \
    && chown uzer:uzer /uzer/.ssh \
    && chmod 700 /uzer/.ssh \
 && rm -rf /var/lib/apt/lists/*
COPY --chown=uzer:uzer key.pub /uzer/.ssh/authorized_keys
COPY entrypoint /entrypoint

EXPOSE 22

ENTRYPOINT ["/entrypoint"]
CMD [""]

with this entrypoint

#!/bin/sh

exit_all() {
  kill $(cat /var/run/sshd.pid)
  exit 0
}

trap exit_all INT TERM

/usr/sbin/sshd -E /var/log/sshd.log

tail -f /var/log/sshd.log

Then I build the image (first copying my newly generate public key to the root of the directory where these files are, naming it key.pub)

docker build -t sshd-sk:0.1 .

and launch a container from it:

docker run --rm -p 10022:22 sshd-sk:0.1

At last, I am able to connect

ssh -i ~/.ssh/my_ecdsa_sk uzer@localhost

I am prompt first to provide the passphrase, then to touch the dongle

Enter passphrase for key '/home/me/.ssh/id_ecdsa_sk': 
Confirm user presence for key ECDSA-SK SHA256:CENSORED
Linux ddcb668dd8b3 5.7.4-arch1-1 #1 SMP PREEMPT Thu, 18 Jun 2020 16:01:07 +0000 x86_64

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
$

Next step is to experiment with the resident key thing, that should enable one to carry around only the dongle.

Quassel and Let’s Encrypt

I love Let’s Encrypt. It is just the right way to secure our http communications.

And I love IRC, and chatting with people using it. Because is a well known and long lived protocol and because it is there a lot of tech geeks and nerds gather 🙂

Team Chat(from https://xkcd.com/1782/)

I also love Quassel (https://quassel-irc.org/), not because it is written in Java (I do not understand it), but because of its paradigm (a core that acts as a client to the IRC servers and to which many clients can connect). And because it is a good solution to use IRC on the smartphone (at least on Android), because connections to IRC servers are unstable via mobile connections.

What I disliked is the fact that I have to authenticate the client to the core at first connection. This is because Quassel core creates a self-signed certificate at installation. This is one of the problems of not having a widespread and accessible system to secure our communications via TLS…but we have it!

Let’s obtain a Let’s Encrypt certificate:

$ certbot certonly --standalone -d my.domain.tld

Following the procedure, we will obtain the certificate, the fullchain and the private key in a specific folder

$  ls /etc/letsencrypt/live/my.domain.tld 
cert.pem chain.pem fullchain.pem privkey.pem README

Now, let’s check where Quassel reads the configuration. On debian-based installations, Quassel creates a user quasselcore with a specific home directory

$ cat /etc/passwd|grep quassel
quasselcore:x:109:114::/var/lib/quassel:/bin/false

There it is

$ ls /var/lib/quassel 
quasselCert.pem quasselcore.conf quassel-storage.sqlite

Let’s backup the self-signed certificate

$ mv  /var/lib/quassel/quasselCert.pem /var/lib/quassel/quasselCert.pem.old

And now let’s use the Let’s Encrypt one

$ cat /etc/letsencrypt/live/my.domain.tdl/{fullchain,privkey}.pem >> /var/lib/quassel/quasselCert.pem
$ systemctl restart quasselcore

And now we can connect to my.domain.tdl with a Let’s Encrypt signed certificate!

If you want also to automate this procedure on certificate renewal, you can create a systemd unit like this

$ cat /lib/systemd/system/quasselcert.path
[Unit]
Description=Triggers the recreation of quassel certificate at certificate renewal 

[Path]
PathChanged=/etc/letsencrypt/live/my.domain.tld/privkey.pem

[Install]
WantedBy=multi-user.target
WantedBy=system-update.target
$ cat /lib/systemd/system/quasselcert.service
[Unit]
Description=Recreation of quassel certificate at certificate renewal

[Service]
Type=oneshot
ExecStartPre=/bin/rm -f /var/lib/quassel/quasselCert.pem
ExecStart=/bin/bash -c 'cat /etc/letsencrypt/live/my.domain.tld/{fullchain,privkey}.pem > /var/lib/quassel/quasselCert.pem'

This should opefully work (not tested!).

Drupal 8 and external smtp relay

I have been recently involved in developing a web portal on drupal. One of the requirements of the project was to run on docker.

Letting aside the royal pain that understanding docker is being to me, I had (and I still have) to face strict limitations on the “customizability” of the environment.

I took drupal directly from the docker image repository, and I have to admit that for a basic and straightforward configuration it is quite simple and plain. But what about more specific needs, like, for example, sending emails? The truth is that it is not so crazy, but it requires a bit of understanding of how docker works. Such understanding I evidently still lack.

Anyway, the basic idea behind it is that, if someone yet “conteinerized” it (please, forgive me for this lingustic murder), you can use it and skip all the mess it would be doing it by yourself. Nice and, in some sense, assigning different tasks to different containers is somehow a modern view of the UNIX way.

Future is scary.