
Deploy public-buckets
Make your Railway Buckets public and geo-distributed.
webserver
Just deployed
url-cache
Just deployed
/data
example-bucket
Bucket
Just deployed
Deploy and Host Public Buckets

Railway Buckets provide an excellent offering to store static files, however there are 2 major limitations:
- They are not public-accessible
- They are not geo distributed (region of the bucket is fixed)
public-buckets template deploys a webserver that and wraps any S3 compatible buckets and makes a CDN like access layer. It's geo distributed, generates pre-signed URLs to avoid exposing buckets to public, and most importantly - utilizes HTTP 302 redirects to return content without proxying the data.
Dependencies for public-buckets Hosting
The backbone is cdn-s3-go, a super fast, open-sourced Go service that does the job. It has very little amount of external dependencies:

There is an optional Redis service, that provides a caching layer for pre-signed URLs. If you see that it negatively affects performance - just delete it.
Demo Project
There is a demo project available for this template. It serves the following URLs from demo bucket:
- https://public-buckets.up.railway.app/demo/images/eagle.jpg
- https://public-buckets.up.railway.app/demo/images/croissant.jpg
Each one image exists only in one regional bucket: one in US and another in EU. Guess which one is where.
Configuration
Template automatically creates an example bucket and example environment variables. There is the main gist of it:
Webserver config accepts list of bucket names as env variable CDN_BUCKET_PUBLIC_NAMES like lfs,avatars. In this template we have example.
It also accepts list of region aliases as env variable CDN_BUCKET_REGION_ALIASES like us,eu. Template deploys only us, you are free to change it.
For every bucket name in the list, it tries to load S3 / Railway Buckets compatible credentials:
CDN_BUCKET_ENDPOINT_{public_bucket_name}_{region_alias}
CDN_BUCKET_REGION_{public_bucket_name}_{region_alias}
CDN_BUCKET_NAME_{public_bucket_name}_{region_alias}
CDN_BUCKET_PATH_PREFIX_{public_bucket_name}_{region_alias}
CDN_BUCKET_ACCESS_KEY_ID_{public_bucket_name}_{region_alias}
CDN_BUCKET_SECRET_ACCESS_KEY_{public_bucket_name}_{region_alias}
Here for instance how demo project was linked:

See the full reference for variables in .env.example.
About Hosting public-buckets
Deploying a Go based docker image, that can be replicated across regions, as it's a stateless gateway. The gateway manages auth to Railway Buckets and acts like a public CDN layer. There is a Redis cache involved, but completely optional, it is included in the template by default, but can be removed in few clicks.
Common Use Cases
- Hosting static files for your next SaaS, for example - avatars and customer data
- Distribution of large blobs, for example, model weights or UGC content as part of the AI processing pipeline
- Upd.dev uses this CDN layer for Git hosting
Deployment Dependencies
- Docker image xlab/cdn-s3-go
- No other external dependencies
Why Deploy public-buckets on Railway?
Railway is a singular platform to deploy your infrastructure stack. Railway will host your infrastructure so you don't have to deal with configuration, while allowing you to vertically and horizontally scale it. In this case, infinite amount of S3 compatible buckets, balanced via Metal-hosted edge layer with little help of redirect magic.
By deploying public-buckets and using cdn-s3-go on Railway, you are enabling your own CDN layer to deliver static across the globe to customers, overseas AI infra, while keeping egress costs zero.
Who needs R2 after that!?
Template Content