Storage Configuration
Boards stores generated images, videos, audio, and other artifacts in object storage. This guide covers configuring the supported storage providers.
Supported Providers
| Provider | Best For |
|---|---|
| Local | Development, single-server deployments |
| S3 | AWS deployments, S3-compatible services |
| GCS | Google Cloud deployments |
| Supabase | When using Supabase for auth/database |
Configuration File
Create storage_config.yaml:
# Default provider for all operations
default_provider: s3
# Provider configurations
providers:
local:
type: local
base_path: /app/data/storage
public_url_base: http://localhost:8800/storage
s3:
type: s3
bucket: my-boards-bucket
region: us-east-1
gcs:
type: gcs
bucket: my-boards-bucket
project: my-gcp-project
supabase:
type: supabase
bucket: boards-storage
# Optional: File limits
max_file_size: 104857600 # 100MB
Set the config path:
BOARDS_STORAGE_CONFIG_PATH=/app/config/storage_config.yaml
Local Storage
For development and single-server deployments:
providers:
local:
type: local
base_path: /app/data/storage
public_url_base: http://localhost:8800/storage
Mount a volume in Docker:
services:
api:
volumes:
- ./data/storage:/app/data/storage
Local storage doesn't work with multiple API replicas unless using a shared filesystem (NFS, EFS).
Amazon S3
Configuration
providers:
s3:
type: s3
bucket: my-boards-bucket
region: us-east-1
# Optional: custom endpoint for S3-compatible services
# endpoint_url: https://s3.example.com
Environment Variables
AWS_ACCESS_KEY_ID=your-access-key
AWS_SECRET_ACCESS_KEY=your-secret-key
AWS_REGION=us-east-1 # Optional if set in config
S3 Bucket Setup
Create a bucket with appropriate permissions:
aws s3 mb s3://my-boards-bucket --region us-east-1
Bucket policy for public read access to artifacts:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicReadGetObject",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::my-boards-bucket/*"
}
]
}
For private access (signed URLs), no bucket policy is needed.
CORS Configuration
Enable CORS for browser uploads:
[
{
"AllowedHeaders": ["*"],
"AllowedMethods": ["GET", "PUT", "POST"],
"AllowedOrigins": ["https://your-app.com"],
"ExposeHeaders": ["ETag"],
"MaxAgeSeconds": 3600
}
]
IAM Policy
Minimum permissions for the application:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:GetObject",
"s3:DeleteObject",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::my-boards-bucket",
"arn:aws:s3:::my-boards-bucket/*"
]
}
]
}
S3-Compatible Services
Boards works with S3-compatible services. Set the endpoint:
providers:
s3:
type: s3
bucket: my-bucket
region: auto
endpoint_url: https://s3.example.com
Compatible services:
- MinIO
- Cloudflare R2
- DigitalOcean Spaces
- Backblaze B2
- Wasabi
Google Cloud Storage
Configuration
providers:
gcs:
type: gcs
bucket: my-boards-bucket
project: my-gcp-project
Authentication
Set the service account credentials:
GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json
Or in Kubernetes with Workload Identity, the credentials are automatic.
Bucket Setup
gsutil mb -p my-gcp-project -l us-central1 gs://my-boards-bucket
Public Access
For public artifacts:
gsutil iam ch allUsers:objectViewer gs://my-boards-bucket
CORS Configuration
cat > cors.json << EOF
[
{
"origin": ["https://your-app.com"],
"method": ["GET", "PUT", "POST"],
"responseHeader": ["Content-Type"],
"maxAgeSeconds": 3600
}
]
EOF
gsutil cors set cors.json gs://my-boards-bucket
IAM Permissions
Required roles:
roles/storage.objectCreator- Upload filesroles/storage.objectViewer- Read filesroles/storage.objectAdmin- Full access (if deleting files)
Supabase Storage
Configuration
providers:
supabase:
type: supabase
bucket: boards-storage
Environment Variables
SUPABASE_URL=https://your-project.supabase.co
SUPABASE_SERVICE_ROLE_KEY=your-service-role-key
Bucket Setup
Create a bucket in Supabase dashboard:
- Go to Storage > New bucket
- Name:
boards-storage - Public: Enable for public artifacts
Or via SQL:
INSERT INTO storage.buckets (id, name, public)
VALUES ('boards-storage', 'boards-storage', true);
RLS Policies
If using Row Level Security:
-- Allow authenticated uploads
CREATE POLICY "Allow uploads"
ON storage.objects FOR INSERT
TO authenticated
WITH CHECK (bucket_id = 'boards-storage');
-- Allow public reads
CREATE POLICY "Allow public reads"
ON storage.objects FOR SELECT
TO public
USING (bucket_id = 'boards-storage');
Advanced Configuration
Routing Rules
Route different artifact types to different providers:
default_provider: s3
providers:
local:
type: local
base_path: /app/data/cache
public_url_base: http://localhost:8800/cache
s3:
type: s3
bucket: my-boards-bucket
region: us-east-1
routing:
rules:
# Cache small files locally
- match:
max_size: 1048576 # 1MB
provider: local
# Videos always to S3
- match:
artifact_type: video
provider: s3
File Size Limits
max_file_size: 104857600 # 100MB in bytes
Allowed Content Types
allowed_content_types:
- image/jpeg
- image/png
- image/webp
- image/gif
- video/mp4
- video/webm
- audio/mpeg
- audio/wav
- application/json
CDN Integration
For better performance, serve artifacts through a CDN:
CloudFront (S3)
- Create a CloudFront distribution pointing to your S3 bucket
- Update the public URL:
providers:
s3:
type: s3
bucket: my-boards-bucket
region: us-east-1
public_url_base: https://d1234567890.cloudfront.net
Cloud CDN (GCS)
- Create a load balancer with Cloud CDN enabled
- Point to your GCS bucket as backend
- Update the public URL in config
Troubleshooting
Permission Denied
- Verify credentials are set correctly
- Check IAM permissions on the bucket
- Ensure bucket exists and name is correct
CORS Errors
- Configure CORS on the bucket
- Verify allowed origins match your domain
- Check browser console for specific error
Large File Uploads Failing
- Check
max_file_sizeconfiguration - Verify network timeout settings
- Consider multipart upload for very large files
Next Steps
- Docker Deployment - Configure storage volumes
- Kubernetes Deployment - Mount config files
- Configuration Reference - All storage variables