fix(system): hostname rename updates /etc/hosts and re-announces mDNS
server.set-name ran hostnamectl but left Debian's 127.0.1.1 line on the old name (breaking sudo's 'unable to resolve host' and hostname -f) and waited on avahi to notice the change by itself. Sync /etc/hosts and avahi-set-host-name (fallback: try-restart avahi-daemon) right after a successful rename, so http(s)://<hostname>.local works immediately — best-effort, never blocks the rename. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
0f5ea9ae15
commit
178ba85c5c
@@ -53,6 +53,7 @@ impl RpcHandler {
|
|||||||
// hit a hostname-mismatch warning on top of the usual self-signed one
|
// hit a hostname-mismatch warning on top of the usual self-signed one
|
||||||
// the moment a node is renamed.
|
// the moment a node is renamed.
|
||||||
if hostname_updated {
|
if hostname_updated {
|
||||||
|
sync_hostname_side_effects(&hostname).await;
|
||||||
if let Err(e) = regenerate_tls_cert(&hostname).await {
|
if let Err(e) = regenerate_tls_cert(&hostname).await {
|
||||||
warn!(hostname = %hostname, "TLS cert regen after rename failed: {}", e);
|
warn!(hostname = %hostname, "TLS cert regen after rename failed: {}", e);
|
||||||
}
|
}
|
||||||
@@ -375,6 +376,46 @@ pub(super) fn hostname_from_server_name(name: &str) -> String {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Post-rename side effects that keep the OS consistent with the new
|
||||||
|
/// hostname — all best-effort, the rename itself has already succeeded.
|
||||||
|
/// Debian resolves the local hostname via the 127.0.1.1 line in /etc/hosts;
|
||||||
|
/// leaving the old name there breaks `sudo` ("unable to resolve host") and
|
||||||
|
/// `hostname -f`. And while avahi eventually follows the kernel hostname,
|
||||||
|
/// re-announcing immediately makes http(s)://<hostname>.local links work
|
||||||
|
/// right after the rename instead of minutes later.
|
||||||
|
async fn sync_hostname_side_effects(hostname: &str) {
|
||||||
|
// hostname_from_server_name guarantees [a-z0-9-], safe to interpolate.
|
||||||
|
let script = format!(
|
||||||
|
"if grep -q '^127\\.0\\.1\\.1' /etc/hosts; then sed -i 's/^127\\.0\\.1\\.1.*/127.0.1.1\\t{h}/' /etc/hosts; else printf '127.0.1.1\\t{h}\\n' >> /etc/hosts; fi",
|
||||||
|
h = hostname
|
||||||
|
);
|
||||||
|
match tokio::process::Command::new("/usr/bin/sudo")
|
||||||
|
.args(["-n", "/bin/sh", "-c", &script])
|
||||||
|
.output()
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
Ok(o) if o.status.success() => {}
|
||||||
|
Ok(o) => warn!(
|
||||||
|
"/etc/hosts hostname sync failed: {}",
|
||||||
|
String::from_utf8_lossy(&o.stderr).trim()
|
||||||
|
),
|
||||||
|
Err(e) => warn!("/etc/hosts hostname sync failed: {}", e),
|
||||||
|
}
|
||||||
|
|
||||||
|
let republished = tokio::process::Command::new("/usr/bin/sudo")
|
||||||
|
.args(["-n", "/usr/bin/avahi-set-host-name", hostname])
|
||||||
|
.output()
|
||||||
|
.await
|
||||||
|
.map(|o| o.status.success())
|
||||||
|
.unwrap_or(false);
|
||||||
|
if !republished {
|
||||||
|
let _ = tokio::process::Command::new("/usr/bin/sudo")
|
||||||
|
.args(["-n", "/usr/bin/systemctl", "try-restart", "avahi-daemon"])
|
||||||
|
.output()
|
||||||
|
.await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async fn set_system_hostname(hostname: &str) -> Result<()> {
|
async fn set_system_hostname(hostname: &str) -> Result<()> {
|
||||||
let output = tokio::process::Command::new("/usr/bin/sudo")
|
let output = tokio::process::Command::new("/usr/bin/sudo")
|
||||||
.args(["-n", "/usr/bin/hostnamectl", "set-hostname", hostname])
|
.args(["-n", "/usr/bin/hostnamectl", "set-hostname", hostname])
|
||||||
|
|||||||
Reference in New Issue
Block a user