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
-
User connects via
msh ssh. The proxy routes the connection through a reverse tunnel to the agent. - The agent allocates a PTY and starts the user's shell. A recording stream is opened to the auth service via gRPC.
- 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.
- 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
# 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.
# 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.
# 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.
# 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:
# 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.
# 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.
# 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 recording | Available |
| Real-time streaming (node-sync) | Available |
| Async upload (node) | Available |
| Local filesystem storage | Available |
| S3-compatible storage | Available |
| AES-256-GCM encryption at rest | Available |
msh play CLI playback | Available |
| eBPF enhanced recording | Available (Linux) |
| Agentless node recording (SSH MITM) | Available |
| Web UI session player | Planned |
Next Steps
- SSH Access — Set up SSH access and node agents.
- Audit Logging — Query audit events linked to session recordings.
- RBAC Configuration — Control who can view session recordings.
- Reverse Proxy Deployment — Deploy MezHub behind a TLS-terminating load balancer.