# S3 Files, enabling S3 buckets as file systems **Published by:** [jackk](https://paragraph.com/@jackkdev/) **Published on:** 2026-04-27 **URL:** https://paragraph.com/@jackkdev/s3-files ## Content AWS has introduced S3 Files, which allows you to access S3 buckets as a filesystem across compute services such as EC2, Lambda, ECS and EKS. Previously, working with S3 followed a download-process-upload pattern:Download objects from S3 to local storageProcess themUpload the results back to S3 With S3 Files, this pattern is no longer necessary. Applications can interact with S3 objects as if they were a local filesystem, making S3 behave like a "shared drive" across your compute environments. Use CasesAI Agents AI agents often need to read and write data across multiple steps. With S3 Files, they can work directly on S3 as a filesystem, making it easier to share state and coordinate without extra syncing.ML pipelines ML workflows such as preprocessing, feature engineering, and model training work primarily with files. Every run typically involves pulling data from S3, processing it locally, and writing the results back. With S3 files, data can be accessed and modified in place, removing the unnecessary data movement.TemplatesThis section provides CloudFormation templates for S3 FilesSystem and its integration with Lambda, ECS task, and EC2.The following values used in the examples are arbitrary and can be adjusted as needed.UID, GID (non-root Linux user)Access point root pathMount path S3 FilesSystemAWSTemplateFormatVersion: "2010-09-09" Description: S3 Files Parameters: S3BucketName: Type: String VpcId: Type: AWS::EC2::VPC::Id SubnetId: Type: AWS::EC2::Subnet::Id Ec2AmiId: Type: AWS::SSM::Parameter::Value Default: "/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2" Resources: S3Bucket: Type: AWS::S3::Bucket Properties: BucketName: !Ref S3BucketName VersioningConfiguration: Status: Enabled S3FilesSystem: Type: AWS::S3Files::FileSystem Properties: Bucket: !GetAtt S3Bucket.Arn RoleArn: !GetAtt S3FilesSystemRole.Arn # For production use, consider creating mount targets in multiple AZs for high availability. S3FilesMountTarget: Type: AWS::S3Files::MountTarget Properties: FileSystemId: !Ref S3FilesSystem SubnetId: !Ref SubnetId SecurityGroups: - !Ref S3FilesSecurityGroup S3FilesSecurityGroup: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: !Sub "${AWS::StackName}-s3-files-sg" VpcId: !Ref VpcId S3FilesSystemRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Principal: Service: elasticfilesystem.amazonaws.com Action: sts:AssumeRole Policies: - PolicyName: !Sub "${AWS::StackName}-s3-files" PolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Action: - s3:ListBucket - s3:ListBucketVersions Resource: - !Sub "arn:aws:s3:::${S3Bucket}" Condition: StringEquals: aws:ResourceAccount: !Ref AWS::AccountId - Effect: Allow Action: - s3:AbortMultipartUpload - s3:DeleteObject* - s3:GetObject* - s3:List* - s3:PutObject* Resource: - !Sub "arn:aws:s3:::${S3Bucket}/*" Condition: StringEquals: aws:ResourceAccount: !Ref AWS::AccountId - Effect: Allow Action: - kms:GenerateDataKey - kms:Encrypt - kms:Decrypt - kms:ReEncryptFrom - kms:ReEncryptTo Resource: - !Sub "arn:aws:kms:${AWS::Region}:${AWS::AccountId}:*" Condition: StringLike: kms:ViaService: !Sub "s3.${AWS::Region}.amazonaws.com" "kms:EncryptionContext:aws:s3:arn": - !Sub "arn:aws:s3:::${S3Bucket}" - !Sub "arn:aws:s3:::${S3Bucket}/*" - Effect: Allow Action: - events:DeleteRule - events:DisableRule - events:EnableRule - events:PutRule - events:PutTargets - events:RemoveTargets Resource: - !Sub "arn:aws:events:${AWS::Region}:${AWS::AccountId}:rule/DO-NOT-DELETE-S3-Files*" Condition: StringEquals: events:ManagedBy: elasticfilesystem.amazonaws.com - Effect: Allow Action: - events:DescribeRule - events:ListRuleNamesByTarget - events:ListRules - events:ListTargetsByRule Resource: - !Sub "arn:aws:events:${AWS::Region}:${AWS::AccountId}:rule/*"Enable S3 bucket versioning.The mount target for S3 Files must to be within the same VPC as your compute services. Lambda # ===== Lambda ===== S3FilesAccessPointLambda: Type: AWS::S3Files::AccessPoint Properties: FileSystemId: !Ref S3FilesSystem PosixUser: Gid: 1000 Uid: 1000 RootDirectory: Path: "/lambda" # Allow User ID 1000 to read/write/execute in the root directory CreationPermissions: OwnerGid: 1000 OwnerUid: 1000 Permissions: "755" S3FilesSecurityGroupIngressLambda: Type: AWS::EC2::SecurityGroupIngress Properties: GroupId: !Ref S3FilesSecurityGroup IpProtocol: tcp FromPort: 2049 ToPort: 2049 SourceSecurityGroupId: !Ref LambdaSecurityGroup LambdaSecurityGroup: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: !Sub "${AWS::StackName}-lambda-sg" VpcId: !Ref VpcId # S3 File System uses NFS (port 2049) over the VPC SecurityGroupEgress: - IpProtocol: tcp FromPort: 2049 ToPort: 2049 DestinationSecurityGroupId: !Ref S3FilesSecurityGroup # NOTE: Ensure the S3 VPC Endpoint or NAT Gateway is configured to allow access between VPC and S3 Lambda: Type: AWS::Lambda::Function DependsOn: S3FilesMountTarget Properties: FunctionName: s3-files-demo Role: !GetAtt LambdaExecutionRole.Arn Handler: index.lambda_handler Runtime: python3.14 MemorySize: 512 Timeout: 30 Code: ZipFile: | import os import json import time MOUNT_PATH = "/mnt/lambda" def lambda_handler(event, context): timestamp = int(time.time()) filename = f"demo-{timestamp}.txt" filepath = os.path.join(MOUNT_PATH, filename) content = f"Hello from Lambda! Written at {timestamp}" with open(filepath, "w") as f: f.write(content) files = os.listdir(MOUNT_PATH) return { "statusCode": 200, "body": json.dumps({"files_in_mount": files[:20]}), } VpcConfig: SecurityGroupIds: - !Ref LambdaSecurityGroup SubnetIds: - !Ref SubnetId # Mount the S3 Files System at /mnt/lambda FileSystemConfigs: - Arn: !GetAtt S3FilesAccessPointLambda.AccessPointArn LocalMountPath: /mnt/lambda LambdaExecutionRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Principal: Service: lambda.amazonaws.com Action: sts:AssumeRole ManagedPolicyArns: - arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole - arn:aws:iam::aws:policy/AmazonS3FilesClientReadWriteAccess Policies: - PolicyName: !Sub "${AWS::StackName}-LambdaS3FilesAccess" PolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Action: - s3:GetObject - s3:GetObjectVersion Resource: !Sub "arn:aws:s3:::${S3Bucket}/*"CreationPermissions for S3Files AccessPoint should be set to enable the user (UID 1000) to create S3 prefix (/lambda), as well as perform read and write operations on S3 objects under that prefix.FileSystemConfigs for Lambda must be configured and the LocalMountPath defines where it is accessible within the Lambda function.Inbound traffic from Lambda for S3 Files Mount Target's security group.Outbound traffic to S3 Files Mount Target for Lambda's security group. ECS Task # ===== ECS Task ===== S3FilesAccessPointEcs: Type: AWS::S3Files::AccessPoint Properties: FileSystemId: !Ref S3FilesSystem PosixUser: Gid: 1001 Uid: 1001 RootDirectory: Path: "/ecs" # Allow User ID 1001 to read/write/execute in the root directory CreationPermissions: OwnerGid: 1001 OwnerUid: 1001 Permissions: "755" S3FilesSecurityGroupIngressECS: Type: AWS::EC2::SecurityGroupIngress Properties: GroupId: !Ref S3FilesSecurityGroup IpProtocol: tcp FromPort: 2049 ToPort: 2049 SourceSecurityGroupId: !Ref EcsTaskSecurityGroup EcsTaskSecurityGroup: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: !Sub "${AWS::StackName}-ecs-task-sg" VpcId: !Ref VpcId SecurityGroupEgress: - IpProtocol: tcp FromPort: 443 ToPort: 443 CidrIp: 0.0.0.0/0 Description: ECR image pull and CloudWatch Logs via NAT Gateway - IpProtocol: tcp FromPort: 2049 ToPort: 2049 DestinationSecurityGroupId: !Ref S3FilesSecurityGroup Description: S3 Files mount target EcrRepository: Type: AWS::ECR::Repository Properties: RepositoryName: !Sub "${AWS::StackName}" # NOTE: Ensure the S3 VPC Endpoint or NAT Gateway is configured to allow access between VPC and S3 # NOTE: Ensure the ECR VPC endpoint or NAT Gateway is configured to allow access for image pulls from ECR EcsCluster: Type: AWS::ECS::Cluster Properties: ClusterName: !Sub "${AWS::StackName}-cluster" EcsLogGroup: Type: AWS::Logs::LogGroup Properties: LogGroupName: !Sub "/ecs/${AWS::StackName}" RetentionInDays: 7 EcsTaskExecutionRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Principal: Service: ecs-tasks.amazonaws.com Action: sts:AssumeRole ManagedPolicyArns: - arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy EcsTaskRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Principal: Service: ecs-tasks.amazonaws.com Action: sts:AssumeRole ManagedPolicyArns: - arn:aws:iam::aws:policy/AmazonS3FilesClientReadWriteAccess Policies: - PolicyName: !Sub "${AWS::StackName}-ECSTaskS3Access" PolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Action: - s3:GetObject - s3:GetObjectVersion Resource: !Sub "arn:aws:s3:::${S3Bucket}/*" EcsTaskDefinition: Type: AWS::ECS::TaskDefinition DependsOn: S3FilesMountTarget Properties: Family: !Sub "${AWS::StackName}-s3-files" RequiresCompatibilities: - FARGATE NetworkMode: awsvpc Cpu: "256" Memory: "512" ExecutionRoleArn: !GetAtt EcsTaskExecutionRole.Arn TaskRoleArn: !GetAtt EcsTaskRole.Arn Volumes: - Name: s3-files S3FilesVolumeConfiguration: FileSystemArn: !GetAtt S3FilesSystem.FileSystemArn AccessPointArn: !GetAtt S3FilesAccessPointEcs.AccessPointArn ContainerDefinitions: - Name: !Sub "${AWS::StackName}-s3-files" Image: !Sub "${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/${EcrRepository}:latest" Essential: true User: "1001:1001" MountPoints: - SourceVolume: s3-files ContainerPath: /mnt/ecs ReadOnly: false LogConfiguration: LogDriver: awslogs Options: awslogs-group: !Ref EcsLogGroup awslogs-region: !Ref AWS::Region awslogs-stream-prefix: ecs EcsService: Type: AWS::ECS::Service DependsOn: S3FilesMountTarget Properties: Cluster: !Ref EcsCluster TaskDefinition: !Ref EcsTaskDefinition LaunchType: FARGATE DesiredCount: 1 NetworkConfiguration: AwsvpcConfiguration: Subnets: - !Ref SubnetId SecurityGroups: - !Ref EcsTaskSecurityGroup# ===== Example in ECS task ===== import json import os import time MOUNT_PATH = "/mnt/ecs" def main(): timestamp = int(time.time()) filename = f"demo-{timestamp}.txt" filepath = os.path.join(MOUNT_PATH, filename) content = f"Hello from ECS! Written at {timestamp}" with open(filepath, "w") as f: f.write(content) files = os.listdir(MOUNT_PATH) print(json.dumps({"files_in_mount": files[:20]})) if __name__ == "__main__": main()CreationPermissions for S3Files AccessPoint should be set to enable the user (UID 1001) to create S3 prefix (/ecs), as well as perform read and write operations on S3 objects under that prefix.MountPoints in ContainerDefinitions must be configured and the ContainerPath specifies where S3 Files is mounted inside the container.Inbound traffic from ECS Task for S3 Files Mount Target's security group.Outbound traffic to S3 Files Mount Target for ECS Task's security group. EC2 # ===== EC2 ===== S3FilesAccessPointEc2: Type: AWS::S3Files::AccessPoint Properties: FileSystemId: !Ref S3FilesSystem PosixUser: Gid: 1002 Uid: 1002 RootDirectory: Path: "/ec2" CreationPermissions: OwnerGid: 1002 OwnerUid: 1002 Permissions: "755" S3FilesSecurityGroupIngressEc2: Type: AWS::EC2::SecurityGroupIngress Properties: GroupId: !Ref S3FilesSecurityGroup IpProtocol: tcp FromPort: 2049 ToPort: 2049 SourceSecurityGroupId: !Ref Ec2SecurityGroup Ec2SecurityGroup: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: !Sub "${AWS::StackName}-ec2-sg" VpcId: !Ref VpcId SecurityGroupEgress: - IpProtocol: tcp FromPort: 2049 ToPort: 2049 DestinationSecurityGroupId: !Ref S3FilesSecurityGroup - IpProtocol: tcp FromPort: 443 ToPort: 443 CidrIp: 0.0.0.0/0 Description: SSM and S3 via NAT Gateway Ec2InstanceRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Principal: Service: ec2.amazonaws.com Action: sts:AssumeRole ManagedPolicyArns: - arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore - arn:aws:iam::aws:policy/AmazonS3FilesClientReadWriteAccess Policies: - PolicyName: !Sub "${AWS::StackName}-Ec2S3Access" PolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Action: - s3:GetObject - s3:GetObjectVersion Resource: !Sub "arn:aws:s3:::${S3Bucket}/*" Ec2InstanceProfile: Type: AWS::IAM::InstanceProfile Properties: Roles: - !Ref Ec2InstanceRole # NOTE: Ensure the S3 VPC Endpoint or NAT Gateway is configured to allow access between VPC and S3 Ec2Instance: Type: AWS::EC2::Instance DependsOn: S3FilesMountTarget Properties: ImageId: !Ref Ec2AmiId InstanceType: t3.micro SubnetId: !Ref SubnetId IamInstanceProfile: !Ref Ec2InstanceProfile SecurityGroupIds: - !Ref Ec2SecurityGroup UserData: Fn::Base64: !Sub | #!/bin/bash set -e # Mount S3 Files access point sudo yum install -y amazon-efs-utils sudo mkdir -p /mnt/ec2 sudo mount -t s3files -o accesspoint=${S3FilesAccessPointEc2.AccessPointId} ${SC3FilesSystem.FileSystemId} /mnt/ec2 # Test writing a file (to be deleted) TIMESTAMP=$(date +%s) FILE="/mnt/ec2/demo-$TIMESTAMP.txt" echo "Hello from EC2! Written at $TIMESTAMP" > "$FILE"CreationPermissions for S3Files AccessPoint should be set to enable the user (UID 1002) to create S3 prefix (/ec2), as well as perform read and write operations on S3 objects under that prefix.Command to mount S3 Files using an access point.Inbound traffic from EC2 for S3 Files Mount Target's security group.Outbound traffic to S3 Files Mount Target for EC2's security group. ## Publication Information - [jackk](https://paragraph.com/@jackkdev/): Publication homepage - [All Posts](https://paragraph.com/@jackkdev/): More posts from this publication - [RSS Feed](https://api.paragraph.com/blogs/rss/@jackkdev): Subscribe to updates