Menu da documentação

Documentação

Installation

Every install shape: VPS, desktop app, kiosk session, paths and flags.

Nesta página

Overview

There is exactly one installer and one command. What changes between a VPS, a laptop and a kiosk machine is not the download — it is which host integration the installer sets up around the same binary.

bash
curl -fsSL https://tde.sh/install | sh

The install page is the short version with a copy button. This page is the long version: every flag, every path, every override.

Platforms and artifacts

PlatformArtifactBuild target
Linuxtde-<tag>-<triple>.tar.gz (static musl)x86_64-unknown-linux-musl, aarch64-unknown-linux-musl
macOSTDE-<tag>.dmg containing TDE.appuniversal (x86_64 + arm64 apple-darwin)

Linux and macOS do not share bytes. They are separate builds from separate workflows, and the installer picks by uname.

The Linux binary is fully static: no glibc, no OpenSSL (TLS is rustls), SQLite compiled in. It runs on Alpine, Debian, Ubuntu and stock VPS images without a single shared-library dependency.

On macOS, TDE.app does not draw pixels itself. Its launcher opens Terminal.app and runs the embedded binary, so the experience is a normal terminal window. Anything below about the Linux kiosk session does not apply.

What the installer actually does

  1. Reads any existing install receipt (~/.local/share/tde/install.json, then /opt/tde/install.json) and prints the currently installed version. A pre-receipt binary found on PATH is reported as a legacy install and migrated safely.
  2. Detects OS and architecture, and refuses unsupported combinations.
  3. Resolves the release: it reads tag_name (or the older tag) out of the channel feed at https://tde.sh/releases/<channel>.json, with plain sed so no jq is needed on a minimal host.
  4. Downloads the artifact and its .sha256 sidecar. A missing checksum or a mismatch aborts the install — there is no unverified path.
  5. Installs atomically (see Where things land).
  6. Applies whichever host integrations you asked for.

Re-running the command is always safe, and is a perfectly good manual update.

Install modes

Flags may be given in any order, after -s --:

bash
curl -fsSL https://tde.sh/install | sh -s -- --persist --system
FlagEffect
(none)Headless install: just the binary. The primary VPS shape.
--appDesktop-app launcher: installs kitty plus a "TDE" applications-menu entry.
--no-appOpt out of the app launcher.
--desktopAlso install the kiosk login session.
--loginAuto-start TDE on interactive SSH login.
--persistAuto-start TDE inside a tmux session that survives disconnects.
--systemInstall system-wide to /usr/local/bin (uses sudo when not root).
--channel NAMERelease channel to resolve (default stable).
-h, --helpPrint usage and exit.

--persist and --login are the same slot: --persist wins whichever order you pass them in.

Headless / VPS — the default

No flags. You get the binary and nothing else, which is exactly right for a server: the desktop is drawn by your terminal over SSH.

bash
ssh user@vps
curl -fsSL https://tde.sh/install | sh
tde

--app — the desktop app

Installs kitty through your package manager and drops a launcher into your applications menu. kitty is chosen deliberately: its graphics protocol is what gives the built-in browser, image viewer and PDF viewer real-pixel rendering, which plain GTK terminals cannot display.

On Linux it installs into user scope, no root required:

  • ~/.local/share/applications/tde-app.desktop
  • ~/.local/share/icons/hicolor/512x512/apps/tde.png

and refreshes the desktop database when update-desktop-database exists. The entry runs kitty --class=tde-app --title=TDE --start-as=maximized tde.

On macOS there is no .desktop machinery: the installer installs kitty via Homebrew when kitty is absent, or warns and points at kitty's download page if Homebrew is missing. Then you open kitty and run tde.

--desktop — the kiosk login session

Turns TDE into a session you can pick at the display manager, replacing the GUI desktop. This one needs root (it writes under /usr/), so the installer uses sudo when you are not root.

It installs:

  • cage — the Wayland kiosk compositor.
  • kitty — best-effort, the preferred kiosk terminal.
  • foot — the lightweight fallback terminal.
  • /usr/local/bin/tde-session — the session launcher.
  • /usr/share/wayland-sessions/tde.desktopTDE (Text Desktop).
  • /usr/share/xsessions/tde-x11-nested.desktop — a nested X11 fallback entry.

It also removes any old /usr/share/xsessions/tde.desktop, because on some display managers that entry started cage as a nested X client and the desktop came up tiny instead of taking over the monitor. Prefer the Wayland entry; the nested X11 one is a fallback, not a real kiosk.

tde-session picks its host in this order:

  1. cage + kitty (full graphics protocol, truecolor, HiDPI)
  2. cage + foot (sixel: real pixels, 256-color palette)
  3. cage + alacritty (cells only)
  4. bare kitty
  5. the current terminal, with a warning

It reads a few environment variables:

VariableDefaultEffect
TDE_BINtdeBinary to launch inside the kiosk terminal.
TDE_FONTGeist Mono if fontconfig knows it, else monospaceKiosk font family.
TDE_FONT_SIZE14Global UI scale — bigger font means bigger cells, so everything scales.
TDE_CAGE_MODElastcage -m mode. extend spans all connected outputs; last fills one.

