You run one command on a server. It creates a throwaway admin account, gives it passwordless sudo, generates an SSH key pair, writes every credential into a tidy folder, and schedules its own deletion. When the time's up the account, its home, its sudo rights, its keys and its archives are all gone.
Handy when a contractor needs root for a day, when you're handing a box to a colleague for a weekend, or when you want a login to hand out and forget about.
- 🔐 32-character random password and a 4096-bit RSA key with its own passphrase
- ⏱️ Timed expiry from 1 hour up to 30 days (720h), default 24h
- 🧹 Layered cleanup: an
atjob for the exact minute, a cron sweeper every 5 minutes that survives reboots and a stoppedatd, and an optional systemd timer for extra visibility on systemd hosts - 🛡️ Hard lock via
chage -Eas a last-resort safety net - 📦 Download bundle:
.tar.gz(and password-protected.zipwhenzipis installed) with everything the recipient needs - 📄 Self-explaining docs inside the bundle: how to connect, how to escalate, how to terminate early
- 🖥️ Interactive menu or plain CLI flags, your choice
- 🚫 Refuses unsafe runs: won't schedule itself from a non-root-owned or world-writable file, and won't purge anything besides a name it generated
One line, download and run:
sudo curl -fsSL https://raw.githubusercontent.com/readypixels/temproot/main/temproot.sh -o /usr/local/sbin/temproot.sh && sudo chmod 755 /usr/local/sbin/temproot.sh && sudo bash /usr/local/sbin/temproot.shThis drops the script where root owns it (the script refuses to schedule itself from anywhere else), makes it executable, and opens the menu. Next time it's:
sudo temproot.sh # menu
sudo temproot.sh --create # straight to a new accountThe script prints the credentials at the end and tells you where the archive landed. Pull it down with:
scp root@SERVER:/root/.temproot_sessions/downloads/temproot_tadmin_xxxxxx_*.tar.gz .Fair. Piping a script straight into sudo bash means running something you haven't seen yet. Do it in three steps instead:
curl -fsSL https://raw.githubusercontent.com/readypixels/temproot/main/temproot.sh -o temproot.sh
less temproot.sh
sudo install -m 755 -o root temproot.sh /usr/local/sbin/temproot.sh
sudo temproot.shDownload it, read it, then move it to a root-owned path and run it. Same script, same result, nothing runs before you've looked at it.
The interactive menu, with one live session showing its countdown:
A full --create run, from key generation to the final summary:
| Flag | What it does |
|---|---|
| (none) | Interactive menu |
--create |
Create a new account right now with the current expiry |
--list |
Show active sessions, time remaining, and which layers guard each one |
--downloads |
Show archive paths |
--purge <user> |
Terminate a session early and wipe everything |
--sweep |
Purge every expired session (this is what cron runs) |
--help |
Usage |
Change the expiry from the menu (option 5) before creating, or edit EXPIRE_HOURS at the
top of the script.
Up to four things guard each session, in this order:
atjob at the exact expiry minute, ifatdis installed and running.- Cron sweeper (
*/5 * * * *) reading each session's.metafile and purging any whose expiry epoch has passed. It installs itself on first create and removes itself when no sessions remain. It works after a reboot and doesn't care whetheratdexists. - systemd timer (
temproot-<user>.timer), created automatically when the box runs systemd. It's optional and additive, not a replacement for the other layers. It exists for one reason: on a systemd host you can watch it withsystemctl list-timersorjournalctl, and it doesn't needatdat all. It closes no security gapatand cron didn't already have. Anyone with root on the box cansystemctl disableorsystemctl maska temproot timer as easily as they can edit a crontab or delete anatjob. See SECURITY.md for what that means for you. - Account hard lock (
chage -E) set to the day after the intended expiry. This is a backstop only.chage -Etakes a date and locks at midnight of this date, so setting it to the expiry date itself would cut a session short by up to 24 hours.
If you only see a warning saying "only the cron sweeper is guarding this session", it's
fine. It means atd isn't around, and either there's no systemd or the timer failed to
install. The sweeper alone is enough. --list shows you which layers are active for each
session, and none of this requires systemd. On Alpine, BusyBox containers, and other
non-systemd setups, temproot runs exactly as it always has: at plus the cron sweeper plus
the hard lock.
temproot_tadmin_xxxxxx/
├── README.txt quick overview
├── ACCESS_INFO.txt master file: server, user, password, key, passphrase
├── PASSWORD.txt
├── SSH_PASSPHRASE.txt
├── SSH_CONNECT_COMMANDS.txt copy-paste ssh / scp lines
├── PUBLIC_KEY.txt
├── HOW_TO_TERMINATE.txt
└── ssh_keys/
├── id_rsa_temproot private key (encrypted with the passphrase)
└── id_rsa_temproot.pub
- Running processes owned by the user (
pkill -u) - The sudoers drop-in
- Membership of
sudo/wheel - The user and its home directory
- The
atjob and the cron sweeper line (once no sessions are left) - The systemd timer and service unit, if one was created
- The session folder under
/root/.temproot_sessions/ - Every archive for the user under
downloads/
Read SECURITY.md before handing bundles to anyone. It says what the script protects, what it deliberately leaves to you, and how to report a problem.
docs/tutorial.md walks through every command with an annotated screenshot per step, from install to purge. All thirteen shots are from a real run.
There's a WSL Ubuntu test loop written up in CLAUDE.md. Short version: copy
the script into /tmp inside WSL, chown it to root, create a 1-hour session, edit the
.meta expiry to the past, and watch the cron sweeper remove it at the next 5-minute mark.
MIT. Do what you like with it, don't blame me if you lock yourself out.
Made with ❤️ by ReadyPixels
🛠️ Built for sysadmins who'd rather hand out a key which expires than a password which doesn't.
⭐ If it saved you a late-night "did I delete the account?" moment, a star is welcome.