lindroids CLI, which is also the server and runs
wherever your Linux programs run: Termux, a Linux distribution under proot (proot-distro,
UserLAnd, Andronix), or an ordinary Linux machine. There is no Android app to install: on Android
every program gets a window of its own, a full-screen Custom Tab of a browser already on the phone
(Firefox, Chrome, Edge, Samsung Internet, Brave…), which lindroids run opens from Termux. On a
desktop the windows show in a browser page.
One command installs or updates it anywhere:
All of them work the same under proot (proot-distro, UserLAnd, Andronix). The installer goes by
what is really there: the package managers that are installed and run, with
/etc/os-release
(ID, ID_LIKE) deciding between several (a Debian with pacman installed uses apt). When the
repository has no package for the CPU, or is not reachable, it installs the static binary instead
and says so. Outside Termux it needs root for the system changes: as root (the usual case in a
proot distro) it runs them directly, otherwise with sudo (or doas); it prints what it is about
to change first.
The installer can be read first: curl -fsSL https://dixonsolutions.github.io/lindroids/install.sh | less.
It honours these variables: LINDROIDS_METHOD (apt-termux, pacman-termux, apt-debian,
pacman-arch, dnf, yum, zypper, apk, xbps or static),
LINDROIDS_INSTALL_DIR (static installs), LINDROIDS_VERSION (static installs; default: latest)
and LINDROIDS_REPO_URL (a mirror or a local test repository).
It also checks for Flatpak and, when it is missing, asks whether to install it with Flathub, with
the package manager it found: apt, pacman, dnf, yum, zypper, apk or xbps. Termux has no flatpak
package, so there it shows a menu:
- Lindroids’ Flatpak for Termux (the default): ostree and Flatpak built from their release
sources with Lindroids’ Android patches (
packaging/termux-flatpak), right there on the phone, once: about 20 minutes and 600 MB of build tools. No root and no Linux distro: apps install per user,flatpak --user install flathub <app-id>, and run withlindroids run <app-id>. With root (tsu),flatpak runworks too, sandboxed by bubblewrap from Termux’s root-repo; - install it in a proot-distro distro you have (one entry per distro), with its own package manager;
- set up a new Debian proot-distro container with it;
- skip it —
lindroids setup flatpakshows the same menu later.
LINDROIDS_FLATPAK=native (the package, else a build), build (always from source),
debian, distro:<name> or no answers the menu in advance.
LINDROIDS_FLATPAK=yes or no answers the questions in advance; with no terminal they are skipped.
Termux
Use Termux from F-Droid or GitHub (the Play Store build works too).lindroids run opens the windows page in the browser (with termux-open-url) and the program’s
windows show there.
Optional packages: pkg install proot-distro to run programs from a Debian/Ubuntu/Arch rootfs
(lindroids run --distro debian …). For X11 programs, lindroids setup x11 installs Xwayland
(from Termux’s x11-repo); xwayland-satellite, which gives every X11 window its own window on the page,
comes with Lindroids. Anywhere else, lindroids setup x11 uses that system’s package manager.
Pairing: the window lindroids run opens carries a ticket, so the browser pairs by itself
the first time and signs in with its own key after that (lindroids displays lists the paired
browsers). A page opened by hand asks for the 6-digit code that lindroids pair prints.
Programs installed inside a proot-distro distro (proot-distro login debian, then apt install xournalpp) run from Termux as they are: lindroids run xournalpp finds that xournalpp is not in
Termux but in debian, and runs it there, as lindroids run --distro debian xournalpp would.
Update: pkg upgrade (or apt update && apt install lindroids), or lindroids update.
Manual setup (what the installer does):
Termux with pacman
With Termux’s pacman bootstrap the installer trusts the repository key withpacman-key and adds a
[lindroids] repository to $PREFIX/etc/pacman.conf, whose settings it keeps in
$PREFIX/etc/pacman.d/lindroids.conf. The package is the same as the .deb (same files). Update: pkg upgrade (or pacman -Syu). By hand:
pacman -R lindroids, then remove the [lindroids] section from
$PREFIX/etc/pacman.conf and $PREFIX/etc/pacman.d/lindroids.conf.
Debian and Ubuntu, including proot-distro, UserLAnd and Andronix
Run as root (the usual case in a proot rootfs) or as a user withsudo:
arm64, armhf, amd64 and i386.
If both Termux and a proot distro have Lindroids, run the server in one place only.
Update: apt update && apt upgrade, or run the installer again.
Manual setup:
Cortex Terminal
Cortex Terminal runs Ubuntu 24.04 on Android without proot: a preloaded library (libcortex-hook.so) maps /usr, /etc, /tmp and the rest into the app’s
own files. Its base system has no curl, so install that first:
/usr/libexec/lindroids/lindroids-glibc). The static lindroids hands
over to it whenever it finds itself in such a root. The browser opens through Cortex’s own
cortex-api open, which works while Cortex is on screen, as it is when you type lindroids run
there. Root mode (a real chroot) needs none of this. lindroids doctor shows what it found:
- Cortex reports uid 0 to programs while their sockets carry the app’s real uid. So Xwayland runs
with access control off (
-ac) and listens only on its socket file inside Cortex’s private storage, never on an abstract socket, so no other app can reach it; and the desktop portal signs in to its D-Bus with ANONYMOUS instead of EXTERNAL. - GLib sends fake uid 0 in
SCM_CREDENTIALS, which the kernel rejects before D-Bus authentication. For fake-root runs using the portal, Lindroids preloads a smallsendmsgshim that substitutes this process’s kernel uid/gid in its own credentials. This also lets GTK reach the portal. Other socket messages and the program’sgetuid()are unchanged. - A colon-separated
SSL_CERT_DIRbecomes one merged CA directory under the runtime directory, with symlinks deduplicated by basename (first source wins).SSL_CERT_FILEnames a PEM bundle containing the merged certificates and any existing bundle. This accommodates Node/Electron’s system CA loader, which scans the directory value as one path. Explicitrun --envvalues override these exports. - Programs get
LOCPATHpointing at Ubuntu’s locales, without which glibc cannot load evenC.UTF-8there. - Cortex replaces
update-mime-databasewith a no-op, so the MIME cache GTK needs to load SVG icons never exists;lindroids runbuilds it with the real one when it is missing or stale.
lab/test-cortex.sh). The credential fix above
has a host regression test reproducing fake root; it still needs verification on Cortex itself.
On x86 Android images, where Cortex’s arm64 build runs under ARM translation, X11 windows stay black.
Google Play Protect may block Cortex’s APK as harmful: that is Cortex’s, not Lindroids’.
Launcher tracking, CA exports and portal checks (including Electron 43) are documented in
the run regression notes.
Arch Linux and derivatives, including proot-distro
The same as Termux with pacman, in/etc: the key goes into pacman’s keyring, [lindroids] into
/etc/pacman.conf (settings in /etc/pacman.d/lindroids.conf), and the package is the static CLI
with xwayland-satellite, for x86_64, aarch64 (Arch Linux ARM), armv7h and
i686. Run as root or with sudo. Update: pacman -Syu, or run the installer again. By hand,
as above with /etc/pacman.conf and .../pacman/arch/$arch.
Fedora, RHEL and openSUSE (dnf, zypper), including proot-distro
One RPM repository for all of them,x86_64, aarch64, armv7hl and i686: the static CLI
and xwayland-satellite (glibc), with Xwayland, libxcb and libxcb-cursor as weak dependencies
(Recommends). Its metadata is signed with the repository key below (repo_gpgcheck=1) and holds
every package’s checksum. The installer writes /etc/yum.repos.d/lindroids.repo (zypper:
/etc/zypp/repos.d/lindroids.repo) and installs lindroids. Update: dnf upgrade /
zypper update, or run the installer again. By hand:
dnf remove lindroids (or zypper remove lindroids) and the .repo file.
yum without dnf (RHEL/CentOS 7, Amazon Linux 2) has a GnuPG too old for the repository’s ed25519
key; the installer uses the static binary there.
Alpine, postmarketOS and Chimera (apk), including proot-distro
The apk repository has the static CLI forx86_64, aarch64, armv7 and x86, without
xwayland-satellite: these are musl systems, and lindroids setup x11 installs Alpine’s own
xwayland-satellite package. Its index is signed with an RSA key (apk does not use OpenPGP),
lindroids.rsa.pub, which the installer puts into /etc/apk/keys/; the repository goes into
/etc/apk/repositories (/etc/apk/repositories.d/lindroids.list where that directory exists).
apk-tools 2 and 3 both read it. Update: apk upgrade, or run the installer again. By hand:
apk del lindroids, then remove the line and the key.
Void Linux (xbps), including proot-distro
/etc/xbps.d/lindroids.conf points at the xbps repository (x86_64, aarch64, armv7l,
i686 and their -musl variants; the glibc ones also carry xwayland-satellite). It is signed with
the same RSA key as the apk repository; xbps asks to trust it on the first sync, and the installer
answers yes for this repository only. Update: xbps-install -Su, or run the installer again.
Void images have neither curl nor wget: xbps-install -S curl first. By hand:
xbps-remove lindroids and rm /etc/xbps.d/lindroids.conf.
Other distributions and plain Linux
The installer downloadslindroids-<version>-<arch>-linux-musl.tar.gz from the latest
GitHub release, checks it against
the release’s SHA256SUMS, and installs ~/.local/bin/lindroids (LINDROIDS_INSTALL_DIR to
change) and, on glibc systems, ~/.local/libexec/lindroids/xwayland-satellite. Architectures:
x86_64, aarch64, armv7, i686. Make sure ~/.local/bin is in PATH. If tar or gzip
is missing it installs them with the package manager.
The same tarballs can be installed by hand:
rm ~/.local/bin/lindroids ~/.local/share/lindroids -r.
Verifying the repository keys
The APT, pacman and RPM repositories are signed with an ed25519 key:gpg --show-keys lindroids.gpg. The same key is in the source tree as
packaging/repo/lindroids.gpg.
The apk and xbps repositories are signed with an RSA key, lindroids.rsa.pub on the site and
packaging/repo/lindroids.rsa.pub in the source tree.
Programs as apps of their own (the default)
lindroids export <program> builds the program an Android app of its own on the phone (its name
and icon in the app list and Recents, its window in Android’s own WebView, no browser) and hands
it to Android’s installer. Nothing is downloaded and no build tools are needed: see
docs/APPS.md.
- Termux from F-Droid or GitHub may open the installer itself: tap Install (the first time, allow Termux to install apps).
- Termux from Google Play may not (it does not declare
REQUEST_INSTALL_PACKAGES): Lindroids puts<Name>.apkin Download and opens the file manager there. Tap it, then Install. The first time, Android asks to allow the file manager to install apps: allow it, go back, tap the APK again. - Google Play Protect may ask to scan the new app: Scan app sends it to Google; More details → Install without scanning installs it after your PIN or fingerprint.
org.lindroids, lindroids app install) is optional: it shows windows of
programs that are not exported. Its design is in BROWSER_AGNOSTIC_APK.md.
Troubleshooting
NO_PUBKEYornot signedfrom apt: the key file is missing or stale; run the installer again.unknown trustorinvalid or corrupted package (PGP signature)from pacman: the key is not trusted in pacman’s keyring; run the installer again (it runspacman-key --addand--lsign-key).apt updatecannot reach the repository from a proot distro: installca-certificates.UNTRUSTED signaturefrom apk:/etc/apk/keys/lindroids.rsa.pubis missing or stale; run the installer again.Gpg Keys not imported/Signature verification failedfrom dnf or zypper: the repository key changed; run the installer again (dnf:dnf clean allfirst).lindroids exportsaid the app is in Download but nothing installs: the installer closes at once when the source app may not install apps; allow the file manager in Android’s Install unknown apps settings, then tap the APK again.lindroids doctorshows what the CLI found (sandbox, proot, Xwayland, xwayland-satellite, server, display, the X display).