mirror of
https://github.com/documenso/documenso.git
synced 2026-06-22 04:12:06 +10:00
679 lines
19 KiB
Plaintext
679 lines
19 KiB
Plaintext
---
|
|
title: Storage Configuration
|
|
description: Configure file storage for uploaded documents and signed PDFs using database storage (default), S3-compatible object storage, or Azure Blob Storage.
|
|
---
|
|
|
|
import { Accordion, Accordions } from 'fumadocs-ui/components/accordion';
|
|
import { Callout } from 'fumadocs-ui/components/callout';
|
|
import { Step, Steps } from 'fumadocs-ui/components/steps';
|
|
import { Tab, Tabs } from 'fumadocs-ui/components/tabs';
|
|
|
|
## Storage Options
|
|
|
|
| Backend | Best For | Scalability | Configuration |
|
|
| ------------ | --------------------------------------- | ----------- | ------------- |
|
|
| `database` | Small deployments, simplicity | Limited | None required |
|
|
| `s3` | Production, large files, backups | High | Required |
|
|
| `azure-blob` | Production on Azure, native Blob access | High | Required |
|
|
|
|
Select the storage backend with the `NEXT_PUBLIC_UPLOAD_TRANSPORT` environment variable:
|
|
|
|
```bash
|
|
# Database storage (default)
|
|
NEXT_PUBLIC_UPLOAD_TRANSPORT=database
|
|
|
|
# S3-compatible storage
|
|
NEXT_PUBLIC_UPLOAD_TRANSPORT=s3
|
|
|
|
# Azure Blob Storage (native)
|
|
NEXT_PUBLIC_UPLOAD_TRANSPORT=azure-blob
|
|
```
|
|
|
|
---
|
|
|
|
## Database Storage
|
|
|
|
Database storage is the default option and requires no additional configuration. Documents are stored as base64-encoded data directly in PostgreSQL.
|
|
|
|
<Tabs items={['Advantages', 'Limitations']}>
|
|
<Tab value="Advantages">
|
|
|
|
- No external dependencies
|
|
- Simple deployment
|
|
- Automatic backups with database
|
|
|
|
</Tab>
|
|
<Tab value="Limitations">
|
|
|
|
- Increases database size significantly
|
|
- Slower for large files
|
|
- Database backup/restore takes longer
|
|
- Not recommended for files larger than 10MB
|
|
|
|
</Tab>
|
|
</Tabs>
|
|
|
|
### Configuration
|
|
|
|
No configuration required. Database storage is enabled when `NEXT_PUBLIC_UPLOAD_TRANSPORT` is unset or set to `database`.
|
|
|
|
---
|
|
|
|
## S3 Configuration
|
|
|
|
S3 storage is recommended for production deployments. Documenso supports AWS S3 and any S3-compatible storage service.
|
|
|
|
### Required Variables
|
|
|
|
| Variable | Description |
|
|
| --------------------------------------- | --------------------------------- |
|
|
| `NEXT_PUBLIC_UPLOAD_TRANSPORT` | Set to `s3` |
|
|
| `NEXT_PRIVATE_UPLOAD_BUCKET` | S3 bucket name |
|
|
| `NEXT_PRIVATE_UPLOAD_REGION` | AWS region (default: `us-east-1`) |
|
|
| `NEXT_PRIVATE_UPLOAD_ACCESS_KEY_ID` | AWS access key ID |
|
|
| `NEXT_PRIVATE_UPLOAD_SECRET_ACCESS_KEY` | AWS secret access key |
|
|
|
|
### Optional Variables
|
|
|
|
| Variable | Description | Default |
|
|
| -------------------------------------- | --------------------------------------------- | ----------- |
|
|
| `NEXT_PRIVATE_UPLOAD_ENDPOINT` | Custom S3 endpoint for S3-compatible services | |
|
|
| `NEXT_PRIVATE_UPLOAD_FORCE_PATH_STYLE` | Use path-style URLs instead of virtual-hosted | `false` |
|
|
| `NEXT_PRIVATE_UPLOAD_REGION` | S3 region | `us-east-1` |
|
|
|
|
---
|
|
|
|
## AWS S3 Setup
|
|
|
|
{/* prettier-ignore */}
|
|
<Steps>
|
|
<Step>
|
|
### Create an S3 Bucket
|
|
|
|
Create a bucket in the AWS Console or using the CLI:
|
|
|
|
```bash
|
|
aws s3 mb s3://your-documenso-bucket --region us-east-1
|
|
```
|
|
|
|
</Step>
|
|
<Step>
|
|
### Configure Bucket Policy
|
|
|
|
Block public access and configure CORS for presigned URL uploads:
|
|
|
|
**CORS Configuration:**
|
|
|
|
```json
|
|
[
|
|
{
|
|
"AllowedHeaders": ["*"],
|
|
"AllowedMethods": ["GET", "PUT", "POST"],
|
|
"AllowedOrigins": ["https://your-documenso-domain.com"],
|
|
"ExposeHeaders": ["ETag"]
|
|
}
|
|
]
|
|
```
|
|
|
|
Apply via AWS Console (Bucket > Permissions > CORS configuration) or CLI:
|
|
|
|
```bash
|
|
aws s3api put-bucket-cors --bucket your-documenso-bucket --cors-configuration file://cors.json
|
|
```
|
|
|
|
</Step>
|
|
<Step>
|
|
### Create IAM User
|
|
|
|
Create an IAM user with programmatic access and attach this policy:
|
|
|
|
```json
|
|
{
|
|
"Version": "2012-10-17",
|
|
"Statement": [
|
|
{
|
|
"Effect": "Allow",
|
|
"Action": ["s3:PutObject", "s3:GetObject", "s3:DeleteObject"],
|
|
"Resource": "arn:aws:s3:::your-documenso-bucket/*"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
</Step>
|
|
<Step>
|
|
### Configure Environment Variables
|
|
|
|
```bash
|
|
NEXT_PUBLIC_UPLOAD_TRANSPORT=s3
|
|
NEXT_PRIVATE_UPLOAD_BUCKET=your-documenso-bucket
|
|
NEXT_PRIVATE_UPLOAD_REGION=us-east-1
|
|
NEXT_PRIVATE_UPLOAD_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLE
|
|
NEXT_PRIVATE_UPLOAD_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
|
|
```
|
|
|
|
</Step>
|
|
</Steps>
|
|
|
|
---
|
|
|
|
## MinIO Setup
|
|
|
|
MinIO is a self-hosted S3-compatible object storage server.
|
|
|
|
{/* prettier-ignore */}
|
|
<Steps>
|
|
<Step>
|
|
### Deploy MinIO
|
|
|
|
Using Docker:
|
|
|
|
```bash
|
|
docker run -d \
|
|
--name minio \
|
|
-p 9000:9000 \
|
|
-p 9001:9001 \
|
|
-e MINIO_ROOT_USER=minioadmin \
|
|
-e MINIO_ROOT_PASSWORD=minioadmin \
|
|
-v minio_data:/data \
|
|
minio/minio server /data --console-address ":9001"
|
|
```
|
|
|
|
Using Docker Compose with Documenso:
|
|
|
|
```yaml
|
|
services:
|
|
minio:
|
|
image: minio/minio
|
|
command: server /data --console-address ":9001"
|
|
ports:
|
|
- '9000:9000'
|
|
- '9001:9001'
|
|
environment:
|
|
MINIO_ROOT_USER: minioadmin
|
|
MINIO_ROOT_PASSWORD: minioadmin
|
|
volumes:
|
|
- minio_data:/data
|
|
|
|
volumes:
|
|
minio_data:
|
|
```
|
|
|
|
</Step>
|
|
<Step>
|
|
### Create a Bucket
|
|
|
|
Access the MinIO Console at `http://localhost:9001` and create a bucket, or use the CLI:
|
|
|
|
```bash
|
|
# Install MinIO client
|
|
mc alias set myminio http://localhost:9000 minioadmin minioadmin
|
|
|
|
# Create bucket
|
|
mc mb myminio/documenso
|
|
```
|
|
|
|
</Step>
|
|
<Step>
|
|
### Configure Environment Variables
|
|
|
|
```bash
|
|
NEXT_PUBLIC_UPLOAD_TRANSPORT=s3
|
|
NEXT_PRIVATE_UPLOAD_BUCKET=documenso
|
|
NEXT_PRIVATE_UPLOAD_ENDPOINT=http://minio:9000
|
|
NEXT_PRIVATE_UPLOAD_FORCE_PATH_STYLE=true
|
|
NEXT_PRIVATE_UPLOAD_ACCESS_KEY_ID=minioadmin
|
|
NEXT_PRIVATE_UPLOAD_SECRET_ACCESS_KEY=minioadmin
|
|
NEXT_PRIVATE_UPLOAD_REGION=us-east-1
|
|
```
|
|
|
|
</Step>
|
|
</Steps>
|
|
|
|
<Callout type="info">
|
|
Set `NEXT_PRIVATE_UPLOAD_FORCE_PATH_STYLE=true` for MinIO and other S3-compatible services that
|
|
don't support virtual-hosted bucket URLs.
|
|
</Callout>
|
|
|
|
---
|
|
|
|
## Other S3-Compatible Services
|
|
|
|
Documenso works with any S3-compatible storage service. Configure the endpoint and enable path-style URLs if required.
|
|
|
|
### Cloudflare R2
|
|
|
|
```bash
|
|
NEXT_PUBLIC_UPLOAD_TRANSPORT=s3
|
|
NEXT_PRIVATE_UPLOAD_BUCKET=documenso
|
|
NEXT_PRIVATE_UPLOAD_ENDPOINT=https://<account-id>.r2.cloudflarestorage.com
|
|
NEXT_PRIVATE_UPLOAD_ACCESS_KEY_ID=your-r2-access-key
|
|
NEXT_PRIVATE_UPLOAD_SECRET_ACCESS_KEY=your-r2-secret-key
|
|
NEXT_PRIVATE_UPLOAD_REGION=auto
|
|
```
|
|
|
|
### DigitalOcean Spaces
|
|
|
|
```bash
|
|
NEXT_PUBLIC_UPLOAD_TRANSPORT=s3
|
|
NEXT_PRIVATE_UPLOAD_BUCKET=documenso
|
|
NEXT_PRIVATE_UPLOAD_ENDPOINT=https://nyc3.digitaloceanspaces.com
|
|
NEXT_PRIVATE_UPLOAD_ACCESS_KEY_ID=your-spaces-key
|
|
NEXT_PRIVATE_UPLOAD_SECRET_ACCESS_KEY=your-spaces-secret
|
|
NEXT_PRIVATE_UPLOAD_REGION=nyc3
|
|
```
|
|
|
|
### Backblaze B2
|
|
|
|
```bash
|
|
NEXT_PUBLIC_UPLOAD_TRANSPORT=s3
|
|
NEXT_PRIVATE_UPLOAD_BUCKET=documenso
|
|
NEXT_PRIVATE_UPLOAD_ENDPOINT=https://s3.us-west-004.backblazeb2.com
|
|
NEXT_PRIVATE_UPLOAD_ACCESS_KEY_ID=your-b2-key-id
|
|
NEXT_PRIVATE_UPLOAD_SECRET_ACCESS_KEY=your-b2-application-key
|
|
NEXT_PRIVATE_UPLOAD_REGION=us-west-004
|
|
```
|
|
|
|
### Wasabi
|
|
|
|
```bash
|
|
NEXT_PUBLIC_UPLOAD_TRANSPORT=s3
|
|
NEXT_PRIVATE_UPLOAD_BUCKET=documenso
|
|
NEXT_PRIVATE_UPLOAD_ENDPOINT=https://s3.us-east-1.wasabisys.com
|
|
NEXT_PRIVATE_UPLOAD_ACCESS_KEY_ID=your-wasabi-key
|
|
NEXT_PRIVATE_UPLOAD_SECRET_ACCESS_KEY=your-wasabi-secret
|
|
NEXT_PRIVATE_UPLOAD_REGION=us-east-1
|
|
```
|
|
|
|
---
|
|
|
|
## Azure Blob Storage
|
|
|
|
Azure Blob Storage is supported as a native transport (not S3-compatible). Documenso uses the official `@azure/storage-blob` SDK and signs SAS URLs with the Storage Account key for browser uploads and downloads.
|
|
|
|
### Required Variables
|
|
|
|
| Variable | Description |
|
|
| --------------------------------------- | ------------------------------------------------- |
|
|
| `NEXT_PUBLIC_UPLOAD_TRANSPORT` | Set to `azure-blob` |
|
|
| `NEXT_PRIVATE_UPLOAD_AZURE_ACCOUNT_NAME` | Azure Storage Account name |
|
|
| `NEXT_PRIVATE_UPLOAD_AZURE_ACCOUNT_KEY` | Azure Storage Account access key |
|
|
| `NEXT_PRIVATE_UPLOAD_AZURE_CONTAINER` | Container name where uploads are stored |
|
|
|
|
### Optional Variables
|
|
|
|
| Variable | Description | Default |
|
|
| ----------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------- |
|
|
| `NEXT_PRIVATE_UPLOAD_AZURE_ENDPOINT` | Custom Blob endpoint URL. Useful for local development against Azurite (for example `http://127.0.0.1:10000`). | `https://<account>.blob.core.windows.net` |
|
|
|
|
### Azure Setup
|
|
|
|
{/* prettier-ignore */}
|
|
<Steps>
|
|
<Step>
|
|
### Create a Storage Account and Container
|
|
|
|
Create a Storage Account in the Azure Portal or via the Azure CLI, then create a container inside it:
|
|
|
|
```bash
|
|
az storage account create \
|
|
--name yourstorageaccount \
|
|
--resource-group your-rg \
|
|
--location eastus \
|
|
--sku Standard_LRS
|
|
|
|
az storage container create \
|
|
--name documenso-documents \
|
|
--account-name yourstorageaccount
|
|
```
|
|
|
|
</Step>
|
|
<Step>
|
|
### Configure CORS on the container
|
|
|
|
The browser uploads documents directly to Azure Blob using a SAS URL, and downloads them the same way, so the Storage Account needs CORS rules that allow your application origin:
|
|
|
|
```bash
|
|
az storage cors add \
|
|
--services b \
|
|
--methods GET PUT \
|
|
--origins https://your-documenso-domain.com \
|
|
--allowed-headers "Content-Type" "x-ms-blob-type" "Authorization" \
|
|
--exposed-headers "*" \
|
|
--max-age 3600 \
|
|
--account-name yourstorageaccount
|
|
```
|
|
|
|
</Step>
|
|
<Step>
|
|
### Configure Environment Variables
|
|
|
|
```bash
|
|
NEXT_PUBLIC_UPLOAD_TRANSPORT=azure-blob
|
|
NEXT_PRIVATE_UPLOAD_AZURE_ACCOUNT_NAME=yourstorageaccount
|
|
NEXT_PRIVATE_UPLOAD_AZURE_ACCOUNT_KEY=your-account-key
|
|
NEXT_PRIVATE_UPLOAD_AZURE_CONTAINER=documenso-documents
|
|
```
|
|
|
|
</Step>
|
|
</Steps>
|
|
|
|
### Local Development with Azurite
|
|
|
|
Azurite is the official Azure Storage emulator. It supports the Blob REST API with account-key authentication.
|
|
|
|
```bash
|
|
docker run -d --name azurite \
|
|
-p 10000:10000 -p 10001:10001 -p 10002:10002 \
|
|
mcr.microsoft.com/azure-storage/azurite
|
|
```
|
|
|
|
Create the container against the well-known development account:
|
|
|
|
```bash
|
|
az storage container create \
|
|
--name documenso-documents \
|
|
--connection-string "DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint=http://127.0.0.1:10000/devstoreaccount1;"
|
|
```
|
|
|
|
Configure environment variables to point at the emulator:
|
|
|
|
```bash
|
|
NEXT_PUBLIC_UPLOAD_TRANSPORT=azure-blob
|
|
NEXT_PRIVATE_UPLOAD_AZURE_ACCOUNT_NAME=devstoreaccount1
|
|
NEXT_PRIVATE_UPLOAD_AZURE_ACCOUNT_KEY=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==
|
|
NEXT_PRIVATE_UPLOAD_AZURE_CONTAINER=documenso-documents
|
|
NEXT_PRIVATE_UPLOAD_AZURE_ENDPOINT=http://127.0.0.1:10000
|
|
```
|
|
|
|
<Callout type="info">
|
|
The Azurite key shown above is the public well-known development key, published by Microsoft for emulator use. Never reuse it in production.
|
|
</Callout>
|
|
|
|
---
|
|
|
|
## CloudFront CDN (Optional)
|
|
|
|
Use Amazon CloudFront to serve documents with lower latency and reduced S3 costs. CloudFront integration uses signed URLs for secure access.
|
|
|
|
### Prerequisites
|
|
|
|
- An S3 bucket configured for Documenso
|
|
- A CloudFront distribution with the S3 bucket as origin
|
|
- A CloudFront key pair for signing URLs
|
|
|
|
{/* prettier-ignore */}
|
|
<Steps>
|
|
<Step>
|
|
### Create a CloudFront Distribution
|
|
|
|
- Go to CloudFront in the AWS Console
|
|
- Create a distribution with your S3 bucket as the origin
|
|
- Configure Origin Access Control (OAC) to restrict direct S3 access
|
|
- Set the default cache behavior to allow GET requests
|
|
|
|
</Step>
|
|
<Step>
|
|
### Create a Key Pair
|
|
|
|
CloudFront signed URLs require a key pair:
|
|
|
|
- Go to CloudFront > Key management > Public keys
|
|
- Create a new public key
|
|
- Create a key group containing the public key
|
|
- Associate the key group with your distribution
|
|
|
|
Keep the private key secure - you'll need it for the environment variable.
|
|
|
|
</Step>
|
|
<Step>
|
|
### Configure Environment Variables
|
|
|
|
```bash
|
|
# CloudFront distribution domain (without https://)
|
|
NEXT_PRIVATE_UPLOAD_DISTRIBUTION_DOMAIN=d1234567890.cloudfront.net
|
|
|
|
# CloudFront key pair ID
|
|
NEXT_PRIVATE_UPLOAD_DISTRIBUTION_KEY_ID=K1234567890ABC
|
|
|
|
# Private key contents (PEM format)
|
|
NEXT_PRIVATE_UPLOAD_DISTRIBUTION_KEY_CONTENTS="-----BEGIN RSA PRIVATE KEY-----
|
|
MIIEpAIBAAKCAQEA...
|
|
-----END RSA PRIVATE KEY-----"
|
|
```
|
|
|
|
<Callout type="warn">
|
|
Store the private key securely. Use environment variables or secrets management rather than
|
|
committing it to version control.
|
|
</Callout>
|
|
|
|
</Step>
|
|
</Steps>
|
|
|
|
### How It Works
|
|
|
|
When CloudFront is configured:
|
|
|
|
{/* prettier-ignore */}
|
|
<Steps>
|
|
<Step>
|
|
### Uploads
|
|
|
|
File uploads still go directly to S3 via presigned URLs.
|
|
|
|
</Step>
|
|
<Step>
|
|
### Downloads
|
|
|
|
File downloads use CloudFront signed URLs.
|
|
|
|
</Step>
|
|
<Step>
|
|
### Caching
|
|
|
|
CloudFront caches files at edge locations.
|
|
|
|
</Step>
|
|
<Step>
|
|
### Expiration
|
|
|
|
Signed URLs expire after 1 hour.
|
|
|
|
</Step>
|
|
</Steps>
|
|
|
|
---
|
|
|
|
## Migration Between Storage Backends
|
|
|
|
Documenso does not provide automatic migration between storage backends. Each document's storage location is recorded in the database.
|
|
|
|
<Callout type="warn">
|
|
Documents uploaded to one storage backend cannot be automatically migrated to another. Plan your
|
|
storage strategy before deploying to production.
|
|
</Callout>
|
|
|
|
### Manual Migration Process
|
|
|
|
To migrate existing documents from database to S3 storage:
|
|
|
|
{/* prettier-ignore */}
|
|
<Steps>
|
|
<Step>
|
|
### Export documents
|
|
|
|
Extract document blobs from the database (e.g. via a script querying `DocumentData` where `type` is `BYTES_64`).
|
|
|
|
</Step>
|
|
<Step>
|
|
### Upload to S3
|
|
|
|
Upload each exported file to your S3 bucket and note the resulting object keys or paths.
|
|
|
|
</Step>
|
|
<Step>
|
|
### Update DocumentData records
|
|
|
|
Point each record to the new S3 location by updating `DocumentData` with the S3 path and setting `type` to `S3_PATH`.
|
|
|
|
</Step>
|
|
</Steps>
|
|
|
|
This requires custom scripts and database modifications.
|
|
|
|
<Callout type="info">
|
|
For production deployments, we recommend starting with S3 storage from the beginning.
|
|
</Callout>
|
|
|
|
### Hybrid Operation
|
|
|
|
During migration, Documenso can read from both backends. The `DocumentData.type` field indicates where each document is stored.
|
|
|
|
- `BYTES_64`: Stored in database
|
|
- `S3_PATH`: Stored in S3
|
|
|
|
New uploads use the configured `NEXT_PUBLIC_UPLOAD_TRANSPORT` backend.
|
|
|
|
---
|
|
|
|
## Storage Sizing
|
|
|
|
### Database Storage Estimates
|
|
|
|
When using database storage, plan for significant database growth:
|
|
|
|
| Documents/Month | Avg Size | Monthly Growth | Annual Growth |
|
|
| --------------- | -------- | -------------- | ------------- |
|
|
| 100 | 500KB | ~50MB | ~600MB |
|
|
| 1,000 | 500KB | ~500MB | ~6GB |
|
|
| 10,000 | 500KB | ~5GB | ~60GB |
|
|
|
|
Database storage includes base64 encoding overhead (~33% increase).
|
|
|
|
### S3 Storage Estimates
|
|
|
|
S3 stores files without encoding overhead:
|
|
|
|
| Documents/Month | Avg Size | Monthly Growth | Annual Growth |
|
|
| --------------- | -------- | -------------- | ------------- |
|
|
| 100 | 500KB | ~50MB | ~600MB |
|
|
| 1,000 | 500KB | ~500MB | ~6GB |
|
|
| 10,000 | 500KB | ~5GB | ~60GB |
|
|
|
|
### Cost Comparison
|
|
|
|
For high-volume deployments, S3 is more cost-effective:
|
|
|
|
| Aspect | Database Storage | S3 Storage |
|
|
| ------------- | ---------------------------- | ----------------------- |
|
|
| Storage cost | Database pricing (~$0.10/GB) | S3 pricing (~$0.023/GB) |
|
|
| Transfer cost | Database I/O | S3 requests + egress |
|
|
| Backup cost | Larger database backups | Separate S3 backups |
|
|
| Performance | Degrades with size | Consistent |
|
|
|
|
---
|
|
|
|
## Upload Size Limits
|
|
|
|
Configure the maximum upload size displayed to users:
|
|
|
|
```bash
|
|
NEXT_PUBLIC_DOCUMENT_SIZE_UPLOAD_LIMIT=10
|
|
```
|
|
|
|
This value is in megabytes. The default is 5MB.
|
|
|
|
<Callout type="info">
|
|
This environment variable controls the UI display. Actual limits may also be enforced by your
|
|
reverse proxy, web server, or S3 configuration.
|
|
</Callout>
|
|
|
|
Ensure your infrastructure supports the configured limit:
|
|
|
|
<Tabs items={['Nginx', 'S3', 'CloudFront']}>
|
|
<Tab value="Nginx">
|
|
|
|
Set `client_max_body_size` to match or exceed your upload limit.
|
|
|
|
</Tab>
|
|
<Tab value="S3">
|
|
|
|
Default object size limit is 5GB; multipart upload may be required for large files.
|
|
|
|
</Tab>
|
|
<Tab value="CloudFront">
|
|
|
|
Default limit is 50MB per request.
|
|
|
|
</Tab>
|
|
</Tabs>
|
|
|
|
---
|
|
|
|
## Troubleshooting
|
|
|
|
<Accordions type="multiple">
|
|
<Accordion title="Access Denied when uploading">
|
|
Causes:
|
|
- Incorrect IAM credentials
|
|
- Bucket policy doesn't allow required operations
|
|
- CORS not configured for presigned URL uploads
|
|
|
|
Solutions:
|
|
- Verify IAM user has `s3:PutObject` permission
|
|
- Check bucket policy allows writes
|
|
- Configure CORS to allow your domain
|
|
|
|
</Accordion>
|
|
<Accordion title="Invalid endpoint (getaddrinfo ENOTFOUND)">
|
|
Causes:
|
|
- Incorrect region configuration
|
|
- Bucket doesn't exist
|
|
- Network connectivity issues
|
|
|
|
Solutions:
|
|
- Verify the bucket exists in the specified region
|
|
- Check the endpoint URL is correct
|
|
- Verify network access to S3
|
|
|
|
</Accordion>
|
|
<Accordion title="SignatureDoesNotMatch">
|
|
Causes:
|
|
- Incorrect secret access key
|
|
- Clock skew between server and S3
|
|
|
|
Solutions:
|
|
- Verify credentials are correct and not expired
|
|
- Ensure server time is synchronized (use NTP)
|
|
|
|
</Accordion>
|
|
<Accordion title="Path-style access required">
|
|
Set path-style access for S3-compatible services:
|
|
|
|
```bash
|
|
NEXT_PRIVATE_UPLOAD_FORCE_PATH_STYLE=true
|
|
```
|
|
|
|
</Accordion>
|
|
<Accordion title="CloudFront signed URL errors (Missing required key 'Key')">
|
|
Causes:
|
|
- Key pair not configured correctly
|
|
- Private key format invalid
|
|
|
|
Solutions:
|
|
- Verify the key pair ID matches the CloudFront configuration
|
|
- Ensure the private key is in PEM format
|
|
- Check for whitespace or encoding issues in the key contents
|
|
|
|
</Accordion>
|
|
</Accordions>
|
|
|
|
---
|
|
|
|
## See Also
|
|
|
|
- [Database Configuration](/docs/self-hosting/configuration/database) - Configure PostgreSQL
|
|
- [Environment Variables](/docs/self-hosting/configuration/environment) - Complete configuration reference
|
|
- [Backups](/docs/self-hosting/maintenance/backups) - Backup strategies for both storage backends
|
|
- [Docker Compose](/docs/self-hosting/deployment/docker-compose) - Deploy with MinIO for local storage
|