Set Up s3cmd 2.x with DigitalOcean Spaces
Last verified 22 Jun 2026
Spaces Object Storage is an S3-compatible service for storing and serving large amounts of data. The built-in Spaces CDN minimizes page load times, improves performance, and reduces bandwidth and infrastructure costs.
s3cmd is a cross-platform command-line tool for managing S3 and S3-compatible object storage.
To use s3cmd with Spaces, you need:
-
s3cmd version 2.0.0 or later.
Check your version with
s3cmd --version. Versions from package managers may be out of date. To install the latest version, see the s3cmd download page. Homebrew users can install s3cmd withbrew install s3cmd.
Initialize the Configuration File
By default, s3cmd’s configuration file (.s3cfg) is a plain text file of key-value pairs that you can edit directly after s3cmd creates it.
s3cmd uses the options in its default configuration file when you run commands. To use a different configuration file, add -c ~/path/to/config/file to each command.
If you use s3cmd primarily with Spaces, configure the default ~/.s3cfg file:
s3cmd --configureIf you already use s3cmd with another service, create an alternate configuration file with the -c flag:
s3cmd --configure -c ~/path/to/config/files3cmd creates the configuration file in the directory where you run the command unless you specify a path.
Enter Access Keys
The configuration script first prompts for an access key and secret key, so enter your Spaces access key and secret key.
Then, accept US as your default region. s3cmd requires a default region value, but Spaces uses the endpoint to determine the bucket region.
You can also leave the access key and secret key prompts blank and use AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables instead.
Enter new values or accept defaults in brackets with Enter.
Refer to user manual for detailed description of all options.
Access key and Secret key are your identifiers for Amazon S3. Leave them empty for using the env variables.
Access Key []: <your-spaces-key>
Secret Key []: <your-spaces-secret>
Default Region [US]:Enter the DigitalOcean Endpoint
Enter the Spaces endpoint for your bucket region. Spaces endpoints use the format <your-region>.digitaloceanspaces.com, for example nyc3.digitaloceanspaces.com.
Use "s3.amazonaws.com" for S3 Endpoint and not modify it to the target Amazon S3.
S3 Endpoint [s3.amazonaws.com]: <your-region>.digitaloceanspaces.comThe next prompt asks for a URL template to access your bucket. Because Spaces supports DNS-based endpoint URLs, enter the template %(bucket)s.nyc3.digitaloceanspaces.com, replacing nyc3 with the region your bucket is in. s3cmd substitutes the %(bucket)s variable with your bucket name at request time.
Use "%(bucket)s.s3.amazonaws.com" to the target Amazon S3. "%(bucket)s" and "%(location)s" vars c
an be used if the target S3 system supports dns based buckets.
DNS-style bucket+hostname:port template for accessing a bucket []: %(bucket)s.nyc3.digitaloceanspaces.comSet an Encryption Password
You can also set up an optional encryption password. GPG encryption protects files before upload and while they are stored in Spaces. Setting a password doesn’t encrypt objects automatically. It makes encryption available for commands that use it later.
Encryption password is used to protect your files from reading
by unauthorized persons while in transfer to S3
Encryption password:Then, enter the path to the GPG program. On Linux, press ENTER to accept the default. On macOS, install GPG first if needed:
brew install gpgThen, find the GPG path:
which gpgNext, enter the path returned by which gpg, or press ENTER to accept the default path shown in brackets:
Path to GPG program [/usr/bin/gpg]:Connect with HTTPS
Spaces requires HTTPS, so accept the default value:
When using secure HTTPS protocol all communication with Amazon S3
servers is protected from 3rd party eavesdropping. This method is
slower than plain HTTP, and can only be proxied with Python 2.7 or newer
Use HTTPS protocol [Yes]: YesSet a Proxy Server
Then, you can optionally set up an HTTP proxy server. If your network requires a proxy, enter its IP address or domain name without the protocol, such as 203.0.113.1 or proxy.example.com.
If your network doesn’t require a proxy, press ENTER to leave the value blank.
On some networks all internet access must go through a HTTP proxy.
Try setting it here if you can't connect to S3 directly
HTTP Proxy server name:Test and Save Settings
After the HTTP proxy prompt, s3cmd displays a summary of the configuration and asks whether to test the credentials:
New settings:
Access Key: <your-spaces-access-key>
Secret Key: <your-spaces-secret>
Default Region: US
S3 Endpoint: <your-region>.digitaloceanspaces.com
DNS-style bucket+hostname:port template for accessing a bucket: %(bucket)s.<your-region>.digitaloceanspaces.com
Encryption password: <your-password>
Path to GPG program: /usr/bin/gpg
Use HTTPS protocol: True
HTTP Proxy server name:
HTTP Proxy server port: 0
Test access with supplied credentials? [Y/n] YAfter the test succeeds, enter Y to save the settings:
Please wait, attempting to list all buckets...
Success. Your access key and secret key worked fine :-)
Now verifying that encryption works...
Success. Encryption and decryption worked fine :-)
Save settings? [y/N] YIf the test fails or you enter N, s3cmd gives you an opportunity to update the configuration. After you save the configuration, s3cmd confirms the file location:
Configuration saved to '/home/sammy/nyc3'Verify with a Test Upload
After saving the configuration, upload a test file to confirm that s3cmd can connect to Spaces:
First, create a test file:
echo "Hello, World!" > hello-world.txtThen, upload the test file to your Spaces bucket:
s3cmd put hello-world.txt s3://<your-example-space>/hello-world.txtReplace <your-example-space> with the name of your Space.
If the upload succeeds, the s3cmd configuration works.
Test the Credentials with an AWS SDK
You can also test the same Spaces credentials with an AWS SDK. The following examples upload a hello-world.txt object to a Spaces bucket:
import { PutObjectCommand, S3Client } from '@aws-sdk/client-s3';
const s3Client = new S3Client({
endpoint: "https://<your-region>.digitaloceanspaces.com",
forcePathStyle: false,
region: "us-east-1",
credentials: {
accessKeyId: process.env.SPACES_KEY,
secretAccessKey: process.env.SPACES_SECRET
}
});
const params = {
Bucket: "<your-example-space>",
Key: "hello-world.txt",
Body: "Hello, World!",
ACL: "private"
};
const uploadObject = async () => {
try {
await s3Client.send(new PutObjectCommand(params));
console.log("Upload successful");
} catch (err) {
console.error("Error", err);
}
};
uploadObject();package main
import (
"fmt"
"os"
"strings"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/credentials"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/s3"
)
func main() {
key := os.Getenv("SPACES_KEY")
secret := os.Getenv("SPACES_SECRET")
s3Config := &aws.Config{
Credentials: credentials.NewStaticCredentials(key, secret, ""),
Endpoint: aws.String("https://<your-region>.digitaloceanspaces.com"),
S3ForcePathStyle: aws.Bool(false),
Region: aws.String("us-east-1"),
}
newSession := session.New(s3Config)
s3Client := s3.New(newSession)
object := &s3.PutObjectInput{
Bucket: aws.String("<your-example-space>"),
Key: aws.String("hello-world.txt"),
Body: strings.NewReader("Hello, World!"),
ACL: aws.String("private"),
}
if _, err := s3Client.PutObject(object); err != nil {
fmt.Println(err.Error())
} else {
fmt.Println("Upload successful")
}
}import os
import boto3
import botocore.config
session = boto3.session.Session()
client = session.client(
's3',
endpoint_url='https://<your-region>.digitaloceanspaces.com',
config=botocore.config.Config(s3={'addressing_style': 'virtual'}),
region_name='<your-region>',
aws_access_key_id=os.getenv('SPACES_KEY'),
aws_secret_access_key=os.getenv('SPACES_SECRET')
)
client.put_object(
Bucket='<your-example-space>',
Key='hello-world.txt',
Body=b'Hello, World!',
ACL='private'
)
print("Upload successful")require 'aws-sdk-s3'
client = Aws::S3::Client.new(
access_key_id: ENV['SPACES_KEY'],
secret_access_key: ENV['SPACES_SECRET'],
endpoint: 'https://<your-region>.digitaloceanspaces.com',
force_path_style: false,
region: 'us-east-1'
)
client.put_object(
bucket: "<your-example-space>",
key: "hello-world.txt",
body: "Hello, World!",
acl: "private"
)
puts "Upload successful"SPACE="<your-example-space>"
REGION="<your-region>"
KEY="<your-spaces-access-key>"
SECRET="<your-spaces-secret>"
FILE="hello-world.txt"
echo "Hello, World!" > $FILE
DATE=$(date -R)
CONTENT_TYPE="text/plain"
ACL="x-amz-acl:private"
STRING="PUT\n\n$CONTENT_TYPE\n$DATE\n$ACL\n/$SPACE/$FILE"
SIGNATURE=$(echo -en "${STRING}" | openssl sha1 -hmac "${SECRET}" -binary | base64)
curl -X PUT -T "$FILE" \
-H "Host: $SPACE.$REGION.digitaloceanspaces.com" \
-H "Date: $DATE" \
-H "Content-Type: $CONTENT_TYPE" \
-H "$ACL" \
-H "Authorization: AWS $KEY:$SIGNATURE" \
"https://$SPACE.$REGION.digitaloceanspaces.com/$FILE"If the upload succeeds, the Spaces credentials work with the selected SDK or cURL example.
For common s3cmd commands, see the s3cmd usage quick reference. For the complete s3cmd command reference, see the s3cmd usage guide or run s3cmd --help.