Jun 01 2026

¡GEOS v1.0.0: Emacs como PID 1, con soporte completo GNU/Hurd!

Tag: advanced,internals/hackingadmin @ 2:53 pm

Hace unos meses publiqué la v0.1 de GEOS (GNU/Emacs Operating System), un sistema operativo donde Emacs es a la vez el userland y el PID 1. Hoy etiqueto la v1.0.0. La novedad es que ya no hace falta hablar en condicional sobre GNU/Hurd: Emacs es PID 1 también ahí, con sesión multi-usuario EXWM de extremo a extremo sobre Debian GNU/Hurd 0.9 canónico.

Tésis

Emacs no es un editor que corre sobre un sistema operativo. Emacs ES el sistema operativo. El kernel da abstracción del hardware. Todo lo que hay por encima (supervisión de procesos, shell, gestor de ventanas, visor de logs, gestor de paquetes, configurador de red, asistente de instalación) vive en buffers, escrito en Elisp, evaluable en caliente, introspectable con C-h f.

El primer proceso de userspace que arranca el kernel es un binario en C diminuto que monta los pseudo-filesystems, recoge zombis, lee /etc/hostname, y hace execve a Emacs. El mismo código C se compila una segunda vez como módulo dinámico de Emacs y se carga desde early-init.el, así que el supervisor vive dentro del proceso supervisado. No hay Shepherd. No hay systemd. No hay /etc/init.d. Si esa frase incomoda, bien, debería.

¿Por qué GNU/Hurd?

Porque la pieza que falta del puzzle GNU es la que tiene casi cuarenta años y la gente sigue asumiendo que no se puede usar en serio. Porque «Emacs como PID 1 sobre Linux» tiene su gracia, pero «Emacs como PID 1 sobre el Hurd» cierra el círculo que Stallman dibujó en una nota al pie hace mucho tiempo. Y porque si funciona en los dos kernels, el código está obligado a respetar una capa de abstracción honesta entre lo específico del kernel y lo que no, lo cual mejora la calidad de todo lo demás.

¿Qué funciona en Debian GNU/Hurd 0.9?

  • pid1 arranca a Hurd, hace setup de los traductores correctos, ejecuta execve a emacs y carga el módulo dinámico que expone los primitives del supervisor.
  • Sesión multi-usuario con login, audit, throttle, lockout y footer de último acceso. El handshake de peer-cred usa auth_server_authenticate sobre Hurd (en Linux es SO_PEERCRED).
  • EXWM 0.33 sobre Xvfb. Las ventanas X11 son buffers de Emacs igual que en Linux. Xorg nativo con DRM sobre Hurd queda como trabajo upstream.
  • SSH de extremo a extremo: ssh -p 2266 root@127.0.0.1 abre una sesión interactiva contra el emacs supervisado.
  • Asistente de instalación: el wizard M-x install formatea con mkfs.ext4 e instala GRUB sobre un segundo disco, todo a través de los wrappers Elisp.
  • M-x geos-poweroff y M-x geos-reboot usan host_reboot vía get_privileged_ports en Hurd, y reboot(2) en Linux. No hay /sbin/poweroff al que llamar; el supervisor ES Emacs y la respuesta a «apaga» vive en Elisp.
  • Buffers de sistema: *processes*, *network*, *journal*, *services*, *disks*, *packages*, *users*, *audio*, *install*. Todos vivos con timer de refresco.

Seam port_caps

Cada syscall específico de Linux dentro de pid1/ pasa por un struct de punteros a función. La implementación Linux vive en port_linux.c y la de Hurd en port_hurd.c (esta última en la rama lateral hurd, rebase semanal sobre main). El Elisp por encima nunca sabe sobre qué kernel está corriendo; consulta geos-kernel sólo si necesita decidir algo concreto.

El build STATIC=1 compila el binario emacs-init de Hurd como ejecutable estático puro: cero dependencias dinámicas, alrededor de 1.5 MiB. Eso es lo que se hornea dentro de la imagen derivada cuando ejecuto iso-build/hurd-image-reroll.sh.

Upstream gaps

Dos filas de la matriz de docs/HURD_PORT.md siguen marcadas como «deferred-upstream»:

  • Audio en hardware real sobre Hurd. Debian GNU/Hurd 0.9 canónico no trae /hurd/audio* ni superficie ALSA/OSS. El flavor FLAVOR=apt-image de la imagen derivada empaqueta el userland de PulseAudio para que el lado Elisp tenga con qué hablar; el sink real es trabajo upstream.
  • Contadores por interfaz de pfinet. El arm Elisp pinta ceros hasta que la superficie del traductor exponga los contadores.

Hay ocho hilos abiertos en bug-hurd, debian-hurd y bug-gnu-emacs documentando estos y otros temas: entre ellos un assertion fail de ext2fs file_pager_write_pages bajo apt-install, un comportamiento sospechoso de SO_RCVTIMEO en pflocal, y la ausencia de la integración evdev/libinput en el Xorg de Hurd. Ninguno bloquea GEOS hoy.

¿Cómo probarlo?

Camino fácil, en un host Linux con KVM:

git clone https://github.com/borjatarraso/gnu-emacs-os.git
cd gnu-emacs-os
./iso-build/dev-vm.sh

El primer build descarga unos 8 GiB en /gnu/store; los siguientes tardan segundos. El boot hasta un frame EXWM utilizable son unos once segundos.

