Amazon S3
This document provides instructions for setting up Amazon S3 as a file storage backend for LibreChat.
Amazon S3 is a scalable, secure object storage service that can be used as a file storage backend for LibreChat. Follow these steps to configure your S3 bucket.
1. Create an AWS Account and Configure an IAM User (or Use IRSA)
Option A: Using an IAM User with Explicit Credentials
-
Sign in to AWS:
- Open the AWS Management Console and sign in with your account.
-
Create or Use an Existing IAM User:
- Navigate to the IAM (Identity and Access Management) section.
- Create a new IAM user with Programmatic Access or select an existing one.
- Attach an appropriate policy (for example,
AmazonS3FullAccessor a custom policy with limited S3 permissions). - After creating the user, you will receive an AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY. Store these securely.
Option B: Using IRSA (IAM Roles for Service Accounts) in Kubernetes
If you are deploying LibreChat on Kubernetes (e.g. on EKS), you can use IRSA to assign AWS permissions to your pods without having to provide explicit credentials. To use IRSA:
- Create a Trust Policy for your EKS service account (example below):
- Create a Policy that grants necessary S3 permissions (example below):
- Annotate your Kubernetes ServiceAccount:
Ensure your LibreChat pods use a service account annotated for IRSA. This way, the AWS SDK in your application (using our updated S3 initialization code) will automatically use the temporary credentials provided by IRSA without needing the environment variables for AWS credentials.
2. Create an S3 Bucket
- Open the S3 Console:
- Go to the Amazon S3 console.
- Create a New Bucket:
- Click "Create bucket".
- Bucket Name: Enter a unique name (e.g.,
mylibrechatbucket). - Region: Select the AWS region closest to your users (for example,
us-east-1oreu-west-1). - Configure Options: Set other options as needed, then click "Create bucket".
3. Update Your Environment Variables
If you are not using IRSA, create or update your .env file in your project’s root directory with the following configuration:
- AWS_ACCESS_KEY_ID: Your IAM user's access key.
- AWS_SECRET_ACCESS_KEY: Your IAM user's secret key.
- AWS_REGION: The AWS region where your S3 bucket is located.
- AWS_BUCKET_NAME: The name of the S3 bucket you created.
- AWS_ENDPOINT_URL: (Optional) The custom AWS endpoint URL. Required for S3-compatible services such as MinIO, Cloudflare R2, Hetzner Object Storage, and Backblaze B2.
- AWS_FORCE_PATH_STYLE: (Optional) Set to
truefor providers that require path-style URLs (endpoint/bucket/key) rather than virtual-hosted-style (bucket.endpoint/key). Required for Hetzner Object Storage, MinIO, and similar providers whose SSL certificates don't cover bucket subdomains. Not needed for AWS S3 or Cloudflare R2. Default:false.
If you are using IRSA on Kubernetes, you do not need to set AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY in your environment. The AWS SDK will automatically obtain temporary credentials via the service account assigned to your pod. Ensure that AWS_REGION and AWS_BUCKET_NAME are still provided.
4. Configure LibreChat to Use Amazon S3
Update your LibreChat configuration file (librechat.yaml) to specify that the application should use Amazon S3 for file handling:
S3 presigned URLs expire — images and avatars will break
S3 does not serve files through a CDN. LibreChat accesses S3 files via presigned URLs, which are temporary signed tokens with a configurable expiry (S3_URL_EXPIRY_SECONDS). AWS caps presigned URL lifetime at 7 days for IAM user credentials, and just a few hours when using temporary credentials (STS/IAM roles such as IRSA). Once a URL expires, the image or avatar it references will appear broken in the UI until the page is refreshed and a new URL is generated.
The refresh logic in LibreChat is not applied consistently — for example, the agent list endpoint returns stored (potentially stale) URLs, while the single-agent endpoint refreshes them. This causes visible broken avatar images in the model selector and chat UI. See the related discussion for full context.
S3 is well-suited for document storage (PDFs, text files, code) where short-lived presigned download URLs are appropriate. For images and avatars that need to render persistently across the UI, use Firebase or configure fileStrategies to route only those types to a CDN-backed strategy:
CloudFront (Amazon's CDN for S3, which eliminates presigned URLs entirely) is planned and in active development.
Summary
- Create an AWS Account & IAM User (or configure IRSA):
- For traditional deployments, create an IAM user with programmatic access and obtain your access keys.
- For Kubernetes deployments (e.g., on EKS), set up IRSA so that your pods automatically obtain temporary credentials.
- Create an S3 Bucket:
- Use the Amazon S3 console to create a bucket, choosing a unique name and region.
- Update Environment Variables:
- For non-IRSA: set
AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY,AWS_REGION, andAWS_BUCKET_NAMEin your.envfile. - For IRSA: set only
AWS_REGIONandAWS_BUCKET_NAME; ensure your pod’s service account is correctly annotated.
- Configure LibreChat:
- Set
fileStrategyto"s3"in yourlibrechat.yamlconfiguration file.
With these steps, your LibreChat application will use Amazon S3 to handle file uploads, downloads, and deletions. Additionally, with IRSA support, your application can run securely on Kubernetes without embedding long-term AWS credentials.
Note
Always ensure your AWS credentials remain secure. Do not commit them to a public repository. Adjust IAM policies to follow the principle of least privilege as needed.
How is this guide?