Why recommending no SSL when behind Cloudflare?
I'm sorry if this had been discussed. Couldn't find it anywhere.
This line from the config template got me puzzled:
Set ssl: false if using something like Cloudflare to terminate SSL (but keep host!).
I've always believed that one has to have SSL at the origin server even if behind a public proxy such as Cloudflare.
Because, otherwise, the request between Cloudflare and the origin server will travel through the public internet unencrypted, right? Like this: User <-encrypted-> Cloudflare <-plain-> Origin
Don't we want to have this instead? User <-encrypted-> Cloudflare <-encrypted-> Origin
I understand that the ultimate answer is "well, it's up to you" which is fair. However, I feel like the way this comment is phrased might deceive users into thinking that they have complete User<->Server encryption when they actually don't.
Or am I missing something here?
I don't think it's deceiving as the comment does say that Cloudflare terminates the SSL, which technically means encryption ends at Cloudflare.
By default, Cloudflare uses Flexible mode, which means that even if you set ssl: true, the connection between Cloudflare and your origin server is still not encrypted. To properly set it up, you need to set SSL mode to Full in Cloudflare. Maybe, that can be mentioned in the comment.
I can create a PR to address this if that would be useful, does that sound good?
So for this to work well with Cloudflare we need to set ssl: true and on cloudflare use the Full/Strict ssl mode?
Also just to confirm, I and many others had hacked Kamal 1 to work with letsencrypt by running mkdir -p /letsencrypt && touch /letsencrypt/acme.json && chmod 600 /letsencrypt/acme.json on the server as suggested in https://github.com/basecamp/kamal/discussions/112.
We also need to remove that dir for this to work well right?
So for this to work well with Cloudflare we need to set ssl: true and on cloudflare use the Full/Strict ssl mode?
Yes, otherwise you will get constant redirect, such as these:
And once you have set this, Full should be enough. It will work again.
Also just to confirm, I and many others had hacked Kamal 1 to work with letsencrypt by running mkdir -p /letsencrypt && touch /letsencrypt/acme.json && chmod 600 /letsencrypt/acme.json on the server as suggested in https://github.com/basecamp/kamal/discussions/112.
We also need to remove that dir for this to work well right?
I started with Kamal 2, so no idea about that. But, I'd suggest, to try without removing first and then remove it and try again.
It would be amazing if kamal-proxy had an easy built-in option to generate self-signed certificates as an option instead of letsencrypt which would allow full (but not strict) end-to-end with cloudflare
Thanks @tuladhar , will try that.
In regards to the original issue, my main issue was with the imperative default advice that might be harmful to the security of the origin.
I'll post that line again:
Set ssl: false if using something like Cloudflare to terminate SSL (but keep host!).
As @tuladhar mentioned, the default setting in Cloudflare is Flexible which means "go over unencrypted HTTP". And then the default advice in Kamal is "turn SSL off when using (something like) Cloudflare"
In their docs, Cloudflare clearly recommends using Full:
Again, it's probably not Kamal's job to educate people about all this. I'm not sure what is a more idiomatic solution here for Kamal specifically, but I'd either remove that recommendation completely from the config template or spend another line explaining implication of ssl: false + public proxy like Cloudflare.
Or flip the statement and always recommend turning SSL on unless the users are really sure that the server will have a reverse proxy in front of it inside their private network (either physically or via some VPN) and it will be terminating SSL.
It would be amazing if kamal-proxy had an easy built-in option to generate self-signed certificates as an option instead of letsencrypt which would allow full (but not strict) end-to-end with cloudflare
But why would you need a self-signed certificate when you can get a valid LE certificate for free for your domain?
@kirillrogovoy PR opened: https://github.com/basecamp/kamal/pull/1054
It would be amazing if kamal-proxy had an easy built-in option to generate self-signed certificates as an option instead of letsencrypt which would allow full (but not strict) end-to-end with cloudflare
But why would you need a self-signed certificate when you can get a valid LE certificate for free for your domain?
The LE cert only works in situations with a single app server, if you are load balancing a bunch of them it’s easier to do self signed. And I want SSL to the load balancer, even if it is self signed.
Thanks @tuladhar! ❤️
Does anybody know of a proven guide that works for Rails 8 + Kamal 2 for setting up:
- SSL and/or DNS with Cloudflare
- 1 DigitalOcean load balancers
- 2-3 DigitalOcean droplets
I watched the DHH videos, bought the Kamal handbook, but am still in SSL proxy CDN DNS hell. For Kamal to succeed I feel like it has to provide a lot of documentation on how to set this stuff up. Otherwise people will just keep using the alternatives.
I was able to get a single DigitalOcean droplet to work with Cloudflare DNS set with an A record for the Droplet and Proxy Status set to "Proxied", i.e. terminating HTTPS. But when I added a DigitalOcean load balancer in front of the Droplet (with the health check for /up on port 80) it's always red. When I try to visit the domain for the load balancer, which is setup in Cloudflare DNS as an A record with "DNS only", I get Cloudflare handshake errors.
I feel like I've tried every combination of variables (i.e. editing production.rb in Rails, editing deploy.yml, spinning up new Droplets, toggling Cloudflare Proxy Status) and I'm 12 hours in and can't find the right set of variables. There should just be a cookbook in the Kamal docs for the common setups for Rails 8 + Kamal 2, or else I'm going to go back crying to fly.io 😭
As far as I can tell @aguynamedben, it's not supported in this configuration. We're in the same situation, multiple backend servers for Kamal behind a Cloudflare load balancer. It only works in Flexible mode where it communicates to the backend using HTTP.
Cloudflare in Full mode needs to trust the certificate of the backend server. In order to do that, I believe, you need to export the Cloudflare Origin certificates and have Kamal run using those certs instead of the Let's Encrypt versions. There aren't any configuration options for that, but a possible PR https://github.com/basecamp/kamal/pull/969 that may enable it to be possible. Unfortuantely it seems stalled at the moment.
I would recommend to get Hetzner/Digital Ocean/your cloud provider load balancer and use the Cloudflare Origin certificates as mentioned by @nathanpalmer. Once Kamal supports custom SSL certificates, there will be more options.
@strzibny hopefully soon https://github.com/basecamp/kamal/pull/1531