# Configure an S3 compatible object storage provider for uploads

**URL:** https://meta.discourse.org/t/configure-an-s3-compatible-object-storage-provider-for-uploads/148916
**Category:** Self-Hosting
**Tags:** cdn, configuring, how-to, reference
**Created:** [April 22, 2020, 10:37pm UTC](https://meta.discourse.org/t/configure-an-s3-compatible-object-storage-provider-for-uploads/148916 "2020-04-22T22:37:37Z")
**Posts on this page:** 16
**Page:** 14

<div class="post-metadata">

### Author: ![Isambard](https://avatars.discourse-cdn.com/v4/letter/i/858c86/32.png) [@Isambard](https://meta.discourse.org/u/Isambard)
#### Post date: [October 28, 2025, 12:11pm UTC](https://meta.discourse.org/t/configure-an-s3-compatible-object-storage-provider-for-uploads/148916/496 "2025-10-28T12:11:57Z")

</div>

Anyone used SeaweedFS? With the uncertainty over MinIO, I’ve been looking at this option and will try it out to see if there are any compatibility issues with Discourse.

---

<div class="post-metadata">

### Author: ![tknospdr](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/tknospdr/32/529762_2.png) [@tknospdr](https://meta.discourse.org/u/tknospdr)
#### Post date: [November 19, 2025, 2:34pm UTC](https://meta.discourse.org/t/configure-an-s3-compatible-object-storage-provider-for-uploads/148916/497 "2025-11-19T14:34:03Z")

</div>

I got R2 working correctly by using this set of rules:

```plaintext
  ## This set of lines allows R2 S3 hosted files to be uploaded and downloaded..
  DISCOURSE_USE_S3: true
  DISCOURSE_S3_REGION: auto
  DISCOURSE_S3_ACCESS_KEY_ID: access-key-id
  DISCOURSE_S3_SECRET_ACCESS_KEY: access-key
  DISCOURSE_S3_CDN_URL: https://eufiles.technospider.com
  DISCOURSE_S3_BUCKET: exotics-unlimited
  DISCOURSE_S3_BACKUP_BUCKET: exotics-unlimited-backups
  DISCOURSE_BACKUP_LOCATION: s3
# DISCOURSE_CDN_URL: https://eufiles.technospider.com
  DISCOURSE_S3_ENDPOINT: https://71 ***** 5d4976.r2.cloudflarestorage.com
# DISCOURSE_INCLUDE_S3_UPLOADS_IN_BACKUPS: true
  DISCOURSE_S3_INSTALL_CORS_RULE: false

```

Once I commented out the CDN\_URL line things worked. I guess by the nature of the fact that R2 auto creates the CDN you don’t need that line and in fact adding it breaks stuff.  
I commented out the include images line just to keep my backup sizes down. I’m using the free tier at R2 and don’t want to go over my limit.

---

<div class="post-metadata">

### Author: ![pfaffman](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/pfaffman/32/120154_2.png) [@pfaffman](https://meta.discourse.org/u/pfaffman)
#### Post date: [November 19, 2025, 2:39pm UTC](https://meta.discourse.org/t/configure-an-s3-compatible-object-storage-provider-for-uploads/148916/498 "2025-11-19T14:39:49Z")

</div>

> [@tknospdr](#):
>
> I commented out the include images line just to keep my backup sizes down.

Right. You really don’t want to use `DISCOURSE_INCLUDE_S3_UPLOADS_IN_BACKUPS` unless you’re moving away from S3. It doesn’t make sense to download all the images from S3 to include them in a backup stored . . . on S3. I once left that enabled on an AWS bucket and had a big bill from downloading every single image every single day.

> [@tknospdr](#):
>
> ```plaintext
> DISCOURSE_CDN_URL: https://eufiles.technospider.com
> 
> ```

This is supposed to be a **separate** CDN that points to your **Discourse** server, not the S3 bucket. Some stuff, like avatars, and I’m not sure what else, is served from your server. The reason it didn’t work is you included your S3 CDN not the site CDN.

---

<div class="post-metadata">

### Author: ![tknospdr](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/tknospdr/32/529762_2.png) [@tknospdr](https://meta.discourse.org/u/tknospdr)
#### Post date: [November 19, 2025, 3:00pm UTC](https://meta.discourse.org/t/configure-an-s3-compatible-object-storage-provider-for-uploads/148916/499 "2025-11-19T15:00:38Z")

</div>

> [@pfaffman](#):
>
> This is supposed to be a **separate** CDN that points to your **Discourse** server, not the S3 bucket. Some stuff, like avatars, and I’m not sure what else, is served from your server. The reason it didn’t work is you included your S3 CDN not the site CDN.

You mean if you use 2 different companies? One for bucket and one for CDN? I’m not well versed on this so I need the info like I’m a 3rd grader…  
I know that when you create a “custom domain” in the R2 interface it acts as a CDN so that’s why I initially tried adding that line.

Anyway, it’s been working perfect for my test site and unless there’s something else that it’s supposed to be doing that it’s not I’d recommend the original post be updated to show that Cloudflare now works with Discourse.

---

<div class="post-metadata">

### Author: ![pfaffman](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/pfaffman/32/120154_2.png) [@pfaffman](https://meta.discourse.org/u/pfaffman)
#### Post date: [November 19, 2025, 3:04pm UTC](https://meta.discourse.org/t/configure-an-s3-compatible-object-storage-provider-for-uploads/148916/500 "2025-11-19T15:04:28Z")

</div>

> [@tknospdr](#):
>
> You mean if you use 2 different companies?

No. You can’t do that. There’s only one S3 key/secret. I was trying to contrive a reason to use include s3 uploads, but there is none.

> [@tknospdr](#):
>
> I know that when you create a “custom domain” in the R2 interface it acts as a CDN so that’s why I initially tried adding that line.

That’s for the S3 Bucket not for your site. There are two different variables `DISCOURSE_S3_CDN_URL` and `DISCOURSE_CDN_URL`. You are treating them as if they are the same. You can not use a CDN for the site, but the reason it didn’t work when you set that variable is that you gave it the wrong CDN.

---

<div class="post-metadata">

### Author: ![tknospdr](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/tknospdr/32/529762_2.png) [@tknospdr](https://meta.discourse.org/u/tknospdr)
#### Post date: [November 19, 2025, 7:02pm UTC](https://meta.discourse.org/t/configure-an-s3-compatible-object-storage-provider-for-uploads/148916/501 "2025-11-19T19:02:11Z")

</div>

Okay, I thought I had a slight grasp of what I was doing, but now I think I’m completely lost.

So what is the difference between S3 CDN and CDN?

Would it still work if I reversed which of those 2 I’ve commented out?

I noticed an odd issue with the background image of my welcome banner too, is that related at all to any of this?

> [@Creating a banner to display at the top of your site](https://meta.discourse.org/t/creating-a-banner-to-display-at-the-top-of-your-site/153718/27):
>
> Having an issue with my background image for the welcome banner. I’m using Cloudflare R2 S3 buckets for object storage on the site in question. When I upload a background image in the admin section it shows up correctly, if I click to show it full size it works. And if I right click and show image in new tab it works and using the public bucket URL: https://eufiles.technospider.com/original/1X/609c9563f4d8c7d229b495a2cb967782a63aa2df.jpeg What it injects into the…

---

<div class="post-metadata">

### Author: ![chapoi](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/chapoi/32/537252_2.png) [@chapoi](https://meta.discourse.org/u/chapoi)
#### Post date: [December 12, 2025, 8:55am UTC](https://meta.discourse.org/t/configure-an-s3-compatible-object-storage-provider-for-uploads/148916/502 "2025-12-12T08:55:48Z")

</div>

14 posts were split to a new topic: [Issues with AWS CDN and S3](https://meta.discourse.org/t/issues-with-aws-cdn-and-s3/391132)

---

<div class="post-metadata">

### Author: ![decryption128](https://avatars.discourse-cdn.com/v4/letter/d/a3d4f5/32.png) [@decryption128](https://meta.discourse.org/u/decryption128)
#### Post date: [January 31, 2026, 12:22am UTC](https://meta.discourse.org/t/configure-an-s3-compatible-object-storage-provider-for-uploads/148916/503 "2026-01-31T00:22:51Z")

</div>

Hi folks - just letting people know that Hetzner’s object storage seems to work pretty well. These are the settings I added to my app.yaml

```plaintext
DISCOURSE_USE_S3: true
DISCOURSE_S3_REGION: whatever
DISCOURSE_S3_INSTALL_CORS_RULE: false
DISCOURSE_S3_ENDPOINT: https://nbg1.your-objectstorage.com
DISCOURSE_S3_ACCESS_KEY_ID: xxxx
DISCOURSE_S3_SECRET_ACCESS_KEY: xxxx
DISCOURSE_S3_CDN_URL: xxxx
DISCOURSE_S3_BUCKET: discourseuploads
DISCOURSE_S3_BACKUP_BUCKET: discoursebackups
DISCOURSE_BACKUP_LOCATION: s3

```

Obviously, replace the following with your own settings:

```plaintext
DISCOURSE_S3_ENDPOINT: (use the URL from the Hetzner dashboard for the location you made your object storage bucket)
DISCOURSE_S3_ACCESS_KEY_ID: (self-explanatory)
DISCOURSE_S3_SECRET_ACCESS_KEY: (self-explanatory)
DISCOURSE_S3_CDN_URL: (use the CDN URL that pulls from your Hetzner bucket’s URL here)

```

Will keep an eye on it for the next few weeks/months on my test server, but so far so good.

---

<div class="post-metadata">

### Author: ![Lilly](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/lilly/32/575047_2.png) [@Lilly](https://meta.discourse.org/u/Lilly)
#### Post date: [May 20, 2026, 11:42am UTC](https://meta.discourse.org/t/configure-an-s3-compatible-object-storage-provider-for-uploads/148916/504 "2026-05-20T11:42:44Z")

</div>

> [@Discourse](#):
>
> ### Cloudflare
> 
> Cloudflare’s offering is incompatible. In testing, @fearlessfrog filed a ticket with Cloudflare and in December 2022 they said:
> 
> > [@](#):
> >
> > Files that you gzip are not currently handled correctly by R2. You have to upload uncompressed files. Cloudflare has transparent compression, they pick identity, gzip, or Brotli based on what the client can handle. This is a difference from S3.

just a note that this is no longer the case - Cloudflare has patched this and R2 buckets are now compatible with S3. i have external backups to Cloudflare R2 and just did a successful full restore to another server. (it’s also free up to 10GB / month)

just need the `bucket name` (for `s3 backup bucket`), `access key ID`, `secret access key` and `jurisdiction-specific endpoint` from Cloudflare R2 object storage to put into the Discourse s3 settings or `app.yml`/`web_only.yml` etc.

---

<div class="post-metadata">

### Author: ![pfaffman](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/pfaffman/32/120154_2.png) [@pfaffman](https://meta.discourse.org/u/pfaffman)
#### Post date: [May 20, 2026, 12:26pm UTC](https://meta.discourse.org/t/configure-an-s3-compatible-object-storage-provider-for-uploads/148916/505 "2026-05-20T12:26:04Z")

</div>

That’s great news! Someone should edit the OP accordingly.

---

<div class="post-metadata">

### Author: ![Lilly](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/lilly/32/575047_2.png) [@Lilly](https://meta.discourse.org/u/Lilly)
#### Post date: [May 20, 2026, 12:29pm UTC](https://meta.discourse.org/t/configure-an-s3-compatible-object-storage-provider-for-uploads/148916/506 "2026-05-20T12:29:03Z")

</div>

~~i have no idea how the new(ish) doc updating works - apparently they are stored here somewhere? [discourse/docs at main · discourse/discourse · GitHub](https://github.com/discourse/discourse/tree/main/docs) but i don’t see self-hosting docs. 🤷‍♀️~~ nevermind, i see the suggested edits link in the wiki edit page. i will suggest an update.

edit: update for Cloudflare R2 object storage has been submitted

---

<div class="post-metadata">

### Author: ![supermathie](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/supermathie/32/507518_2.png) [@supermathie](https://meta.discourse.org/u/supermathie)
#### Post date: [June 22, 2026, 6:15pm UTC](https://meta.discourse.org/t/configure-an-s3-compatible-object-storage-provider-for-uploads/148916/507 "2026-06-22T18:15:33Z")

</div>

A post was split to a new topic: [Avatars take a long time to load after moving to S3-compatible R2](https://meta.discourse.org/t/avatars-take-a-long-time-to-load-after-moving-to-s3-compatible-r2/405827)

---

<div class="post-metadata">

### Author: ![Lilly](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/lilly/32/575047_2.png) [@Lilly](https://meta.discourse.org/u/Lilly)
#### Post date: [July 2, 2026, 2:43am UTC](https://meta.discourse.org/t/configure-an-s3-compatible-object-storage-provider-for-uploads/148916/508 "2026-07-02T02:43:01Z")

</div>

i suggested an update - fixed all the broken links to the various sections in the OP contents, and updated the Cloudflare R2 configuration notes.

---

<div class="post-metadata">

### Author: ![chapoi](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/chapoi/32/537252_2.png) [@chapoi](https://meta.discourse.org/u/chapoi)
#### Post date: [July 2, 2026, 8:54am UTC](https://meta.discourse.org/t/configure-an-s3-compatible-object-storage-provider-for-uploads/148916/509 "2026-07-02T08:54:21Z")

</div>

Thank you 🙏

This could have been a boost so I didnt have to type more chars

---

<div class="post-metadata">

### Author: ![Thomas\_Rother](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/thomas_rother/32/423597_2.png) [@Thomas\_Rother](https://meta.discourse.org/u/Thomas_Rother)
#### Post date: [August 15, 2026, 9:21am UTC](https://meta.discourse.org/t/configure-an-s3-compatible-object-storage-provider-for-uploads/148916/510 "2026-08-15T09:21:11Z")

</div>

@chapoi @Lilly

In Europe, EU-DSGVO compliant S3 compatible storage can also be used with [hetzner.de](http://hetzner.de) . Within the EU they operate ISO/IEC 27001:2022-certified datacenters in Germany and Finland. Maybe this information can be added to the main list above.

# Example Configuration for [hetzner.de](http://hetzner.de)

| Configuration | Value | |
| --- | --- | --- |
| S3 endpoint | https://[datacenter].your-objectstorage.com | |
| S3 endpoint datacenter | [datacenter] = hel1 (Helsinki), fsn1(Falkenstein), nbg1 (Nuremberg) | |
| S3 access key ID | Hetzner S3 access key | |
| S3 secret access key | Hetzner S3 secret key (only displayed once during S3 storage creation) | |
| S3 upload bucket | Hetzner S3 bucket name | |
| Enable S3 uploads | true | |

Note that the warning about “The server is configured to upload files to S3, but there is no S3 CDN configured” must be ignored. [hetzner.de](http://hetzner.de) does not provide global CDN functionality yet. See [https://docs.hetzner.com/storage/general/which-storage-is-right-for-me](https://docs.hetzner.com/storage/general/which-storage-is-right-for-me) for details.

---

<div class="post-metadata">

### Author: ![kcahtoor](https://avatars.discourse-cdn.com/v4/letter/k/9de0a6/32.png) [@kcahtoor](https://meta.discourse.org/u/kcahtoor)
#### Post date: [September 15, 2026, 1:04am UTC](https://meta.discourse.org/t/configure-an-s3-compatible-object-storage-provider-for-uploads/148916/511 "2026-09-15T01:04:57Z")

</div>

> [@Discourse](#):
>
> Cloudflare R2  
> Depending on your needs (uploads or backups or both), these are the relevant settings to insert into your `app.yml` file or in your `Admin-All site settings` search for `S3`:
> 
> ```plaintext
> DISCOURSE_S3_UPLOAD_BUCKET: your-upload-bucket-name
>   
> 
> ```

This is going to fail when using `s3:upload_assets` because this process is looking for `DISCOURSE_S3_BUCKET`

[Previous page](https://meta.discourse.org/t/configure-an-s3-compatible-object-storage-provider-for-uploads/148916.md?page=13)
