Send Tailscale SSH session recordings to S3 · Tailscale Docs

Send Tailscale SSH session recordings to S3

Last validated: Jan 9, 2026
By default, Tailscale SSH session recording will save recordings to the Docker host's filesystem. While this is a fast and straightforward way to deploy session recorders, you may want to use a more scalable and resilient storage solution like Amazon S3.

Tailscale SSH session recording is currently in beta. To try it, follow the steps below to enable it for your network using Tailscale v1.40.1 or later.

Tailscale SSH session recording is available for the Personal and Enterprise plans.
You can configure session recorder nodes to send recordings to Amazon S3 or another S3-compatible object storage service such as MinIO, Wasabi, Google Cloud Storage, or Cloudflare R2.

If you deploy recorder nodes with the built-in web UI enabled, users can access recordings stored in S3 in the web UI.

Configure S3 as storage for session recording nodes

Prerequisites

To configure S3 as the backend storage for session recording, you must have access to an AWS account with permission to create:

and either

or

Create an IAM policy and user/role

Create the following IAM policy in your AWS account. Replace <bucket-name> with the name of your S3 bucket on both lines of the Resource section.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:PutObject",
        "s3:GetBucketLocation",
        "s3:GetObject",
        "s3:ListBucket"
      ],
      "Resource": [
        "arn:aws:s3:::<bucket-name>/*",
        "arn:aws:s3:::<bucket-name>"
      ]
    }
  ]
}

If you are running the recorder nodes without the built-in web UI, you can omit s3:GetObject and s3:ListBucket from this policy. s3:PutObject and s3:GetBucketLocation are always required.

If you plan to use IAM access keys for permission to write to the bucket, assign this policy a new IAM user, and create an access key for this user. If you plan to use an IAM role, create an IAM role and attach the previously defined policy to the role.

Deploy the recorder node

Deploying a recorder node with S3 as the storage backend is similar to the standard filesystem deployment. You'll need to add your IAM credentials or role, and the S3 bucket information.

Deploy with AWS access keys

For AWS access keys, specify the AWS access key and secret key:

docker run --name tsrecorder --rm -it \
  -e TS_AUTHKEY=$TS_AUTHKEY \
  -e AWS_ACCESS_KEY=$AWS_ACCESS_KEY \
  -e AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY \
  -v $HOME/tsrecorder:/data \
  tailscale/tsrecorder:stable \
  /tsrecorder --dst='s3://s3.us-east-2.amazonaws.com' --statedir=/data/state \
  --bucket=$S3_BUCKET_NAME --ui \

Deploy with attached IAM roles

For IAM roles, the credentials are retrieved from the AWS metadata service. You'll need to assign an IAM role (and if using an EC2 instance, an IAM instance profile) to the container.

docker run --name tsrecorder --rm -it \
  -e TS_AUTHKEY=$TS_AUTHKEY \
  -v $HOME/tsrecorder:/data \
  tailscale/tsrecorder:stable \
  /tsrecorder --dst='s3://s3.us-east-2.amazonaws.com' --statedir=/data/state \
  --bucket=$S3_BUCKET_NAME --ui \

If the instance you're provisioning the Docker container is using Instance Metadata v2, the default PUT response hop limit is 1 (that is, from the EC2 instance to the metadata service). For IAM instance profiles to work with Docker, you must first configure the limit to account for the extra hop through the EC2 instance, so 2 at minimum.

Required flags:

Optional flags:

There are multiple ways to define the AWS IAM credentials needed to connect to an S3 bucket. In order of precedence, they are:

  1. Specify --access-key and --secret-key
  2. Set AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY
  3. Specify none of the above, and be on an EC2 instance with the right permissions.

Cloudflare R2 Compatibility

Cloudflare R2 Storage provides an S3-compatible API; however, an additional setting is needed due to differences in their implementation. To use Cloudflare R2 as the storage service for session recordings set the environment variable S3_SEND_CONTENT_MD5 to true in addition to any environment variables you are already passing.

S3_SEND_CONTENT_MD5=true