Recently released, Fedora CoreOS is the Fedora’s team attempt at building an immutable and container centric operating system.

Let’s take a look

What is Fedora CoreOS

Fedora CoreOS is a fedora derivative centered around three main concepts:

  • Container-centric: CoreOS is built in order to make the computer a great candidate for joining in all your Kubernetes and Docker endavours
  • Immutability: The system configuration is applied at boot time. In order to reconfigure the machine, the system has to be reprovisioned. The main benefit of this approach is trying to avoid the configuration management drift that occours over time, encouraging a more structured approach to configuring systems (many refer to that with the term infrastructure as code)
  • Transactional updates: Updates are either applied in their entirety or not applied at all, the system preserves past snapshots allowing it to revert to safe savepoints if anything goes south.

It was born from the ideas of CoreOS’s Container Linux and revolves around Fedora packages delivered via a transactional package manager called rpm-ostree and a boot time configuration tool called ignition.

Testbed environment

For this first test I rented one of these cheap KVM virtual private servers.

Sadly the provider did not provide me with a preconfigured image, so I rebooted in the provider’s rescue console running Debian 10.

The first ingredient of our recipe is the coreos-installer, a single binary allowing easy installation.

I could not find a prebuilt binary package, but thanks to coreos-installer being a Rust binary, all it took to compile it from source were these four commands:

# Libraries needed by the OpenSSL crate
apt-get install -y pkg-config libssl-dev
# Rust compiler and tools
wget -O - https://sh.rustup.rs | sh # Please be aware that piping directly into sh is unsafe
# Setup build environment
source $HOME/.cargo/env
# The build command itself
cargo install coreos-installer

See the commands’ output

The Fedora CoreOS configuration file

The entirety of the system configuration is defined inside a single .yaml file. This file is read and applied only when the machine is reprovisioned so the only way to force a reconfiguration is effectively starting again from a blank slate.

To experiment I started with a very simple one, but there are a lot of things to fiddle with:

variant: fcos
version: 1.0.0
passwd:
  users:
    - name: "g4b1bb097"
      ssh_authorized_keys:
        - "<YOUR_PUBLIC_KEY>"
      groups: [ 'wheel' ]
storage:
  files:
    - path: /etc/sudoers.d/passwordless
      contents:
        inline: |
          %wheel	ALL=(ALL)	NOPASSWD: ALL
      mode: 0440

Ignoring the first two lines of boilerplate, this basic config does two things:

  • Creates a g4b1bb097 user belonging to wheel (the default systemd administrative group)
  • Creates a file in /etc/sudoers.d/passwordless allowing users in wheel to escalate privileges without a password (since g4b1bb097 is only accessibile via public key authentication)

This very readable file has to be converted into an ignition file (a JSON that can be parsed by the actual installer) so I performed the translation using the handy Fedora CoreOS Configuration Transpiler (FCCT) container:

podman run --rm -i quay.io/coreos/fcct:release --pretty --strict < fcct.yaml > fcct.ign

See the resulting fcct.ign

In order to not have bad surprises I validated the ignition file with the ignition-validate tool’s container image

podman run --rm -i quay.io/coreos/ignition-validate - < fcct.ign

After performing this step, I copied the fcct.ign file to the target and started the installation process:

coreos-installer install --stream testing --ignition-file fcct.ign /dev/sda

Please be aware that here I’m explicitly requesting the testing version, if you want to try the stable you have to remove --stream testing from the command above.

The installation finished in a very short time, thanks also to the very small download size (approximately half a gigabyte)

root@debian:~# coreos-installer install --stream testing --ignition-file fcct.ign /dev/sda
Downloading testing image (raw.xz) and signature
gpg: Signature made Wed 03 Jun 2020 04:28:09 AM UTC
gpg:                using RSA key 6C13026D12C944D0
gpg: Good signature from "Fedora (32) <fedora-32-primary@fedoraproject.org>" [ultimate]
> Read disk 479.5 MiB/479.5 MiB (100%)
Writing Ignition config
Install complete.

By peeking at the installation disk partition layout we can see that currently the installed system is not taking up the entire disk:

root@debian:~# lsblk
NAME   MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sda      8:0    0  200G  0 disk
├─sda1   8:1    0  384M  0 part
├─sda2   8:2    0  127M  0 part
├─sda3   8:3    0    1M  0 part
└─sda4   8:4    0  2.2G  0 part

First boot

It is now time to kickoff a reboot with systemctl reboot and see what happens through the VNC console.

The boot menu is mostly unpopulated, with only the latest release, after upgrading there will be extra entries, allowing for easy rollback

