<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.tetrain.com/index.php?action=history&amp;feed=atom&amp;title=Tornedo.tetrain.com_Runbook</id>
	<title>Tornedo.tetrain.com Runbook - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.tetrain.com/index.php?action=history&amp;feed=atom&amp;title=Tornedo.tetrain.com_Runbook"/>
	<link rel="alternate" type="text/html" href="https://wiki.tetrain.com/index.php?title=Tornedo.tetrain.com_Runbook&amp;action=history"/>
	<updated>2026-07-25T18:57:27Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.43.9</generator>
	<entry>
		<id>https://wiki.tetrain.com/index.php?title=Tornedo.tetrain.com_Runbook&amp;diff=4211&amp;oldid=prev</id>
		<title>Admin: Publish runbook documentation</title>
		<link rel="alternate" type="text/html" href="https://wiki.tetrain.com/index.php?title=Tornedo.tetrain.com_Runbook&amp;diff=4211&amp;oldid=prev"/>
		<updated>2026-07-25T16:41:30Z</updated>

		<summary type="html">&lt;p&gt;Publish runbook documentation&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;Reproducible, command-by-command runbook. Companion to [[Tornedo.tetrain.com Upgrade Plan|&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;tornedo.tetrain.com_upgrade_plan.md&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;]] (the decision log — why each choice was made, dead ends, root-cause analysis). Read that for context; use this to execute.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;What this actually is&amp;#039;&amp;#039;&amp;#039;: not an OS upgrade of the original box. An in-place &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;leapp&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; chain was attempted first and was blocked by IPA&amp;#039;s own tooling (&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;ipa-server does not support in-place upgrade&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; — a hard inhibitor, not a config problem). The real migration is &amp;#039;&amp;#039;&amp;#039;build a brand-new IPA server, replicate data onto it, promote it to primary, retire the original&amp;#039;&amp;#039;&amp;#039; — a replica-and-promote pattern, executed through an *intermediate* bridge server because a direct replica jump from IPA 4.6 (2017) straight to IPA 4.13 failed outright (CA-cloning &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;403 Forbidden&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; — a real protocol incompatibility across ~7 major versions).&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Provenance note on exactness&amp;#039;&amp;#039;&amp;#039;: the commands below are the literal ones recorded during execution — most of the destructive/privileged steps in this migration required Directory Manager or &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;admin&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; Kerberos credentials, which were deliberately never handled directly (the client ran those specific commands themselves, each time, in their own session — noted inline below wherever that applies). Everything else was run and captured directly. Re-verified live on 2026-07-25: &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;ipa.tetrain.com&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; is confirmed AlmaLinux 9.7 / IPA 4.13.1, with the exact 4GB &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;/swapfile&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; entry in &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;/etc/fstab&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; described in Phase 3 still present and in use.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Phase 0 — Pre-upgrade diagnostics on the original server (&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;tornedo.tetrain.com&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;) ==&lt;br /&gt;
&lt;br /&gt;
Do this regardless of which upgrade strategy you end up using — both found real, independently worth-fixing problems.&lt;br /&gt;
&lt;br /&gt;
=== 0.1 Cert auto-renewal was broken (found, not caused, by this work) ===&lt;br /&gt;
&lt;br /&gt;
Symptom: three certmonger-tracked certs (LDAP/&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;dirsrv&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;httpd&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;, KDC) all show &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;status: MONITORING&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;auto-renew: yes&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; but every renewal attempt fails with:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;nowiki&amp;gt;&lt;br /&gt;
Error setting up ccache for &amp;quot;host&amp;quot; service on client using default keytab:&lt;br /&gt;
Keytab contains no suitable keys for host/ip-172-26-27-51.ap-south-1.compute.internal@.&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Root cause: this is an AWS EC2 instance; its live system hostname had drifted to the AWS internal DNS name instead of the enrolled FQDN (&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;/etc/krb5.keytab&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; only has keys for &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;host/tornedo.tetrain.com&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;) — almost certainly cloud-init resetting the hostname on a prior reboot.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;nowiki&amp;gt;&lt;br /&gt;
hostnamectl set-hostname tornedo.tetrain.com&lt;br /&gt;
&lt;br /&gt;
# prevent recurrence — stop cloud-init from resetting it again on the next reboot&lt;br /&gt;
cat &amp;gt;&amp;gt; /etc/cloud/cloud.cfg &amp;lt;&amp;lt;&amp;#039;EOF&amp;#039;&lt;br /&gt;
preserve_hostname: true&lt;br /&gt;
EOF&lt;br /&gt;
&lt;br /&gt;
# resubmit the three near-expiry cert requests (get the request IDs from `getcert list` first)&lt;br /&gt;
getcert resubmit -i &amp;lt;ldap-request-id&amp;gt;&lt;br /&gt;
getcert resubmit -i &amp;lt;httpd-request-id&amp;gt;&lt;br /&gt;
getcert resubmit -i &amp;lt;kdc-request-id&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# confirm&lt;br /&gt;
getcert list   # all should show status: MONITORING, no ca-error, new far-future expiry&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Verified: all three cleared, new expiry &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;2028-07-23&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; on all three.&lt;br /&gt;
&lt;br /&gt;
=== 0.2 Duplicate RPM versions + point-release patch ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;nowiki&amp;gt;&lt;br /&gt;
package-cleanup --dupes          # will show duplicate-version entries for ipa-server,&lt;br /&gt;
                                  # 389-ds-base, krb5-server, pki-ca etc. — sign of a prior&lt;br /&gt;
                                  # interrupted/incomplete update&lt;br /&gt;
