diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..619a4f8b803772ad4d5e578a0a483769b4e13a62
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+/config/*.ign
+/.idea/
+/manifest.json
\ No newline at end of file
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..24ffa698631052cfa282895d28cee18dff823b92
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,4 @@
+.PHONY: all
+all:
+	make -C config
+	hetzner-robot-automation manifest.json
\ No newline at end of file
diff --git a/config/Makefile b/config/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..033dfb3f90d1a1e7aa7795a68275956cae55b837
--- /dev/null
+++ b/config/Makefile
@@ -0,0 +1,5 @@
+configs := $(wildcard *.bu)
+
+.PHONY: ignition.ign
+ignition.ign: $(configs)
+	yq eval-all '. as $$item ireduce ({}; . *+ $$item )' $^ | butane -d . -sp -o $@
diff --git a/config/kubernetes.bu b/config/kubernetes.bu
new file mode 100644
index 0000000000000000000000000000000000000000..93a651a89228fb76c0bbcc8ad9c9f7ecfbe6540b
--- /dev/null
+++ b/config/kubernetes.bu
@@ -0,0 +1,94 @@
+variant: fcos
+version: 1.4.0
+storage:
+  files:
+    - path: /etc/yum.repos.d/kubernetes.repo
+      mode: 0644
+      contents:
+        local: kubernetes/repo.conf
+    - path: /etc/modules-load.d/k8s.conf
+      mode: 0644
+      contents:
+        local: kubernetes/modules.conf
+    - path: /etc/sysctl.d/k8s.conf
+      mode: 0644
+      contents:
+        local: kubernetes/sysctl.conf
+    - path: /etc/dnf/modules.d/cri-o.module
+      mode: 0644
+      overwrite: true
+      contents:
+        inline: |
+          [cri-o]
+          name=cri-o
+          stream=1.17
+          profiles=
+          state=enabled
+    - path: /etc/kubernetes/kubeadm-config.yaml
+      mode: 0600
+      contents:
+        local: kubernetes/kubeadm.yaml
+    - path: /root/.bashrc.d/kubeconfig.sh
+      mode: 0755
+      contents:
+        inline: |-
+          export KUBECONFIG=/etc/kubernetes/admin.conf
+    - path: /usr/local/bin/cilium
+      mode: 0755
+      contents:
+        source: https://github.com/cilium/cilium-cli/releases/latest/download/cilium-linux-amd64.tar.gz
+        compression: gzip
+systemd:
+  units:
+    - name: kubernetes-install.service
+      enabled: true
+      contents: |
+        [Unit]
+        Description=Install Overlay Packages
+        Requires=NetworkManager-wait-online.service
+        Requires=zincati.service
+        After=NetworkManager-wait-online.service
+        After=zincati.service
+        Before=multi-user.target
+
+        [Service]
+        Type=oneshot
+        RemainAfterExit=yes
+        ExecStart=rpm-ostree install kubelet kubeadm kubectl helm cri-o --idempotent --reboot
+
+        [Install]
+        RequiredBy=multi-user.target
+        WantedBy=multi-user.target
+    - name: kubernetes-init.service
+      enabled: true
+      contents: |
+        [Unit]
+        Description=Initialize Kubernetes Cluster
+        Requires=NetworkManager-wait-online.service
+        Requires=kubernetes-install.service
+        After=NetworkManager-wait-online.service
+        After=kubernetes-install.service
+        Before=multi-user.target
+
+        [Service]
+        Type=oneshot
+        RemainAfterExit=yes
+        User=root
+        Group=root
+        ExecStartPre=systemctl enable --now kubelet crio
+        ExecStart=kubeadm init \
+            --config /etc/kubernetes/kubeadm-config.yaml \
+            --skip-phases mark-control-plane
+        ExecStartPost=helm install cilium cilium \
+            --kubeconfig /etc/kubernetes/admin.conf \
+            --repo https://helm.cilium.io/ \
+            --version 1.12.0 \
+            --namespace kube-system \
+            --set cni.binPath=/opt/cni/bin/ \
+            --set cni.confPath=/etc/cni/net.d \
+            --set operator.replicas=1 \
+            --set hubble.relay.enabled=true \
+            --set hubble.ui.enabled=true \
+            --set kubeProxyReplacement=disabled
+        [Install]
+        WantedBy=multi-user.target
\ No newline at end of file
diff --git a/config/kubernetes/kubeadm.yaml b/config/kubernetes/kubeadm.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..9c02d624d740afbf4f02f6498ce10be43611adf9
--- /dev/null
+++ b/config/kubernetes/kubeadm.yaml
@@ -0,0 +1,14 @@
+apiVersion: kubeadm.k8s.io/v1beta3
+kind: InitConfiguration
+nodeRegistration:
+  kubeletExtraArgs:
+    volume-plugin-dir: "/opt/libexec/kubernetes/kubelet-plugins/volume/exec/"
+  criSocket: "unix:///var/run/crio/crio.sock"
+---
+apiVersion: kubeadm.k8s.io/v1beta3
+kind: ClusterConfiguration
+controllerManager:
+  extraArgs:
+    flex-volume-plugin-dir: "/opt/libexec/kubernetes/kubelet-plugins/volume/exec/"
+networking:
+  podSubnet: "10.244.0.0/16"
diff --git a/config/kubernetes/modules.conf b/config/kubernetes/modules.conf
new file mode 100644
index 0000000000000000000000000000000000000000..a13fc1798d7fc00fa672d49db70d5331cf4427d1
--- /dev/null
+++ b/config/kubernetes/modules.conf
@@ -0,0 +1 @@
+br_netfilter
diff --git a/config/kubernetes/repo.conf b/config/kubernetes/repo.conf
new file mode 100644
index 0000000000000000000000000000000000000000..65eda50b5bf0405c666239ad543d1a9cc7a59c17
--- /dev/null
+++ b/config/kubernetes/repo.conf
@@ -0,0 +1,7 @@
+[kubernetes]
+name=Kubernetes
+baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64
+enabled=1
+gpgcheck=1
+repo_gpgcheck=1
+gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
diff --git a/config/kubernetes/sysctl.conf b/config/kubernetes/sysctl.conf
new file mode 100644
index 0000000000000000000000000000000000000000..8df03f11a49efdf78d2cd70f2989533acf83c59f
--- /dev/null
+++ b/config/kubernetes/sysctl.conf
@@ -0,0 +1,3 @@
+net.bridge.bridge-nf-call-iptables  = 1
+net.bridge.bridge-nf-call-ip6tables = 1
+net.ipv4.ip_forward                 = 1
diff --git a/config/network.bu b/config/network.bu
new file mode 100644
index 0000000000000000000000000000000000000000..417ab1174db643001f7ea3c059a1c27d5836e44b
--- /dev/null
+++ b/config/network.bu
@@ -0,0 +1,12 @@
+variant: fcos
+version: 1.4.0
+storage:
+  files:
+    - path: /etc/hostname
+      mode: 0644
+      contents:
+        inline: nitrogen.kuschku.de
+    - path: /etc/NetworkManager/system-connections/enp0s31f6.nmconnection
+      mode: 0600
+      contents:
+        local: network/connection.ini
diff --git a/config/network/connection.ini b/config/network/connection.ini
new file mode 100644
index 0000000000000000000000000000000000000000..4e4a0fb0dfffd43c3c14dba34c4d28106d4001d3
--- /dev/null
+++ b/config/network/connection.ini
@@ -0,0 +1,22 @@
+[connection]
+id=enp0s31f6
+type=ethernet
+interface-name=enp0s31f6
+
+[ethernet]
+mac-address-blacklist=
+mtu=auto
+
+[ipv4]
+address1=148.251.132.182/32,148.251.132.161
+dns=8.8.8.8
+dns-priority=100
+dns-search=
+may-fail=false
+method=manual
+
+[ipv6]
+address1=2a01:4f8:210:3186::1/64,fe80::1
+dns-priority=100
+dns-search=
+method=manual
diff --git a/config/selinux_disable.bu b/config/selinux_disable.bu
new file mode 100644
index 0000000000000000000000000000000000000000..86438dafcaa10fbf3d7f4ca91c55d0a69ef69c2d
--- /dev/null
+++ b/config/selinux_disable.bu
@@ -0,0 +1,5 @@
+variant: fcos
+version: 1.4.0
+kernel_arguments:
+  should_exist:
+    - selinux=0
diff --git a/config/smt_enable.bu b/config/smt_enable.bu
new file mode 100644
index 0000000000000000000000000000000000000000..ddfc321416062bfaa980dc70b2955c4688ae15da
--- /dev/null
+++ b/config/smt_enable.bu
@@ -0,0 +1,7 @@
+variant: fcos
+version: 1.4.0
+kernel_arguments:
+  should_exist:
+    - mitigations=auto
+  should_not_exist:
+    - mitigations=auto,nosmt
diff --git a/config/ssh_authorized_keys.bu b/config/ssh_authorized_keys.bu
new file mode 100644
index 0000000000000000000000000000000000000000..e36b13e21eab6af30a615644e40278cc407e86c1
--- /dev/null
+++ b/config/ssh_authorized_keys.bu
@@ -0,0 +1,12 @@
+variant: fcos
+version: 1.4.0
+passwd:
+  users:
+    - name: core
+      ssh_authorized_keys:
+        #- "sk-ecdsa-sha2-nistp256@openssh.com AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3BlbnNzaC5jb20AAAAIbmlzdHAyNTYAAABBBAjcAKCjQOCcZDTNnpwuruMPwMUi/sguTOt8bhUvWYE3zplaxb+DeAAw6/GuDNFHje6fr73uyy0lUfsx1vCUpnAAAAAEc3NoOg== blue:janne@discovery"
+        #- "sk-ecdsa-sha2-nistp256@openssh.com AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3BlbnNzaC5jb20AAAAIbmlzdHAyNTYAAABBBBwjBa2Djk00G9MR+hIcW3oZ3G0LNGHT6gTZwCTdqibC4pxwXgtHFTFhYFDY0ySTI96QQtf+iQkHgxrAdIjcxaIAAAAEc3NoOg== black:janne@discovery"
+        - "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC6lUSmgANEiwHOXX8C15UPbmEeqHGtLviULB/HcRn9zrhJ5YyQPaMmu4wmCXLw3lA2marl2dyMcvqIFgZXLb0UcSJu+UiF+cCWAS9KEzcROcocm5DbTsAOi2kz7PVhBu5SVo8W42L5IdJhk6FyxvZAadUAg+viNAqR9y9I/3J+7hzZYyTtPP/xvIEe/HrXd9gONP7v6H73ou69PUM+OjV2u1PpYk5PByWaa+Smnftr9ziUjIhjzFmV2fRwAxoh/S2ttR3zv4plAFuuZxObKq3oO3evwgF7PG7vH4Fb1AgMu+euQtc5EjcVGyC01XQjVkeC2L1n0wDTUgD03qesfhWb janne@discovery"
+        #- "sk-ecdsa-sha2-nistp256@openssh.com AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3BlbnNzaC5jb20AAAAIbmlzdHAyNTYAAABBBIbESjs0T8rxl1LCWm2Dowi6pNPxGC4JUs+1cge/1MdU3Xpdmyu/etl7oXM//e2AYj9wX7tPre7TTJsElvkAc1QAAAAEc3NoOg== black:janne@curiosity"
+        #- "sk-ecdsa-sha2-nistp256@openssh.com AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3BlbnNzaC5jb20AAAAIbmlzdHAyNTYAAABBBNDcOUzfmt0X2f7+0hY5UnzMQH5/VLzjss77xqWw7poMzF+rBTvaoU+qeVfXDYvyqpeUoOV27uc7AHDxPbnhhpQAAAAEc3NoOg== blue:janne@curiosity"
+        - "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC39uDh9/3/sbAh72zdPfHZE3iGSsbppgiEKZPvZHgndbdGPz5JvnMn+K+VqjLLDMH5Ez+LJUIxPJcolH4iuGCEXcA/7SM6c8V5OII/S/533fgHbBhK4DUDyMMOsTPSM5HInArcn+h6/RVJ+vJgBZVh2DeR2XAEL+9q2oZQLvyq8yjGD30m4K0pYFjSRFsiyGITvghYoKdoGkF8bOKir9nymwWF1bVywCBHCMlyXFXn3zy+Xrkab0Y5SD0bRAXBL8U2PoCNBPNtqggW364AxYL4LGjN+tOsi0A7es6L05LQdDcUIRogDpMSlburoir+Z+CYX8O2oj96NQkBHV0dQlikcT87bCHRnFxxas0ZqS27Wf/OwtNlAC5eNRv4a1KMln80s9RjJUWvJcmw9hx/KHWJLQui07kClSk+kjxALP7/xnrclqa1tk7xzNysuHlXuvRO/4JURjQ8gLzo6V1IsEieH6rnu55HhPrq+flmzl02z5J3a835jk1t87NHV3p2A48= janne@curiosity"
diff --git a/config/storage_raid.bu b/config/storage_raid.bu
new file mode 100644
index 0000000000000000000000000000000000000000..686b0974a29d53698086d1febfb555c105ef3361
--- /dev/null
+++ b/config/storage_raid.bu
@@ -0,0 +1,61 @@
+variant: fcos
+version: 1.4.0
+storage:
+  disks:
+    - device: /dev/nvme0n1
+      partitions:
+        - label: root-1
+          size_mib: 65536
+        - label: var-1
+          size_mib: 65536
+        - label: storage-ssd-1
+    - device: /dev/nvme1n1
+      partitions:
+        - label: root-2
+          size_mib: 65536
+        - label: var-2
+          size_mib: 65536
+        - label: storage-ssd-2
+    - device: /dev/sda
+      partitions:
+        - label: storage-hdd-1
+    - device: /dev/sdb
+      partitions:
+        - label: storage-hdd-2
+  raid:
+    - name: md-var
+      level: raid1
+      devices:
+        - /dev/disk/by-partlabel/var-1
+        - /dev/disk/by-partlabel/var-2
+    - name: md-storage-ssd
+      level: raid1
+      devices:
+        - /dev/disk/by-partlabel/storage-ssd-1
+        - /dev/disk/by-partlabel/storage-ssd-2
+    - name: md-storage-hdd
+      level: raid1
+      devices:
+        - /dev/disk/by-partlabel/storage-hdd-1
+        - /dev/disk/by-partlabel/storage-hdd-2
+  filesystems:
+    - device: /dev/md/md-var
+      path: /var
+      format: xfs
+      wipe_filesystem: true
+      with_mount_unit: true
+    - device: /dev/md/md-storage-ssd
+      path: /var/lib/data-ssd
+      format: xfs
+      wipe_filesystem: true
+      with_mount_unit: true
+    - device: /dev/md/md-storage-hdd
+      path: /var/lib/data-hdd
+      format: xfs
+      wipe_filesystem: true
+      with_mount_unit: true
+boot_device:
+  mirror:
+    devices:
+      - /dev/nvme0n1
+      - /dev/nvme1n1
diff --git a/install.sh b/install.sh
new file mode 100755
index 0000000000000000000000000000000000000000..fe02821ade3317fc2c6bf3c1f0779ed1cf791d06
--- /dev/null
+++ b/install.sh
@@ -0,0 +1,43 @@
+#!/bin/bash
+set -euo pipefail
+
+update-alternatives --set iptables /usr/sbin/iptables-legacy
+
+apt-get update
+apt-get install --no-install-recommends -y podman
+
+wipefs -a /dev/md/* || true
+(ls /dev/md/* | xargs -n1 mdadm --stop) || true
+wipefs -a /dev/nvme0n1p* || true
+wipefs -a /dev/nvme1n1p* || true
+wipefs -a /dev/nvme0n1
+wipefs -a /dev/nvme1n1
+wipefs -a /dev/sda
+wipefs -a /dev/sdb
+
+podman run \
+    --pull=always \
+    --privileged \
+    --rm \
+    -v /dev:/dev \
+    -v /run/udev:/run/udev \
+    -v .:/data \
+    -w /data \
+    quay.io/coreos/coreos-installer:release \
+    install \
+    --ignition-file /data/ignition.ign \
+    --platform metal \
+    --delete-karg mitigations=auto,nosmt \
+    --append-karg mitigations=auto \
+    --append-karg selinux=0 \
+    -- \
+    /dev/nvme0n1
+
+mkdir -p /mnt/boot
+
+mount /dev/nvme0n1p2 /mnt/boot
+rm /mnt/boot/EFI/fedora/BOOTX64.CSV
+umount /mnt/boot || true
+
+lsblk
+systemctl reboot