Welcome! Type "help" for available commands.
$
Loading terminal interface...
Back to Blog

How I Finally Got a DigitalOcean Spaces Bucket to Default Public (Spoiler: Ditch Per-Bucket Keys)

July 20, 2025
William Callahan

Software engineer and founder with a background in finance and tech. Currently building aVenture.vc, a platform for researching private companies. Based in San Francisco.

digitaloceans3object storageaws-clis3cmddevopssysadminhostingcdnbucket policyacl
How I Finally Got a DigitalOcean Spaces Bucket to Default Public (Spoiler: Ditch Per-Bucket Keys)

What This Post Covers

This guide covers:

  • Why Per-Bucket Access Keys are the secret villain behind most 403 Forbidden policy errors.
  • The dead-simple ACL approach that works every time.
  • When you can safely use a JSON bucket policy (and when to save yourself the headache).
  • How to turn on server access logging—no support ticket required anymore.

I thought making a bucket public on DigitalOcean Spaces would be a ten-second checkbox. Instead I burned an afternoon chasing 403 Forbidden errors and second-guessing my JSON.

The truth I wish I'd known: if you leave Per-Bucket Access Keys enabled you can't modify most bucket policies—period. Turn that feature off, switch to a regular all-or-nothing access key, and everything snaps into place.

Below is the exact sequence that finally worked for me, with the false turns called out so you don't repeat them.

1. Disable Per-Bucket Access Keys (Yes, Really)

DigitalOcean's per-bucket keys sound great on paper: tight scoping, least-privilege, all that good stuff. Unfortunately the current implementation blocks PutBucketPolicy, PutBucketLogging, and a few other S3 calls—even if the UI insists the key has those permissions.

Fix: In the Spaces dashboard, open your bucket ➜ Settings ➜ toggle Per-Bucket Access Keys off. Grab a classic Spaces key (or create a new one) that has full account-wide access. Use that for every command below.

If you're still seeing 403s after this step, double-check that your CLI is using the new key.

2. Install s3cmd (AWS CLI Works, But s3cmd is Friendlier Here)

# macOS
brew install s3cmd

# Ubuntu / Debian
sudo apt-get install s3cmd

Run s3cmd --configure and drop in your Spaces key, secret, and region (for me: sfo3). When it asks for the endpoint, use sfo3.digitaloceanspaces.com (swap for your region).

3. The No-Drama ACL Method

This is the zero-friction route I recommend.

a. Make the bucket listable

s3cmd setacl s3://YOUR_BUCKET --acl-public

b. Flip every existing object to public

s3cmd setacl s3://YOUR_BUCKET/ --acl-public --recursive

c. Upload new files as public by default

s3cmd put local-file.jpg s3://YOUR_BUCKET/remote-file.jpg --acl-public

That's it. Skip the rest of the post unless you love yak-shaving.

4. The JSON Bucket Policy Rabbit Hole (Optional)

Feel like you must use a proper policy? Fine—just remember the Per-Bucket Keys warning above.

  1. Create public-policy.json:
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": "*",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::YOUR_BUCKET/*"
    }
  ]
}
  1. Push it with the AWS CLI (endpoint is mandatory):
aws s3api put-bucket-policy \
  --bucket YOUR_BUCKET \
  --endpoint-url https://YOUR_REGION.digitaloceanspaces.com \
  --policy file://public-policy.json

If that still throws a 403, triple-check that you're using a non-scoped key.

5. Good News: Access Logging is Self-Serve Now

Back in early 2025 you had to open a support ticket to enable server access logging. As of July 2025 the feature is rolled out for everyone—no ticket required.

Enable it with a single call:

aws s3api put-bucket-logging \
  --bucket YOUR_SOURCE_BUCKET \
  --endpoint-url https://YOUR_REGION.digitaloceanspaces.com \
  --bucket-logging-status '{
    "LoggingEnabled": {
      "TargetBucket": "your-log-destination-bucket",
      "TargetPrefix": "logs/"
    }
  }'

