> For the complete documentation index, see [llms.txt](https://docs.p0.dev/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.p0.dev/integrations/resource-integrations/file-transfer.md).

# File Transfer

The File Transfer integration lets you copy a local file to an AWS EC2 instance through a customer-owned S3 bucket, where each file is staged only for the duration of the transfer and then removed. It supports AWS EC2 instances only. P0 grants just-in-time access for each transfer, so every file movement is requested, approved, and audited like any other P0 access request.

{% hint style="warning" %}
File Transfer is in **beta**. The setup and command syntax may change in future releases.
{% endhint %}

{% hint style="info" %}
**p0 file transfer or p0 scp?** Use **File Transfer** to move large files to AWS EC2 instances: it stages the file in S3 with multipart upload and has the instance download it directly, which is faster than [**p0 scp**](/p0-cli/p0-commands-and-usage/p0-scp.md) streaming the bytes over the SSH tunnel. File Transfer only copies files *to* an instance. For small files, quick copies, copying files *from* an instance, or non-AWS instances, use **p0 scp**.
{% endhint %}

This guide has the following sections:

1. [Prerequisites](#prerequisites)
2. [Installation instructions](#installation-instructions)
   * [Option 1: Set up with Terraform](#option-1-set-up-with-terraform)
   * [Option 2: Set up manually](#option-2-set-up-manually)
3. [Configuration reference](#configuration-reference)
4. [Permissions granted](#permissions-granted)
5. [Security](#security)
6. [Transfer your first file](#transfer-your-first-file)

## Prerequisites

Ensure you have the following before you continue:

* An existing P0 account at [p0.app](https://p0.app/).
* The P0 [AWS IAM integration](/integrations/resource-integrations/aws.md) installed for the AWS account that hosts your target instances.
* The P0 [SSH integration](/integrations/resource-integrations/ssh.md) for that account. File Transfer reaches instances over SSH, so the account needs the SSH integration — but you don't need to install it in advance if you [set up with Terraform](#option-1-set-up-with-terraform). See [Does my account need the SSH integration?](#does-my-account-need-the-ssh-integration) for details.
* An S3 bucket to use as the staging area. The bucket must be *in the same AWS account* that hosts your target instances. If you [set up with Terraform](#option-1-set-up-with-terraform), the `terraform-aws-p0-file-transfer` module creates this bucket for you with secure defaults.
* The [P0 CLI](/integrations/resource-integrations/ssh.md#install-the-p0-cli-package) >= v0.27.5 installed on your computer.
* `curl` installed on each destination instance. It's present by default on mainstream EC2 AMIs, such as Amazon Linux, Ubuntu, and RHEL.

## Installation instructions

Set up File Transfer in one of two ways:

* [**Option 1: Set up with Terraform**](#option-1-set-up-with-terraform) — recommended. The `terraform-aws-p0-file-transfer` module provisions and hardens the staging bucket for you.
* [**Option 2: Set up manually**](#option-2-set-up-manually) — register an existing S3 bucket through the P0 dashboard.

### Does my account need the SSH integration?

Yes — File Transfer reaches instances over SSH, so the target AWS account must have the P0 [SSH integration](/integrations/resource-integrations/ssh.md) installed. How you satisfy this requirement depends on your setup path:

* **Terraform:** You don't need SSH installed beforehand. Include the `p0_ssh_aws` resource in your configuration (shown in [Option 1](#option-1-set-up-with-terraform)) to install it in the same `terraform apply`. If SSH is already installed for the account, omit that resource.
* **Manual:** SSH must already be installed for the account. Only AWS accounts with the SSH integration installed appear in the dashboard dropdown. Install the [SSH integration](/integrations/resource-integrations/ssh.md) first if your account is missing.

### Option 1: Set up with Terraform

We recommend installing File Transfer with the [`terraform-aws-p0-file-transfer`](https://registry.terraform.io/modules/p0-security/p0-file-transfer/aws/latest) module (creates the S3 bucket) and the [P0 Terraform provider](https://registry.terraform.io/providers/p0-security/p0/latest/docs/resources/file_transfer) (installs File Transfer in P0). The module provisions the staging S3 bucket with secure defaults so you don't have to create or harden the bucket by hand, and the provider registers it with P0.

1. **Install the Terraform CLI** if you haven't already. See the [Terraform installation guide](https://developer.hashicorp.com/terraform/install).
2. **Generate a P0 API token.** The P0 provider authenticates with an API token that you create in the P0 dashboard — see [Generating an API key](/p0-management/generating-an-api-key.md). Export it so the provider can read it:

```bash
export P0_API_TOKEN=<your-p0-api-token>
```

3. **Configure the providers.** In a new or existing Terraform project, create a configuration file (for example, `main.tf`) that declares the P0 and AWS providers. The `terraform-aws-p0-file-transfer` module provisions AWS resources, so it needs the AWS provider configured with credentials and a region for the account that hosts your instances:

```terraform
terraform {
  required_providers {
    p0 = {
      source  = "p0-security/p0"
      version = ">= 0.43.0"
    }
    aws = {
      source  = "hashicorp/aws"
      version = ">= 5.42.0"
    }
  }
}

provider "p0" {
  org = "your-p0-organization"
}

provider "aws" {
  region = "us-east-1"
}
```

Configure AWS credentials the same way you would for any AWS Terraform project — for example, by setting `AWS_PROFILE` or the standard AWS environment variables. For more provider options, see the [P0 Terraform provider documentation](https://registry.terraform.io/providers/p0-security/p0/latest/docs).

4. **Declare the file transfer module and resources.** Add the following to your configuration. The [`p0_file_transfer`](https://registry.terraform.io/providers/p0-security/p0/latest/docs/resources/file_transfer) resource requires the AWS SSH integration (`p0_ssh_aws`) on the same account. Include the `p0_ssh_aws` resource to install SSH in the same apply, or omit it if SSH is already installed for the account.

```terraform
# Creates the S3 bucket and cloud resources needed for file transfer.
module "file_transfer_bucket" {
  source  = "p0-security/p0-file-transfer/aws"
  version = "0.1.1"
}

# If SSH is not already installed for this AWS account, declare it here first.
# Otherwise, feel free to skip this declaration.
resource "p0_ssh_aws" "example" {
  account_id = module.file_transfer_bucket.account_id
}

# Installs the file transfer integration in your P0 account.
resource "p0_file_transfer" "example" {
  account_id  = module.file_transfer_bucket.account_id
  bucket_name = module.file_transfer_bucket.bucket_name
  depends_on  = [module.file_transfer_bucket]
}
```

| Argument      | Required | Description                                                                                                                                                              |
| ------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `account_id`  | Yes      | The AWS account ID. The SSH integration must be installed for this account — either already installed, or declared with the `p0_ssh_aws` resource earlier in this topic. |
| `bucket_name` | Yes      | The staging S3 bucket, without the `s3://` prefix.                                                                                                                       |

5. **Initialize the working directory.** Run `terraform init` in the project directory. Terraform downloads the P0 and AWS providers and the `terraform-aws-p0-file-transfer` module.

```bash
terraform init
```

6. **Preview the changes.** Run `terraform plan` to review what Terraform creates — the staging S3 bucket, the SSH integration (if you declared `p0_ssh_aws`), and the File Transfer integration.

```bash
terraform plan
```

7. **Apply the configuration.** Run `terraform apply`. Terraform shows the plan and prompts for confirmation — enter `yes` to proceed.

```bash
terraform apply
```

After Terraform applies, File Transfer is ready to use.

{% hint style="info" %}
For further documentation on what the Terraform module does, visit the [Terraform Registry](https://registry.terraform.io/modules/p0-security/p0-file-transfer/aws/latest).
{% endhint %}

#### What Terraform provisions

When you apply this configuration, the `terraform-aws-p0-file-transfer` module creates the staging S3 bucket with the following settings:

| Setting                           | Value                                                                                                                            |
| --------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
| Bucket name                       | `p0-transfers-<account_id>`, derived automatically from the AWS account ID.                                                      |
| Lifecycle — `uploads/` expiration | Objects under the `uploads/` prefix delete automatically after 1 day.                                                            |
| Lifecycle — incomplete uploads    | Incomplete multipart uploads abort after 1 day.                                                                                  |
| Versioning                        | Disabled.                                                                                                                        |
| Public access                     | Fully blocked — `block_public_acls`, `block_public_policy`, `ignore_public_acls`, and `restrict_public_buckets` are all enabled. |
| Bucket policy                     | Denies all S3 operations over non-HTTPS connections (`DenyInsecureTransport`).                                                   |
| Encryption                        | AES256 (SSE-S3), with S3 Bucket Keys enabled.                                                                                    |
| Object ownership                  | `BucketOwnerEnforced` (ACLs disabled).                                                                                           |

The `uploads/` lifecycle rule is a safety net: P0 deletes each file after a successful transfer, and the rule clears anything left behind by an interrupted transfer.

### Option 2: Set up manually

{% hint style="warning" %}
The dashboard flow registers an existing S3 bucket with P0 — it doesn't create the bucket. Create the staging bucket first. **We strongly recommend the** [**`terraform-aws-p0-file-transfer`**](https://registry.terraform.io/modules/p0-security/p0-file-transfer/aws/latest) **module**, which provisions the bucket with the correct hardened settings automatically. Creating the bucket manually is possible but error-prone: you must replicate every setting the module applies yourself (see [What Terraform provisions](#what-terraform-provisions)).
{% endhint %}

1. Go to [p0.app](https://p0.app/) in your browser. Select **Integrations**, then under the **Resources** section, select **File transfer**.
2. From the list of **Available components**, select **File transfer access control**.
3. Select **+ Add account**.
4. From the **Account identifier** dropdown, select the AWS account that hosts your target instances, then select **Next**.

{% hint style="info" %}
Only AWS accounts with the SSH integration installed appear in the **Account identifier** dropdown. If your account is missing, install the [SSH integration](/integrations/resource-integrations/ssh.md) first.
{% endhint %}

5. In the **S3 bucket name** field, enter the name of your customer-owned bucket, without the `s3://` prefix. Use a valid S3 DNS-style name: 3–63 characters, lowercase letters, numbers, dots, and hyphens. The bucket must be *in the AWS account you selected in the previous step*.

   The bucket name is the only detail you enter.

{% hint style="warning" %}
If P0 can't find the bucket in the selected account, the install fails with a validation error. Confirm the bucket name and that the bucket lives in the account you selected, then try again.
{% endhint %}

6. Select **Finish** to complete the setup. The account now appears on the **File transfer access control** page.

{% hint style="success" %}
You're now set up with File Transfer for P0 on AWS.
{% endhint %}

## Configuration reference

| Field        | Required | Description                                                                                                    | Example              |
| ------------ | -------- | -------------------------------------------------------------------------------------------------------------- | -------------------- |
| `bucketName` | Yes      | Customer-owned S3 bucket for staging transfers, without the `s3://` prefix. Must be a valid S3 DNS-style name. | `my-transfer-bucket` |

`bucketName` is the only value you provide. When you install File Transfer, P0 verifies that the bucket exists in the selected AWS account and reads its region and AWS partition directly from AWS.

P0 grants each transfer temporary read and write access scoped to your own prefix in this bucket. P0 never requires standing access to the bucket's full contents.

## Permissions granted

When a File Transfer request is approved, P0 grants two scoped, temporary permissions:

* **SSH access to the destination instance**, through the [P0 SSH integration](/integrations/resource-integrations/ssh.md) — the same access as `p0 ssh`.
* **S3 read/write access**, through the [P0 AWS integration](/integrations/resource-integrations/aws.md). P0 grants the [`AmazonS3ReadWriteAccess`](/integrations/resource-integrations/aws/requesting-access/permission-levels.md#amazons3readwriteaccess) permission on the staging bucket, scoped to your own `uploads/<your-user-key>/` prefix.

## Security

File Transfer grants the least access necessary, for the shortest time, inside your own AWS account:

* **Just-in-time and audited.** Each transfer is a P0 access request — requested, approved, and logged like any other access. There's no standing access to the bucket.
* **File Transfer implies SSH access.** A transfer downloads the file by running a command on the destination over SSH, so it grants the same access as `p0 ssh` to that instance. Approve requests with that in mind.
* **Least privilege and short-lived.** P0 grants temporary credentials scoped to your own prefix in the bucket, and both the credentials and the download URL expire automatically.
* **Your bucket, cleaned up automatically.** The staging bucket lives in your AWS account and is hardened with secure defaults. P0 removes each uploaded file after the transfer completes — see [What Terraform provisions](#what-terraform-provisions) for the bucket's security settings.

## Transfer your first file

With setup complete, use the `p0 file-transfer` CLI command to copy a local file to an instance. Pass the local file path and the destination instance ID or name:

```bash
p0 file-transfer ./config.yaml i-1234567890abcdef0 --reason "Deploy updated config"
```

P0 requests just-in-time access, uploads the file, and downloads it to your home directory on the instance.

For the full command reference, options, and troubleshooting, see [Transfer a file to an instance](/integrations/resource-integrations/file-transfer/transferring-files.md).
