Introduction
If you don’t know what Hetzner is, you’re missing out. It is a cloud provider very similar to Digital Ocean, but with incredibly cheap prices. Currently, it’s my first choice when it comes to deploying my side projects.
While Hetzner doesn’t have as many features as Digital Ocean, they have the important ones. And today I’d like to talk about one in particular, the Object Storage. It’s basically a wrapper for AWS S3 with cheap prices and none of the complexity to set up.
So, if you want to try Rails Active Storage with Hetzner, I’m going to show you how easy it is to set up.
Prerequisites
- Rails 6.0 or higher
- A Hetzner account
- Basic understanding of Rails Active Storage
Table of Contents
- Creating a Bucket
- Generating Credentials
- Configuring Your Rails Application
- Testing Your Configuration
- Security Considerations
Creating a Bucket
The first thing you have to do is go to your Hetzner account and create a new bucket, by clicking on Object Storage on the sidebar then “Create Bucket” on the right top corner.

Navigate to the Object Storage section and click ‘Create Bucket’
Next, you’ll see this modal asking to select location, input a name (this will be important) for your bucket which will be also used as URL. For object lock, you can leave it as disabled, and in visibility, you can select public (read-only).

Configure your bucket settings: select location, name, and visibility
That’s it, the bucket is ready for you to use it. But before you can set up your app to use it, we need to generate credentials, which is also very easy.
Generating Credentials
When you click on your bucket, you’ll be redirected to an overview page and in that page, you’ll click on “Actions” -> “Generate Credentials”. You’ll be prompted to input a description for those credentials and that’s it. Copy both access key and secret key into a safe place.

Generate and securely store your access and secret keys
Configuring Your Rails Application
Now, we need to save those credentials somewhere in the application. You can either use the dotenv gem, which I don’t recommend for secrets, or you can use Rails' built-in credentials system.
I’m going to use Rails' credentials system. Let’s use the Rails commands to set the secrets:
bin/rails credentials:edit
Save your keys exactly like this:
hetzner:
access_key_id: YOUR_ACCESS_KEY
secret_access_key: YOUR_SECRET_KEY
Now let’s edit your config/storage.yml
file:
hetzner:
service: S3 # YES, this is correct! Hetzner is S3 compatible, remember?
endpoint: https://hel1.your-objectstorage.com # Format: https://<region>.your-objectstorage.com
access_key_id: <%= Rails.application.credentials.dig(:hetzner, :access_key_id) %>
secret_access_key: <%= Rails.application.credentials.dig(:hetzner, :secret_access_key) %>
region: eu-central # if you selected Finland as location
bucket: <the name you gave your bucket when creating it>
Note: The endpoint URL format varies by region. For example:
- Finland:
https://hel1.your-objectstorage.com
- Germany:
https://fsn1.your-objectstorage.com
- USA:
https://us1.your-objectstorage.com
The last part is to change your config/environments/production.rb file to use the new Hetzner configuration you just added:
# Store uploaded files on the local file system (see config/storage.yml for options).
config.active_storage.service = :hetzner
Testing Your Configuration
To verify your configuration is working correctly, you can use the Rails console:
# Start the Rails console
rails c
# Test the connection
ActiveStorage::Blob.service.exist?("test.txt")
If this returns false
(which is expected for a non-existent file), your connection is working properly.
Security Considerations
When using public buckets, consider the following security measures:
- Access Control: Even with a public bucket, you can still control access through your application logic.
- File Validation: Implement strict file type and size validation in your models.
- Expiring URLs: For sensitive files, consider using expiring URLs instead of public access.
Conclusion
That’s it! Now all your files uploaded using Active Storage will be stored in your Hetzner bucket. This setup provides a cost-effective alternative to AWS S3 while maintaining compatibility with Rails Active Storage.
For more information, check out: