termal.in

← Blog

How to record SSH sessions — without keylogging yourself

· Termalin team sshsession-recordingsecuritytutorial

Sooner or later you want a record of what happened in a terminal. A deploy went sideways at 2 a.m. and the postmortem needs facts, not memories. A new teammate wants to see how the migration was actually run. An auditor wants proof. Or — the new reason — an AI agent worked on your server, and “what exactly did it do?” deserves a better answer than a summary written by the same agent.

Recording SSH sessions is a solved problem several times over. What’s not solved by default is doing it without quietly building a keylogger aimed at yourself. Let’s go through the options, then the trap.

The quick ways to record a session

script — always there. Ships with every Unix since before you were born:

script -T timing.log session.log
# ... work ...
exit
scriptreplay -t timing.log session.log

Records everything printed to the terminal, replays with original timing. Crude but dependable; the files are plain text plus a timing track.

asciinema — the pretty one. asciinema rec demo.cast records the terminal as a compact JSON event stream you can replay in a browser, embed in docs, or share. Perfect for demos and how-tos; less ideal as an audit trail (it’s trivially editable).

tlog — the server-side one. Red Hat’s tlog wraps the login shell and journals every session to systemd-journald or Elasticsearch. Being server-side, it catches every way in — handy for the “all access to this box is recorded” requirement. Pairing it with a session-recording-aware SSSD setup is the classic RHEL compliance stack.

auditd tty logging — the heavyweight. pam_tty_audit records TTY input at the kernel level. Note the word input. We’ll come back to it.

The trap: recording input records your secrets

Here’s the thing nobody mentions until an incident: a terminal session has two streams. Output — what the server printed — is what you almost always want: commands appear there anyway (your shell echoes them), along with everything they printed. Input — the raw keystrokes — adds exactly one category of data output doesn’t have: the things that were deliberately not echoed.

What isn’t echoed? Passwords at sudo prompts. Passphrases. The token you pasted into a login prompt. The database password you typed into psql. Record keystrokes and your audit trail is now a credentials file with excellent timestamps — stored for years, synced to log servers, readable by whoever reads logs.

pam_tty_audit has a disable=* / enable=root dance and a log_passwd option specifically because of this; the default without care is unsafe. Homegrown wrappers that tee stdin are unsafe, period. If your recording setup can answer the question “what was the sudo password?”, it’s not an audit trail — it’s an incident waiting for a retention policy.

The rule: record output, never input. You lose nothing forensically — every command that ran is visible in the output stream — and you stop hoarding secrets.

Storage is part of the design

Recordings are as sensitive as shell history times ten: they contain config files you catted, database rows you selected, environment dumps. Two boring rules cover most of it: store them encrypted, and decide who can replay before the first recording exists, not after. If recordings sync anywhere (they should — a laptop-only audit trail dies with the laptop), the sync should be end-to-end encrypted so the storage provider is not silently a member of your security team.

The agent angle

If AI agents touch your servers, recording stops being a compliance checkbox and becomes the core of the trust model. The properties that matter:

  • The recording is made by the client, not narrated by the agent. What ran is what you replay — not what the model chose to summarize.
  • Agent actions are labeled. At 2 a.m. you need “the agent did this, I did that” to be a filter, not a reconstruction.
  • Output-only still applies. The agent’s session shouldn’t capture your keystrokes when you step in to type into it.

How Termalin does it

Termalin records sessions output-only by design — keystrokes are never captured, so there is nothing password-shaped to leak. Recording is a per-host toggle; replay is built in (with timing, like scriptreplay but with a UI), and every command an agent ran through the MCP server is marked as the agent’s in the recording and the audit log, with the device and IP it came from. Recordings sync end-to-end encrypted on Pro — the server stores ciphertext it cannot replay.

The takeaway works with any stack, ours included: record everything the server said, nothing you typed blind, encrypt the archive — and when an agent drives, make the recording the ground truth.


Termalin’s Free tier records and replays locally with no host limits — download it, or see session recording in detail.

Try it on one host.

Termalin is a fast SSH client for you — and your agents.

Free tier · 14-day Pro trial · pricing