fix: port detection broken since v0.11.2 (#85, #63)

setcap cap_setgid+ep on the system Python binary made all Python
processes non-dumpable, blocking /proc/[pid]/fd/ access needed by
_pid_from_inode() to resolve socket inodes to PIDs.

Fix: copy the Python binary to python3-ot and setcap only the copy.
The open-terminal server uses python3-ot (has CAP_SETGID for
multi-user os.setgroups()), while user-spawned python3 stays
capability-free and dumpable.

Slim/Alpine: removed setcap entirely (multi-user mode requires sudo,
which only the full image has). Kept libcap packages installed.

README: corrected Image Variants table — multi-user mode is
full-image only.
This commit is contained in:
Timothy Jaeryang Baek 2026-03-19 17:42:17 -05:00
parent 5a6747fa2d
commit 2da589100c
5 changed files with 18 additions and 16 deletions

View file

@ -4,6 +4,13 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
## [0.11.21] - 2026-03-19
### Fixed
- 🔍 **Port detection broken since v0.11.2**`setcap cap_setgid+ep` on the system Python binary (added for multi-user `os.setgroups()`) made all Python processes non-dumpable, blocking `/proc/[pid]/fd/` access needed to resolve socket inodes to PIDs. Ports from user-spawned Python servers were silently filtered out. Fixed by copying the Python binary and granting `cap_setgid` only to the copy (`python3-ot`), used exclusively by the open-terminal server. The system `python3` stays capability-free so user processes remain dumpable. Slim and Alpine images had `setcap` removed entirely since they don't support multi-user mode. ([#85](https://github.com/open-webui/open-terminal/issues/85), [#63](https://github.com/open-webui/open-terminal/issues/63))
- 📖 **README** — Image Variants table incorrectly listed multi-user mode as supported on slim and alpine images. Multi-user mode requires `sudo`, which only the full image includes.
## [0.11.20] - 2026-03-15
### Fixed

View file

@ -58,10 +58,13 @@ RUN pip install --no-cache-dir \
python-docx python-pptx pypdf csvkit
COPY . .
# setcap MUST run in the same layer as the Python binary to avoid
# overlay2 copy-up corruption of libpython3.12.so ("file too short").
# Create a capability-bearing Python copy for the server process only.
# The system python3 stays clean so user-spawned Python processes remain
# dumpable (readable via /proc/[pid]/fd/ for port detection).
RUN pip install --no-cache-dir . \
&& setcap cap_setgid+ep $(readlink -f $(which python3))
&& cp "$(readlink -f "$(which python3)")" /usr/local/bin/python3-ot \
&& setcap cap_setgid+ep /usr/local/bin/python3-ot \
&& sed -i "1s|.*|#!/usr/local/bin/python3-ot|" "$(which open-terminal)"
RUN useradd -m -s /bin/bash user && echo 'user ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers

View file

@ -65,7 +65,6 @@ FROM python:3.12.13-alpine
# Core: tini (PID 1), su-exec (drop privileges, Alpine's gosu)
# Utilities: curl, git, jq, less, procps (ps/top)
# Firewall: iptables, ipset, dnsmasq (egress whitelist)
# Permissions: libcap (setcap for cap_setgid)
# Shell: bash (the terminal API spawns bash sessions)
#
# ➡️ Want more tools? Add them here, one per line for easy diffs:
@ -98,9 +97,7 @@ COPY . .
# that landed after the pinned base image was published.
RUN apk upgrade --no-cache
# Install the app itself (fast — all deps are already present) and grant
# the Python binary cap_setgid so multi-user mode can call setgid().
# ⚠️ setcap MUST run in the same layer as the binary to avoid overlay2 issues.
# Install the app itself (fast — all deps are already present).
#
# Cleanup removes ~20 MB of unnecessary files:
# - pip itself (not needed at runtime)
@ -112,8 +109,7 @@ RUN pip install --no-cache-dir --no-deps . \
&& pip uninstall -y pip setuptools 2>/dev/null || true \
&& find /usr/local/lib/python3.12 -type d -name "__pycache__" -exec rm -rf {} + 2>/dev/null || true \
&& find /usr/local/lib/python3.12 -type f -name "*.pyc" -o -name "*.pyo" -delete 2>/dev/null || true \
&& find /usr/local/lib/python3.12 -type d -name "tests" -o -name "test" | xargs rm -rf 2>/dev/null || true \
&& setcap cap_setgid+ep "$(readlink -f "$(which python3)")"
&& find /usr/local/lib/python3.12 -type d -name "tests" -o -name "test" | xargs rm -rf 2>/dev/null || true
# ── Non-root user ─────────────────────────────────────────────────────────
#

View file

@ -61,7 +61,6 @@ FROM python:3.12.13-slim
# Core: tini (PID 1), gosu (drop privileges)
# Utilities: curl, git, jq, less, procps (ps/top)
# Firewall: iptables, ipset, dnsmasq (egress whitelist)
# Permissions: libcap2-bin (setcap for cap_setgid)
#
# ➡️ Want more tools? Add them here, one per line for easy diffs:
# e.g. vim \
@ -92,9 +91,7 @@ COPY . .
# Not recommended for reproducible builds; prefer bumping the base image tag.
# RUN apt-get update && apt-get upgrade -y && rm -rf /var/lib/apt/lists/*
# Install the app itself (fast — all deps are already present) and grant
# the Python binary cap_setgid so multi-user mode can call setgid().
# ⚠️ setcap MUST run in the same layer as the binary to avoid overlay2 issues.
# Install the app itself (fast — all deps are already present).
#
# Cleanup removes ~20 MB of unnecessary files:
# - pip itself (not needed at runtime)
@ -106,8 +103,7 @@ RUN pip install --no-cache-dir --no-deps . \
&& pip uninstall -y pip setuptools 2>/dev/null || true \
&& find /usr/local/lib/python3.12 -type d -name "__pycache__" -exec rm -rf {} + 2>/dev/null || true \
&& find /usr/local/lib/python3.12 -type f -name "*.pyc" -o -name "*.pyo" -delete 2>/dev/null || true \
&& find /usr/local/lib/python3.12 -type d -name "tests" -o -name "test" | xargs rm -rf 2>/dev/null || true \
&& setcap cap_setgid+ep "$(readlink -f "$(which python3)")"
&& find /usr/local/lib/python3.12 -type d -name "tests" -o -name "test" | xargs rm -rf 2>/dev/null || true
# ── Non-root user ─────────────────────────────────────────────────────────
#

View file

@ -1,6 +1,6 @@
[project]
name = "open-terminal"
version = "0.11.20"
version = "0.11.21"
description = "A remote terminal API."
readme = "README.md"
authors = [