Skip to content

About

Base Docker image for running Linux GUI apps in the browser, with clipboard integration and audio forwarding

Resources

Code of conduct

Contributing

Security policy

Stars

3 stars

Watchers

0 watching

Forks

GUI Web Base

Logo

Deploy Docker image  GitHub Release  GitHub last commit (branch)
Docker Image Size (tag)  Docker Pulls  GitHub License

A Docker base image to simplify the creation of downstream containers that run Linux GUI apps in a web browser.

⚡ Features

  • Linux apps in your browser
  • Rootless runtime - Never needs root, and runs as any --user you choose.
  • Integrated clipboard - Seamless copy-paste between app and browser.
  • Audio forwarding - Stream audio from the app to your browser seamlessly.
  • Automatic restart - Apps relaunch automatically when closed.
  • HTTPS redirect – Enforces secure connections over HTTPS, by default.
  • Launch apps from UI – .desktop entries are exposed and can be launched via the UI.

✨ Getting Started

This image is designed to be used as a base for Dockerfiles.
Install a desired GUI app and call the following to launch it.

CMD ["start-app","[--no-restart]", "<app>", "[args...]"]
  • Example Dockerfile with xterm

# Prefer version pinning (at least a major, e.g. :v1)
# Pinning to <major>.<minor> (e.g. :v1.1) limits updates to patches only.
FROM aandree5/gui-web-base:v1.1