If you get a 403 here, you already know the likely cause: you forgot to disable Per-Bucket Access Keys.


tl;dr

  1. Turn off Per-Bucket Access Keys.
  2. Use ACLs for the fastest public-by-default setup.
  3. Policies and access logging work once you're using a full-access key—no more support tickets.

Similar Content

Home
CV
ExperienceEducation
ProjectsBookmarksInvestmentsContactBlog
Welcome! Type "help" for available commands.
$
Loading terminal interface...

Similar Content

Related Articles

September 25, 2025
How to Secure Environment Variables for LLMs, MCPs, and AI Tools Using 1Password or Doppler

How to Secure Environment Variables for LLMs, MCPs, and AI Tools Using 1Password or Doppler

Stop hardcoding API keys in MCP configs and AI tool settings. Learn how to use 1Password CLI or Doppler to inject secrets just-in-time for Claude, Cur...

security1passworddopplermcpaillm+10
BLOG
August 22, 2025
Claude Code Output Styles: Explanatory, Learning, and Custom Options

Claude Code Output Styles: Explanatory, Learning, and Custom Options

An implementation guide to Claude Code's /output-style, the built‑in Explanatory and Learning modes (with to-do prompts), and creating reusable custom...

aiclaude codeoutput styleslearningcustom stylesexplanatory+7
BLOG
February 10, 2025
How I Host My Apps: How to Deploy in 2025

How I Host My Apps: How to Deploy in 2025

The hosting setup I use for aVenture.vc, plus why you shouldn't waste time with complex cloud services when starting out.

devopsdockercloudstartupshostapps+6
BLOG

Related Bookmarks

loggingsucks.com
December 22, 2025
Logging Sucks - Your Logs Are Lying To You

Logging Sucks - Your Logs Are Lying To You

Why traditional logging fails and how wide events can fix your observability

database performanceobservability engineeringstructured loggingwide eventscircuit breakerslogs+7
LINK
cassidoo.co
September 28, 2025
Questions to ask when you think need to finish something

Questions to ask when you think need to finish something

When a pursuit becomes a drag, here’s some questions to help you figure out why, and what to do about it.

project managementproductivity tipsdecision-makingmotivationside projectsquestions+7
LINK
github.com
August 8, 2025
GitHub - gotify/server: A simple server for sending and receiving messages in real-time per WebSocket. (Includes a sleek web-ui)

GitHub - gotify/server: A simple server for sending and receiving messages in real-time per WebSocket. (Includes a sleek web-ui)

A simple server for sending and receiving messages in real-time per WebSocket. (Includes a sleek web-ui) - gotify/server

open source projectsself-hosted messaging serversreal-time communicationwebsocket applicationsrest apisserver+7
LINK

Related Books

100 Java Mistakes and How to Avoid Them

100 Java Mistakes and How to Avoid Them

Tagir Valeev

Whenever you make a mistake writing Java, it's almost guaranteed that someone else has made it before! In 100 Java Mistakes and How To Avoid Them you'...

computerstagir valeevsimon and schusterjava100mistakes+5
BOOK
Advanced Algorithms and Data Structures

Advanced Algorithms and Data Structures

Marcello La Rocca

marcello la roccaadvancedalgorithmsdatastructures
BOOK
Essential TypeScript 5, Third Edition

Essential TypeScript 5, Third Edition

Adam Freeman

"TypeScript is a popular superset of JavaScript that adds support for static typing. TypeScript's typing features, which will be instantly familiar to...

computersadam freemansimon and schustertypescriptessentialthird+5
BOOK

Related Investments

Vest

Vest

Vest is an application that allows investing in the US stock market in Latin America.

investment platformsseedactivevestmarketapplication+5
INV
Switch

Switch

Switch provides a simple way to pool money and spend with a group.

paymentspre-seedactiveswitchprovidessimple+5
INV
Anfin

Anfin

Vietnamese investment platform making stock and crypto investing accessible to retail investors.

financeseedactiveanfininvestmentplatform+5
INV