Symptom

An S3 client (AWS CLI, boto3, s3cmd, s5cmd) returns 403 Access Denied against s3.runatlas.is. Variants:

An error occurred (403) when calling the PutObject operation: Forbidden
An error occurred (AccessDenied) when calling the HeadBucket operation: Forbidden

Investigation

1. Are your S3 credentials the right ones?

Atlas’s S3 endpoint uses dedicated S3 access keys — they are not the same as your CloudStack API key. Confirm where you got the keys: the Console’s Storage → Access keys view, or via the API. CloudStack API keys against s3.runatlas.is will always 403.

aws --endpoint-url https://s3.runatlas.is configure list

Check that access_key and secret_key are the S3-specific pair you copied from the storage view.

2. Are you signing for the right region?

Atlas’s S3 is exposed without strict region constraints, but most SDKs will fail to sign if no region is configured at all. Set:

aws configure set region us-east-1

(Any valid AWS region name works; us-east-1 is the universal default.)

3. Path-style vs virtual-hosted-style URL

Atlas supports both, but some SDK versions default to a URL style the bucket name doesn’t accept. If you’re getting 403 on what looks like a valid request, try forcing path-style:

aws --endpoint-url https://s3.runatlas.is \
    s3api put-object \
    --bucket mybucket \
    --key hello.txt \
    --body hello.txt

If that works but virtual-hosted-style fails, switch your SDK to path-style (s3.config.S3Config(s3={'addressing_style': 'path'}) in boto3) or check that your bucket name is DNS-safe (lowercase, no underscores).

4. Clock skew

S3 signatures are time-sensitive — a clock skew of more than 15 minutes between your machine and Atlas’s clock will produce a 403. Check date -u on your machine; if it’s far off, sync NTP:

sudo systemctl restart systemd-timesyncd

5. Wrong bucket / object owner

If the bucket was created by a different user in your account, you may not have permission to write to it. Confirm:

aws --endpoint-url https://s3.runatlas.is s3api get-bucket-acl --bucket mybucket

If the owner is not you, switch to credentials for the right user or have the bucket owner grant you a policy.

Solution

The fix is almost always:

  • Re-copy S3-specific credentials from the Console’s storage view (not the CloudStack API view).
  • Set an AWS region (any).
  • Force path-style addressing if your bucket name has dots or your SDK is finicky.
  • Sync your system clock.

If the 403 persists with fresh credentials and clock-synced, the bucket may have an explicit deny policy. Use:

aws --endpoint-url https://s3.runatlas.is s3api get-bucket-policy --bucket mybucket

To inspect and update it. See Buckets for the canonical guide.

If you’re still stuck, email mailto:help@runatlas.is with the bucket name, the credentials’ access-key prefix (first 4 chars only — never the full key), and the timestamp.