Boot menu

Here the ignition tool is expanding and repartitioning the disk

Partitioning of the disk

If you have specified other options such as our passwordless file, ignition will apply these modifications too

Writing of the files specified in the configuration

After ~10 seconds the system is ready to roll, indicating its SSH fingerprints and IP address

System ready

Inspection of the booted system

The system has been automatically repartitioned as follows

[g4b1bb097@localhost ~]$ lsblk
NAME   MAJ:MIN RM   SIZE RO TYPE MOUNTPOINT
sda      8:0    0   200G  0 disk
├─sda1   8:1    0   384M  0 part /boot
├─sda2   8:2    0   127M  0 part /boot/efi
├─sda3   8:3    0     1M  0 part
└─sda4   8:4    0 199.5G  0 part /sysroot
[g4b1bb097@localhost ~]$ mount
/dev/sda1 on /boot type ext4 (rw,relatime,seclabel)
/dev/sda2 on /boot/efi type vfat (rw,relatime,fmask=0022,dmask=0022,codepage=437,iocharset=ascii,shortname=mixed,errors=remount-ro)
/dev/sda4 on /var type xfs (rw,relatime,seclabel,attr2,inode64,logbufs=8,logbsize=32k,prjquota)

Fedora CoreOS on its own is very light on resources, thanks to a minimal amount of enabled services

[g4b1bb097@localhost ~]$ free -h
              total        used        free      shared  buff/cache   available
Mem:          7.8Gi       157Mi       7.4Gi       0.0Ki       206Mi       7.4Gi
Swap:            0B          0B          0B
[g4b1bb097@localhost ~]$ systemctl list-unit-files --state=enabled
UNIT FILE                                      STATE   VENDOR PRESET
ostree-finalize-staged.path                    enabled enabled
afterburn-checkin.service                      enabled enabled
afterburn-firstboot-checkin.service            enabled enabled
afterburn-sshkeys@.service                     enabled enabled
autovt@.service                                enabled disabled
chronyd.service                                enabled enabled
console-login-helper-messages-issuegen.service enabled enabled
console-login-helper-messages-motdgen.service  enabled enabled
coreos-check-ignition-config.service           enabled enabled
coreos-check-ssh-keys.service                  enabled enabled
coreos-liveiso-success.service                 enabled enabled
coreos-update-ca-trust.service                 enabled enabled
dbus-broker.service                            enabled enabled
dbus-org.freedesktop.nm-dispatcher.service     enabled disabled
dbus.service                                   enabled disabled
dbxtool.service                                enabled enabled
fedora-coreos-pinger.service                   enabled enabled
getty@.service                                 enabled enabled
ignition-firstboot-complete.service            enabled enabled
irqbalance.service                             enabled enabled
lvm2-monitor.service                           enabled enabled
mdmonitor.service                              enabled enabled
multipathd.service                             enabled enabled
NetworkManager-dispatcher.service              enabled enabled
NetworkManager-wait-online.service             enabled enabled
NetworkManager.service                         enabled enabled
ostree-remount.service                         enabled enabled
selinux-autorelabel-mark.service               enabled enabled
sshd.service                                   enabled enabled
sssd.service                                   enabled enabled
systemd-pstore.service                         enabled enabled
zincati.service                                enabled enabled
dbus.socket                                    enabled enabled
dm-event.socket                                enabled enabled
docker.socket                                  enabled enabled
lvm2-lvmpolld.socket                           enabled enabled
multipathd.socket                              enabled disabled
ctrl-alt-del.target                            enabled disabled
machines.target                                enabled enabled
reboot.target                                  enabled enabled
remote-cryptsetup.target                       enabled enabled
remote-fs.target                               enabled enabled
runlevel6.target                               enabled disabled
fstrim.timer                                   enabled enabled
logrotate.timer                                enabled enabled

45 unit files listed.

Trying out a test container

I decided to test out Fedora CoreOS with a realistic container: a GitLab 13 instance

podman run --rm \
  -e GITLAB_OMNIBUS_CONFIG="gitlab_rails['initial_root_password'] = \"myVeeerySecurePassword\";" \
  -p 2222:22 \
  -p 80:80 \
  -p 443:443 \
  --name gitlab \
  gitlab/gitlab-ce:13.0.4-ce.0

After a while, via a browser

GitLab Admin Dashboard

As expected, everything went smoothly!

Conclusion

I like very much this paradigm and I am looking forward to exaustively trying out the system with a variety of workloads.

Of course this blogpost was only about the very first step, so I’ll see you later for more experimentation with Fedora CoreOS.

Happy hacking!