Skip to content
jronminhPublic

About

Real apt + dpkg that install Debian packages into ~/.local without root, built only on what Debian ships: user and mount namespaces, unprivileged overlayfs and systemd's user manager. Services run as sandboxed user units. Plain bash, no containers or helpers.

Topics

Resources

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

154 Commits

Folders and files

Repository files navigation

sudo-less

Install Debian packages into your home folder — no root, no sudo. It feels like apt because it is apt.

license: GPL-3.0-or-later platform: Debian root: not required

sudo-less gives you a real apt and dpkg that install .deb packages into ~/.sudo-less instead of the system. Your system files stay untouched, and you don't need admin rights. And nothing changes in how you work: a program you install runs by its name, a desktop app shows up in your launcher, a service starts on its own. No enter, no run, no second system to step into.

Use it when you can't — or would rather not — install software system-wide.

sudo-less: apt-get install without sudo, into ~/.sudo-less

What it is, and what it is not

sudo-less is Debian's own apt, installing into ~/.sudo-less, on top of the system you already run, with no root at any point.

  • Debian's own packages: the same archive, versions and ABI as your system; not a separate world of packages.
  • Shared with the host: what the system already has (libc, Qt, Python, ...) counts as installed. Only what you ask for is fetched, and it runs on the system's own libraries.
  • No root: not to install, not to run. The admin's only step is enabling unprivileged user namespaces, which Debian does by default.
  • Seamless: sl-install, which is apt install, then the program runs by its name, like everything else on your system. When a package needs to find its files at /usr or /etc, a small script under its name steps into the view for it (~0.03 s); launchers, services and their restarts on upgrade come with the package.

How it compares:

packages from relation to the host root what you installed runs
sudo-less the Debian archive shares it: installs only what the host lacks, into ~/.sudo-less no by its name
sudo apt the Debian archive installs into the system, for everyone yes by its name
Homebrew, Nix, Guix, conda their own repositories a second world of packages and libraries beside the host's no (Nix often once) by its name, from that world (conda: once activated)
Flatpak --user, AppImage bundles with their own runtimes isolated from the host no flatpak run org.example.App, or the AppImage file
distrobox, toolbox, podman, proot a whole distribution a second system in a container subordinate ids (root once), proot none inside it (distrobox enter), or exported app by app

So it is for this: you run Debian, you need more of Debian's packages, you have no sudo, and you want neither a second package world nor a second system.

What it is not:

  • Not an isolation tool. Programs you install run as you, with your files, as on any system. What sudo-less sandboxes is a package while it installs, and its services (docs/security.md).
  • Not a new distribution, and not for other distributions: it installs Debian packages on Debian.
  • Not a container. The views and sandboxes below are the means, not the point: packages expect their files at /usr, /etc, /var; a service has no system user to keep it from your files; services need a manager.

Built only on what Debian already has. The install and run path needs no container, no proot, no fakeroot, no bubblewrap, no daemon of our own, no helper binary. sudo-less stands on three mechanisms every standard Debian install ships:

mechanism from what sudo-less does with it
user and mount namespaces the kernel, driven by util-linux's unshare, nsenter, mount, setpriv (Essential and required packages) a private view where dpkg is "root" of a system whose /usr, /etc, /var are your ~/.local; a sandbox for services
overlayfs, unprivileged the kernel (5.11 and later) your prefix laid over the host's directories: the host's files show through, every write lands in ~/.sudo-less
systemd's user manager systemd --user, running as you the packages' services, translated into user units, started, restarted and removed with their package

On top of them: the real apt and dpkg, rebuilt to live in ~/.sudo-less, and plain bash scripts. A package's service keeps its own systemd sandbox (ProtectSystem=, SystemCallFilter=, ...), rebuilt with the same namespaces and a seccomp filter loaded by setpriv, and a system service that has none gets a strict one, since here it runs as you.

Install

Caution

AI-assisted and unaudited. The scripts, patches and docs were written with AI assistants (opencode, Claude Code). Read the code before you run it — especially the root script under admin/. This is not a security-reviewed artifact; docs/security.md says what it protects and what not.

No root, no compiling:

curl -fsSL https://raw.githubusercontent.com/jronminh/sudo-less/main/bootstrap.sh | bash

Then, in a new shell:

sl-update
sl-install -y ripgrep htop jq     # installs into ~/.sudo-less
sl-list                           # the packages you installed
sl-status                         # the prefix, and a check that all is well

The sl-* commands are sudo-less's; sl-help lists them. The sl- names keep them apart from the system's apt and dpkg, which manage the host.

ripgrep, htop and jq are now on your PATH — that's the whole idea. The download is checked against a published hash; see docs/release.md for how the trust works and how to verify a build yourself.

Uninstall

