# CloudStorage

[![Commercial](https://img.shields.io/badge/License-Commercial-red.svg)](LICENSE.md)
[![Cockpit CMS](https://img.shields.io/badge/Cockpit%20CMS-Addon-blue.svg)](https://getcockpit.com)
[![Cloud Storage](https://img.shields.io/badge/Storage-AWS%20S3%20%7C%20Azure%20Blob-green.svg)](#supported-providers)

> **Seamless cloud storage integration for Cockpit CMS**

CloudStorage is a commercial addon that extends Cockpit CMS's file storage capabilities to support major cloud storage providers. Store your uploaded files, assets, and media directly in AWS S3 or Azure Blob Storage with automatic URL generation and CDN compatibility.

## ✨ Features

### ☁️ **Cloud Storage Providers**
- **AWS S3**: Full S3 API compatibility with custom endpoint support
- **Azure Blob Storage**: Complete Azure Blob integration with container management
- **S3-Compatible Services**: Support for DigitalOcean Spaces, MinIO, and other S3-compatible providers

### 🔧 **Seamless Integration**
- **Drop-in Replacement**: Transparently replaces local file storage
- **Multiple Configurations**: Support for multiple storage providers simultaneously
- **Automatic Mounting**: Files are automatically accessible through Cockpit's asset system
- **Cache Management**: Intelligent cleanup of local cached files

### 🚀 **Performance & Scale**
- **CDN Ready**: Automatic public URL generation for CDN integration
- **Prefix Organization**: Organize files with custom folder structures
- **Visibility Control**: Configure public/private file access
- **Multi-Server Ready**: Perfect for load-balanced and containerized deployments

### 🔒 **Security & Reliability**
- **Secure Authentication**: Support for IAM roles, access keys, and connection strings
- **Region Selection**: Choose optimal storage regions for performance
- **Custom Endpoints**: Support for private clouds and alternative providers
- **Error Handling**: Comprehensive validation and error reporting

## 🚀 Quick Start

### 1. Installation

CloudStorage is a commercial addon included with Cockpit CMS Pro licenses.

### 2. Install Dependencies

**Required for Azure Blob Storage:**
```bash
composer require azure-oss/storage-blob-flysystem
```

⚠️ **Important**: Azure Blob Storage will **not work** without this package. The CloudStorage addon will throw an exception if you try to use Azure without installing this dependency first.

**AWS S3**: Dependencies are typically included with Cockpit CMS - no additional installation required.

### 3. Configure Storage

Add your cloud storage configuration to `config/config.php`:

```php
<?php
return [
    // ... other config options
    
    'cloudStorage' => [
        
        // AWS S3 Configuration
        'primary_s3' => [
            'type' => 's3',
            'key' => 'AKIA...',                    // AWS Access Key
            'secret' => 'your-secret-key',         // AWS Secret Key
            'bucket' => 'my-cockpit-uploads',      // S3 Bucket Name
            'region' => 'us-east-1',               // AWS Region
            'prefix' => 'uploads/',                // Optional: File prefix/folder
            'visibility' => 'public'               // File visibility
        ],
        
        // Azure Blob Storage Configuration
        'azure_storage' => [
            'type' => 'azure',
            'account' => 'mystorageaccount',       // Storage Account Name
            'key' => 'your-storage-key',          // Storage Account Key
            'container' => 'uploads',             // Blob Container
            'prefix' => 'cockpit/',               // Optional: File prefix
            'url' => 'https://cdn.example.com'   // Optional: Custom CDN URL
        ]
    ]
];
```

### 4. Upload Files

Once configured, all file uploads through Cockpit will automatically be stored in your configured cloud storage. No changes needed to your content workflows!

## ⚙️ Configuration

### AWS S3 Configuration

```php
'cloudStorage' => [
    's3_storage' => [
        'type' => 's3',
        'key' => 'AKIA1234567890EXAMPLE',        // Required: AWS Access Key ID
        'secret' => 'wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY', // Required: AWS Secret Access Key
        'bucket' => 'my-bucket-name',            // Required: S3 Bucket Name
        'region' => 'us-west-2',                 // Required: AWS Region
        'prefix' => 'uploads/cockpit/',          // Optional: File prefix (default: '')
        'version' => 'latest',                   // Optional: AWS API version (default: 'latest')
        'endpoint' => 'https://s3.example.com', // Optional: Custom endpoint for S3-compatible services
        'url' => 'https://cdn.example.com',     // Optional: Custom base URL for file access
        'visibility' => 'public'                // Optional: Default file visibility (default: 'public')
    ]
];
```

### Azure Blob Storage Configuration

⚠️ **Prerequisite**: Run `composer require azure-oss/storage-blob-flysystem` before using Azure Blob Storage.

```php
'cloudStorage' => [
    'azure_storage' => [
        'type' => 'azure',
        'account' => 'mystorageaccount',         // Required: Storage Account Name
        'key' => 'your-storage-account-key',    // Required: Storage Account Key
        'container' => 'uploads',               // Required: Blob Container Name
        'prefix' => 'cockpit/files/',           // Optional: File prefix (default: '')
        'url' => 'https://cdn.example.com'     // Optional: Custom base URL for file access
    ]
];
```

**Alternative Azure Authentication:**
```php
'azure_storage' => [
    'type' => 'azure',
    'connectionString' => 'DefaultEndpointsProtocol=https;AccountName=...', // Direct connection string
    'container' => 'uploads',
    'prefix' => 'cockpit/'
]
```

## 🔧 Advanced Configuration

### Multiple Storage Providers

Configure multiple storage providers for different use cases:

```php
'cloudStorage' => [
    
    // Primary storage for uploads
    'uploads' => [
        'type' => 's3',
        'key' => 'AKIA...',
        'secret' => 'secret...',
        'bucket' => 'app-uploads',
        'region' => 'us-east-1',
        'prefix' => 'uploads/',
        'visibility' => 'public'
    ],
    
    // Private storage for backups
    'backups' => [
        'type' => 's3',
        'key' => 'AKIA...',
        'secret' => 'secret...',
        'bucket' => 'app-backups',
        'region' => 'us-east-1',
        'prefix' => 'backups/',
        'visibility' => 'private'
    ],
    
    // Azure for media files
    'media' => [
        'type' => 'azure',
        'account' => 'mediastorage',
        'key' => 'key...',
        'container' => 'media',
        'url' => 'https://media-cdn.example.com'
    ]
];
```

### S3-Compatible Providers

Configure alternative S3-compatible providers:

**DigitalOcean Spaces:**
```php
'do_spaces' => [
    'type' => 's3',
    'key' => 'your-spaces-key',
    'secret' => 'your-spaces-secret',
    'bucket' => 'my-space-name',
    'region' => 'nyc3',
    'endpoint' => 'https://nyc3.digitaloceanspaces.com',
    'url' => 'https://my-space-name.nyc3.cdn.digitaloceanspaces.com'
]
```

**MinIO:**
```php
'minio' => [
    'type' => 's3',
    'key' => 'minioadmin',
    'secret' => 'minioadmin',
    'bucket' => 'uploads',
    'region' => 'us-east-1',
    'endpoint' => 'http://localhost:9000',
    'url' => 'http://localhost:9000/uploads'
]
```

**Wasabi:**
```php
'wasabi' => [
    'type' => 's3',
    'key' => 'your-wasabi-key',
    'secret' => 'your-wasabi-secret',
    'bucket' => 'my-bucket',
    'region' => 'us-east-1',
    'endpoint' => 'https://s3.wasabisys.com'
]
```

### CDN Integration

Configure CDN URLs for optimized file delivery:

```php
'cdn_storage' => [
    'type' => 's3',
    'key' => 'AKIA...',
    'secret' => 'secret...',
    'bucket' => 'my-bucket',
    'region' => 'us-east-1',
    'url' => 'https://d1234567890.cloudfront.net'  // CloudFront distribution URL
]
```

### File Organization

Use prefixes to organize files in logical structures:

```php
'organized_storage' => [
    'type' => 's3',
    'key' => 'AKIA...',
    'secret' => 'secret...',
    'bucket' => 'my-app-storage',
    'region' => 'us-east-1',
    'prefix' => 'production/uploads/',  // Files stored as: production/uploads/filename.jpg
    'visibility' => 'public'
]
```

## 🔐 Security Best Practices

### AWS IAM Policy

Create a minimal IAM policy for Cockpit CMS access:

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

### Environment Variables

Store sensitive credentials in environment variables:

```php
'cloudStorage' => [
    'production' => [
        'type' => 's3',
        'key' => $_ENV['AWS_ACCESS_KEY_ID'],
        'secret' => $_ENV['AWS_SECRET_ACCESS_KEY'],
        'bucket' => $_ENV['S3_BUCKET'],
        'region' => $_ENV['AWS_REGION'],
        'prefix' => 'uploads/'
    ]
];
```

### Azure Access Control

Use Azure Storage access keys or Shared Access Signatures (SAS):

```php
'azure_secure' => [
    'type' => 'azure',
    'account' => $_ENV['AZURE_STORAGE_ACCOUNT'],
    'key' => $_ENV['AZURE_STORAGE_KEY'],
    'container' => 'uploads',
    'prefix' => 'secure/'
]
```

## 🚀 Production Deployment

### Docker Environment

Example Docker configuration:

```dockerfile
# Dockerfile
FROM php:8.1-apache

# Install required extensions
RUN docker-php-ext-install pdo_mysql

# Copy application
COPY . /var/www/html/

# Set environment variables
ENV AWS_ACCESS_KEY_ID=your-key
ENV AWS_SECRET_ACCESS_KEY=your-secret
ENV S3_BUCKET=your-bucket
ENV AWS_REGION=us-east-1
```

### Kubernetes ConfigMap

```yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: cockpit-config
data:
  config.php: |
    <?php
    return [
        'cloudStorage' => [
            'k8s_storage' => [
                'type' => 's3',
                'key' => getenv('AWS_ACCESS_KEY_ID'),
                'secret' => getenv('AWS_SECRET_ACCESS_KEY'),
                'bucket' => getenv('S3_BUCKET'),
                'region' => getenv('AWS_REGION'),
                'prefix' => 'k8s/uploads/'
            ]
        ]
    ];
```

### Load Balancer Setup

For multi-server deployments, ensure all instances use the same cloud storage configuration:

```php
// Shared storage across all application instances
'cloudStorage' => [
    'shared' => [
        'type' => 's3',
        'key' => $_ENV['AWS_ACCESS_KEY_ID'],
        'secret' => $_ENV['AWS_SECRET_ACCESS_KEY'],
        'bucket' => $_ENV['SHARED_S3_BUCKET'],
        'region' => $_ENV['AWS_REGION'],
        'prefix' => $_ENV['APP_ENV'] . '/uploads/'  // e.g., "production/uploads/"
    ]
];
```

## 🔧 Troubleshooting

### Common Issues

**❌ "Azure Blob filestorage adapter is not installed"**

This error occurs when you try to use Azure Blob Storage without installing the required dependency.

**Solution:**
```bash
composer require azure-oss/storage-blob-flysystem
```

**Why this happens**: Azure Blob Storage requires an additional Flysystem adapter that's not included by default with Cockpit CMS. This is intentional to keep the core installation lightweight.

**"AWS S3 key is not defined"**
```php
// Ensure all required S3 parameters are set
'cloudStorage' => [
    'my_s3' => [
        'type' => 's3',
        'key' => 'required',      // ✅ AWS Access Key ID
        'secret' => 'required',   // ✅ AWS Secret Access Key  
        'bucket' => 'required',   // ✅ S3 Bucket Name
        'region' => 'required'    // ✅ AWS Region
    ]
];
```

**"Azure Blob connection string is not defined"**
```php
// Either provide account + key OR connectionString
'azure_storage' => [
    'type' => 'azure',
    'account' => 'required',    // ✅ Storage Account Name
    'key' => 'required',        // ✅ Storage Account Key
    'container' => 'required'   // ✅ Container Name
]
```

**Files not accessible/404 errors**
```php
// Check bucket/container permissions and URL configuration
'storage_config' => [
    'type' => 's3',
    // ... other config
    'visibility' => 'public',  // ✅ Ensure files are publicly accessible
    'url' => 'https://correct-cdn-url.com'  // ✅ Verify URL is correct
]
```

### Debug Mode

Enable debug logging in Cockpit to troubleshoot storage issues:

```php
// config/config.php
return [
    'debug' => true,  // Enable debug mode
    'cloudStorage' => [
        // ... your storage config
    ]
];
```

### Test Configuration

Verify your storage configuration with a simple test:

```php
// Test file upload functionality
$app = Cockpit::instance();

// This should work if CloudStorage is configured correctly
$testFile = $app->fileStorage->write('test.txt', 'Hello CloudStorage!');

if ($testFile) {
    echo "✅ CloudStorage is working correctly";
} else {
    echo "❌ CloudStorage configuration issue";
}
```

### Performance Tips

1. **Choose nearby regions** for better upload/download speeds
2. **Use CDN URLs** for public file access
3. **Configure proper caching headers** in your cloud provider
4. **Monitor storage costs** and usage patterns
5. **Use prefixes** to organize files efficiently

## 📊 Monitoring & Analytics

### AWS CloudWatch

Monitor S3 usage and performance:
- **Request metrics**: GET, PUT, DELETE operations
- **Storage metrics**: Total bucket size, object count
- **Error rates**: 4xx and 5xx error monitoring

### Azure Monitor

Track Blob Storage metrics:
- **Transaction metrics**: Request count and latency
- **Capacity metrics**: Used capacity per container
- **Availability monitoring**: Service health status

### Cost Optimization

- **Lifecycle policies**: Automatically move old files to cheaper storage classes
- **Monitoring**: Set up billing alerts for unexpected costs
- **Cleanup**: Regular cleanup of temporary and cache files

## 📄 License

This is a commercial addon for Cockpit CMS. See [LICENSE.md](LICENSE.md) for full terms.

## 🙏 Credits

CloudStorage is developed by [Agentejo](https://agentejo.com) as part of the Cockpit CMS Pro ecosystem.

---

**Ready to scale your file storage?** Configure CloudStorage and move your Cockpit CMS uploads to the cloud today!