Using S3 Object Storage
The OSL provides S3-compatible object storage backed by our Ceph cluster. Once we have created a bucket for your project and delivered your access keys, you can use any S3-compatible client to upload, download, and manage your data.
What you need
Your access key and secret key. We deliver these through the Secrets app on our Nextcloud instance at cloud.osuosl.org – never by email or chat. If you have not received them yet, or have lost them, contact us at support@osuosl.org.
The name of your bucket. Bucket names follow the scheme
<project>-<bucket>(for example,fooproject-backups).An S3-compatible client such as
s3cmd, the AWS CLI,rclone, or a library likeboto3.
Endpoint
All clients connect to our RADOS Gateway at:
Endpoint:
https://s3.osuosl.orgRegion: any value works; use
us-east-1if your client requires one.
We support path-style (https://s3.osuosl.org/<bucket>) and
virtual-hosted (https://<bucket>.s3.osuosl.org) bucket addressing.
Warning
Keep your secret key private. Anyone with both keys has full access to your buckets. If a key is exposed, contact us so we can rotate it.
s3cmd
s3cmd is a simple command-line client. Install it
from your distribution’s package manager (apt install s3cmd,
dnf install s3cmd) or with pip install s3cmd.
Create ~/.s3cfg with your keys:
[default]
access_key = YOUR_ACCESS_KEY
secret_key = YOUR_SECRET_KEY
host_base = s3.osuosl.org
host_bucket = %(bucket)s.s3.osuosl.org
use_https = True
Then use it:
$ s3cmd ls # list your buckets
2026-06-10 09:30 s3://fooproject-backups
$ s3cmd ls s3://fooproject-backups/ # list objects in a bucket
$ s3cmd put file.tar.gz s3://fooproject-backups/
$ s3cmd get s3://fooproject-backups/file.tar.gz
$ s3cmd sync ./localdir/ s3://fooproject-backups/localdir/
$ s3cmd del s3://fooproject-backups/file.tar.gz
AWS CLI
The AWS CLI works against our gateway by
pointing --endpoint-url at it. Configure a named profile:
$ aws configure --profile osl
AWS Access Key ID [None]: YOUR_ACCESS_KEY
AWS Secret Access Key [None]: YOUR_SECRET_KEY
Default region name [None]: us-east-1
Default output format [None]: json
Then pass the endpoint on each command (or set it once with
AWS_ENDPOINT_URL=https://s3.osuosl.org):
$ aws --profile osl --endpoint-url https://s3.osuosl.org s3 ls
$ aws --profile osl --endpoint-url https://s3.osuosl.org s3 ls s3://fooproject-backups/
$ aws --profile osl --endpoint-url https://s3.osuosl.org s3 cp file.tar.gz s3://fooproject-backups/
$ aws --profile osl --endpoint-url https://s3.osuosl.org s3 sync ./localdir/ s3://fooproject-backups/localdir/
rclone
rclone is handy for syncing and mounting. Add a
remote to ~/.config/rclone/rclone.conf:
[osl]
type = s3
provider = Ceph
access_key_id = YOUR_ACCESS_KEY
secret_access_key = YOUR_SECRET_KEY
endpoint = https://s3.osuosl.org
$ rclone lsd osl: # list buckets
$ rclone ls osl:fooproject-backups
$ rclone copy ./localdir osl:fooproject-backups/localdir
$ rclone sync ./localdir osl:fooproject-backups/localdir
boto3 (Python)
To access the service from Python, point boto3 at the endpoint:
import boto3
s3 = boto3.client(
"s3",
endpoint_url="https://s3.osuosl.org",
aws_access_key_id="YOUR_ACCESS_KEY",
aws_secret_access_key="YOUR_SECRET_KEY",
)
# Upload, download, and list objects
s3.upload_file("file.tar.gz", "fooproject-backups", "file.tar.gz")
s3.download_file("fooproject-backups", "file.tar.gz", "file.tar.gz")
for obj in s3.list_objects_v2(Bucket="fooproject-backups").get("Contents", []):
print(obj["Key"], obj["Size"])
Public Access and Listing
By default your bucket is private: objects can only be read with your keys, and the bucket contents cannot be listed anonymously. There are two separate things you may want to enable:
Public read of objects – lets anyone download a known object URL such as
https://fooproject-backups.s3.osuosl.org/file.tar.gz.Public listing – lets anyone list the objects in the bucket (the gateway returns an XML listing, not a browsable HTML index).
Warning
Only make a bucket or object public if the data is meant to be available to everyone. Public listing lets anyone enumerate every object in the bucket. Never store secrets or private data in a public bucket.
Making objects public with s3cmd
To make a single object publicly readable:
$ s3cmd setacl s3://fooproject-backups/file.tar.gz --acl-public
You can also set the ACL at upload time with -P / --acl-public:
$ s3cmd put -P file.tar.gz s3://fooproject-backups/
To make the whole bucket public, including all existing objects, add
--recursive:
$ s3cmd setacl s3://fooproject-backups --acl-public --recursive
To make something private again, use --acl-private (with --recursive to
apply it to existing objects).
Enabling public listing with a bucket policy
A public ACL on the bucket allows listing, but a bucket policy gives you finer
control and is easier to audit. The following policy makes every object in the
bucket downloadable and allows anonymous listing. Save it as
policy.json:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicRead",
"Effect": "Allow",
"Principal": "*",
"Action": ["s3:GetObject"],
"Resource": ["arn:aws:s3:::fooproject-backups/*"]
},
{
"Sid": "PublicList",
"Effect": "Allow",
"Principal": "*",
"Action": ["s3:ListBucket"],
"Resource": ["arn:aws:s3:::fooproject-backups"]
}
]
}
Apply it with s3cmd:
$ s3cmd setpolicy policy.json s3://fooproject-backups
or with the AWS CLI:
$ aws --profile osl --endpoint-url https://s3.osuosl.org \
s3api put-bucket-policy --bucket fooproject-backups --policy file://policy.json
If you only want public downloads (a CDN-style bucket where URLs are shared but
the contents aren’t enumerable), include just the PublicRead statement and
omit PublicList.
To remove the policy and make the bucket private again:
$ s3cmd delpolicy s3://fooproject-backups
A browsable HTML listing
The gateway only returns the raw XML listing described above. If you want a
nice browsable index in a web browser – like the one the OpenVox project uses for its package repository – you
can drop a small single-page app into the bucket that renders the XML listing
client-side. We recommend aws-s3-bucket-browser, which is a single
index.html file with no server-side component.
First make sure the bucket allows public listing and downloads, using the
PublicRead + PublicList bucket policy from the previous section.
Then download index.html from the project and edit the config block near
the top of the file. The only required setting is bucketUrl, which points at
your bucket’s REST endpoint:
const config = {
title: 'fooproject',
bucketUrl: 'https://s3.osuosl.org/fooproject-backups',
// rootPrefix: 'subfolder/', // only list a subfolder
// pageSize: 50,
// defaultOrder: 'name-asc', // (name|size|dateModified)-(asc|desc)
}
The page hides its own index.html from the listing by default, so the
browser file won’t show up among your objects.
Upload it to the bucket as a public object:
$ s3cmd put -P --mime-type=text/html index.html s3://fooproject-backups/
The listing is then available in a browser at the object’s URL:
https://s3.osuosl.org/fooproject-backups/index.html
Because index.html is served from the same bucket it lists, the requests are
same-origin and no CORS configuration is needed. If you serve the page from a
different host (for example behind your own domain via bucketMaskUrl), add a
CORS rule allowing GET from that origin to the bucket.
Notes and Limits
Creating buckets: We create your project’s buckets for you. If you need an additional bucket, contact support@osuosl.org rather than creating it yourself – bucket names are shared across the whole gateway and must follow the
<project>-<bucket>naming scheme.Object size: Use multipart uploads for large objects.
s3cmd, the AWS CLI, andrcloneall do this automatically.Quotas: We don’t normally set quotas, but please be mindful of your usage. If you expect to store a large amount of data, let us know in advance.
Getting Help
If you run into trouble, or need a new bucket or a key rotated, email us at support@osuosl.org.