Linux 05 Sierpień 2026

Distrobox — probar aplicaciones en aislamiento sin arriesgar actualizaciones

También en:

Tienes una instalación que funciona bien y, en el horizonte, aparece una versión nueva. Quieres probarla antes de sobrescribir el paquete en el host. Docker clásico es incómodo con aplicaciones GUI (sobre todo Electron): X11, GPU, FUSE, flujos de login. Distrobox resuelve exactamente eso — un contenedor con integración gráfica completa, mientras la instalación del host queda intacta.

Me pasó dos veces hace poco. A veces necesito una versión anterior del slicer de mi impresora 3D: las actualizaciones de Snapmaker pueden liar la configuración. También veo y oigo problemas con Cursor: la lista de tareas no funciona en 3.12 y en 3.9 sí; los modelos se ralentizan mucho en ciertos tipos de tareas, mientras la versión anterior sigue yendo bien. Vendría bien algo que se pueda lanzar en un entorno aislado…

Este artículo explica primero qué es Distrobox y cuándo tiene sentido, y después — con un ejemplo real — guía el test de Cursor 3.14.x junto a una instalación estable 3.9.x: home separado, AppImage, trampas del directorio de trabajo y un atajo práctico al OAuth.


Qué es Distrobox

Distrobox es una capa sobre Podman o Docker. Su objetivo no es el sandbox duro (como Flatpak), sino la integración. El contenedor obtiene:

  • acceso a X11 / Wayland (las ventanas GUI se ven nativas),
  • audio, USB, discos,
  • (por defecto) tu directorio home,
  • la posibilidad de exportar aplicaciones al menú del host.

En la práctica ejecutas software de otra distribución — o una copia aparte del mismo programa — sin dual-boot y sin pelearte con Docker completo bajo Electron. El mismo patrón sirve para un IDE, un slicer, un editor de audio o cualquier app que no quieras actualizar a ciegas.

Para qué se usa

Distrobox sirve sobre todo para ejecutar software “como en otra distro”, manteniendo el escritorio normal del host. Usos típicos:

  1. Apps no disponibles o problemáticas en tu distribución — paquetes solo para Fedora/Arch, dependencias viejas, conflictos de bibliotecas.
  2. Entornos de desarrollo aislados — un stack aparte (Node, Python, toolchain) sin ensuciar el sistema.
  3. GUI desde un contenedor — gran ventaja frente a Docker puro: ventanas, audio y archivos del home funcionan sin montajes manuales complicados.
  4. Versiones antiguas o nuevas en paralelo — probar o hacer rollback sin actualizar el host (Cursor, slicers 3D, etc.).
  5. Exportar la app al menú del host (distrobox-export) — parece una aplicación del sistema.

Lo que no es: un sandbox duro de seguridad. Se integra a propósito con el host (home, X11, dispositivos). Si la idea es “no confío en este código”, mejor Flatpak o un contenedor normal con mounts limitados.

Distrobox frente a Docker clásico

Distrobox Docker clásico
Objetivo entornos de desarrollo / GUI integrados con el host aislamiento de servicios, CI, servidores
Ventanas GUI funciona de entrada (X11/Wayland) montaje manual de sockets, mucha fricción
Home compartido con el host por defecto suele ser un volumen aparte
Sandbox débil — no lo trates como aislamiento de seguridad más fuerte (con una configuración sensata)

Requisitos

  • Linux con Podman o Docker (Distrobox prefiere Podman si ambos están instalados),
  • el paquete distrobox de tu distro, o el script de instalación upstream.

En Kubuntu / Ubuntu suele bastar:

sudo apt install distrobox podman

Ejemplo: un Cursor nuevo sin actualizar el host

Objetivo: probar el Cursor más reciente (aquí: AppImage 3.14.7) sin tocar el .deb que funciona (p. ej. 3.9.16 en /usr/bin/cursor).

