garage-installer

AWS CLI Configuration for Garage

← Back to Documentation Index Main README

This guide explains how to properly configure the AWS CLI to work with your Garage S3 cluster.

Why Special Configuration is Needed

Garage requires specific AWS CLI settings that differ from standard AWS S3:

  1. Path-Style Addressing: Garage uses path-style URLs (http://endpoint/bucket/key) instead of virtual-host style (http://bucket.endpoint/key)
  2. Custom Region: You must specify garage as the region (or whatever you configured in garage.toml)
  3. Custom Endpoint: Your Garage S3 API endpoint instead of AWS’s S3 endpoints

Quick Setup

After a successful installation, the installer will display your cluster’s S3 API endpoints. You’ll need:

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

Option 2: Environment Variables

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

Usage Examples

List Buckets

aws s3 ls

Create a Bucket

aws s3 mb s3://my-bucket

Upload a File

aws s3 cp myfile.txt s3://my-bucket/

Download a File

aws s3 cp s3://my-bucket/myfile.txt ./downloaded.txt

Sync a Directory

aws s3 sync ./local-folder s3://my-bucket/remote-folder/

List Objects in a Bucket

aws s3 ls s3://my-bucket/

Delete a File

aws s3 rm s3://my-bucket/myfile.txt

Delete a Bucket (must be empty)

aws s3 rb s3://my-bucket

Common Issues and Solutions

“Invalid signature” Error

Symptoms:

An error occurred (AccessDenied) when calling the PutObject operation: Forbidden: Invalid signature

Solutions:

  1. Verify path-style addressing is configured:
    aws configure get default.s3.addressing_style
    # Should return: path
    
  2. If not set, configure it:
    aws configure set default.s3.addressing_style path
    
  3. Verify your credentials are correct (access key and secret key)

  4. Make sure you’re using the correct endpoint URL

“Cannot satisfy location constraint” Error

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

Endpoint Not Reachable

Symptoms:

Could not connect to the endpoint URL

Solutions:

  1. Verify the node is accessible: ping cafe-1
  2. Check firewall rules allow port 3900
  3. Verify Garage is running: ssh mihay42@cafe-1 "docker ps | grep garage"
  4. Try the other node’s endpoint if you have multiple nodes

Access Denied for Bucket Operations

Symptoms:

An error occurred (AccessDenied) when calling the [operation]

Solutions:

  1. Check bucket permissions are granted to your key:
    ssh mihay42@cafe-1 "docker exec garage /garage bucket info my-bucket"
    
  2. Grant permissions if needed:
    ssh mihay42@cafe-1 "docker exec garage /garage bucket allow my-bucket --read --write --key YOUR_KEY_ID"
    

Managing Keys and Permissions

Creating a New Key

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.

Granting Bucket Permissions

# 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.

Viewing Key Information

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.

Advanced Configuration

Using Multiple Profiles

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

Using with Scripts

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/

Testing Your Configuration

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:

  1. Use Key ID (GKxxx…) with key allow --create-bucket
  2. Use key name with bucket allow --read --write
  3. After creating a bucket, you must grant your key read/write permissions to use it

If all commands succeed, your AWS CLI is properly configured!

See Also