Linux 05 Sierpień 2026

Distrobox — izolowane testowanie aplikacji bez ryzyka aktualizacji

Dostępne też w:

Masz działającą instalację aplikacji, na której wszystko działa, a na horyzoncie pojawia się nowa wersja. Chcesz ją sprawdzić, zanim nadpiszesz pakiet na hoście. Klasyczny Docker do programów z GUI (szczególnie Electron) jest uciążliwy: X11, GPU, FUSE, logowanie. Distrobox rozwiązuje dokładnie ten problem — kontener z pełną integracją graficzną, a instalacja na hoście zostaje nietknięta.

W ostatnim czasie miałem dwa takie przypadki. Czasem muszę skorzystać z wcześniejszej wersji slicera do mojej drukarki 3D — Snapmaker potrafi zrobić rozgardiasz przy aktualizacji i jest dramat z ustawieniami. Ostatnio też widzę i słyszę o problemach z Cursor: lista to-do nie działa w 3.12, a w 3.9 jest OK; modele znacząco spowolniły na jakimś rodzaju tasków, a na wcześniejszej wersji chodzą jak wcześniej. Przydałoby się coś, co można odpalić w izolowanym środowisku…

Ten artykuł najpierw wyjaśnia, czym jest Distrobox i kiedy ma sens, a potem — na realnym przykładzie — przeprowadza przez test Cursor 3.14.x obok stabilnej instalacji 3.9.x: osobny home, AppImage, pułapki z katalogiem roboczym oraz praktyczne obejście logowania OAuth.


Czym jest Distrobox

Distrobox to warstwa nad Podmanem lub Dockerem, której celem nie jest twarde sandboxowanie (jak Flatpak), tylko integracja. Kontener dostaje:

  • dostęp do X11 / Wayland (okna GUI wyglądają jak natywne),
  • dźwięk, USB, dyski,
  • (domyślnie) Twój katalog domowy,
  • możliwość eksportu aplikacji do menu hosta.

W praktyce uruchamiasz oprogramowanie z innej dystrybucji — albo osobną kopię tego samego programu — bez dual-bootu i bez walczenia z pełnym Dockerem pod Electronem. Ten sam wzorzec działa dla IDE, slicera, edytora audio czy dowolnej apki, której nie chcesz aktualizować „na ślepo”.

Do czego się go używa

Distrobox służy głównie do uruchamiania oprogramowania „jak na innej dystrybucji”, przy zachowaniu normalnego desktopu hosta. Typowe zastosowania:

  1. Aplikacje niedostępne lub problematyczne na Twojej dystrybucji — paczki tylko dla Fedory/Archa, stare zależności, konflikt bibliotek.
  2. Izolowane środowiska deweloperskie — osobny stack (Node, Python, toolchain) bez zaśmiecania systemu.
  3. GUI z kontenera — duża przewaga nad zwykłym Dockerem: okna, dźwięk i pliki z home działają bez ręcznej konfiguracji.
  4. Starsze lub nowsze wersje programów obok siebie — test lub rollback bez aktualizacji hosta (Cursor, slicer 3D, itd.).
  5. Eksport apki do menu hosta (distrobox-export) — wygląda jak zwykła aplikacja systemowa.

Czego nie jest: twardym sandboxem bezpieczeństwa. Celowo mocno integruje się z hostem (home, X11, urządzenia). Do izolacji „nieufam temu kodowi” lepszy Flatpak albo zwykły kontener z ograniczonymi mountami.

Distrobox vs zwykły Docker

Distrobox Klasyczny Docker
Cel środowisko deweloperskie / GUI zintegrowane z hostem izolacja usług, CI, serwery
Okna GUI działa „od ręki” (X11/Wayland) ręczny montaż socketów, dużo tarcia
Home domyślnie współdzielony z hostem zwykle osobny volume
Sandbox słaby — nie traktuj jak izolacji bezpieczeństwa silniejszy (przy sensownej konfiguracji)

Wymagania

  • Linux z Podmanem lub Dockerem (Distrobox preferuje Podmana, jeśli oba są zainstalowane),
  • pakiet distrobox z dystrybucji albo instalacja ze skryptu upstream.

Na Kubuntu / Ubuntu zwykle wystarczy:

sudo apt install distrobox podman

Przykład: nowy Cursor bez aktualizacji hosta

Cel: przetestować najnowszy Cursor (tu: AppImage 3.14.7), nie ruszając działającego pakietu .deb (np. 3.9.16 w /usr/bin/cursor).

Strategia:

  1. Kontener Distrobox z osobnym katalogiem home.
  2. W środku — AppImage najnowszej wersji.
  3. Dane edytora (~/.config/Cursor) lądują w home kontenera, nie w hostowym.

Bez osobnego home Distrobox zamontuje Twój prawdziwy ~/ i nowy Cursor może nadpisać ustawienia / bazę SQLite działającej instalacji. Tego unikamy.

Host                          Distrobox (cursor-test)
─────                         ───────────────────────
/usr/bin/cursor  (3.9.x)      Cursor.AppImage (3.14.x)
~/.config/Cursor              ~/cursor-test-home/.config/Cursor
     ↑ nietknięte                    ↑ izolowane dane