Log out and pick TDE (Text Desktop) from the session menu (LightDM, GDM, SDDM). TDE_FONT_SIZE is the single lever for scale: try 11 on a dense 4K panel, 18 on a TV.

--login and --persist — SSH autostart

Both write a marked block into ~/.profile, between # >>> TDE autostart >>> and # <<< TDE autostart <<<. The block is removed and rewritten on every install, so re-running never stacks duplicates.

--login execs TDE directly:

~/.profile
# >>> TDE autostart >>>
if [ -z "$TDE_NO_AUTOSTART" ] && [ -z "$TDE_STARTED" ] && [ -t 0 ] && command -v tde >/dev/null 2>&1; then
  export TDE_STARTED=1
  exec tde
fi
# <<< TDE autostart <<<

--persist installs tmux if missing and execs TDE inside an attach-or-create session instead, so the desktop survives a dropped connection:

bash
TDE_TMUX_SESSION="${TDE_TMUX_SESSION:-loop}"
exec tmux new-session -A -s "$TDE_TMUX_SESSION" tde

Set TDE_TMUX_SESSION to use a name other than loop.

--system — system-wide install

Without it, a non-root install is per user. With it (or when you are already root), everything moves to system paths and sudo is used as needed. The installer aborts if --system is requested with neither root nor sudo available.

Where things land

Linux installs never overwrite a binary in place. Each release goes into its own immutable directory and a symlink is swapped atomically, which is what makes an interrupted install a no-op and a rollback possible.

ScopeBinary entry pointInstall root
user (default)~/.local/bin/tde~/.local/share/tde
--system / root/usr/local/bin/tde/opt/tde

Inside the install root:

text
<root>/versions/<tag>/tde   the immutable release binary
<root>/current              symlink -> versions/<tag>
<root>/install.json         the install receipt

~/.local/bin/tde is a symlink to <root>/current/tde, replaced by an atomic rename. If a plain (non-symlink) binary was already sitting there from an older install, it is preserved as tde.legacy for rollback.

The receipt records what was installed and where the updater should look next time:

~/.local/share/tde/install.json
{
"schema": 1,
"version": "v0.3.32",
"channel": "stable",
"mode": "user",
"root": "/home/you/.local/share/tde",
"manifest": "https://tde.sh/releases/stable.json"
}

mode is user, system, or macos-app. The in-app updater reads manifest from here, which is how a mirror chosen at install time keeps applying to later background updates — see Updating.

On macOS the app is installed to ~/Applications/TDE.app, or /Applications with --system. The previous bundle is kept as TDE.app.previous, and the receipt is still written to ~/.local/share/tde/install.json.

If the chosen bin directory is not on your PATH, the installer prints the exact line to add to ~/.profile rather than editing it silently.

Environment overrides

VariableDefaultEffect
TDE_CHANNELstableChannel to resolve (same as --channel).
TDE_MANIFEST_URLhttps://tde.sh/releases/<channel>.jsonRelease-feed override. Recorded in the receipt.
TDE_RELEASE_BASEhttps://tde.sh/releasesBase for immutable artifact URLs.
TDE_VERSIONlatest in the feedInstall a specific tag, skipping feed resolution.
TDE_URLFull artifact URL. Overrides repo and version resolution entirely.
TDE_PACKAGING_BASEhttps://tde.sh/packagingWhere --app / --desktop fetch the .desktop files, icon and tde-session.

The checksum sidecar is always fetched from <artifact-url>.sha256, including when you set TDE_URL — a mirror has to publish both.

bash
# Pin a version
TDE_VERSION=v0.3.30 curl -fsSL https://tde.sh/install | sh

# Point everything at an internal mirror
TDE_MANIFEST_URL=https://mirror.corp/tde/stable.json \
TDE_RELEASE_BASE=https://mirror.corp/tde/releases \
TDE_PACKAGING_BASE=https://mirror.corp/tde/packaging \
  curl -fsSL https://tde.sh/install | sh

Building from source

For development, or when you cannot reach the release host:

bash
cargo build --release -p tde
./target/release/tde

The repository also carries scripted equivalents of the installer for CI and image builds — packaging/install.sh for the kiosk login session (needs root, targets apt/dnf/pacman/zypper hosts) and packaging/install-vps.sh for the headless path, which builds the static binary itself when cargo is present. Both are aimed at a repo checkout, not at end users.

A cargo build living under target/debug or target/release never auto-updates itself.

Uninstall

packaging/uninstall.sh removes the system install and the login session:

bash
sudo packaging/uninstall.sh

It deletes /usr/local/bin/tde, /usr/local/bin/tde-session and the three session entries (PREFIX overrides /usr/local). It deliberately leaves /opt/tde, ~/.tde, cage and foot alone.

For a user install, or to remove state as well, delete by hand:

bash
rm -f  ~/.local/bin/tde ~/.local/bin/tde.legacy
rm -rf ~/.local/share/tde        # versioned binaries + install receipt
rm -rf ~/.tde                    # runtime state, update staging
rm -rf ~/.config/tde             # configuration
rm -f  ~/.local/share/applications/tde-app.desktop

If you used --login or --persist, also delete the marked block in ~/.profile between # >>> TDE autostart >>> and # <<< TDE autostart <<<.

Next