Your system is never touched, so there is nothing to undo there. In your home, everything of sudo-less's is in ~/.sudo-less; outside it there are only links into it (the services' units, the session's environment, the run view's unit and ~/.config/sudo-less, under ~/.config and ~/.local/share/systemd/user) and one line in ~/.bashrc and ~/.profile, marked # >>> sudo-less PATH >>>, that reads the prefix's shell settings if they are there.

sl-uninstall          # says what goes
sl-uninstall --yes    # stops the services, removes the links, the PATH block and ~/.sudo-less

Your settings (~/.config/sudo-less, a link to ~/.sudo-less/.sl/config) go with it: copy them first to keep them. What the services kept in ~/.local/state and ~/.cache stays, like any program's.

From ~/.local (before 2026-10)

sudo-less used to install into ~/.local, which it shared with other programs. tools/migrate.sh moves such an install to ~/.sudo-less, one step at a time: plan (changes nothing), install (the new prefix, and your packages again), carry (config files you changed, the services' state, alternatives you chose), clean-old (lists what was sudo-less's in ~/.local; --yes removes it).

Goal

A user created on a standard Debian install, with no sudo, installs and uses .deb packages from the supported sections into ~/.sudo-less. The admin does a one-time step (admin/) and nothing per package.

Measured by:

  1. A new user works at once: bootstrap.sh, then apt-get update && apt-get install PKG, on a fresh standard install.
  2. Coverage per section: the share of randomly sampled packages that install and run, per supported Debian section, re-measured each release.
  3. A clear boundary: which sections are the admin's, and which packages are never and why.

Where it stands: criterion 1 is verified on a fresh account with the release build. Criterion 2 is measured by the survey below. Criterion 3 is the problem map, and sl-install enforces it.

Evidence: the survey

The approach (rebuild only apt and dpkg, and make the prefix look like / only for the programs that need it) is checked by a survey rather than by hand-picked examples. dev/survey.sh takes packages sampled at random, 3 per Debian section. It installs each one into a fresh copy of the same prefix, then runs every program it ships. It records where each package stops: while installing or while running, and why.

Latest run, 2026-09-24, on 129 packages from 43 supported sections:

packages share
installs and works 86 67 %
blocked by version skew: the archive is newer than the host 30 23 %
a maintainer script fails 9 7 %
other (refused at unpack; already on the host; a program fails or runs partly) 4 3 %
  • Excluding skew, 87 % work. The admin removes skew by upgrading the host; on Debian stable it is close to zero.
  • Most programs need no tricks. Of the 70 programs checked, 22 run directly from ~/.sudo-less/usr/bin and 42 through the shared run view.
  • Better than the first design (a Termux-style relocated dpkg, same 129 packages): installs went from 63 % to 68 %, and programs from 14 working and 12 failing to 26 working and 1 failing.
  • The failures fall into a few known classes: system users, ownership changes, writes to host directories the view has no copy of. Each is placed on the problem map with its fix, or marked as the admin's.
  • Outside the supported sections (36 packages from admin, net, mail, kernel, ...), 19 install. Most failures are services, system users and /boot, which the admin's sections are meant to hold. That is the basis for a proposed limited admin and net scope.

Read more:

  • The full report: method, per-section tables, package-by-package comparison, failure classes, and next steps.
  • The raw results: results.tsv (one line per package: install verdict, error detail, each program and how it ran) and the sample, list.tsv.
  • The first survey, the baseline: docs/survey-2026-09.md.
  • To re-run it: see the header of dev/survey.sh.

Does it work for my package?

It depends first on the package's Debian section (docs/standard.md):

  • Supported: libraries and -dev, languages (python, perl, ruby, java, rust, golang, javascript, …; see docs/ecosystems.md), utils, text, editors, doc, fonts, science, graphics, sound, video, games, and desktop apps.
  • The admin's: admin, kernel, net and mail servers, database and httpd servers, tasks, metapackages, and anything that creates a system user or ships a service, in any section.
  • Services, experimental: a service package that needs no system user can already run its systemd units as your own user units, sandboxed, while you are logged in (docs/services.md). The standard still counts these packages as the admin's until a survey measures how many work (#36).

sl-install refuses a package that needs root (one that creates a system user, or installs kernel modules), before anything is installed, and says why. To check a package by hand first:

scripts/catalog/check-package.sh nginx tree ranger

What can and cannot work, and why: docs/problems.md.

Why you'd want this

  • A locked-down or managed machine where you have no admin rights but still need real tools and a compiler.
  • A shared server or lab box where touching system packages is forbidden.
  • Keeping the system clean — install into ~/.sudo-less even when you do have sudo, and leave /usr alone.

Not the right tool for: software Debian does not package (Homebrew, Nix, conda, Flathub have more), scientific stacks pinned apart from the system (conda, spack), or desktop apps you want isolated (Flatpak). And if you have sudo and don't care about a pristine system, just use apt.

How it works