# Install app
USER root
RUN apt-get update && \
    apt-get install -y my-app && \
    && apt-get autoremove \
    && apt-get clean \
    && rm -rf /var/lib/apt/lists/*
USER gwb

# Start app
CMD ["start-app", "xterm"]
  • Build and run

# Build the image
docker build -t gui-web-xterm .

# Run it
docker run -d -p 443:5443 gui-web-xterm

To access the app open https://localhost in the browser.

⚙️ Configuration

  • Build-Time Arguments

These can be set using --build-arg during docker build to define default values baked into the image.

Argument Description Default Example
GWB_RUN_BASE Base directory for per-user runtime state. /run/gwb --build-arg GWB_RUN_BASE=/var/gwb
UMASK Default file creation mask applied at runtime. 077 --build-arg UMASK=027
  • Runtime Environment Variables

These can be overridden by any downstream image or container using ENV or -e flags.

Variable Description Default Example
APP_DIRS Space-separated list of directories the app must be able to write to. Checked at startup, missing ones are created where possible, and the container exits with a clear error if any are not writable by the running user. (unset) ENV APP_DIRS="/myapp/config /var/cache" or -e APP_DIRS="..."
GWB_RUN_BASE Base directory for per-user runtime state. Each user gets <base>/<uid>/. /run/gwb ENV GWB_RUN_BASE=/var/gwb or -e GWB_RUN_BASE=/var/gwb
UMASK File creation mask used during startup. Controls default permissions for generated files. 077 ENV UMASK=027 or -e UMASK=027
ALLOW_HTTP Allows plain HTTP connections. When false, HTTP is redirected to HTTPS. true ENV ALLOW_HTTP=false or -e ALLOW_HTTP=false

ALLOW_HTTP is recomended set to false to keep all traffic secure, even with self-signed certificates. In some cases it can be usefull to allow HTTP access, shuch as if the app is going to be behind a reverse proxy, which is handling SSL certificates.

  • Permissions

The container never runs as root. It runs as the default gwb user, or as whatever identity you pass to --user.

  • Running as any user. Pass --user <uid>:<gid> to match a mounted folder's ownership, with no rebuild and no root:

    # Run as the current host user so mounted folders line up
    docker run -d -p 443:5443 \
      --user "$(id -u):$(id -g)" \
      -v "$PWD/data:/myapp/data" \
      -e APP_DIRS="/myapp/data" \
      my-app

    All runtime state (home directory, XDG_RUNTIME_DIR, SSL certificate, NGINX logs and temp files) are created at startup under /run/gwb/<uid>/, so they are always owned by the user actually running the container. Everything else in the image is read-only to the app.

  • Mounted folders only need to be writable by the uid/gid the container is running as. Any directory listed in APP_DIRS is checked at startup and the container exits with a clear error if it isn't writable.

  • Persistence. Mount a volume at /run/gwb to keep the generated SSL certificate and runtime state between runs. Otherwise a new self-signed certificate is generated on each start (and whenever the uid changes). A read-only root filesystem works too, as long as the paths written at runtime stay writable:

    docker run -d -p 443:5443 --read-only \
      --tmpfs /run/gwb:mode=1777 \
      --tmpfs /run/dbus:mode=1777 \
      --tmpfs /tmp:mode=1777 \
      --tmpfs /tmp/.X11-unix:mode=1777 \
      my-app
  • Hardening. Because nothing in the image ever needs to escalate privileges, downstream images can be run with --security-opt no-new-privileges.

  • Downstream Dockerfiles inherit USER gwb, so switch back to root for any build step that writes outside /run/gwb — installing packages, adding files, or running configure-xpra, then switch back before the final image:

    FROM aandree5/gui-web-base:v1.1
    
    USER root
    RUN apt-get update && apt-get install -y my-app && apt-get clean
    RUN configure-xpra --content-type class-instance:my-app=text
    COPY my-config/ /opt/my-app/config/
    USER gwb
    
    CMD ["start-app", "my-app"]
  • App Launch Flags

These options can be passed to CMD in your Dockerfile to customize app behavior.

Option Description Default Example
--no-restart Prevents the app from restarting when its window is closed. (enabled) CMD ["start-app", "--no-restart", "my-app"]
--title Sets the browser tab title for the web interface. GUI Web Base CMD ["start-app", "--title", "My Web App", "my-app"]
--min-quality * Sets the minimum image encoding quality (1–100). Lower values save bandwidth. 0 (auto) CMD ["start-app", "--min-quality", "80", "my-app"]
--min-speed * Sets the minimum encoding speed (1–100). Higher values reduce latency. 0 (auto) CMD ["start-app", "--min-speed", "50", "my-app"]
--auto-refresh-delay * Delay (in seconds) before sending a lossless refresh after lossy updates. 0.25 CMD ["start-app", "--auto-refresh-delay", "0.2", "my-app"]

* See the Xpra manual for more information.

  • Xpra Content-Type Mapping

Use the configure-xpra script during build to append content-type rules to Xpra’s config files. Pass mappings using --content-type in the format [fallback:]<type>:<key>=<value>.

# Multiple flags can be passed
# If the value contains spaces or special characters, wrap the value in quotes.
USER root
RUN configure-xpra \
  --content-type role:gimp-dock=text \
  --content-type "title:- Gmail -=text" \
  --content-type class-instance:xterm=text \
  --content-type commands:my_special_command=picture \
  --content-type fallback:role:browser=browser
USER gwb
  • Supported Match Types

Type Format Example Description
role role:gimp-dock=text Matches the window's internal role name (e.g. toolbars, docks, dialogs).
title title:- Gmail -=text Matches the window title shown in the title bar.
class-instance class-instance:xterm=text Matches the X11 class/instance name of the window.
commands command:my_special_command=picture Matches the command used to launch the application.
fallback fallback:role:browser=browser (generic fallback) Applies when no other match succeeds and is evaluated last as a catch-all rule.

For more details, see the Xpra tuning documentation.

🎛️ Menu Integration

This image includes a built-in freedesktop-compliant menu file that allows installed apps with .desktop files to be discovered and launched from the UI.

If an app provides a .desktop entry (installed either to /usr/share/applications or ~/.local/share/applications), it will automatically appear in the browser-based menu, no extra configuration needed.

🏷️ Versioning & Tags

This project follows Semantic Versioning and uses automated releases.

Tag Overview

Format Example Description
latest - Always the newest, may include breaking changes.
v<major> v1 Latest stable for a major version. No breaking changes.
v<major>.<minor> v1.1 Latest patch for a minor version. No new featues.
v<major>.<minor>.<patch> v1.1.0 Fixed version, only changes if manually updated.

🛠️ Contributing

Contributions are welcome! Please follow these steps to get set up:

  1. Clone the repository:

    git clone https://github.com/Aandree5/gui-web-base.git
    cd gui-web-base
  2. Install pre-commit hooks (for license headers, linting, etc.):

    pip install pre-commit
    pre-commit install
  3. Follow Conventional Commits for commit messages:

    • feat: - New feature
    • fix: - Bug fix
    • docs: - Documentation changes
    • chore: - Maintenance or tooling
    • ci: - CI/CD or workflow updates
    • refactor: - Code improvements without changing behavior
    • revert: - Revert a previous commit
  4. Open a Pull Request against main.

📦 Tech Stack Overview

  • Debian trixie-slim
    Stable Linux base, optimized for performance and size.

  • Xpra
    Enables remote access to Linux desktop apps via the web.

  • Xpra HTML5 Client
    For interacting with GUI apps through Xpra.

📚 Resources

☕ Support

If you find the project useful, consider supporting its development! Your donations help cover costs and fund future improvements.

You can support through:

Static Badge  Static Badge  Static Badge

About

Base Docker image for running Linux GUI apps in the browser, with clipboard integration and audio forwarding

Resources

Code of conduct

Contributing

Security policy

Stars

3 stars

Watchers

0 watching

Forks

Releases

Sponsor this project

Packages

Used by

Contributors

Languages