Estrategia:

  1. Contenedor Distrobox con un directorio home separado.
  2. Dentro — el AppImage más nuevo.
  3. Los datos del editor (~/.config/Cursor) van al home del contenedor, no al del host.

Sin un home aparte, Distrobox monta tu ~/ real y el Cursor nuevo puede sobrescribir ajustes / la base SQLite de la instalación que funciona. Eso lo evitamos.

Host                          Distrobox (cursor-test)
─────                         ───────────────────────
/usr/bin/cursor  (3.9.x)      Cursor.AppImage (3.14.x)
~/.config/Cursor              ~/cursor-test-home/.config/Cursor
     ↑ intacto                       ↑ datos aislados

El mismo esquema se aplica a otras apps: --home separado, binario / AppImage / paquete dentro del contenedor, host intacto.


Paso 1 — home separado y creación del contenedor

mkdir -p ~/cursor-test-home

distrobox create \
  --name cursor-test \
  --image ubuntu:24.04 \
  --home ~/cursor-test-home \
  --additional-packages "libfuse2t64 libgtk-3-0 libnss3 libxss1 libasound2t64"

Lo clave es --home ~/cursor-test-home. Distrobox también montará el /home/$USER real (integración con el host), pero $HOME dentro del contenedor apunta al directorio de prueba — y ahí deben ir las configs de las apps que respetan $HOME / XDG.

Entrar al contenedor:

distrobox enter -nw cursor-test

La flag -nw (no workdir) te deja directamente en el $HOME del contenedor. Sin ella, Distrobox conserva el directorio actual del host — si entras desde /home/tu, tras enter sigues en /home/tu y parece que --home no funcionó.

Comprobación:

echo $HOME    # /home/tu/cursor-test-home
pwd           # con -nw: lo mismo
ls ~          # skel (.bashrc, .profile, …) — no tu home completo del host

Si pwd muestra /home/tu y echo $HOME muestra .../cursor-test-home, está bien — haz cd ~ o entra con -nw.


Paso 2 — descargar Cursor (AppImage)

El endpoint https://cursor.com/api/download?platform=linux-x64&releaseTrack=stable no devuelve un binario, solo JSON con downloadUrl, debUrl, version, etc.

Incorrecto (obtienes un JSON de ~600 B):

curl -L "https://cursor.com/api/download?platform=linux-x64&releaseTrack=stable" -o Cursor.AppImage

Correcto:

# dentro del contenedor, en $HOME
URL=$(python3 -c "import json,urllib.request; print(json.load(urllib.request.urlopen('https://cursor.com/api/download?platform=linux-x64&releaseTrack=stable'))['downloadUrl'])")
curl -fL -o Cursor.AppImage "$URL"
chmod +x Cursor.AppImage
file Cursor.AppImage   # esperado: ELF 64-bit … (~280 MB)

Ejecución:

./Cursor.AppImage
# en Ubuntu 24.04+ a veces hace falta:
./Cursor.AppImage --no-sandbox
# o si falta FUSE:
./Cursor.AppImage --appimage-extract-and-run

Launcher opcional:

cat > ~/run-cursor.sh <<'EOF'
#!/bin/bash
set -euo pipefail
export HOME=/home/$USER/cursor-test-home   # ajusta la ruta
cd "$HOME"
exec ./Cursor.AppImage --no-sandbox "$@"
EOF
chmod +x ~/run-cursor.sh

Paso 3 — trampa: login OAuth en el contenedor

Cursor inicia sesión con OAuth en un navegador externo (xdg-open). En Distrobox, el clic en “Log in” a menudo no hace nada.

Por qué

  1. Distrobox sustituye xdg-open por distrobox-host-exec.
  2. distrobox-host-exec depende de host-spawn, y host-spawn necesita Flatpak en el host (interfaz D-Bus org.freedesktop.Flatpak.Development).
  3. Sin Flatpak obtienes Error: Cannot download host-spawn / código de salida 127 — el navegador no se abre.

