Files
openaccounting-server/STORAGE.md
Aaron Guise 6558a09258 deps: update vendor dependencies for S3-compatible storage
Updates AWS SDK and removes Blazer B2 dependency in favor of unified
S3-compatible approach. Includes configuration examples and documentation.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-01 23:07:58 +12:00

5.3 KiB

Modular Storage System

The OpenAccounting server now supports multiple storage backends for file attachments. This allows you to choose between local filesystem storage for simple deployments or cloud storage for production/multi-user environments.

Supported Storage Backends

1. Local Filesystem Storage

Perfect for self-hosted deployments or development environments.

Configuration:

{
  "storage": {
    "backend": "local",
    "local": {
      "root_dir": "./uploads",
      "base_url": "https://yourapp.com/files"
    }
  }
}

Environment Variables:

OA_STORAGE_BACKEND=local
OA_STORAGE_LOCAL_ROOT_DIR=./uploads
OA_STORAGE_LOCAL_BASE_URL=https://yourapp.com/files

2. Amazon S3 Storage

Reliable cloud storage for production deployments.

Configuration:

{
  "storage": {
    "backend": "s3",
    "s3": {
      "region": "us-east-1",
      "bucket": "my-openaccounting-attachments",
      "prefix": "attachments",
      "access_key_id": "AKIA...",
      "secret_access_key": "...",
      "endpoint": "",
      "path_style": false
    }
  }
}

Environment Variables:

OA_STORAGE_BACKEND=s3
OA_STORAGE_S3_REGION=us-east-1
OA_STORAGE_S3_BUCKET=my-openaccounting-attachments
OA_STORAGE_S3_PREFIX=attachments
OA_STORAGE_S3_ACCESS_KEY_ID=AKIA...
OA_STORAGE_S3_SECRET_ACCESS_KEY=...

Features:

  • Automatic presigned URL generation
  • Configurable expiry times
  • Support for S3-compatible services (MinIO, DigitalOcean Spaces)
  • IAM role support (leave credentials empty to use IAM)

3. Backblaze B2 Storage

Cost-effective cloud storage alternative to S3.

Configuration:

{
  "storage": {
    "backend": "b2",
    "b2": {
      "account_id": "your-b2-account-id",
      "application_key": "your-b2-application-key",
      "bucket": "my-openaccounting-attachments", 
      "prefix": "attachments"
    }
  }
}

Environment Variables:

OA_STORAGE_BACKEND=b2
OA_STORAGE_B2_ACCOUNT_ID=your-b2-account-id
OA_STORAGE_B2_APPLICATION_KEY=your-b2-application-key
OA_STORAGE_B2_BUCKET=my-openaccounting-attachments
OA_STORAGE_B2_PREFIX=attachments

API Endpoints

The storage system provides both legacy and new endpoints:

New Storage-Agnostic Endpoints

Upload Attachment:

POST /api/v1/attachments
Content-Type: multipart/form-data

transactionId: uuid
description: string (optional)
file: binary data

Get Attachment Metadata:

GET /api/v1/attachments/{id}

Get Download URL:

GET /api/v1/attachments/{id}/url

Download File:

GET /api/v1/attachments/{id}?download=true

Delete Attachment:

DELETE /api/v1/attachments/{id}

Legacy Endpoints (Still Supported)

The original transaction-scoped endpoints remain available for backward compatibility:

  • GET/POST /api/v1/orgs/{orgId}/transactions/{transactionId}/attachments

Security Features

  • File type validation - Only allowed MIME types are accepted
  • File size limits - Configurable maximum file size (default 10MB)
  • Path traversal protection - Prevents directory traversal attacks
  • Access control - Files are linked to users and organizations
  • Presigned URLs - Time-limited access for cloud storage

File Organization

Files are automatically organized by date:

uploads/
├── 2025/
│   ├── 01/
│   │   ├── 15/
│   │   │   ├── uuid1.pdf
│   │   │   └── uuid2.png
│   │   └── 16/
│   │       └── uuid3.jpg

Configuration Examples

Development (Local Storage)

{
  "storage": {
    "backend": "local",
    "local": {
      "root_dir": "./dev-uploads"
    }
  }
}

Production (S3 with IAM)

{
  "storage": {
    "backend": "s3", 
    "s3": {
      "region": "us-west-2",
      "bucket": "prod-openaccounting-files",
      "prefix": "attachments"
    }
  }
}

Cost-Optimized (Backblaze B2)

{
  "storage": {
    "backend": "b2",
    "b2": {
      "account_id": "${B2_ACCOUNT_ID}",
      "application_key": "${B2_APP_KEY}",
      "bucket": "openaccounting-prod"
    }
  }
}

Migration Between Storage Backends

When changing storage backends, existing attachments will remain in the old storage location. The database records contain the storage path, so files can be accessed until migrated.

To migrate:

  1. Update configuration to new backend
  2. Restart server
  3. New uploads will use the new backend
  4. Optional: Run migration script to move existing files

Environment-Specific Considerations

Self-Hosted

  • Use local storage for simplicity
  • Ensure backup strategy includes upload directory
  • Consider disk space management

Cloud Deployment

  • Use S3 or B2 for reliability and scalability
  • Configure proper IAM policies
  • Enable versioning and lifecycle policies

Multi-Region

  • Use cloud storage with appropriate region selection
  • Consider CDN integration for better performance

Troubleshooting

Storage backend not initialized:

  • Check configuration syntax
  • Verify credentials for cloud backends
  • Ensure storage directories/buckets exist

Permission denied:

  • Check file system permissions for local storage
  • Verify IAM policies for S3
  • Confirm B2 application key permissions

Large file uploads failing:

  • Check MaxFileSize configuration
  • Verify network timeouts
  • Consider multipart upload for large files