Configuring CoreOS
There are already a number of good resources for deploying CoreOS to various systems. See References This document focuses on the particulars of configuring CoreOS as a base for small and medium network infrastructure services.
The Principle of Least Config
In keeping with the minimalist philosophy of CoreOS, the configuration will apply only those settings necessary to boot the system and provide remote access and configuration management. The first two are fairly trivial, but the last involves a bit of system gymnastics.
The CoreOS configuration is applied at first boot and is provided to the installer when writing the boot media to storage.
coreos-infra.bu
---
# 1 - Specify the target and schema version
variant: fcos
version: 1.6.0
# 2 - Provide an ssh public key for the core user
passwd:
users:
- name: core
ssh_authorized_keys_local:
- infra-ansible-ed25519.pub
storage:
files:
# 3 - Define the system hostname
- path: /etc/hostname
contents:
inline: |
infra-01.example.com
# 4a - A script to overlay the ansible packages and clean up
- path: /usr/local/bin/install-overlay-packages
user:
name: root
group:
name: root
mode: 0755
contents:
inline: |
#!/bin/bash
if [ -x /usr/bin/ansible ] ; then
rm /usr/local/bin/install-overlay-packages
systemctl disable install-overlay-packages
rm /etc/systemd/system/install-overlay-packages.service
else
rpm-ostree install --assumeyes ansible
systemctl reboot
fi
systemd:
units:
# 4b - Define a one-time service to run at first boot
- name: install-overlay-packages.service
enabled: true
contents: |
[Unit]
Description=Install Overlay Packages
After=systemd-resolved.service
Before=zincati.service
[Service]
Type=oneshot
ExecStart=/usr/local/bin/install-overlay-packages
[Install]
WantedBy=multi-user.target
1 - Butane Preamble
The Butane configuration schema begins with two values that identify the target OS and the schema version itself.
variant: fcos
version: 1.6.0
This indicates that the file targets Fedora CoreOS and the schema version is 1.6.0. This assists the parser in validating the remainder of the configuration against the indicated schema.
2 - Core User - SSH Public Key
CoreOS deploys with two default users, root
and core
. The root
user is not intended for direct login. Neither has a password by
default. CoreOS is meant to be accessed by SSH on a network by the
core
user.
passwd:
users:
- name: core
ssh_authorized_keys_local:
- infra-ansible-ed25519.pub
The core
user already exists so no additional parameters need to be
provided. The user definition only specifies a public key file who’s
contents will be inserted into the authorized_keys
file of that
user.
The ssh_authorized_keys_local
option above consists of a list
of filenames on the local machine that will be merged into the
ignition file during transformation. The directory containing that
file is provided on the butane
command line using the --files-dir
argument.
3 - Hostname
When you log into a system it’s convenient to see the hostname in the
CLI prompts. It’s also good for reviewing logs. The hostname for
Fedora is set using the /etc/hostname
file.
storage:
files:
- path: /etc/hostname
contents:
inline: |
infra-01.example.com
By convention this file contains the fully-qualified domain name of the host, and the hostname is the first element of the FQDN.
4 - Package Overlay - Install Ansible
This is the first place where CoreOS is properly customized. The goal is to automate management of the host and service using Ansible. The Fedora Project is agonistic to the user selection of configuration management software, so no CM software is installed by default. These two sections create the parts needed to overlay Ansible on first boot and then reboot so that the Ansible package contents are available.
4a - Overlay Script
The first part of this first-boot process is a shell script placed so that it can be written and removed after use.
- path: /usr/local/bin/install-overlay-packages
user:
name: root
group:
name: root
mode: 0755
contents:
inline: |
#!/bin/bash
if [ -x /usr/bin/ansible ] ; then
rm /usr/local/bin/install-overlay-packages
systemctl disable install-overlay-packages
rm /etc/systemd/system/install-overlay-packages.service
else
rpm-ostree install --assumeyes ansible
systemctl reboot
fi
The first half of this section defines the location, ownership and
permissions of the file. The second half, under the contents
key
contains the body of this script.
This script checks to see if the ansible binary is present and
executable. If so, then the script removes itself and the systemd
service unit file that triggers the script on boot. If ansible
is
not present, then the script overlays the Ansible RPM and then
reboots.
This means that the service and hence the script is executed twice. On
first boot it runs the installlation command and reboots. The second
time it detects that ansible
is present and then disables and
removes itself.
4b - One-time First Boot Service
The CoreOS specification allows the user to define and control the
operation of systemd
services. This final section defines a service
that executes the script previously defined.
systemd:
units:
- name: install-overlay-packages.service
enabled: true
contents: |
[Unit]
Description=Install Overlay Packages
After=systemd-resolved.service
Before=zincati.service
[Service]
Type=oneshot
ExecStart=/usr/local/bin/install-overlay-packages
[Install]
WantedBy=multi-user.target
This unit file defines when the service should start and what it
should do. The service will run after networking is enabled and the
DNS systemd-resolved
service is running, but before the zincati
update
service is started. It runs the script defined above but does not
detach as it would for a daemon.
As noted, this unit is deleted by the script when it runs the second
time and detects the presence of the ansible
binary.
Transforming the Butane System Spec
The next step is to transform the Butane file to Ignition. The CoreOS installer places the Ignition file onto the new filesystem so that it is available on first boot so it must be provided at the installer CLI invocation.
The butane
binary can be installed on a Fedora system from an RPM,
or it can run as a software container. See
Getting Started in
the Butane documents to decide what works best for you.
butane --pretty --files-dir ~/.ssh < coreos-infra.bu > coreos-infra.ign
This call only takes two parameters:
-
--pretty
This just pretty prints the JSON output. It’s entirely cosmetic and unnecessary. -
--files-dir ~/.ssh
This tellsbutane
where to find any external files, specifically, in this case, the location of the public key file for thecore
user.
The result of running
coreos-infra.ign
{
"ignition": {
"version": "3.5.0"
},
"passwd": {
"users": [
{
"name": "core",
"sshAuthorizedKeys": [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGl7GOHs9enyGZ7tTSh8E8G5mE+B9gyVVnz41hRyxbbN Infrastructure Ansible Key"
]
}
]
},
"storage": {
"files": [
{
"path": "/etc/hostname",
"contents": {
"compression": "",
"source": "data:,infra-01.example.com%0A"
}
},
{
"group": {
"name": "root"
},
"path": "/usr/local/bin/install-overlay-packages",
"user": {
"name": "root"
},
"contents": {
"compression": "gzip",
"source": "data:;base64,H4sIAAAAAAAC/3yPPQ7CMAyF95zCiDnkABwFMTipSyOcpMpLK3p71B8hMcBkyX7fZ/t8cj5m5xmDiT3dyL7ITahblzOiV6E7XakNkg1RTftYS2DdQjGjsaots1TlxY4cnvwQGCIsaJJCU+oieDX9Ca9macHtUHfUn/oLpM4xiBGFrPiYbEGr8llC1jIwJVkEdLzydVQVX0ozfTTvAAAA//9VmB3oBgEAAA=="
},
"mode": 493
}
]
},
"systemd": {
"units": [
{
"contents": "[Unit]\nDescription=Install Overlay Packages\nAfter=systemd-resolved.service\nBefore=zincati.service\n\n[Service]\nType=oneshot\nExecStart=/usr/local/bin/install-overlay-packages\n\n[Install]\nWantedBy=multi-user.target",
"enabled": true,
"name": "install-overlay-packages.service"
}
]
}
}
There are a couple of things to note in this transformation and
result. The SSH public key string is merged verbatim from the
file. The install-overlay-packages
script is compressed and
serialized as base64 of a gzip file. The systemd
unit file is a JSON
string with embedded newlines: \n. Together these make a single
configuration file that can be copied around, served over HTTP or
other file service without corruption from encoding.
Keep this file handy as it is used as input for the next step.
References
-
Butane
The Butane format usage and specifications. -
Ignition
The Ignition spec for CoreOS configuration. -
CoreOS on Bare Metal
How to install CoreOS on Bare Metal. This includes variants for PXE, and Live ISO installations. -
CoreOS on Raspberry Pi 4
How to install CoreOS on Raspberry Pi 4 or 5. This includes instructions for installing EFI boot components that are not present in the Pi boot firmware. -
systemd one-shot service
A blog post on the workings of Systemd one-shot service units. -
coreos-installer
Usage and arguments for the CoreOS installer binary. This can be run from a live ISO or on a second host to write to the boot media.