Skip to content

Session Recordings

Minh Tu Le edited this page Apr 10, 2026 · 2 revisions

The Gateway records interactive sessions (e.g., kubectl exec, SSH shell) in Asciicast v2 format (playable with the Twingate session player or asciinema play) and emits them as structured JSON audit logs to stderr. Each log entry has logger: "gateway.audit" and contains the recording content in the asciicast field, with an asciicast_sequence_num that increments on each flush (long sessions produce multiple entries). Since recordings are just structured logs on stderr, they can be routed to any storage backend using standard log pipelines (Vector, Fluentd, Fluent Bit, etc.).

Example: Use Vector to Sync Recordings to GCS

Vector is an open-source observability pipeline that can collect, transform, and route logs. This example uses the Vector Helm chart to filter session recordings from Gateway pods and export them as .cast files to Google Cloud Storage.

Prerequisites

Prior to configuring Vector, ensure the following prerequisites are met:

  1. Create a Google Cloud Storage bucket for log storage.
  2. Establish a Service Account in Google Cloud Platform with appropriate bucket write permissions. We'll be using this user with Workload Identity to authenticate the Vector pods.
  3. Apply the vector.dev/twingate-gateway=true label to the target Gateway pods by applying the Gateway's podLabels setting in its values.yaml.

Vector Installation and Configuration

Create a configuration file named values.yaml that defines the Vector logs processing pipeline. This configuration implements the following workflow:

  • Collects structured JSON logs from Kubernetes pods labeled with vector.dev/twingate-gateway=true
  • Processes and filters logs containing session recordings (identified by the asciicast field)
  • Exports the filtered recordings as .cast files to the designated Google Cloud Storage bucket
role: Agent
logLevel: "info"
env:
  - name: VECTOR_SELF_NODE_NAME
    valueFrom:
      fieldRef:
        fieldPath: spec.nodeName

rbac:
  create: true

serviceAccount:
  create: true
  annotations:
    iam.gke.io/gcp-service-account: <SERVICE_ACCOUNT_EMAIL>  # TODO: replace this
  name: vector

customConfig:
  data_dir: /vector-data-dir
  api:
    enabled: true
    address: 0.0.0.0:8686
    playground: false
  sources:
    gateway_logs:
      type: kubernetes_logs
      extra_label_selector: vector.dev/twingate-gateway=true
    internal_metrics:
      type: internal_metrics
  transforms:
    gateway_json_logs:
      type: remap
      inputs:
        - gateway_logs
      drop_on_abort: true
      metric_tag_values: single
      source: |-
        parsed_json = parse_json!(.message)
        if parsed_json == null {
          abort
        }
        if parsed_json.logger != "gateway.audit" {
          abort
        }
        . = parsed_json
      timezone: local
    session_logging:
      type: remap
      inputs:
        - gateway_json_logs
      drop_on_abort: true
      metric_tag_values: single
      source: |-
        if .asciicast == null {
          abort
        }
        parsed_ts = parse_timestamp!(.ts, "%Y-%m-%dT%H:%M:%S%.3fZ")
        . = {
          "filename_ts_part": format_timestamp!(parsed_ts, "%Y%m%d%H%M%S"),
          "user_id": replace!(.user.username, r'@|\.', "_"),
          "conn_id": .conn_id,
          "message": .asciicast,
          "asciicast_sequence_num": .asciicast_sequence_num
        }
      timezone: local
  sinks:
    gcs:
      type: gcp_cloud_storage
      inputs:
        - session_logging
      bucket: <YOUR_GCS_BUCKET_NAME>  # TODO: replace this
      key_prefix: sessionrecordings/{{"{{"}} .user_id {{"}}"}}_{{"{{"}} .filename_ts_part {{"}}"}}_{{"{{"}} .asciicast_sequence_num {{"}}"}}
      filename_extension: cast
      filename_append_uuid: false
      compression: none
      encoding:
        codec: text
      batch:
        max_events: 1
        timeout_secs: 1

Add the vector helm repository:

helm repo add vector https://helm.vector.dev
helm repo update

Then install Vector in a dedicated namespace:

helm install vector vector/vector -n vector --create-namespace -f values.yaml

Clone this wiki locally