Flatcar Container Linux

Flatcar Linux is a community distribution designed for container workloads, with high security and low maintenance. Many container users have migrated from CoreOS onto Flatcar Linux. The recommended way to provision Flatcar Container Linux is to use an ignition file at first boot. This documentation will guide you in uploading and managing Ignition files, deploying flatcar linux, and various networking scenarios.

Ignition files

Ignition is a configuration utility used by Flatcar to provide initial operating system configuration. Ignition files are JSON files that are provided to the OS at boot time to configure disk layouts, filesystems, networking, services and more. An Ignition file is required for the first boot of your Flatcar Container Linux installation. We currently support version 2.X and 3.X of Ignition files.

More info on Ignition specification used by Flatcar

Uploading new ignition files

Ignition files are uploaded via the POST /ignition endpoint and are stored permanently under your client account.

curl --request POST \
     --url https://core.hivelocity.net/api/v2/ignition/ \
     --header 'Accept: application/json' \
     --header 'Content-Type: application/json' \
     --header "X-API-KEY: $API_KEY"

Minimum Ignition file

If you are unsure how to write an Ignition file. You can use the minimum viable file below. After deployment you will be able to access your device via password like any other OS.

{
    "ignition": {
        "version": "2.4.0"
    }
}

Deploying Flatcar with an Ignition File

To use an uploaded ignition file during deployment pass in the ignitionId to the POST /bare-metal-device endpoint.

curl -X 'POST' \
  'https://core.hivelocity.net/api/v2/bare-metal-devices/' \
  -H 'accept: application/json' \
  -H "X-API-KEY: $API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{
  "period": "hourly",
  "productId": 584,
  "hostname": "server.example.com",
  "locationName": "TPA1",
  "osName": "Flatcar"
  "ignitionId": YOUR_IGNITION_ID
}'

🚧

Flatcar requires an Ignition file

If you provision a server with Flatcar but fail to provide an Ignition file the device will be inaccessible after provisioning. The Ignition file is required to enable basic networking. See Hivelocity Injections below.

Re-Provisioning Flatcar with a new Ignition file

To re-provision an existing server with a new Ignition file, upload your new Ignition file then use the PUT /bare-metal-device endpoint. Pass in the same data you used during deployment along with your new ignitionId

curl --request PUT \
     --url https://core.hivelocity.net/api/v2/bare-metal-devices/DEVICE_ID \
     --header 'Accept: application/json' \
     --header 'Content-Type: application/json' \
     -H "X-API-KEY: $API_KEY" \
     --data '
{
     "hostname": "server.example.com",
     "osName": "Flatcar Linux 3139.x",
     "ignitionId": "YOUR_NEW_IGNITION_ID"
}
'

πŸ“˜

Reboots use a separate endpoint

Ignition files are only required for first boot. If you do not need to re-provision your server and simply wish to reload your server use the reboot action in the POST /device/{deviceId}/power endpoint.

Custom Metadata

In many cases, it is desirable to inject dynamic data into services written by Ignition. Because Ignition itself is static and cannot inject dynamic data into configs, this must be done as the system starts using a custom metadata agent

Hivelocity provides the following variables for injection:

VariableValue
COREOS_HIVELOCITY_PUBLIC_NICName of the first nic. For example: eno1.

Note the API ensures that this nic is always used for public internet access (IPs and VLANs with routed interfaced) in devices with unbonded ports.
COREOS_HIVELOCITY_PRIVATE_NICName of the second nic. For example: eno2.

Note the API ensures that Private VLANs for devices with unbonded ports are only assignable to this nic.
COREOS_HIVELOCITY_HOSTNAMEThe hostname provided to the deployment endpoint at provisioning time. For example: server.hivelocity.net
COREOS_HIVELOCITY_PUBLIC_IPV4_IPEvery device deploys with a default IPv4 subnet.

The first usable IP in the default subnet. For example: 77.88.99.250
COREOS_HIVELOCITY_PUBLIC_IPV4_FULLThis is the entire default subnet as expected by systemd.network.address. For example: 77.88.99.250/29
COREOS_HIVELOCITY_PUBLIC_IPV4_GATEWAYThe gateway IP of the default subnet. For example: 77.88.99.249
COREOS_HIVELOCITY_PUBLIC_IPV4_SUBNETThis is the entire default subnet in CIDR notation. For example: 77.88.99.248/29
COREOS_HIVELOCITY_PUBLIC_IPV4_NETMASKThe subnet mask of the device's default IPv4 subnet. For example: 255.255.255.247
COREOS_HIVELOCITY_PUBLIC_IPV4_NETWORKThe network address of the default subnet. For example: 77.88.99.248

πŸ“˜

You can also inject COREOS_HIVELOCITY variables into networkd.units and storage.files

