Less3 is an S3-compatible object storage platform that you can run anywhere.
Core use cases for Less3:
- Local object storage - S3-compatible storage on your laptop, virtual machine, container, or bare metal
- Private cloud object storage - use your existing private cloud hardware to create an S3-compatible storage pool
- Development and test - local devtest against S3-compatible storage
- Remote storage - deploy S3-compatible storage in environments where you must control data placement
v2.1.17
- Multipart upload support - InitiateMultipartUpload, UploadPart, CompleteMultipartUpload, AbortMultipartUpload, ListParts, ListMultipartUploads
- Enhanced AWS CLI compatibility
- Dependency updates for improved stability
- See
AWSCLI.md
for comprehensive testing commands
First things first - do you need help or have feedback? Please file an issue here.
Thanks to @iain-cyborn for helping make the platform better!
- .NET 8.0 SDK or runtime
- Supported databases: SQLite (default), SQL Server, MySQL, or PostgreSQL
Clone, build, and run Less3:
git clone https://github.com/jchristn/less3
cd less3
dotnet build src/Less3.sln
cd src/Less3
dotnet run
On first launch, Less3 will run a setup wizard that creates:
system.json
- Server configurationless3.db
- SQLite database (default)- A sample "default" bucket with test files
To re-run the setup wizard at any time:
dotnet run setup
dotnet publish src/Less3/Less3.csproj -c Release -o ./publish
cd publish
dotnet Less3.dll
Webserver.Hostname: MUST be set to a DNS hostname. IP addresses are not supported (parsing will fail). Incoming HTTP requests must have a HOST header matching this value, or you will receive 400/Bad Request
.
Wildcard Listeners: Using *
, +
, or 0.0.0.0
for Webserver.Hostname
requires administrative/root privileges (OS requirement).
{
"Webserver": {
"Hostname": "localhost",
"Port": 8000
},
"BaseDomain": null,
"Storage": {
"DiskDirectory": "./disk/",
"TempDirectory": "./temp/"
},
"Database": {
"Type": "Sqlite",
"Filename": "./less3.db"
},
"AdminApiKey": "less3admin",
"ValidateSignatures": true
}
Less3 was designed to be consumed using the AWS SDK, AWS CLI, MinIO Client (mc), or direct RESTful integration in accordance with Amazon's official S3 API documentation (https://docs.aws.amazon.com/AmazonS3/latest/API/Welcome.html).
- AWS SDK (C#, Python, Java, etc.)
- AWS CLI - See
AWSCLI.md
for comprehensive testing commands - MinIO Client (mc) - See
MINIO.md
for comprehensive testing commands - CloudBerry Explorer for S3 (https://www.cloudberrylab.com/explorer/windows/amazon-s3.aspx)
- S3 Browser (http://s3browser.com/)
Should you encounter a discrepancy between how Less3 operates and how AWS S3 operates, please file an issue with details and supporting AWS documentation.
Less3 implements the following AWS S3 APIs. For a complete compatibility matrix, refer to the 'assets' directory.
- ListBuckets - List all buckets
- CreateBucket (Write) - Create a new bucket
- DeleteBucket (Delete) - Delete an empty bucket
- HeadBucket (Exists) - Check if bucket exists
- ListObjectsV2 (Read) - List objects in a bucket
- ListObjectVersions (ReadVersions) - List object versions
- GetBucketAcl (ReadAcl) - Get bucket access control list
- PutBucketAcl (WriteAcl) - Set bucket access control list
- GetBucketTagging (ReadTagging) - Get bucket tags
- PutBucketTagging (WriteTagging) - Set bucket tags
- DeleteBucketTagging (DeleteTagging) - Delete bucket tags
- GetBucketVersioning (ReadVersioning) - Get bucket versioning configuration
- PutBucketVersioning (WriteVersioning) - Set bucket versioning (no MFA delete support)
- GetBucketLocation (ReadLocation) - Get bucket location/region
- ListMultipartUploads (ReadMultipartUploads) - List in-progress multipart uploads
- PutObject (Write) - Upload an object
- GetObject (Read) - Download an object
- HeadObject (Exists) - Check if object exists
- DeleteObject (Delete) - Delete an object or version
- DeleteObjects (DeleteMultiple) - Delete multiple objects
- GetObjectAcl (ReadAcl) - Get object access control list
- PutObjectAcl (WriteAcl) - Set object access control list
- GetObjectTagging (ReadTagging) - Get object tags
- PutObjectTagging (WriteTagging) - Set object tags
- DeleteObjectTagging (DeleteTagging) - Delete object tags
- GetObject with Range (ReadRange) - Download partial object content
- CreateMultipartUpload (InitiateMultipartUpload) - Start a multipart upload
- UploadPart - Upload a part of a multipart upload
- CompleteMultipartUpload - Finalize a multipart upload
- AbortMultipartUpload - Cancel a multipart upload
- ListParts (ReadParts) - List parts of a multipart upload
Less3 aims to faithfully implement S3 API behavior. However, there are a few minor differences that should be inconsequential for most use cases:
- Version IDs: Stored as integers internally rather than opaque strings (e.g.,
1
,2
,3
instead of AWS-style strings) - Region: Defaults to
us-west-1
(configurable viaRegionString
in system.json) - Signature Validation: Can be enabled/disabled via
ValidateSignatures
setting (enabled by default)
If you encounter incompatibilities or unexpected behavior with supported APIs, please file an issue with:
- Description of the expected behavior
- Link to AWS S3 documentation
- Steps to reproduce the issue
Less3 supports both S3 URL styles for accessing buckets and objects:
- Format:
http://hostname:port/bucket/key
- Configuration: Do NOT set
BaseDomain
in system.json (leave it null) - Example:
http://localhost:8000/mybucket/myfile.txt
- Use Case: Simple setup, local development, no DNS configuration needed
- Format:
http://bucket.hostname:port/key
- Configuration Requirements:
- Set
BaseDomain
to your base domain (e.g.,.localhost
- note the leading period) - Set
Webserver.Hostname
to*
(wildcard listener) - Run Less3 with administrative/root privileges
- Ensure DNS resolves bucket subdomains to your Less3 server (e.g.,
mybucket.localhost
)
- Set
- Example:
http://mybucket.localhost:8000/myfile.txt
- Use Case: Production environments, AWS S3-like URL structure
Configuration Example (system.json for virtual hosted-style):
{
"BaseDomain": ".localhost",
"Webserver": {
"Hostname": "*",
"Port": 8000
}
}
Less3 provides REST APIs for administrative operations such as managing users, credentials, and buckets.
Admin APIs require the x-api-key
header with a value matching AdminApiKey
in system.json (default: less3admin
).
http://hostname:port/admin/{resource}/{operation}
- users - Manage user accounts
- credentials - Manage access keys and secret keys
- buckets - Manage buckets and bucket configuration
curl -X GET http://localhost:8000/admin/users/list \
-H "x-api-key: less3admin"
For detailed API documentation, refer to the project wiki.
Less3 is built using a series of open-source packages, including:
- AWS SDK - https://github.com/aws/aws-sdk-net
- S3 Server - https://github.com/jchristn/s3server
- Watson Webserver - https://github.com/jchristn/WatsonWebserver
- WatsonORM - https://github.com/jchristn/watsonorm
Less3 is available on DockerHub.
- Navigate to the
Docker
directory - Run the deployment:
cd Docker docker compose up -d
The Docker
directory contains:
compose.yaml
- Docker Compose configurationsystem.json
- Pre-configured Less3 settingsless3.db
- SQLite database (will be created on first run)
- Port: 8000
- Access Key:
default
- Secret Key:
default
- Protocol: HTTP (no SSL)
- URL Style: Path-style (
http://localhost:8000/bucket/key
) - Hostname:
*
(accepts all incoming requests)
The Docker deployment maps the following directories for persistence:
./system.json
→/app/system.json
- Configuration file./less3.db
→/app/less3.db
- Database./logs/
→/app/logs/
- Log files./temp/
→/app/temp/
- Temporary files during uploads./disk/
→/app/disk/
- Object storage data
cd src
docker build -t less3:custom -f Less3/Dockerfile .
Important: For production deployments, always:
- Change the default access key and secret key
- Use persistent volume mounts for database and storage
- Consider using a non-SQLite database (SQL Server, MySQL, or PostgreSQL)
Refer to CHANGELOG.md for details.