| ← Back to Documentation Index | Main README |
This guide explains how to properly configure the AWS CLI to work with your Garage S3 cluster.
Garage requires specific AWS CLI settings that differ from standard AWS S3:
http://endpoint/bucket/key) instead of virtual-host style (http://bucket.endpoint/key)garage as the region (or whatever you configured in garage.toml)After a successful installation, the installer will display your cluster’s S3 API endpoints. You’ll need:
http://node1:3900 or http://node2:3900GK)Create or edit ~/.aws/credentials:
[default]
aws_access_key_id=GKxxxxxxxxxxxxxxxxxxxx
aws_secret_access_key=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Create or edit ~/.aws/config:
[default]
region=garage
endpoint_url=http://your-node:3900
For temporary use or scripts:
export AWS_ACCESS_KEY_ID="GKxxxxxxxxxxxxxxxxxxxx"
export AWS_SECRET_ACCESS_KEY="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
export AWS_DEFAULT_REGION="garage"
export AWS_ENDPOINT_URL="http://your-node:3900"
# Configure path-style addressing globally
aws configure set default.s3.addressing_style path
aws s3 ls
aws s3 mb s3://my-bucket
aws s3 cp myfile.txt s3://my-bucket/
aws s3 cp s3://my-bucket/myfile.txt ./downloaded.txt
aws s3 sync ./local-folder s3://my-bucket/remote-folder/
aws s3 ls s3://my-bucket/
aws s3 rm s3://my-bucket/myfile.txt
aws s3 rb s3://my-bucket
Symptoms:
An error occurred (AccessDenied) when calling the PutObject operation: Forbidden: Invalid signature
Solutions:
aws configure get default.s3.addressing_style
# Should return: path
aws configure set default.s3.addressing_style path
Verify your credentials are correct (access key and secret key)
Symptoms:
An error occurred (IllegalLocationConstraintException) when calling the CreateBucket operation:
Cannot satisfy location constraint aws-global
Solution:
Ensure region is set to garage (or your custom region name):
aws configure set default.region garage
Symptoms:
Could not connect to the endpoint URL
Solutions:
ping cafe-1ssh mihay42@cafe-1 "docker ps | grep garage"Symptoms:
An error occurred (AccessDenied) when calling the [operation]
Solutions:
ssh mihay42@cafe-1 "docker exec garage /garage bucket info my-bucket"
ssh mihay42@cafe-1 "docker exec garage /garage bucket allow my-bucket --read --write --key YOUR_KEY_ID"
Keys can only be created on the Garage server via SSH:
# Create a new key (from your local machine)
ssh mihay42@cafe-1 "docker exec garage /garage key create my-new-key"
# Or SSH to the node first
ssh mihay42@cafe-1
docker exec garage /garage key create my-new-key
# IMPORTANT: Save the Secret Key immediately - it cannot be retrieved later!
Output example:
==== ACCESS KEY INFORMATION ====
Key ID: GKxxxxxxxxxxxxxxxxxxxx
Key name: my-new-key
Secret key: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Created: 2025-11-17 03:31:47.729 +00:00
Validity: valid
Expiration: never
Can create buckets: false
==== BUCKETS FOR THIS KEY ====
Permissions ID Global aliases Local aliases
Enabling Bucket Creation:
By default, new keys cannot create buckets (Can create buckets: false). To grant this permission:
# Allow the key to create buckets (use the Key ID from above)
ssh mihay42@cafe-1 "docker exec garage /garage key allow --create-bucket GKxxxxxxxxxxxxxxxxxxxx"
Output after granting bucket creation permission:
==== ACCESS KEY INFORMATION ====
Key ID: GKxxxxxxxxxxxxxxxxxxxx
Key name: my-new-key
Secret key: (redacted)
Created: 2025-11-17 03:31:47.729 +00:00
Validity: valid
Expiration: never
Can create buckets: true
==== BUCKETS FOR THIS KEY ====
Permissions ID Global aliases Local aliases
You can verify the permission was granted by checking Can create buckets: true in the output.
# Grant full ownership (read, write, and ability to delete bucket)
ssh mihay42@cafe-1 "docker exec garage /garage bucket allow --read --write --owner nextcloud-bucket --key nextcloud-app-key"
# Grant read/write permissions (most common)
ssh mihay42@cafe-1 "docker exec garage /garage bucket allow --read --write nextcloud-bucket --key nextcloud-app-key"
# Grant read-only permissions
ssh mihay42@cafe-1 "docker exec garage /garage bucket allow --read nextcloud-bucket --key nextcloud-app-key"
# Grant write-only permissions
ssh mihay42@cafe-1 "docker exec garage /garage bucket allow --write nextcloud-bucket --key nextcloud-app-key"
Note: Use bucket name (not bucket ID) and key name (not key ID) in these commands.
ssh mihay42@cafe-1 "docker exec garage /garage key info my-key-name"
Note: The secret key will be shown as (redacted) for security. It’s only displayed once when the key is created.
You can configure multiple profiles for different keys or endpoints:
~/.aws/credentials:
[default]
aws_access_key_id = GK_default_key
aws_secret_access_key = default_secret
[production]
aws_access_key_id = GK_prod_key
aws_secret_access_key = prod_secret
[staging]
aws_access_key_id = GK_staging_key
aws_secret_access_key = staging_secret
~/.aws/config:
[default]
region = garage
endpoint_url = http://node1:3900
s3 =
addressing_style = path
[profile production]
region = garage
endpoint_url = http://prod-node:3900
s3 =
addressing_style = path
[profile staging]
region = garage
endpoint_url = http://staging-node:3900
s3 =
addressing_style = path
Usage:
# Use default profile
aws s3 ls
# Use production profile
aws s3 ls --profile production
# Use staging profile
aws s3 ls --profile staging
Create a helper script (~/bin/garage-s3):
#!/bin/bash
# Wrapper script for Garage S3 operations
export AWS_ACCESS_KEY_ID="${GARAGE_ACCESS_KEY:-GKxxxxxxxxxxxxxxxxxxxx}"
export AWS_SECRET_ACCESS_KEY="${GARAGE_SECRET_KEY:-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}"
export AWS_DEFAULT_REGION="garage"
export AWS_ENDPOINT_URL="${GARAGE_ENDPOINT:-http://node1:3900}"
# Ensure path-style addressing
aws configure set default.s3.addressing_style path 2>/dev/null
# Pass all arguments to aws
aws "$@"
Make it executable:
chmod +x ~/bin/garage-s3
Usage:
garage-s3 s3 ls
garage-s3 s3 cp myfile.txt s3://my-bucket/
Run these commands to verify everything works:
# First, grant your key permission to create buckets (use your Key ID)
ssh mihay42@cafe-1 "docker exec garage /garage key allow --create-bucket GKxxxxxxxxxxxxxxxxxxxx"
# Test connectivity and credentials
aws s3 ls
# Create a test bucket (now works with create-bucket permission)
aws s3 mb s3://test-bucket
# Grant yourself permissions to use the bucket (use your key name)
ssh mihay42@cafe-1 "docker exec garage /garage bucket allow --read --write test-bucket --key YOUR_KEY_NAME"
# Upload a test file
echo "Hello Garage!" > test.txt
aws s3 cp test.txt s3://test-bucket/
# Download and verify
aws s3 cp s3://test-bucket/test.txt downloaded.txt
cat downloaded.txt
# Cleanup
aws s3 rm s3://test-bucket/test.txt
aws s3 rb s3://test-bucket
rm test.txt downloaded.txt
Important:
key allow --create-bucketbucket allow --read --writeIf all commands succeed, your AWS CLI is properly configured!