# Using Discourse with Cloudflare: Best Practices

**URL:** https://meta.discourse.org/t/using-discourse-with-cloudflare-best-practices/293405
**Category:** Self-Hosting
**Tags:** how-to, cloudflare
**Created:** [January 30, 2024, 2:56am UTC](https://meta.discourse.org/t/using-discourse-with-cloudflare-best-practices/293405 "2024-01-30T02:56:10Z")
**Posts on this page:** 20
**Page:** 1

<div class="post-metadata">

### Author: ![Discourse](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/discourse/32/148734_2.png) [@Discourse](https://meta.discourse.org/u/Discourse)
#### Post date: [January 30, 2024, 2:56am UTC](https://meta.discourse.org/t/using-discourse-with-cloudflare-best-practices/293405/1 "2024-01-30T02:56:10Z")

</div>

# Using Discourse with Cloudflare

> 🔖 This guide explains how to configure and use Discourse with Cloudflare, including security best practices and troubleshooting tips.
> 
> 🙋 Required user level: Administrator
> 
> ℹ Console access is required for self-hosted installations

## Summary

Cloudflare can enhance your Discourse instance with improved performance through CDN, additional security layers like DDoS protection, and HTTPS support. This guide covers the setup process and best practices for optimal configuration.

## Why use Cloudflare with Discourse

Using Cloudflare with your Discourse instance provides several key benefits:

- **Performance** : Cloudflare’s CDN can improve worldwide access to common assets, enhancing user experience globally ([source](https://meta.discourse.org/t/enable-a-cdn-for-your-discourse/14857/1))
- **Security** : Additional protection layers including:
  - DDoS protection ([source](https://developers.cloudflare.com/ddos-protection/))
  - HTTPS support ([source](https://developers.cloudflare.com/ssl/origin-configuration/ssl-modes/full-strict/)) (alternative to [Discourse’s Let’s Encrypt setup](https://meta.discourse.org/t/set-up-https-support-with-lets-encrypt/40709))

> ⚠ For self-hosted installations, while Cloudflare offers these benefits, it adds complexity to your setup.

## Setting up Cloudflare

1. Familiarize yourself with [Cloudflare Fundamentals](https://developers.cloudflare.com/fundamentals/)
2. Follow the [setup directions](https://developers.cloudflare.com/fundamentals/setup/) to configure Cloudflare for your domain and get the [security, performance, and reliability benefits](https://developers.cloudflare.com/fundamentals/concepts/how-cloudflare-works/)

## Configuration best practices

### DNS settings

- Ensure DNS records pointing to your Discourse instance are proxied
- Access DNS settings at `dash.cloudflare.com/?to=/:account/:zone/dns`

### SSL/TLS configuration

- Set encryption mode to “Full (strict)”
- Access SSL/TLS settings at `dash.cloudflare.com/?to=/:account/:zone/ssl-tls`

> ⚠ Incorrect SSL/TLS configuration may cause redirect loops

### Caching configuration

- Set caching level to “Standard”
- Access caching settings at `dash.cloudflare.com/?to=/:account/:zone/caching/configuration`

### Cache rules

Cloudflare has deprecated Page Rules in favor of their modern [Rules](https://developers.cloudflare.com/rules/) system. Create the following using **Cache Rules** at `dash.cloudflare.com/?to=/:account/:zone/rules`:

- Set Cache Level to “Bypass” for `community.example.com/session/*`
- Configure URL normalization settings to normalize incoming URLs

### Network settings

The network settings at `dash.cloudflare.com/?to=/:account/:zone/network` generally do not affect Discourse functionality. Discourse does not use WebSockets, gRPC, or the `CF-IPCountry` / `True-Client-IP` headers. These settings can be left at their defaults unless other software on the same domain requires specific configuration.

### WAF (Web Application Firewall) settings

If your Cloudflare plan supports Managed Rules, create the following:

1. Skip WAF on post creation/edits:

```ruby
(starts_with(http.request.uri.path, "/posts") and http.request.method in {"POST" "PUT"})

```

1. For [Data Explorer](https://meta.discourse.org/t/32566?silent=true) plugin users, skip WAF on admin queries:

```ruby
((http.request.uri.path contains "/admin/plugins/explorer/queries/" or http.request.uri.path contains "/admin/plugins/discourse-data-explorer/queries/") and http.request.method eq "PUT")

```

For both rules:

- Choose “Skip all remaining rules”
- Enable “Log matching requests”

> ℹ If you are on a Business plan or above, you can use the `matches` regex operator for more precise matching. The `starts_with` and `contains` operators used above work on all plans including Free and Pro.

Access WAF settings at `dash.cloudflare.com/?to=/:account/:zone/firewall/managed-rules`

### Content optimization

Configure the following at `dash.cloudflare.com/?to=/:account/:zone/speed/optimization`:

- Enable Brotli
- Disable Rocket Loader™

> ⚠ Discourse frequently receives site down reports [due to Rocket Loader™ being enabled](https://meta.discourse.org/search?q=rocket%20loader%20order%3Alatest)

## Additional configuration for self-hosted installations

To ensure correct IP address forwarding, add the following to the templates section in your `containers/app.yml`:

```yaml
- "templates/cloudflare.template.yml"

```

> ⚠ After adding the template, you must rebuild your container with `./launcher rebuild app` for the changes to take effect.

Related: [How do you setup Cloudflare?](https://meta.discourse.org/t/how-do-you-setup-cloudflare/32258/6)

## Support resources

- [Cloudflare Community Support](https://community.cloudflare.com/t/using-discourse-with-cloudflare-best-practices/602890)
- [Search Discourse Meta for Cloudflare-related issues](https://meta.discourse.org/search?q=cloudflare)

## Troubleshooting

### Content Security Policy (CSP) issues

If you encounter CSP errors:

- Verify that Rocket Loader is disabled
- Check that scripts are properly added to the `content security policy script src` site setting

### OneBox functionality

If OneBox is being blocked:

- Check if Super Bot Fight Mode is enabled
- Adjust the “Definitely automated” setting if it’s set to “Managed” or “Block”
- Consider creating a custom WAF rule for the OneBox user agent

> [@Discourse](#):
>
> ## Special Thanks to…
> 
> @tcloonan for authoring this topic 👏🏻

> Last edited by @nat 2025-05-06T09:48:57Z
> 
> > **Check document**
> >
> > Perform check on document:

---

<div class="post-metadata">

### Author: ![Kevin7](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/kevin7/32/110326_2.png) [@Kevin7](https://meta.discourse.org/u/Kevin7)
#### Post date: [February 12, 2024, 6:22pm UTC](https://meta.discourse.org/t/using-discourse-with-cloudflare-best-practices/293405/2 "2024-02-12T18:22:30Z")

</div>

Good morning,

Thank you for this guide which I followed to the letter but I encounter a problem, each time I activate Cloudflare in my console I get an error with the CSP which displays to me (Refused to execute inline script because it violates the following Content Security Policy directive: "script-src) and after having indicated to me the urls present in my CSP: (Either the ‘unsafe-inline’ keyword, a hash (‘sha256-VCiGKEA…=’), or a nonce (‘nonce-…’) is required to enable inline execution.

I tried looking everywhere but I can’t find a solution other than disabling the proxy which solves my problem?

THANKS.

---

<div class="post-metadata">

### Author: ![nat](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/nat/32/235063_2.png) [@nat](https://meta.discourse.org/u/nat)
#### Post date: [February 14, 2024, 8:45am UTC](https://meta.discourse.org/t/using-discourse-with-cloudflare-best-practices/293405/3 "2024-02-14T08:45:34Z")

</div>

Can you check if rocket loader is turned off?

Another thing is to check that the scripts are appropriately added to `content security policy script src` site setting.

If none of these are working out, I suggest reaching out to Cloudflare @ [https://community.cloudflare.com/t/using-discourse-with-cloudflare-best-practices/602890](https://community.cloudflare.com/t/using-discourse-with-cloudflare-best-practices/602890).

---

<div class="post-metadata">

### Author: ![Richie](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/richie/32/115110_2.png) [@Richie](https://meta.discourse.org/u/Richie)
#### Post date: [February 14, 2024, 10:46am UTC](https://meta.discourse.org/t/using-discourse-with-cloudflare-best-practices/293405/4 "2024-02-14T10:46:27Z")

</div>

Thanks for this @nat and @tcloonan

This has been on my list of things to do for a year or two, but I’ve been put off by the age of some of the older threads on this subject 😃

Any issues or special things for people using AWS S3 for storage and for backups? 🤔

---

<div class="post-metadata">

### Author: ![TheDarkWizard](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/thedarkwizard/32/177913_2.png) [@TheDarkWizard](https://meta.discourse.org/u/TheDarkWizard)
#### Post date: [February 14, 2024, 11:20am UTC](https://meta.discourse.org/t/using-discourse-with-cloudflare-best-practices/293405/5 "2024-02-14T11:20:17Z")

</div>

Do you still need the cloudflare template in app.yml for true IP addresses or has that changed over the years?

---

<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: [February 26, 2024, 2:40pm UTC](https://meta.discourse.org/t/using-discourse-with-cloudflare-best-practices/293405/6 "2024-02-26T14:40:14Z")

</div>

> [@TheDarkWizard](#):
>
> Do you still need the cloudflare template in app.yml for true IP addresses or has that changed over the years?

Yes. You do need the cloudflare template. Without it, all traffic will appear to come from cloudflare’s servers rather than the user’s browser IP.

I don’t see it mentioned in the OP, which seems like a glaring omission. How did you infer that you needed it?

> [@How do you setup Cloudflare?](https://meta.discourse.org/t/how-do-you-setup-cloudflare/32258/6):
>
> add `cloudflare.template.yml` to the end of the templates section in `app.yml`.

---

<div class="post-metadata">

### Author: ![TheDarkWizard](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/thedarkwizard/32/177913_2.png) [@TheDarkWizard](https://meta.discourse.org/u/TheDarkWizard)
#### Post date: [February 26, 2024, 2:50pm UTC](https://meta.discourse.org/t/using-discourse-with-cloudflare-best-practices/293405/7 "2024-02-26T14:50:50Z")

</div>

> [@pfaffman](#):
>
> I don’t see it mentioned in the OP, which seems like a glaring omission. How did you infer that you needed it?

Hi! Been around since 2014 (some years mostly silent) but have been working our getting our community migrated over since 2020 with a custom importer, and we are working on the second version of our in-house plugin to insert and enable bbob as a bbcode engine into Discourse. You can follow our progress here: [GitHub - RpNation/bbcode: RpNation's Official BBCode Implementation for Discourse · GitHub](https://github.com/rpnation/bbcode)

I’ve been breathing this software for a bit now. We do use Cloudflare, so I’ve been re-researching what if any issues it has with discourse, since we are now at the stage where I can start worrying about less vital things that are not considered blockers.

@nat Could you add an edit about the template for self-hosted instances!

---

<div class="post-metadata">

### Author: ![nat](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/nat/32/235063_2.png) [@nat](https://meta.discourse.org/u/nat)
#### Post date: [February 27, 2024, 9:55am UTC](https://meta.discourse.org/t/using-discourse-with-cloudflare-best-practices/293405/9 "2024-02-27T09:55:39Z")

</div>

> [@TheDarkWizard](#):
>
> @nat Could you add an edit about the template for self-hosted instances!

Done, thank you both for pointing this out!

---

<div class="post-metadata">

### Author: ![terraboss](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/terraboss/32/381157_2.png) [@terraboss](https://meta.discourse.org/u/terraboss)
#### Post date: [April 23, 2024, 1:35pm UTC](https://meta.discourse.org/t/using-discourse-with-cloudflare-best-practices/293405/10 "2024-04-23T13:35:49Z")

</div>

> [@Discourse](#):
>
> **Content Optimization** should have Brotli turned on, and **Rocket Loader™ off**. [Go here to set Content Optimization](https://dash.cloudflare.com/?to=/:account/:zone/speed/optimization). ⚠ Discourse gets plenty site down reports [due to Rocket Loader™ being on](https://meta.discourse.org/search?q=rocket%20loader%20order%3Alatest).

Thank you very much! That was probably also the reason why my site was suddenly no longer accessible. I must have played with the Cloudflare settings a bit too much.

Since my old domain provider only supported DNSSec inadequately & incorrectly, I had to look for something new. That’s when Cloudflare came to mind. The free plan is completely sufficient for me. It’s a shame that the tariffs don’t even scale reasonably to the requirements.

---

<div class="post-metadata">

### Author: ![shawa](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/shawa/32/426315_2.png) [@shawa](https://meta.discourse.org/u/shawa)
#### Post date: [June 27, 2024, 7:50pm UTC](https://meta.discourse.org/t/using-discourse-with-cloudflare-best-practices/293405/11 "2024-06-27T19:50:39Z")

</div>

> [@pfaffman](#):
>
> Yes. You do need the cloudflare template. Without it, all traffic will appear to come from cloudflare’s servers rather than the user’s browser IP.

Is it adding to this location?

 ![image](https://global.discourse-cdn.com/meta/original/4X/b/6/3/b63c862f6bc9f534b5f01f0a3aad3df9669796b9.png)

---

<div class="post-metadata">

### Author: ![Crius](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/crius/32/317214_2.png) [@Crius](https://meta.discourse.org/u/Crius)
#### Post date: [August 8, 2024, 3:36pm UTC](https://meta.discourse.org/t/using-discourse-with-cloudflare-best-practices/293405/12 "2024-08-08T15:36:58Z")

</div>

Just for accuracy, the query for the WAF exclusion is:

`(http.request.uri.path eq "/posts(/[0-9]+)?" and http.request.method in {"POST" "PUT"})`

 ![image](https://global.discourse-cdn.com/meta/original/4X/9/7/c/97c1e6a1dc1fb95cfcc153bca3f0135e94d048f2.png)

You can copy-paste it if you click on the `Edit expression` on the left instead of using the form selection.

Noticed today as I updated and suddenly half the forum wasn’t working due to Auto Minify 😩

Edit: just noticed this is a wiki post. Silly me, I have edited the initial post.

---

<div class="post-metadata">

### Author: ![Can](https://avatars.discourse-cdn.com/v4/letter/c/9dc877/32.png) [@Can](https://meta.discourse.org/u/Can)
#### Post date: [November 4, 2024, 11:33am UTC](https://meta.discourse.org/t/using-discourse-with-cloudflare-best-practices/293405/13 "2024-11-04T11:33:37Z")

</div>

SSL/TLS encryption mode Full (strict). Will there be a problem if it is not closed? Won’t automatic SSL be defined anyway?

 ![The image depicts a screenshot of the Cloudflare SSL/TLS encryption mode settings, specifically highlighting that it is currently set to "Off (not secure)". (Captioned by AI)](https://global.discourse-cdn.com/meta/original/4X/8/c/0/8c05a6197c78b90c247f877b7e6639c8bcbe6805.png)

---

<div class="post-metadata">

### Author: ![stance455](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/stance455/32/255345_2.png) [@stance455](https://meta.discourse.org/u/stance455)
#### Post date: [November 8, 2024, 10:15am UTC](https://meta.discourse.org/t/using-discourse-with-cloudflare-best-practices/293405/14 "2024-11-08T10:15:41Z")

</div>

Just to add to this, seems the OneBox functionality is being blocked when Super Bot Fight Mode is on and the setting Definitely automated is set to Managed or block..

You can get around this by setting up a custom WAF rule for the Onebox user agent but perhaps there is a more secure way of doing this?

---

<div class="post-metadata">

### Author: ![thoka](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/thoka/32/115652_2.png) [@thoka](https://meta.discourse.org/u/thoka)
#### Post date: [December 3, 2024, 6:30am UTC](https://meta.discourse.org/t/using-discourse-with-cloudflare-best-practices/293405/15 "2024-12-03T06:30:23Z")

</div>

Related to

> [@Rebuild goes into a loop](https://meta.discourse.org/t/rebuild-goes-into-a-loop/339731/10):
>
> As an aside I simply input the cloudflare template at the bottom of app.yml as directed, but launcher came up with a syntax error. I removed it and all is fine.

this part might need some better wording:

> [@Discourse](#):
>
> To ensure the correct IP address gets sent to Discourse, you will want to add the following line to the end of your `containers/app.yml`.
> 
> ```plaintext
> cloudflare.template.yml
> 
> ```

@supermathie Suggestion:

> you will want to add the following line to the end of your templates section in `containers/app.yml`.

as illustrated in [Using Discourse with Cloudflare: Best Practices - #11 by shawa](https://meta.discourse.org/t/using-discourse-with-cloudflare-best-practices/293405/11)

At best, a link to a general how-to about templates in server configuration could be provided also, which I was not able to find at first sight.

---

<div class="post-metadata">

### Author: ![LotusJeff](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/lotusjeff/32/477888_2.png) [@LotusJeff](https://meta.discourse.org/u/LotusJeff)
#### Post date: [March 18, 2025, 10:35pm UTC](https://meta.discourse.org/t/using-discourse-with-cloudflare-best-practices/293405/20 "2025-03-18T22:35:29Z")

</div>

I would suggest turning off AI bots within Cloudflare. This can be found under security-\>bots-\>block AI bots.

The AI bots were hammering my site with 30K to 40K page views daily. After turning on this filter, my AI bot traffic significantly dropped.

 ![The bar chart depicts site traffic distributions, segmented into categories like Logged-in, Anonymously, Known Crawler, and Other, with varying traffic volumes across different categories. (Captioned by AI)](https://global.discourse-cdn.com/meta/original/4X/2/6/6/266dd48103e72b9d6431e083de893ae0ed5b4ff0.png)

---

<div class="post-metadata">

### Author: ![majorjc\_MS](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/majorjc_ms/32/498912_2.png) [@majorjc\_MS](https://meta.discourse.org/u/majorjc_MS)
#### Post date: [April 16, 2025, 2:27am UTC](https://meta.discourse.org/t/using-discourse-with-cloudflare-best-practices/293405/21 "2025-04-16T02:27:54Z")

</div>

> [@Discourse](#):
>
> ## Additional configuration for self-hosted installations
> 
> To ensure correct IP address forwarding, add the following to the templates section in your `containers/app.yml`:
> 
> ```plaintext
> cloudflare.template.yml
> 
> ```

The above code should be changed to:

```plaintext
 - "templates/cloudflare.template.yml"

```

thanks,  
Major

---

<div class="post-metadata">

### Author: ![MichaIng](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/michaing/32/251089_2.png) [@MichaIng](https://meta.discourse.org/u/MichaIng)
#### Post date: [May 2, 2025, 5:43pm UTC](https://meta.discourse.org/t/using-discourse-with-cloudflare-best-practices/293405/22 "2025-05-02T17:43:51Z")

</div>

Is it really true that WebSockets support should be enabled in Cloudflare?

Worked well for us without for years, and as far as I could find info here on the forum, Discourse does not make any use of WebSockets.

---

<div class="post-metadata">

### Author: ![ivette\_limon](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/ivette_limon/32/501759_2.png) [@ivette\_limon](https://meta.discourse.org/u/ivette_limon)
#### Post date: [May 4, 2025, 8:27pm UTC](https://meta.discourse.org/t/using-discourse-with-cloudflare-best-practices/293405/23 "2025-05-04T20:27:50Z")

</div>

i dont understand if i have to do this

---

<div class="post-metadata">

### Author: ![nat](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/nat/32/235063_2.png) [@nat](https://meta.discourse.org/u/nat)
#### Post date: [May 6, 2025, 9:58am UTC](https://meta.discourse.org/t/using-discourse-with-cloudflare-best-practices/293405/24 "2025-05-06T09:58:04Z")

</div>

You are right. I don’t believe we use Websockets.

I’ve removed it, and also updated the template snippet from the user above.

---

<div class="post-metadata">

### Author: ![MichaIng](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/michaing/32/251089_2.png) [@MichaIng](https://meta.discourse.org/u/MichaIng)
#### Post date: [May 7, 2025, 5:45pm UTC](https://meta.discourse.org/t/using-discourse-with-cloudflare-best-practices/293405/25 "2025-05-07T17:45:09Z")

</div>

While on it, I think the whole Network settings are irrelevant for Discourse:

- IPv6 compatibility cannot be disabled anymore, and of course Discourse does not depend on it, but can perfectly run on an IPv4-only system.
- IP Geolocation adds the `CF-IPCountry` header to requests, which is however not used by Discourse. It uses its own (optional) MaxMind feature.
- Network Error Logging adds the [Report-To](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Report-To) response header, which browsers can use to report errors to. It is however deprecated, and even that the feature can be enabled with all Cloudflare plans, the dashboard element to actually view the reports is available only with Enterprise plan. So in this case for some old browsers it might just be a privacy regression and network overhead.
- Onion Routing enhances privacy for requests coming from the Tor network. Discourse won’t care or even know this.
- The Pseudo IPv4 feature might even be needed if the host runs some software, like ancient analytics or similar, which supports IPv4 addresses only. The proxy headers of Cloudflare, like `Cf-Connecting-IP` (or others, depending on what one configures) can then be adjusted to have a moreless unique IPv4 address, instead of the actual IPv6 address of the client, to work around the fact that IPv6 support for client-\>Cloudflare requests cannot be disabled anymore. Again, Discourse won’t care. I mean it would be a problem for e.g. GeoIP detection, but the feature is disabled by default, and admins of course should enable it only, if strictly required by whichever software they run, accepting the downside of non-true client IPs. It can be also configured to only add a new header with the pseudo IPv4 address, and analytics (or whatever) requests can then rewrite client IP headers where needed, while requests to Discourse would not be affected. In any case, for Discourse functionality in general, the feature is irrelevant.
- True-Client-IP Header adds just this header in addition to `CF-Connecting-IP` and `X-Forwarded-For`. Discourse does not make use of it, also the Discourse config template uses `CF-Connecting-IP` instead. So it has no effect.
- gRPC is not used by Discourse, but having Cloudflare enabled to forward gRPC requests does not hurt either, same as with WebSockets. Both might be needed enabled for other software running on the same Cloudflare domain.
- Maximum Upload Size 100 MB is default and minimum. Larger upload sizes require Business or Enterprise plans, and Discourse won’t break if Cloudflare allows larger uploads.

The only thing I am not sure about whether it can have an effect is Response Buffering. And I cannot test as it is an Enterprise-only feature. But I cannot imagine that the client cares whether packets are streamed form CF edge as they come in, or sent in one chunk ones compete at the edge. For cached data (cached at Cloudflare I mean), this is done always anyway, and there is does not cause issues, at least. This feature only affects non-cached data.

So basically I would remove the whole “Network settings” section as something which is irrelevant for Cloudflare functionality, but other software might require certain settings or admins might prefer them a certain way, and should know that Discourse will function in any case.

[Next page](https://meta.discourse.org/t/using-discourse-with-cloudflare-best-practices/293405.md?page=2)
