Session Recording

Mezite records every SSH session, capturing the full terminal input and output stream. Recordings provide a complete audit trail of what happened during a session and can be replayed for incident review, compliance, or training.

Recording is enabled by default and requires no additional configuration. All SSH sessions are automatically recorded at the agent and uploaded to the auth service for centralized storage and playback.


How Recording Works

Session recording happens at the agent (the mezd process running on the target node), not at the proxy. This is an important architectural decision:

  • The proxy routes SSH connections between clients and agents via encrypted tunnels. It only sees the raw SSH protocol stream (key exchange, encrypted packets) — not the actual terminal content.
  • The agent terminates the SSH connection and allocates a PTY (pseudo-terminal) for the user's shell. It has direct access to the clean, decrypted terminal I/O — the commands typed and the output displayed.

By recording at the agent after SSH decryption and PTY allocation, Mezite captures exactly what the user sees in their terminal — clean text, not encrypted protocol bytes.

Recording Flow

  1. User connects via msh ssh. The proxy routes the connection through a reverse tunnel to the agent.
  2. The agent allocates a PTY and starts the user's shell. A recording stream is opened to the auth service via gRPC.
  3. As terminal I/O flows through the PTY, each chunk is written to a local recording file and simultaneously streamed to the auth service with millisecond-precision timestamps.
  4. When the session ends, the recording is finalized. The auth service stores it in the configured backend (local filesystem or S3) and links it to the session's audit events.

What Gets Recorded

Session recording captures terminal I/O — the byte stream between the user's terminal and the remote shell:

  • All commands typed by the user (stdin)
  • All output displayed in the terminal (stdout/stderr)
  • Terminal control sequences (colors, cursor movement, screen clears)
  • Timing information for each chunk (enabling real-time playback at any speed)

Recordings do not capture:

  • File transfer contents (SCP/SFTP payloads)
  • Port-forwarded traffic
  • Activity outside the Mezite-proxied session

Recording Modes

Mezite supports three recording modes, configured via the cluster setting session_recording:

Mode Where Upload Integrity
node-sync (default) Agent Real-time streaming via gRPC Session killed if stream breaks
node Agent After session ends (bulk upload) Agent could tamper before upload
off - - No recording

node-sync (Default)

The agent records terminal I/O locally and streams each chunk to the auth service in real-time via gRPC. If the stream to the auth service breaks (network failure, auth service restart), the SSH session is terminated. This guarantees that every session is fully recorded — there is no window where a session runs unrecorded.

This is the recommended mode for compliance-sensitive environments where you need to guarantee that all session activity is captured.

node (Async)

The agent records terminal I/O to a local file. After the session ends, the recording is uploaded to the auth service via gRPC. The session continues even if the auth service is temporarily unreachable — the upload is retried later.

Use this mode when session availability is more important than recording guarantees (e.g., the agent must work even if the auth service is briefly down for maintenance).

Changing the Recording Mode

Set recording mode bash
# View current mode
mezctl config get session_recording

# Change to async mode
mezctl config set session_recording node

# Change back to real-time streaming
mezctl config set session_recording node-sync

# Disable recording entirely
mezctl config set session_recording off

The recording mode is a cluster-wide setting stored in the auth service. Agents query this setting at startup and when establishing new sessions. Changes take effect for new sessions — existing sessions continue with their original mode.


Storage

Session recordings are stored by the auth service. Two storage backends are available:

Local Filesystem (Default)

Recordings are stored on the auth service's local filesystem. This is suitable for single-node deployments and development.

Default local storage (no configuration needed) bash
# Recordings are stored in:
# /var/lib/mezite/recordings/<session-id>.rec

# To verify storage location:
mezctl config get session_recording
# node-sync

S3-Compatible Storage

For production deployments, configure an S3-compatible backend for durable, scalable recording storage. This works with AWS S3, MinIO, or any S3-compatible object store.

S3 storage configuration (environment variables) bash
# Set the storage backend to S3
MEZITE_RECORDING_BACKEND=s3

