diff --git a/playbooks/groups/batcave.yml b/playbooks/groups/batcave.yml
index e3fa03fd90..383b126603 100644
--- a/playbooks/groups/batcave.yml
+++ b/playbooks/groups/batcave.yml
@@ -58,6 +58,7 @@
   - { role: nfs/client, when: inventory_hostname.startswith('batcave'), mnt_dir: '/srv/web/pub', nfs_src_dir: 'fedora_ftp/fedora.redhat.com/pub' }
   - { role: nfs/client, when: inventory_hostname.startswith('batcave01'), mnt_dir: '/mnt/fedora/app', nfs_src_dir: 'fedora_app/app' }
   - { role: mirror_pagure_ansible, tags: ['mirror_pagure_ansible'] }
+  - kickstarts
 
   pre_tasks:
   - import_tasks: "{{ tasks_path }}/yumrepos.yml"
diff --git a/roles/kickstarts/files/fedora-post.sh b/roles/kickstarts/files/fedora-post.sh
new file mode 100644
index 0000000000..df90efef27
--- /dev/null
+++ b/roles/kickstarts/files/fedora-post.sh
@@ -0,0 +1,25 @@
+#!/bin/bash
+# This script gets run on every host after the kickstart runs.
+
+infraurl="https://infrastructure.fedoraproject.org"
+
+# suck down a root ssh key from our central location
+mkdir -p /root/.ssh
+chmod 700 /root/.ssh
+curl -o /root/.ssh/authorized_keys $infraurl/infra/ssh/admin.pub
+
+#
+# setup our sshd_config
+#
+curl -o /etc/ssh/sshd_config $infraurl/infra/ssh/sshd_config.default 
+restorecon -Rv /etc/ssh
+
+# we don't want /tmp tmpfs
+systemctl mask tmp.mount
+
+systemctl start postfix
+
+echo "$HOSTNAME has just been [re]installed" |/bin/mail -s "$HOSTNAME - INSTALLED" -r admin@fedoraproject.org admin@fedoraproject.org
+
+mkdir -p /etc/ansible/facts.d
+date +%Y%m%d > /etc/ansible/facts.d/install_date.fact
diff --git a/roles/kickstarts/files/rhel9-post.sh b/roles/kickstarts/files/rhel9-post.sh
new file mode 100644
index 0000000000..2ba89d2f93
--- /dev/null
+++ b/roles/kickstarts/files/rhel9-post.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+# This script gets run on every host after the kickstart runs.
+
+infraurl="https://infrastructure.fedoraproject.org"
+
+# suck down a root ssh key from our central location
+mkdir -p /root/.ssh
+chmod 700 /root/.ssh
+curl -o/root/.ssh/authorized_keys $infraurl/infra/ssh/admin.pub
+#
+# setup our sshd_config
+#
+curl -o/etc/ssh/sshd_config $infraurl/infra/ssh/sshd_config.default 
+restorecon -Rv /etc/ssh
+
+#
+# setup our repos
+#
+pushd /etc/yum.repos.d
+curl -O $infraurl/rhel/rhel9.repo
+curl -O $infraurl/rhel/epel9.repo
+curl -O $infraurl/infra/ansible/files/common/rhel-infra-tags.repo
+popd
+
+#
+# This is needed for ansible ssh pipeline support to work
+#
+pushd /etc/sudoers.d
+echo "Defaults !requiretty" > norequiretty
+chmod 440 norequiretty
+popd
+
+systemctl start postfix && \
+    echo "$HOSTNAME has just been [re]installed" | \
+    /bin/mail -s "$HOSTNAME - INSTALLED" \
+    -r admin@fedoraproject.org admin@fedoraproject.org
+
+mkdir -p /etc/ansible/facts.d
+date +%Y%m%d > /etc/ansible/facts.d/install_date.fact
diff --git a/roles/kickstarts/tasks/main.yml b/roles/kickstarts/tasks/main.yml
new file mode 100644
index 0000000000..ef7221e898
--- /dev/null
+++ b/roles/kickstarts/tasks/main.yml
@@ -0,0 +1,24 @@
+---
+- name: Copy kickstart templates to published dir for use
+  ansible.builtin.template:
+    src="{{ item }}".j2
+    dest="/srv/web/repo/rhel/ks/{{ item }}"
+  with_items:
+    - kvm-fedora
+    - kvm-rhel
+    - hardware-rhel-9-08disk
+    - hardware-rhel-9-06disk
+  tags:
+  - config
+  - kickstarts
+
+- name: Copy post install files to published dir for use
+  ansible.builtin.copy:
+    src="{{ item }}"
+    dest="/srv/web/repo/rhel/ks/post/{{ item }}"
+  with_items:
+    - rhel9-post.sh
+    - fedora-post.sh
+  tags:
+  - config
+  - kickstarts
diff --git a/roles/kickstarts/templates/hardware-rhel-9-06disk.j2 b/roles/kickstarts/templates/hardware-rhel-9-06disk.j2
new file mode 100644
index 0000000000..9d515c41b1
--- /dev/null
+++ b/roles/kickstarts/templates/hardware-rhel-9-06disk.j2
@@ -0,0 +1,109 @@
+#
+## This kickstart is for Dell systems with 8 disks. It will build either a virthost or cloud.
+##
+
+# System authorization information
+auth --enableshadow --passalgo=sha512
+# Use network installation
+vnc --password install
+# Use network install
+url --url=https://infrastructure.fedoraproject.org/repo/rhel/RHEL9-x86_64/
+repo --name=epel --baseurl=https://infrastructure.fedoraproject.org/pub/epel/9/Everything/x86_64/
+repo --name="net-baseos"     --baseurl=https://infrastructure.fedoraproject.org/repo/rhel/rhel9/x86_64/rhel-9-for-x86_64-baseos-rpms/
+repo --name="net-appstream"  --baseurl=https://infrastructure.fedoraproject.org/repo/rhel/rhel9/x86_64/rhel-9-for-x86_64-appstream-rpms/
+repo --name="net-crb" --baseurl=https://infrastructure.fedoraproject.org/repo/rhel/rhel9/x86_64/codeready-builder-for-rhel-9-x86_64-rpms/
+
+# Firewall configuration
+firewall --disabled
+firstboot --disable
+# Keyboard layouts
+# old format: keyboard us
+# new format:
+keyboard --vckeymap=us --xlayouts=''
+# System language
+lang en_US.UTF-8
+
+# Network information
+#network  --bootproto=dhcp --device=br0 --bridgeslaves=eth0 --ipv6=off --activate --hostname=localhost.localdomain
+#network  --bootproto=dhcp --device=br1 --bridgeslaves=eth1 --ipv6=off --onboot=off 
+# Reboot after installation
+reboot
+# Root password
+rootpw --iscrypted "{{ kickstart_initial_password_encrypted }}"
+# SELinux configuration
+selinux --enforcing
+# System services
+services --disabled="firewalld,kdump" --enabled="postfix,rsyslog,chronyd"
+# Do not configure the X Window System
+skipx
+# System timezone
+timezone UTC --utc
+# System bootloader configuration
+ignoredisk --only-use=sda,sdb,sdc,sdd,sde,sdf
+bootloader --location=mbr --boot-drive=sda --append="net.ifnames=0" --driveorder=sda,sdb,sdc,sdd,sde,sdf
+zerombr
+clearpart --drives=sda,sdb,sdc,sdd,sde,sdf --all --initlabel
+
+# Disk partitioning information
+part raid.200 --fstype="mdmember" --ondisk=sda --size=1000
+part raid.210 --fstype="mdmember" --ondisk=sdb --size=1000
+part raid.220 --fstype="mdmember" --ondisk=sdc --size=1000
+part raid.230 --fstype="mdmember" --ondisk=sdd --size=1000
+part raid.240 --fstype="mdmember" --ondisk=sde --size=1000
+part raid.250 --fstype="mdmember" --ondisk=sdf --size=1000
+part raid.300 --fstype="mdmember" --ondisk=sda --size=477
+part raid.310 --fstype="mdmember" --ondisk=sdb --size=477
+part raid.320 --fstype="mdmember" --ondisk=sdc --size=477
+part raid.330 --fstype="mdmember" --ondisk=sdd --size=477
+part raid.340 --fstype="mdmember" --ondisk=sde --size=477
+part raid.350 --fstype="mdmember" --ondisk=sdf --size=477
+part raid.400 --fstype="mdmember" --ondisk=sda --size=65536 --grow
+part raid.410 --fstype="mdmember" --ondisk=sdb --size=65536 --grow
+part raid.420 --fstype="mdmember" --ondisk=sdc --size=65536 --grow
+part raid.430 --fstype="mdmember" --ondisk=sdd --size=65536 --grow
+part raid.440 --fstype="mdmember" --ondisk=sde --size=65536 --grow
+part raid.450 --fstype="mdmember" --ondisk=sdf --size=65536 --grow
+
+raid /boot     --device=0 --fstype="ext4"    --level=RAID1  raid.200 raid.210 raid.220 raid.230 raid.240 raid.250
+raid /boot/efi --device=1 --fstype="efi" --level=RAID1 --fsoptions="umask=0077,shortname=winnt" raid.300 raid.310 raid.320 raid.330 raid.340 raid.350
+raid pv.610 --device=2 --fstype="lvmpv" --level=RAID6 --encrypted --passphrase="{{ luks_initial_password }}" --chunksize=512 raid.400 raid.410 raid.420 raid.430 raid.440 raid.450
+
+volgroup vg_guests --pesize=4096 pv.610
+
+logvol /     --fstype="xfs"  --size=100000 --name=LogVol00 --vgname=vg_guests
+logvol swap  --fstype="swap" --size=64000  --name=LogVol01 --vgname=vg_guests
+
+%packages
+-geolite2-city
+-iwl*firmware
+-subscription-manager
+bash-completion
+bind-utils
+clevis*
+cronie-noanacron
+crontabs
+dhclient
+grubby
+iptables-services
+nfs-utils
+nmap-ncat
+openssh-clients
+openssh-server
+patch
+postfix
+rsync
+screen
+strace
+s-nail
+tmpwatch
+tmux
+traceroute
+vim-enhanced
+zsh
+%end
+
+%post --nochroot --log=/mnt/sysimage/root/post.output --erroronfail
+mkdir /mnt/sysimage/root/tmp
+chroot /mnt/sysimage /usr/bin/curl http://infrastructure.fedoraproject.org/rhel/ks/post/rhel9-post.sh -o /root/tmp/rhel9-post.sh
+chroot /mnt/sysimage sh /root/tmp/rhel9-post.sh
+%end
diff --git a/roles/kickstarts/templates/hardware-rhel-9-08disk.j2 b/roles/kickstarts/templates/hardware-rhel-9-08disk.j2
new file mode 100644
index 0000000000..9e9b913118
--- /dev/null
+++ b/roles/kickstarts/templates/hardware-rhel-9-08disk.j2
@@ -0,0 +1,118 @@
+#
+## This kickstart is for Dell systems with 8 disks. It will build either a virthost or cloud.
+##
+
+# System authorization information
+auth --enableshadow --passalgo=sha512
+# Use network installation
+vnc --password install
+# Use network install
+url --url=http://infrastructure.fedoraproject.org/repo/rhel/RHEL9-x86_64/
+repo --name=epel --baseurl=http://infrastructure.fedoraproject.org/pub/epel/9/Everything/x86_64/
+repo --name="net-baseos"     --baseurl=http://infrastructure.fedoraproject.org/repo/rhel/rhel9/x86_64/rhel-9-for-x86_64-baseos-rpms/
+repo --name="net-appstream"  --baseurl=http://infrastructure.fedoraproject.org/repo/rhel/rhel9/x86_64/rhel-9-for-x86_64-appstream-rpms/
+repo --name="net-crb" --baseurl=http://infrastructure.fedoraproject.org/repo/rhel/rhel9/x86_64/codeready-builder-for-rhel-9-x86_64-rpms/
+
+# Firewall configuration
+firewall --disabled
+firstboot --disable
+ignoredisk --only-use=sda,sdb,sdc,sdd,sde,sdf,sdg,sdh
+# Keyboard layouts
+# old format: keyboard us
+# new format:
+keyboard --vckeymap=us --xlayouts=''
+# System language
+lang en_US.UTF-8
+
+# Network information
+#network  --bootproto=dhcp --device=br0 --bridgeslaves=eth0 --ipv6=off --activate --hostname=localhost.localdomain
+#network  --bootproto=dhcp --device=br1 --bridgeslaves=eth1 --ipv6=off --onboot=off 
+# Reboot after installation
+reboot
+# Root password
+rootpw --iscrypted "{{ kickstart_initial_password_encrypted }}"
+# SELinux configuration
+selinux --enforcing
+# System services
+services --disabled="firewalld,kdump" --enabled="postfix,rsyslog,chronyd"
+# Do not configure the X Window System
+skipx
+# System timezone
+timezone UTC --utc
+# System bootloader configuration
+ignoredisk --only-use=sda,sdb,sdc,sdd,sde,sdf,sdg,sdh
+bootloader --location=mbr --boot-drive=sda --append="net.ifnames=0" --driveorder=sda,sdb,sdc,sdd,sde,sdf,sdh
+zerombr
+clearpart --drives=sda,sdb,sdc,sdd,sde,sdf,sdg,sdh --all --initlabel
+
+# Disk partitioning information
+part raid.200 --fstype="mdmember" --ondisk=sda --size=1000
+part raid.210 --fstype="mdmember" --ondisk=sdb --size=1000
+part raid.220 --fstype="mdmember" --ondisk=sdc --size=1000
+part raid.230 --fstype="mdmember" --ondisk=sdd --size=1000
+part raid.240 --fstype="mdmember" --ondisk=sde --size=1000
+part raid.250 --fstype="mdmember" --ondisk=sdf --size=1000
+part raid.260 --fstype="mdmember" --ondisk=sdg --size=1000
+part raid.270 --fstype="mdmember" --ondisk=sdh --size=1000
+part raid.300 --fstype="mdmember" --ondisk=sda --size=477
+part raid.310 --fstype="mdmember" --ondisk=sdb --size=477
+part raid.320 --fstype="mdmember" --ondisk=sdc --size=477
+part raid.330 --fstype="mdmember" --ondisk=sdd --size=477
+part raid.340 --fstype="mdmember" --ondisk=sde --size=477
+part raid.350 --fstype="mdmember" --ondisk=sdf --size=477
+part raid.360 --fstype="mdmember" --ondisk=sdg --size=477
+part raid.370 --fstype="mdmember" --ondisk=sdh --size=477
+part raid.400 --fstype="mdmember" --ondisk=sda --size=65536 --grow
+part raid.410 --fstype="mdmember" --ondisk=sdb --size=65536 --grow
+part raid.420 --fstype="mdmember" --ondisk=sdc --size=65536 --grow
+part raid.430 --fstype="mdmember" --ondisk=sdd --size=65536 --grow
+part raid.440 --fstype="mdmember" --ondisk=sde --size=65536 --grow
+part raid.450 --fstype="mdmember" --ondisk=sdf --size=65536 --grow
+part raid.460 --fstype="mdmember" --ondisk=sdg --size=65536 --grow
+part raid.470 --fstype="mdmember" --ondisk=sdh --size=65536 --grow
+
+raid /boot     --device=0 --fstype="ext4"    --level=RAID1  raid.200 raid.210 raid.220 raid.230 raid.240 raid.250 raid.260 raid.270
+raid /boot/efi --device=1 --fstype="efi" --level=RAID1 --fsoptions="umask=0077,shortname=winnt" raid.300 raid.310 raid.320 raid.330 raid.340 raid.350 raid.360 raid.370
+raid pv.610 --device=2 --fstype="lvmpv" --level=RAID6 --encrypted --passphrase="{{ luks_initial_password }}" --chunksize=512 raid.400 raid.410 raid.420 raid.430 raid.440 raid.450 raid.460 raid.470
+
+volgroup vg_guests --pesize=4096 pv.610
+
+logvol /     --fstype="xfs"  --size=100000 --name=LogVol00 --vgname=vg_guests
+logvol swap  --fstype="swap" --size=64000  --name=LogVol01 --vgname=vg_guests
+
+%packages
+-geolite2-city
+-iwl*firmware
+-subscription-manager
+bash-completion
+bind-utils
+clevis*
+cronie-noanacron
+crontabs
+dhclient
+grubby
+iptables-services
+nfs-utils
+nmap-ncat
+openssh-clients
+openssh-server
+patch
+postfix
+rsync
+screen
+strace
+s-nail
+tmpwatch
+tmux
+traceroute
+vim-enhanced
+zsh
+-insights-client
+-rhc
+%end
+
+%post --nochroot --log=/mnt/sysimage/root/post.output --erroronfail
+mkdir /mnt/sysimage/root/tmp
+chroot /mnt/sysimage /usr/bin/curl http://infrastructure.fedoraproject.org/rhel/ks/post/rhel9-post.sh -o /root/tmp/rhel9-post.sh
+chroot /mnt/sysimage sh /root/tmp/rhel9-post.sh
+%end
diff --git a/roles/kickstarts/templates/kvm-fedora.j2 b/roles/kickstarts/templates/kvm-fedora.j2
new file mode 100644
index 0000000000..185baaec06
--- /dev/null
+++ b/roles/kickstarts/templates/kvm-fedora.j2
@@ -0,0 +1,54 @@
+text
+lang en_US.UTF-8
+rootpw --iscrypted "$6$guz8Ahbu7dooMee7$mMECodGBXWD16v6hSiyWTbSzrbW0qldF4QrX8wlGfFlnqNc7xid9A60BAerNy6/vZS3.V.qywdRQ2TTKeSzOX0"
+firewall --enable --ssh
+timezone --utc UTC
+keyboard us
+selinux --enforcing
+skipx
+reboot
+
+clearpart --all --initlabel
+bootloader
+reqpart --add-boot
+part btrfs.007 --size=2000 --fstype=btrfs --grow
+btrfs none --label=fedora btrfs.007
+btrfs /     --subvol --name=root LABEL=fedora
+
+url --metalink "https://mirrors.fedoraproject.org/metalink?repo=fedora-$releasever&arch=$basearch"
+repo --name=updates --metalink "https://mirrors.fedoraproject.org/metalink?repo=updates-released-f$releasever&arch=$basearch"
+
+%packages
+kernel-core
+-kernel
+bind-utils
+-cronie-anacron
+chrony
+cronie-noanacron
+crontabs
+dhcp-client
+iptables
+iptables-services
+python3-libselinux
+mailx
+nc
+nfs-utils
+openssh-clients
+openssh-server
+patch
+postfix
+rsyslog
+rsync
+screen
+tmux
+strace
+traceroute
+vim-enhanced
+xz
+%end
+
+%post --nochroot --log=/mnt/sysimage/root/post.output --erroronfail
+mkdir /mnt/sysimage/root/tmp
+chroot /mnt/sysimage /usr/bin/curl https://infrastructure.fedoraproject.org/rhel/ks/post/buildvm-post.sh -o /root/tmp/fedora-post.sh
+chroot /mnt/sysimage /bin/bash /root/tmp/fedora-post.sh
+%end
diff --git a/roles/kickstarts/templates/kvm-rhel.j2 b/roles/kickstarts/templates/kvm-rhel.j2
new file mode 100644
index 0000000000..aa9213fdf3
--- /dev/null
+++ b/roles/kickstarts/templates/kvm-rhel.j2
@@ -0,0 +1,80 @@
+text
+skipx
+# License Agreement
+eula --agreed
+# Network information
+
+# Setup Repository info
+url --url=https://infrastructure.fedoraproject.org/repo/rhel/RHEL9-x86_64/
+repo --name=epel --baseurl=https://infrastructure.fedoraproject.org/pub/epel/9/Everything/x86_64/
+repo --name="net-baseos"     --baseurl=https://infrastructure.fedoraproject.org/repo/rhel/rhel9/x86_64/rhel-9-for-x86_64-baseos-rpms/
+repo --name="net-appstream"  --baseurl=https://infrastructure.fedoraproject.org/repo/rhel/rhel9/x86_64/rhel-9-for-x86_64-appstream-rpms/
+repo --name="net-crb" --baseurl=https://infrastructure.fedoraproject.org/repo/rhel/rhel9/x86_64/codeready-builder-for-rhel-9-x86_64-rpms/
+# Run the Setup Agent on first boot
+firstboot --disable
+# Keyboard layouts
+keyboard --vckeymap=us --xlayouts='us'
+# System language
+lang en_US.UTF-8 --addsupport=en_GB.UTF-8
+# System authorization information
+auth --enableshadow --passalgo=sha512
+# Root password
+rootpw --iscrypted "{{ kickstart_initial_password_encrypted }}"
+# System timezone
+timezone UTC --utc
+# System bootloader configuration
+zerombr
+bootloader --append="net.ifnames=0 crashkernel=auto" --location=mbr --boot-drive=vda
+# Partition clearing information
+clearpart --initlabel --all
+# Filesystem Data
+reqpart --add-boot
+part pv.100 --fstype="lvmpv" --size=1000 --grow
+volgroup vg_vm --pesize=4096 pv.100
+logvol /     --fstype="xfs"  --size=10000 --name=LogVol00 --vgname=vg_vm --grow
+logvol swap  --fstype="swap" --size=8192  --name=LogVol01 --vgname=vg_vm
+# What to do at the end
+reboot
+
+%packages
+@core
+authselect-compat
+bash-completion
+bind-utils
+cronie-noanacron
+crontabs
+dhclient
+iptables-services
+nfs-utils
+nmap-ncat
+openssh-clients
+openssh-server
+patch
+postfix
+python3
+python3-libselinux
+rsync
+rsyslog
+strace
+telnet
+tmpwatch
+tmux
+traceroute
+vim-enhanced
+yum
+yum-utils
+zsh
+-biosdevname
+-cronie-anacron
+-subscription-manager
+-insights-client
+-rhc
+-iwl*
+-yum-rhn-plugin
+%end
+
+%post --nochroot --log=/mnt/sysimage/root/post.output --erroronfail
+mkdir /mnt/sysimage/root/tmp
+chroot /mnt/sysimage /usr/bin/curl https://infrastructure.fedoraproject.org/rhel/ks/post/rhel9-post.sh -o /root/tmp/rhel9-post.sh
+chroot /mnt/sysimage /bin/bash /root/tmp/rhel9-post.sh
+%end