A pty-wrapping shell logger for Linux: it gives a user a real, interactive shell while transparently recording every keystroke and every byte of output to a human-readable transcript and/or syslog, so elevated (or simply audited) access doesn't have to mean "trust and hope."
sudo rootsh
behaves exactly like sudo -s, except everything typed and printed in
that shell is captured to /var/log/rootsh/<user>.<timestamp>.<pid>
and forwarded to syslog line by line, out of the logged-in user's
reach.
The actively maintained implementation is the Python rewrite under
python/ -- a from-scratch rewrite of the original C
project (2004-2013, ~4,100 lines) targeting Linux only, with zero
runtime dependencies beyond the standard library, written in 2026 by
Zareh Kasparian, 13 years after development had stopped (see
AUTHORS). Start there:
python/README.md-- install, usage, deploymentpython/ARCHITECTURE.md-- full technical deep dive: process/data flow, on-disk formats, the privilege model, every module explained
The original C implementation still lives at the repository root
(src/, rootsh.1, configure.in, ...) for historical reference; see
Original C version below. It is
not maintained -- all new work happens in python/.
- Human-readable transcripts by default. ANSI/VT100 escape codes are stripped and output is split into clean lines before it ever hits disk or syslog -- not a raw terminal byte dump.
- Tamper-evident, not just tamper-logged. A SHA-256 hash chain covers every line of a session as it's written; editing any earlier line invalidates every digest after it. Optional periodic syslog checkpoints get evidence off-box before a compromised session could erase local traces.
- A reviewer workflow. Specific users can be authorized to replay
other users' session logs (
rootsh-review) -- and that review itself is fully re-recorded, so "who looked at what, and when" is its own auditable trail, not a blind spot. - Two deployment models: run explicitly via
sudo rootsh, or set as a user's actual login shell so every login andssh user@host commandis captured automatically, with the user never typingrootshat all -- no PAM module, no wrapping every individual command.
git clone <this repo>
cd rootsh/python
sudo ./install.sh
The installer is an interactive wizard (system-wide or per-user
install, log locations, syslog settings, reviewer list); every prompt
also has a --flag for unattended use. Full details, including the
login-shell deployment mode, are in python/README.md.
rootsh forks a pty pair, execs the target shell as the pty's slave,
and relays stdin↔pty in a select() loop, splitting pty output
into clean lines as it goes and feeding each line to a local file, a
running hash chain, and/or syslog. The one genuinely subtle piece: set
as a login shell, rootsh runs at the logged-in user's own uid --
login(1)/sshd already dropped privilege before exec'ing it -- so
it can't write into the root-owned session-log directory on its own.
A small, narrowly-scoped privileged helper (carrying only
CAP_DAC_OVERRIDE, not setuid or root) bridges exactly that one gap.
See python/ARCHITECTURE.md for the full
explanation, including why that piece has to be compiled C rather than
more Python.
GPL-3.0-or-later. See COPYING.
The project began in 2004 as a C tool built around a hand-rolled
forkpty() (with BSD/SysV-STREAMS fallbacks for old Solaris/HP-UX/AIX)
and a custom getopt/config parser. Development stopped around 2013;
its last maintainer's own notes, in the original plain-text
README at the repository root, describe switching to
sudo's own I/O logging (Defaults iolog_dir=...,
LOG_OUTPUT:LOG_INPUT:) instead of continuing rootsh's development.
The Python rewrite exists because that original code, and the ideas in
it, were still worth having in a form that's actually maintainable --
see python/README.md's "What changed vs the
original" for a full
accounting of what changed and why.