diff --git a/ansible/roles/ironic/templates/ironic-tftp.json.j2 b/ansible/roles/ironic/templates/ironic-tftp.json.j2
index f3b426fcf7..46859ef61d 100644
--- a/ansible/roles/ironic/templates/ironic-tftp.json.j2
+++ b/ansible/roles/ironic/templates/ironic-tftp.json.j2
@@ -2,7 +2,7 @@
 {% set pxe_cfg = 'grub.cfg' if enable_ironic_pxe_uefi | bool else 'default' %}
 
 {
-    "command": "/usr/sbin/in.tftpd --verbose --foreground --user root --address 0.0.0.0:69 --map-file /map-file /var/lib/ironic/tftpboot",
+    "command": "/usr/sbin/in.tftpd --verbose --foreground --user nobody --address 0.0.0.0:69 --map-file /map-file /var/lib/ironic/tftpboot",
     "config_files": [
 {% if not ironic_dnsmasq_serve_ipxe | bool and groups['ironic-inspector'] | length > 0 %}
 {% if not enable_ironic_pxe_uefi | bool %}
diff --git a/releasenotes/notes/ironic-tftp-nobody-835803ba36398ea3.yaml b/releasenotes/notes/ironic-tftp-nobody-835803ba36398ea3.yaml
new file mode 100644
index 0000000000..2c7489e60e
--- /dev/null
+++ b/releasenotes/notes/ironic-tftp-nobody-835803ba36398ea3.yaml
@@ -0,0 +1,6 @@
+---
+security:
+  - |
+    Kolla Ansible used to run Ironic's tftpd as an (unprivileged) root
+    user.
+    Now, it will explicitly use the nobody user.