Community skill — not reviewed. It was shared by 落嵛 and has not been checked by Neta. Read SKILL.md below before letting an agent use it.
Use it in Cohub
Paste this into your agent's chat — it fetches the skill and follows it.
Use the skill: portable-debian-openshot-setup. Run `npx -y @neta-art/neta-search-cli@latest skills use @sunset1896/portable-debian-openshot-setup --via site` and follow what it prints. Read its complete output, redirecting it to a temporary file first if necessary, and resolve relative paths from the skill directory it prints.
Install from a terminal
npx -y @neta-art/neta-search-cli@latest skills use @sunset1896/portable-debian-openshot-setup
Summary
Set up a portable Debian system and a working OpenShot video editor, even on a locked-down machine without admin rights.
Downloads an official install-free Debian system image that can run from a USB stick, and checks that the download is intact.
Confirms whether admin commands work inside that Debian system, and shows you the evidence it found.
Builds a separate Debian workspace you can switch into, even if you have no admin access on the machine.
Installs the OpenShot video editor there and checks that it opens, with a screenshot as proof.
Best for people who want a ready-to-use editing setup; it does not make videos itself.
SKILL.md
# Portable Debian + OpenShot Setup
This skill is a reusable methodology for "download a portable Debian → confirm sudo → switch environment → install OpenShot → verify it works".
The skill files contain nothing private to a specific environment; every variable is parameterized with placeholders (`[DEBIAN_VERSION]`, `[DESKTOP]`, etc.),
so any environment, any Debian version and any desktop environment follows the same flow reliably.
Reply in the user's language; any text the user sees in reports follows the user's language.
**Tested update, 2026-08**: this skill has been run end to end in a Studio sandbox (Debian 12 bookworm, no root, `node` user),
including the Debian 13.6 Live ISO, building trixie with proot, installing OpenShot 3.1.1 and
a headless launch check on a host-side Xvfb. The 6 new pitfalls found and fixed during testing are built into the scripts and this document
(see "Known pitfalls" and each stage's "Failure handling").
## When to use this skill
- The user wants to "download a portable / install-free Debian (Live ISO) to carry around on a USB stick".
- The user wants to confirm whether sudo works inside a Debian Live system, and how to verify it.
- The user wants to switch the working environment to Debian inside a no-root / restricted sandbox (especially a version newer than the host, e.g. host bookworm → trixie).
- The user wants to install the OpenShot video editor in a Debian environment and confirm that it really runs.
- The user wants this whole chain (download → confirm → switch → install → verify) done in one go.
## When not to use this skill
- The user only wants to install an ordinary package, with no Debian environment setup involved.
- The user wants to generate/edit video content itself (use an output skill or process it directly with ffmpeg).
- The user wants to install Debian as the main system on a real machine (use the official installer; no Live/portable approach needed).
---
## Flow skeleton (six stages; each depends on the ones before)
| Stage | Input | Action | Output | Key failure points |
|---|---|---|---|---|
| 0. Prepare tools | Network, disk | One-step no-root download + unpack of all tools | proot/fakeroot/debootstrap/unsquashfs/xorriso/host-side Xvfb | Mixed deb version families, fakeroot getopt swallowing arguments |
| 1. Download portable Debian | Official mirror URL, desktop preference | Download Live ISO + SHA256SUMS | Verified ISO | Disk space, resuming downloads |
| 2. Confirm sudo | Live ISO (or a booted Live) | Unpack and inspect /etc/sudoers + live-config | Sudo availability verdict | ISO unpacking tool (pycdlib does not work on this ISO) |
| 3. Switch environment | Output of stages 0/1/2, or debootstrap directly | No root → build a trixie userland with proot | Working trixie environment entry point | glibc version, automatic binds, missing functions, empty placeholder files |
| 4. Install OpenShot | Stage 3 environment + apt network | apt install openshot-qt + python3-openshot | Installed packages | PPA unavailable, x11-common postinst, dependency tree pulling in systemd |
| 5. Verify it works | Stage 4 output | Four-way check: version/import/headless GUI/screenshot | Evidence of a successful launch | Xvfb spinning inside the guest, webengine needing GPU disabled |
> If the host already has root, stage 0 can be skipped (install the tools with apt directly), and stage 3 simplifies to
> `debootstrap trixie [DIR]` + `chroot`; everything else stays the same.
---
## Stage 0: Prepare tools (required in a no-root sandbox)
**Goal**: on a host without root and without an apt lock, prepare every tool the later stages need.
> Tested in the Studio sandbox: `apt-get update` fails on `/var/lib/apt/lists/lock` permissions,
> so `apt install` is impossible. The correct route is to download .deb files directly from the deb.debian.org pool and unpack them with `dpkg -x`, no install needed.
```bash
# One step (downloads 18 debs + static proot, unpacks them, generates the fakeroot wrapper and env.sh)
bash scripts/prepare-tools-no-root.sh /tmp/openshot-work/tools
source /tmp/openshot-work/tools/env.sh
```
**Key notes**:
- **The fakeroot wrapper must add the `--` separator** (built into the script): otherwise fakeroot's getopt
swallows debootstrap's `--variant`, `--foreign` and similar arguments as its own options and reports a usage error.
- **Debs must come from the host's version family**: e.g. bookworm uses the libisoburn 1.5.4 series; mixing in trixie's 1.5.8
gives `undefined symbol: iso_image_zisofs_discard_bpt` (glibc/ABI mismatch).
- **libjte2's source package folder is `jigit`** (pool/main/j/jigit/); looking under `libjte2` returns 404.
**Failure handling**:
- `download failed` → check the network and URL; the pool path structure is `pool/main/<first letter>/<source package>/`.
- `dpkg-deb: not a Debian format archive` → what was downloaded is a 404 HTML page; check the URL and download again.
---
## Stage 1: Download a portable Debian (Live ISO)
**Goal**: get an install-free, USB-bootable Debian Live image and verify its integrity.
1. **Probe the latest version and available desktops**:
```bash
# Official Live image folder (amd64)
curl -s https://cdimage.debian.org/debian-cd/current-live/amd64/iso-hybrid/ \
| grep -oE 'debian-live-[0-9.]+-amd64-[a-z]+\.iso' | sort -u
# Desktop options: standard (no desktop, ~2.0GB) gnome xfce lxqt mate cinnamon kde (~3.9GB)
# Tested 2026-08: latest is 13.6.0, xfce is 3.83GB
```
2. **Choose version and desktop**: `[DEBIAN_VERSION]` (defaults to the latest in current-live), `[DESKTOP]` (xfce recommended for light portability; kde for the full feature set).
3. **Download** (use `wget -c` to support resuming):
```bash
mkdir -p [WORKDIR] && cd [WORKDIR]
wget -c https://cdimage.debian.org/debian-cd/current-live/amd64/iso-hybrid/debian-live-[VERSION]-amd64-[DESKTOP].iso
```
4. **Also download the checksum file and verify** (required):
```bash
wget -c https://cdimage.debian.org/debian-cd/current-live/amd64/iso-hybrid/SHA256SUMS
grep '[DESKTOP].iso$' SHA256SUMS | sha256sum -c - # expected output ...OK
# Verifying large files is slow (3.9GB takes roughly 10–15 minutes; tested 12 seconds (fast NVMe) to several minutes (NAS))
```
5. **Confirm it is bootable** (optional): `file [ISO]` should show `ISO 9660 ... (DOS/MBR boot sector) ... bootable`.
**Failure handling**:
- Not enough disk space → check `df -h`; the ISO is 2–3.9GB, reserve at least twice that (tested peak over the whole run ~17GB).
- Download interrupted → resume with `wget -c`; verification fails → delete and download again (never use a broken file).
- `sha256sum -c` reports a pile of `FAILED open or read` → normal (SHA256SUMS also lists checksums for
.contents/.log/.packages files we did not download); only check that the target ISO line says OK.
**Reference script**: `scripts/download-debian-live.sh`
---
## Stage 2: Confirm whether sudo works
**Goal**: confirm that sudo works inside the portable Live system, with evidence.
**Verdict first** (official Debian Live behavior, verified on 13.x): **sudo works fully by default, and the default user needs no password**.
- Default user `user` / password `live` (created by live-config, UID 1000).
- `/etc/sudoers` contains `%sudo ALL=(ALL:ALL) ALL`.
- The live-config script `0040-sudo` runs at boot: it writes `user ALL=(ALL) NOPASSWD: ALL` to
`/etc/sudoers.d/live` and runs `usermod -a -G sudo user` → passwordless sudo in the terminal.
- The only exception: when the boot parameters include `noroot` / `live-config.noroot`, sudo is disabled (available by default without them).
**Verification method A: test after booting a real machine / USB stick**
```bash
sudo id # no password, outputs uid=0(root)
sudo -i # elevate to a root shell
```
**Verification method B: without hardware, unpack the ISO for evidence** (recommended in a sandbox)
```bash
# 1) Extract the squashfs from the ISO (xorriso first; pycdlib does not work on the 13.6 ISO, see below)
# 2) Unpack the squashfs root filesystem (unsquashfs, with LD_LIBRARY_PATH pointing at liblzo2)
# 3) Check the key files:
cat etc/sudoers # should show %sudo ALL=(ALL:ALL) ALL
grep -n "NOPASSWD\|sudo" usr/lib/live/config/0040-sudo # should show the passwordless rule and usermod
grep -n "LIVE_USERNAME" usr/lib/live/init-config.sh # should show the user/live defaults
```
**Tested note (new pitfall)**: pycdlib cannot parse the Debian 13.6 Live ISO
(`PyCdlibInvalidISO: Only single CE record supported`), and p7zip misidentifies the ISO as a zstd stream.
**Use xorriso first**:
```bash
LD_LIBRARY_PATH=$TOOLS/xorriso/usr/lib/x86_64-linux-gnu \
$TOOLS/xorriso/usr/bin/xorriso -osirrox on -indev [ISO] -extract /live [OUT_DIR]
```
**Failure handling**: sudoers looks abnormal (modified) → as a member of the `%sudo` group, check with `visudo -c`; no sudo group → the image was trimmed; add it with `apt install sudo` inside the environment in stage 3.
**Reference script**: `scripts/verify-sudo-in-iso.sh` (xorriso method A built in)
---
## Stage 3: Switch the working environment to the portable Debian (trixie)
**Goal**: make every later operation run in the Debian [VERSION] environment instead of the host environment.
**Key decision**:
- Host has root → `debootstrap trixie [DIR]` + `chroot` directly; simplest.
- **Host has no root (sandbox) → use the proot userland approach** (this skill's main path, below).
### 3.1 Prepare tools (no-root case)
Run `scripts/prepare-tools-no-root.sh` (stage 0) directly; it produces:
static proot, the fakeroot wrapper, debootstrap, unsquashfs, xorriso and host-side Xvfb.
> ⚠️ Do not use fakechroot to run a distribution newer than the host: fakechroot loads libraries with the **host ld.so**,
> and when the host glibc is too old (e.g. bookworm 2.36 running trixie 2.41 binaries) it fails straight away with
> `GLIBC_2.38 not found`. proot also redirects the ELF interpreter into the rootfs, so it does not have this problem.
### 3.2 Build the trixie root filesystem (setup-proot-trixie.sh has every fix built in)
```bash
bash scripts/setup-proot-trixie.sh trixie /tmp/trixie-root
```
Inside, the script runs in this order (matching the original SKILL steps 3.2–3.4, with the tested fixes):
1. **First stage** (download + unpack only, fakeroot emulating ownership):
```bash
fakeroot debootstrap --variant=minbase --foreign --arch=amd64 \
[SUITE] [ROOTFS_DIR] http://deb.debian.org/debian
```
2. **Copy the debootstrap files into the rootfs** (needed by second-stage) — ⚠️ testing found the original flow missed `functions`:
```bash
mkdir -p [ROOTFS_DIR]/usr/share/debootstrap
cp -r /path/to/debootstrap/scripts/* [ROOTFS_DIR]/usr/share/debootstrap/
cp /path/to/debootstrap/functions [ROOTFS_DIR]/usr/share/debootstrap/ # crucial!
cp [ROOTFS_DIR]/debootstrap/{suite,arch,mirror,variant,required,base,suite-script,debpaths,deburis} \
[ROOTFS_DIR]/usr/share/debootstrap/ 2>/dev/null
```
3. **Seed a valid /etc/passwd + /etc/group** (⚠️ new pitfall fix): early in second-stage these two files do not exist,
so proot -R binds the host files and writes fail; empty placeholder files in turn make base-files postinst's
`chown root:root` report `invalid group`. The correct seed: extract
`usr/share/base-passwd/passwd.master` and `group.master` from the base-passwd deb downloaded in the first stage and copy them over (the script does this automatically, with a fallback).
4. **Second stage** (configure dpkg inside proot) — ⚠️ you must set `DEBOOTSTRAP_DIR=/usr/share/debootstrap` explicitly
(the path inside the rootfs; otherwise proot inherits the host path, which shadows the rootfs configuration) and pass explicit binds:
```bash
DEBOOTSTRAP_DIR=/usr/share/debootstrap \
proot -0 -R [ROOTFS_DIR] \
-b [ROOTFS_DIR]/etc/localtime:/etc/localtime \
-b [ROOTFS_DIR]/etc/group:/etc/group \
-b [ROOTFS_DIR]/etc/passwd:/etc/passwd \
-b [ROOTFS_DIR]/etc/nsswitch.conf:/etc/nsswitch.conf \
-b /proc -b /dev -b /sys -b /etc/resolv.conf -w / \
/debootstrap/debootstrap --second-stage
```
5. **Wrap up**: seed `/usr/sbin/policy-rc.d` (`exit 101`, see stage 4), write the apt sources,
run `dpkg --configure -a` (if second-stage left unconfigured packages) and `apt-get update`.
### 3.3 Generate a reusable entry script
See `references/trixie-env.sh` (template, with the /etc/passwd bind added): every operation enters
the trixie environment through the entry script, which sets PATH, the automatic bind fixes, HOME/TERM and other environment variables.
**Failure handling**:
- `dpkg was interrupted` → run `dpkg --configure -a` inside the environment first.
- second-stage reports a missing `/usr/share/debootstrap/suite` → step 2 of 3.2 did not run, or
`DEBOOTSTRAP_DIR` is still the host path → set it explicitly to `/usr/share/debootstrap`.
- second-stage reports `cannot open /usr/share/debootstrap/functions` → functions was not copied (step 2 of 3.2).
- `chown: invalid group` → the /etc/group placeholder content is invalid; rewrite it from the base-passwd master, then `dpkg --configure -a`.
- postinst of systemd and similar packages crashes proot (`compare_paths2: Assertion`) → see stage 4 failure handling.
**Reference script**: `scripts/setup-proot-trixie.sh` (completes every step of 3.2 + wrap-up in one go)
---
## Stage 4: Install OpenShot
**Goal**: install the OpenShot video editor and its Python API inside the trixie environment.
**Prerequisites**: the stage 3 environment works and `apt-get update` succeeds (network OK).
### 4.1 Do not take the PPA route (a guaranteed pitfall on Debian)
| Habitual command | What actually happens on Debian 13 |
|---|---|
| `sudo add-apt-repository ppa:openshot.developers/ppa` | `software-properties-common` was removed in Debian 13; and the PPA only builds Ubuntu packages (focal~plucky), with no trixie build |
| Installing from the PPA | Ubuntu binaries are incompatible with trixie dependencies (Python/Qt versions); dependency conflicts are very likely |
**The right way**: install the packages straight from Debian's official repository (trixie has openshot-qt 3.1.1 + python3-openshot 0.3.3).
### 4.2 Install (--no-install-recommends recommended)
```bash
bash scripts/install-openshot.sh /tmp/trixie-env.sh
# Equivalent to:
[ENV_ENTRY] bash -c '
export DEBIAN_FRONTEND=noninteractive
apt-get update
# --no-install-recommends: cuts the systemd/usb-modeswitch/wpasupplicant recommends chain,
# shrinking the dependency tree and avoiding the risk of systemd postinst crashing under proot
apt-get install -y --no-install-recommends openshot-qt python3-openshot
apt-get install -y --no-install-recommends libgl1-mesa-dri libglx-mesa0 mesa-utils xvfb scrot
'
```
**⚠️ Tested new pitfall (policy-rc.d is required)**: x11-common's postinst calls `invoke-rc.d`,
which cannot find `/sbin/runlevel` or `/usr/sbin/policy-rc.d` inside chroot/proot and returns error 102;
dpkg marks the postinst as failed and **drags down** a batch of packages along with it: xvfb, scrot, libice6, libxtst6 and more.
Fix: seed `/usr/sbin/policy-rc.d` (content `exit 101`, meaning "do not run init scripts but report success",
the standard Docker practice), then finish with `dpkg --configure -a`. setup-proot-trixie.sh has this built in.
**Failure handling**:
- proot crashes with `compare_paths2: Assertion length2 > 0 failed` (triggered by systemd postinst's
`systemd-tmpfiles --create`) → two fixes:
① add `--no-install-recommends` to the install command (this skill's default; avoids it entirely);
② if systemd must be installed: patch `/var/lib/dpkg/info/systemd.postinst`, wrapping the
`systemd-tmpfiles ... --create ...` block in `if false; then ... fi`, then run `dpkg --configure -a`.
- `add-apt-repository: command not found` → see 4.1; use the official repository instead.
- The install script prints ✅ but actually failed → the original script's inner echo masked the exit code; the updated version fixes this with `set -e`.
When troubleshooting, look directly at the tail of the apt/dpkg output (`E: Sub-process ... returned an error code (1)`).
**Reference script**: `scripts/install-openshot.sh`
---
## Stage 5: Verify OpenShot works (must pass)
**Goal**: prove the install is not just "installed" but "usable".
```bash
bash scripts/verify-openshot.sh /tmp/trixie-env.sh # one-step four-way verification
```
Or step by step by hand:
```bash
# 1) Version and module import
[ENV_ENTRY] bash -c '
openshot-qt --version # expected output 3.1.1
python3 -c "import openshot; print(openshot.OPENSHOT_VERSION_FULL)" # expected 0.3.3
python3 -c "import openshot_qt" # expected: no exception
'
# 2) Headless GUI launch — ⚠️ Xvfb must run on the host side (see below), and webengine needs GPU disabled
export DISPLAY=:99 LIBGL_ALWAYS_SOFTWARE=1 HOME=/root \
QTWEBENGINE_DISABLE_SANDBOX=1 \
QTWEBENGINE_CHROMIUM_FLAGS="--disable-gpu --disable-gpu-compositing --disable-software-rasterizer"
openshot-qt > /tmp/openshot.log 2>&1 &
sleep 15
kill -0 $! && echo "OPENSHOT RUNNING OK" # process alive = main window initialized successfully
# 3) Screenshot as evidence
DISPLAY=:99 scrot /tmp/openshot_screenshot.png
# 4) No fatal errors in the log
grep -iE "failed|traceback|signal" /tmp/openshot.log | grep -viE "zygote|OOM|dbus" || echo "NO FATAL ERRORS"
```
**⚠️ Tested new pitfall 1: Xvfb inside the guest spins the CPU**. About 1 minute after starting inside proot, Xvfb enters
a single-threaded R-state spin (`cat /proc/PID/wchan` outputs 0) and every X request hangs — OpenShot shows up as
**process alive but frozen**, which is very easy to mistake for a pass. Fix: **run Xvfb on the host side** (bookworm's
xserver-xorg-core unpacked + LD_LIBRARY_PATH); the guest connects through the /tmp socket that proot binds automatically:
```bash
# Host side (tool set provided by prepare-tools-no-root.sh)
LD_LIBRARY_PATH=$TOOLS/hostxvfb/usr/lib/x86_64-linux-gnu \
setsid nohup $TOOLS/proot \
-b $TOOLS/hostxvfb/usr/bin/xkbcomp:/usr/bin/xkbcomp \
-b $TOOLS/hostxvfb/usr/share/X11/xkb:/usr/share/X11/xkb \
$TOOLS/hostxvfb/usr/bin/Xvfb :99 -screen 0 1280x800x24 -ac &
# Self-check: ls /tmp/.X11-unix/X99 shows the socket, and cat /proc/PID/wchan is ep_poll (not 0)
```
> proot as pure binding = no -R, no -0, only two paths mapped. Why bind xkbcomp: the X server looks for
> `/usr/bin/xkbcomp` at its compiled path, and the host's /usr/bin is not writable, so it cannot be placed there; the xkb data is likewise bound to
> `/usr/share/X11/xkb`. Without them you get `Failed to activate virtual core keyboard: 2`.
**⚠️ Tested new pitfall 2: QtWebEngine needs GPU disabled**. Without a GPU, the webengine renderer fails at
`GpuChannelMsg_CreateCommandBuffer` → SIGSEGV → SIGABRT and the whole process exits.
Adding `QTWEBENGINE_DISABLE_SANDBOX=1` (the Chromium sandbox is unavailable under fake root) and
`QTWEBENGINE_CHROMIUM_FLAGS="--disable-gpu ..."` fixes it.
**Pass criteria**: correct version number + successful module import + GUI process stays alive (≥10s) + no fatal errors in the log.
(Note: `Unhandled crash detected` in the log is OpenShot reporting the crash history of the **previous session**,
not a failure in this run; `zygote/OOM/webengine/sentry` errors are all benign.)
**Failure handling**:
- `Failed to create OpenGL context` → confirm mesa software rendering is installed and `LIBGL_ALWAYS_SOFTWARE=1` is set,
that Xvfb is alive (`ls /tmp/.X11-unix/`) and that `DISPLAY=:99` is correct.
- Xvfb socket exists but clients time out → check `cat /proc/PID/wchan`: 0 = spinning (the typical symptom of running
inside the guest) → switch to the host-side setup.
- Process exits immediately → check the stack at the tail of the log; commonly a missing Qt platform plugin → `apt install --no-install-recommends libqt5gui5` and related packages.
- scrot times out → first confirm the X server is healthy (same wchan check as above), then retry.
**Reference script**: `scripts/verify-openshot.sh` (automates the host-side Xvfb launch + four-way verification)
---
## Quality checklist
- [ ] Stage 0: `fakeroot /bin/true` passes, proot `--version` passes, unsquashfs/xorriso work
- [ ] ISO downloaded and `sha256sum -c` passes (target line `...OK`)
- [ ] The sudo verdict has evidence (sudoers + 0040-sudo script content, or a test inside Live)
- [ ] The trixie environment entry script works, `apt-get update` succeeds, `/etc/os-release` shows the target version
- [ ] OpenShot version, python3-openshot import and openshot_qt import all pass
- [ ] The GUI keeps running on the host-side Xvfb for ≥10s, with no fatal errors in the log
- [ ] Screenshot taken as evidence (optional but recommended)
## Resources
- `scripts/prepare-tools-no-root.sh` — stage 0: one-step no-root preparation of every tool (including the fakeroot wrapper and env.sh)
- `scripts/download-debian-live.sh` — stage 1: probe/download/verify the Live ISO
- `scripts/verify-sudo-in-iso.sh` — stage 2: unpack the ISO with xorriso to verify sudo (replacement for the failing pycdlib)
- `scripts/setup-proot-trixie.sh` — stage 3: one-step no-root build of the trixie userland (every fix built in)
- `scripts/install-openshot.sh` — stage 4: install OpenShot + headless rendering support (exit-code masking fixed)
- `scripts/verify-openshot.sh` — stage 5: automated four-way verification (host-side Xvfb + webengine GPU disabled)
- `references/trixie-env.sh` — proot entry script template (with the /etc/passwd bind fix)
- `references/requirements.md` — prerequisites, Studio environment snapshot, known-pitfall quick reference (12 items)
## Test record (2026-08-31, Studio sandbox)
- Environment: Debian 12 bookworm, node user (no root), 4 cores, 15G RAM, 46G free disk
- ISO: debian-live-13.6.0-amd64-xfce.iso (3.83GB), SHA256 passed
- sudo: `%sudo ALL=(ALL:ALL) ALL` + `0040-sudo` NOPASSWD + default user user/live, full evidence
- trixie environment: built with proot v5.3.0, /etc/os-release = Debian 13 (trixie)
- OpenShot: 3.1.1 + python3-openshot 0.3.3, headless launch on host-side Xvfb :99, alive ≥10s, screenshot taken
- New pitfalls: xorriso instead of pycdlib, copying functions, DEBOOTSTRAP_DIR shadowing, valid passwd/group seed,
policy-rc.d, guest Xvfb spin, webengine GPU disabled, install script exit-code masking (6 items in total, all built in)