Para Hurd, partiendo de una instalación limpia de Debian GNU/Hurd 0.9, basta con ejecutar install/hurd-bootstrap.sh como root y reiniciar. La receta completa (paquetes apt, build, formato de init.args, ruta de rollback) está en docs/HURD_BOOT.md. La ruta alternativa es iso-build/hurd-image-reroll.sh, que hornea una imagen derivada de la canónica con pid1 estático, árbol de supervisor, GRUB serial y authorized_keys ya dentro; se arranca bajo QEMU y se entra por SSH.

Si alguien quiere comparar con la canónica vainilla, GEOS_BYPASS=1 ./iso-build/hurd-image-reroll.sh produce una imagen con /sbin/init stock (bash, sysvinit, getty) en lugar del PID 1 de Emacs, manteniendo las conveniencias del bake (consola serial, claves SSH ya inyectadas).

Limitaciones aceptadas

Emacs es de un solo hilo. Un regex atascado bloquea el OS. Una llamada de red lenta bloquea el OS. Un (while t) bloquea el OS. El buffer *panic* mitiga el caso de los errores Elisp que pasan por condition-case, pero no salva del loop apretado en código C ni de la llamada de red sin timeout. Es una restricción de diseño asumida, no un bug. Pierdo aproximadamente una sesión a la semana por un freeze que tengo que recuperar desde QEMU. Me parece un ratio aceptable. Puede que a ti no, y esa es una razón legítima para no usar este OS.

Demo

Enlaces

Licencia: GPLv3-or-later. Maintainer: borja.tarraso@member.fsf.org.


Sep 01 2024

Configuración de org-mode: TODO + agenda + imágenes + notificaciones

Tag: advancedadmin @ 8:08 am

Con esta configuración de org-mode para emacs podremos movernos de manera más conveniente en org-mode. Definimos algunos keybidings típicos así como activamos el sistema de logs para guardar el accountability de las tareas así como su timestamp. Además guardaremos el estado de las mismas conectándolo con el fichero en tasks.org y activando un sistema de checklist de org-mode. Por último incluiremos los diccionarios de babel, que nos permitirán mostrar imágenes inline, y sintaxis para interpretar los múltiples lenguajes:

;; ---------------------------------------------------------------------------
;; Org-mode configuration
;; ---------------------------------------------------------------------------

(setq org-log-done 'time)
(define-key global-map "\C-cl" 'org-store-link)
(define-key global-map "\C-ca" 'org-agenda)
(setq org-log-done t)

;; Connect agenda with org files
(setq org-agenda-files (list "~/zsync/tasks.org"))

(add-to-list 'load-path (expand-file-name "~/.emacs.d/ch/"))
(require 'org-checklist)

;; Show images inline when opening an org file
(add-hook 'org-babel-after-execute-hook 'org-display-inline-images)
(add-hook 'org-mode-hook 'org-display-inline-images)

Keybindings para manejar tareas:

  • C-c C-c para finalizar una tarea simple
  • C-c C-t para finalizar un set complejo de tareas
  • C-c a t para marcar como tarea a realizar y marcarla como ‘TODO’

Keybindings para manejar prioridades en las tareas:

  • C-c , to set tasks priority (priority must be on the top of org file)
  • C-c , + para incrementar la prioridad de una tarea
  • C-c , – para decrementar la prioridad de una tarea

Keybindings clave para la agenda:

  • C-c C-d para insertar una fecha limite para un set de tareas (deadline)
  • C-c C-s para añadir al backlog o hacer schedule de un set de tareas (schedule)
  • Una vez haya sido seleccionado la tarea deseada, presiona enter acto seguido C-c a a para org-agenda Now pres ‘l‘ (lower case L) to set log mode on

Keybindings para tiempos sobre tareas:

  • C-c / d para comprobar tareas con una fecha limite (deadlines)
  • C-c / b para comprobar tareas pendientes y deadlines (backlog)
  • C-c / a para comprobar tareas pasadas deadlines (after)

Keybindings para cambiar formas de visualización en tareas:

  • C-c – Cambia la numeración (se debe evitar usarlo sobre los títulos, ya que aquí se ignoraría el TODO)

Después de esto podemos añadir más funcionalidades, como limpiar todos los reminders de la agenda para el día de hoy y volver a construirlos de cero y activar todas las notificaciones de nuevo. Además podemos hacer que esta tarea se ejecute automaticamente después de medianoche.

;; ---------------------------------------------------------------------------
;; Reminders
;; ---------------------------------------------------------------------------

; Erase all reminders and rebuilt reminders for today from the agenda
(defun bh/org-agenda-to-appt ()
(interactive)
(setq appt-time-msg-list nil)
(org-agenda-to-appt))

; Rebuild the reminders everytime the agenda is displayed
(add-hook 'org-finalize-agenda-hook 'bh/org-agenda-to-appt 'append)

; This is at the end of my .emacs - so appointments are set up when Emacs starts
; This line is currently failing, need more investigation
;(bh/org-agenda-to-appt)

; Activate appointments so we get notifications
(appt-activate t)

; If we leave Emacs running overnight - reset the appointments one minute after midnight
(run-at-time "24:01" nil 'bh/org-agenda-to-appt)

Por último podemos cambiar el ciclo de tareas por defecto para tener un TODO-INPROGRESS-WAITING(opcional)-DONE y poder emplear atajos o shortcuts de teclado para ello.

(setq org-todo-keywords
'((sequence "TODO(t!)" "INPROGRESS(i!)" "WAITING(w!/!)" "|" "DONE(d!)")
))

Sep 01 2024

Apophis offensive security workstation

Tag: internals/hackingadmin @ 6:28 am

L480 Apophis con triple pantalla para seguridad ofensiva móvil


Página siguiente »