Aunque el navegador se abra, aparece un segundo problema: tras el login, el callback cursor://… en el host suele ir al Cursor del host (handler en /usr/share/applications), no a la instancia del contenedor.

Para un smoke-test de funciones de IA no merece la pena pelearse con eso. Es más simple copiar la sesión de la instalación que ya funciona en el host.


Paso 4 — atajo al OAuth: copiar la sesión del host

Cursor guarda los tokens en SQLite:

~/.config/Cursor/User/globalStorage/state.vscdb

Claves, entre otras:

  • cursorAuth/accessToken
  • cursorAuth/refreshToken
  • cursorAuth/cachedEmail
  • cursorAuth/cachedTeam
  • cursorAuth/stripeMembershipType

Cierra el Cursor de prueba y luego, en el host:

import sqlite3, shutil, time

host = "/home/USER/.config/Cursor/User/globalStorage/state.vscdb"
test = "/home/USER/cursor-test-home/.config/Cursor/User/globalStorage/state.vscdb"
keys = [
    "cursorAuth/accessToken",
    "cursorAuth/refreshToken",
    "cursorAuth/cachedEmail",
    "cursorAuth/cachedScopedProfile",
    "cursorAuth/cachedSignUpType",
    "cursorAuth/cachedTeam",
    "cursorAuth/stripeMembershipType",
]

h = sqlite3.connect(f"file:{host}?mode=ro", uri=True)
vals = {k: h.execute("SELECT value FROM ItemTable WHERE key=?", (k,)).fetchone()[0] for k in keys}
h.close()

shutil.copy2(test, test + f".bak-{int(time.time())}")
t = sqlite3.connect(test)
for k, v in vals.items():
    t.execute(
        "INSERT INTO ItemTable(key,value) VALUES(?,?) "
        "ON CONFLICT(key) DO UPDATE SET value=excluded.value",
        (k, v),
    )
t.execute("DELETE FROM ItemTable WHERE key=?", ("glass.lastSignedInAuthId",))
t.commit()
t.close()
print("OK")

Tras reiniciar el AppImage debería quedar logueado en la misma cuenta que el host. Es compartir sesión a propósito: cómodo para pruebas, no para un aislamiento duro de identidad.

Si aun así quieres el camino del navegador: instala flatpak en el host (ruta oficial de host-spawn) o instala un navegador dentro del contenedor. Vigila el conflicto del handler cursor://.


Paso 5 — qué conviene probar antes de actualizar el host

  • arranque GUI, layout, abrir un proyecto,
  • Agent / Chat / terminal,
  • Git, extensiones, MCP,
  • el workflow típico del día a día,
  • las herramientas que usas, duración de los comandos.

Si todo va bien — actualizas el .deb del host como siempre. Si no — borras el contenedor y te quedas con la versión anterior.


Limpieza

distrobox stop cursor-test
distrobox rm cursor-test
rm -rf ~/cursor-test-home

El Cursor del host no cambia.


Checklist — chuleta rápida

  1. distrobox create … --home ~/cursor-test-home
  2. distrobox enter -nw cursor-test
  3. Descargar el AppImage real desde downloadUrl (no el JSON crudo de la API)
  4. Copiar tokens del state.vscdb del host (el OAuth en el contenedor suele no arrancar)
  5. Probar el workflow habitual
  6. Tras el test: distrobox rm + eventual actualización del .deb

Resumen

Distrobox es una forma práctica de tener un “segundo Linux” para GUI sin dual-boot y sin el circo de Docker con Electron. Sirve igual para un slicer 3D que para un IDE: --home aparte, binario en el contenedor, host intacto.

Con Cursor, además, el OAuth en Distrobox puede quedarse en silencio total: para una prueba rápida, lo más cómodo es copiar la sesión de la instalación que ya funciona. Así actualizar el host deja de ser un salto al vacío: primero compruebas, después sobrescribes lo que ya te va bien.