mirror of
https://github.com/open-webui/open-terminal.git
synced 2026-11-04 08:10:53 +00:00
refac
This commit is contained in:
1 parent
b1fdd9ea1d
commit
200b7ee445
7 files changed
+51
-10
No files matched your search
@@ -4,6 +4,20 @@ 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.15.2] - 2026-11-02
|
||||
|
||||
### Added
|
||||
|
||||
- Added `OPEN_TERMINAL_BROWSER_NO_SANDBOX=true` for deployments where Chromium cannot start with its sandbox enabled. The same setting applies to Browser tabs and Chromium opened from the Linux Desktop in the Docker image. Restart or redeploy Open Terminal after changing it. This setting turns off Chromium's built-in sandbox protection.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Chrome startup failures on Linux and Mac now show the actual error, such as a locked browser profile or an unavailable sandbox, instead of the generic message asking you to check the installation, user, and sandbox support. The error is also saved in the server logs.
|
||||
|
||||
### Security
|
||||
|
||||
- Chromium's sandbox now stays enabled by default in Docker. Previously, Open Terminal automatically disabled it when it detected Docker. Existing deployments that cannot run sandboxed Chromium must now explicitly set `OPEN_TERMINAL_BROWSER_NO_SANDBOX=true` to keep launching the browser.
|
||||
|
||||
## [0.15.1] - 2026-11-02
|
||||
|
||||
### Added
|
||||
|
||||
@@ -66,6 +66,12 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
xauth xdotool xclip scrot libreoffice libreoffice-gtk3 \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Debian's launcher resets CHROMIUM_FLAGS before reading this directory.
|
||||
RUN printf '%s\n' \
|
||||
'case "${OPEN_TERMINAL_BROWSER_NO_SANDBOX:-false}" in' \
|
||||
' [tT][rR][uU][eE]|1|[yY][eE][sS]) export CHROMIUM_FLAGS="$CHROMIUM_FLAGS --no-sandbox" ;;' \
|
||||
'esac' > /etc/chromium.d/open-terminal
|
||||
|
||||
COPY . .
|
||||
# Create a capability-bearing Python copy for the server process only.
|
||||
# The system python3 stays clean so user-spawned Python processes remain
|
||||
|
||||
@@ -234,6 +234,12 @@ and advertise them as disabled in `/api/config`. Values `false`, `0`, and `no`
|
||||
(case-insensitive) disable the feature. Restart the server after changing these settings.
|
||||
Desktop support still requires its platform dependencies to be available.
|
||||
|
||||
Chromium's sandbox is enabled by default, including in Docker. For a deployment
|
||||
that cannot support it, set `OPEN_TERMINAL_BROWSER_NO_SANDBOX=true` and restart the
|
||||
server. This applies to both managed Browser tabs and Chromium launched from the
|
||||
Linux Desktop in the Docker image. It disables Chromium's sandbox; the container's isolation remains
|
||||
unchanged. Values `true`, `1`, and `yes` (case-insensitive) enable this override.
|
||||
|
||||
> [!TIP]
|
||||
> Use the system config at `/etc/open-terminal/config.toml` to set site-wide defaults for host and port, and the user config for personal settings like the API key — this keeps the key out of `ps` / `htop`.
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ import sys
|
||||
import websockets
|
||||
|
||||
from fastapi import WebSocket, WebSocketDisconnect
|
||||
from open_terminal.env import sanitized_environ
|
||||
from open_terminal.env import BROWSER_NO_SANDBOX, sanitized_environ
|
||||
from .rewrite import target_url
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
@@ -104,8 +104,15 @@ class Host:
|
||||
self.sequence = 0
|
||||
self.pending = {}
|
||||
self.handlers = {}
|
||||
self.stderr = b""
|
||||
self.stderr_reader = asyncio.create_task(self.read_stderr())
|
||||
self.reader = asyncio.create_task(self.read())
|
||||
|
||||
async def read_stderr(self):
|
||||
if self.process.stderr is not None:
|
||||
while chunk := await self.process.stderr.read(4096):
|
||||
self.stderr = (self.stderr + chunk)[-4096:]
|
||||
|
||||
async def read(self):
|
||||
try:
|
||||
while True:
|
||||
@@ -171,6 +178,8 @@ class Host:
|
||||
await self.process.wait()
|
||||
self.reader.cancel()
|
||||
await asyncio.gather(self.reader, return_exceptions=True)
|
||||
with contextlib.suppress(TimeoutError):
|
||||
await asyncio.wait_for(self.stderr_reader, 1)
|
||||
if self.channel:
|
||||
await self.channel.close()
|
||||
if self.display:
|
||||
@@ -243,13 +252,13 @@ async def get_host(session):
|
||||
"--no-default-browser-check",
|
||||
"--disable-dev-shm-usage",
|
||||
]
|
||||
if BROWSER_NO_SANDBOX:
|
||||
args.append("--no-sandbox")
|
||||
if os.name == "nt":
|
||||
host = await windows_host(args, profile, session.fs.home)
|
||||
hosts[key] = host
|
||||
return host
|
||||
args.append("--remote-debugging-pipe")
|
||||
if Path("/.dockerenv").exists():
|
||||
args.append("--no-sandbox")
|
||||
display = None
|
||||
if all(
|
||||
shutil.which(name) for name in ("Xtigervnc", "xauth", "xrandr", "xdotool")
|
||||
@@ -302,7 +311,7 @@ async def get_host(session):
|
||||
*command,
|
||||
stdin=asyncio.subprocess.PIPE,
|
||||
stdout=asyncio.subprocess.PIPE,
|
||||
stderr=asyncio.subprocess.DEVNULL,
|
||||
stderr=asyncio.subprocess.PIPE,
|
||||
limit=16 * 1024 * 1024,
|
||||
**kwargs,
|
||||
)
|
||||
@@ -313,11 +322,11 @@ async def get_host(session):
|
||||
host = Host(process, display)
|
||||
try:
|
||||
await host.send("Browser.getVersion")
|
||||
except Exception:
|
||||
except Exception as exc:
|
||||
await host.close()
|
||||
raise RuntimeError(
|
||||
"Chrome could not start. Check its installation, OS user, and sandbox support."
|
||||
)
|
||||
detail = host.stderr.decode(errors="replace").strip() or str(exc)
|
||||
log.warning("Chrome startup failed: %s", detail)
|
||||
raise RuntimeError(f"Chrome could not start: {detail}") from exc
|
||||
hosts[key] = host
|
||||
return host
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ from fastapi.responses import Response
|
||||
from pydantic import BaseModel, Field, model_validator
|
||||
|
||||
from open_terminal.dependencies import get_filesystem, matches_api_key, verify_api_key
|
||||
from open_terminal.env import sanitized_environ
|
||||
from open_terminal.env import BROWSER_NO_SANDBOX, sanitized_environ
|
||||
from open_terminal.utils.fs import UserFS
|
||||
|
||||
router = APIRouter(prefix="/desktop", tags=["desktop"])
|
||||
@@ -67,6 +67,8 @@ class Desktop:
|
||||
"XDG_RUNTIME_DIR": str(self.runtime),
|
||||
"XAUTHORITY": str(self.runtime / "Xauthority"),
|
||||
}
|
||||
if BROWSER_NO_SANDBOX:
|
||||
self.env["OPEN_TERMINAL_BROWSER_NO_SANDBOX"] = "true"
|
||||
|
||||
async def spawn(self, *command, **kwargs):
|
||||
if self.fs.username:
|
||||
|
||||
@@ -144,6 +144,10 @@ ENABLE_BROWSER = os.environ.get(
|
||||
str(config.get("enable_browser", True)),
|
||||
).lower() not in ("false", "0", "no")
|
||||
|
||||
BROWSER_NO_SANDBOX = os.environ.get(
|
||||
"OPEN_TERMINAL_BROWSER_NO_SANDBOX", "false"
|
||||
).lower() in ("true", "1", "yes")
|
||||
|
||||
ENABLE_DESKTOP = os.environ.get(
|
||||
"OPEN_TERMINAL_ENABLE_DESKTOP",
|
||||
str(config.get("enable_desktop", True)),
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
[project]
|
||||
name = "open-terminal"
|
||||
version = "0.15.1"
|
||||
version = "0.15.2"
|
||||
description = "A remote computer API."
|
||||
license = "MIT"
|
||||
readme = "README.md"
|
||||
|
||||
Reference in new issue
Block a user