# Troubleshooting "BAD CSRF" error on initial site setup?

**URL:** https://meta.discourse.org/t/troubleshooting-bad-csrf-error-on-initial-site-setup/97059
**Category:** Self-hosting
**Created:** [9월 12, 2018, 5:23오후 UTC](https://meta.discourse.org/t/troubleshooting-bad-csrf-error-on-initial-site-setup/97059 "2018-09-12T17:23:19Z")
**Posts on this page:** 20
**Page:** 1

<div class="post-metadata">

### Author: ![Lee\_Ars](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/lee_ars/32/1597_2.png) [@Lee\_Ars](https://meta.discourse.org/u/Lee_Ars)
#### Post date: [9월 12, 2018, 5:23오후 UTC](https://meta.discourse.org/t/troubleshooting-bad-csrf-error-on-initial-site-setup/97059/1 "2018-09-12T17:23:19Z")

</div>

Standing up a new Discourse forum as a separate docker container on a dedicated physical server that is already running an existing Discourse forum (which is humming along with no errors).

Bootstrapping works without errors and the initial “You’ve successfully installed Discourse!” message appears without issue, and I can enter my desired username & PW without any error. However, on submitting the form, rather than sending the initial registration email, Discourse displays a white page with `["BAD CSRF"]` in the upper left corner.

I’m honestly not even sure where to start troubleshooting this. Searching here on meta didn’t really yield any results that appear relevant.

Suggestions on where to start looking?

---

<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: [9월 12, 2018, 5:39오후 UTC](https://meta.discourse.org/t/troubleshooting-bad-csrf-error-on-initial-site-setup/97059/2 "2018-09-12T17:39:26Z")

</div>

It’s likely a problem with whatever is doing https. How’s that configured?

---

<div class="post-metadata">

### Author: ![Lee\_Ars](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/lee_ars/32/1597_2.png) [@Lee\_Ars](https://meta.discourse.org/u/Lee_Ars)
#### Post date: [9월 12, 2018, 5:41오후 UTC](https://meta.discourse.org/t/troubleshooting-bad-csrf-error-on-initial-site-setup/97059/3 "2018-09-12T17:41:19Z")

</div>

> [@pfaffman](#):
>
> It’s likely a problem with whatever is doing https. How’s that configured?

The web server hosts 4 domains and seven separate web sites, so universal SSL termination is done by HAProxy so I can keep the layers separated and provide caching even to SSL content.

The stack is HAProxy → Varnish (cache) → nginx reverse proxy → Discourse.

Worth noting that I had no issues setting up the first Discourse forum under this same configuration.

Edited to add - client connections are over https, but I’m proxying from nginx to the docker container’s HTTP port, not HTTPS (again, doing what works for the first Discourse instance). I can try changing that to the HTTPS port to see what happens, though, if that’ll help.

edit^2 - no, that didn’t help.

---

<div class="post-metadata">

### Author: ![Lee\_Ars](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/lee_ars/32/1597_2.png) [@Lee\_Ars](https://meta.discourse.org/u/Lee_Ars)
#### Post date: [9월 12, 2018, 7:27오후 UTC](https://meta.discourse.org/t/troubleshooting-bad-csrf-error-on-initial-site-setup/97059/4 "2018-09-12T19:27:10Z")

</div>

Looking through the Discourse `production.log` and this is what I see:

```plaintext
Started POST "/finish-installation/register" for 2601:2c4:c700:745f:216:3eff:0:11 at 2018-09-12 19:21:26 +0000
Processing by FinishInstallationController#register as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"[redacted]", "email"=>"redacted", "username"=>"redacted", "password"=>"[FILTERED]", "commit"=>"Register"}
Can't verify CSRF token authenticity.
  Rendering text template
  Rendered text template (0.0ms)
Filter chain halted as :verify_authenticity_token rendered or redirected
Completed 403 Forbidden in 2ms (Views: 0.3ms | ActiveRecord: 0.0ms)

```

Still looking through the other threads on meta where `Can't verify CSRF token authenticity` has come up.  
I also see the 403 response in Chrome’s console:

```plaintext
Request URL: https://(forum url)/finish-installation/register
Request Method: POST
Status Code: 403 
Remote Address: [2607:fad0:3524:1::8]:443
Referrer Policy: strict-origin-when-cross-origin

```

---

<div class="post-metadata">

### Author: ![Falco](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/falco/32/179432_2.png) [@Falco](https://meta.discourse.org/u/Falco)
#### Post date: [9월 12, 2018, 8:51오후 UTC](https://meta.discourse.org/t/troubleshooting-bad-csrf-error-on-initial-site-setup/97059/5 "2018-09-12T20:51:42Z")

</div>

This happens when SSL is badly configured. Most of the times a header is missing from the reverse proxy config.

---

<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: [9월 12, 2018, 9:04오후 UTC](https://meta.discourse.org/t/troubleshooting-bad-csrf-error-on-initial-site-setup/97059/6 "2018-09-12T21:04:56Z")

</div>

> [@Falco](#):
>
> a header is missing from the reverse proxy config

^ this - the host header has to remain intact throughout, otherwise encryption can’t be established. Is it all IP/port based behind HAProxy?

Out of curiosity why are you using HAProxy in front of Varnish and then nginx behind?

---

<div class="post-metadata">

### Author: ![Lee\_Ars](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/lee_ars/32/1597_2.png) [@Lee\_Ars](https://meta.discourse.org/u/Lee_Ars)
#### Post date: [9월 12, 2018, 9:06오후 UTC](https://meta.discourse.org/t/troubleshooting-bad-csrf-error-on-initial-site-setup/97059/7 "2018-09-12T21:06:37Z")

</div>

Right, and my first guess was to make sure `X-Forwarded-Proto` was being appended properly by the reverse proxy—and it is. That’s the annoying thing here—the configuration between [the working forum](https://discourse.bigdinosaur.org/) and the new one is identical.

And when I say “identical” I mean literally using the exact same processes and config files 😃 They’re both on the same server, so other than the nginx configuration file in `sites-available` they’re even using the exact same set of configuration files. Everything’s the exact same.

The nginx config is pretty short—hard for me to screw that up:

```plaintext
server {
	server_name [redacted];
	listen 8881;
	listen 8882 http2;

	sendfile on;

	location / {
		access_log off;
		proxy_set_header X-Real-IP $remote_addr;
		proxy_set_header Host $http_host;
		proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
		proxy_set_header X-Forwarded-Proto https;
		proxy_redirect off;
		proxy_pass http://localhost:7996;
	}
}

```

The only differences between it and the config for the working forum is the `server_name` directive and the port I’m passing to.

---

<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: [9월 12, 2018, 9:08오후 UTC](https://meta.discourse.org/t/troubleshooting-bad-csrf-error-on-initial-site-setup/97059/8 "2018-09-12T21:08:23Z")

</div>

> [@Lee\_Ars](#):
>
> They’re both on the same server, so other than the nginx configuration file in `sites-available` they’re even using the exact same set of configuration files. Everything’s the exact same.
> 
> The nginx config is pretty short—hard for me to screw that up:

Is HAProxy using a SAN cert, or unique IPs and separate certificates?

---

<div class="post-metadata">

### Author: ![Lee\_Ars](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/lee_ars/32/1597_2.png) [@Lee\_Ars](https://meta.discourse.org/u/Lee_Ars)
#### Post date: [9월 12, 2018, 9:10오후 UTC](https://meta.discourse.org/t/troubleshooting-bad-csrf-error-on-initial-site-setup/97059/9 "2018-09-12T21:10:38Z")

</div>

> [@Stephen](#):
>
> Out of curiosity why are you using HAProxy in front of Varnish and then nginx behind?

The overall config goals were to 1) encrypt everything and 2) cache everything. These are obviously opposing goals, so the way I went about it was to stratify things: SSL termination first, then a cache layer, then a web server that both serves static stuff and also functions as a reverse proxy as needed (for wordpress, discourse, and a few other things).

I initially had a fair amount of trouble with the “nginx sandwich” approach (nginx → varnish → nginx)—getting two separate instances of nginx to work properly with Upstart on ubuntu 14.04 proved to be very difficult and required a lot of screwing around, so I ditched nginx as my ssl termination layer and went with haproxy instead. If I were redoing this now, I’d go with Hitch, but ripping out haproxy at this point would require some research on how to do the transition.

edit:

> [@Stephen](#):
>
> Is HAProxy using a SAN cert, or unique IPs and separate certificates?

HAProxy is using separate LetsEncrypt certificates (maintained via acme.sh), one per host. This is done mainly because the number of sites being hosted has changed over time and changing/updating a single SAN certificate proved to be kind of a pain in the ass. Additionally, I have a couple of tenant sites that would prefer to keep their SSL configs as separate from mine as possible.

---

<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: [9월 12, 2018, 9:13오후 UTC](https://meta.discourse.org/t/troubleshooting-bad-csrf-error-on-initial-site-setup/97059/10 "2018-09-12T21:13:12Z")

</div>

> [@Lee\_Ars](#):
>
> getting two separate instances of nginx to work properly with Upstart on ubuntu 14.04 proved to be very difficult and required a lot of screwing around

Fair enough, they’re just separate sites though in the same instance of NGINX, it’s quite a common setup. Due to the nature of the app Discourse doesn’t really respond well or need external caching, HAProxy is only going to give you some port-redirection-fu there, which Nginx also covers.

---

<div class="post-metadata">

### Author: ![Falco](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/falco/32/179432_2.png) [@Falco](https://meta.discourse.org/u/Falco)
#### Post date: [9월 12, 2018, 9:14오후 UTC](https://meta.discourse.org/t/troubleshooting-bad-csrf-error-on-initial-site-setup/97059/11 "2018-09-12T21:14:19Z")

</div>

> [@Lee\_Ars](#):
>
> The only differences between it and the config for the working forum is the `server_name` directive and the port I’m passing to.

Did you enable `force_https` in the second site?

---

<div class="post-metadata">

### Author: ![Lee\_Ars](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/lee_ars/32/1597_2.png) [@Lee\_Ars](https://meta.discourse.org/u/Lee_Ars)
#### Post date: [9월 12, 2018, 9:23오후 UTC](https://meta.discourse.org/t/troubleshooting-bad-csrf-error-on-initial-site-setup/97059/12 "2018-09-12T21:23:23Z")

</div>

> [@Falco](#):
>
> Did you enable `force_https` in the second site?

Is there an easy way to do that via config file editing? I can’t log into the new site yet—I can’t get past the initial admin user registration step.

> [@Stephen](#):
>
> Fair enough, they’re just separate sites though in the same instance of NGINX, it’s quite a common setup. Due to the nature of the app Discourse doesn’t really respond well or need external caching,

Yeah, I’m aware of Discourse’s cache behavior—this config has been live for a number of years. Discourse is not the only tenant application on the box, though, so its requirements get added into the mix along with everything else’s, and pretty much everything else on the box is very cache-friendly.

I honestly hadn’t thought about doing this all with a single instance of nginx. That’s definitely an interesting suggestion, though I’d need to sit down and whiteboard out the flow. Initial connections on port 443 (or 80 redirected to 443), proxying to varnish, proxying from there to nginx on a different port, I suppose, though I’m wary to rely on a single application for all three layers here. Feels like isolating errors and fixing them becomes considerably more complex.

(I’m aware nginx has serviceable cache, but it lacks varnish’s rich purge/ban functionality and makes manual object invalidation into a giant pain.)

---

<div class="post-metadata">

### Author: ![Falco](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/falco/32/179432_2.png) [@Falco](https://meta.discourse.org/u/Falco)
#### Post date: [9월 12, 2018, 9:27오후 UTC](https://meta.discourse.org/t/troubleshooting-bad-csrf-error-on-initial-site-setup/97059/13 "2018-09-12T21:27:31Z")

</div>

> [@Lee\_Ars](#):
>
> Is there an easy way to do that via config file editing? I can’t log into the new site yet—I can’t get past the initial admin user registration step.
> 
> ![](https://global.discourse-cdn.com/meta/original/3X/7/8/7870384b9c69ec5f2a8ba0387f6b99e48fd00746.jpeg) Stephen:

This should do it:

```plaintext
./launcher enter app
cd /var/www/discourse
rails c
SiteSetting.force_https = true

```

---

<div class="post-metadata">

### Author: ![Lee\_Ars](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/lee_ars/32/1597_2.png) [@Lee\_Ars](https://meta.discourse.org/u/Lee_Ars)
#### Post date: [9월 12, 2018, 9:37오후 UTC](https://meta.discourse.org/t/troubleshooting-bad-csrf-error-on-initial-site-setup/97059/14 "2018-09-12T21:37:07Z")

</div>

No joy - set to true:

```plaintext
[1] pry(main)> SiteSetting.force_https
=> true
[2] pry(main)> 

```

Stopped & restarted the docker container just to be sure (not sure if that’s necessary or not but figured it couldn’t hurt), but still receiving the same error.

---

<div class="post-metadata">

### Author: ![Falco](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/falco/32/179432_2.png) [@Falco](https://meta.discourse.org/u/Falco)
#### Post date: [9월 12, 2018, 9:43오후 UTC](https://meta.discourse.org/t/troubleshooting-bad-csrf-error-on-initial-site-setup/97059/15 "2018-09-12T21:43:59Z")

</div>

So your setup is:

HAProxy → Varnish (cache) → nginx reverse proxy → Docker

And SSL termination happens at HAProxy, right? Is the HAProxy config the same for both sites? With same header injection?

---

<div class="post-metadata">

### Author: ![Lee\_Ars](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/lee_ars/32/1597_2.png) [@Lee\_Ars](https://meta.discourse.org/u/Lee_Ars)
#### Post date: [9월 12, 2018, 9:50오후 UTC](https://meta.discourse.org/t/troubleshooting-bad-csrf-error-on-initial-site-setup/97059/16 "2018-09-12T21:50:16Z")

</div>

> [@Falco](#):
>
> And SSL termination happens at HAProxy, right? Is the HAProxy config the same for both sites? With same header injection?

Exact same—traffic for both sites is going through the same haproxy `frontend` and same `backend`. Not doing any header injection with haproxy—in fact, I’m using HAproxy in TCP mode so that I can pass traffic via `proxy-protocol-v2` to varnish, which lets me offer full HTTP/2 from the nginx reverse proxy at the bottom of the stack.

I do response header injection via varnish (hsts, referrer-policy, x-frame-options, x-content-type-options, a few others), and request header injection (like x-forwarded-protocol) with nginx.

edit - I totally understand the limits of free support—if this is going to turn complicated, I’ll bang on it a while on my own this weekend when I’ve got some spare time (and more importantly, some latitude to break things a bit). My hope was that this was going to be something really simple—and it still might be!—but I don’t want to be a pain.

---

<div class="post-metadata">

### Author: ![fais3000](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/fais3000/32/218714_2.png) [@fais3000](https://meta.discourse.org/u/fais3000)
#### Post date: [4월 29, 2021, 9:17오후 UTC](https://meta.discourse.org/t/troubleshooting-bad-csrf-error-on-initial-site-setup/97059/17 "2021-04-29T21:17:52Z")

</div>

같은 문제로 고생하고 계신 분들을 위해 아래 내용을 참고해 주세요.

저도 비슷한 문제를 겪었습니다. 제 환경은 Cloudflare 뒤에서 Nginx를 사용하고 있었고, 서브폴더에 포럼을 설치해 둔 상태였습니다.

결국 다음과 같은 조합으로 문제를 해결할 수 있었습니다.

- Cloudflare에서 해당 서브폴더의 캐싱을 비활성화
- 아래 Nginx 블록 설정

```plaintext
    location /folder {
        proxy_ssl_server_name on;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto https;
        proxy_pass http://localhost:1357/folder;
    }

```

---

<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: [4월 30, 2021, 2:11오전 UTC](https://meta.discourse.org/t/troubleshooting-bad-csrf-error-on-initial-site-setup/97059/18 "2021-04-30T02:11:54Z")

</div>

해결되어서 다행입니다! 테스트 사이트도 Cloudflare 뒤에 있었나요?

---

<div class="post-metadata">

### Author: ![fais3000](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/fais3000/32/218714_2.png) [@fais3000](https://meta.discourse.org/u/fais3000)
#### Post date: [4월 30, 2021, 6:48오전 UTC](https://meta.discourse.org/t/troubleshooting-bad-csrf-error-on-initial-site-setup/97059/19 "2021-04-30T06:48:09Z")

</div>

다른 사이트도 Cloudflare를 사용하고 있었지만 캐싱이 활성화되어 있지 않았습니다. 새로운 사이트 루트에는 페이지 규칙을 통해 공격적인 캐싱이 활성화되어 있으며, 이는 서브폴더에도 적용되므로 문제가 발생한 것입니다.

**브라우저 캐시 TTL: 1개월, Always Online: 켜짐, 캐시 레벨: 모든 항목 캐시, Edge 캐시 TTL: 2419200초**

또한 다음 헤더도 매우 중요하다고 생각합니다.

```plaintext
        proxy_set_header X-Forwarded-Proto https;

```

---

<div class="post-metadata">

### Author: ![JammyDodger](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/jammydodger/32/254611_2.png) [@JammyDodger](https://meta.discourse.org/u/JammyDodger)
#### Post date: [7월 18, 2024, 7:23오전 UTC](https://meta.discourse.org/t/troubleshooting-bad-csrf-error-on-initial-site-setup/97059/21 "2024-07-18T07:23:54Z")

</div>