yum check&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Client-run patch update to latest available CentOS 7.9 (via Vault — 7&amp;#039;s regular mirrors are gone):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;nowiki&amp;gt;&lt;br /&gt;
# repoint at Vault first if not already — the box&amp;#039;s mirrorlist is dead for a pruned EOL release&lt;br /&gt;
sed -i &amp;#039;s|mirrorlist=|#mirrorlist=|; s|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|&amp;#039; \&lt;br /&gt;
  /etc/yum.repos.d/CentOS-Base.repo&lt;br /&gt;
yum update -y&lt;br /&gt;
needs-restarting -r   # confirms glibc/systemd/openssl-libs/kernel installed but not yet active&lt;br /&gt;
reboot&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After reboot:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;nowiki&amp;gt;&lt;br /&gt;
uname -r              # confirm new kernel is actually running&lt;br /&gt;
ipactl status          # every service should report RUNNING&lt;br /&gt;
getcert list           # all certs still MONITORING, no errors&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then the actual cleanup (client ran this step directly — review the transaction list before confirming, watch for grub2/dracut/kernel entries):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;nowiki&amp;gt;&lt;br /&gt;
package-cleanup --cleandupes&lt;br /&gt;
package-cleanup --dupes    # re-verify clean&lt;br /&gt;
yum check&lt;br /&gt;
ipactl status&lt;br /&gt;
getcert list&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Full consistent backup, taken after the above (needed regardless of upgrade strategy):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;nowiki&amp;gt;&lt;br /&gt;
ipa-backup --data --logs&lt;br /&gt;
# -&amp;gt; /var/lib/ipa/backup/ipa-full-&amp;lt;timestamp&amp;gt;, briefly stops/restarts IPA services for&lt;br /&gt;
#    consistency (seconds, not a real outage)&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Phase 1 — In-place &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;leapp&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; attempt (abandoned — kept for the record, don&amp;#039;t repeat) ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;nowiki&amp;gt;&lt;br /&gt;
leapp preupgrade&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the point where the strategy changed: &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;leapp preupgrade&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; reported 5 inhibitors, one of which was &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;ipa-server does not support in-place upgrade&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; — Red Hat&amp;#039;s own tooling refuses to leapp-upgrade a FreeIPA/IdM server outright and points to a separate IdM migration guide. &amp;#039;&amp;#039;&amp;#039;Do not attempt &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;leapp upgrade&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; on an IPA server&amp;#039;&amp;#039;&amp;#039; — go straight to Phase 2&amp;#039;s replica-and-promote pattern instead.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Phase 2 — Build the intermediate bridge replica (&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;ipa8.tetrain.com&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;, Rocky Linux 8.10) ==&lt;br /&gt;
&lt;br /&gt;
Needed because a direct IPA-4.6-to-IPA-4.13 replica failed at CA-cloning with &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;403 Forbidden&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; — too many major versions apart. This bridge server is temporary — built, used once to carry data forward, then decommissioned (Phase 4).&lt;br /&gt;
&lt;br /&gt;
=== 2.1 Base OS + firewall ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;nowiki&amp;gt;&lt;br /&gt;
# this box has firewalld active (the eventual final-target box, ipa.tetrain.com, does not —&lt;br /&gt;
# check per-box, don&amp;#039;t assume)&lt;br /&gt;
firewall-cmd --permanent --add-service=freeipa-ldap&lt;br /&gt;
firewall-cmd --permanent --add-service=freeipa-ldaps&lt;br /&gt;
firewall-cmd --permanent --add-service=dns&lt;br /&gt;
firewall-cmd --permanent --add-service=http&lt;br /&gt;
firewall-cmd --permanent --add-service=https&lt;br /&gt;
firewall-cmd --permanent --add-service=kerberos&lt;br /&gt;
firewall-cmd --permanent --add-port=464/tcp --add-port=464/udp&lt;br /&gt;
firewall-cmd --permanent --add-port=8080/tcp --add-port=8443/tcp&lt;br /&gt;
firewall-cmd --reload&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 2.2 Fix &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;/etc/hosts&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; before attempting install ===&lt;br /&gt;
&lt;br /&gt;
Cloud-init&amp;#039;s default template mapped this box&amp;#039;s own hostname to &amp;#039;&amp;#039;&amp;#039;both&amp;#039;&amp;#039;&amp;#039; &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;127.0.0.1&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;::1&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; — IPA&amp;#039;s installer explicitly refuses a hostname that resolves to loopback.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;nowiki&amp;gt;&lt;br /&gt;
# edit /etc/hosts: remove the loopback mapping for this box&amp;#039;s own hostname, add a real line:&lt;br /&gt;
#   &amp;lt;real-ip&amp;gt;  ipa8.tetrain.com  ipa8&lt;br /&gt;
&lt;br /&gt;
# stop cloud-init from reverting it on next boot:&lt;br /&gt;
echo &amp;#039;manage_etc_hosts: false&amp;#039; &amp;gt;&amp;gt; /etc/cloud/cloud.cfg&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also add an entry for the &amp;#039;&amp;#039;&amp;#039;old&amp;#039;&amp;#039;&amp;#039; server here too — it has the same AWS-default-PTR reverse-DNS mismatch as Phase 0.1, and this box needs to resolve it correctly to talk to it:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;nowiki&amp;gt;&lt;br /&gt;
echo &amp;#039;&amp;lt;tornedo-real-ip&amp;gt;  tornedo.tetrain.com&amp;#039; &amp;gt;&amp;gt; /etc/hosts&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 2.3 Install IPA (EL8 packages it via a DNF module, not a plain package) ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;nowiki&amp;gt;&lt;br /&gt;
dnf module enable idm:DL1 -y&lt;br /&gt;
dnf install -y @idm:DL1/server @idm:DL1/dns   # dns component per your actual topology needs&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 2.4 Run the replica install ===&lt;br /&gt;
&lt;br /&gt;
Needs real &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;admin&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; Kerberos credentials for &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;check_creds&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;, not just the host keytab — &amp;#039;&amp;#039;&amp;#039;run &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;kinit&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; and the install command together in one session that never leaves your hands&amp;#039;&amp;#039;&amp;#039; (this migration&amp;#039;s rule throughout: admin/Directory Manager passwords are never typed into or passed through the assisting session):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;nowiki&amp;gt;&lt;br /&gt;
kinit admin&lt;br /&gt;
ipa-replica-install --setup-ca --unattended&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If a prior attempt failed and needs retrying:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;nowiki&amp;gt;&lt;br /&gt;
ipa-server-install --uninstall -U&lt;br /&gt;
# this also wipes client enrollment — get a fresh OTP before retrying:&lt;br /&gt;
#   on the SOURCE server: ipa host-disable ipa8.tetrain.com ; ipa host-mod --random ipa8.tetrain.com&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Two non-fatal warnings are expected and fine (&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;acmeIPAServerCert&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; profile import failure, &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;dnaHostname&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; lookup timeout — both known transient issues during replica install). Immediately after a successful install, run:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;nowiki&amp;gt;&lt;br /&gt;
ipa-server-upgrade&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(re-migrates certificate profiles, clears the two warnings above).&lt;br /&gt;
&lt;br /&gt;
=== 2.5 Validate before moving on ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;nowiki&amp;gt;&lt;br /&gt;
ipactl status                              # all 7 services RUNNING&lt;br /&gt;
getcert list                               # all certs MONITORING, no errors&lt;br /&gt;
ldapsearch -Y EXTERNAL -H ldapi:/// -b &amp;quot;&amp;quot; -s base   # LDAPI search succeeds&lt;br /&gt;
kinit -kt /etc/krb5.keytab host/ipa8.tetrain.com    # ticket issuance works&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Phase 3 — Build the final target (&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;ipa.tetrain.com&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;, AlmaLinux 9) from the bridge ==&lt;br /&gt;
&lt;br /&gt;
Confirmed live 2026-07-25: this box is AlmaLinux 9.7, &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;ipa-server-4.13.1-3.el9_8.2&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;389-ds-base-2.8.0-8.el9_8&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;krb5-server-1.21.1-10.el9_8&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Networking between &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;ipa8&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; and this box was already fully open both directions on ports 389/636/88/464/80/443/8080/8443 — check this per-pair, don&amp;#039;t assume it&amp;#039;s always already open.&lt;br /&gt;
&lt;br /&gt;
=== 3.1 Same &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;/etc/hosts&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; loopback fix as Phase 2.2 ===&lt;br /&gt;
&lt;br /&gt;
Same class of bug, same fix, on this box too.&lt;br /&gt;
&lt;br /&gt;
=== 3.2 Critical: add swap before attempting &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;--setup-ca&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
This box has 1.6G RAM and (originally) zero swap. The CA database init step spawns a JVM (&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;ca-db-init&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;) that OOMs *silently* — no debug log, no catalina output, exit code 255, no kernel OOM-killer entry (the JVM fails to reserve heap before its own logging initializes). &amp;#039;&amp;#039;&amp;#039;Add swap before attempting the CA setup, not after failing once&amp;#039;&amp;#039;&amp;#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;nowiki&amp;gt;&lt;br /&gt;
fallocate -l 4G /swapfile&lt;br /&gt;
chmod 600 /swapfile&lt;br /&gt;
mkswap /swapfile&lt;br /&gt;
swapon /swapfile&lt;br /&gt;
echo &amp;#039;/swapfile swap swap defaults 0 0&amp;#039; &amp;gt;&amp;gt; /etc/fstab&lt;br /&gt;
free -h   # confirm swap is present&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(Confirmed live 2026-07-25: this exact &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;/swapfile&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; + &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;/etc/fstab&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; entry is still in place and in active use — 295MB in use at time of check.)&lt;br /&gt;
&lt;br /&gt;
=== 3.3 Run the replica install ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;nowiki&amp;gt;&lt;br /&gt;
kinit admin   # client-run, same rule as Phase 2.4&lt;br /&gt;
ipa-replica-install --setup-ca --skip-mem-check --unattended&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;--skip-mem-check&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; is required here specifically because of the low-RAM box above — without it the installer refuses to proceed even with swap present.&lt;br /&gt;
&lt;br /&gt;
If retrying after a failed attempt, clean up in this order (all recurring issues on this hop):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;nowiki&amp;gt;&lt;br /&gt;
# 1. stale topology/master entry left by any attempt that got past &amp;quot;adding master entry&amp;quot;&lt;br /&gt;
#    before failing later — host-disable/host-mod CANNOT touch a master entry, must force-delete:&lt;br /&gt;
ipa server-del ipa.tetrain.com --force&lt;br /&gt;
&lt;br /&gt;
# 2. kill orphaned processes from a failed uninstall (ipa-server-install --uninstall often&lt;br /&gt;
#    reports success without actually stopping these) — prefer stop+pkill over `disable` for&lt;br /&gt;
#    ad-hoc cleanup, since `disable` can remove the systemd .wants/ symlink directory as a side&lt;br /&gt;
#    effect and break the NEXT install attempt&amp;#039;s symlink creation:&lt;br /&gt;
systemctl stop pki-tomcatd@pki-tomcat.service&lt;br /&gt;
pkill -9 ns-slapd&lt;br /&gt;
pkill -9 -f pki-tomcatd&lt;br /&gt;
ps aux | grep -E &amp;#039;ns-slapd|pki-tomcatd&amp;#039;   # confirm actually gone before retrying&lt;br /&gt;
mkdir -p /etc/systemd/system/pki-tomcatd.target.wants/   # recreate if a `disable` removed it&lt;br /&gt;
&lt;br /&gt;
ipa-server-install --uninstall -U&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Immediately after a successful install:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;nowiki&amp;gt;&lt;br /&gt;
ipa-server-upgrade&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 3.4 Validate ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;nowiki&amp;gt;&lt;br /&gt;
ipactl status&lt;br /&gt;
kinit -kt /etc/krb5.keytab host/ipa.tetrain.com   # issues a valid krbtgt/TORNEDO.TETRAIN.COM ticket&lt;br /&gt;
ipa user-show admin                                # full LDAP+API roundtrip&lt;br /&gt;
curl -sI https://ipa.tetrain.com/ipa/ui/            # expect HTTP/1.1 200&lt;br /&gt;
free -h                                             # confirm swap actually got used during install&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also worth checking from a real existing production client (not the box itself) — proves actual external reachability without touching that client&amp;#039;s persistent config:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;nowiki&amp;gt;&lt;br /&gt;
# from any already-enrolled client:&lt;br /&gt;
nc -zv ipa.tetrain.com 389 636 88 464 80 443&lt;br /&gt;
ldapsearch -x -H ldap://ipa.tetrain.com -b &amp;#039;&amp;#039; -s base namingcontexts&lt;br /&gt;
# expect: dc=tornedo,dc=tetrain,dc=com  and  o=ipaca&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Phase 4 — Decommission the intermediate bridge (&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;ipa8.tetrain.com&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;) ==&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Do not &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;server-del&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; the bridge directly&amp;#039;&amp;#039;&amp;#039; — it&amp;#039;s the only link connecting the original and the final target; deleting it first splits the topology into two disconnected islands with no sync path between them (IPA&amp;#039;s own topology check catches and blocks this correctly). Add a direct segment between the two *remaining* servers first, for &amp;#039;&amp;#039;&amp;#039;both&amp;#039;&amp;#039;&amp;#039; suffixes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;nowiki&amp;gt;&lt;br /&gt;
ipa topologysegment-add domain --leftnode=tornedo.tetrain.com --rightnode=ipa.tetrain.com&lt;br /&gt;
ipa topologysegment-add ca --leftnode=tornedo.tetrain.com --rightnode=ipa.tetrain.com&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Verify both new agreements are actually replicating before proceeding:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;nowiki&amp;gt;&lt;br /&gt;
ipa topologysegment-find domain&lt;br /&gt;
ipa topologysegment-find ca&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now the bridge is safe to remove:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;nowiki&amp;gt;&lt;br /&gt;
ipa server-del ipa8.tetrain.com --force&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Verify:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;nowiki&amp;gt;&lt;br /&gt;
ipactl status                    # all 7 services RUNNING on ipa.tetrain.com&lt;br /&gt;
getcert list                     # all 9 certs MONITORING (ipa-custodia&amp;#039;s renewal role&lt;br /&gt;
                                  #  shouldn&amp;#039;t be disrupted even though ipa8 was its&lt;br /&gt;
                                  #  install-time &amp;quot;master peer&amp;quot;)&lt;br /&gt;
ipa user-show admin              # LDAP+API roundtrip still works&lt;br /&gt;
ipa topologysegment-find domain  # only the direct tornedo&amp;lt;-&amp;gt;ipa.tetrain.com link remains,&lt;br /&gt;
                                  # no references to ipa8 anywhere&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;ipa8.tetrain.com&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&amp;#039;s VM is now safe to power off.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Phase 5 — SRV-based cutover (not an IP/identity handoff) ==&lt;br /&gt;
&lt;br /&gt;
Checked first: &amp;#039;&amp;#039;&amp;#039;confirm no DNS SRV records already exist&amp;#039;&amp;#039;&amp;#039; for the domain (&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;dig&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; — if every client is relying purely on the literal hostname, this is your situation and this approach applies). This is simpler than making &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;ipa.tetrain.com&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; impersonate &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;tornedo.tetrain.com&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&amp;#039;s identity (fragile, not well-supported) — instead, publish real SRV records under the *old* hostname&amp;#039;s zone, pointing at the new server&amp;#039;s *own* name:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;nowiki&amp;gt;&lt;br /&gt;
_ldap._tcp.tornedo.tetrain.com.            SRV 0 100 389  ipa.tetrain.com.&lt;br /&gt;
_kerberos._tcp.tornedo.tetrain.com.        SRV 0 100 88   ipa.tetrain.com.&lt;br /&gt;
_kerberos._udp.tornedo.tetrain.com.        SRV 0 100 88   ipa.tetrain.com.&lt;br /&gt;
_kerberos-master._tcp.tornedo.tetrain.com. SRV 0 100 88   ipa.tetrain.com.&lt;br /&gt;
_kerberos-master._udp.tornedo.tetrain.com. SRV 0 100 88   ipa.tetrain.com.&lt;br /&gt;
_kpasswd._tcp.tornedo.tetrain.com.         SRV 0 100 464  ipa.tetrain.com.&lt;br /&gt;
_kpasswd._udp.tornedo.tetrain.com.         SRV 0 100 464  ipa.tetrain.com.&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(Plain client-discovery SRV records — &amp;#039;&amp;#039;&amp;#039;not&amp;#039;&amp;#039;&amp;#039; the &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;_msdcs.&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;-style records &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;ipa-adtrust-install&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; prints, which are for actual Windows AD trust interop and weren&amp;#039;t needed here.)&lt;br /&gt;
&lt;br /&gt;
Every &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;sssd.conf&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; in this fleet already has &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;ipa_server = _srv_, tornedo.tetrain.com&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; — SRV lookup first, literal-name fallback second — so once these records exist, enrolled clients discover and switch to &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;ipa.tetrain.com&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; with &amp;#039;&amp;#039;&amp;#039;zero client-side config changes&amp;#039;&amp;#039;&amp;#039;, and &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;tornedo.tetrain.com&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&amp;#039;s A record can stay up as a fallback the whole time.&lt;br /&gt;
&lt;br /&gt;
Client published all 7 records. Verify:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;nowiki&amp;gt;&lt;br /&gt;
dig SRV _ldap._tcp.tornedo.tetrain.com +short&lt;br /&gt;
dig SRV _kerberos._tcp.tornedo.tetrain.com +short&lt;br /&gt;
# ... (repeat for all 7) — all should resolve, correct priority/weight/port, target ipa.tetrain.com.&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
End-to-end proof it&amp;#039;s actually working, from a real enrolled client:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;nowiki&amp;gt;&lt;br /&gt;
systemctl restart sssd&lt;br /&gt;
cat /var/lib/sss/pubconf/kdcinfo.TORNEDO.TETRAIN.COM&lt;br /&gt;
# should now show ipa.tetrain.com&amp;#039;s IP, not tornedo.tetrain.com&amp;#039;s — this is the literal&lt;br /&gt;
# artifact SSSD writes with its discovery result, the most reliable way to confirm SRV&lt;br /&gt;
# discovery actually worked (vs. just &amp;quot;dig succeeded&amp;quot;)&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Phase 6 — Critical gotcha: missing SIDs break login for real (non-admin) users ==&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Symptom&amp;#039;&amp;#039;&amp;#039;: &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;admin&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; logs into &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;ipa.tetrain.com&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&amp;#039;s web UI fine; every other real user fails with the same password, even though it works on &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;tornedo.tetrain.com&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;. Confirmed via &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;krb5kdc.log&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;: a normal user&amp;#039;s AS-REQ fails at &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;HANDLE_AUTHDATA: ... No such file or directory&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; during PAC generation — &amp;#039;&amp;#039;&amp;#039;not&amp;#039;&amp;#039;&amp;#039; &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;PREAUTH_FAILED&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; (not a password problem).&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Root cause&amp;#039;&amp;#039;&amp;#039;: &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;ipa-replica-install --unattended&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; silently skips SID generation for existing users when it can&amp;#039;t prompt interactively — this is the exact warning unattended mode swallows: *&amp;quot;N existing users or groups do not have a SID identifier assigned... installer will NOT run ipa-sidgen task.&amp;quot;* IPA 4.13 enforces PAC/SID generation during ticket issuance more strictly than IPA 4.6 does, so this only breaks on the *new* server despite identical replicated LDAP data.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Fix — run this after every unattended replica install that involves a version jump&amp;#039;&amp;#039;&amp;#039;, don&amp;#039;t wait for a real user to hit it:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;nowiki&amp;gt;&lt;br /&gt;
# ipa-adtrust-install isn&amp;#039;t installed by the base @idm:DL1/server module — separate package:&lt;br /&gt;
dnf install -y ipa-server-trust-ad&lt;br /&gt;
ipa-adtrust-install -U --add-sids&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Verify:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;nowiki&amp;gt;&lt;br /&gt;
ldapsearch -Y EXTERNAL -H ldapi:/// -b &amp;quot;dc=tornedo,dc=tetrain,dc=com&amp;quot; \&lt;br /&gt;
  &amp;quot;(&amp;amp;(objectClass=posixAccount)(!(ipaNTSecurityIdentifier=*)))&amp;quot; uid&lt;br /&gt;
# should return zero users&lt;br /&gt;
ldapsearch -Y EXTERNAL -H ldapi:/// -b &amp;quot;uid=&amp;lt;real-user&amp;gt;,cn=users,cn=accounts,dc=tornedo,dc=tetrain,dc=com&amp;quot; ipaNTSecurityIdentifier&lt;br /&gt;
# should now show S-1-5-21-...-&amp;lt;rid&amp;gt;&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;smb&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;winbind&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; services will now also be running (side effect of &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;ipa-adtrust-install&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;, expected). Have the real user re-test their actual login as final confirmation.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Phase 7 — Promote the CA renewal master ==&lt;br /&gt;
&lt;br /&gt;
The renewal master defaults to whichever server is currently the only one — needs to move explicitly once there&amp;#039;s more than one CA replica:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;nowiki&amp;gt;&lt;br /&gt;
ipa-csreplica-manage set-renewal-master ipa.tetrain.com&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Needs the &amp;#039;&amp;#039;&amp;#039;Directory Manager&amp;#039;&amp;#039;&amp;#039; password specifically (more privileged than &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;admin&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;) — client-run, same rule as every other admin-credential step. Verify:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;nowiki&amp;gt;&lt;br /&gt;
ldapsearch -Y EXTERNAL -H ldapi:/// -b &amp;quot;cn=masters,cn=ipa,cn=etc,dc=tornedo,dc=tetrain,dc=com&amp;quot; \&lt;br /&gt;
  &amp;quot;(cn=CA)&amp;quot; ipaConfigString&lt;br /&gt;
# should show: ipaConfigString: caRenewalMaster   on the ipa.tetrain.com entry&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Phase 8 — Client remediation reference (recurring bug classes found during fleet sweep) ==&lt;br /&gt;
&lt;br /&gt;
Not a linear sequence — this is a diagnostic reference for &amp;#039;&amp;#039;&amp;#039;any client that doesn&amp;#039;t switch to the new server after the Phase 5 SRV records go live&amp;#039;&amp;#039;&amp;#039;, encountered across ~50 hosts during the actual sweep. Check in this order:&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;8.1 — Simple caching lag (try first, cheapest check):&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;nowiki&amp;gt;&lt;br /&gt;
systemctl restart sssd            # or: /etc/init.d/sssd restart  (no-systemd boxes)&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Resolves the majority of &amp;quot;stuck on old IP&amp;quot; cases by itself.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;8.2 — &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;dns_lookup_kdc = false&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;/etc/krb5.conf&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;:&amp;#039;&amp;#039;&amp;#039; SRV discovery is disabled at the Kerberos level entirely — no amount of waiting fixes this.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;nowiki&amp;gt;&lt;br /&gt;
sed -i &amp;#039;s/dns_lookup_kdc = false/dns_lookup_kdc = true/&amp;#039; /etc/krb5.conf&lt;br /&gt;
systemctl restart sssd&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;8.3 — Wrong &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;dns_discovery_domain&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;sssd.conf&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;:&amp;#039;&amp;#039;&amp;#039; If it&amp;#039;s set to a *shorter* suffix than the real IPA domain (e.g. &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;tetrain.com&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; instead of &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;tornedo.tetrain.com&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;), SSSD constructs and queries the wrong SRV record names entirely (&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;_ldap._tcp.tetrain.com&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;, which doesn&amp;#039;t exist) — silent failure, &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;dig&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; with the *correct* full name still works manually, which masks this during casual diagnosis. Confirmed on 3+ hosts.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;nowiki&amp;gt;&lt;br /&gt;
# in sssd.conf, correct only dns_discovery_domain — leave ipa_domain alone if other config&lt;br /&gt;
# depends on it (some long-established clients have ipa_domain = tetrain.com tied to other&lt;br /&gt;
# working config; don&amp;#039;t touch it, just fix dns_discovery_domain):&lt;br /&gt;
sed -i &amp;#039;s/dns_discovery_domain = tetrain.com/dns_discovery_domain = tornedo.tetrain.com/&amp;#039; /etc/sssd/sssd.conf&lt;br /&gt;
systemctl restart sssd&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A host stuck on the old IP even after an aggressive &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;sss_cache -E&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; + full stop/start needs &amp;#039;&amp;#039;&amp;#039;both&amp;#039;&amp;#039;&amp;#039; 8.2 and 8.3 checked — they&amp;#039;re independent settings causing an identical-looking symptom.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;8.4 — Wrong &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;ipa_domain&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; (distinct from 8.3, found during a later live-outage remediation):&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;nowiki&amp;gt;&lt;br /&gt;
# correct ALL of: [domain/...] section header, domains=, ipa_domain, ipa_server static&lt;br /&gt;
# fallback in sssd.conf, and [realms] kdc/admin_server in krb5.conf — all need to agree on&lt;br /&gt;
# the real domain, tornedo.tetrain.com, not a shortened alias&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;8.5 — Host firewall allowlist (packets never leave the host):&amp;#039;&amp;#039;&amp;#039; Some hosts run a default-DROP &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;iptables OUTPUT&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; policy with an explicit per-destination-IP allowlist that has the old server&amp;#039;s IP hardcoded but never got the new one added — correct DNS/krb5 config doesn&amp;#039;t help if the packets are dropped before leaving the box.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;nowiki&amp;gt;&lt;br /&gt;
iptables -A OUTPUT -d &amp;lt;ipa.tetrain.com-IP&amp;gt; -j ACCEPT   # mirror whatever rule pattern the&lt;br /&gt;
                                                         # old server&amp;#039;s IP already has&lt;br /&gt;
iptables-save &amp;gt; /etc/sysconfig/iptables   # or your distro&amp;#039;s persistence mechanism&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;8.6 — Local DNS resolver lying (one host, but worth checking anywhere self-hosting DNS):&amp;#039;&amp;#039;&amp;#039; A host whose own &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;/etc/resolv.conf&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; lists itself as the *first* nameserver can return a valid empty &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;NOERROR&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; for the SRV query — glibc&amp;#039;s resolver treats that as final and never falls through to the other working resolvers listed after it, even though they&amp;#039;d succeed. Config looks completely correct; DNS is just silently lying.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;nowiki&amp;gt;&lt;br /&gt;
# reorder /etc/resolv.conf: put a working recursive resolver FIRST, keep the local one but&lt;br /&gt;
# deprioritized (don&amp;#039;t remove it if other local config depends on it)&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;8.7 — Debian/Ubuntu-specific: &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;ipa-client-install&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; doesn&amp;#039;t wire up PAM the way RHEL does.&amp;#039;&amp;#039;&amp;#039; RHEL-family systems use &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;authselect&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;, which &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;ipa-client-install&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; configures automatically. Debian/Ubuntu use &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;pam-auth-update&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;, a &amp;#039;&amp;#039;&amp;#039;separate&amp;#039;&amp;#039;&amp;#039; mechanism &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;ipa-client-install&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; doesn&amp;#039;t touch — enrollment can report success while login still fails completely with zero SSSD log activity (looks identical to &amp;quot;wrong password&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;nowiki&amp;gt;&lt;br /&gt;
# after ipa-client-install completes on any Debian-family box, always:&lt;br /&gt;
pam-auth-update --force --enable sss&lt;br /&gt;
pam-auth-update --force --enable mkhomedir   # if --mkhomedir was passed to ipa-client-install&lt;br /&gt;
                                               # and doesn&amp;#039;t seem to be creating home dirs&lt;br /&gt;
# --force is needed if the image ships a &amp;quot;local modification&amp;quot; in common-auth (e.g. a custom&lt;br /&gt;
# nullok tweak) that would otherwise block the non-forced update&lt;br /&gt;
grep pam_sss /etc/pam.d/common-auth /etc/pam.d/common-account   # verify before calling it done&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;8.8 — &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;/etc/hosts&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; with swapped hostname labels + loopback (recurring on new-onboarding, not just the migration):&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;nowiki&amp;gt;&lt;br /&gt;
# e.g. &amp;quot;sysnet-zurt&amp;quot; written where the real hostname is &amp;quot;zurt-sysnet&amp;quot;, AND pointed at 127.0.1.1&lt;br /&gt;
# — ipa-client-install fails outright with a Python socket.gaierror before even reaching the&lt;br /&gt;
# usual loopback-resolution failure. Fix: correct hostname + real routable IP, same as Phase&lt;br /&gt;
# 2.2/3.1, plus manage_etc_hosts: false in cloud-init config.&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;8.9 — Ubuntu 25.10+: &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;sudo-rs&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; silently ignores IPA sudo rules.&amp;#039;&amp;#039;&amp;#039; Symptom: a user with a confirmed-valid IPA sudo rule (&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;ipa sudorule-show &amp;lt;rule&amp;gt;&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;) gets denied, with &amp;#039;&amp;#039;&amp;#039;zero&amp;#039;&amp;#039;&amp;#039; SSSD sudo-responder log activity even though &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;libsss-sudo&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; is installed and the SSSD sudo socket exists and is correctly permissioned. Root cause: Ubuntu 25.10 ships &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;sudo-rs&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; (Rust reimplementation) as the *default* &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;/usr/bin/sudo&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;, and it doesn&amp;#039;t support SSSD/IPA-driven sudo rules — falls back to local-file-only sudoers evaluation with a plausible-looking denial and no diagnostic trail. Classic GNU sudo is usually already installed alongside it, just not the active alternative (registered at &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;/usr/bin/sudo.ws&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; on this Ubuntu convention, no &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;dpkg-divert&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; involved):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;nowiki&amp;gt;&lt;br /&gt;
update-alternatives --install /usr/bin/sudo sudo /usr/bin/sudo.ws 50&lt;br /&gt;
update-alternatives --set sudo /usr/bin/sudo.ws&lt;br /&gt;
sudo --version         # confirm it no longer reports &amp;quot;sudo-rs&amp;quot;&lt;br /&gt;
sudo -l -U &amp;lt;user&amp;gt;       # confirm it now shows the real IPA-sourced rule&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;8.10 — Missing &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;chrony&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; on minimal/stripped images:&amp;#039;&amp;#039;&amp;#039; &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;ipa-client-install&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; tries to configure &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;chrony&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; for time sync but doesn&amp;#039;t install it if missing — fails outright at that step.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;nowiki&amp;gt;&lt;br /&gt;
apt-get install -y chrony    # or dnf/yum equivalent — before retrying ipa-client-install&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Phase 9 — Security incident found + remediated during this work (fail2ban) ==&lt;br /&gt;
&lt;br /&gt;
Not part of the migration itself, but found while investigating why &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;admin&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&amp;#039;s Kerberos account kept hitting lockout thresholds (&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;krbPwdMaxFailure&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;) during cleanup work — real, active exposure.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Diagnosis&amp;#039;&amp;#039;&amp;#039;: &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;krb5kdc.log&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; showed repeated auth failures against &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;kadmin/changepw&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; for a long-disabled account (&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;nsAccountLock: TRUE&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;, expired since 2022) from &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;relay.isgec.com&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;, plus &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;admin&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; itself getting hit from two other boxes. On &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;relay.isgec.com&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;: &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;ss -tnp&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; showed multiple simultaneous SSH connections from wildly different, geographically scattered public IPs — signature of a distributed credential-stuffing botnet. That box had &amp;#039;&amp;#039;&amp;#039;no fail2ban&amp;#039;&amp;#039;&amp;#039; and &amp;#039;&amp;#039;&amp;#039;&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;PasswordAuthentication yes&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&amp;#039;&amp;#039;&amp;#039; — fully exposed.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;nowiki&amp;gt;&lt;br /&gt;
# CentOS 7, post-EOL mirrors pruned — fail2ban-server needs systemd-python, which needs a&lt;br /&gt;
# systemd bump unavailable on the regular (dead) mirrors:&lt;br /&gt;
sed -i &amp;#039;s|mirrorlist=|#mirrorlist=|; s|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org/7.9.2009|&amp;#039; \&lt;br /&gt;
  /etc/yum.repos.d/CentOS-Base.repo&lt;br /&gt;
yum install -y fail2ban&lt;br /&gt;
systemctl is-system-running   # confirm &amp;quot;running&amp;quot; after the systemd bump, no reboot needed on EL7&lt;br /&gt;
                               # (live daemon-reexec handles it)&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;/etc/fail2ban/jail.local&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;nowiki&amp;gt;&lt;br /&gt;
[sshd]&lt;br /&gt;
enabled = true&lt;br /&gt;
maxretry = 5&lt;br /&gt;
bantime = 3600&lt;br /&gt;
findtime = 600&lt;br /&gt;
ignoreip = 127.0.0.1/8 &amp;lt;your-own-VPN-egress-IP&amp;gt;&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;nowiki&amp;gt;&lt;br /&gt;
systemctl enable --now fail2ban&lt;br /&gt;
fail2ban-client status sshd            # confirm jail active&lt;br /&gt;
fail2ban-client get sshd ignoreip      # confirm your own IP is whitelisted BEFORE relying on this&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This picked up the already-in-progress attack immediately (214 failed attempts recorded, 5 attacking IPs banned on the spot).&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;This is very likely fleet-wide, not just this one host&amp;#039;&amp;#039;&amp;#039; — was not swept beyond this box. Before considering this closed elsewhere: check &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;fail2ban&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; presence + &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;PasswordAuthentication&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; setting on every reachable box in the fleet, apply the same fix pattern, and consider disabling SSH password auth fleet-wide (key-only) as the actual fix rather than just rate-limiting.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Current state / what&amp;#039;s still open ==&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;tornedo.tetrain.com&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; (original box) — client-shut-down, not yet formally decommissioned (Phase 3-5 of the separate decommission checklist in the decision log). All hosts found still live-dependent on it at the last readiness check have since been individually remediated (Phase 8 patterns above) and verified with a live &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;kinit -k&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;.&lt;br /&gt;
* Fleet-wide fail2ban sweep (Phase 9) — not done beyond &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;relay.isgec.com&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;.&lt;br /&gt;
* A handful of active clients were found hitting the old server that weren&amp;#039;t in the original 50-host inventory at all (unidentified IPs with regular live traffic) — need identifying and properly enrolling against &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;ipa.tetrain.com&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; before the original box can be considered fully safe to power off for good.&lt;br /&gt;
&lt;br /&gt;
[[Category:Infrastructure Documentation]]&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
</feed>