# S3 bucket and region
MEZITE_S3_BUCKET=mezite-session-recordings
MEZITE_S3_REGION=us-east-1

# Credentials (or use IAM roles if running on AWS)
MEZITE_S3_ACCESS_KEY=AKIAIOSFODNN7EXAMPLE
MEZITE_S3_SECRET_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY

# Optional: prefix for S3 keys
MEZITE_S3_PREFIX=recordings/

# Optional: force path-style addressing (required for MinIO)
MEZITE_S3_FORCE_PATH_STYLE=true

# Optional: custom endpoint (for MinIO or other S3-compatible stores)
MEZITE_S3_ENDPOINT=http://minio:9000

Encryption at Rest

Recordings can be encrypted at rest using AES-256-GCM. When enabled, each recording chunk is encrypted before being written to storage. The recording structure (timestamps, directions) remains parseable without decryption — only the terminal I/O payload is encrypted.

Enable recording encryption bash
# Set a 32-byte hex-encoded encryption key
MEZITE_RECORDING_ENC_KEY=3d992ae268214710f48d680749460...

Playback

Use msh play to replay a recorded session in your terminal:

Session playback bash
# List recent sessions
msh sessions ls
# SESSION ID                            USER   NODE          LOGIN  STARTED               ENDED
# a1b2c3d4-e5f6-7890-abcd-ef1234567890  alice  web-server-01  ubuntu 2026-04-11T10:28:35Z  2026-04-11T10:41:09Z

# Play back a session
msh play a1b2c3d4-e5f6-7890-abcd-ef1234567890
# Playing session a1b2c3d4... (user: alice, host: web-server-01)
# ubuntu@web-server-01:~$ ls -la
# total 48
# drwxr-xr-x 6 ubuntu ubuntu 4096 Apr 11 10:28 .
# ...

# Play at 2x speed
msh play --speed=2 a1b2c3d4-e5f6-7890-abcd-ef1234567890

Audit Integration

Session recordings are linked to the corresponding session.start and session.end audit events. Each audit event includes the session ID, user, node, login, and duration — the recording adds the full terminal I/O for that session.

Find and play sessions from audit events bash
# List all sessions for a specific user
msh sessions ls --user=alice

# List sessions via audit events
mezctl audit ls --type=session.end --last=24h

Permissions

Access to session recordings is controlled by RBAC:

  • Users can view recordings of their own sessions.
  • Admins can view all recordings and manage recording settings.

Agent Configuration

The agent's recording behavior is controlled by the MEZITE_RECORDING_MODE environment variable. This is separate from the cluster-wide session_recording setting — the agent env var determines what the agent does, while the cluster setting determines the default for new deployments.

Agent recording environment variables bash
# Recording mode (default: "node")
# The cluster default is "node-sync" but the agent binary defaults to "node".
# Set explicitly to match your cluster's session_recording setting.
MEZITE_RECORDING_MODE=node-sync

# Enhanced recording with eBPF (Linux only, requires privileged mode)
# Captures command executions, file access, and network connections
MEZITE_BPF_ENABLED=true

Agentless Nodes

Agentless OpenSSH nodes (registered with mezctl nodes add --openssh) are recorded via SSH MITM. The proxy terminates the client's SSH session and opens a separate SSH connection to the target host using a short-lived certificate signed by the Mezite User CA. The proxy sits between two decrypted SSH sessions and records the plaintext channel data — exactly what the user types and sees.

This requires no additional configuration beyond the standard agentless setup (TrustedUserCAKeys on the target host). Recordings appear in msh sessions ls and can be played back with msh play just like agent-recorded sessions.


Current Status

Feature Status
Agent-side PTY recordingAvailable
Real-time streaming (node-sync)Available
Async upload (node)Available
Local filesystem storageAvailable
S3-compatible storageAvailable
AES-256-GCM encryption at restAvailable
msh play CLI playbackAvailable
eBPF enhanced recordingAvailable (Linux)
Agentless node recording (SSH MITM)Available
Web UI session playerPlanned

Next Steps