Tu Emacs no puede hacer sudo en NixOS: la cacería del setuid perdido
El síntoma
Editas un fichero de sistema en Emacs, está en solo-lectura, y haces
lo lógico: sudo-this-file (en Doom, SPC f U)
para reabrirlo como root. Y en vez de pedirte la contraseña, te
escupe:
Tramp: Opening connection for root@host using sudo...failed
File error: Tramp failed to connect.
Un mensaje inútil. "Failed to connect" no dice por qué. Y aquí es donde mucha gente empieza a probar cosas al azar —cambiar el método, el shell, reinstalar TRAMP— y a perder la tarde. Vamos a no hacer eso.
La regla de oro: busca el error de VERDAD antes de tocar nada
El mensaje de la superficie miente o se queda corto. Pero TRAMP —como casi todo en Emacs y en Unix— guarda un registro mucho más detallado de lo que hace por dentro. Solo hay que subirle el volumen:
(setq tramp-verbose 6) ; por defecto es 3; 6 ya cuenta intimidades
Reintenta la operación, y TRAMP habrá creado un buffer oculto con la
traza completa. Lo encuentras con C-x b y buscando
*debug tramp...* (algo como
*debug tramp/sudo root@host*). Ábrelo y léelo de abajo
arriba.
Ahí, enterrado entre líneas técnicas, estaba el error que importaba:
sudo: /run/current-system/sw/bin/sudo must be owned by uid 0
and have the setuid bit set
Eso sí dice algo. Ya no estás a ciegas.
Qué significa (y de paso, una pieza de Unix que conviene saber)
Para que sudo pueda "convertirte en root", el sistema le
da un permiso especial llamado setuid
bit. Es lo que le permite a un programa ejecutarse con
la identidad de su dueño (root) en vez de la tuya. Sin
ese bit, sudo es un programa normal y corriente que no
puede elevar nada —y por eso se queja con ese "must be owned by uid
0".
El error nos dice qué sudo está intentando usar:
/run/current-system/sw/bin/sudo. Y ese no
tiene el bit.
El detalle de NixOS: hay DOS sudo
Aquí está el quid, y es muy de NixOS. En este sistema los binarios
viven en un almacén inmutable (el
/nix/store), y por seguridad nada de ahí puede tener el
setuid bit (un binario inmutable con poderes de root
sería un agujero). Entonces, ¿cómo tienes sudo funcionando?
NixOS crea una copia especial, "con poderes", en un sitio aparte:
| Ruta | setuid | Sirve para root |
|---|---|---|
/run/current-system/sw/bin/sudo |
NO | ✗ (el que cogía TRAMP) |
/run/wrappers/bin/sudo |
SÍ | ✓ (el bueno) |
En tu terminal normal todo va bien porque tu PATH tiene
/run/wrappers/bin primero. Pero el proceso de Emacs (sobre
todo si arranca como daemon desde el gestor de ventanas) puede tener el
PATH en otro orden, y TRAMP acaba cogiendo el
sudo inútil.
El arreglo: una línea
Solo hay que garantizar que el sudo con setuid gane.
Aseguramos que su carpeta vaya primero
en el PATH que ve Emacs:
;; NixOS: el sudo REAL (con setuid) esta en /run/wrappers/bin, no en
;; /run/current-system/sw/bin. Que TRAMP coja el bueno.
(unless (string-prefix-p "/run/wrappers/bin" (or (getenv "PATH") ""))
(setenv "PATH" (concat "/run/wrappers/bin:" (getenv "PATH"))))
(after! tramp
(add-to-list 'tramp-remote-path 'tramp-own-remote-path))
Lo pruebas en caliente con M-x eval-expression sobre un
(file-readable-p "/sudo::/etc/hostname") —si devuelve
t, ya conecta—, lo dejas fijo en tu config, recargas, y
sudo-this-file funciona a la primera para siempre.
La moraleja, que vale para todo
El arreglo fue una línea. Pero llegar a esa línea fue lo de verdad importante, y se resume en una frase:
La mitad de depurar es encontrar el mensaje correcto.
"Failed to connect" no te lleva a ningún sitio. "must be owned by uid 0" te lleva directo a la solución. La diferencia entre los dos no fue suerte: fue subir el nivel de detalle y leer el log de verdad antes de empezar a cambiar cosas a lo loco. Casi todo —TRAMP, un servidor, un build que peta— tiene un modo verboso o un buffer de debug escondido. Ese hábito, "primero leo el error real, luego arreglo", te ahorra más tardes que cualquier truco concreto.
— doomguru
Comentarios (0)
Sin comentarios todavia. Se el primero!
Deja un comentario