Ten sam układ przenosisz na inne aplikacje: osobny --home, binarka / AppImage / pakiet wewnątrz kontenera, host nietknięty.


Krok 1 — osobny home i utworzenie kontenera

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"

Kluczowe jest --home ~/cursor-test-home. Distrobox i tak dodatkowo zamontuje prawdziwy /home/$USER (integracja z hostem), ale zmienna $HOME w kontenerze wskazuje na katalog testowy — i tam powinny iść pliki konfiguracyjne aplikacji respektujących $HOME / XDG.

Wejście do kontenera:

distrobox enter -nw cursor-test

Flaga -nw (no workdir) sprawia, że lądujesz od razu w $HOME kontenera. Bez niej Distrobox zachowuje bieżący katalog z hosta — jeśli wchodzisz z /home/ty, po enter nadal jesteś w /home/ty i wygląda to, jakby --home nie działało.

Sprawdzenie:

echo $HOME    # /home/ty/cursor-test-home
pwd           # po -nw: to samo
ls ~          # skel (.bashrc, .profile, …) — nie Twój pełny home hosta

Jeśli pwd pokazuje /home/ty, a echo $HOME pokazuje .../cursor-test-home, wszystko jest OK — po prostu zrób cd ~ albo wchodź z -nw.


Krok 2 — pobranie Cursor (AppImage)

Endpoint https://cursor.com/api/download?platform=linux-x64&releaseTrack=stable nie zwraca pliku binarnego, tylko JSON z polami downloadUrl, debUrl, version itd.

Błędne (dostaniesz plik ~600 B z JSON-em):

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

Poprawne:

# w kontenerze, w $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   # oczekuj: ELF 64-bit … (~280 MB)

Uruchomienie:

./Cursor.AppImage
# na Ubuntu 24.04+ czasem potrzeba:
./Cursor.AppImage --no-sandbox
# albo gdy brakuje FUSE:
./Cursor.AppImage --appimage-extract-and-run

Wygodny launcher (opcjonalnie):

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

Krok 3 — pułapka: logowanie OAuth w kontenerze

Cursor loguje się przez OAuth w zewnętrznej przeglądarce (xdg-open). W Distroboxie klik „Log in” często nic nie robi.

Dlaczego

  1. Distrobox podmienia xdg-open na distrobox-host-exec.
  2. distrobox-host-exec opiera się o host-spawn, a host-spawn wymaga na hoście Flatpaka (interfejs D-Bus org.freedesktop.Flatpak.Development).
  3. Bez Flatpaka dostajesz Error: Cannot download host-spawn / exit code 127 — przeglądarka się nie otwiera.

Nawet gdy uda się otworzyć przeglądarkę, pojawia się drugi problem: po zalogowaniu callback cursor://… na hoście trafia zwykle do hostowego Cursor (handler z /usr/share/applications), a nie do instancji w kontenerze.

Do smoke-testu funkcji AI nie warto z tym walczyć. Prostsze jest skopiowanie sesji z działającej instalacji na hoście.


Krok 4 — obejście OAuth: skopiowanie sesji z hosta

Cursor trzyma tokeny w SQLite:

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

Klucze m.in.:

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

Zamknij testowy Cursor, potem na hoście:

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")

Po restarcie AppImage powinien być zalogowany na to samo konto co host. To świadome współdzielenie sesji — wygodne do testów, nie do „twardej” izolacji tożsamości.

Jeśli jednak chcesz iść ścieżką przeglądarki: na hoście zainstaluj flatpak (oficjalna ścieżka host-spawn) albo doinstaluj przeglądarkę w kontenerze. Pamiętaj wtedy o konflikcie handlera cursor://.


Krok 5 — co warto przetestować przed aktualizacją hosta

  • start GUI, layout, otwarcie projektu,
  • Agent / Chat / terminal,
  • Git, rozszerzenia, MCP,
  • typowy workflow dnia codziennego,
  • toole, które lubisz, czas trwania komend.

Jeśli wszystko gra — aktualizujesz .deb na hoście jak zwykle. Jeśli nie — wyrzucasz kontener i zostajesz przy starej wersji.


Sprzątanie

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

Hostowy Cursor pozostaje bez zmian.


Checklist — szybka ściąga

  1. distrobox create … --home ~/cursor-test-home
  2. distrobox enter -nw cursor-test
  3. Pobrać prawdziwy AppImage z downloadUrl (nie surowy JSON z API)
  4. Skopiować tokeny z hostowego state.vscdb (OAuth w kontenerze zwykle nie rusza)
  5. Przetestować typowy workflow
  6. Po teście: distrobox rm + ewentualna aktualizacja .deb

Podsumowanie

Distrobox to praktyczny sposób na „drugi Linux” pod GUI bez dual-bootu i bez Dockerowego circus z Electronem. Przyda się zarówno przy slicerze 3D, jak i przy IDE: osobny --home, binarka w kontenerze, host nietknięty.

W przypadku Cursor dodatkowo warto wiedzieć, że logowanie OAuth w Distroboxie potrafi kompletnie zamilknąć — do szybkiego testu najwygodniej skopiować sesję z działającej instalacji. Dzięki temu aktualizacja hosta przestaje być skokiem na główkę: najpierw sprawdzasz, potem dopiero nadpisujesz to, co działa.