apt and dpkg are the real Debian programs (apt 3.3.3, dpkg 1.23.11) plus a few patches forked from Termux's, rebuilt to install into ~/.sudo-less. dpkg runs in a private view where ~/.sudo-less looks like /usr, /etc and /var, so packages install unchanged (docs/view.md). After each apt run, prefix-integrate makes what was installed usable: launchers, a small script for each program that needs the view, and a user unit for each service. Your copy keeps its own package database, separate from the system's, and treats everything already on the system as already installed — so it only fetches what you actually ask for. Neither program is a fork.

In ~/.sudo-less, usr, etc, var and opt are what packages install, and all the view lays over the host. sudo-less itself (apt, dpkg, the tools, the sl-* commands, your settings, its records) is in one hidden folder, .sl, which no view shows as a system path and a package's install scripts cannot write.

The system's own apt and dpkg are untouched, and they keep their names: apt and dpkg in your shell are always the system's (sudo apt updates the OS). Your copies live off PATH, in ~/.sudo-less/.sl/apt and .sl/dpkg, and the sl-* commands run them: sl-install, sl-remove, sl-list, sl-help for the rest, and sl-apt / sl-dpkg for anything else. Each points apt at the prefix's config for its own run only.

Full detail: docs/apt-dpkg-port.md.

Everything here is plain shell scripts — no daemon, no third-party runtime, no binaries of our own. The only compiled code is apt and dpkg themselves; everything else is the kernel, util-linux and systemd, as Debian ships them. That's deliberate, and it's what makes the project special: you can read every line of what runs on your machine, and there is nothing to trust but the code in this repo.

Going deeper

  • docs/design.md — the whole solution on one page: the pipeline sudo-less hangs on apt's hooks, its parts, and what exists today.
  • docs/survey.md — a random sample by Debian section, installed and run: what works today and what blocks the rest.
  • docs/standard.md — scope by Debian section, and how each package is checked.
  • docs/ecosystems.md — what each language and some single packages made hard, and what the prefix view changes.
  • docs/view.md — the prefix views: the one dpkg runs in, the shared one for installed programs that need it, the one services run in, and the sandbox built on top.
  • docs/security.md — what you trust, what a package can reach while it installs and runs, the sandboxes, and their known limits.
  • docs/services.md — packages' services under your own systemd: what the user manager can do, how a unit is translated, the default sandbox.
  • docs/problems.md — every obstacle between a .deb and a user without root, by when it bites and who can fix it (for contributors).
  • docs/admin-features.md — planned: one-time admin steps that give userspace more (linger, subid, devices), and the rule that keeps them safe.
  • docs/porting.md — building apt/dpkg yourself.
  • docs/methodology.md — the design and its limits.
  • docs/prior-art.md — Termux and proot-distro: the same problem from the other end, and what we took from them.
  • dev/ — tools for developing sudo-less, such as a dsb policy with a clean test account.

Status

A personal experiment shared as a toolkit, for Debian-family systems. The account names in the docs (mobian = admin, master = unprivileged) are just examples. One maintainer supports one thing at a time: the install above is the supported path; everything else (building from source, GUI apps, the deeper tricks) is experimental. See docs/release.md.

Repository layout

bootstrap.sh   one-command install (fetches prebuilt apt/dpkg)
apt-dpkg/      apt/dpkg: setup, config/ (apt.conf.d hooks, dpkg.cfg),
               patches/ (a fork of Termux's, patches/UPSTREAM.md)
tools/         install.sh (puts the tools below into the prefix: run it after
               changing one), prefix-view.sh (the install, run and service views),
               prefix-sandbox.sh (systemd's sandbox directives on a view),
               prefix-integrate.sh (after dpkg: launchers, then
               prefix-wrap.sh, which programs run in the view, then
               prefix-units.sh, packages' systemd units as user units),
               prefix-check.sh (refuses what
               needs root), prefix-run.sh (the older overlay)
scripts/       build, setup and catalog helpers
admin/         one-time root step that enables userspace: enable-userspace.sh
dev/           tools for developing sudo-less (dsb test policy, survey.sh)
docs/          all the detail

Disclaimer

Provided "as is", without warranty of any kind (see LICENSE). The admin step changes system settings (user namespaces, PATH for all users); read docs/methodology.md and the admin/ script first. Parts were written with AI assistance and may contain mistakes. You are responsible for your system and for keeping a recoverable admin path. Not affiliated with Debian or Termux.

Contributors & license

Built by jronminh with deepseek-v4-flash (opencode) and Claude (Claude Code) as pairing assistants — see CONTRIBUTORS.md.

GPL-3.0-or-later. The patches under apt-dpkg/patches/ are a fork of termux/termux-packages's and remain under their original GPL-2.0-or-later terms (apt-dpkg/patches/UPSTREAM.md).

About

Real apt + dpkg that install Debian packages into ~/.local without root, built only on what Debian ships: user and mount namespaces, unprivileged overlayfs and systemd's user manager. Services run as sandboxed user units. Plain bash, no containers or helpers.

Topics

Resources

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages