Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 66 additions & 23 deletions .devcontainer/skills/codespace-webtop/SKILL.md

Large diffs are not rendered by default.

20 changes: 13 additions & 7 deletions .devcontainer/skills/codespace-webtop/references/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
## Stack Overview

```
Browser (port 3000, GitHub auth) → nginx → selkies (127.0.0.1:8082, mode=websockets)
Browser (port 3000, GitHub auth) → selkies (0.0.0.0:3000, mode=websockets)
selkies drives pixelflux capture on Xvfb :20 running XFCE
pixelflux: Rust X11 capture → H.264/JPEG stripes → WebSocket
```
Expand All @@ -14,9 +14,8 @@ Browser (port 3000, GitHub auth) → nginx → selkies (127.0.0.1:8082, mode=web
|-----------|---------|------|---------|
| Xvfb | `Xvfb :20` | — | Headless X11 display (1920x1080x24) |
| XFCE | `xfce4-session` | — | Desktop environment (window manager, panel, file manager) |
| selkies | `selkies` | 127.0.0.1:8082 | Serves React client + WebSocket media/input protocol |
| selkies | `selkies` | 0.0.0.0:3000 | Serves React client + WebSocket media/input protocol |
| pixelflux | (Rust .so) | — | X11 screen capture → H.264/JPEG stripes |
| nginx | `nginx` | 0.0.0.0:3000 | Reverse proxy with WS upgrade |

## Data Flow

Expand All @@ -40,15 +39,22 @@ Browser (port 3000, GitHub auth) → nginx → selkies (127.0.0.1:8082, mode=web
```
~/.selkies/
├── venv/ # Python venv with selkies + pixelflux + pcmflux
├── wheels/ # Vendored selkies wheel (for offline install)
├── web_root/ # Built React dashboard (copied at install)
└── pid/ # PID files (xvfb, xfce, selkies)

/etc/nginx/sites-enabled/selkies # nginx reverse proxy config
```

## Logs

- Xvfb: `/tmp/selkies-logs/xvfb.log`
- XFCE: `/tmp/selkies-logs/xfce.log`
- selkies: `/tmp/selkies-logs/selkies.log`
- nginx: `/var/log/nginx/error.log`

## Migration: Legacy nginx Cleanup

The original architecture used nginx as a reverse proxy (`3000 → 127.0.0.1:8082`). The current architecture binds selkies directly to `0.0.0.0:3000`. On upgrades, the `start` command handles legacy artifacts:

1. **Port check** — If port 3000 (or `$SELKIES_PORT`) is occupied, attempt graceful nginx stop via `nginx -s quit`.
2. **Force cleanup** — If port remains occupied, use `fuser -k` to kill the occupying process.
3. **Config removal** — Delete `/etc/nginx/sites-enabled/selkies` so a later nginx restart won't reload the stale proxy config.

This ensures clean migration from old installations without affecting unrelated nginx instances on the same host.
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Disk Space Optimization

## Build-Time vs Runtime Artifacts

The webtop install compiles pixelflux and pcmflux from Rust source (they require PyO3 Rust extensions). After compilation, only the resulting `.so` files in the venv are needed at runtime. The following are **build-time only** and can be safely removed after install:

| Artifact | Size | Why removable |
|----------|------|---------------|
| `~/.rustup` | ~1.5GB | Rust toolchain (compiler, std lib) — only needed to compile extensions |
| `~/.cargo/registry` | ~575MB | Cargo crate cache — only needed during build |
| `~/.selkies/selkies-src/` | ~170MB | Full git clone + node_modules — only `web_root/` dist matters |
| `~/.cache/pip` | ~32MB | pip download cache |

**Total savings: ~2.3GB** (from ~3GB -> ~250MB runtime footprint).

## Cleanup Procedure (in `cmd_install`)

```bash
# Track whether we installed Rust ourselves
local rust_installed_by_us=0
if ! command -v cargo &>/dev/null && [[ ! -d "$HOME/.cargo" && ! -d "$HOME/.rustup" ]]; then
rust_installed_by_us=1
# ... install rustup ...
fi

# After pip install + web build:
if [[ "$rust_installed_by_us" -eq 1 ]]; then
# We installed it -- safe to remove entirely
rm -rf "$HOME/.rustup" "$HOME/.cargo"
else
# User had pre-existing toolchain -- only clean build cache
rm -rf "$HOME/.cargo/registry/cache" "$HOME/.cargo/registry/src" "$HOME/.cargo/git/db"
fi
rm -rf "$HOME/.selkies/selkies-src" "$HOME/.cache/pip"
```

## Reinstalling After Cleanup

If the user runs `install` again:
- Rust toolchain will be re-downloaded if `rust_installed_by_us=1` (we removed it)
- Cargo registry will be repopulated on first build
- `selkies-src` will be re-cloned
- This is correct behavior -- cleanup trades disk for re-download time on reinstall

## Git Commit Pinning (Reproducibility)

The three git dependencies are pinned to specific commits:

| Repo | Pin | How to update |
|------|-----|---------------|
| pixelflux | `bf07c68` | `git ls-remote https://github.com/selkies-project/pixelflux.git HEAD` |
| pcmflux | `d2683ef` | `git ls-remote https://github.com/selkies-project/pcmflux.git HEAD` |
| selkies | `1d9b67b` | `git ls-remote https://github.com/selkies-project/selkies.git HEAD` |

Update pins in `selkies-native.sh` when new features/fixes are needed. Never use mutable `@HEAD` or branch names -- they break reproducibility.
56 changes: 46 additions & 10 deletions .devcontainer/skills/codespace-webtop/references/troubleshooting.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,12 @@ If you already have a wheel, drop it in `scripts/wheels/` and it will be used (t

## selkies serves 404 on `/` but WS connects

**Cause**: The web client is NOT bundled in the selkies wheel. selkies returns 404 on `/` unless `--web-root` points at a built client. nginx proxies `/` to selkies, so you get a 404 page in the browser even though the WebSocket at `/api/websockets` may work.
**Cause**: The web client is NOT bundled in the selkies wheel. selkies returns 404 on `/` unless `--web-root` points at a built client.

**Fix**:
1. Build the client: `cmd_build_web` (clone selkies repo → `addons/selkies-web-core` → `npm ci` → `npm run build` → copy `dist/` to `~/.selkies/web_root`).
2. Ensure `start` passes `--web-root=~/.selkies/web_root` (it does by default).
3. Verify: `curl -s -o /dev/null -w "%{http_code}" http://127.0.0.1:8082/` → should be `200`.
3. Verify: `curl -s -o /dev/null -w "%{http_code}" http://127.0.0.1:3000/` → should be `200`.

## ImportError: libva/libva-drm/libva-x11

Expand All @@ -51,28 +51,65 @@ sudo apt-get install -y libva2 libva-drm2 libva-x11-2

**Cause**: The WebSocket path changed in newer selkies versions.

**Fix**: The correct path is `/api/websockets`, not `/websockets/primary`. Ensure nginx config proxies WebSocket upgrade to the right path (the template handles this correctly).
**Fix**: The correct path is `/api/websockets`, not `/websockets/primary`. Ensure the selkies `--web-root` is set correctly.

## Nginx not starting on port 3000
## selkies can't start on port 3000 (port in use)

**Cause**: Port already in use, or Codespaces port visibility not set to `public`.
**Cause**: Another process is using port 3000.

**Fix**:
```bash
sudo nginx -s stop # if nginx is already running
sudo lsof -i :3000 # check what's using the port
# In Codespaces: set port 3000 to public in VS Code Ports panel
# Kill the process or change SELKIES_PORT
```

## selkies can't see DISPLAY

**Cause**: DISPLAY env var not set or incorrect.

**Fix**: selkies must be started with `DISPLAY=:20` env var:
**Fix**: selkies must be started with `DISPLAY=:20` env var (the script handles this automatically):
```bash
DISPLAY=:20 ~/.selkies/venv/bin/selkies --addr=127.0.0.1 --port=8082 --mode=websockets
DISPLAY=:20 ~/.selkies/venv/bin/selkies --addr=0.0.0.0 --port=3000 --mode=websockets
```

## pixelflux build fails (No CMAKE_ASM_NASM_COMPILER / missing libudev / missing libavutil)

**Cause**: pixelflux compiles Rust extensions that link against system C libraries. The error messages vary by missing dependency:
- `No CMAKE_ASM_NASM_COMPILER` → missing `nasm` (for x264 SIMD assembly)
- `Package libudev was not found` → missing `libudev-dev`
- `HINT: if you have installed the library, try setting PKG_CONFIG_PATH to the directory containing libavutil.pc` → missing ffmpeg dev packages

**Fix**: Install all build deps before `pip install`:
```bash
sudo apt-get install -y nasm cmake pkg-config libudev-dev libx264-dev \
libturbojpeg0-dev libavcodec-dev libavformat-dev libavutil-dev \
libswscale-dev libavfilter-dev libgbm-dev libinput-dev \
libwayland-dev libxkbcommon-dev libegl-dev libgles-dev libclang-dev
```
Plus Rust toolchain: `curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y`

See the "Build deps" table in SKILL.md Prerequisites for the full list with purposes.

## pcmflux~=2.1.0 not found (Could not find a version that satisfies the requirement)

**Cause**: `selkies` requires `pcmflux~=2.1.0` (audio capture), but 2.1.0 is unreleased on PyPI (max: 2.0.0). Like pixelflux, the 2.1.0 version exists only in the selkies-project fork's git HEAD. Building from git is the only way to get it.

**Fix**: Install pcmflux from git **before** selkies:
```bash
source ~/.selkies/venv/bin/activate
pip install "git+https://github.com/selkies-project/pcmflux.git"
```

## Interrupted apt leaves dpkg broken (dpkg was interrupted)

**Cause**: Installing XFCE4 (a large package set) can hit the terminal timeout, leaving dpkg in an unconfigured state. All subsequent apt calls fail with "dpkg was interrupted".

**Fix**:
```bash
sudo DEBIAN_FRONTEND=noninteractive dpkg --configure -a
```
The `DEBIAN_FRONTEND=noninteractive` is critical — without it, `keyboard-configuration` launches an interactive debconf dialog that hangs the terminal. After this, retry `prereqs --fix`.

## Process won't die after stop

**Cause**: `setsid` spawns processes in a new session; PID tracking may miss child processes.
Expand All @@ -84,7 +121,6 @@ DISPLAY=:20 ~/.selkies/venv/bin/selkies --addr=127.0.0.1 --port=8082 --mode=webs
pkill -f "pixelflux" 2>/dev/null
pkill -f "xfce4" 2>/dev/null
pkill -f "Xvfb :20" 2>/dev/null
sudo nginx -s quit 2>/dev/null
```

## XFCE components not starting
Expand Down
Loading
Loading