Finestra

Window, in Italian. A desktop environment that runs in your browser and drives a headless Linux server. Windows, a taskbar, a terminal on a real PTY, a file manager, a system manager — and real Linux GUI applications, drawn on the server and rendered in a window.

Install

On the server, over SSH:

$ curl -fsSL BASE/get.sh | sudo bash

That downloads the current release, checks it against its published SHA-256, and runs the installer inside it. No toolchain, no npm, no third-party apt repository — the release carries its own Node runtime.

It asks one question: who the desktop runs as. The default is you — your home directory, the journal, and sudo, which is the same reach as the SSH session you are typing it in and nothing more. The alternatives are the same account without privilege, or a system account with no home at all: read-only observability. Answer it in advance if you are not there to type:

curl -fsSL BASE/get.sh | sudo bash -s -- --system-account

The answer is recorded and survives upgrades, and it can be changed later — see Afterwards.

Ubuntu 24.04 or newer, x86_64. The native pieces are built against 24.04's glibc; the installer refuses an older machine rather than failing later and less clearly.
Already running web desktop? Run the same one-liner. It takes the old install over: your access token, your settings and your answer to the who-runs-as question all survive, so the URL you have bookmarked keeps working. The old service, /opt/web-desktop and the web-desktop system account are removed, and the installer prints exactly what it took over and what it removed. If the new service does not come up, the old one is put back untouched.

Connect

It listens on 127.0.0.1:7070 and nothing else, so there is no port to open. Forward it over the SSH you already have:

ssh -L 7070:127.0.0.1:7070 you@server

Then open the URL the installer printed — it carries the access token. That tunnel is the authentication boundary: reaching the desktop means you already got onto the machine with a key you own, and the token is a second latch on top of it.

What you get

Terminal

A real PTY on the host. Reopens where you left it, and only asks before closing when something is running.

Files

Browse, rename, upload, download. Double-click opens whichever app handles that file.

System Manager

Processes, systemd units, the journal, disks, listening ports and certificates — live, from /proc and journalctl.

Native applications

Real Linux GUI apps in a window, through a Wayland compositor written for this.

Several machines

One shell, one connection per server, straight from your browser. The servers never learn about each other.

Session restore

Windows come back after a reload — geometry, stacking, focus, and where each app was.

Afterwards

sudo systemctl status finestra              # is it up
journalctl -u finestra -f                    # follow its logs
sudo /opt/finestra/current/update.sh <tarball>    # upgrade in place
sudo /opt/finestra/current/update.sh --rollback   # undo a bad upgrade

Changing who it runs as

The install keeps the script that asked, so the answer can be changed on a machine that no longer has the release it came from. It rewrites the unit, moves the state to follow the account — carrying the token across, so the URL you already have keeps working — and restarts:

sudo /opt/finestra/current/configure.sh --show   # what it is now
sudo /opt/finestra/current/configure.sh          # ask again
sudo /opt/finestra/current/configure.sh --as-me  # or answer directly

Prefer to do it by hand?

Download the tarball, check it, unpack it, and run the same installer:

curl -fLO BASE/releases/TARBALL
curl -fLO BASE/releases/TARBALL.sha256
sha256sum -c TARBALL.sha256
tar xzf TARBALL
cd finestra-VERSION && sudo ./install.sh
release  VERSION
sha256   SHA
built    BUILT
download the tarball · get.sh