Why Fedora CoreOS is the Perfect “Missing Piece” for Containers?
Forget waiting for ISO files to download then clicking “Next” until your hand gets tired just to partition disks or create users. If you’re managing a few servers, that’s fine. But when that number grows to dozens or hundreds of container nodes, you need a different mindset: Immutable Infrastructure.
Fedora CoreOS (FCOS) was born to solve this problem. After using Fedora as my daily driver for two years, I’ve realized FCOS isn’t a one-size-fits-all OS. It’s extremely minimalist. You shouldn’t SSH into it to manually edit configuration files. Instead, everything from users and network settings to systemd units is predefined and automatically executed during the first boot.
The biggest selling point is Ignition. Unlike Cloud-init, which runs after the OS has booted, Ignition intervenes at the initramfs stage. It allows you to format disks and set up file systems before any other processes run. If the configuration is wrong, the system stops immediately. This helps avoid unstable servers caused by hidden configuration errors.
Tooling: From YAML to JSON
Writing Ignition configuration files directly in JSON is a nightmare because it’s so prone to syntax errors. To make life easier, we use Butane. This tool allows you to write configurations in human-readable YAML, then compile them into JSON for Ignition.
On Fedora, you can install Butane with a single command:
sudo dnf install butane
If you’re using another operating system, leverage the power of containers:
alias butane='podman run --rm -v ".:/pwd":z --workdir /pwd quay.io/coreos/butane:release'
Hands-on: Configuring Butane and Ignition
Let’s try a real-world scenario: Create a user named itfromzero, load an SSH key, and automatically run an Nginx container as soon as the machine starts.
1. Drafting the Butane configuration file (.bu)
Create a config.bu file. Don’t forget to replace the SSH key section with your personal key to ensure you can gain access later:
variant: fcos
version: 1.5.0
passwd:
users:
- name: itfromzero
groups:
- sudo
- wheel
ssh_authorized_keys:
- ssh-ed25519 AAAAC3Nza... user@hostname
systemd:
units:
- name: hello-world.service
enabled: true
contents: |
[Unit]
Description=Run Nginx container automatically
After=network-online.target
Wants=network-online.target
[Service]
TimeoutStartSec=0
ExecStartPre=-/usr/bin/podman kill nginx-server
ExecStartPre=-/usr/bin/podman rm nginx-server
ExecStartPre=/usr/bin/podman pull nginx:latest
ExecStart=/usr/bin/podman run --name nginx-server -p 8080:80 nginx
[Install]
WantedBy=multi-user.target
storage:
files:
- path: /etc/hostname
mode: 0644
contents:
inline: fcos-lab-01
This structure consists of three key parts. The passwd section manages identity, removing the need for passwords to enhance security. The systemd section manages the container lifecycle via Podman. Finally, storage allows you to directly interact with the file system, such as setting the hostname.
2. Compiling to an Ignition file (.ign)
Now, convert the YAML file into a machine-readable format:
butane --pretty --strict config.bu > config.ign
Note: You should never edit the .ign file manually. Make all changes in the Butane file to ensure consistency.
Deployment and Verification
To test quickly without renting a Cloud instance, you can use qemu locally. First, download the FCOS disk image:
coreos-installer download -f qemu
xz -d fedora-coreos-*.qemu.qcow2.xz
Launch the virtual machine and load the configuration via the -fw_cfg parameter:
qemu-system-x86_64 -m 2048 -cpus 2 \
-drive if=virtio,file=fedora-coreos-qemu.qcow2 \
-fw_cfg name=opt/com.coreos/config,file=config.ign \
-net nic,model=virtio -net user,hostfwd=tcp::2222-:22,hostfwd=tcp::8080-:8080
It only takes about 10-15 seconds for the machine to finish booting. Now, try to SSH in to check:
ssh -p 2222 itfromzero@localhost
Once inside, use the podman ps command to see if the Nginx container is up. A major plus of FCOS is Zincati. This service automatically handles background OS updates. If an update fails, the system automatically rolls back to the last stable state.
If the configuration doesn’t run as expected, don’t panic. Check the detailed logs with this command:
journalctl -u ignition-firstboot-complete
Applying this approach can save you up to 80% of the time spent on manual server setup. Instead of fiddling with each node, you simply manage configuration files in Git. For DevOps beginners, mastering Ignition is a solid stepping stone toward mastering Kubernetes later on.

