We use tracking cookies to understand how you use the product and help us improve it. For more information on how we store cookies, read our  privacy policy.

Setup & Configuration

Configure AWS S3 credentials and create your storage bucket.

To use AWS S3 for file storage, you need to configure environment variables validated by @t3-oss/env-nextjs. The S3 client in lib/amazon/s3.ts handles all file operations.

Required Environment Variables

Plainform requires five S3-related environment variables:

.env
AWS_ACCESS_KEY_ID="your-access-key-id"
AWS_SECRET_ACCESS_KEY="your-secret-access-key"
AWS_S3_ENDPOINT="https://your-bucket.s3.region.amazonaws.com"
AWS_S3_REGION="us-east-1"
AWS_S3_BUCKET="your-bucket-name"

These are validated in env.ts:

env.ts
export const env = createEnv({
  server: {
    AWS_ACCESS_KEY_ID: z.string().min(5),
    AWS_SECRET_ACCESS_KEY: z.string().min(5),
    AWS_S3_ENDPOINT: z.string().min(5),
    AWS_S3_REGION: z.string().min(5),
    AWS_S3_BUCKET: z.string().min(5),
    // ... other variables
  },
});

Setup Steps

Create AWS Account

Sign up at AWS and log in to the AWS Management Console.

Create S3 Bucket

  1. Navigate to S3 in the AWS Console
  2. Click Create bucket
  3. Enter bucket name (e.g., myapp-storage)
  4. Choose region (e.g., us-east-1)
  5. Configure permissions:
    • Block all public access: Uncheck if you need public URLs
    • Bucket policy: Add policy for public read access (optional)

Example bucket policy for public read:

Bucket Policy
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "PublicReadGetObject",
      "Effect": "Allow",
      "Principal": "*",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::your-bucket-name/*"
    }
  ]
}

Create IAM User

  1. Go to IAMUsers in AWS Console
  2. Click Create user
  3. Enter username (e.g., s3-upload-user)
  4. Attach policy: AmazonS3FullAccess (or create custom policy)

Custom policy for specific bucket:

IAM Policy
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:PutObject",
        "s3:GetObject",
        "s3:DeleteObject",
        "s3:ListBucket"
      ],
      "Resource": [
        "arn:aws:s3:::your-bucket-name",
        "arn:aws:s3:::your-bucket-name/*"
      ]
    }
  ]
}

Generate Access Keys

  1. Select your IAM user
  2. Go to Security credentials tab
  3. Click Create access key
  4. Choose Application running outside AWS
  5. Copy Access Key ID and Secret Access Key

Save the secret access key immediately - you can't retrieve it later.

Add to Environment Variables

Update your .env file:

.env
AWS_ACCESS_KEY_ID="AKIAIOSFODNN7EXAMPLE"
AWS_SECRET_ACCESS_KEY="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
AWS_S3_ENDPOINT="https://myapp-storage.s3.us-east-1.amazonaws.com"
AWS_S3_REGION="us-east-1"
AWS_S3_BUCKET="myapp-storage"

Never commit .env to version control. It's already in .gitignore.

Verify Configuration

Start your development server:

Terminal
npm run dev

If environment variables are missing or invalid, @t3-oss/env-nextjs will throw a validation error and prevent the app from starting.

S3 Client Configuration

The S3 client is pre-configured in lib/amazon/s3.ts:

lib/amazon/s3.ts
import { S3Client } from '@aws-sdk/client-s3';
import { env } from '@/env';

export const s3 = new S3Client({
  region: env.AWS_S3_REGION,
  credentials: {
    accessKeyId: env.AWS_ACCESS_KEY_ID,
    secretAccessKey: env.AWS_SECRET_ACCESS_KEY,
  },
});

No additional configuration needed - the client is ready to use.

CORS Configuration (Optional)

If uploading files from the browser, configure CORS on your S3 bucket:

  1. Go to your bucket in AWS Console
  2. Navigate to PermissionsCORS
  3. Add CORS configuration:
CORS Configuration
[
  {
    "AllowedHeaders": ["*"],
    "AllowedMethods": ["GET", "PUT", "POST", "DELETE"],
    "AllowedOrigins": ["http://localhost:3000", "https://yourdomain.com"],
    "ExposeHeaders": ["ETag"]
  }
]

Security Best Practices

  • Use IAM roles in production instead of access keys (for EC2, Lambda, etc.)
  • Rotate access keys regularly (every 90 days recommended)
  • Limit permissions to only what's needed (principle of least privilege)
  • Enable bucket versioning to protect against accidental deletions
  • Use signed URLs for temporary access instead of public buckets
  • Monitor access with AWS CloudTrail and S3 access logs

Next Steps

How is this guide ?

Last updated on