Running a full Linux desktop on a Windows or macOS-based machine usually requires dual-booting, a virtual machine on your PC, or a remote desktop connection to a system that's actually running it. But what if I told you there was a way to run Linux so that you can access a full operating system and desktop from just your web browser? That's the promise of containers like LinuxServer's Webtop, and after using it, it's hard not to see why this approach is so compelling.
At a glance, it seems... weird. You point your browser at a local IP address or hostname and suddenly you have a full XFCE desktop running in your browser. There's a file manager, a terminal, a browser, and all the familiar Linux tidbits, yet none of it is running natively. Instead, the entire environment lives inside a Docker container, and your browser is effectively rendering a stream of the desktop running inside of it. It's lightweight, fast to spin up, and doesn't care whether you're on Windows, macOS, or even a Chromebook. So long as you have Docker, it's all you need.
What really interested me on this setup, though, is how neatly it fits into a modern home lab or NAS-centric workflow. This turns a Linux desktop into a service like any other that you would self-host, as you can deploy it anywhere. It's accessible in any place that I can securely reach my network, and works quite similarly in some ways to the remote desktop configuration that I have set up with my Ubuntu VM already. However, shifting Linux to a browser-based interface changes how you might use it quite a bit, and has quite a few limitations.
It's a desktop that lives in a container
Though with some big drawbacks
The Webtop container is deceptively simple in how it works. I'm using the Ubuntu XFCE version, which is just a standard Ubuntu environment running an XFCE desktop, paired with a web-based remote display stack. When you connect to it over your browser, you're not streaming a traditional VNC session in the old sense, but a more modern, optimized web interface that handles input, audio, and display surprisingly well. The result feels far closer to a lightweight virtual desktop than a clunky remote session. It's shockingly simple to set up, too, and here's my Docker compose file.
version: "3"
networks:
proxy-net:
external: true
volumes:
webtop_home:
services:
webtop:
image: lscr.io/linuxserver/webtop:ubuntu-xfce
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: all
capabilities: [gpu]
container_name: webtop
environment:
- PUID=1000
- PGID=1000
- TZ=Etc/UTC
ports:
- 3000:3000
volumes:
- webtop_home:/config
shm_size: "1gb"
restart: unless-stopped
Just because I wanted to see if it would work, this deployment was tested on Windows 11 using Docker Desktop, rather than my MacBook or a Linux-based server. Surprisingly, it did, and nvidia-smi correctly picks up my GPU out of the box. The /config directory is mapped to a volume in the above compose file as it functions as the home directory in Webtop, and is also where proot-apps are stored. These are applications that will persist when the container is recreated, and are the recommended way to install applications in Webtop.
With all of this combined, I can install packages, tweak configuration files, and customize the desktop just as I would on a normal Linux install. Given that this is running in a container, there are limitations. You're not getting full system-level control in the same way you would on a baremetal or even virtualized install, and certain operations that assume direct access to the host OS are off the table. As an experiment, I tried to install and start an NFS server inside the Webtop container. The packages installed, configuration files were created, and then everything fell apart the moment the service tried to actually boot up and configure itself.
debconf: falling back to frontend: Readline
Creating config file /etc/default/nfs-kernel-server with new version
invoke-rc.d: could not determine current runlevel
invoke-rc.d: policy-rc.d denied execution of start.
Processing triggers for man-db (2.12.0-4build2) ...
Processing triggers for libc-bin (2.39-0ubuntu8.6) ...
What failed wasn't NFS itself, but the assumptions it makes about the system it's running on. An NFS server expects control over kernel-level networking features, access to system services like systemd, and permission to manage long-running daemons. Inside a container, none of those things exist in the way a traditional Linux system expects. There is no real init system, no meaningful runlevel or system target, and no authority to start privileged, kernel-facing services. Linux environments running inside containers behave fundamentally differently from Linux systems running on bare metal or inside virtual machines, and system services like an NFS server are built around assumptions that simply aren't present in that environment.
GPU access is a big deal
It's more than just transcoding
I was surprised that GPU access worked on Windows, but it's a big deal that it does. From the container's point of view, the GPU might as well be locally installed, and applications can access CUDA, OpenGL, and other acceleration APIs as if they were running on the host machine. So many applications, particularly in machine learning contexts, expect the presence of accelerated graphics. Without a GPU, you're stuck with software-based graphics, which would become a bottleneck very quickly for any serious workloads.
This opens the door to some pretty hefty deployments, assuming you're interested in that kind of thing. You could run a local LLM, experiment with machine learning frameworks, or even transcode video from your container. Transcoding is one that most Jellyfin or Plex users will roll their eyes at, as that's been standard practice for, well, a long time. However, there's a fundamental difference in thinking when it comes to exposing a GPU to a Docker container for transcoding, and exposing a GPU to a Docker container for using it as a full operating system. Both do the same thing, but the latter opens up significantly more opportunities.
That's why running Webtop on a NAS with a discrete GPU, or even an integrated GPU, can be especially powerful. You can centralize your development environment on a machine that's designed to run 24/7 and manage your storage reliably, or you can use it as a way to deploy anything you want that makes use of your GPU.
When it makes sense to run desktop Linux as a Docker container
Basically wherever a browser is most beneficial
This setup isn't for everyone, and I can imagine quite a few people have no need for a setup like this. If you need native, low-latency input for gaming or you rely heavily on USB peripherals that don't map cleanly into a container, then a local install or a virtual machine will still make more sense as well. Paired with Tailscale or another, similar tool alongside a remote access client, you can achieve practically the same, if not better, experience, anyway.
However, where this setup can excel is in a scenario where you want the consistency and centralization of a Linux environment that's accessible from any device with a browser. You could use it for remote development, for example, or create a simple containerized image that you can deploy anywhere in moments, so long as Docker is present. The GPU access is just an additional layer that pushes it into the realm of productivity more than anything else.
For me, I just like the fact that it reframes Linux as a "service" I can access. Like how I access Home Assistant or Jellyfin in my browser, I can also access a Linux desktop. It's a full desktop-class experience that I can access no matter where I am, so long as it's running and I can remotely access it. It's pretty neat. To be clear, there are trade-offs, like being dependent on network quality alongside the fact that browser-based desktops will never feel quite as fast as anything native will. But there's still an additional dimension of flexibility this unlocks for specific workflows, and with GPU support, performance isn't one of the reasons you won't want to try it.
