# Full site CDN acceleration for Discourse

**URL:** https://meta.discourse.org/t/full-site-cdn-acceleration-for-discourse/21467
**Category:** Self-Hosting
**Tags:** cdn, explanation
**Created:** [October 24, 2014, 6:17am UTC](https://meta.discourse.org/t/full-site-cdn-acceleration-for-discourse/21467 "2014-10-24T06:17:57Z")
**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: [October 24, 2014, 6:17am UTC](https://meta.discourse.org/t/full-site-cdn-acceleration-for-discourse/21467/1 "2014-10-24T06:17:58Z")

</div>

[Fastly](http://www.fastly.com/) , [CloudFlare](https://www.cloudflare.com) and a few other CDNs offer a mode where they accelerate dynamic content.

In a nutshell you point your domain IP address at the CDN and the CDN will intelligently decide how to deal with the request.

- Static content can be easily served from cache
- Dynamic content can be routed to the site.

This provides some advantages over only shipping static assets which is covered in [the CDN howto](https://meta.discourse.org/t/enable-a-cdn-for-your-discourse/14857).

- You can elect for “[shielding](http://www.fastly.com/products/origin-shield/)” that protects your site from traffic spikes.
- Dynamic content can be accelerated using techniques like delta compression. (note: in general our payload fits in 1 RTT so this has less of an impact)
- SSL negotiation can happen at the edge cutting on expensive round trips for negotiation.

If you enable full site acceleration with a CDN it is critical you follow 3 rules

1. The “message bus” **must** be served from the origin.

2. You need to set up X-Forwarded-For trust. For Cloudflare, add `cloudflare.template.yml` to your `app.yml` file.

3. Be extra careful with techniques that apply optimisation to the site, stuff like Rocket Loader can stop Discourse from working. Discourse is already heavily optimised, this is not needed.

To serve “[long polling](http://en.wikipedia.org/wiki/Comet_%28programming%29)” requests from a different domain, set the hidden site setting `long_polling_base_url` to the origin server. This is best configured by adding the `DISCOURSE_LONG_POLLING_BASE_URL` environment variable in your `app.yml`, or via the Rails console.

For example, if your site is on “[http://forum.example.com](http://forum.example.com)” you should set up **`http://forum-direct.example.com/`** to plug into the site setting. If you don’t your site will be broken.

If you are fronting Discourse using Varnish you probably want to follow the same trick here and bypass Varnish for the message bus requests.

### Boring technical notes:

Achieving a working message bus on a completely different domain is quite challenging. Our message bus is aware of which user is polling, the other domain may have no cookie set up so untouched there are two issues. Firstly, you can’t even make standard ajax requests cross domain without a huge [CORS](http://en.wikipedia.org/wiki/Cross-origin_resource_sharing) dance.

Secondly, we needed a mechanism to inform the other domain who the user is so we can poll for the correct information.

When long polling base url is changed, Discourse ships an extra meta tag that shares a “cross domain” auth token. This token is passed using a custom header back to the message bus. The token expires after 7 days or as soon as the user logs off.

You can see most of the implementation here: [FEATURE: allow long polling to go to a different url · discourse/discourse@aa9b3bb · GitHub](https://github.com/discourse/discourse/commit/aa9b3bb35accce498438e22344a3c352a9bc6592)

> Last edited by @JammyDodger 2024-05-25T11:15:40Z
> 
> > **Check document**
> >
> > Perform check on document:

---

<div class="post-metadata">

### Author: ![fantasticfears](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/fantasticfears/32/119608_2.png) [@fantasticfears](https://meta.discourse.org/u/fantasticfears)
#### Post date: [October 30, 2014, 1:24am UTC](https://meta.discourse.org/t/full-site-cdn-acceleration-for-discourse/21467/2 "2014-10-30T01:24:05Z")

</div>

> [@sam](#):
>
> in general our paylod fits in 1 RTT

I don’t know what it means… fits in 1 RTT?

---

<div class="post-metadata">

### Author: ![sam](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/sam/32/102149_2.png) [@sam](https://meta.discourse.org/u/sam)
#### Post date: [October 30, 2014, 1:50am UTC](https://meta.discourse.org/t/full-site-cdn-acceleration-for-discourse/21467/3 "2014-10-30T01:50:21Z")

</div>

1 Round trip, read up abount TCP congestion control, initial windows and so on.

[http://samsaffron.com/archive/2012/03/01/why-upgrading-your-linux-kernel-will-make-your-customers-much-happier](http://samsaffron.com/archive/2012/03/01/why-upgrading-your-linux-kernel-will-make-your-customers-much-happier)

---

<div class="post-metadata">

### Author: ![renoirb](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/renoirb/32/114880_2.png) [@renoirb](https://meta.discourse.org/u/renoirb)
#### Post date: [May 2, 2015, 2:29am UTC](https://meta.discourse.org/t/full-site-cdn-acceleration-for-discourse/21467/4 "2015-05-02T02:29:09Z")

</div>

**UPDATE 2015-04-02** : I just made the full example more complete.

I am confused with this definition.

> [@sam](#):
>
> To server “long polling” requests from a different domain, set the Site Setting long polling base url to the origin server.
> 
> For example, if your CDN is pulling from “[http://some-origin.com](http://some-origin.com)” be sure to plug in [http://some-origin.com/](http://some-origin.com/) into the site setting. If you don’t your site will be broken.

But I think this should clarify it. Please, don’t hesitate to tell me if i’m doing something wrong.

The confusing part is that if “[http://some-origin.com/](http://some-origin.com/)”. If you are behind Fastly, you have to use a CNAME entry and then you have to have a sub domain name and not the top level.

**Background:** In DNS, a top level domain name (i.e. “[some-origin.com](http://some-origin.com)”) can _only_ have `A` records. Since Fastly requires we use a `CNAME` entry, we have no choice but to use a sub domain name.

Let’s say that we will then use “[http://discourse.some-origin.com/](http://discourse.some-origin.com/)” to serve our Discourse forum so we can use Fastly.

Now there’s this thing called “long polling” which is basically an `OPTION` HTTP request with a long time before returning anything. If we use the Fastly or Varnish address, as Discourse would by default, Varnish will time out and “long polling” won’t work.

**More background:** Varnish has this option to bypass in known contexts through `vcl_pipe` which is roughly a raw TCP socket. But Fastly doesn’t offer it [because of the _size_ of their setup](https://community.fastly.com/t/vcl-pipe-heads-up/163).

## Proposed setup

Let’s enable long polling and expose our site under Fastly. We’ll need two names, one pointing to Fastly’s and the other to the IP addresses we give within the service dashboard.

1. **[discourse.some-origin.com](http://discourse.some-origin.com)** that’s our desired Discourse site domain name
2. **[discoursepolling.some-origin.com](http://discoursepolling.some-origin.com)** (pick any name) that we’ll configure in Discourse to access directly to our public facing frontend web server

In my case, I generally have many web apps running that are only accessible from my internal network. I refer to them as “upstream”; the same term NGINX uses in their config. Since this number of web apps you would host on a site can fluctuate, you might still want the number public IP address to remain stable. That’s why I setup a NGINX server in front that proxies to internal web app server. I refer to them as “frontends”.

Let’s say you have two public facing frontends running NGINX.

Those would be the ones you setup in Fastly like this.

 ![Fastly service configuration, at Hosts tab](https://global.discourse-cdn.com/meta/original/3X/a/f/af4528a911369a427ad5d07fb0d91daa11a0f998.png)

Here we see two _Backends_ in Fastly pannel at `Configure -> Hosts`.

Notice that in this example i’m using `443` port because my backends are configured to communicate between Fastly and my frontends through TLS. But you don’t need to.

Quoting again @sam;

[quote=“sam, post:1, topic:21467”]  
To server “long polling” requests from a different domain, set the Site Setting long polling base url to the origin server.[/quote]

Really means here is that we would have to put one of those IP addresses in Discourse settings.

What I’d recommend is to create a list of `A` entries for all your frontends.

In the end we need three things:

1. What’s the public name that Fastly will serve
2. Which IPs are the frontends
3. Which hostname we want to use for long polling and we’ll add it to our VirtualHost

The zone file would look like this;

```plaintext
# The public facing URL
discourse.some-origin.com. IN CNAME global.prod.fastly.net.

# The list of IP addresses you’d give to Fastly as origins/backends
frontends.some-origin.com. IN A 8.8.8.113
frontends.some-origin.com. IN A 8.8.8.115

# The long polling URL entry
discoursepolling.some-origin.com. IN CNAME frontends.some-origin.com.

```

That way you can setup the “long polling base url” correctly without setting a single point of failure.

![](https://global.discourse-cdn.com/meta/original/3X/3/7/375e4c9dccb0d96b1f60aa31f4cb687e4e987522.png)

Then, we can go in Discourse admin zone and adjust the “long polling base url” to our other domain name.

```plaintext
# /etc/nginx/sites-enabled/10-discourse

# Let’s redirect to SSL, in case somebody tries to access the direct IP with
# host header.
server {
    listen 80;
    server_name discoursepolling.some-origin.com discourse.some-origin.com;
    include common_params;
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl;
    server_name discoursepolling.some-origin.com discourse.some-origin.com;
    # Rest of NGINX server block
    # Also, I would make a condition if we are in discoursepolling but not
    # under using anything specific to polling.
    # #TODO; find paths specific to polling
}

```

To see if it works; look at your web browser developer tool “Network inspector” for `/poll` calls on `discoursepolling.some-origin.com`, and see if you have `200 OK` status code.

---

<div class="post-metadata">

### Author: ![brahn](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/brahn/32/109267_2.png) [@brahn](https://meta.discourse.org/u/brahn)
#### Post date: [January 23, 2017, 4:39am UTC](https://meta.discourse.org/t/full-site-cdn-acceleration-for-discourse/21467/5 "2017-01-23T04:39:46Z")

</div>

> [@sam](#):
>
> To serve “long polling” requests from a different domain, set the Site Setting long polling base url to the origin server.
> 
> For example, if your site is on “[http://forum.example.com](http://forum.example.com)” you should set up [http://forum-direct.example.com/](http://forum-direct.example.com/) to plug into the site setting. If you don’t your site will be broken.

To clarify something here, in a multisite configuration, all sites should use the same long polling url? It looks to me like the this line is making that a requirement:

> <https://github.com/discourse/discourse/blob/5dbd6a304bed5400be481d71061d3e3ebb4d6785/config/initializers/004-message_bus.rb#L28>

thanks!

**Edit: No wait, that doesn’t work.**

base site: [example.com](http://example.com)  
long polling url: [origin.example.com](http://origin.example.com)

multisite 1: [mysite.com](http://mysite.com)

If mysite uses [origin.example.com](http://origin.example.com) as the long polling address I get:

```plaintext
XMLHttpRequest cannot load https://origin.example.com/message-bus/634dd18187094c6c950c0bf14f74c239/poll. Response to preflight request doesn't pass access control check: The 'Access-Control-Allow-Origin' header has a value 'https://example.com' that is not equal to the supplied origin. Origin 'https://mysite.com' is therefore not allowed access.

```

If mysite uses it’s own long polling origin as the domain I get this:

```plaintext
XMLHttpRequest cannot load https://origin.mysite.com/message-bus/b35c9c8e958f44f78d0d4773dc6d75f3/poll. Response to preflight request doesn't pass access control check: The 'Access-Control-Allow-Origin' header has a value 'https://example.com' that is not equal to the supplied origin. Origin 'https://mysite.com' is therefore not allowed access.

```

Is this because of `"Access-Control-Allow-Origin" => Discourse.base_url_no_prefix` ?

---

<div class="post-metadata">

### Author: ![aurelien](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/aurelien/32/81863_2.png) [@aurelien](https://meta.discourse.org/u/aurelien)
#### Post date: [September 13, 2017, 12:09pm UTC](https://meta.discourse.org/t/full-site-cdn-acceleration-for-discourse/21467/6 "2017-09-13T12:09:31Z")

</div>

I have noticed there is no “cloudfront.template.yml” in discourse\_docker/templates/. So I am wondering:  
Can CloudFront work using the same techniques ?

---

<div class="post-metadata">

### Author: ![aurelien](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/aurelien/32/81863_2.png) [@aurelien](https://meta.discourse.org/u/aurelien)
#### Post date: [September 15, 2017, 9:51am UTC](https://meta.discourse.org/t/full-site-cdn-acceleration-for-discourse/21467/7 "2017-09-15T09:51:53Z")

</div>

Also, can we use http2 ? Is the long polling stuff still needed when using http2 ?

---

<div class="post-metadata">

### Author: ![fefrei](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/fefrei/32/119538_2.png) [@fefrei](https://meta.discourse.org/u/fefrei)
#### Post date: [September 15, 2017, 12:37pm UTC](https://meta.discourse.org/t/full-site-cdn-acceleration-for-discourse/21467/8 "2017-09-15T12:37:58Z")

</div>

If you’re using a the supported Docker-based install, HTTP2 should be working automatically! ☀

Long polling is still needed for notifications to appear live.

---

<div class="post-metadata">

### Author: ![SouperC](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/souperc/32/62875_2.png) [@SouperC](https://meta.discourse.org/u/SouperC)
#### Post date: [September 15, 2017, 8:04pm UTC](https://meta.discourse.org/t/full-site-cdn-acceleration-for-discourse/21467/9 "2017-09-15T20:04:36Z")

</div>

> [@aurelien](#):
>
> I have noticed there is no “cloudfront.template.yml” in discourse\_docker/templates/. So I am wondering:
> 
> Can CloudFront work using the same techniques ?

I think if you have cloudfront setup, it’s only delivering specific objects (images), rather than the site/application in it’s entirety with js and so on.

So the only thing you need is to have the correct cloudfront url for those images.

---

<div class="post-metadata">

### Author: ![ryanerwin](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/ryanerwin/32/94589_2.png) [@ryanerwin](https://meta.discourse.org/u/ryanerwin)
#### Post date: [May 20, 2018, 5:13pm UTC](https://meta.discourse.org/t/full-site-cdn-acceleration-for-discourse/21467/10 "2018-05-20T17:13:05Z")

</div>

Some additional notes for anyone who decides to use HTTPS together with Full site CDN acceleration

1. Discourse internally uses the value of `SiteSetting.force_https` to decide if your `access-control-allow-origin:` is the HTTP or HTTPS version of your site. If while polling you see an error in the browser console along the lines of `preflight request doesn't pass access control check: The 'Access-Control-Allow-Origin' header has a value http doesn't match https`, double check your `force_https` setting. Also note the protocol in your `DISCOURSE_CORS_ORIGIN` in your container definition (http|https) will be overridden by `force_https`.  
Don’t forget to add `DISCORSE_ENABLE_CORS: true` in your container definition.

2. If you were planning to only do HTTPS from your end users to your CDN, and then HTTP from your CDN to your actual Discourse `web_only` containers, **lots of custom configuration** will be required.

3. If your CDN is serving your site on HTTPS, then whatever Long Polling URL you setup must also be on HTTPS, so even if the CDN is handling your HTTPS, you must still setup HTTPS on your Discourse servers. If you run into an error about `Same-origin policy`, double check that you’re not trying to connect to HTTP instead of HTTPS

4. You might use the following templates in your container definition:

```plaintext
  - "templates/web.template.yml"
  - "templates/web.ssl.template.yml"
  - "templates/fastly.template.yml"

```

- Towards the end of the `hook:ssl` inside `templates/web.ssl.template.yml` you’ll see this block being added to your `/etc/nginx/conf.d/discourse.conf`.

```nginx
if ($http_host != $$ENV_DISCOURSE_HOSTNAME) {
    rewrite (.*) https://$$ENV_DISCOURSE_HOSTNAME$1 permanent;
}

```

- You’ll need to need to comment these lines out, otherwise you’re long polling attempts always serve up 301 redirects back to your origin, instead of respecting whatever you set in `SiteSetting.long_polling_base_url`

1. The easiest way I’ve found to do this is to copy `templates/web.ssl.template.yml` to `local.web.ssl.template.yml` and just remove those extra lines, and update your container reference to use your local template. If you go that route, you should periodically `diff` your local version with the origional version, because there are some [security improvements that are regularly incorporated](https://github.com/discourse/discourse_docker/commits/master/templates/web.ssl.template.yml) into this template.

* * *

Some of the error messages you’ll run into until things are configured correctly.

> Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at [https://polling.example.com/message-bus/37c91c51e6cd4b0c95288b8fc29a0480/poll](https://polling.example.com/message-bus/37c91c51e6cd4b0c95288b8fc29a0480/poll). (Reason: CORS header ‘Access-Control-Allow-Origin’ missing).
> 
> Reason: CORS header ‘Access-Control-Allow-Origin’ missing
> 
> Response to preflight request doesn’t pass access control check: No ‘Access-Control-Allow-Origin’ header is present on the requested resource
> 
> Failed to load [https://polling.example.com/message-bus/8caefcec2cf94de3ae684c4b953a1084/poll:](https://polling.example.com/message-bus/8caefcec2cf94de3ae684c4b953a1084/poll:) Response for preflight is invalid (redirect)

---

<div class="post-metadata">

### Author: ![brahn](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/brahn/32/109267_2.png) [@brahn](https://meta.discourse.org/u/brahn)
#### Post date: [May 21, 2018, 2:46am UTC](https://meta.discourse.org/t/full-site-cdn-acceleration-for-discourse/21467/11 "2018-05-21T02:46:42Z")

</div>

> [@ryanerwin](#):
>
> The easiest way I’ve found to do this is to copy `templates/web.ssl.template.yml` to `local.web.ssl.template.yml` and just remove those extra lines

You can do this with a `- replace` in your app.yml similar to how it is described on [Setting up Let’s Encrypt with Multiple Domains](https://meta.discourse.org/t/setting-up-let-s-encrypt-with-multiple-domains/56685).

```plaintext
  after_ssl:
    - replace:
        filename: "/etc/nginx/conf.d/discourse.conf"
        from: /return 301 https.+/
        to: |
          return 301 https://$host$request_uri;

    - replace:
        filename: "/etc/nginx/conf.d/discourse.conf"
        from: /gzip on;[^\}]+\}/m
        to: |
          gzip on;
          add_header Strict-Transport-Security 'max-age=31536000'; # remember the certificate for a year and automatically connect to HTTPS for this domain

```

---

<div class="post-metadata">

### Author: ![ryanerwin](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/ryanerwin/32/94589_2.png) [@ryanerwin](https://meta.discourse.org/u/ryanerwin)
#### Post date: [May 21, 2018, 3:22am UTC](https://meta.discourse.org/t/full-site-cdn-acceleration-for-discourse/21467/12 "2018-05-21T03:22:44Z")

</div>

@brahn, I was looking at using a pups replace line, but I couldn’t figure out how to do a multi-line match in pups…

Note that [templates/web.ssl.template.yml](https://github.com/discourse/discourse_docker/blob/bfe8ac9477e2070378ce286e2b104913d710c5be/templates/web.ssl.template.yml) is inside of the port 443 block, not the port 80 block.

Is there a way to use the [pups](https://github.com/discourse/pups), [replace command](https://github.com/discourse/pups/blob/7bde3d3f6a25db8ae3d0a9d6e0beedd5b20cf4ed/lib/pups/replace_command.rb) to match the entire mult-line string?

```plaintext
if ($http_host != www.example.com) {
   rewrite (.*) https://www.example.com$1 permanent;
}

```

The most direct way I thought of inside the container definition is an exec line running perl, awk or sed to do the multiline replace… but then you’ve got shell escaping along with your target language to disentangle before it will work…

---

<div class="post-metadata">

### Author: ![brahn](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/brahn/32/109267_2.png) [@brahn](https://meta.discourse.org/u/brahn)
#### Post date: [May 21, 2018, 3:52am UTC](https://meta.discourse.org/t/full-site-cdn-acceleration-for-discourse/21467/13 "2018-05-21T03:52:17Z")

</div>

The first `replace` takes care of the redirect from http to https for multisite. Perhaps that one is not relevant for you.

The second `replace` is multi-line. It replaces everything from line [33](https://github.com/discourse/discourse_docker/blob/bfe8ac9477e2070378ce286e2b104913d710c5be/templates/web.ssl.template.yml#L33) to line [39](https://github.com/discourse/discourse_docker/blob/bfe8ac9477e2070378ce286e2b104913d710c5be/templates/web.ssl.template.yml#L39) that was added by the web.ssl template.

It just removes that whole rewrite block. I could not figure out what purpose it serves and it breaks mutlisite so…

You could do this in your `app.yml`:

```plaintext
after_ssl:
    - replace:
        filename: "/etc/nginx/conf.d/discourse.conf"
        from: /gzip on;[^\}]+\}/m
        to: |
          gzip on;
          add_header Strict-Transport-Security 'max-age=31536000'; # remember the certificate for a year and automatically connect to HTTPS for this domain
          if ($http_host != www.example.com) {
            rewrite (.*) https://www.example.com$1 permanent;
          }

```

---

<div class="post-metadata">

### Author: ![itsbhanusharma](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/itsbhanusharma/32/180717_2.png) [@itsbhanusharma](https://meta.discourse.org/u/itsbhanusharma)
#### Post date: [January 23, 2019, 7:44am UTC](https://meta.discourse.org/t/full-site-cdn-acceleration-for-discourse/21467/14 "2019-01-23T07:44:48Z")

</div>

@sam

I’m curious to know one thing:  
Eg. My discourse is hosted on `forum.example.com`  
Can I set long polling base to `poll.example.org` which points to the same server IP?  
Will it have any impact considering CSP?

---

<div class="post-metadata">

### Author: ![satonotdead](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/satonotdead/32/447830_2.png) [@satonotdead](https://meta.discourse.org/u/satonotdead)
#### Post date: [April 7, 2020, 6:50am UTC](https://meta.discourse.org/t/full-site-cdn-acceleration-for-discourse/21467/15 "2020-04-07T06:50:17Z")

</div>

Hi there. Why you guys recommends keep away from Cloudflare when we are in Discourse?

I’m trying to install it in my new VPS (Debian in Hetzner) and I thought that could be useful to keep Cloudflare on in my little server.

Thanks for your time.

---

<div class="post-metadata">

### Author: ![Stephen](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/stephen/32/95011_2.png) [@Stephen](https://meta.discourse.org/u/Stephen)
#### Post date: [April 7, 2020, 6:55am UTC](https://meta.discourse.org/t/full-site-cdn-acceleration-for-discourse/21467/16 "2020-04-07T06:55:52Z")

</div>

CloudFlare isn’t a conventional CDN, it’s a network proxy. Some of their performance features alter the code between client and server.

Leaving those features on can break Discourse in new and interesting ways. If you turn them off, you’re just adding extra network hops between the Discourse app in your browser, and the server. More hops = a less responsive interface.

---

<div class="post-metadata">

### Author: ![satonotdead](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/satonotdead/32/447830_2.png) [@satonotdead](https://meta.discourse.org/u/satonotdead)
#### Post date: [April 7, 2020, 7:02am UTC](https://meta.discourse.org/t/full-site-cdn-acceleration-for-discourse/21467/17 "2020-04-07T07:02:39Z")

</div>

Well, I’m in Hetzner VPS and I read that could be good to use Cloudflare to keep my server safe (in eventual attacks). CDN could be OK too, because I’m in another country (America, not Germany).

What do you think about it?

---

<div class="post-metadata">

### Author: ![Stephen](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/stephen/32/95011_2.png) [@Stephen](https://meta.discourse.org/u/Stephen)
#### Post date: [April 7, 2020, 7:18am UTC](https://meta.discourse.org/t/full-site-cdn-acceleration-for-discourse/21467/18 "2020-04-07T07:18:14Z")

</div>

I’m not going to comment on whether you should be worried about attacks. You need to make that assessment yourself, but don’t fall prey to FUD.

If you leave their performance features enabled we cannot support you here. As mentioned above they interfere with the javascript in ways that do no good.

You may be able to make the basic asset caching work with all of the other performance features turned off.

Even then, if Cloudflare is active during installation and setup, certificate enrolment will fail. Let’s Encrypt isn’t supported behind a Cloudflare proxy for initial enrolment.

---

<div class="post-metadata">

### Author: ![satonotdead](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/satonotdead/32/447830_2.png) [@satonotdead](https://meta.discourse.org/u/satonotdead)
#### Post date: [April 7, 2020, 7:33am UTC](https://meta.discourse.org/t/full-site-cdn-acceleration-for-discourse/21467/19 "2020-04-07T07:33:14Z")

</div>

Thanks for your answer Stephen. I’m facing issues trying to install Discourse and I thought that could be related to Cloudflare.

So, I can’t use it neither to manage DNS? How can I protect my server and keep Discourse without Cloudflare?

---

<div class="post-metadata">

### Author: ![RGJ](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/rgj/32/523185_2.png) [@RGJ](https://meta.discourse.org/u/RGJ)
#### Post date: [April 7, 2020, 7:57am UTC](https://meta.discourse.org/t/full-site-cdn-acceleration-for-discourse/21467/20 "2020-04-07T07:57:14Z")

</div>

> [@satonotdead](#):
>
> So, I can’t use it neither to manage DNS?

Press the orange cloud next to your hostname in the Cloudfare control panel so the cloud turns grey.  
Then install Discourse. If you want to protect your server, press the grey cloud so it turns orange, but make sure to disable all performance features first.

[Next page](https://meta.discourse.org/t/full-site-cdn-acceleration-for-discourse/21467.md?page=2)