This is behavior provided by the Hivelocity API and is not supported in standard Ignition. You can pass the above variables in the format {VARIABLE} to the contents section of networkd.units and the variables will be replaced with values in your file before first provision.

You can also pass them in the same {VARIABLE} format to the URI encoded contents of storage.files. Hivelocity will decode the contents, replace the variables in the content with values, then re-encode the new content and inject it back into your ignition file before first provision.

Both of the above injection scenarios happen after the API call for deployment is made, the variable replacement happens in memory, and the new Ignition file is used for the first provision.

Hivelocity Injections

When deploying with an Ignition configuration, Hivelocity will inject additional configuration to your Ignition file to ensure your deployment works with our networking and systems. This injection happens after the API call for deployment is made, the new data is added to your provided Ignition file in memory, and the new Ignition file is used for the first provision.

networkd.units

The following files are always injected into the networkd.units. This ensures the physical nics on the machine are appropriately configured to communicated with the network.

Bonded

These configs are injected into first deploys of devices with default bonded nics. They take the mac addresses of the device nics and put them into a bond. The last item ensures this bond has the default public IP that comes with the device.

{
    "contents": "[Match]\nMACAddress=01:23:45:67:89:0a\n[Network]\nBond=bond0",
    "name": "00-01_23_45_67_89_0a.network"
},
{
    "contents": "[Match]\nMACAddress=01:23:45:67:89:0a\n[Network]\nBond=bond0",
    "name": "00-01_23_45_67_89_0a.network"
},
{
    "contents": "[NetDev]\nName=bond0\nKind=bond\n[Bond]\nMode=802.3ad\nMIIMonitorSec=1s\nLACPTransmitRate=fast",
    "name": "10-bond0.netdev"
},
{
    "contents": "[Match]\nName=bond0\n[Network]\nAddress={COREOS_HIVELOCITY_PUBLIC_IPV4_FULL}\nGateway={COREOS_HIVELOCITY_PUBLIC_IPV4_GATEWAY}\nDNS=8.8.8.8\nDNS=8.8.4.4",
    "name": "20-bond0.network"
}

Unbonded

This config is injected into first deploys of devices with default unbonded nics. It takes the mac address of the public (first) nic and ensures it has the default public IP that comes with the device.

{
    "contents": "[Match]\nMACAddress=01:23:45:67:89:0a\n[Network]\nAddress={COREOS_HIVELOCITY_PUBLIC_IPV4_FULL}\nGateway={COREOS_HIVELOCITY_PUBLIC_IPV4_GATEWAY}\nDNS=8.8.8.8\nDNS=8.8.4.4",
    "name": "20-01_23_45_67_89_0a.network"
}

passwd.users

If you do not provide your own password hash for the root user this config is injected with the randomly generated default password Hivelocity creates for all new deployments. This password is retrievable after deployment for 7 days in the API or portal.

{
    "name": "root",
    "passwordHash": "$6$NOT-A-REAL-LOGIN-HASH"
}

storage.files

The /etc/hostname is always injected here to match the provided hostname provided in the order.

{
    "contents": {
        "source": "data:text/plain;base64,d2hhdA=="
    },
    "filesystem": "root",
    "mode": 420,
    "path": "/etc/hostname"
}

systemd.units

The provisioning-hook.service is always injected. This service enables the Hivelocity provisioning system to determine when your device has completed provisioning. Do not override this file or you will not be able to access your device.

{
    "contents": "[Unit]\nDescription=Provisioning Hook\nAfter=docker.service\nAfter=network-online.target\nRequires=network-online.target\nStartLimitInterval=10m\nStartLimitBurst=30\n[Service]\nExecStart=curl -XPOST 'https://hivelocity.net/core/api/v2/update-progress' --fail -H 'Content-Type: application/json' -H 'X-API-KEY: sample' -o /tmp/provisioning_hook_output\nRemainAfterExit=true\nType=oneshot\nRestart=on-failure\nRestartSec=1s\n[Install]\nWantedBy=multi-user.target",
    "enabled": true,
    "name": "provisioning-hook.service"
},
{
    "contents": "[Unit]\nDescription=Hivelocity CoreOS Metadata\nAfter=network-online.target\nRequires=network-online.target\nStartLimitInterval=3m\nStartLimitBurst=30\n[Service]\nExecStart=/usr/bin/mkdir --parent /run/metadata\nExecStart=curl -XGET 'https://hivelocity.net/core/api/v2/coreos-metadata' --fail -H 'Content-Type: application/json' -H 'X-API-KEY: sample' -o /run/metadata/coreos\nRemainAfterExit=true\nType=oneshot\nRestart=on-failure\nRestartSec=1s\n[Install]\nWantedBy=multi-user.target",
    "enabled": false,
     "name": "coreos-metadata.service"
}

Overriding Hivelocity Injections

The order of resolution of the file names matters. You can directly replace the above files by creating files with the same name in your Ignition file.

Examples