The AWS console is great until you want to give someone a read-only link to a single bucket. Then it’s terrible: you have to mint an IAM user or a federated role, walk them through the console, scope it down, deal with their MFA, and so on. All they wanted was to browse a folder.
s3xplorer started as a weekend POC to play with the AWS Go SDK v2 and the minio client, and turned into the tool I now use to expose a bucket to humans without giving them AWS credentials.
What it does
You give it a YAML config with S3 credentials and a bucket name. It exposes a small web UI where users can navigate the bucket as if it were a file tree, with a light/dark mode, optional prefix scoping, and (optionally) a “restore from Glacier” button for archived objects.
It’s deliberately limited: read-mostly, one bucket per instance, no upload, no delete from the UI. The point is to be the boring “give people a link” layer in front of S3.
v0.5.0: PostgreSQL changed everything
The version that made this tool actually useful is 0.5.0. Before that, every browse hit S3 directly — which is fine for a small bucket, painful for one with 100k+ objects, and expensive at scale (every ListObjectsV2 is a billable call).
The new architecture introduces a PostgreSQL backend:
- A background scanner periodically syncs the bucket into Postgres on a cron schedule.
- The web UI reads from the database, not from S3. Browsing is instant, even on huge buckets.
- Deletion sync is optional, so the database can be kept in lockstep with the bucket.
- The first scan can take a while; subsequent access is essentially free.
That trade-off — slightly stale data, instant UI — fits exactly the use case I built it for.
Configuring it
A config for a local MinIO instance, with the database backend on:
s3:
endpoint: http://127.0.0.1:9090
region: "us-east-1"
access_key: minioadminn
api_key: minioadminn
bucket: example
prefix: rando/
restore_days: 1
enable_glacier_restore: false
skip_bucket_validation: false
database:
url: "postgres://postgres:postgres@localhost:5432/s3xplorer?sslmode=disable"
scan:
enable_background_scan: true
cron_schedule: "0 2 * * *" # daily at 2 AM
enable_initial_scan: false
enable_deletion_sync: true
bucket_sync:
enable: true
sync_threshold: "24h"
delete_threshold: "168h"
max_retries: 3
log_level: info
Two things worth pointing out:
- The
prefixsetting scopes the UI to a sub-path. Combined with bucket policies, that’s how I share “just this folder” with someone. enable_glacier_restoreis off by default. If your bucket has Glacier objects and you want users to be able to trigger restores from the UI, flip it on.
Running it
Three ways, in order of friction:
# Binary
s3xplorer -f config.yaml
# Docker
docker run -v $(pwd)/config.yaml:/cfg.yaml -p 8081:8081 sgaunet/s3xplorer:latest
# Helm chart, for Kubernetes
helm repo add s3xplorer https://sgaunet.github.io/helm-s3xplorer/
helm repo update
helm search repo s3xplorer
For a local demo with MinIO, the README ships a docker-compose.yml that brings up MinIO and s3xplorer together. That’s the path I recommend if you just want to kick the tyres.
A few honest words about scope
The author of this tool is me, and I’ll be the first to say it’s not a competitor to mature S3 explorers. From the README: it started as a POC and “still needs refactor and improvements.” That’s still true. What it does have going for it:
- Dead simple deploy story (one binary, one config, optional Postgres)
- A genuinely useful niche: read-only, one-bucket-at-a-time UI for non-AWS humans
- The Glacier restore button, which I find myself reaching for surprisingly often
- A Helm chart that just works on a small cluster
- An IAM CloudFormation stack in
docs/so you can spin up the right scoped policy in one click
Where to find it
- Source: github.com/sgaunet/s3xplorer
- Helm chart: github.com/sgaunet/helm-s3xplorer
- License: MIT
If you’ve ever been asked “can you just send me the files in that bucket?” and groaned at the IAM dance ahead of you, give s3xplorer a try. Stand it up once, hand out the URL, move on with your day.