The OpenShift Installer allows for several different levels of customization. It is important to understand how and why each of these levels is exposed and the ramifications of making changes at each of these levels. This guide will attempt to walk through each of them and provide examples for why an administrator may want to make customizations.
Cluster customization can be broken into four major levels: OpenShift, Kubernetes, Platform, and OS. These four levels are rough abstraction layers (OpenShift being the highest layer and OS being the lowest) and fall into either the validated or unvalidated buckets. The levels within the validated bucket (OpenShift and Platform) encompass customization that is safe to perform - installation and automatic updates will succeed regardless of the changes made (to a reasonable degree). The levels within the unvalidated bucket (Kubernetes and OS) encompass customization that is not necessarily safe - after introducing changes, installation and automatic updates may not succeed.
The most simple customization is exposed by the installer as an interactive series of prompts. These prompts are required and represent a high-level of customization. They are needed in order to get a running OpenShift cluster, but they aren't enough to get anything other than a vanilla deployment out of the box. Further customization is possible once the cluster has been provisioned, but isn't covered in this document as it is a "Day 2" operation.
While the default cluster size may be sufficient for some, many will need to make alterations. This can include increasing the number of machines in the control plane, changing the type of the virtual machines that will be used (e.g. AWS instances), or adjusting the CIDR range used for the Kubernetes service network. This level of customization is exposed via the installer's install-config.yaml
. The install-config can be accessed by running openshift-install create install-config
. This file can then be modified as needed before running a later target.
The install-config.yaml
generated by the installer will not have all of the available fields populated, so they may need to be manually added if they are needed.
The following install-config.yaml
properties are available:
apiVersion
(required string): The API version for theinstall-config.yaml
content. The current version (as described in this documentation) isv1
. The installer may also support older API versions.additionalTrustBundle
(optional string): a PEM-encoded X.509 certificate bundle that will be added to the nodes' trusted certificate store. This trust bundle may also be used when a proxy has been configured.additionalTrustBundlePolicy
(optional string): determines when to add the AdditionalTrustBundle to the nodes'' trusted certificate store. "Proxyonly" is the default. The field can be set to following specified values. "Proxyonly" : adds the AdditionalTrustBundle to nodes when http/https proxy is configured. "Always" : always adds AdditionalTrustBundle.baseDomain
(required string): The base domain to which the cluster should belong.capabilities
(optional capabilities): Capabilities configures the installation of optional core cluster components.controlPlane
(optional machine-pool): The configuration for the machines that comprise the control plane.compute
(optional array of machine-pools): The configuration for the machines that comprise the compute nodes.featureSet
(optional string): A feature set as defined in the OpenShift API. Notably,TechPreviewNoUpgrade
can be used to enable Installer features protected by a Tech Preview feature gate. Feature sets will be applied to the cluster--not just the Installer--and may affect the supportability and upgradability of the cluster, depending on the specified feature set.fips
(optional boolean): Enables FIPS mode (default false).imageContentSources
(optional array of objects): Sources and repositories for the release-image content. Each entry in the array is an object with the following properties:source
(required string): The repository that users refer to, e.g. in image pull specifications.mirrors
(optional array of strings): One or more repositories that may also contain the same images.
metadata
(required object): Kubernetes resource ObjectMeta, from which only thename
parameter is consumed.name
(required string): The name of the cluster. DNS records for the cluster are all subdomains of{{.metadata.name}}.{{.baseDomain}}
.
networking
(optional object): The configuration for the pod network provider in the cluster.clusterNetwork
(optional array of objects): The IP address pools for pods. The default is 10.128.0.0/14 with a host prefix of /23.cidr
(required IP network): The IP block address pool.hostPrefix
(required integer): The prefix size to allocate to each node from the CIDR. For example, 24 would allocate 2^8=256 addresses to each node. If this field is not used by the plugin, it can be left unset.
machineNetwork
(optional array of objects): The IP address pools for machines.cidr
(required IP network): The IP block address pool. The default is 10.0.0.0/16 for all platforms other than libvirt. For libvirt, the default is 192.168.126.0/24.
networkType
(optional string): The type of network to install. The default is OVNKubernetes.serviceNetwork
(optional array of IP networks): The IP address pools for services. The default is 172.30.0.0/16.
platform
(required object): The configuration for the specific platform upon which to perform the installation.aws
(optional object): AWS-specific properties.baremetal
(optional object): Baremetal IPI-specific properties.azure
(optional object): Azure-specific properties.openstack
(optional object): OpenStack-specific properties.ovirt
(optional object): oVirt-specific properties.vsphere
(optional object): vSphere-specific properties.
proxy
(optional object): The proxy settings for the cluster. If unset, the cluster will not be configured to use a proxy.httpProxy
(optional string): The URL of the proxy for HTTP requests.httpsProxy
(optional string): The URL of the proxy for HTTPS requests.noProxy
(optional string): A comma-separated list of domains and CIDRs for which the proxy should not be used.
publish
(optional string): This controls how the user facing endpoints of the cluster like the Kubernetes API, OpenShift routes etc. are exposed. Valid values areExternal
(the default) andInternal
.pullSecret
(required string): The secret to use when pulling images.sshKey
(optional string): The public Secure Shell (SSH) key to provide access to instances.
baselineCapabilitySet
(optional string): Selects an initial set of optional capabilities to enable. The default value isvCurrent
(the default). Aadditional valid values can be found here.additionalEnabledCapabilities
(optional array of strings): Extends the set of managed capabilities beyond the baseline defined inbaselineCapabilitySet
. Default is an empty set. Valid values can be found here.
IP networks are represented as strings using Classless Inter-Domain Routing (CIDR) notation with a traditional IP address or network number, followed by the "/" (slash) character, followed by a decimal value between 0 and 32 that describes the number of significant bits. For example, 10.0.0.0/16 represents IP addresses 10.0.0.0 through 10.0.255.255.
The following machine-pool properties are available:
architecture
(optional string): Determines the instruction set architecture of the machines in the pool. Currently, heterogeneous clusters are not supported, so all pools must specify the same architecture. Valid values areamd64
(the default).hyperthreading
(optional string): Determines the mode of hyperthreading that machines in the pool will utilize. Valid values areEnabled
(the default) andDisabled
.name
(required string): The name of the machine pool.platform
(optional object): Platform-specific machine-pool configuration.aws
(optional object): AWS-specific properties.azure
(optional object): Azure-specific properties.gcp
(optional object): GCP-specific properties.openstack
(optional object): OpenStack-specific properties.ovirt
(optional object): oVirt-specific properties.vsphere
(optional object): vSphere-specific properties.
replicas
(optional integer): The machine count for the machine pool.
While all complete install-config.yaml
will contain platform-specific sections, the following example fragments demonstrate platform-agnostic options:
apiVersion: v1
additionalTrustBundle: |
-----BEGIN CERTIFICATE-----
...base-64-encoded, DER Certificate Authority cert...
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
...base-64-encoded, DER Certificate Authority cert...
-----END CERTIFICATE-----
baseDomain: example.com
metadata:
name: test-cluster
platform: ...
pullSecret: '{"auths": ...}'
sshKey: ssh-ed25519 AAAA...
An example install config where the user can specify a custom list of capabilities than a default set deployed by the installer. In this example, the user requested to use None
, an empty set, as the baseline capability set but specified that the openshift-samples
to be installed.
apiVersion: v1
baseDomain: example.com
metadata:
name: test-cluster
platform: ...
capabilities:
baselineCapabilitySet: None
additionalEnabledCapabilities:
- openshift-samples
sshKey: ...
An example install config with custom machine pools to grow the size of the worker pool and disable hyperthreading:
apiVersion: v1
baseDomain: example.com
controlPlane:
name: master
hyperthreading: Disabled
compute:
- name: worker
hyperthreading: Disabled
replicas: 5
metadata:
name: test-cluster
platform: ...
pullSecret: '{"auths": ...}'
sshKey: ssh-ed25519 AAAA...
An example install config with custom networking:
apiVersion: v1
baseDomain: example.com
metadata:
name: test-cluster
networking:
clusterNetwork:
- cidr: 10.128.0.0/14
hostPrefix: 23
machineNetwork:
- cidr: 10.0.0.0/16
networkType: OpenShiftSDN
serviceNetwork:
- 172.30.0.0/16
platform: ...
pullSecret: '{"auths": ...}'
sshKey: ssh-ed25519 AAAA...
An example install config with custom image content sources:
apiVersion: v1
baseDomain: example.com
metadata:
name: test-cluster
imageContentSources:
- mirrors:
- registry.example.com/ocp4/openshift4
source: quay.io/openshift-release-dev/ocp-release-nightly
- mirrors:
- registry.example.com/ocp4/openshift4
source: quay.io/openshift-release-dev/ocp-v4.0-art-dev
platform: ...
pullSecret: '{"auths": ...}'
sshKey: ssh-ed25519 AAAA...
That configuration is compatible with mirrored releases created with mirror
commands like:
$ oc adm release mirror \
> --from=quay.io/openshift-release-dev/ocp-release-nightly:4.2.0-0.nightly-XXXXXX \
> --to=registry.example.com/ocp4/openshift4 \
> --to-release-image=registry.example.com/ocp4/openshift4:4.2.0-0.nightly-XXXXXX
...
Success
Update image: registry.example.com/ocp4/openshift4:4.2.0-0.nightly-2019-09-11-114314
Mirror prefix: registry.example.com/ocp4/openshift4
To use the new mirrored repository to install, add the following section to the install-config.yaml:
imageContentSources:
- mirrors:
- registry.example.com/ocp4/openshift4
source: quay.io/openshift-release-dev/ocp-release-nightly
- mirrors:
- registry.example.com/ocp4/openshift4
source: quay.io/openshift-release-dev/ocp-v4.0-art-dev
...
If your mirror(s) are signed by a certificate authority which RHCOS does not trust by default, you may also wish to configure an additional trust bundle.
An example install config routing outgoing traffic through a proxy:
apiVersion: v1
baseDomain: example.com
metadata:
name: test-cluster
proxy:
httpsProxy: https://username:password@proxy.example.com:123/
httpProxy: https://username:password@proxy.example.com:123/
noProxy: 123.example.com,10.88.0.0/16
platform: ...
pullSecret: '{"auths": ...}'
sshKey: ssh-ed25519 AAAA...
If your proxy certificate is signed by a certificate authority which RHCOS does not trust by default, you may also wish to configure an additional trust bundle.
If additionalTrustBundle
and at least one proxy
setting are configured, the cluster
Proxy object will be configured with trustedCA
referencing the additional trust bundle.
In addition to customizing OpenShift and aspects of the underlying platform, the installer allows arbitrary modification to the Kubernetes objects that are injected into the cluster. Note that there is currently no validation on the modifications that are made, so it is possible that the changes will result in a non-functioning cluster. The Kubernetes manifests can be viewed and modified using the manifests
and manifest-templates
targets.
The manifests
target will render the manifest templates and output the result into the asset directory. Perhaps the most common use for this target is to include additional manifests in the initial installation. These manifests could be added after the installation as a "Day 2" operation, but there may be cases where they are necessary beforehand.
The manifest-templates
target will output the unrendered manifest templates into the asset directory. This allows modification to the templates before they have been rendered, which may be useful to users who wish to reuse the templates between cluster deployments.
IMPORTANT:
- These customizations require using the
manifests
target that does not provide compatibility guarantees.
In most cases, user applications should be run on the cluster via Kubernetes workload objects (e.g. DaemonSet, Deployment, etc). For example, DaemonSets are the most stable way to run a logging agent on all hosts. However, there may be some cases where these workloads need to be executed prior to the node joining the Kubernetes cluster. For example, a compliance mandate like "the user must run auditing tools as soon as the operating system comes up" might require a custom systemd unit for an auditing container in the Ignition config for some or all nodes.
Further, some aspects of RHEL CoreOS machines (usually kernel arguments such as nosmt
for disabling hyperthreading) may need to be configured before user workloads land on a system.
The configuration of machines in OpenShift is controlled using MachineConfig
objects and what configuration is applied to a machine in the OpenShift cluster is based on the MachineConfigPool objects. For these "day 1" cases, MachineConfig
objects can be provided as additional manifests.
-
openshift-install --dir $INSTALL_DIR create manifests
-
Copy files with
MachineConfig
objects to$INSTALL_DIR/openshift/
directory.These custom
MachineConfig
objects are black boxes to the installer and the installer only plays the role ofoc create -f <custom-machine-config-object>
early enough into cluster bootstrap to make sure the configuration is used by the MachineConfigOperator. -
openshift-install --dir $INSTALL_DIR create cluster
All control plane nodes by default register with a taint node-role.kubernetes.io/master=:NoSchedule
making them unschedulable by most normal workloads. An installation that requires the control plane to boot without that taint can push a custom MachineConfig
object with a kubelet.service
that doesn't include the taint.
For example:
-
Run
manifests
target to create all the manifests.$ mkdir no-taint-cluster $ cp aws-install-config.yaml no-taint-cluster/install-config.yaml $ openshift-install --dir no-taint-cluster create manifests INFO Consuming "Install Config" from target directory $ ls -l no-taint-cluster/** no-taint-cluster/manifests: total 68 -rw-r--r--. 1 xxxxx xxxxx 169 Feb 28 10:54 04-openshift-machine-config-operator.yaml -rw-r--r--. 1 xxxxx xxxxx 1589 Feb 28 10:54 cluster-config.yaml -rw-r--r--. 1 xxxxx xxxxx 149 Feb 28 10:54 cluster-dns-02-config.yml -rw-r--r--. 1 xxxxx xxxxx 243 Feb 28 10:54 cluster-infrastructure-02-config.yml -rw-r--r--. 1 xxxxx xxxxx 154 Feb 28 10:54 cluster-ingress-02-config.yml -rw-r--r--. 1 xxxxx xxxxx 557 Feb 28 10:54 cluster-network-01-crd.yml -rw-r--r--. 1 xxxxx xxxxx 327 Feb 28 10:54 cluster-network-02-config.yml -rw-r--r--. 1 xxxxx xxxxx 264 Feb 28 10:54 cvo-overrides.yaml -rw-r--r--. 1 xxxxx xxxxx 118 Feb 28 10:54 kube-cloud-config.yaml -rw-r--r--. 1 xxxxx xxxxx 1304 Feb 28 10:54 kube-system-configmap-root-ca.yaml -rw-r--r--. 1 xxxxx xxxxx 4030 Feb 28 10:54 machine-config-server-tls-secret.yaml -rw-r--r--. 1 xxxxx xxxxx 856 Feb 28 10:54 pull.json no-taint-cluster/openshift: total 28 -rw-r--r--. 1 xxxxx xxxxx 293 Feb 28 10:54 99_binding-discovery.yaml -rw-r--r--. 1 xxxxx xxxxx 181 Feb 28 10:54 99_kubeadmin-password-secret.yaml -rw-r--r--. 1 xxxxx xxxxx 330 Feb 28 10:54 99_openshift-cluster-api_cluster.yaml -rw-r--r--. 1 xxxxx xxxxx 1015 Feb 28 10:54 99_openshift-cluster-api_master-machines-0.yaml -rw-r--r--. 1 xxxxx xxxxx 2655 Feb 28 10:54 99_openshift-cluster-api_master-user-data-secret.yaml -rw-r--r--. 1 xxxxx xxxxx 1750 Feb 28 10:54 99_openshift-cluster-api_worker-machineset.yaml -rw-r--r--. 1 xxxxx xxxxx 2655 Feb 28 10:54 99_openshift-cluster-api_worker-user-data-secret.yaml
-
Create a
MachineConfig
that includeskubelet.service
that has no taints.cat > no-taint-cluster/openshift/99-master-kubelet-no-taint.yaml <<EOF apiVersion: machineconfiguration.openshift.io/v1 kind: MachineConfig metadata: labels: machineconfiguration.openshift.io/role: master name: 02-master-kubelet spec: config: ignition: version: 3.1.0 systemd: units: - contents: | [Unit] Description=Kubernetes Kubelet Wants=rpc-statd.service [Service] Type=notify ExecStartPre=/bin/mkdir --parents /etc/kubernetes/manifests ExecStartPre=/bin/rm -f /var/lib/kubelet/cpu_manager_state EnvironmentFile=-/etc/kubernetes/kubelet-workaround EnvironmentFile=-/etc/kubernetes/kubelet-env ExecStart=/usr/bin/kubelet \ --config=/etc/kubernetes/kubelet.conf \ --bootstrap-kubeconfig=/etc/kubernetes/kubeconfig \ --rotate-certificates \ --kubeconfig=/var/lib/kubelet/kubeconfig \ --container-runtime-endpoint=/var/run/crio/crio.sock \ --allow-privileged \ --node-labels=node-role.kubernetes.io/master \ --minimum-container-ttl-duration=6m0s \ --client-ca-file=/etc/kubernetes/ca.crt \ --cloud-provider=aws \ --volume-plugin-dir=/etc/kubernetes/kubelet-plugins/volume/exec \ \ --anonymous-auth=false \ Restart=always RestartSec=10 [Install] WantedBy=multi-user.target enabled: true name: kubelet.service EOF
machineconfiguration.openshift.io/role: master
label attaches thisMachineConfig
to the masterMachineConfigPool
. The default configuration for thekubelet.service
includes the taint. -
Run
cluster
target to create the cluster using the custom manifests.$ openshift-install --dir no-taint-cluster create cluster INFO Consuming "Openshift Manifests" from target directory INFO Consuming "Master Machines" from target directory INFO Consuming "Common Manifests" from target directory INFO Creating infrastructure resources... INFO Waiting up to 30m0s for the Kubernetes API at https://api.test-cluster.example.com:6443... ...
Check that no control plane nodes registered with taints:
$ oc --kubeconfig no-taint-cluster/auth/kubeconfig get nodes -ojson | jq '.items[] | select(.metadata.labels."node-role.kubernetes.io/master" == "") | .spec.taints' null
Check that the
02-master-kubelet
MachineConfig
exists in the cluster:oc --kubeconfig no-taint-cluster/auth/kubeconfig get machineconfigs NAME GENERATEDBYCONTROLLER IGNITIONVERSION CREATED 00-master 3.11.0-744-g5b05d9d3-dirty 3.1.0 137m 00-master-ssh 3.11.0-744-g5b05d9d3-dirty 137m 00-worker 3.11.0-744-g5b05d9d3-dirty 3.1.0 137m 00-worker-ssh 3.11.0-744-g5b05d9d3-dirty 137m 01-master-container-runtime 3.11.0-744-g5b05d9d3-dirty 3.1.0 137m 01-master-kubelet 3.11.0-744-g5b05d9d3-dirty 3.1.0 137m 02-master-kubelet 3.1.0 137m 01-worker-container-runtime 3.11.0-744-g5b05d9d3-dirty 3.1.0 137m 01-worker-kubelet 3.11.0-744-g5b05d9d3-dirty 3.1.0 137m 99-master-3c81ffa3-3b8d-11e9-ac1e-52fdfc072182-registries 3.11.0-744-g5b05d9d3-dirty 133m 99-worker-3c83a226-3b8d-11e9-ac1e-52fdfc072182-registries 3.11.0-744-g5b05d9d3-dirty 133m master-55491738d7cd1ad6c72891e77c35e024 3.11.0-744-g5b05d9d3-dirty 3.1.0 137m worker-edab0895c59dba7a566f4b955d87d964 3.11.0-744-g5b05d9d3-dirty 3.1.0 137m
Custom kernel arguments can be applied to through manifests as an installer operation, and can also be applied as a MachineConfig as a day 2 operation. The kernel arguments are applied upon boot and will be honored by the Machine-Config-Operator from then on.
Example application of loglevel=7
(change Linux kernel log level to KERN_DEBUG) for master nodes:
-
Run
manifests
target to create all the manifests.$ mkdir log_debug_cluster $ openshift-install --dir log_debug_cluster create manifests ... $ ls -l log_debug_cluster/openshift ... 99_openshift-machineconfig_99-master-ssh.yaml 99_openshift-machineconfig_99-worker-ssh.yaml ...
-
. Create a
MachineConfig
that adds a kernel argument to change log level:cat > log_debug_cluster/openshift/99-master-kargs-loglevel.yaml <<EOF apiVersion: machineconfiguration.openshift.io/v1 kind: MachineConfig metadata: labels: machineconfiguration.openshift.io/role: "master" name: 99-master-kargs-loglevel spec: config: ignition: version: 3.1.0 kernelArguments: - 'loglevel=7' EOF
-
Run
cluster
target to create the cluster using the custom manifests.$ openshift-install --dir log_debug_cluster create cluster ...
Check that the machineconfig has the kernel arguments applied
$ oc --kubeconfig log_debug_cluster/auth/kubeconfig get machineconfigs NAME GENERATEDBYCONTROLLER IGNITIONVERSION CREATED 99-master-kargs-loglevel bd846958bc95d049547164046a962054fca093df 3.1.0 26h 99-master-ssh bd846958bc95d049547164046a962054fca093df 3.1.0 26h ... rendered-master-5f4a5bd806567871be1b608474eca373 bd846958bc95d049547164046a962054fca093df 3.1.0 26h $ oc describe machineconfig/rendered-master-5f4a5bd806567871be1b608474eca373 | grep -A 1 "Kernel Arguments" Kernel Arguments: loglevel=7
If you wish to confirm the kernel argument is indeed being applied on the system, you can
oc debug
into a node and check withrpm-ostree kargs
.
With OCP 4.4 and onward release, it is possible to switch from traditional to Real Time (RT) kernel on RHCOS node. During install time, switching to RT kernel can be done through manifests as an installer operation. See customizing MachineConfig to configure kernelType during install time. To set kernelType as day 2 operation, see MachineConfiguration doc.
Example for switching to RT kernel on worker nodes during initial cluster install:
-
Run
manifests
target to create all the manifests.$ mkdir realtime_kernel $ openshift-install --dir realtime_kernel create manifests
-
Create a
MachineConfig
that setskernelType
torealtime
:cat > realtime_kernel/openshift/99-worker-kerneltype.yaml <<EOF apiVersion: machineconfiguration.openshift.io/v1 kind: MachineConfig metadata: labels: machineconfiguration.openshift.io/role: "worker" name: 99-worker-kerneltype spec: config: ignition: version: 3.1.0 kernelType: realtime EOF
-
Run
cluster
target to create the cluster using the custom manifests.$ openshift-install --dir realtime_kernel create cluster
Check that the MachineConfig has the kernelType applied
$ oc --kubeconfig realtime_kernel/auth/kubeconfig get machineconfigs NAME GENERATEDBYCONTROLLER IGNITIONVERSION AGE ... 99-worker-kerneltype 3.1.0 80m 99-worker-ssh 3.1.0 80m rendered-worker-853ba9bf0337db528a857a9c7380b95a 6306be9274cd3052f5075c81fa447c7895b7b9f4 3.1.0 78m ...
-
To confirm that worker node has switched to RT kernel, access one of the worker node and run
uname -a
$ oc --kubeconfig realtime_kernel/auth/kubeconfig debug node/<worker_node> ... sh-4.2# uname -a Linux <worker_node> 4.18.0-147.3.1.rt24.96.el8_1.x86_64 #1 SMP PREEMPT RT Wed Nov 27 18:29:55 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
Note: The RT kernel lowers throughput (performance) in return for improved worst-case latency bounds. This feature is intended only for use cases that require consistent low latency. For more information, see the Linux Foundation wiki and the RHEL RT portal.
RHCOS is a minimal OCP focused OS which provides capabilities common across all the platforms. With extensions support, beginning in OCP 4.6 and onward, users can enable a limited set of additional functionality on the RHCOS nodes. In OCP 4.6 the supported extension is usbguard
.
Extensions can be installed by creating a MachineConfig object. It can be enabled during cluster installation as well as later on. See customizing MachineConfig to enable an extension during install time. For day2 install, see MachineConfiguration doc.
Example MachineConfig to install usbguard on worker nodes:
apiVersion: machineconfiguration.openshift.io/v1
kind: MachineConfig
metadata:
labels:
machineconfiguration.openshift.io/role: worker
name: worker-extensions
spec:
config:
ignition:
version: 3.1.0
extensions:
- usbguard
In rare circumstances, certain modifications to the bootstrap and other machines may be necessary. The installer provides the "ignition-configs" target, which allows arbitrary modification to the Ignition Configs used to boot these machines. Note that there is currently no validation on the modifications that are made, so it is possible that the changes will result in a non-functioning cluster.
An example worker.ign
is shown below. It has been modified to increase the HTTP timeouts used when fetching the generated worker config from the cluster. This isn't likely to be useful, but it does demonstrate what is possible.
{
"ignition": {
"version": "3.1.0",
"config": {
"merge": [{
"source": "https://test-cluster-api.example.com:22623/config/worker"
}]
},
"security": {
"tls": {
"certificateAuthorities": [{
"source": "data:text/plain;charset=utf-8;base64,LS0tLS1CRU..."
}]
}
},
"timeouts": {
"httpResponseHeaders": 120
}
},
"passwd": {
"users": [{
"name": "core",
"sshAuthorizedKeys": [
"ssh-ed25519 AAAA..."
]
}]
}
}