Metadata-Version: 2.4
Name: chroot-distro
Version: 2.8.3
Summary: chroot-distro is a lightweight Linux container management utility built around chroot.
License-Expression: GPL-3.0-only
Project-URL: Homepage, https://github.com/sabamdarif/chroot-distro
Project-URL: Repository, https://github.com/sabamdarif/chroot-distro
Project-URL: Bug Tracker, https://github.com/sabamdarif/chroot-distro/issues
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: backports-zstd; python_version < "3.14"
Dynamic: license-file

# Chroot-Distro

Chroot-Distro lets you run real Linux systems (Ubuntu, Debian, Alpine, Arch, and more) inside Termux on a rooted Android device, or on any regular Linux machine.

It works in three simple steps: it downloads an image from Docker Hub (or extracts a tarball you give it), unpacks it into a folder, and enters it using the Linux kernel's own `chroot` and `mount` features. Because it talks to the kernel directly, everything runs at native speed. It can also build images from a Dockerfile and push them to a registry.

Root access is required. On Termux, the root manager's `su` is used automatically. On regular Linux, a one-time `sudo chroot-distro setup` removes all future password prompts.

## Table of contents

1. [Introduction](#introduction)
2. [Commands reference](#commands-reference)
   * [`install`](#install)
   * [`login`](#login)
   * [`run`](#run)
   * [`list`](#list)
   * [`ps`](#ps)
   * [`copy`](#copy)
   * [`sync`](#sync)
   * [`rename`](#rename)
   * [`unmount`](#unmount)
   * [`kill`](#kill)
   * [`reset`](#reset)
   * [`backup`](#backup)
   * [`restore`](#restore)
   * [`diff`](#diff)
   * [`search`](#search)
   * [`setup`](#setup)
   * [`info`](#info)
   * [`help`](#help)
   * [`build`](#build)
   * [`push`](#push)
   * [`clear-cache`](#clear-cache)
   * [`remove`](#remove)
3. [Storage layout](#storage-layout)
4. [Environment variables](#environment-variables)
5. [Limitations](#limitations)
6. [Donate](#donate)

## Introduction

Chroot-Distro needs Python 3.10 or newer. It has no third-party dependencies.

### Install on Termux (Android)

1. Root your device (Magisk, KernelSU, APatch, or similar).
2. Install Termux from [F-Droid](https://f-droid.org/en/packages/com.termux/) or [GitHub Releases](https://github.com/termux/termux-app/releases).
3. Run:

```sh
pkg install python
pip install chroot-distro
```

No `sudo` or `tsu` package is needed.

### Install on regular Linux

```sh
sudo apt install python3-pip   # Debian/Ubuntu example
sudo pip install chroot-distro
```

Install with `sudo` (system-wide), not `pip install --user`. The passwordless daemon runs the code as root, so it refuses user-writable installs.

### Passwordless setup (Linux only)

Run this once so you never have to type a password again:

```sh
sudo chroot-distro setup
```

It creates a `chroot-distro` group, adds you to it, and starts a small root service (works with systemd, OpenRC, runit, dinit, and sysvinit). Log out and back in (or run `newgrp chroot-distro`) and you are done.

Add more users later with `sudo usermod -aG chroot-distro <username>`. Remove the service with `sudo chroot-distro setup --uninstall`.

> [!WARNING]
> Members of the `chroot-distro` group get root-equivalent access, exactly like the `docker` group. Only add people you trust.

### Quick start

```sh
chroot-distro install ubuntu:24.04     # download and install Ubuntu
chroot-distro login ubuntu             # open a shell inside it
chroot-distro list                     # see what is installed
chroot-distro remove ubuntu            # delete it
```

## Commands reference

Every command accepts `-h` / `--help`. Run `chroot-distro -V` to print the version.

### install

```
chroot-distro install [OPTIONS] IMAGE
Aliases: add, i, in, ins
```

Create a container. `IMAGE` can be:

| Source | Example |
|---|---|
| Docker Hub image | `ubuntu:24.04`, `alpine` |
| Other registry | `ghcr.io/foo/bar:latest` |
| Local file | `./rootfs.tar.gz`, `./image.oci.tar` |
| Web link | `https://example.com/rootfs.tar.xz` |

| Option | Description |
|---|---|
| `-n`, `--name NAME` | Give the container a custom name. Default is the image name. Needed to install the same image twice. |
| `-a`, `--architecture ARCH` | Install for a different CPU type (`aarch64`, `x86_64`, `linux/arm64`, ...). Default is your device's CPU. |
| `--allow-insecure` | Skip TLS certificate checks when downloading. Only for registries with self-signed certificates. |
| `-q`, `--quiet` | Only show errors. |

For private images, set `CD_DOCKER_AUTH` first:

```sh
export CD_DOCKER_AUTH=myuser:mypassword
chroot-distro install myuser/private-image:tag
```

Downloaded layers are cached, so installing the same image again works offline.

### login

```
chroot-distro login [OPTIONS] CONTAINER [-- COMMAND ...]
Aliases: sh
```

Open a shell inside a container. Add `--` followed by a command to run that command instead of a shell:

```sh
chroot-distro login ubuntu
chroot-distro login ubuntu -- uname -a
```

| Option | Description |
|---|---|
| `-u`, `--user USER` | Log in as this user instead of root. Accepts a name, `name:group`, a numeric `uid`, or `uid:gid`. |
| `--isolated` | Maximum isolation: nothing from the host is shared, and the container gets its own mount, PID, UTS, and IPC namespaces. All `--shared-*` and `--bind` flags are ignored in this mode. Needs kernel namespace support. |
| `--minimal` | Bare minimum mode: only `/dev`, `/proc`, `/sys` (plus `/run`, `/dev/pts`, `/dev/shm` when present) and a stripped environment. Cannot be combined with `--isolated`. |
| `--shared-home` | Make your host home folder available inside the container. |
| `--shared-tmp` | Share the host `/tmp` with the container. By default the container gets its own empty `/tmp`. |
| `--shared-display` | Share the host screen (X11/Wayland), audio, and D-Bus, so GUI apps work. `--shared-x11` is an accepted alias. |
| `-b`, `--bind SRC[:DEST[:OPTIONS]]` | Make any host folder available inside the container. Optional mount options like `ro` or `ro,nosuid`. Can be given more than once. |
| `-w`, `--work-dir PATH` | Start in this folder instead of the user's home. |
| `-e`, `--env VAR=VALUE` | Set an environment variable inside the container. Can be given more than once. |
| `--get-chroot-cmd` | Print the exact chroot command that would run, without running it. |

If you want namespace isolation but still keep all the normal shared folders, set `CD_USE_NS=1` instead of using `--isolated`.

GPU acceleration (AMD, Intel, NVIDIA) is detected and set up automatically on regular Linux. No flag needed.

### run

```
chroot-distro run [OPTIONS] CONTAINER [-- ARG ...]
```

Run the start command (Entrypoint/Cmd) defined by the container's image, like `docker run`. Mainly for server images (nginx, nextcloud, databases). Only works for containers installed from Docker/OCI images.

`run` accepts all `login` options above, plus:

| Option | Description |
|---|---|
| `--entrypoint EXECUTABLE` | Run this program instead of the image's Entrypoint. Arguments after `--` become its arguments. |
| `-d`, `--detach` | Run in the background and return immediately. Output goes to a log file (path is printed). Stop it with `chroot-distro kill CONTAINER`. |

```sh
chroot-distro run nextcloud
chroot-distro run -d nextcloud
```

### list

```
chroot-distro list [OPTIONS]
Aliases: li, ls
```

Show installed containers with their size, image source, and whether they are in use.

| Option | Description |
|---|---|
| `-v`, `--verbose` | Also show image details: source URL, image type, default user, working directory, and exposed ports. |
| `-q`, `--quiet` | Print only container names, one per line. |

### ps

```
chroot-distro ps [OPTIONS]
```

Show active sessions: PID, container, type (`login` or `run`), user, uptime, and command. Detached sessions are marked with `*`.

| Option | Description |
|---|---|
| `-q`, `--quiet` | Print only PIDs, one per line. Useful in scripts. |

### copy

```
chroot-distro copy [OPTIONS] [CONTAINER:]SRC [CONTAINER:]DEST
Aliases: cp
```

Copy files between the host and a container, or between two containers. Container paths use the `name:path` form.

| Option | Description |
|---|---|
| `-r`, `--recursive` | Copy folders with everything inside them. |
| `-m`, `--move` | Move instead of copy (source is deleted after). |
| `-v`, `--verbose` | Show each copied file. |
| `-q`, `--quiet` | Only show errors. |

```sh
chroot-distro copy ./file.txt ubuntu:/root/file.txt
```

### sync

```
chroot-distro sync [OPTIONS] [CONTAINER:]SRC [CONTAINER:]DEST
```

Like `copy`, but only transfers files that changed. Always recursive. Files are compared by size and modification time.

| Option | Description |
|---|---|
| `-c`, `--checksum` | Compare by checksum instead of modification time. Slower but more precise. |
| `-d`, `--delete` | Also delete files at the destination that no longer exist at the source. |
| `-v`, `--verbose` | Show each synced or deleted file. |
| `-q`, `--quiet` | Only show errors. |

### rename

```
chroot-distro rename OLDNAME NEWNAME
```

Rename a container.

| Option | Description |
|---|---|
| `-q`, `--quiet` | Only show errors. |

### unmount

```
chroot-distro unmount CONTAINER
Aliases: umount, um
```

Cleanly end all sessions of a container and remove its mounts. The gentle version of `kill`.

### kill

```
chroot-distro kill (CONTAINER | PID)
Aliases: k, stop
```

Force-stop a running container, like `docker kill`. Accepts a container name or a session PID from `chroot-distro ps`. All its processes are terminated and everything is unmounted. Container data is kept.

### reset

```
chroot-distro reset CONTAINER
```

Wipe a container and reinstall it fresh from its original image. All data inside is lost. Only works for containers installed from Docker/OCI images.

| Option | Description |
|---|---|
| `-q`, `--quiet` | Only show errors. |

### backup

```
chroot-distro backup [OPTIONS] CONTAINER
Aliases: bak, bkp
```

Save a container as a TAR archive. Without `--output`, the archive goes to stdout so you can pipe it.

| Option | Description |
|---|---|
| `-o`, `--output FILE` | Write to a file. Compression is picked from the extension (`.tar.gz`, `.tar.xz`, ...). Will not overwrite an existing file. |
| `-c`, `--compress TYPE` | Force compression: `gzip`, `bzip2`, `xz`, or `none`. |
| `-v`, `--verbose` | Show each archived file. |
| `-q`, `--quiet` | Only show errors. |

```sh
chroot-distro backup ubuntu -o ubuntu.tar.xz
chroot-distro backup ubuntu | gpg -c > ubuntu.tar.gpg
```

### restore

```
chroot-distro restore [OPTIONS] [BACKUP_FILE]
```

Bring back a container from a backup archive. Without a file, it reads from stdin. Compression is detected automatically.

| Option | Description |
|---|---|
| `-v`, `--verbose` | Show each extracted file. |
| `-q`, `--quiet` | Only show errors. |

```sh
chroot-distro restore ubuntu.tar.xz
gpg -d ubuntu.tar.gpg | chroot-distro restore
```

### diff

```
chroot-distro diff CONTAINER
```

Show what changed inside a container compared to its original image, like `docker diff`. `A` means added, `C` changed, `D` deleted. Needs the image layers to still be in the cache, so avoid `clear-cache` if you want `diff` to keep working.

### search

```
chroot-distro search [OPTIONS] TERM
Aliases: find, se
```

Search Docker Hub. Shows image name, stars, official status, and a short description.

| Option | Description |
|---|---|
| `-l`, `--limit N` | Show up to N results (default 25, max 100). |

### setup

```
chroot-distro setup [OPTIONS]
```

One-time passwordless setup on regular Linux. See [Passwordless setup](#passwordless-setup-linux-only). Not needed on Termux.

| Option | Description |
|---|---|
| `--user USERNAME` | Add this user to the `chroot-distro` group instead of the user who ran the command. |
| `--uninstall` | Stop and remove the daemon service. The group is kept. |
| `-q`, `--quiet` | Only show errors. |

### info

```
chroot-distro info
Aliases: version-info, nf
```

Print a diagnostics report: versions, device details, host capabilities, installed containers, and basic health checks. Attach it when filing a bug report.

### help

```
chroot-distro help [COMMAND]
Aliases: h, he, hel
```

Show detailed help for a command, or general usage when no command is given.

### build

```
chroot-distro build [OPTIONS] [PATH]
```

Build an image from a Dockerfile, like `docker build` but without Docker. `PATH` is the folder with your Dockerfile (default: current folder). The result is stored locally, so `chroot-distro install <tag>` installs it offline.

| Option | Description |
|---|---|
| `-f`, `--file PATH` | Use a Dockerfile at a different location. Pass `-` to read it from stdin. |
| `-t`, `--tag REF` | Name the image (like `myapp:1.0`). Can be given more than once. |
| `--build-arg K=V` | Set a build-time `ARG`. Can be given more than once. |
| `-a`, `--architecture ARCH` | Build for a different CPU type. Default is your device's CPU. |
| `--target STAGE` | Stop at a named stage of a multi-stage build. |
| `-o`, `--output FILE` | Also save the image as an OCI tarball (`.oci.tar`, `.oci.tar.gz`, `.oci.tar.xz`). Can be given more than once. |
| `--install-as NAME` | Install the built image as a container right after the build. |
| `--secret id=NAME[,src=PATH]` | Give a secret to `RUN --mount=type=secret` steps. Without `src=`, the value comes from the environment variable `NAME`. Secrets never end up in the image. |
| `--ssh ID[=SOCK]` | Give an SSH agent socket to `RUN --mount=type=ssh` steps. Default socket is `$SSH_AUTH_SOCK`. |
| `--no-cache` | Rebuild every step from scratch instead of reusing cached steps. |
| `--progress MODE` | Output style: `auto`, `plain`, `tty`, or `rawjson`. |
| `-v`, `--verbose` | Show each instruction and full `RUN` output. |
| `-q`, `--quiet` | Only show errors. |

`RUN` steps need root because they execute inside the half-built image. `RUN --mount` with `type=bind`, `cache`, `tmpfs`, `secret`, and `ssh` is supported. `RUN --network=none`, `RUN --security`, `COPY --link`, and `COPY --parents` are not, and fail with a clear error.

```sh
chroot-distro build -t myapp:1.0 --install-as myapp .
```

### push

```
chroot-distro push [OPTIONS] IMAGE
```

Upload an image you built with `build -t` to Docker Hub or another registry. Layers already on the registry are skipped.

| Option | Description |
|---|---|
| `-a`, `--architecture ARCH` | Push the image built for that CPU type. Default is your device's CPU. |
| `--allow-insecure` | Skip TLS certificate checks. Only for registries with self-signed certificates. |
| `-q`, `--quiet` | Only show errors. |

Set `CD_DOCKER_AUTH=username:password` before pushing to a private repository.

### clear-cache

```
chroot-distro clear-cache
Aliases: clear, cl
```

Delete all cached downloads (image layers, manifests, build cache) and show how much space was freed. After this, installing an image needs the network again, and `diff` stops working for existing containers.

| Option | Description |
|---|---|
| `-v`, `--verbose` | Show each deleted file. |
| `-q`, `--quiet` | Only show errors. |

### remove

```
chroot-distro remove [OPTIONS] CONTAINER
Aliases: rm
```

Delete a container and all its data. There is no confirmation and no undo. Active sessions are unmounted first.

| Option | Description |
|---|---|
| `-v`, `--verbose` | Show each deleted file. |
| `-q`, `--quiet` | Only show errors. |

## Storage layout

Everything lives in one data folder:

| Platform | Data folder | Cache folder |
|---|---|---|
| Termux | `$PREFIX/var/lib/chroot-distro/` | `$PREFIX/var/lib/chroot-distro/cache/` |
| Regular Linux | `~/.local/share/chroot-distro/` | `~/.cache/chroot-distro/` |

On regular Linux, commands run as root, so the folders are usually under `/root/` unless you set `XDG_DATA_HOME` / `XDG_CACHE_HOME`.

Inside the data folder:

| Path | Contents |
|---|---|
| `containers/<name>/rootfs/` | The container's filesystem |
| `containers/<name>/manifest.json` | Image info used by `reset` and `run` |
| `sessions/` | Active session records used by `ps` |
| `locks/` | Lock files preventing conflicting commands |
| `cache/oci_layers/` | Downloaded image layers |
| `cache/oci_manifests/` | Downloaded image manifests |

## Environment variables

All of these are optional.

| Variable | Effect |
|---|---|
| `CD_DOCKER_AUTH` | Registry login as `username:password` (or `username:token`). The colon is required. Used by `install`, `build`, and `push`. |
| `CD_DOWNLOAD_WORKERS` | How many layers to download at once (default 4, max 10). |
| `CD_DOWNLOAD_RATE_LIMIT` | Download speed limit, like `5M` for 5 MiB/s. Default is unlimited. |
| `CD_DOWNLOAD_MAX_RETRIES` | Retries per failed download (default 3, max 20). |
| `CD_USER` | Default user for `login`/`run` when `--user` is not given. |
| `CD_WORKDIR` | Default working directory for `login`/`run` when `--work-dir` is not given. |
| `CD_ENV` | Extra guest environment variables, one `VAR=VALUE` per line. `--env` wins on conflict. |
| `CD_ENTRYPOINT` | Default entrypoint for `run` when `--entrypoint` is not given. |
| `CD_USE_NS` | Set to `1` to give every `login`/`run` its own namespaces while keeping all normal shared folders. |
| `CD_USE_ISOLATION` | Set to `1` to force maximum isolation, same as `--isolated`. Also the only way to isolate `build` `RUN` steps. |
| `CD_FORCE_NO_COLORS` | Disable colored output. |
| `TERMUX__PREFIX` | Override the Termux prefix path. |
| `TERMUX__HOME` | Override the Termux home path used by `--shared-home`. |
| `TERMUX_APP__PACKAGE_NAME` | Termux app package name (default `com.termux`). |
| `XDG_DATA_HOME`, `XDG_CACHE_HOME` | Move the data and cache folders on regular Linux. |

## Limitations

- **Root is required.** The kernel's `chroot` and `mount` features need it. There is no rootless mode, and no support for non-rooted Android.
- **Network is shared with the host by design.** Containers use your Wi-Fi, mobile data, and VPN directly. There is no network isolation, even with `--isolated`.
- **GPU is shared by design.** GPU access is automatic whenever supported hardware is detected.
- **No full init systems.** `systemd` and similar will not work inside containers. Individual long-running programs are fine.
- **Isolation is partial.** `--isolated` covers mount, PID, UTS, and IPC namespaces. It is not a full container runtime like Docker or Podman.
- **Builds are not full BuildKit.** `RUN` steps execute under chroot. A few BuildKit features are rejected with an error, and multi-platform images are not produced.
- **`push` is single-architecture.** Build and push once per CPU type.
- **Backups capture files only.** Running programs are not saved by `backup`/`restore`.
- **Registry login is env-var only.** Set `CD_DOCKER_AUTH`. Docker's `config.json` credential helpers are not read.

## Donate

If this project is useful to you, tips in cryptocurrency are welcome:

**Bitcoin**

```
13Q7xf3qZ9xH81rS2gev8N4vD92L9wYiKH
```

**Ethereum / USDT (BEP20, ERC20)**

```
0x1d216cf986d95491a479ffe5415dff18dded7e71
```

**USDT (TRC20)**

```
TCjRKPLG4BgNdHibt2yeAwgaBZVB4JoPaD
```

**Dogecoin**

```
DJkMCnBAFG14TV3BqZKmbbjD8Pi1zKLLG6
```

---

## Issues and contributing

- **Bug reports**: https://github.com/sabamdarif/chroot-distro/issues
- **License**: GPL-3.0-only. See [LICENSE](LICENSE).

### Acknowledgments

- [proot-distro](https://github.com/termux/proot-distro) — cli design, inspiration and a lot more.
- [pyLoad](https://github.com/pyload/pyload) — downloader improvements.
- [distrobox](https://github.com/89luca89/distrobox/) - shared-display option improvements.
- [Magisk-Modules-Alt-Repo/chroot-distro](https://github.com/Magisk-Modules-Alt-Repo/chroot-distro) - some info about chroot on android.
- [ravindu644/Ubuntu-Chroot](https://github.com/ravindu644/Ubuntu-Chroot) - some info about chroot on android.
